Mercurial > sdl-ios-xcode
annotate src/audio/qsa/SDL_qsa_audio.c @ 4593:3892fe2f6537
Fixed so many things. See the changelog listed below.
1. Use SDL_X11_HAVE_XRENDER to check for RENDER at runtime.
2. Added lots of comments.
3. Added checks and lots of calls to SDL_SetError().
4. Fixed X11_CreateTexture() so that the pixmap and image created
are for the format specified by the user and not the window
format. This is only for the RENDER case.
5. The above change required that functions to convert SDL
pixel format enums to Visuals and XRenderPictFormats be added.
6. Fixed lots of 'style' issues.
author | Sunny Sachanandani <sunnysachanandani@gmail.com> |
---|---|
date | Sat, 17 Jul 2010 15:38:24 +0530 |
parents | 4160ba33b597 |
children | b530ef003506 |
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 | |
3699
4160ba33b597
Removed test for "driver is valid, but doesn't see any audio devices."
Ryan C. Gordon <icculus@icculus.org>
parents:
3697
diff
changeset
|
886 return 1; /* this audio target is available. */ |
3099
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
887 } |
82e60908fab1
Date: Mon, 23 Mar 2009 09:17:24 +0200
Sam Lantinga <slouken@libsdl.org>
parents:
diff
changeset
|
888 |
3139 | 889 AudioBootStrap QSAAUDIO_bootstrap = { |
890 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
|
891 }; |
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 /* vi: set ts=4 sw=4 expandtab: */ |