diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | deadbeef.h | 59 | ||||
-rw-r--r-- | main.c | 29 | ||||
-rw-r--r-- | playback.h | 34 | ||||
-rw-r--r-- | playlist.c | 1 | ||||
-rw-r--r-- | plugins.c | 10 | ||||
-rw-r--r-- | plugins/alsa/alsa.c | 67 | ||||
-rw-r--r-- | plugins/gtkui/gtkui.c | 10 | ||||
-rw-r--r-- | plugins/mpgmad/mpgmad.c | 22 | ||||
-rw-r--r-- | scripts/configure_minimal.sh | 1 | ||||
-rwxr-xr-x | scripts/quickinstall.sh | 1 | ||||
-rw-r--r-- | streamer.c | 107 |
12 files changed, 163 insertions, 179 deletions
diff --git a/Makefile.am b/Makefile.am index fb4a7b5f..77db2954 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,6 @@ deadbeef_SOURCES =\ streamer.c streamer.h\ messagepump.c messagepump.h\ conf.c conf.h\ - playback.h\ threading_pthread.c threading.h\ volume.c volume.h\ junklib.h junklib.c utf8.c utf8.h u8_lc_map.h\ @@ -619,20 +619,63 @@ typedef struct DB_plugin_s { const char *configdialog; } DB_plugin_t; -typedef struct DB_fileinfo_s { - struct DB_decoder_s *plugin; +// file format stuff + +// channel mask - combine following flags to tell streamer which channels are +// present in input/output streams +enum { + DDB_SPEAKER_FRONT_LEFT = 0x1, + DDB_SPEAKER_FRONT_RIGHT = 0x2, + DDB_SPEAKER_FRONT_CENTER = 0x4, + DDB_SPEAKER_LOW_FREQUENCY = 0x8, + DDB_SPEAKER_BACK_LEFT = 0x10, + DDB_SPEAKER_BACK_RIGHT = 0x20, + DDB_SPEAKER_FRONT_LEFT_OF_CENTER = 0x40, + DDB_SPEAKER_FRONT_RIGHT_OF_CENTER = 0x80, + DDB_SPEAKER_BACK_CENTER = 0x100, + DDB_SPEAKER_SIDE_LEFT = 0x200, + DDB_SPEAKER_SIDE_RIGHT = 0x400, + DDB_SPEAKER_TOP_CENTER = 0x800, + DDB_SPEAKER_TOP_FRONT_LEFT = 0x1000, + DDB_SPEAKER_TOP_FRONT_CENTER = 0x2000, + DDB_SPEAKER_TOP_FRONT_RIGHT = 0x4000, + DDB_SPEAKER_TOP_BACK_LEFT = 0x8000, + DDB_SPEAKER_TOP_BACK_CENTER = 0x10000, + DDB_SPEAKER_TOP_BACK_RIGHT = 0x20000 +}; + +typedef struct { int bps; + int is_float; // bps must be 32 if this is true + int is_multichannel; // usually 0, in which case channels=1 is mono, and channels=2 is stereo int channels; int samplerate; + uint32_t channelmask; +} ddb_waveformat_t; + +typedef struct DB_fileinfo_s { + struct DB_decoder_s *plugin; + + // these parameters should be set in decoder->open + ddb_waveformat_t fmt; + + // readpos should be updated to current decoder time (in seconds) float readpos; + + // this is the (optional) file handle, that can be used by streamer to + // request interruption of current read operation DB_FILE *file; } DB_fileinfo_t; +enum { + DDB_DECODER_HINT_16BIT = 0x1, // that flag means streamer prefers 16 bit streams for performance reasons +}; + // decoder plugin typedef struct DB_decoder_s { DB_plugin_t plugin; - DB_fileinfo_t *(*open) (void); + DB_fileinfo_t *(*open) (uint32_t hints); // init is called to prepare song to be started int (*init) (DB_fileinfo_t *info, DB_playItem_t *it); @@ -691,15 +734,11 @@ typedef struct DB_output_s { int (*unpause) (void); // one of output_state_t enum values int (*state) (void); - // following functions must return output sampling rate, bits per sample and number - // of channels - int (*samplerate) (void); - int (*bitspersample) (void); - int (*channels) (void); - // must return 0 for little endian output, or 1 for big endian - int (*endianness) (void); // soundcard enumeration (can be NULL) void (*enum_soundcards) (void (*callback)(const char *name, const char *desc, void*), void *userdata); + + // parameters of current output + ddb_waveformat_t fmt; } DB_output_t; // dsp plugin @@ -47,7 +47,6 @@ #include <unistd.h> #include "gettext.h" #include "playlist.h" -#include "playback.h" #include "threading.h" #include "messagepump.h" #include "streamer.h" @@ -368,6 +367,7 @@ player_mainloop (void) { uint32_t p1; uint32_t p2; while (messagepump_pop(&msg, &ctx, &p1, &p2) != -1) { + DB_output_t *output = plug_get_output (); switch (msg) { case M_REINIT_SOUND: plug_reinit_sound (); @@ -377,7 +377,7 @@ player_mainloop (void) { return; case M_PLAYSONG: if (p1) { - p_stop (); + output->stop (); pl_playqueue_clear (); streamer_set_nextsong (0, 1); } @@ -386,7 +386,7 @@ player_mainloop (void) { } break; case M_PLAYSONGNUM: - p_stop (); + output->stop (); pl_playqueue_clear (); streamer_set_nextsong (p1, 1); break; @@ -394,25 +394,25 @@ player_mainloop (void) { streamer_set_nextsong (-2, 0); break; case M_NEXTSONG: - p_stop (); + output->stop (); streamer_move_to_nextsong (1); break; case M_PREVSONG: - p_stop (); + output->stop (); streamer_move_to_prevsong (); break; case M_PAUSESONG: - if (p_get_state () == OUTPUT_STATE_PAUSED) { - p_unpause (); + if (output->state () == OUTPUT_STATE_PAUSED) { + output->unpause (); plug_trigger_event_paused (0); } else { - p_pause (); + output->pause (); plug_trigger_event_paused (1); } break; case M_PLAYRANDOM: - p_stop (); + output->stop (); streamer_move_to_randomsong (); break; case M_PLAYLISTREFRESH: @@ -487,10 +487,11 @@ sigsegv_handler (int sig) { void save_resume_state (void) { playItem_t *trk = streamer_get_playing_track (); + DB_output_t *output = plug_get_output (); float playpos = -1; int playtrack = -1; int playlist = streamer_get_current_playlist (); - int paused = (p_get_state () == OUTPUT_STATE_PAUSED); + int paused = (output->state () == OUTPUT_STATE_PAUSED); if (trk && playlist >= 0) { playtrack = str_get_idx_of (trk); playpos = streamer_get_playpos (); @@ -505,7 +506,8 @@ save_resume_state (void) { void restore_resume_state (void) { - if (conf_get_int ("resume_last_session", 0) && p_isstopped ()) { + DB_output_t *output = plug_get_output (); + if (conf_get_int ("resume_last_session", 0) && output->state () == OUTPUT_STATE_STOPPED) { int plt = conf_get_int ("resume.playlist", -1); int track = conf_get_int ("resume.track", -1); float pos = conf_get_float ("resume.position", -1); @@ -795,9 +797,10 @@ main (int argc, char *argv[]) { server_close (); // stop streaming and playback before unloading plugins - p_stop (); + DB_output_t *output = plug_get_output (); + output->stop (); streamer_free (); - p_free (); + output->free (); // plugins might still hood references to playitems, // and query configuration in background diff --git a/playback.h b/playback.h deleted file mode 100644 index 21ac74f1..00000000 --- a/playback.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - DeaDBeeF - ultimate music player for GNU/Linux systems with X11 - Copyright (C) 2009-2010 Alexey Yakovenko <waker@users.sourceforge.net> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ -#ifndef __PLAYBACK_H -#define __PLAYBACK_H - -#define p_init plug_get_output ()->init -#define p_free plug_get_output ()->free -#define p_play plug_get_output ()->play -#define p_stop plug_get_output ()->stop -#define p_pause plug_get_output ()->pause -#define p_unpause plug_get_output ()->unpause -#define p_get_rate plug_get_output ()->samplerate -#define p_get_state plug_get_output ()->state - -#define p_state() (plug_get_output ()->state ()) -#define p_isstopped() (p_state () == OUTPUT_STATE_STOPPED) -#define p_ispaused() (p_state () == OUTPUT_STATE_PAUSED) - -#endif // __PLAYBACK_H @@ -39,7 +39,6 @@ #include "playlist.h" #include "streamer.h" #include "messagepump.h" -#include "playback.h" #include "plugins.h" #include "junklib.h" #include "vfs.h" @@ -38,7 +38,6 @@ #include "playlist.h" #include "volume.h" #include "streamer.h" -#include "playback.h" #include "common.h" #include "conf.h" #include "junklib.h" @@ -931,9 +930,10 @@ plug_select_output (void) { void plug_reinit_sound (void) { - int state = p_get_state (); + DB_output_t *output = plug_get_output (); + int state = output->state (); - p_free (); + output->free (); DB_output_t *prev = plug_get_output (); if (plug_select_output () < 0) { @@ -942,13 +942,13 @@ plug_reinit_sound (void) { output_plugin = prev; } streamer_reset (1); - if (p_init () < 0) { + if (output->init () < 0) { streamer_set_nextsong (-2, 0); return; } if (state != OUTPUT_STATE_PAUSED && state != OUTPUT_STATE_STOPPED) { - if (p_play () < 0) { + if (output->play () < 0) { trace ("failed to reinit sound output\n"); streamer_set_nextsong (-2, 0); } diff --git a/plugins/alsa/alsa.c b/plugins/alsa/alsa.c index 65178e55..b74dcabf 100644 --- a/plugins/alsa/alsa.c +++ b/plugins/alsa/alsa.c @@ -42,7 +42,6 @@ DB_functions_t *deadbeef; static snd_pcm_t *audio; static int alsa_terminate; static int requested_rate = -1; -static int alsa_rate = 44100; static int state; // one of output_state_t static uintptr_t mutex; static intptr_t alsa_tid; @@ -106,12 +105,6 @@ static int palsa_unpause (void); static int -palsa_get_rate (void); - -static int -palsa_get_bps (void); - -static int palsa_get_channels (void); static int @@ -123,7 +116,6 @@ palsa_enum_soundcards (void (*callback)(const char *name, const char *desc, void static int palsa_set_hw_params (int samplerate) { snd_pcm_hw_params_t *hw_params = NULL; -// int alsa_resample = conf_get_int ("alsa.resample", 0); int err = 0; if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { @@ -173,8 +165,8 @@ palsa_set_hw_params (int samplerate) { snd_strerror (err)); goto error; } - alsa_rate = val; - trace ("chosen samplerate: %d Hz\n", alsa_rate); + plugin.fmt.samplerate = val; + trace ("chosen samplerate: %d Hz\n", val); if ((err = snd_pcm_hw_params_set_channels (audio, hw_params, 2)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", @@ -202,6 +194,13 @@ palsa_set_hw_params (int samplerate) { snd_strerror (err)); goto error; } + + plugin.fmt.bps = 16; + plugin.fmt.channels = 2; + plugin.fmt.is_float = 0; + plugin.fmt.is_multichannel = 0; + plugin.fmt.channelmask = 0; + error: if (hw_params) { snd_pcm_hw_params_free (hw_params); @@ -233,10 +232,10 @@ palsa_init (void) { mutex = deadbeef->mutex_create (); if (requested_rate != -1) { - alsa_rate = requested_rate; + plugin.fmt.samplerate = requested_rate; } - if (palsa_set_hw_params (alsa_rate) < 0) { + if (palsa_set_hw_params (plugin.fmt.samplerate) < 0) { goto open_error; } @@ -313,9 +312,9 @@ palsa_change_rate (int rate) { trace ("palsa_change_rate: %d\n", rate); requested_rate = rate; if (!audio) { - return alsa_rate; + return plugin.fmt.samplerate; } - if (rate == alsa_rate) { + if (rate == plugin.fmt.samplerate) { trace ("palsa_change_rate %d: ignored\n", rate); return rate; } @@ -326,10 +325,10 @@ palsa_change_rate (int rate) { UNLOCK; if (ret < 0) { trace ("palsa_change_rate: impossible to set samplerate to %d\n", rate); - return alsa_rate; + return plugin.fmt.samplerate; } - trace ("chosen samplerate: %d\n", alsa_rate); - return alsa_rate; + trace ("chosen samplerate: %d\n", plugin.fmt.samplerate); + return plugin.fmt.samplerate; } int @@ -453,33 +452,6 @@ palsa_unpause (void) { return 0; } -int -palsa_get_rate (void) { - if (!audio) { - palsa_init (); - } - return alsa_rate; -} - -int -palsa_get_bps (void) { - return 16; -} - -int -palsa_get_channels (void) { - return 2; -} - -static int -palsa_get_endianness (void) { -#if WORDS_BIGENDIAN - return 1; -#else - return 0; -#endif -} - static void palsa_thread (void *context) { prctl (PR_SET_NAME, "deadbeef-alsa", 0, 0, 0, 0); @@ -541,7 +513,7 @@ palsa_thread (void *context) { frames_to_deliver = snd_pcm_avail_update (audio); } UNLOCK; - usleep (period_size * 1000000 / alsa_rate / 2); + usleep (period_size * 1000000 / plugin.fmt.samplerate / 2); } } @@ -688,9 +660,6 @@ static DB_output_t plugin = { .pause = palsa_pause, .unpause = palsa_unpause, .state = palsa_get_state, - .samplerate = palsa_get_rate, - .bitspersample = palsa_get_bps, - .channels = palsa_get_channels, - .endianness = palsa_get_endianness, .enum_soundcards = palsa_enum_soundcards, + .fmt = {.samplerate = 44100} }; diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c index 06ceb756..46b3edf8 100644 --- a/plugins/gtkui/gtkui.c +++ b/plugins/gtkui/gtkui.c @@ -154,15 +154,15 @@ update_songinfo (gpointer ctx) { const char *mode; char temp[20]; - if (c->channels <= 2) { - mode = c->channels == 1 ? _("Mono") : _("Stereo"); + if (c->fmt.channels <= 2) { + mode = c->fmt.channels == 1 ? _("Mono") : _("Stereo"); } else { - snprintf (temp, sizeof (temp), "%dch Multichannel", c->channels); + snprintf (temp, sizeof (temp), "%dch Multichannel", c->fmt.channels); mode = temp; } - int samplerate = c->samplerate; - int bitspersample = c->bps; + int samplerate = c->fmt.samplerate; + int bitspersample = c->fmt.bps; songpos = playpos; // codec_unlock (); diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c index 03ddbc91..1d5890ac 100644 --- a/plugins/mpgmad/mpgmad.c +++ b/plugins/mpgmad/mpgmad.c @@ -567,7 +567,7 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { static DB_fileinfo_t * -cmp3_open (void) { +cmp3_open (uint32_t hints) { DB_fileinfo_t *_info = malloc (sizeof (mpgmad_info_t)); mpgmad_info_t *info = (mpgmad_info_t *)_info; memset (info, 0, sizeof (mpgmad_info_t)); @@ -651,9 +651,9 @@ cmp3_init (DB_fileinfo_t *_info, DB_playItem_t *it) { trace ("bad mpeg file: %f\n", it->fname); return -1; } - _info->bps = info->buffer.bitspersample; - _info->samplerate = info->buffer.samplerate; - _info->channels = info->buffer.channels; + _info->fmt.bps = info->buffer.bitspersample; + _info->fmt.samplerate = info->buffer.samplerate; + _info->fmt.channels = info->buffer.channels; mad_stream_init(&info->stream); mad_stream_options (&info->stream, MAD_OPTION_IGNORECRC); @@ -748,12 +748,12 @@ cmp3_decode_requested_int16 (mpgmad_info_t *info) { *((int16_t*)info->buffer.out) = sample; info->buffer.readsize -= 2; info->buffer.out += 2; - if (MAD_NCHANNELS(&info->frame.header) == 2 && info->info.channels == 2) { + if (MAD_NCHANNELS(&info->frame.header) == 2 && info->info.fmt.channels == 2) { *((int16_t*)info->buffer.out) = MadFixedToSshort (info->synth.pcm.samples[1][idx]); info->buffer.readsize -= 2; info->buffer.out += 2; } - else if (MAD_NCHANNELS(&info->frame.header) == 1 && info->info.channels == 2) { + else if (MAD_NCHANNELS(&info->frame.header) == 1 && info->info.fmt.channels == 2) { *((int16_t*)info->buffer.out) = sample; info->buffer.readsize -= 2; info->buffer.out += 2; @@ -775,12 +775,12 @@ cmp3_decode_requested_float32 (mpgmad_info_t *info) { *((float*)info->buffer.out) = sample; info->buffer.readsize -= 4; info->buffer.out += 4; - if (MAD_NCHANNELS(&info->frame.header) == 2 && info->info.channels == 2) { + if (MAD_NCHANNELS(&info->frame.header) == 2 && info->info.fmt.channels == 2) { *((float*)info->buffer.out) = MadFixedToFloat (info->synth.pcm.samples[1][idx]); info->buffer.readsize -= 4; info->buffer.out += 4; } - else if (MAD_NCHANNELS(&info->frame.header) == 1 && info->info.channels == 2) { + else if (MAD_NCHANNELS(&info->frame.header) == 1 && info->info.fmt.channels == 2) { *((float*)info->buffer.out) = sample; info->buffer.readsize -= 4; info->buffer.out += 4; @@ -864,11 +864,11 @@ cmp3_stream_frame (mpgmad_info_t *info) { } } - info->info.samplerate = info->frame.header.samplerate; + info->info.fmt.samplerate = info->frame.header.samplerate; #if 0 // don't switch number of channels on the fly - if (info->info.channels == 0) { - info->info.channels = MAD_NCHANNELS(&info->frame.header); + if (info->info.fmt.channels == 0) { + info->info.fmt.channels = MAD_NCHANNELS(&info->frame.header); } #endif diff --git a/scripts/configure_minimal.sh b/scripts/configure_minimal.sh new file mode 100644 index 00000000..4044a03c --- /dev/null +++ b/scripts/configure_minimal.sh @@ -0,0 +1 @@ +./configure --enable-maintainer-mode --disable-nullout --disable-oss --disable-sid --disable-ffap --disable-vtx --disable-adplug --disable-vorbis --disable-ffmpeg --disable-flac --disable-sndfile --disable-wavpack --disable-cdda --disable-gme --disable-dumb --disable-musepack --disable-wildmidi --disable-tta --disable-dca --disable-aac --disable-mms --disable-shn --disable-ao --disable-supereq --disable-artwork --disable-lfm --disable-vfs-curl --disable-hotkeys --disable-notify --disable-shellexec diff --git a/scripts/quickinstall.sh b/scripts/quickinstall.sh index 39a948ea..28fccb1c 100755 --- a/scripts/quickinstall.sh +++ b/scripts/quickinstall.sh @@ -1,4 +1,5 @@ #!/bin/sh +rm /usr/local/lib/deadbeef/* cp ./deadbeef /usr/local/bin/ cp ./plugins/nullout/.libs/nullout.so /usr/local/lib/deadbeef/ cp ./plugins/cdda/.libs/cdda.so /usr/local/lib/deadbeef/ @@ -29,7 +29,6 @@ #include "playlist.h" #include "common.h" #include "streamer.h" -#include "playback.h" #include "messagepump.h" #include "conf.h" #include "plugins.h" @@ -539,6 +538,7 @@ streamer_song_removed_notify (playItem_t *it) { // that must be called after last sample from str_playing_song was done reading static int streamer_set_current (playItem_t *it) { + DB_output_t *output = plug_get_output (); int err = 0; playItem_t *from, *to; // need to add refs here, because streamer_start_playback can destroy items @@ -551,7 +551,7 @@ streamer_set_current (playItem_t *it) { pl_item_ref (to); } trace ("\033[0;35mstreamer_set_current from %p to %p\033[37;0m\n", from, it); - if (!playing_track || p_isstopped ()) { + if (!playing_track || output->state () == OUTPUT_STATE_STOPPED) { trace ("buffering = on\n"); streamer_buffering = 1; trace ("\033[0;35mstreamer_start_playback[1] from %p to %p\033[37;0m\n", from, it); @@ -633,7 +633,7 @@ streamer_set_current (playItem_t *it) { dec = plug_get_decoder_for_id (it->decoder_id); if (dec) { trace ("\033[0;33minit decoder for %s\033[37;0m\n", it->fname); - fileinfo = dec->open (); + fileinfo = dec->open (0); if (fileinfo && dec->init (fileinfo, DB_PLAYITEM (it)) != 0) { trace ("\033[0;31mfailed to init decoder\033[37;0m\n") dec->free (fileinfo); @@ -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->channels, fileinfo->samplerate); + trace ("bps=%d, channels=%d, samplerate=%d\n", fileinfo->bps, fileinfo->fmt.channels, fileinfo->fmt.samplerate); } // FIXME: that might break streaming at boundaries between 2 different samplerates // streamer_reset (0); // reset SRC @@ -719,12 +719,13 @@ streamer_get_apx_bitrate (void) { void streamer_set_nextsong (int song, int pstate) { + DB_output_t *output = plug_get_output (); trace ("streamer_set_nextsong %d %d\n", song, pstate); streamer_lock (); streamer_abort_files (); nextsong = song; nextsong_pstate = pstate; - if (p_isstopped ()) { + if (output->state () == OUTPUT_STATE_STOPPED) { if (pstate == 1) { // means user initiated this streamer_playlist = plt_get_curr_ptr (); } @@ -748,6 +749,7 @@ static void streamer_start_new_song (void) { trace ("nextsong=%d\n", nextsong); streamer_lock (); + DB_output_t *output = plug_get_output (); int sng = nextsong; int initsng = nextsong; int pstate = nextsong_pstate; @@ -763,7 +765,7 @@ streamer_start_new_song (void) { playItem_t *try = str_get_for_idx (sng); if (!try) { // track is not in playlist trace ("track #%d is not in playlist; stopping playback\n", sng); - p_stop (); + output->stop (); mutex_lock (decodemutex); if (playing_track) { @@ -806,39 +808,39 @@ streamer_start_new_song (void) { try = NULL; badsong = -1; trace ("pstate = %d\n", pstate); - trace ("playback state = %d\n", p_state ()); + trace ("playback state = %d\n", output->state ()); if (pstate == 0) { - p_stop (); + output->stop (); } else if (pstate == 1 || pstate == 3) { last_bitrate = -1; avg_bitrate = -1; - if (p_state () != OUTPUT_STATE_PLAYING) { + if (output->state () != OUTPUT_STATE_PLAYING) { streamer_reset (1); if (fileinfo) { - plug_get_output ()->change_rate (fileinfo->samplerate); + plug_get_output ()->change_rate (fileinfo->fmt.samplerate); } - if (p_play () < 0) { + if (output->play () < 0) { fprintf (stderr, "streamer: failed to start playback; output plugin doesn't work\n"); streamer_set_nextsong (-2, 0); } } } else if (pstate == 2) { - if (p_get_state () == OUTPUT_STATE_STOPPED) { + if (output->state () == OUTPUT_STATE_STOPPED) { last_bitrate = -1; avg_bitrate = -1; streamer_reset (1); if (fileinfo) { - plug_get_output ()->change_rate (fileinfo->samplerate); + plug_get_output ()->change_rate (fileinfo->fmt.samplerate); } - if (p_play () < 0) { + if (output->play () < 0) { fprintf (stderr, "streamer: failed to start playback; output plugin doesn't work\n"); streamer_set_nextsong (-2, 0); return; } } - p_pause (); + output->pause (); } } @@ -851,6 +853,7 @@ streamer_thread (void *ctx) { while (!streaming_terminate) { struct timeval tm1; + DB_output_t *output = plug_get_output (); gettimeofday (&tm1, NULL); if (nextsong >= 0) { // start streaming next song trace ("\033[0;34mnextsong=%d\033[37;0m\n", nextsong); @@ -866,7 +869,7 @@ streamer_thread (void *ctx) { bytes_until_next_song = -1; trace ("nextsong=-2\n"); nextsong = -1; - p_stop (); + output->stop (); if (playing_track) { trace ("sending songfinished to plugins [1]\n"); plug_trigger_event (DB_EV_SONGFINISHED, 0); @@ -886,7 +889,7 @@ streamer_thread (void *ctx) { streamer_unlock (); continue; } - else if (p_isstopped ()) { + else if (output->state () == OUTPUT_STATE_STOPPED) { usleep (50000); continue; } @@ -896,7 +899,7 @@ streamer_thread (void *ctx) { if (!streaming_track) { // means last song was deleted during final drain nextsong = -1; - p_stop (); + output->stop (); streamer_set_current (NULL); streamer_unlock (); continue; @@ -924,9 +927,9 @@ streamer_thread (void *ctx) { if (conf_get_int ("playback.dynsamplerate", 0)) { // don't switch if unchanged - int prevtrack_samplerate = p_get_rate (); - if (prevtrack_samplerate != fileinfo->samplerate) { - int newrate = plug_get_output ()->change_rate (fileinfo->samplerate); + int prevtrack_samplerate = output->fmt.samplerate; + if (prevtrack_samplerate != fileinfo->fmt.samplerate) { + int newrate = output->change_rate (fileinfo->fmt.samplerate); if (newrate != prevtrack_samplerate) { // restart streaming of current track trace ("streamer: output samplerate changed from %d to %d; restarting track\n", prevtrack_samplerate, newrate); @@ -936,7 +939,7 @@ streamer_thread (void *ctx) { DB_decoder_t *dec = NULL; dec = plug_get_decoder_for_id (streaming_track->decoder_id); if (dec) { - fileinfo = dec->open (); + fileinfo = dec->open (0); if (fileinfo && dec->init (fileinfo, DB_PLAYITEM (streaming_track)) < 0) { dec->free (fileinfo); fileinfo = NULL; @@ -950,17 +953,17 @@ streamer_thread (void *ctx) { streamer_buffering = 1; streamer_reset (1); if (fileinfo) { - prevtrack_samplerate = fileinfo->samplerate; + prevtrack_samplerate = fileinfo->fmt.samplerate; } } } // output plugin may stop playback before switching samplerate - if (p_state () != OUTPUT_STATE_PLAYING) { + if (output->state () != OUTPUT_STATE_PLAYING) { if (fileinfo) { - plug_get_output ()->change_rate (fileinfo->samplerate); + plug_get_output ()->change_rate (fileinfo->fmt.samplerate); } - if (p_play () < 0) { + if (output->play () < 0) { fprintf (stderr, "streamer: failed to start playback after samplerate change; output plugin doesn't work\n"); streamer_set_nextsong (-2, 0); streamer_unlock (); @@ -1005,7 +1008,7 @@ streamer_thread (void *ctx) { DB_decoder_t *dec = NULL; dec = plug_get_decoder_for_id (streaming_track->decoder_id); if (dec) { - fileinfo = dec->open (); + fileinfo = dec->open (0); if (fileinfo && dec->init (fileinfo, DB_PLAYITEM (streaming_track)) != 0) { dec->free (fileinfo); fileinfo = NULL; @@ -1048,7 +1051,7 @@ streamer_thread (void *ctx) { } // read ahead at 2x speed of output samplerate, in 4k blocks - int rate = p_get_rate (); + int rate = output->fmt.samplerate; if (!rate) { trace ("str: got 0 output samplerate\n"); usleep(20000); @@ -1187,7 +1190,7 @@ streamer_reset (int full) { // must be called when current song changes by exter src_reset (src); // reset dsp DB_dsp_t **dsp = deadbeef->plug_get_dsp_list (); - //int srate = p_get_rate (); + //int srate = output->fmt.samplerate; for (int i = 0; dsp[i]; i++) { if (dsp[i]->enabled ()) { dsp[i]->reset (); @@ -1359,7 +1362,7 @@ float32_to_int16 (float *in, int16_t *out, int nsamples) { static int streamer_read_data_for_src (int16_t *buffer, int frames) { - int channels = fileinfo->channels; + int channels = fileinfo->fmt.channels; if (channels > 2) { channels = 2; } @@ -1379,7 +1382,7 @@ streamer_read_data_for_src (int16_t *buffer, int frames) { static int streamer_read_data_for_src_float (float *buffer, int frames) { - int channels = fileinfo->channels; + int channels = fileinfo->fmt.channels; if (channels > 2) { channels = 2; } @@ -1410,16 +1413,17 @@ streamer_read_data_for_src_float (float *buffer, int frames) { static int streamer_decode_src_libsamplerate (uint8_t *bytes, int size) { + DB_output_t *output = plug_get_output (); int initsize = size; int16_t *out = (int16_t *)bytes; - int samplerate = fileinfo->samplerate; + int samplerate = fileinfo->fmt.samplerate; if (!samplerate) { return 0; } - float ratio = p_get_rate ()/(float)samplerate; + float ratio = output->fmt.samplerate/(float)samplerate; while (size > 0) { int n_output_frames = size / sizeof (int16_t) / 2; - int n_input_frames = n_output_frames * samplerate / p_get_rate () + 100; + int n_input_frames = n_output_frames * samplerate / output->fmt.samplerate + 100; // read data from decoder if (n_input_frames >= SRC_BUFFER - src_remaining ) { n_input_frames = SRC_BUFFER - src_remaining; @@ -1444,7 +1448,7 @@ streamer_decode_src_libsamplerate (uint8_t *bytes, int size) { srcdata.input_frames = src_remaining; srcdata.output_frames = size/4; srcdata.src_ratio = ratio; -// trace ("SRC from %d to %d\n", samplerate, p_get_rate ()); +// trace ("SRC from %d to %d\n", samplerate, output->fmt.samplerate); srcdata.end_of_input = 0;//(nread == n_input_frames) ? 0 : 1; //if (streamer_buffering) src_lock (); @@ -1486,10 +1490,10 @@ streamer_decode_src (uint8_t *bytes, int size) { int16_t *out = (int16_t *)bytes; DB_decoder_t *decoder = streaming_track->decoder; int samplerate = decoder->info.samplerate; - float ratio = (float)samplerate / p_get_rate (); + float ratio = (float)samplerate / output->fmt.samplerate; while (size > 0) { int n_output_frames = size / sizeof (int16_t) / 2; - int n_input_frames = n_output_frames * samplerate / p_get_rate () + 100; + int n_input_frames = n_output_frames * samplerate / output->fmt.samplerate + 100; // read data from decoder if (n_input_frames > SRC_BUFFER - src_remaining ) { n_input_frames = SRC_BUFFER - src_remaining; @@ -1526,6 +1530,7 @@ streamer_decode_src (uint8_t *bytes, int size) { // returns number of bytes been read static int streamer_read_async (char *bytes, int size) { + DB_output_t *output = plug_get_output (); int initsize = size; for (;;) { int bytesread = 0; @@ -1535,13 +1540,13 @@ streamer_read_async (char *bytes, int size) { mutex_unlock (decodemutex); break; } - if (fileinfo->samplerate != -1) { - int nchannels = fileinfo->channels; + if (fileinfo->fmt.samplerate != -1) { + int nchannels = fileinfo->fmt.channels; if (nchannels > 2) { nchannels = 2; } - int samplerate = fileinfo->samplerate; - if (fileinfo->samplerate == p_get_rate ()) { + int samplerate = fileinfo->fmt.samplerate; + if (fileinfo->fmt.samplerate == output->fmt.samplerate) { // samplerate match if (nchannels == 2) { bytesread = fileinfo->plugin->read_int16 (fileinfo, bytes, size); @@ -1555,11 +1560,11 @@ streamer_read_async (char *bytes, int size) { bytesread *= 2; } } - else if (src_is_valid_ratio (p_get_rate ()/(double)samplerate)) { + else if (src_is_valid_ratio (output->fmt.samplerate/(double)samplerate)) { bytesread = streamer_decode_src_libsamplerate (bytes, size); } else { - fprintf (stderr, "error: invalid ratio! %d / %d (this indicates decoder or streamer bug)\n", p_get_rate (), samplerate); + fprintf (stderr, "error: invalid ratio! %d / %d (this indicates decoder or streamer bug)\n", output->fmt.samplerate, samplerate); fprintf (stderr, "error: file: %s\n", streaming_track ? streaming_track->fname : "(null)"); // immediately start streaming next track bytes_until_next_song = -1; @@ -1569,7 +1574,7 @@ streamer_read_async (char *bytes, int size) { if (bytesread > 0) { // apply dsp DB_dsp_t **dsp = deadbeef->plug_get_dsp_list (); - int srate = p_get_rate (); + int srate = output->fmt.samplerate; for (int i = 0; dsp[i]; i++) { if (dsp[i]->enabled ()) { dsp[i]->process_int16 ((int16_t *)bytes, bytesread/4, 2, 16, srate); @@ -1612,14 +1617,15 @@ streamer_read (char *bytes, int size) { if (!playing_track) { return -1; } + DB_output_t *output = plug_get_output (); streamer_lock (); int sz = min (size, streambuffer_fill); if (sz) { memcpy (bytes, streambuffer, sz); memmove (streambuffer, streambuffer+sz, streambuffer_fill-sz); streambuffer_fill -= sz; - playpos += (float)sz/p_get_rate ()/4.f; - playing_track->playtime += (float)sz/p_get_rate ()/4.f; + playpos += (float)sz/output->fmt.samplerate/4.f; + playing_track->playtime += (float)sz/output->fmt.samplerate/4.f; if (playlist_track) { playing_track->filetype = playlist_track->filetype; } @@ -1721,14 +1727,15 @@ streamer_configchanged (void) { void streamer_play_current_track (void) { playlist_t *plt = plt_get_curr_ptr (); - if (p_ispaused () && playing_track) { + DB_output_t *output = plug_get_output (); + if (output->state () == OUTPUT_STATE_PAUSED && playing_track) { // unpause currently paused track - p_unpause (); + output->unpause (); plug_trigger_event_paused (0); } else if (plt->current_row[PL_MAIN] != -1) { // play currently selected track in current playlist - p_stop (); + output->stop (); // get next song in queue int idx = -1; playItem_t *next = pl_playqueue_getnext (); @@ -1746,7 +1753,7 @@ streamer_play_current_track (void) { } else { // restart currently playing track - p_stop (); + output->stop (); streamer_set_nextsong (0, 1); } } |