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