diff options
author | waker <wakeroid@gmail.com> | 2010-11-09 21:59:10 +0100 |
---|---|---|
committer | waker <wakeroid@gmail.com> | 2010-11-09 21:59:10 +0100 |
commit | 6691bdb5619d20d9f4d230e857d51b127b718b1f (patch) | |
tree | dea4932ace91d2e6aef7c410aca9c1cf254516c6 | |
parent | fefae21f4e8af5d90d14a5e90d259ebb32cc335c (diff) |
new alsa setformat
-rw-r--r-- | deadbeef.h | 4 | ||||
-rw-r--r-- | plugins/alsa/alsa.c | 104 | ||||
-rw-r--r-- | streamer.c | 29 |
3 files changed, 87 insertions, 50 deletions
@@ -724,8 +724,8 @@ typedef struct DB_output_s { int (*init) (void); // free is called if output plugin was changed to another, or unload is about to happen int (*free) (void); - // reconfigure output to another samplerate, if supported - int (*change_rate) (int rate); + // reconfigure output to another format, if supported + void (*setformat) (ddb_waveformat_t *fmt); // play, stop, pause, unpause are called by deadbeef in response to user // events, or as part of streaming process int (*play) (void); diff --git a/plugins/alsa/alsa.c b/plugins/alsa/alsa.c index b74dcabf..837305cd 100644 --- a/plugins/alsa/alsa.c +++ b/plugins/alsa/alsa.c @@ -23,8 +23,8 @@ #include "../../deadbeef.h" #include "../../config.h" -//#define trace(...) { fprintf(stderr, __VA_ARGS__); } -#define trace(fmt,...) +#define trace(...) { fprintf(stderr, __VA_ARGS__); } +//#define trace(fmt,...) #define min(x,y) ((x)<(y)?(x):(y)) @@ -41,7 +41,7 @@ DB_functions_t *deadbeef; static snd_pcm_t *audio; static int alsa_terminate; -static int requested_rate = -1; +static ddb_waveformat_t requested_fmt; static int state; // one of output_state_t static uintptr_t mutex; static intptr_t alsa_tid; @@ -89,8 +89,8 @@ palsa_init (void); static int palsa_free (void); -static int -palsa_change_rate (int rate); +static void +palsa_setformat (ddb_waveformat_t *fmt); static int palsa_play (void); @@ -114,7 +114,7 @@ static void palsa_enum_soundcards (void (*callback)(const char *name, const char *desc, void*), void *userdata); static int -palsa_set_hw_params (int samplerate) { +palsa_set_hw_params (ddb_waveformat_t *fmt) { snd_pcm_hw_params_t *hw_params = NULL; int err = 0; @@ -136,22 +136,45 @@ palsa_set_hw_params (int samplerate) { goto error; } - snd_pcm_format_t fmt; + snd_pcm_format_t sample_fmt; + + switch (fmt->bps) { + case 8: + sample_fmt = SND_PCM_FORMAT_S8; + break; + case 16: +#if WORDS_BIGENDIAN + sample_fmt = SND_PCM_FORMAT_S16_BE; +#else + sample_fmt = SND_PCM_FORMAT_S16_LE; +#endif + break; + case 24: +#if WORDS_BIGENDIAN + sample_fmt = SND_PCM_FORMAT_S24_3BE; +#else + sample_fmt = SND_PCM_FORMAT_S24_3LE; +#endif + break; + case 32: #if WORDS_BIGENDIAN - fmt = SND_PCM_FORMAT_S16_BE; + sample_fmt = SND_PCM_FORMAT_S32_BE; #else - fmt = SND_PCM_FORMAT_S16_LE; + sample_fmt = SND_PCM_FORMAT_S32_LE; #endif - if ((err = snd_pcm_hw_params_set_format (audio, hw_params, fmt)) < 0) { + break; + }; + + if ((err = snd_pcm_hw_params_set_format (audio, hw_params, sample_fmt)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); goto error; } - snd_pcm_hw_params_get_format (hw_params, &fmt); + snd_pcm_hw_params_get_format (hw_params, &sample_fmt); trace ("chosen sample format: %04Xh\n", (int)fmt); - int val = samplerate; + int val = fmt->samplerate; int ret = 0; if ((err = snd_pcm_hw_params_set_rate_resample (audio, hw_params, conf_alsa_resample)) < 0) { @@ -168,7 +191,7 @@ palsa_set_hw_params (int samplerate) { plugin.fmt.samplerate = val; trace ("chosen samplerate: %d Hz\n", val); - if ((err = snd_pcm_hw_params_set_channels (audio, hw_params, 2)) < 0) { + if ((err = snd_pcm_hw_params_set_channels (audio, hw_params, fmt->channels)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); goto error; @@ -195,8 +218,26 @@ palsa_set_hw_params (int samplerate) { goto error; } - plugin.fmt.bps = 16; - plugin.fmt.channels = 2; + switch (sample_fmt) { + case SND_PCM_FORMAT_S8: + plugin.fmt.bps = 8; + break; + case SND_PCM_FORMAT_S16_BE: + case SND_PCM_FORMAT_S16_LE: + plugin.fmt.bps = 16; + break; + case SND_PCM_FORMAT_S24_3BE: + case SND_PCM_FORMAT_S24_3LE: + plugin.fmt.bps = 24; + break; + case SND_PCM_FORMAT_S32_BE: + case SND_PCM_FORMAT_S32_LE: + plugin.fmt.bps = 32; + break; + } + + plugin.fmt.bps = sample_fmt; + plugin.fmt.channels = nchan; plugin.fmt.is_float = 0; plugin.fmt.is_multichannel = 0; plugin.fmt.channelmask = 0; @@ -231,11 +272,11 @@ palsa_init (void) { mutex = deadbeef->mutex_create (); - if (requested_rate != -1) { - plugin.fmt.samplerate = requested_rate; + if (requested_fmt.samplerate != 0) { + memcpy (&plugin.fmt, &requested_fmt, sizeof (ddb_waveformat_t)); } - if (palsa_set_hw_params (plugin.fmt.samplerate) < 0) { + if (palsa_set_hw_params (&plugin.fmt) < 0) { goto open_error; } @@ -307,28 +348,27 @@ open_error: return -1; } -int -palsa_change_rate (int rate) { - trace ("palsa_change_rate: %d\n", rate); - requested_rate = rate; +void +palsa_setformat (ddb_waveformat_t *fmt) { + memcpy (&requested_fmt, fmt, sizeof (ddb_waveformat_t)); + trace ("palsa_setformat %dbit %s %s %dch %dHz channelmask=%X\n", fmt->bps, fmt->is_float ? "float" : "int", fmt->is_multichannel ? "multichannel" : "", fmt->channels, fmt->samplerate, fmt->channelmask); if (!audio) { - return plugin.fmt.samplerate; + return; } - if (rate == plugin.fmt.samplerate) { - trace ("palsa_change_rate %d: ignored\n", rate); - return rate; + if (!memcmp (fmt, &plugin.fmt, sizeof (ddb_waveformat_t))) { + trace ("palsa_setformat ignored\n"); + return; } state = OUTPUT_STATE_STOPPED; LOCK; snd_pcm_drop (audio); - int ret = palsa_set_hw_params (rate); + int ret = palsa_set_hw_params (fmt); UNLOCK; if (ret < 0) { - trace ("palsa_change_rate: impossible to set samplerate to %d\n", rate); - return plugin.fmt.samplerate; + trace ("palsa_change_rate: impossible to set requested format\n"); + return; } - trace ("chosen samplerate: %d\n", plugin.fmt.samplerate); - return plugin.fmt.samplerate; + trace ("new format %dbit %s %s %dch %dHz channelmask=%X\n", plugin.fmt.bps, plugin.fmt.is_float ? "float" : "int", plugin.fmt.is_multichannel ? "multichannel" : "", plugin.fmt.channels, plugin.fmt.samplerate, plugin.fmt.channelmask); } int @@ -654,7 +694,7 @@ static DB_output_t plugin = { .plugin.configdialog = settings_dlg, .init = palsa_init, .free = palsa_free, - .change_rate = palsa_change_rate, + .setformat = palsa_setformat, .play = palsa_play, .stop = palsa_stop, .pause = palsa_pause, @@ -36,8 +36,8 @@ #include "volume.h" #include "vfs.h" -//#define trace(...) { fprintf(stderr, __VA_ARGS__); } -#define trace(fmt,...) +#define trace(...) { fprintf(stderr, __VA_ARGS__); } +//#define trace(fmt,...) // #define WRITE_DUMP 1 @@ -660,7 +660,7 @@ streamer_set_current (playItem_t *it) { streaming_track = it; pl_item_ref (streaming_track); mutex_unlock (decodemutex); - trace ("bps=%d, channels=%d, samplerate=%d\n", fileinfo->bps, fileinfo->fmt.channels, fileinfo->fmt.samplerate); + trace ("bps=%d, channels=%d, samplerate=%d\n", fileinfo->fmt.bps, fileinfo->fmt.channels, fileinfo->fmt.samplerate); } // FIXME: that might break streaming at boundaries between 2 different samplerates // streamer_reset (0); // reset SRC @@ -818,7 +818,7 @@ streamer_start_new_song (void) { if (output->state () != OUTPUT_STATE_PLAYING) { streamer_reset (1); if (fileinfo) { - plug_get_output ()->change_rate (fileinfo->fmt.samplerate); + plug_get_output ()->setformat (&fileinfo->fmt); } if (output->play () < 0) { fprintf (stderr, "streamer: failed to start playback; output plugin doesn't work\n"); @@ -832,7 +832,7 @@ streamer_start_new_song (void) { avg_bitrate = -1; streamer_reset (1); if (fileinfo) { - plug_get_output ()->change_rate (fileinfo->fmt.samplerate); + plug_get_output ()->setformat (&fileinfo->fmt); } if (output->play () < 0) { fprintf (stderr, "streamer: failed to start playback; output plugin doesn't work\n"); @@ -927,12 +927,14 @@ streamer_thread (void *ctx) { if (conf_get_int ("playback.dynsamplerate", 0)) { // don't switch if unchanged - int prevtrack_samplerate = output->fmt.samplerate; - if (prevtrack_samplerate != fileinfo->fmt.samplerate) { - int newrate = output->change_rate (fileinfo->fmt.samplerate); - if (newrate != prevtrack_samplerate) { + ddb_waveformat_t prevfmt; + memcpy (&prevfmt, &output->fmt, sizeof (ddb_waveformat_t)); + if (memcmp (&output->fmt, &fileinfo->fmt, sizeof (ddb_waveformat_t))) { + output->setformat (&fileinfo->fmt); + // check if the format actually changed + if (memcmp (&output->fmt, &prevfmt, sizeof (ddb_waveformat_t))) { // restart streaming of current track - trace ("streamer: output samplerate changed from %d to %d; restarting track\n", prevtrack_samplerate, newrate); + trace ("streamer: output samplerate changed from %d to %d; restarting track\n", prevfmt.samplerate, output->fmt.samplerate); mutex_lock (decodemutex); fileinfo->plugin->free (fileinfo); fileinfo = NULL; @@ -952,16 +954,13 @@ streamer_thread (void *ctx) { bytes_until_next_song = -1; streamer_buffering = 1; streamer_reset (1); - if (fileinfo) { - prevtrack_samplerate = fileinfo->fmt.samplerate; - } } } // output plugin may stop playback before switching samplerate if (output->state () != OUTPUT_STATE_PLAYING) { if (fileinfo) { - plug_get_output ()->change_rate (fileinfo->fmt.samplerate); + plug_get_output ()->setformat (&fileinfo->fmt); } if (output->play () < 0) { fprintf (stderr, "streamer: failed to start playback after samplerate change; output plugin doesn't work\n"); @@ -1570,7 +1569,6 @@ streamer_read_async (char *bytes, int size) { bytes_until_next_song = -1; } } - trace ("streamer: bytesread=%d\n", bytesread); if (bytesread > 0) { // apply dsp DB_dsp_t **dsp = deadbeef->plug_get_dsp_list (); @@ -1584,7 +1582,6 @@ streamer_read_async (char *bytes, int size) { mutex_unlock (decodemutex); bytes += bytesread; size -= bytesread; - trace ("streamer: size=%d\n", size); if (size == 0) { return initsize; } |