Changeset 4160:87a2bd2f45a7 in roaraudio


Ignore:
Timestamp:
08/13/10 16:53:16 (14 years ago)
Author:
phi
Branch:
default
Phase:
public
Message:

updated ALSA driver a lot

Location:
roard
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • roard/driver_alsa.c

    r3695 r4160  
    3131#define ALSA_PCM_NEW_HW_PARAMS_API 
    3232 
    33 typedef struct roar_alsa { 
    34  snd_pcm_t *handle; 
    35  snd_pcm_hw_params_t* params; 
    36 } roar_alsa_t; 
     33static 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 
     83static 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 
     147error: 
     148 snd_pcm_hw_params_free(device->params); 
     149 ROAR_DBG("driver_alsa_set_params(device=%p) = -1", device); 
     150 return -1; 
     151} 
    37152 
    38153int driver_alsa_open_vio(struct roar_vio_calls * inst, char * device, struct roar_audio_info * info, int fh, struct roar_stream_server * sstream) { 
     
    40155 char            * alsa_dev; 
    41156 int               rc; 
    42  unsigned          buffer_time = 200000; // 200ms buffer 
    43  snd_pcm_uframes_t frames      = ROAR_OUTPUT_BUFFER_SAMPLES; // ALSA frames 
    44  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; 
    47157 int               autoconf; 
    48158 
     159 ROAR_DBG("driver_alsa_open_vio(inst=%p, device='%s', info=%p, fh=%i, sstream=%p) = ?", inst, device, info, fh, sstream); 
    49160 
    50161 if ( fh != -1 ) 
     
    53164 if ( (interface = roar_mm_calloc(1, sizeof(roar_alsa_t))) == NULL ) 
    54165  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); 
    55168 
    56169 if ( device == NULL ) { 
     
    60173 } 
    61174 
     175 ROAR_DBG("driver_alsa_open_vio(inst=%p, device='%s', info=%p, fh=%i, sstream=%p) = ?", inst, device, info, fh, sstream); 
     176 
    62177 rc = snd_pcm_open(&(interface->handle), alsa_dev, SND_PCM_STREAM_PLAYBACK, 0);  
    63178 if ( rc < 0 ) { 
     
    68183 
    69184 // 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); 
    119188 
    120189 // We did not find a codec 
    121  if ( format == SND_PCM_FORMAT_UNKNOWN ) { 
     190 if ( interface->format == SND_PCM_FORMAT_UNKNOWN ) { 
    122191  autoconf = streams_get_flag(ROAR_STREAM(sstream)->id, ROAR_FLAG_AUTOCONF); 
    123192  if ( autoconf == -1 ) { 
     
    130199 
    131200#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; 
    134203#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; 
    137206#else 
    138207   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"); 
     
    146215 } 
    147216 
    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 ) 
    150222  goto init_error; 
    151223 
    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); 
    175225 
    176226 memset(inst, 0, sizeof(struct roar_vio_calls)); 
     
    179229 inst->write = driver_alsa_write; 
    180230 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); 
    181235 
    182236 return 0; 
     
    223277 
    224278ssize_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; 
    226281 ssize_t ret; 
    227282 
    228283 while (size) { 
    229   ret = driver_alsa_write_int(vio, buf, size); 
     284  ret = driver_alsa_write_int(vio, mutable_buf, size); 
    230285  if ( ret < 0 ) 
    231286   return -1; 
    232287 
    233   have += ret; 
    234   buf += ret; 
    235   size -= ret; 
     288  have        += ret; 
     289  mutable_buf += ret; 
     290  size        -= ret; 
    236291 } 
    237292 
     
    239294} 
    240295 
     296int 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 */ 
     304static 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 
     326int 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 
    241369#endif 
    242370 
  • roard/include/driver_alsa.h

    r3692 r4160  
    2828#define _DRIVER_ALSA_H_ 
    2929 
     30typedef 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 
    3039int     driver_alsa_open_vio(struct roar_vio_calls * inst, char * device, struct roar_audio_info * info, int fh, struct roar_stream_server * sstream); 
    3140ssize_t driver_alsa_write   (struct roar_vio_calls * vio, void *buf, size_t count); 
    3241int     driver_alsa_close   (struct roar_vio_calls * vio); 
     42int     driver_alsa_sync    (struct roar_vio_calls * vio); 
     43int     driver_alsa_ctl     (struct roar_vio_calls * vio, int cmd, void * data); 
    3344 
    3445#endif 
Note: See TracChangeset for help on using the changeset viewer.