Mercurial > sdl-ios-xcode
annotate src/audio/qsa/SDL_qsa_audio.c @ 3139:7f684f249ec9
indent
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 23 May 2009 22:41:08 +0000 |
parents | 60301ed80050 |
children | f7b03b6838cb |
rev | line source |
---|---|
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
1 /* |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
2 SDL - Simple DirectMedia Layer |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
3 Copyright (C) 1997-2009 Sam Lantinga |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
4 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
5 This library is free software; you can redistribute it and/or |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
6 modify it under the terms of the GNU Library General Public |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
7 License as published by the Free Software Foundation; either |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
8 version 2 of the License, or (at your option) any later version. |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
9 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
10 This library is distributed in the hope that it will be useful, |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
13 Library General Public License for more details. |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
14 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
15 You should have received a copy of the GNU Library General Public |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
16 License along with this library; if not, write to the Free |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
18 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
19 Sam Lantinga |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
20 slouken@libsdl.org |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
21 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
22 QNX Sound Architecture (QSA) SDL driver |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
23 Copyright (C) 2009 Mike Gorchak |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
24 (mike@malva.ua, lestat@i.com.ua) |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
25 */ |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
26 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
27 #include "SDL_config.h" |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
28 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
29 #include <errno.h> |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
30 #include <unistd.h> |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
31 #include <fcntl.h> |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
32 #include <signal.h> |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
33 #include <sys/types.h> |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
34 #include <sys/time.h> |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
35 #include <sched.h> |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
36 #include <sys/select.h> |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
37 #include <sys/neutrino.h> |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
38 #include <sys/asoundlib.h> |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
39 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
40 #include "SDL_timer.h" |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
41 #include "SDL_audio.h" |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
42 #include "../SDL_audiomem.h" |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
43 #include "../SDL_audio_c.h" |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
44 #include "SDL_qsa_audio.h" |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
45 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
46 /* The tag name used by QSA audio framework */ |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
47 #define DRIVER_NAME "qsa" |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
48 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
49 /* default channel communication parameters */ |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
50 #define DEFAULT_CPARAMS_RATE 44100 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
51 #define DEFAULT_CPARAMS_VOICES 1 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
52 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
53 #define DEFAULT_CPARAMS_FRAG_SIZE 4096 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
54 #define DEFAULT_CPARAMS_FRAGS_MIN 1 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
55 #define DEFAULT_CPARAMS_FRAGS_MAX 1 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
56 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
57 #define QSA_NO_WORKAROUNDS 0x00000000 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
58 #define QSA_MMAP_WORKAROUND 0x00000001 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
59 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
60 struct BuggyCards |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
61 { |
3139 | 62 char *cardname; |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
63 unsigned long bugtype; |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
64 }; |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
65 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
66 #define QSA_WA_CARDS 3 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
67 #define QSA_MAX_CARD_NAME_LENGTH 33 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
68 |
3139 | 69 struct BuggyCards buggycards[QSA_WA_CARDS] = { |
70 {"Sound Blaster Live!", QSA_MMAP_WORKAROUND}, | |
71 {"Vortex 8820", QSA_MMAP_WORKAROUND}, | |
72 {"Vortex 8830", QSA_MMAP_WORKAROUND}, | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
73 }; |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
74 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
75 /* List of found devices */ |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
76 #define QSA_MAX_DEVICES 32 |
3139 | 77 #define QSA_MAX_NAME_LENGTH 81+16 /* Hardcoded in QSA, can't be changed */ |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
78 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
79 typedef struct _QSA_Device |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
80 { |
3139 | 81 char name[QSA_MAX_NAME_LENGTH]; /* Long audio device name for SDL */ |
82 int cardno; | |
83 int deviceno; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
84 } QSA_Device; |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
85 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
86 QSA_Device qsa_playback_device[QSA_MAX_DEVICES]; |
3139 | 87 uint32_t qsa_playback_devices; |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
88 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
89 QSA_Device qsa_capture_device[QSA_MAX_DEVICES]; |
3139 | 90 uint32_t qsa_capture_devices; |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
91 |
3139 | 92 static inline void |
93 QSA_SetError(const char *fn, int status) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
94 { |
3139 | 95 SDL_SetError("QSA: %s() failed: %s", fn, snd_strerror(status)); |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
96 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
97 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
98 /* card names check to apply the workarounds */ |
3139 | 99 static int |
100 QSA_CheckBuggyCards(_THIS, unsigned long checkfor) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
101 { |
3139 | 102 char scardname[QSA_MAX_CARD_NAME_LENGTH]; |
103 int it; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
104 |
3139 | 105 if (snd_card_get_name |
106 (this->hidden->cardno, scardname, QSA_MAX_CARD_NAME_LENGTH - 1) < 0) { | |
107 return 0; | |
108 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
109 |
3139 | 110 for (it = 0; it < QSA_WA_CARDS; it++) { |
111 if (SDL_strcmp(buggycards[it].cardname, scardname) == 0) { | |
112 if (buggycards[it].bugtype == checkfor) { | |
113 return 1; | |
114 } | |
115 } | |
116 } | |
117 | |
118 return 0; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
119 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
120 |
3139 | 121 static void |
122 QSA_ThreadInit(_THIS) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
123 { |
3139 | 124 struct sched_param param; |
125 int status; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
126 |
3139 | 127 /* Increase default 10 priority to 25 to avoid jerky sound */ |
128 status = SchedGet(0, 0, ¶m); | |
129 param.sched_priority = param.sched_curpriority + 15; | |
130 status = SchedSet(0, 0, SCHED_NOCHANGE, ¶m); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
131 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
132 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
133 /* PCM channel parameters initialize function */ |
3139 | 134 static void |
135 QSA_InitAudioParams(snd_pcm_channel_params_t * cpars) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
136 { |
3139 | 137 SDL_memset(cpars, 0, sizeof(snd_pcm_channel_params_t)); |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
138 |
3139 | 139 cpars->channel = SND_PCM_CHANNEL_PLAYBACK; |
140 cpars->mode = SND_PCM_MODE_BLOCK; | |
141 cpars->start_mode = SND_PCM_START_DATA; | |
142 cpars->stop_mode = SND_PCM_STOP_STOP; | |
143 cpars->format.format = SND_PCM_SFMT_S16_LE; | |
144 cpars->format.interleave = 1; | |
145 cpars->format.rate = DEFAULT_CPARAMS_RATE; | |
146 cpars->format.voices = DEFAULT_CPARAMS_VOICES; | |
147 cpars->buf.block.frag_size = DEFAULT_CPARAMS_FRAG_SIZE; | |
148 cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN; | |
149 cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
150 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
151 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
152 /* This function waits until it is possible to write a full sound buffer */ |
3139 | 153 static void |
154 QSA_WaitDevice(_THIS) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
155 { |
3139 | 156 fd_set wfds; |
157 fd_set rfds; | |
158 int selectret; | |
159 struct timeval timeout; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
160 |
3139 | 161 if (!this->hidden->iscapture) { |
162 FD_ZERO(&wfds); | |
163 FD_SET(this->hidden->audio_fd, &wfds); | |
164 } else { | |
165 FD_ZERO(&rfds); | |
166 FD_SET(this->hidden->audio_fd, &rfds); | |
167 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
168 |
3139 | 169 do { |
170 /* Setup timeout for playing one fragment equal to 2 seconds */ | |
171 /* If timeout occured than something wrong with hardware or driver */ | |
172 /* For example, Vortex 8820 audio driver stucks on second DAC because */ | |
173 /* it doesn't exist ! */ | |
174 timeout.tv_sec = 2; | |
175 timeout.tv_usec = 0; | |
176 this->hidden->timeout_on_wait = 0; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
177 |
3139 | 178 if (!this->hidden->iscapture) { |
179 selectret = | |
180 select(this->hidden->audio_fd + 1, NULL, &wfds, NULL, | |
181 &timeout); | |
182 } else { | |
183 selectret = | |
184 select(this->hidden->audio_fd + 1, &rfds, NULL, NULL, | |
185 &timeout); | |
186 } | |
187 | |
188 switch (selectret) { | |
189 case -1: | |
190 { | |
191 SDL_SetError("QSA: select() failed: %s\n", strerror(errno)); | |
192 return; | |
193 } | |
194 break; | |
195 case 0: | |
196 { | |
197 SDL_SetError("QSA: timeout on buffer waiting occured\n"); | |
198 this->hidden->timeout_on_wait = 1; | |
199 return; | |
200 } | |
201 break; | |
202 default: | |
203 { | |
204 if (!this->hidden->iscapture) { | |
205 if (FD_ISSET(this->hidden->audio_fd, &wfds)) { | |
206 return; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
207 } |
3139 | 208 } else { |
209 if (FD_ISSET(this->hidden->audio_fd, &rfds)) { | |
210 return; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
211 } |
3139 | 212 } |
213 } | |
214 break; | |
215 } | |
216 } while (1); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
217 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
218 |
3139 | 219 static void |
220 QSA_PlayDevice(_THIS) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
221 { |
3139 | 222 snd_pcm_channel_status_t cstatus; |
223 int written; | |
224 int status; | |
225 int towrite; | |
226 void *pcmbuffer; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
227 |
3139 | 228 if ((!this->enabled) || (!this->hidden)) { |
229 return; | |
230 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
231 |
3139 | 232 towrite = this->spec.size; |
233 pcmbuffer = this->hidden->pcm_buf; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
234 |
3139 | 235 /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ |
236 do { | |
237 written = | |
238 snd_pcm_plugin_write(this->hidden->audio_handle, pcmbuffer, | |
239 towrite); | |
240 if (written != towrite) { | |
241 /* Check if samples playback got stuck somewhere in hardware or in */ | |
242 /* the audio device driver */ | |
243 if ((errno == EAGAIN) && (written == 0)) { | |
244 if (this->hidden->timeout_on_wait != 0) { | |
245 SDL_SetError("QSA: buffer playback timeout\n"); | |
246 return; | |
247 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
248 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
249 |
3139 | 250 /* Check for errors or conditions */ |
251 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { | |
252 /* Let a little CPU time go by and try to write again */ | |
253 SDL_Delay(1); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
254 |
3139 | 255 /* if we wrote some data */ |
256 towrite -= written; | |
257 pcmbuffer += written * this->spec.channels; | |
258 continue; | |
259 } else { | |
260 if ((errno == EINVAL) || (errno == EIO)) { | |
261 SDL_memset(&cstatus, 0, sizeof(cstatus)); | |
262 if (!this->hidden->iscapture) { | |
263 cstatus.channel = SND_PCM_CHANNEL_PLAYBACK; | |
264 } else { | |
265 cstatus.channel = SND_PCM_CHANNEL_CAPTURE; | |
266 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
267 |
3139 | 268 status = |
269 snd_pcm_plugin_status(this->hidden->audio_handle, | |
270 &cstatus); | |
271 if (status < 0) { | |
272 QSA_SetError("snd_pcm_plugin_status", status); | |
273 return; | |
274 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
275 |
3139 | 276 if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || |
277 (cstatus.status == SND_PCM_STATUS_READY)) { | |
278 if (!this->hidden->iscapture) { | |
279 status = | |
280 snd_pcm_plugin_prepare(this->hidden-> | |
281 audio_handle, | |
282 SND_PCM_CHANNEL_PLAYBACK); | |
283 } else { | |
284 status = | |
285 snd_pcm_plugin_prepare(this->hidden-> | |
286 audio_handle, | |
287 SND_PCM_CHANNEL_CAPTURE); | |
288 } | |
289 if (status < 0) { | |
290 QSA_SetError("snd_pcm_plugin_prepare", status); | |
291 return; | |
292 } | |
293 } | |
294 continue; | |
295 } else { | |
296 return; | |
297 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
298 } |
3139 | 299 } else { |
300 /* we wrote all remaining data */ | |
301 towrite -= written; | |
302 pcmbuffer += written * this->spec.channels; | |
303 } | |
304 } while ((towrite > 0) && (this->enabled)); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
305 |
3139 | 306 /* If we couldn't write, assume fatal error for now */ |
307 if (towrite != 0) { | |
308 this->enabled = 0; | |
309 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
310 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
311 |
3139 | 312 static Uint8 * |
313 QSA_GetDeviceBuf(_THIS) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
314 { |
3139 | 315 return this->hidden->pcm_buf; |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
316 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
317 |
3139 | 318 static void |
319 QSA_CloseDevice(_THIS) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
320 { |
3139 | 321 if (this->hidden != NULL) { |
322 if (this->hidden->audio_handle != NULL) { | |
323 if (!this->hidden->iscapture) { | |
324 /* Finish playing available samples */ | |
325 snd_pcm_plugin_flush(this->hidden->audio_handle, | |
326 SND_PCM_CHANNEL_PLAYBACK); | |
327 } else { | |
328 /* Cancel unread samples during capture */ | |
329 snd_pcm_plugin_flush(this->hidden->audio_handle, | |
330 SND_PCM_CHANNEL_CAPTURE); | |
331 } | |
332 snd_pcm_close(this->hidden->audio_handle); | |
333 this->hidden->audio_handle = NULL; | |
334 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
335 |
3139 | 336 if (this->hidden->pcm_buf != NULL) { |
337 SDL_FreeAudioMem(this->hidden->pcm_buf); | |
338 this->hidden->pcm_buf = NULL; | |
339 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
340 |
3139 | 341 SDL_free(this->hidden); |
342 this->hidden = NULL; | |
343 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
344 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
345 |
3139 | 346 static int |
347 QSA_OpenDevice(_THIS, const char *devname, int iscapture) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
348 { |
3139 | 349 int status = 0; |
350 int format = 0; | |
351 SDL_AudioFormat test_format = 0; | |
352 int found = 0; | |
353 snd_pcm_channel_setup_t csetup; | |
354 snd_pcm_channel_params_t cparams; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
355 |
3139 | 356 /* Initialize all variables that we clean on shutdown */ |
357 this->hidden = | |
358 (struct SDL_PrivateAudioData *) SDL_calloc(1, | |
359 (sizeof | |
360 (struct | |
361 SDL_PrivateAudioData))); | |
362 if (this->hidden == NULL) { | |
363 SDL_OutOfMemory(); | |
364 return 0; | |
365 } | |
366 SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData)); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
367 |
3139 | 368 /* Initialize channel transfer parameters to default */ |
369 QSA_InitAudioParams(&cparams); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
370 |
3139 | 371 /* Initialize channel direction: capture or playback */ |
372 this->hidden->iscapture = iscapture; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
373 |
3139 | 374 /* Find deviceid and cardid by device name for playback */ |
375 if ((!this->hidden->iscapture) && (devname != NULL)) { | |
376 uint32_t device; | |
377 int32_t status; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
378 |
3139 | 379 /* Search in the playback devices */ |
380 device = 0; | |
381 do { | |
382 status = SDL_strcmp(qsa_playback_device[device].name, devname); | |
383 if (status == 0) { | |
384 /* Found requested device */ | |
385 this->hidden->deviceno = qsa_playback_device[device].deviceno; | |
386 this->hidden->cardno = qsa_playback_device[device].cardno; | |
387 break; | |
388 } | |
389 device++; | |
390 if (device >= qsa_playback_devices) { | |
391 QSA_CloseDevice(this); | |
392 SDL_SetError("No such playback device"); | |
393 return 0; | |
394 } | |
395 } while (1); | |
396 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
397 |
3139 | 398 /* Find deviceid and cardid by device name for capture */ |
399 if ((this->hidden->iscapture) && (devname != NULL)) { | |
400 /* Search in the capture devices */ | |
401 uint32_t device; | |
402 int32_t status; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
403 |
3139 | 404 /* Searching in the playback devices */ |
405 device = 0; | |
406 do { | |
407 status = SDL_strcmp(qsa_capture_device[device].name, devname); | |
408 if (status == 0) { | |
409 /* Found requested device */ | |
410 this->hidden->deviceno = qsa_capture_device[device].deviceno; | |
411 this->hidden->cardno = qsa_capture_device[device].cardno; | |
412 break; | |
413 } | |
414 device++; | |
415 if (device >= qsa_capture_devices) { | |
416 QSA_CloseDevice(this); | |
417 SDL_SetError("No such capture device"); | |
418 return 0; | |
419 } | |
420 } while (1); | |
421 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
422 |
3139 | 423 /* Check if SDL requested default audio device */ |
424 if (devname == NULL) { | |
425 /* Open system default audio device */ | |
426 if (!this->hidden->iscapture) { | |
427 status = snd_pcm_open_preferred(&this->hidden->audio_handle, | |
428 &this->hidden->cardno, | |
429 &this->hidden->deviceno, | |
430 SND_PCM_OPEN_PLAYBACK); | |
431 } else { | |
432 status = snd_pcm_open_preferred(&this->hidden->audio_handle, | |
433 &this->hidden->cardno, | |
434 &this->hidden->deviceno, | |
435 SND_PCM_OPEN_CAPTURE); | |
436 } | |
437 } else { | |
438 /* Open requested audio device */ | |
439 if (!this->hidden->iscapture) { | |
440 status = | |
441 snd_pcm_open(&this->hidden->audio_handle, | |
442 this->hidden->cardno, this->hidden->deviceno, | |
443 SND_PCM_OPEN_PLAYBACK); | |
444 } else { | |
445 status = | |
446 snd_pcm_open(&this->hidden->audio_handle, | |
447 this->hidden->cardno, this->hidden->deviceno, | |
448 SND_PCM_OPEN_CAPTURE); | |
449 } | |
450 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
451 |
3139 | 452 /* Check if requested device is opened */ |
453 if (status < 0) { | |
454 this->hidden->audio_handle = NULL; | |
455 QSA_CloseDevice(this); | |
456 QSA_SetError("snd_pcm_open", status); | |
457 return 0; | |
458 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
459 |
3139 | 460 if (!QSA_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) { |
461 /* Disable QSA MMAP plugin for buggy audio drivers */ | |
462 status = | |
463 snd_pcm_plugin_set_disable(this->hidden->audio_handle, | |
464 PLUGIN_DISABLE_MMAP); | |
465 if (status < 0) { | |
466 QSA_CloseDevice(this); | |
467 QSA_SetError("snd_pcm_plugin_set_disable", status); | |
468 return 0; | |
469 } | |
470 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
471 |
3139 | 472 /* Try for a closest match on audio format */ |
473 format = 0; | |
474 /* can't use format as SND_PCM_SFMT_U8 = 0 in qsa */ | |
475 found = 0; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
476 |
3139 | 477 for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) { |
478 /* if match found set format to equivalent QSA format */ | |
479 switch (test_format) { | |
480 case AUDIO_U8: | |
481 { | |
482 format = SND_PCM_SFMT_U8; | |
483 found = 1; | |
484 } | |
485 break; | |
486 case AUDIO_S8: | |
487 { | |
488 format = SND_PCM_SFMT_S8; | |
489 found = 1; | |
490 } | |
491 break; | |
492 case AUDIO_S16LSB: | |
493 { | |
494 format = SND_PCM_SFMT_S16_LE; | |
495 found = 1; | |
496 } | |
497 break; | |
498 case AUDIO_S16MSB: | |
499 { | |
500 format = SND_PCM_SFMT_S16_BE; | |
501 found = 1; | |
502 } | |
503 break; | |
504 case AUDIO_U16LSB: | |
505 { | |
506 format = SND_PCM_SFMT_U16_LE; | |
507 found = 1; | |
508 } | |
509 break; | |
510 case AUDIO_U16MSB: | |
511 { | |
512 format = SND_PCM_SFMT_U16_BE; | |
513 found = 1; | |
514 } | |
515 break; | |
516 case AUDIO_S32LSB: | |
517 { | |
518 format = SND_PCM_SFMT_S32_LE; | |
519 found = 1; | |
520 } | |
521 break; | |
522 case AUDIO_S32MSB: | |
523 { | |
524 format = SND_PCM_SFMT_S32_BE; | |
525 found = 1; | |
526 } | |
527 break; | |
528 case AUDIO_F32LSB: | |
529 { | |
530 format = SND_PCM_SFMT_FLOAT_LE; | |
531 found = 1; | |
532 } | |
533 break; | |
534 case AUDIO_F32MSB: | |
535 { | |
536 format = SND_PCM_SFMT_FLOAT_BE; | |
537 found = 1; | |
538 } | |
539 break; | |
540 default: | |
541 { | |
542 break; | |
543 } | |
544 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
545 |
3139 | 546 if (!found) { |
547 test_format = SDL_NextAudioFormat(); | |
548 } | |
549 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
550 |
3139 | 551 /* assumes test_format not 0 on success */ |
552 if (test_format == 0) { | |
553 QSA_CloseDevice(this); | |
554 SDL_SetError("QSA: Couldn't find any hardware audio formats"); | |
555 return 0; | |
556 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
557 |
3139 | 558 this->spec.format = test_format; |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
559 |
3139 | 560 /* Set the audio format */ |
561 cparams.format.format = format; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
562 |
3139 | 563 /* Set mono/stereo/4ch/6ch/8ch audio */ |
564 cparams.format.voices = this->spec.channels; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
565 |
3139 | 566 /* Set rate */ |
567 cparams.format.rate = this->spec.freq; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
568 |
3139 | 569 /* Setup the transfer parameters according to cparams */ |
570 status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams); | |
571 if (status < 0) { | |
572 QSA_CloseDevice(this); | |
573 QSA_SetError("snd_pcm_channel_params", status); | |
574 return 0; | |
575 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
576 |
3139 | 577 /* Make sure channel is setup right one last time */ |
578 SDL_memset(&csetup, '\0', sizeof(csetup)); | |
579 if (!this->hidden->iscapture) { | |
580 csetup.channel = SND_PCM_CHANNEL_PLAYBACK; | |
581 } else { | |
582 csetup.channel = SND_PCM_CHANNEL_CAPTURE; | |
583 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
584 |
3139 | 585 /* Setup an audio channel */ |
586 if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) { | |
587 QSA_CloseDevice(this); | |
588 SDL_SetError("QSA: Unable to setup channel\n"); | |
589 return 0; | |
590 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
591 |
3139 | 592 /* Calculate the final parameters for this audio specification */ |
593 SDL_CalculateAudioSpec(&this->spec); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
594 |
3139 | 595 this->hidden->pcm_len = this->spec.size; |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
596 |
3139 | 597 if (this->hidden->pcm_len == 0) { |
598 this->hidden->pcm_len = | |
599 csetup.buf.block.frag_size * this->spec.channels * | |
600 (snd_pcm_format_width(format) / 8); | |
601 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
602 |
3139 | 603 /* |
604 * Allocate memory to the audio buffer and initialize with silence | |
605 * (Note that buffer size must be a multiple of fragment size, so find | |
606 * closest multiple) | |
607 */ | |
608 this->hidden->pcm_buf = | |
609 (Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len); | |
610 if (this->hidden->pcm_buf == NULL) { | |
611 QSA_CloseDevice(this); | |
612 SDL_OutOfMemory(); | |
613 return 0; | |
614 } | |
615 SDL_memset(this->hidden->pcm_buf, this->spec.silence, | |
616 this->hidden->pcm_len); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
617 |
3139 | 618 /* get the file descriptor */ |
619 if (!this->hidden->iscapture) { | |
620 this->hidden->audio_fd = | |
621 snd_pcm_file_descriptor(this->hidden->audio_handle, | |
622 SND_PCM_CHANNEL_PLAYBACK); | |
623 } else { | |
624 this->hidden->audio_fd = | |
625 snd_pcm_file_descriptor(this->hidden->audio_handle, | |
626 SND_PCM_CHANNEL_CAPTURE); | |
627 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
628 |
3139 | 629 if (this->hidden->audio_fd < 0) { |
630 QSA_CloseDevice(this); | |
631 QSA_SetError("snd_pcm_file_descriptor", status); | |
632 return 0; | |
633 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
634 |
3139 | 635 /* Prepare an audio channel */ |
636 if (!this->hidden->iscapture) { | |
637 /* Prepare audio playback */ | |
638 status = | |
639 snd_pcm_plugin_prepare(this->hidden->audio_handle, | |
640 SND_PCM_CHANNEL_PLAYBACK); | |
641 } else { | |
642 /* Prepare audio capture */ | |
643 status = | |
644 snd_pcm_plugin_prepare(this->hidden->audio_handle, | |
645 SND_PCM_CHANNEL_CAPTURE); | |
646 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
647 |
3139 | 648 if (status < 0) { |
649 QSA_CloseDevice(this); | |
650 QSA_SetError("snd_pcm_plugin_prepare", status); | |
651 return 0; | |
652 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
653 |
3139 | 654 /* We're really ready to rock and roll. :-) */ |
655 return 1; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
656 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
657 |
3139 | 658 int |
659 QSA_DetectDevices(int iscapture) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
660 { |
3139 | 661 uint32_t it; |
662 uint32_t cards; | |
663 uint32_t devices; | |
664 int32_t status; | |
665 | |
666 /* Detect amount of available devices */ | |
667 /* this value can be changed in the runtime */ | |
668 cards = snd_cards(); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
669 |
3139 | 670 /* If io-audio manager is not running we will get 0 as number */ |
671 /* of available audio devices */ | |
672 if (cards == 0) { | |
673 /* We have no any available audio devices */ | |
674 return 0; | |
675 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
676 |
3139 | 677 /* Find requested devices by type */ |
678 if (!iscapture) { | |
679 /* Playback devices enumeration requested */ | |
680 for (it = 0; it < cards; it++) { | |
681 devices = 0; | |
682 do { | |
683 status = | |
684 snd_card_get_longname(it, | |
685 qsa_playback_device | |
686 [qsa_playback_devices].name, | |
687 QSA_MAX_NAME_LENGTH); | |
688 if (status == EOK) { | |
689 snd_pcm_t *handle; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
690 |
3139 | 691 /* Add device number to device name */ |
692 sprintf(qsa_playback_device[qsa_playback_devices].name + | |
693 SDL_strlen(qsa_playback_device | |
694 [qsa_playback_devices].name), " d%d", | |
695 devices); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
696 |
3139 | 697 /* Store associated card number id */ |
698 qsa_playback_device[qsa_playback_devices].cardno = it; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
699 |
3139 | 700 /* Check if this device id could play anything */ |
701 status = | |
702 snd_pcm_open(&handle, it, devices, | |
703 SND_PCM_OPEN_PLAYBACK); | |
704 if (status == EOK) { | |
705 qsa_playback_device[qsa_playback_devices].deviceno = | |
706 devices; | |
707 status = snd_pcm_close(handle); | |
708 if (status == EOK) { | |
709 qsa_playback_devices++; | |
710 } | |
711 } else { | |
712 /* Check if we got end of devices list */ | |
713 if (status == -ENOENT) { | |
714 break; | |
715 } | |
716 } | |
717 } else { | |
718 break; | |
719 } | |
720 | |
721 /* Check if we reached maximum devices count */ | |
722 if (qsa_playback_devices >= QSA_MAX_DEVICES) { | |
723 break; | |
724 } | |
725 devices++; | |
726 } while (1); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
727 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
728 /* Check if we reached maximum devices count */ |
3139 | 729 if (qsa_playback_devices >= QSA_MAX_DEVICES) { |
730 break; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
731 } |
3139 | 732 } |
733 } else { | |
734 /* Capture devices enumeration requested */ | |
735 for (it = 0; it < cards; it++) { | |
736 devices = 0; | |
737 do { | |
738 status = | |
739 snd_card_get_longname(it, | |
740 qsa_capture_device | |
741 [qsa_capture_devices].name, | |
742 QSA_MAX_NAME_LENGTH); | |
743 if (status == EOK) { | |
744 snd_pcm_t *handle; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
745 |
3139 | 746 /* Add device number to device name */ |
747 sprintf(qsa_capture_device[qsa_capture_devices].name + | |
748 SDL_strlen(qsa_capture_device | |
749 [qsa_capture_devices].name), " d%d", | |
750 devices); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
751 |
3139 | 752 /* Store associated card number id */ |
753 qsa_capture_device[qsa_capture_devices].cardno = it; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
754 |
3139 | 755 /* Check if this device id could play anything */ |
756 status = | |
757 snd_pcm_open(&handle, it, devices, | |
758 SND_PCM_OPEN_CAPTURE); | |
759 if (status == EOK) { | |
760 qsa_capture_device[qsa_capture_devices].deviceno = | |
761 devices; | |
762 status = snd_pcm_close(handle); | |
763 if (status == EOK) { | |
764 qsa_capture_devices++; | |
765 } | |
766 } else { | |
767 /* Check if we got end of devices list */ | |
768 if (status == -ENOENT) { | |
769 break; | |
770 } | |
771 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
772 |
3139 | 773 /* Check if we reached maximum devices count */ |
774 if (qsa_capture_devices >= QSA_MAX_DEVICES) { | |
775 break; | |
776 } | |
777 } else { | |
778 break; | |
779 } | |
780 devices++; | |
781 } while (1); | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
782 |
3139 | 783 /* Check if we reached maximum devices count */ |
784 if (qsa_capture_devices >= QSA_MAX_DEVICES) { | |
785 break; | |
786 } | |
787 } | |
788 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
789 |
3139 | 790 /* Return amount of available playback or capture devices */ |
791 if (!iscapture) { | |
792 return qsa_playback_devices; | |
793 } else { | |
794 return qsa_capture_devices; | |
795 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
796 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
797 |
3139 | 798 const char * |
799 QSA_GetDeviceName(int index, int iscapture) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
800 { |
3139 | 801 if (!iscapture) { |
802 if (index >= qsa_playback_devices) { | |
803 return "No such playback device"; | |
804 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
805 |
3139 | 806 return qsa_playback_device[index].name; |
807 } else { | |
808 if (index >= qsa_capture_devices) { | |
809 return "No such capture device"; | |
810 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
811 |
3139 | 812 return qsa_capture_device[index].name; |
813 } | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
814 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
815 |
3139 | 816 void |
817 QSA_WaitDone(_THIS) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
818 { |
3139 | 819 if (!this->hidden->iscapture) { |
820 if (this->hidden->audio_handle != NULL) { | |
821 /* Wait till last fragment is played and stop channel */ | |
822 snd_pcm_plugin_flush(this->hidden->audio_handle, | |
823 SND_PCM_CHANNEL_PLAYBACK); | |
824 } | |
825 } else { | |
826 if (this->hidden->audio_handle != NULL) { | |
827 /* Discard all unread data and stop channel */ | |
828 snd_pcm_plugin_flush(this->hidden->audio_handle, | |
829 SND_PCM_CHANNEL_CAPTURE); | |
830 } | |
831 } | |
832 } | |
833 | |
834 void | |
835 QSA_Deinitialize(void) | |
836 { | |
837 /* Clear devices array on shutdown */ | |
838 SDL_memset(qsa_playback_device, 0x00, | |
839 sizeof(QSA_Device) * QSA_MAX_DEVICES); | |
840 SDL_memset(qsa_capture_device, 0x00, | |
841 sizeof(QSA_Device) * QSA_MAX_DEVICES); | |
842 qsa_playback_devices = 0; | |
843 qsa_capture_devices = 0; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
844 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
845 |
3139 | 846 static int |
847 QSA_Init(SDL_AudioDriverImpl * impl) | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
848 { |
3139 | 849 snd_pcm_t *handle = NULL; |
850 int32_t status = 0; | |
851 | |
852 /* Clear devices array */ | |
853 SDL_memset(qsa_playback_device, 0x00, | |
854 sizeof(QSA_Device) * QSA_MAX_DEVICES); | |
855 SDL_memset(qsa_capture_device, 0x00, | |
856 sizeof(QSA_Device) * QSA_MAX_DEVICES); | |
857 qsa_playback_devices = 0; | |
858 qsa_capture_devices = 0; | |
859 | |
860 /* Set function pointers */ | |
861 /* DeviceLock and DeviceUnlock functions are used default, */ | |
862 /* provided by SDL, which uses pthread_mutex for lock/unlock */ | |
863 impl->DetectDevices = QSA_DetectDevices; | |
864 impl->GetDeviceName = QSA_GetDeviceName; | |
865 impl->OpenDevice = QSA_OpenDevice; | |
866 impl->ThreadInit = QSA_ThreadInit; | |
867 impl->WaitDevice = QSA_WaitDevice; | |
868 impl->PlayDevice = QSA_PlayDevice; | |
869 impl->GetDeviceBuf = QSA_GetDeviceBuf; | |
870 impl->CloseDevice = QSA_CloseDevice; | |
871 impl->WaitDone = QSA_WaitDone; | |
872 impl->Deinitialize = QSA_Deinitialize; | |
873 impl->LockDevice = NULL; | |
874 impl->UnlockDevice = NULL; | |
875 | |
876 impl->OnlyHasDefaultOutputDevice = 0; | |
877 impl->ProvidesOwnCallbackThread = 0; | |
878 impl->SkipMixerLock = 0; | |
879 impl->HasCaptureSupport = 1; | |
880 impl->OnlyHasDefaultOutputDevice = 0; | |
881 impl->OnlyHasDefaultInputDevice = 0; | |
882 | |
883 /* Check if io-audio manager is running or not */ | |
884 status = snd_cards(); | |
885 if (status == 0) { | |
886 /* if no, return immediately */ | |
887 return 1; | |
888 } | |
889 | |
890 /* At this point we are definitely has an audio device */ | |
891 return 2; | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
892 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
893 |
3139 | 894 AudioBootStrap QSAAUDIO_bootstrap = { |
895 DRIVER_NAME, "QNX QSA Audio", QSA_Init, 0 | |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
896 }; |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
897 |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
898 /* vi: set ts=4 sw=4 expandtab: */ |