diff options
-rw-r--r-- | callbacks.c | 4 | ||||
-rw-r--r-- | palsa.c | 60 | ||||
-rw-r--r-- | playlist.c | 5 | ||||
-rw-r--r-- | streamer.c | 6 | ||||
-rw-r--r-- | streamer.h | 2 |
5 files changed, 64 insertions, 13 deletions
diff --git a/callbacks.c b/callbacks.c index 3418280a..78a7b9c1 100644 --- a/callbacks.c +++ b/callbacks.c @@ -93,7 +93,7 @@ on_playlist_realize (GtkWidget *widget, // setup drag-drop target gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, &entry, 1, GDK_ACTION_COPY | GDK_ACTION_MOVE); gtk_drag_dest_add_uri_targets (widget); - gtk_drag_dest_set_track_motion (widget, TRUE); +// gtk_drag_dest_set_track_motion (widget, TRUE); } @@ -452,7 +452,7 @@ on_playlist_drag_failed (GtkWidget *widget, GtkDragResult arg2, gpointer user_data) { - return FALSE; + return TRUE; } @@ -24,6 +24,8 @@ static int bufsize = 4096*4; static float volume = 1; static int alsa_terminate = 0; static int alsa_rate = 48000; +static int state = 0; // 0 = stopped, 1 = playing, 2 = pause +static uintptr_t mutex; static void palsa_callback (char *stream, int len); @@ -36,6 +38,7 @@ palsa_init (void) { int err; snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; + state = 0; if ((err = snd_pcm_open (&audio, "default", SND_PCM_STREAM_PLAYBACK, 0))) { fprintf (stderr, "could not open audio device (%s)\n", @@ -134,8 +137,10 @@ palsa_init (void) { printf ("AUDIO: Unable to allocate memory for sample buffers.\n"); goto open_error; } + snd_pcm_pause (audio, 1); // put into STOPPED state alsa_terminate = 0; + mutex = mutex_create (); thread_start (palsa_thread, 0); return 0; @@ -152,44 +157,70 @@ open_error: void palsa_free (void) { if (audio) { + mutex_lock (mutex); alsa_terminate = 1; - usleep (1000); snd_pcm_close(audio); audio = NULL; if (samplebuffer) { free (samplebuffer); samplebuffer = NULL; } + mutex_unlock (mutex); + mutex_free (mutex); } } int palsa_play (void) { // start updating thread + int err; + if (state == 0) { +#if 0 + if ((err = snd_pcm_drop (audio)) < 0) { + fprintf (stderr, "cannot drop audio interface(%s)\n", + snd_strerror (err)); + } +#endif + if ((err = snd_pcm_prepare (audio)) < 0) { + fprintf (stderr, "cannot prepare audio interface for use (%s)\n", + snd_strerror (err)); + } + streamer_reset (1); + } + if (state != 1) { + state = 1; + snd_pcm_pause (audio, 0); + } return 0; } int palsa_stop (void) { // set stop state + state = 0; + snd_pcm_pause (audio, 1); return 0; } int palsa_ispaused (void) { // return pause state - return 0; + return (state == 2); } int palsa_pause (void) { // set pause state + state = 2; + snd_pcm_pause (audio, 1); return 0; } int palsa_unpause (void) { // unset pause state + state = 1; + snd_pcm_pause (audio, 0); return 0; } @@ -206,14 +237,24 @@ palsa_get_rate (void) { static void palsa_thread (uintptr_t context) { int err; - while (!alsa_terminate) { + for (;;) { + mutex_lock (mutex); + if (alsa_terminate) { + mutex_unlock (mutex); + break; + } /* wait till the interface is ready for data, or 1 second has elapsed. */ +// if (state != 1) { +// usleep (1000); +// continue; +// } if ((err = snd_pcm_wait (audio, 1000)) < 0) { - fprintf (stderr, "poll failed (%s)\n", strerror (errno)); - break; + mutex_unlock (mutex); + fprintf (stderr, "alsa poll failed (%s)\n", strerror (errno)); + continue; } /* find out how much space is available for playback data */ @@ -221,12 +262,14 @@ palsa_thread (uintptr_t context) { snd_pcm_sframes_t frames_to_deliver; if ((frames_to_deliver = snd_pcm_avail_update (audio)) < 0) { if (frames_to_deliver == -EPIPE) { + mutex_unlock (mutex); fprintf (stderr, "an xrun occured\n"); - break; + continue; } else { + mutex_unlock (mutex); fprintf (stderr, "unknown ALSA avail update return value (%d)\n", frames_to_deliver); - break; + continue; } } @@ -238,8 +281,9 @@ palsa_thread (uintptr_t context) { if ((err = snd_pcm_writei (audio, buf, frames_to_deliver)) < 0) { fprintf (stderr, "write failed (%s)\n", snd_strerror (err)); } + mutex_unlock (mutex); + usleep (0); // let other threads gain some spin (avoid deadlock) } - alsa_terminate = 0; } static void @@ -676,6 +676,8 @@ ps_set_current (playItem_t *it) { int ret = 0; int from = ps_get_idx_of (playlist_current_ptr); int to = ps_get_idx_of (it); +#if 0 + // this produces some kind of bug in the beginning of track if (it == playlist_current_ptr) { if (it && it->codec) { codec_lock (); @@ -684,6 +686,7 @@ ps_set_current (playItem_t *it) { } return ret; } +#endif codec_lock (); if (playlist_current_ptr && playlist_current_ptr->codec) { playlist_current_ptr->codec->free (); @@ -701,7 +704,7 @@ ps_set_current (playItem_t *it) { } } if (playlist_current_ptr) { - streamer_reset (); + streamer_reset (0); } codec_unlock (); messagepump_push (M_SONGCHANGED, 0, from, to); @@ -50,6 +50,7 @@ streamer_thread (uintptr_t ctx) { usleep (3000); } } + p_play (); } streamer_lock (); if (streambuffer_fill < STREAM_BUFFER_SIZE) { @@ -93,8 +94,11 @@ streamer_free (void) { } void -streamer_reset (void) { // must be called when current song changes by external reasons +streamer_reset (int full) { // must be called when current song changes by external reasons codecleft = 0; + if (full) { + streambuffer_fill = 0; + } src_reset (src); } @@ -11,7 +11,7 @@ int streamer_read (char *bytes, int size); void -streamer_reset (void); +streamer_reset (int full); void streamer_lock (void); |