summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar waker <wakeroid@gmail.com>2010-11-09 21:59:10 +0100
committerGravatar waker <wakeroid@gmail.com>2010-11-09 21:59:10 +0100
commit6691bdb5619d20d9f4d230e857d51b127b718b1f (patch)
treedea4932ace91d2e6aef7c410aca9c1cf254516c6
parentfefae21f4e8af5d90d14a5e90d259ebb32cc335c (diff)
new alsa setformat
-rw-r--r--deadbeef.h4
-rw-r--r--plugins/alsa/alsa.c104
-rw-r--r--streamer.c29
3 files changed, 87 insertions, 50 deletions
diff --git a/deadbeef.h b/deadbeef.h
index d09e8ac9..435bd934 100644
--- a/deadbeef.h
+++ b/deadbeef.h
@@ -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,
diff --git a/streamer.c b/streamer.c
index 0b89583a..07318570 100644
--- a/streamer.c
+++ b/streamer.c
@@ -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;
}