Changeset 4160:87a2bd2f45a7 in roaraudio
- Timestamp:
- 08/13/10 16:53:16 (14 years ago)
- Branch:
- default
- Phase:
- public
- Location:
- roard
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
roard/driver_alsa.c
r3695 r4160 31 31 #define ALSA_PCM_NEW_HW_PARAMS_API 32 32 33 typedef struct roar_alsa { 34 snd_pcm_t *handle; 35 snd_pcm_hw_params_t* params; 36 } roar_alsa_t; 33 static snd_pcm_format_t driver_alsa_roar_fmt_to_alsa(struct roar_audio_info * info) { 34 snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN; 35 36 switch (info->codec) { 37 case ROAR_CODEC_PCM_S_LE: 38 switch (info->bits) { 39 case 8: format = SND_PCM_FORMAT_S8; break; 40 case 16: format = SND_PCM_FORMAT_S16_LE; break; 41 case 24: format = SND_PCM_FORMAT_S24_3LE; break; 42 case 32: format = SND_PCM_FORMAT_S32_LE; break; 43 } 44 break; 45 case ROAR_CODEC_PCM_S_BE: 46 switch (info->bits) { 47 case 8: format = SND_PCM_FORMAT_S8; break; 48 case 16: format = SND_PCM_FORMAT_S16_BE; break; 49 case 24: format = SND_PCM_FORMAT_S24_3BE; break; 50 case 32: format = SND_PCM_FORMAT_S32_BE; break; 51 } 52 break; 53 case ROAR_CODEC_PCM_U_LE: 54 switch (info->bits) { 55 case 8: format = SND_PCM_FORMAT_U8; break; 56 case 16: format = SND_PCM_FORMAT_U16_LE; break; 57 case 24: format = SND_PCM_FORMAT_U24_3LE; break; 58 case 32: format = SND_PCM_FORMAT_U32_LE; break; 59 } 60 break; 61 case ROAR_CODEC_PCM_U_BE: 62 switch (info->bits) { 63 case 8: format = SND_PCM_FORMAT_U8; break; 64 case 16: format = SND_PCM_FORMAT_U16_BE; break; 65 case 24: format = SND_PCM_FORMAT_U24_3BE; break; 66 case 32: format = SND_PCM_FORMAT_U32_BE; break; 67 } 68 break; 69 case ROAR_CODEC_ALAW: 70 format = SND_PCM_FORMAT_A_LAW; 71 break; 72 case ROAR_CODEC_MULAW: 73 format = SND_PCM_FORMAT_MU_LAW; 74 break; 75 case ROAR_CODEC_GSM: 76 format = SND_PCM_FORMAT_GSM; 77 break; 78 } 79 80 return format; 81 } 82 83 static int driver_alsa_set_params(roar_alsa_t * device) { 84 unsigned int buffer_time = 32000; // 32ms buffer if possible. 85 // *_buffer_time_near() will pick something as close as possible. 86 snd_pcm_uframes_t frames = ROAR_OUTPUT_BUFFER_SAMPLES; 87 int rc; 88 89 ROAR_DBG("driver_alsa_set_params(device=%p) = ?", device); 90 91 if ( snd_pcm_hw_params_malloc(&device->params) < 0 ) 92 return -1; 93 94 ROAR_DBG("driver_alsa_set_params(device=%p) = ?", device); 95 96 if ( snd_pcm_hw_params_any(device->handle, device->params) < 0 ) 97 goto error; 98 99 ROAR_DBG("driver_alsa_set_params(device=%p) = ?", device); 100 101 if ( snd_pcm_hw_params_set_access(device->handle, device->params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 ) 102 goto error; 103 104 ROAR_DBG("driver_alsa_set_params(device=%p) = ?", device); 105 106 if ( snd_pcm_hw_params_set_format(device->handle, device->params, device->format) < 0) 107 goto error; 108 109 ROAR_DBG("driver_alsa_set_params(device=%p) = ?", device); 110 111 ROAR_DBG("driver_alsa_set_params(device=%p): device->info.channels=%i", device, device->info.channels); 112 113 if ( snd_pcm_hw_params_set_channels(device->handle, device->params, device->info.channels) < 0 ) 114 goto error; 115 116 ROAR_DBG("driver_alsa_set_params(device=%p) = ?", device); 117 118 if ( snd_pcm_hw_params_set_rate(device->handle, device->params, device->info.rate, 0) < 0 ) 119 goto error; 120 121 ROAR_DBG("driver_alsa_set_params(device=%p) = ?", device); 122 123 if ( snd_pcm_hw_params_set_buffer_time_near(device->handle, device->params, &buffer_time, NULL) < 0 ) 124 goto error; 125 126 ROAR_DBG("driver_alsa_set_params(device=%p) = ?", device); 127 128 if ( snd_pcm_hw_params_set_period_size_near(device->handle, device->params, &frames, NULL) < 0 ) 129 goto error; 130 131 ROAR_DBG("driver_alsa_set_params(device=%p) = ?", device); 132 133 rc = snd_pcm_hw_params(device->handle, device->params); 134 if (rc < 0) { 135 ROAR_ERR("driver_alsa_open_vio(*): unable to set hw parameters: %s", snd_strerror(rc)); 136 goto error; 137 } 138 139 ROAR_DBG("driver_alsa_set_params(device=%p) = ?", device); 140 141 snd_pcm_hw_params_free(device->params); 142 143 ROAR_DBG("driver_alsa_set_params(device=%p) = 0", device); 144 145 return 0; 146 147 error: 148 snd_pcm_hw_params_free(device->params); 149 ROAR_DBG("driver_alsa_set_params(device=%p) = -1", device); 150 return -1; 151 } 37 152 38 153 int driver_alsa_open_vio(struct roar_vio_calls * inst, char * device, struct roar_audio_info * info, int fh, struct roar_stream_server * sstream) { … … 40 155 char * alsa_dev; 41 156 int rc; 42 unsigned buffer_time = 200000; // 200ms buffer43 snd_pcm_uframes_t frames = ROAR_OUTPUT_BUFFER_SAMPLES; // ALSA frames44 snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN; // If this isn't set further down, we pick 16 bit audio if we're using autoconf.45 uint16_t channels = info->channels;46 uint32_t samplerate = info->rate;47 157 int autoconf; 48 158 159 ROAR_DBG("driver_alsa_open_vio(inst=%p, device='%s', info=%p, fh=%i, sstream=%p) = ?", inst, device, info, fh, sstream); 49 160 50 161 if ( fh != -1 ) … … 53 164 if ( (interface = roar_mm_calloc(1, sizeof(roar_alsa_t))) == NULL ) 54 165 return -1; 166 167 ROAR_DBG("driver_alsa_open_vio(inst=%p, device='%s', info=%p, fh=%i, sstream=%p) = ?", inst, device, info, fh, sstream); 55 168 56 169 if ( device == NULL ) { … … 60 173 } 61 174 175 ROAR_DBG("driver_alsa_open_vio(inst=%p, device='%s', info=%p, fh=%i, sstream=%p) = ?", inst, device, info, fh, sstream); 176 62 177 rc = snd_pcm_open(&(interface->handle), alsa_dev, SND_PCM_STREAM_PLAYBACK, 0); 63 178 if ( rc < 0 ) { … … 68 183 69 184 // Setting sample format, yay. 70 if ( info->codec == ROAR_CODEC_PCM_S_LE ) { 71 switch (info->bits) { 72 case 8: 73 format = SND_PCM_FORMAT_S8; 74 break; 75 case 16: 76 format = SND_PCM_FORMAT_S16_LE; 77 break; 78 case 32: 79 format = SND_PCM_FORMAT_S32_LE; 80 break; 81 } 82 } else if ( info->codec == ROAR_CODEC_PCM_U_LE ) { 83 switch (info->bits) { 84 case 8: 85 format = SND_PCM_FORMAT_U8; 86 break; 87 case 16: 88 format = SND_PCM_FORMAT_U16_LE; 89 break; 90 case 32: 91 format = SND_PCM_FORMAT_U32_LE; 92 break; 93 } 94 } else if ( info->codec == ROAR_CODEC_PCM_S_BE ) { 95 switch (info->bits) { 96 case 8: 97 format = SND_PCM_FORMAT_S8; 98 break; 99 case 16: 100 format = SND_PCM_FORMAT_S16_BE; 101 break; 102 case 32: 103 format = SND_PCM_FORMAT_S32_BE; 104 break; 105 } 106 } else if ( info->codec == ROAR_CODEC_PCM_U_BE ) { 107 switch (info->bits) { 108 case 8: 109 format = SND_PCM_FORMAT_U8; 110 break; 111 case 16: 112 format = SND_PCM_FORMAT_U16_BE; 113 break; 114 case 32: 115 format = SND_PCM_FORMAT_U32_BE; 116 break; 117 } 118 } 185 interface->format = driver_alsa_roar_fmt_to_alsa(info); 186 187 ROAR_DBG("driver_alsa_open_vio(inst=%p, device='%s', info=%p, fh=%i, sstream=%p) = ?", inst, device, info, fh, sstream); 119 188 120 189 // We did not find a codec 121 if ( format == SND_PCM_FORMAT_UNKNOWN ) {190 if ( interface->format == SND_PCM_FORMAT_UNKNOWN ) { 122 191 autoconf = streams_get_flag(ROAR_STREAM(sstream)->id, ROAR_FLAG_AUTOCONF); 123 192 if ( autoconf == -1 ) { … … 130 199 131 200 #if ROAR_CODEC_DEFAULT == ROAR_CODEC_PCM_S_LE 132 format= SND_PCM_FORMAT_S16_LE;133 info->codec = ROAR_CODEC_PCM_S_LE;201 interface->format = SND_PCM_FORMAT_S16_LE; 202 info->codec = ROAR_CODEC_PCM_S_LE; 134 203 #elif ROAR_CODEC_DEFAULT == ROAR_CODEC_PCM_S_BE 135 format= SND_PCM_FORMAT_S16_BE;136 info->codec = ROAR_CODEC_PCM_S_BE;204 interface->format = SND_PCM_FORMAT_S16_BE; 205 info->codec = ROAR_CODEC_PCM_S_BE; 137 206 #else 138 207 ROAR_ERR("driver_alsa_open_vio(*): ALSA only support little- or big-endian sample format. Please select -oO codec=pcm_s_le or pcm_s_be"); … … 146 215 } 147 216 148 149 if ( snd_pcm_hw_params_malloc(&interface->params) < 0 ) 217 memcpy(&(interface->info), info, sizeof(struct roar_audio_info)); 218 219 ROAR_DBG("driver_alsa_open_vio(inst=%p, device='%s', info=%p, fh=%i, sstream=%p) = ?", inst, device, info, fh, sstream); 220 221 if ( driver_alsa_set_params(interface) < 0 ) 150 222 goto init_error; 151 223 152 if ( snd_pcm_hw_params_any(interface->handle, interface->params) < 0 ) 153 goto init_error; 154 if ( snd_pcm_hw_params_set_access(interface->handle, interface->params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 ) 155 goto init_error; 156 if ( snd_pcm_hw_params_set_format(interface->handle, interface->params, format) < 0) 157 goto init_error; 158 if ( snd_pcm_hw_params_set_channels(interface->handle, interface->params, channels) < 0 ) 159 goto init_error; 160 if ( snd_pcm_hw_params_set_rate_near(interface->handle, interface->params, &samplerate, NULL) < 0 ) 161 goto init_error; 162 if ( snd_pcm_hw_params_set_buffer_time_near(interface->handle, interface->params, &buffer_time, NULL) < 0 ) 163 goto init_error; 164 if ( snd_pcm_hw_params_set_period_size_near(interface->handle, interface->params, &frames, NULL) < 0 ) 165 goto init_error; 166 167 rc = snd_pcm_hw_params(interface->handle, interface->params); 168 if (rc < 0) { 169 ROAR_ERR("driver_alsa_open_vio(*): unable to set hw parameters: %s", snd_strerror(rc)); 170 snd_pcm_hw_params_free(interface->params); 171 goto init_error; 172 } 173 174 snd_pcm_hw_params_free(interface->params); 224 ROAR_DBG("driver_alsa_open_vio(inst=%p, device='%s', info=%p, fh=%i, sstream=%p) = ?", inst, device, info, fh, sstream); 175 225 176 226 memset(inst, 0, sizeof(struct roar_vio_calls)); … … 179 229 inst->write = driver_alsa_write; 180 230 inst->close = driver_alsa_close; 231 inst->sync = driver_alsa_sync; 232 inst->ctl = driver_alsa_ctl; 233 234 ROAR_DBG("driver_alsa_open_vio(inst=%p, device='%s', info=%p, fh=%i, sstream=%p) = 0", inst, device, info, fh, sstream); 181 235 182 236 return 0; … … 223 277 224 278 ssize_t driver_alsa_write(struct roar_vio_calls * vio, void *buf, size_t size) { 225 ssize_t have = 0; 279 char* mutable_buf = (char*)buf; 280 ssize_t have = 0; 226 281 ssize_t ret; 227 282 228 283 while (size) { 229 ret = driver_alsa_write_int(vio, buf, size);284 ret = driver_alsa_write_int(vio, mutable_buf, size); 230 285 if ( ret < 0 ) 231 286 return -1; 232 287 233 have += ret;234 buf+= ret;235 size -= ret;288 have += ret; 289 mutable_buf += ret; 290 size -= ret; 236 291 } 237 292 … … 239 294 } 240 295 296 int driver_alsa_sync(struct roar_vio_calls * vio) { 297 roar_alsa_t * device = vio->inst; 298 return snd_pcm_drain(device->handle); 299 } 300 301 /* Stop the driver, set new params, and restart */ 302 /* Not been able to test this function. */ 303 /* Assuming that params can be reset after halting the PCM device */ 304 static int driver_alsa_reopen_device(roar_alsa_t * device) { 305 306 if ( snd_pcm_drop(device->handle) < 0 ) { 307 ROAR_ERR("driver_alsa_reopen_device(*): snd_pcm_drop() failed."); 308 return -1; 309 } 310 311 if ( driver_alsa_set_params(device) < 0 ) { 312 ROAR_ERR("driver_alsa_reopen_device(*): driver_alsa_set_params() failed."); 313 return -1; 314 } 315 316 return 0; 317 } 318 319 /* Not completely tested. 320 * Tested: 321 * ROAR_VIO_CTL_GET_DELAY 322 * ROAR_VIO_CTL_SET_SSTREAMID 323 * ROAR_VIO_CTL_SET_SSTREAM 324 */ 325 326 int driver_alsa_ctl(struct roar_vio_calls * vio, int cmd, void * data) { 327 roar_alsa_t * device = vio->inst; 328 snd_pcm_sframes_t alsa_delay; 329 330 ROAR_DBG("driver_alsa_ctl(vio=%p, cmd=0x%.8x, data=%p) = ?", vio, cmd, data); 331 332 switch (cmd) { 333 case ROAR_VIO_CTL_GET_DELAY: 334 if ( snd_pcm_delay(device->handle, &alsa_delay) < 0 ) 335 return -1; 336 else { 337 *(uint_least32_t *)data = snd_pcm_frames_to_bytes(device->handle, alsa_delay); 338 ROAR_DBG("driver_alsa_ctl(vio=%p, cmd=ROAR_VIO_CTL_GET_DELAY(0x%.8x), data=%p): %i bytes.", vio, cmd, data, (int)(*(uint_least32_t*)data)); 339 } 340 break; 341 342 case ROAR_VIO_CTL_SET_SSTREAMID: 343 device->ssid = *(int *)data; 344 ROAR_DBG("driver_alsa_ctl(vio=%p, cmd=ROAR_VIO_CTL_SET_SSTREAMID(0x%.8x), data=%p): ssid=%i", vio, cmd, data, device->ssid); 345 break; 346 347 case ROAR_VIO_CTL_SET_SSTREAM: 348 device->sstream = data; 349 ROAR_DBG("driver_alsa_ctl(vio=%p, cmd=ROAR_VIO_CTL_SET_SSTREAM(0x%.8x), data=%p): sstream=%p", vio, cmd, data, device->sstream); 350 break; 351 352 case ROAR_VIO_CTL_GET_AUINFO: 353 ROAR_DBG("driver_alsa_ctl(vio=%p, cmd=ROAR_VIO_CTL_GET_AUINFO(0x%.8x), data=%p) = ?", vio, cmd, data); 354 memcpy(data, &(device->info), sizeof(struct roar_audio_info)); 355 break; 356 357 case ROAR_VIO_CTL_SET_AUINFO: 358 ROAR_DBG("driver_alsa_ctl(vio=%p, cmd=ROAR_VIO_CTL_SET_AUINFO(0x%.8x), data=%p) = ?", vio, cmd, data); 359 memcpy(&(device->info), data, sizeof(struct roar_audio_info)); 360 return driver_alsa_reopen_device(device); 361 362 default: 363 return -1; 364 } 365 366 return 0; 367 } 368 241 369 #endif 242 370 -
roard/include/driver_alsa.h
r3692 r4160 28 28 #define _DRIVER_ALSA_H_ 29 29 30 typedef struct roar_alsa { 31 snd_pcm_t * handle; 32 snd_pcm_hw_params_t * params; 33 snd_pcm_format_t format; 34 struct roar_audio_info info; 35 struct roar_stream_server * sstream; 36 int ssid; 37 } roar_alsa_t; 38 30 39 int driver_alsa_open_vio(struct roar_vio_calls * inst, char * device, struct roar_audio_info * info, int fh, struct roar_stream_server * sstream); 31 40 ssize_t driver_alsa_write (struct roar_vio_calls * vio, void *buf, size_t count); 32 41 int driver_alsa_close (struct roar_vio_calls * vio); 42 int driver_alsa_sync (struct roar_vio_calls * vio); 43 int driver_alsa_ctl (struct roar_vio_calls * vio, int cmd, void * data); 33 44 34 45 #endif
Note: See TracChangeset
for help on using the changeset viewer.