From 7d0f7176f06f933ae2c8d5ca6e7336b70875ffdc Mon Sep 17 00:00:00 2001 From: Alexey Yakovenko Date: Mon, 26 Oct 2009 20:36:16 +0100 Subject: added buffering indication to playing status fixed replaygain scale bug --- gtkplaylist.c | 83 ++++++++++++++++++++++++++++++++++++++++++----- gtkplaylist.h | 9 +++++ main.c | 49 +++++----------------------- pixmaps/Makefile.am | 5 +-- pixmaps/buffering_16.png | Bin 0 -> 228 bytes playlist.c | 8 +++++ streamer.c | 57 +++++++++++++++++++++++--------- 7 files changed, 143 insertions(+), 68 deletions(-) create mode 100644 pixmaps/buffering_16.png diff --git a/gtkplaylist.c b/gtkplaylist.c index 658c7bd2..a4f4e125 100644 --- a/gtkplaylist.c +++ b/gtkplaylist.c @@ -50,6 +50,10 @@ //#define trace(...) { fprintf(stderr, __VA_ARGS__); } #define trace(fmt,...) +extern GtkWidget *mainwin; +extern GtkStatusIcon *trayicon; +extern gtkplaylist_t main_playlist; + // orange on dark color scheme float colo_dark_orange[COLO_COUNT][3] = { { 0x7f/255.f, 0x7f/255.f, 0x7f/255.f }, // cursor @@ -91,6 +95,7 @@ int rowheight = -1; static uintptr_t play16_pixbuf; static uintptr_t pause16_pixbuf; +static uintptr_t buffering16_pixbuf; static GdkCursor* cursor_sz; static GdkCursor* cursor_drag; @@ -167,7 +172,6 @@ colhdr_anim_swap (gtkplaylist_t *pl, int c1, int c2, int x1, int x2) { colhdr_anim.anim_active = 1; timeline_stop (colhdr_anim.timeline, 0); timeline_init (colhdr_anim.timeline, COLHDR_ANIM_TIME, 100, colhdr_anim_cb, &colhdr_anim); - printf ("timeline_start\n"); timeline_start (colhdr_anim.timeline); } @@ -178,6 +182,7 @@ gtkpl_init (void) { //memcpy (colo_current, colo_dark_orange, sizeof (colo_current)); play16_pixbuf = draw_load_pixbuf ("play_16.png"); pause16_pixbuf = draw_load_pixbuf ("pause_16.png"); + buffering16_pixbuf = draw_load_pixbuf ("buffering_16.png"); rowheight = draw_get_font_size () + 12; memcpy (colo_current, colo_white_blue, sizeof (colo_current)); } @@ -330,10 +335,6 @@ gtkpl_draw_pl_row (gtkplaylist_t *ps, int row, playItem_t *it) { } int width, height; draw_get_canvas_size ((uintptr_t)ps->backbuf, &width, &height); -// if (it == playlist_current_ptr && ps->colwidths[0] > 0 && !p_isstopped ()) { -// uintptr_t pixbuf = p_ispaused () ? pause16_pixbuf : play16_pixbuf; -// draw_pixbuf ((uintptr_t)ps->backbuf, pixbuf, ps->colwidths[0]/2-8-ps->hscrollpos, (row - ps->scrollpos) * rowheight + rowheight/2 - 8, 0, 0, 16, 16); -// } if (it && ((it->selected && ps->multisel) || (row == ps->row && !ps->multisel))) { if (row % 2) { theme_set_bg_color (COLO_PLAYLIST_SEL_EVEN); @@ -386,8 +387,19 @@ gtkpl_draw_pl_row (gtkplaylist_t *ps, int row, playItem_t *it) { int x = -ps->hscrollpos; gtkpl_column_t *c; for (c = ps->columns; c; c = c->next) { - if (it == playlist_current_ptr && c->id == DB_COLUMN_PLAYING && !p_isstopped ()) { - uintptr_t pixbuf = p_ispaused () ? pause16_pixbuf : play16_pixbuf; + if (it == playlist_current_ptr && c->id == DB_COLUMN_PLAYING/* && !p_isstopped ()*/) { + int paused = p_ispaused (); + int buffering = !streamer_ok_to_read (-1); + uintptr_t pixbuf; + if (paused) { + pixbuf = pause16_pixbuf; + } + else if (!buffering) { + pixbuf = play16_pixbuf; + } + else { + pixbuf = buffering16_pixbuf; + } draw_pixbuf ((uintptr_t)ps->backbuf, pixbuf, x + c->width/2 - 8 - ps->hscrollpos, (row - ps->scrollpos) * rowheight + rowheight/2 - 8, 0, 0, 16, 16); } else { @@ -1055,7 +1067,6 @@ gtkpl_handle_drag_drop (gtkplaylist_t *ps, int drop_y, uint32_t *d, int length) int idx = 0; playItem_t *next = NULL; for (playItem_t *it = playlist_head[ps->iterator]; it && processed < length; it = next, idx++) { - // printf ("idx: %d\n", d[i]); next = it->next[ps->iterator]; if (idx == d[processed]) { if (it->prev[ps->iterator]) { @@ -1439,7 +1450,6 @@ on_header_motion_notify_event (GtkWidget *widget, if (event->time - last_header_motion_ev < 50 || prev_header_x == event->x) { return FALSE; } - //printf ("%f\n", event->time - last_header_motion_ev); last_header_motion_ev = event->time; prev_header_x = event->x; gdk_window_set_cursor (widget->window, cursor_sz); @@ -1864,3 +1874,58 @@ gtkpl_column_rewrite_config (gtkplaylist_t *pl) { conf_set_str (key, value); } } + +void +set_tray_tooltip (const char *text) { +#if (GTK_MINOR_VERSION < 16) + gtk_status_icon_set_tooltip (trayicon, text); +#else + gtk_status_icon_set_tooltip_text (trayicon, text); +#endif +} + +void +gtkpl_current_track_changed (playItem_t *it) { + char str[600]; + char dname[512]; + pl_format_item_display_name (it, dname, 512); + snprintf (str, 600, "DeaDBeeF - %s", dname); + gtk_window_set_title (GTK_WINDOW (mainwin), str); + set_tray_tooltip (str); +} + +struct songchange_t { + int from, to; +}; + +static gboolean +gtkpl_songchanged_callback (void *data) { + struct songchange_t *sc = (struct songchange_t *)data; + int from = sc->from; + int to = sc->to; + free (sc); + // update window title + if (from >= 0 || to >= 0) { + if (to >= 0) { + playItem_t *it = pl_get_for_idx (to); + if (it) { // it might have been deleted after event was sent + gtkpl_current_track_changed (it); + } + } + else { + gtk_window_set_title (GTK_WINDOW (mainwin), "DeaDBeeF"); + set_tray_tooltip ("DeaDBeeF"); + } + } + // update playlist view + gtkpl_songchanged (&main_playlist, from, to); + return FALSE; +} + +void +gtkpl_songchanged_wrapper (int from, int to) { + struct songchange_t *sc = malloc (sizeof (struct songchange_t)); + sc->from = from; + sc->to = to; + g_idle_add (gtkpl_songchanged_callback, sc); +} diff --git a/gtkplaylist.h b/gtkplaylist.h index b060947e..2e827839 100644 --- a/gtkplaylist.h +++ b/gtkplaylist.h @@ -249,4 +249,13 @@ gtkpl_column_rewrite_config (gtkplaylist_t *pl); void gtkpl_expose_header (gtkplaylist_t *ps, int x, int y, int w, int h); +void +set_tray_tooltip (const char *text); + +void +gtkpl_songchanged_wrapper (int from, int to); + +void +gtkpl_current_track_changed (playItem_t *it); + #endif // __GTKPLAYLIST_H diff --git a/main.c b/main.c index 89577ffd..5bf14332 100644 --- a/main.c +++ b/main.c @@ -66,15 +66,6 @@ GtkWidget *searchwin; GtkStatusIcon *trayicon; GtkWidget *traymenu; -void -set_tray_tooltip (const char *text) { -#if (GTK_MINOR_VERSION < 16) - gtk_status_icon_set_tooltip (trayicon, text); -#else - gtk_status_icon_set_tooltip_text (trayicon, text); -#endif -} - // playlist configuration structures gtkplaylist_t main_playlist; gtkplaylist_t search_playlist; @@ -109,7 +100,7 @@ update_songinfo (void) { songpos = 0; } else if (str_playing_song.decoder) { - codec_lock (); +// codec_lock (); DB_decoder_t *c = str_playing_song.decoder; float playpos = streamer_get_playpos (); int minpos = playpos / 60; @@ -121,7 +112,7 @@ update_songinfo (void) { int samplerate = c->info.samplerate; int bitspersample = c->info.bps; songpos = playpos; - codec_unlock (); +// codec_unlock (); char t[100]; if (str_playing_song._duration >= 0) { @@ -339,16 +330,6 @@ server_update (void) { return 0; } -void -current_track_changed (playItem_t *it) { - char str[600]; - char dname[512]; - pl_format_item_display_name (it, dname, 512); - snprintf (str, 600, "DeaDBeeF - %s", dname); - gtk_window_set_title (GTK_WINDOW (mainwin), str); - set_tray_tooltip (str); -} - void player_thread (uintptr_t ctx) { prctl (PR_SET_NAME, "deadbeef-player", 0, 0, 0, 0); @@ -388,26 +369,12 @@ player_thread (uintptr_t ctx) { GDK_THREADS_LEAVE(); return; case M_SONGCHANGED: - GDK_THREADS_ENTER(); - // update window title - int from = p1; - int to = p2; - if (from >= 0 || to >= 0) { - if (to >= 0) { - playItem_t *it = pl_get_for_idx (to); - if (it) { // it might have been deleted after event was sent - current_track_changed (it); - } - } - else { - gtk_window_set_title (GTK_WINDOW (mainwin), "DeaDBeeF"); - set_tray_tooltip ("DeaDBeeF"); - } + { + int from = p1; + int to = p2; + gtkpl_songchanged_wrapper (from, to); + plug_trigger_event (DB_EV_SONGCHANGED, 0); } - // update playlist view - gtkpl_songchanged (&main_playlist, p1, p2); - GDK_THREADS_LEAVE(); - plug_trigger_event (DB_EV_SONGCHANGED, 0); break; case M_PLAYSONG: gtkpl_playsong (&main_playlist); @@ -424,7 +391,7 @@ player_thread (uintptr_t ctx) { GDK_THREADS_ENTER(); gtkpl_redraw_pl_row (&main_playlist, p1, it); if (it == playlist_current_ptr) { - current_track_changed (it); + gtkpl_current_track_changed (it); } GDK_THREADS_LEAVE(); } diff --git a/pixmaps/Makefile.am b/pixmaps/Makefile.am index 86bc3ef0..fd8452cd 100644 --- a/pixmaps/Makefile.am +++ b/pixmaps/Makefile.am @@ -1,10 +1,11 @@ pixmapsdir = $(pkgdatadir)/pixmaps pixmaps_DATA =\ -next_24.png\ pause_16.png\ -pause_24.png\ play_16.png\ +buffering_16.png\ +next_24.png\ +pause_24.png\ play_24.png\ prev_24.png\ random_24.png\ diff --git a/pixmaps/buffering_16.png b/pixmaps/buffering_16.png new file mode 100644 index 00000000..bf5b8887 Binary files /dev/null and b/pixmaps/buffering_16.png differ diff --git a/playlist.c b/playlist.c index e437adc2..13a1c3f8 100644 --- a/playlist.c +++ b/playlist.c @@ -648,6 +648,8 @@ playItem_t * pl_item_alloc (void) { playItem_t *it = malloc (sizeof (playItem_t)); memset (it, 0, sizeof (playItem_t)); + it->replaygain_album_peak = 1; + it->replaygain_track_peak = 1; return it; } @@ -1202,12 +1204,18 @@ pl_load (const char *fname) { if (fread (&it->replaygain_album_peak, 1, 4, fp) != 4) { goto load_fail; } + if (it->replaygain_album_peak == 0) { + it->replaygain_album_peak = 1; + } if (fread (&it->replaygain_track_gain, 1, 4, fp) != 4) { goto load_fail; } if (fread (&it->replaygain_track_peak, 1, 4, fp) != 4) { goto load_fail; } + if (it->replaygain_track_peak == 0) { + it->replaygain_track_peak = 1; + } // printf ("loading file %s\n", it->fname); int16_t nm = 0; if (fread (&nm, 1, 2, fp) != 2) { diff --git a/streamer.c b/streamer.c index 70abb550..ef8618e5 100644 --- a/streamer.c +++ b/streamer.c @@ -85,6 +85,8 @@ playItem_t str_streaming_song; static playItem_t *orig_playing_song; static playItem_t *orig_streaming_song; +static int streamer_buffering; + // playlist must call that whenever item was removed void streamer_song_removed_notify (playItem_t *it) { @@ -105,19 +107,24 @@ 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) { + int from, to; + streamer_buffering = 1; + from = orig_playing_song ? pl_get_idx_of (orig_playing_song) : -1; + to = it ? pl_get_idx_of (it) : -1; + if (!orig_playing_song || p_isstopped ()) { + playlist_current_ptr = it; + } + trace ("from=%d, to=%d\n", from, to); + trace ("sending songchanged\n"); + messagepump_push (M_SONGCHANGED, 0, from, to); trace ("streamer_set_current %p, buns=%d\n", it); -// if (str_streaming_song.decoder) { -// trace ("sending songfinished to plugins [1]\n"); -// plug_trigger_event (DB_EV_SONGFINISHED); -// str_streaming_song.decoder->free (); -// } if(str_streaming_song.decoder) { str_streaming_song.decoder->free (); pl_item_free (&str_streaming_song); } orig_streaming_song = it; if (!it) { - return 0; + goto success; } if (!it->decoder && it->filetype && !strcmp (it->filetype, "content")) { // try to get content-type @@ -173,6 +180,8 @@ streamer_set_current (playItem_t *it) { if (bytes_until_next_song == -1) { bytes_until_next_song = 0; } +success: + messagepump_push (M_TRACKCHANGED, 0, to, 0); return 0; } @@ -242,7 +251,6 @@ streamer_thread (uintptr_t ctx) { badsong = sng; } // try jump to next song - playlist_current_ptr = try; pl_nextsong (0); usleep (50000); continue; @@ -266,7 +274,7 @@ streamer_thread (uintptr_t ctx) { trace ("sending songfinished to plugins [1]\n"); plug_trigger_event (DB_EV_SONGFINISHED, 0); } - messagepump_push (M_SONGCHANGED, 0, pl_get_idx_of (orig_playing_song), -1); +// messagepump_push (M_SONGCHANGED, 0, pl_get_idx_of (orig_playing_song), -1); streamer_set_current (NULL); pl_item_free (&str_playing_song); orig_playing_song = NULL; @@ -282,11 +290,16 @@ streamer_thread (uintptr_t ctx) { // means last song was deleted during final drain nextsong = -1; p_stop (); - messagepump_push (M_SONGCHANGED, 0, pl_get_idx_of (playlist_current_ptr), -1); +// messagepump_push (M_SONGCHANGED, 0, pl_get_idx_of (playlist_current_ptr), -1); streamer_set_current (NULL); continue; } trace ("bytes_until_next_song=0, starting playback of new song\n"); + int from = orig_playing_song ? pl_get_idx_of (orig_playing_song) : -1; + int to = orig_streaming_song ? pl_get_idx_of (orig_streaming_song) : -1; + trace ("from=%d, to=%d\n", from, to); + trace ("sending songchanged\n"); + messagepump_push (M_SONGCHANGED, 0, from, to); bytes_until_next_song = -1; // plugin will get pointer to str_playing_song if (str_playing_song.decoder) { @@ -297,9 +310,6 @@ streamer_thread (uintptr_t ctx) { pl_item_free (&str_playing_song); // copy streaming into playing pl_item_copy (&str_playing_song, &str_streaming_song); - int from = orig_playing_song ? pl_get_idx_of (orig_playing_song) : -1; - int to = orig_streaming_song ? pl_get_idx_of (orig_streaming_song) : -1; - trace ("from=%d, to=%d\n", from, to); orig_playing_song = orig_streaming_song; if (orig_playing_song) { orig_playing_song->played = 1; @@ -308,8 +318,6 @@ streamer_thread (uintptr_t ctx) { } playlist_current_ptr = orig_playing_song; // that is needed for playlist drawing - trace ("sending songchanged\n"); - messagepump_push (M_SONGCHANGED, 0, from, to); // plugin will get pointer to new str_playing_song trace ("sending songstarted to plugins\n"); plug_trigger_event (DB_EV_SONGSTARTED, 0); @@ -338,6 +346,11 @@ streamer_thread (uintptr_t ctx) { bytes_until_next_song = -1; } + streamer_buffering = 1; + int trk = pl_get_idx_of (orig_streaming_song); + if (trk != -1) { + messagepump_push (M_TRACKCHANGED, 0, trk, 0); + } streamer_lock (); streambuffer_fill = 0; streambuffer_pos = 0; @@ -780,10 +793,22 @@ streamer_get_fill (void) { int streamer_ok_to_read (int len) { - if (bytes_until_next_song > 0) { + if (len >= 0 && (bytes_until_next_song > 0 || streambuffer_fill >= (len*2))) { + if (streamer_buffering) { + streamer_buffering = 0; + if (orig_streaming_song) { + int trk = pl_get_idx_of (orig_streaming_song); + if (trk != -1) { + messagepump_push (M_TRACKCHANGED, 0, trk, 0); + } + } + } return 1; } - return streambuffer_fill >= (len*2); + else { + return 1-streamer_buffering; + } + return 0; } int -- cgit v1.2.3