diff options
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | playlist.c | 50 | ||||
-rw-r--r-- | plugins.c | 3 | ||||
-rw-r--r-- | plugins/gtkui/gtkplaylist.c | 112 | ||||
-rw-r--r-- | plugins/gtkui/gtkui.h | 10 | ||||
-rw-r--r-- | plugins/gtkui/search.c | 12 | ||||
-rw-r--r-- | plugins/mpgmad/mpgmad.c | 4 | ||||
-rw-r--r-- | streamer.c | 31 |
8 files changed, 176 insertions, 49 deletions
@@ -640,9 +640,10 @@ main (int argc, char *argv[]) { plug_unload_all (); // at this point we can simply do exit(0), but let's clean up for debugging + + plt_free (); // plt_free may access conf_* conf_free (); messagepump_free (); - plt_free (); plug_free_decoder_ids (); pl_free (); sigterm_handled = 1; @@ -44,6 +44,9 @@ #pragma GCC optimize("O0") +#define DISABLE_LOCKING 1 + +// file format revision history // 1.0->1.1 changelog: // added sample-accurate seek positions for sub-tracks #define PLAYLIST_MAJOR_VER 1 @@ -65,8 +68,10 @@ static playlist_t *playlists_head = NULL; static playlist_t *playlist = NULL; // current playlist static int plt_loading = 0; // disable sending event about playlist switch, config regen, etc +#if !DISABLE_LOCKING static uintptr_t mutex; static uintptr_t mutex_plt; +#endif #define LOCK {pl_lock();} #define UNLOCK {pl_unlock();} @@ -79,12 +84,15 @@ static uintptr_t mutex_plt; int pl_init (void) { +#if !DISABLE_LOCKING mutex = mutex_create_recursive (); mutex_plt = mutex_create_recursive (); +#endif } void pl_free (void) { +#if !DISABLE_LOCKING if (mutex) { mutex_free (mutex); mutex = 0; @@ -93,26 +101,35 @@ pl_free (void) { mutex_free (mutex_plt); mutex_plt = 0; } +#endif } void plt_lock (void) { +#if !DISABLE_LOCKING mutex_lock (mutex_plt); +#endif } void plt_unlock (void) { +#if !DISABLE_LOCKING mutex_unlock (mutex_plt); +#endif } void pl_lock (void) { +#if !DISABLE_LOCKING mutex_lock (mutex); +#endif } void pl_unlock (void) { +#if !DISABLE_LOCKING mutex_unlock (mutex); +#endif } void @@ -328,11 +345,6 @@ plt_set_title (int plt, const char *title) { return -1; } -//playlist_t * -//plt_get_curr_ptr (void) { -// return playlist; -//} - void plt_free (void) { PLT_LOCK; @@ -1263,6 +1275,7 @@ void pl_item_ref (playItem_t *it) { LOCK; it->_refc++; + printf ("+it %p: refc=%d: %s\n", it, it->_refc, it->fname); UNLOCK; } @@ -1288,6 +1301,7 @@ void pl_item_unref (playItem_t *it) { LOCK; it->_refc--; + printf ("-it %p: refc=%d: %s\n", it, it->_refc, it->fname); if (it->_refc < 0) { fprintf (stderr, "\033[0;31mplaylist: bad refcount on item %p\033[37;0m\n", it); } @@ -1773,6 +1787,7 @@ pl_load (const char *fname) { } pl_insert_item (playlist->tail[PL_MAIN], it); pl_item_unref (it); + trace ("last playlist item refc: %d\n", it->_refc); it = NULL; } GLOBAL_UNLOCK; @@ -2261,22 +2276,38 @@ pl_is_selected (playItem_t *it) { playItem_t * pl_get_first (int iter) { - return playlist->head[iter]; + playItem_t *p = playlist->head[iter]; + if (p) { + pl_item_ref (p); + } + return p; } playItem_t * pl_get_last (int iter) { - return playlist->tail[iter]; + playItem_t *p = playlist->tail[iter]; + if (p) { + pl_item_ref (p); + } + return p; } playItem_t * pl_get_next (playItem_t *it, int iter) { - return it ? it->next[iter] : NULL; + playItem_t *next = it ? it->next[iter] : NULL; + if (next) { + pl_item_ref (next); + } + return next; } playItem_t * pl_get_prev (playItem_t *it, int iter) { - return it ? it->prev[iter] : NULL; + playItem_t *prev = it ? it->prev[iter] : NULL; + if (prev) { + pl_item_ref (prev); + } + return prev; } int @@ -2477,6 +2508,7 @@ pl_playqueue_getnext (void) { LOCK; if (playqueue_count > 0) { playItem_t *val = playqueue[0]; + pl_item_ref (val); UNLOCK; return val; } @@ -426,6 +426,9 @@ plug_trigger_event_trackinfochanged (int trk) { event.index = trk; event.track = DB_PLAYITEM (pl_get_for_idx (trk)); plug_event_call (DB_EVENT (&event)); + if (event.track) { + pl_item_unref ((playItem_t *)event.track); + } } void diff --git a/plugins/gtkui/gtkplaylist.c b/plugins/gtkui/gtkplaylist.c index 2c423e11..7d9f5980 100644 --- a/plugins/gtkui/gtkplaylist.c +++ b/plugins/gtkui/gtkplaylist.c @@ -48,14 +48,6 @@ #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) -#define PL_HEAD(iter) (deadbeef->pl_get_first(iter)) -#define PL_TAIL(iter) (deadbeef->pl_get_last(iter)) -#define PL_NEXT(it, iter) (deadbeef->pl_get_next(it, iter)) -#define PL_PREV(it, iter) (deadbeef->pl_get_prev(it, iter)) -#define SELECTED(it) (deadbeef->pl_is_selected(it)) -#define SELECT(it, sel) (deadbeef->pl_set_selected(it,sel)) -#define VSELECT(it, sel) {deadbeef->pl_set_selected(it,sel);gtk_pl_redraw_item_everywhere (it);} - extern DB_functions_t *deadbeef; // defined in gtkui.c #define trace(...) { fprintf(stderr, __VA_ARGS__); } @@ -435,12 +427,17 @@ gtkpl_draw_playlist (gtkplaylist_t *ps, int x, int y, int w, int h) { // draw background DB_playItem_t *it = deadbeef->pl_get_for_idx_and_iter (ps->scrollpos, ps->iterator); DB_playItem_t *it_copy = it; + if (it_copy) { + REF (it_copy); + } for (row = row1; row < row2_full; row++) { gtkpl_draw_pl_row_back (ps, row, it); - if (it) { + if (it) { + UNREF (it); it = PL_NEXT (it, ps->iterator); } } + UNREF (it); it = it_copy; int idx = 0; for (row = row1; row < row2; row++, idx++) { @@ -448,8 +445,11 @@ gtkpl_draw_playlist (gtkplaylist_t *ps, int x, int y, int w, int h) { break; } gtkpl_draw_pl_row (ps, row, it); - it = PL_NEXT (it, ps->iterator); + DB_playItem_t *next = PL_NEXT (it, ps->iterator); + UNREF (it); + it = next; } + UNREF (it); draw_end (); } @@ -501,7 +501,7 @@ void gtkpl_select_single (gtkplaylist_t *ps, int sel) { int idx=0; DB_playItem_t *it = PL_HEAD (ps->iterator); - for (; it; it = PL_NEXT (it, ps->iterator), idx++) { + for (; it; idx++) { if (idx == sel) { if (!SELECTED (it)) { VSELECT (it, 1); @@ -510,7 +510,11 @@ gtkpl_select_single (gtkplaylist_t *ps, int sel) { else if (SELECTED (it)) { VSELECT (it, 0); } + DB_playItem_t *next = PL_NEXT (it, ps->iterator); + UNREF (it); + it = next; } + UNREF (it); } // {{{ expected behaviour for mouse1 without modifiers: @@ -566,12 +570,15 @@ gtkpl_mouse1_pressed (gtkplaylist_t *ps, int state, int ex, int ey, double time) if (prev != r) { deadbeef->pl_set_cursor (ps->iterator, r); if (prev != -1) { - gtkpl_redraw_pl_row (&main_playlist, prev, deadbeef->pl_get_for_idx (prev)); + DB_playItem_t *prev_it = deadbeef->pl_get_for_idx (prev); + gtkpl_redraw_pl_row (&main_playlist, prev, prev_it); + UNREF (prev_it); } if (r != -1) { gtkpl_redraw_pl_row (&main_playlist, r, it); } } + UNREF (it); deadbeef->sendmessage (M_PLAYSONGNUM, 0, r, 0); return; } @@ -606,11 +613,16 @@ gtkpl_mouse1_pressed (gtkplaylist_t *ps, int state, int ex, int ey, double time) } else { dragwait = 1; - gtkpl_redraw_pl_row (ps, prev, gtkpl_get_for_idx (ps, prev)); + DB_playItem_t *item = gtkpl_get_for_idx (ps, prev); + gtkpl_redraw_pl_row (ps, prev, item); + UNREF (item); if (deadbeef->pl_get_cursor (ps->iterator) != prev) { - gtkpl_redraw_pl_row (ps, deadbeef->pl_get_cursor (ps->iterator), gtkpl_get_for_idx (ps, deadbeef->pl_get_cursor (ps->iterator))); + DB_playItem_t *item = gtkpl_get_for_idx (ps, deadbeef->pl_get_cursor (ps->iterator)); + gtkpl_redraw_pl_row (ps, deadbeef->pl_get_cursor (ps->iterator), item); + UNREF (item); } } + UNREF (it); } else if (state & GDK_CONTROL_MASK) { // toggle selection @@ -618,6 +630,7 @@ gtkpl_mouse1_pressed (gtkplaylist_t *ps, int state, int ex, int ey, double time) DB_playItem_t *it = gtkpl_get_for_idx (ps, y); if (it) { VSELECT (it, 1 - SELECTED (it)); + UNREF (it); } } } @@ -626,7 +639,7 @@ gtkpl_mouse1_pressed (gtkplaylist_t *ps, int state, int ex, int ey, double time) int start = min (prev, deadbeef->pl_get_cursor (ps->iterator)); int end = max (prev, deadbeef->pl_get_cursor (ps->iterator)); int idx = 0; - for (DB_playItem_t *it = PL_HEAD (ps->iterator); it; it = PL_NEXT (it, ps->iterator), idx++) { + for (DB_playItem_t *it = PL_HEAD (ps->iterator); it; idx++) { if (idx >= start && idx <= end) { if (!SELECTED (it)) { VSELECT (it, 1); @@ -637,13 +650,19 @@ gtkpl_mouse1_pressed (gtkplaylist_t *ps, int state, int ex, int ey, double time) VSELECT (it, 0); } } + DB_playItem_t *next = PL_NEXT (it, ps->iterator); + UNREF (it); } } if (deadbeef->pl_get_cursor (ps->iterator) != -1 && sel == -1) { - gtkpl_redraw_pl_row (ps, deadbeef->pl_get_cursor (ps->iterator), gtkpl_get_for_idx (ps, deadbeef->pl_get_cursor (ps->iterator))); + DB_playItem_t *it = gtkpl_get_for_idx (ps, deadbeef->pl_get_cursor (ps->iterator)); + gtkpl_redraw_pl_row (ps, deadbeef->pl_get_cursor (ps->iterator), it); + UNREF (it); } if (prev != -1 && prev != deadbeef->pl_get_cursor (ps->iterator)) { - gtkpl_redraw_pl_row (ps, prev, gtkpl_get_for_idx (ps, prev)); + DB_playItem_t *it = gtkpl_get_for_idx (ps, prev); + gtkpl_redraw_pl_row (ps, prev, it); + UNREF (it); } } @@ -764,7 +783,8 @@ gtkpl_mousemove (gtkplaylist_t *ps, GdkEventMotion *event) { int start = min (y, shift_sel_anchor); int end = max (y, shift_sel_anchor); int idx=0; - for (DB_playItem_t *it = PL_HEAD(ps->iterator); it; it = PL_NEXT(it, ps->iterator), idx++) { + DB_playItem_t *it; + for (it = PL_HEAD(ps->iterator); it; idx++) { if (idx >= start && idx <= end) { if (!SELECTED (it)) { VSELECT (it, 1); @@ -773,7 +793,11 @@ gtkpl_mousemove (gtkplaylist_t *ps, GdkEventMotion *event) { else if (SELECTED (it)) { VSELECT (it, 0); } + DB_playItem_t *next = PL_NEXT(it, ps->iterator); + UNREF (it); + it = next; } + UNREF (it); } if (event->y < 10) { @@ -844,7 +868,9 @@ gtkpl_scroll (gtkplaylist_t *ps, int newscroll) { int start = ps->nvisiblerows-d-1; start = max (0, ps->nvisiblerows-d-1); for (i = start; i <= ps->nvisiblerows; i++) { - gtkpl_redraw_pl_row_novis (ps, i+ps->scrollpos, gtkpl_get_for_idx (ps, i+ps->scrollpos)); + DB_playItem_t *it = gtkpl_get_for_idx (ps, i+ps->scrollpos); + gtkpl_redraw_pl_row_novis (ps, i+ps->scrollpos, it); + UNREF (it); } } else { @@ -852,7 +878,9 @@ gtkpl_scroll (gtkplaylist_t *ps, int newscroll) { ps->scrollpos = newscroll; int i; for (i = 0; i <= d+1; i++) { - gtkpl_redraw_pl_row_novis (ps, i+ps->scrollpos, gtkpl_get_for_idx (ps, i+ps->scrollpos)); + DB_playItem_t *it = gtkpl_get_for_idx (ps, i+ps->scrollpos); + gtkpl_redraw_pl_row_novis (ps, i+ps->scrollpos, it); + UNREF (it); } } } @@ -890,10 +918,14 @@ gtkpl_songchanged (gtkplaylist_t *ps, int from, int to) { } if (from >= 0) { - gtkpl_redraw_pl_row (ps, from, gtkpl_get_for_idx (ps, from)); + DB_playItem_t *it = gtkpl_get_for_idx (ps, from); + gtkpl_redraw_pl_row (ps, from, it); + UNREF (it); } if (to >= 0) { - gtkpl_redraw_pl_row (ps, to, gtkpl_get_for_idx (ps, to)); + DB_playItem_t *it = gtkpl_get_for_idx (ps, to); + gtkpl_redraw_pl_row (ps, to, it); + UNREF (it); } } @@ -983,7 +1015,8 @@ gtkpl_keypress (gtkplaylist_t *ps, int keyval, int state) { int start = min (cursor, shift_sel_anchor); int end = max (cursor, shift_sel_anchor); int idx=0; - for (DB_playItem_t *it = PL_HEAD (ps->iterator); it; it = PL_NEXT(it,ps->iterator), idx++) { + DB_playItem_t *it; + for (it = PL_HEAD (ps->iterator); it; idx++) { if (idx >= start && idx <= end) { VSELECT (it, 1); } @@ -991,7 +1024,11 @@ gtkpl_keypress (gtkplaylist_t *ps, int keyval, int state) { { VSELECT (it, 0); } + DB_playItem_t *next = PL_NEXT(it,ps->iterator); + UNREF (it); + it = next; } + UNREF (it); } } else { @@ -1144,6 +1181,8 @@ gtkpl_add_fm_dropped_files (gtkplaylist_t *ps, char *ptr, int length, int drop_y DB_playItem_t *after = NULL; if (drop_before) { after = PL_PREV (drop_before, ps->iterator); + UNREF (drop_before); + drop_before = NULL; } else { after = PL_TAIL (ps->iterator); @@ -1165,6 +1204,9 @@ gtkpl_add_fm_dropped_files (gtkplaylist_t *ps, char *ptr, int length, int drop_y inserted = deadbeef->pl_insert_file (after, fname, &abort, gtkpl_add_file_info_cb, NULL); } if (inserted) { + if (after) { + UNREF (after); + } after = inserted; } } @@ -1176,6 +1218,9 @@ gtkpl_add_fm_dropped_files (gtkplaylist_t *ps, char *ptr, int length, int drop_y } free (ptr); + if (after) { + UNREF (after); + } g_idle_add (progress_hide_idle, NULL); } @@ -1623,12 +1668,15 @@ gtkpl_get_idx_of (gtkplaylist_t *ps, DB_playItem_t *it) { DB_playItem_t *c = PL_HEAD(ps->iterator); int idx = 0; while (c && c != it) { - c = PL_NEXT(c, ps->iterator);; + DB_playItem_t *next = PL_NEXT(c, ps->iterator); + UNREF (c); + c = next; idx++; } if (!c) { return -1; } + UNREF (c); return idx; } @@ -1636,9 +1684,12 @@ DB_playItem_t * gtkpl_get_for_idx (gtkplaylist_t *ps, int idx) { DB_playItem_t *it = PL_HEAD(ps->iterator); while (idx--) { - if (!it) + if (!it) { return NULL; - it = PL_NEXT(it, ps->iterator); + } + DB_playItem_t *next = PL_NEXT(it, ps->iterator); + UNREF (it); + it = next; } return it; } @@ -1869,6 +1920,7 @@ update_win_title_idle (gpointer data) { notify_notification_show (notification, NULL); } } + UNREF (track); } } #endif @@ -1879,6 +1931,7 @@ update_win_title_idle (gpointer data) { DB_playItem_t *it = deadbeef->pl_get_for_idx (to); if (it) { // it might have been deleted after event was sent gtkpl_current_track_changed (it); + UNREF (it); } } else { @@ -1909,9 +1962,12 @@ redraw_queued_tracks (gtkplaylist_t *pl) { if (deadbeef->pl_playqueue_test (it) != -1) { gtkpl_redraw_pl_row (pl, i, it); } - it = PL_NEXT (it, pl->iterator); + DB_playItem_t *next = PL_NEXT (it, pl->iterator); + UNREF (it); + it = next; i++; } + UNREF (it); } static gboolean @@ -1970,10 +2026,12 @@ gtkpl_set_cursor_cb (gpointer data) { if (sc->prev >= minvis && sc->prev <= maxvis) { it = deadbeef->pl_get_for_idx_and_iter (sc->prev, sc->iter); gtkpl_redraw_pl_row (sc->pl, sc->prev, it); + UNREF (it); } if (sc->cursor >= minvis && sc->cursor <= maxvis) { it = deadbeef->pl_get_for_idx_and_iter (sc->cursor, sc->iter); gtkpl_redraw_pl_row (sc->pl, sc->cursor, it); + UNREF (it); } int newscroll = sc->pl->scrollpos; diff --git a/plugins/gtkui/gtkui.h b/plugins/gtkui/gtkui.h index 2031b502..3217ab5c 100644 --- a/plugins/gtkui/gtkui.h +++ b/plugins/gtkui/gtkui.h @@ -19,6 +19,16 @@ #ifndef __GTKUI_H #define __GTKUI_H +#define PL_HEAD(iter) (deadbeef->pl_get_first(iter)) +#define PL_TAIL(iter) (deadbeef->pl_get_last(iter)) +#define PL_NEXT(it, iter) (deadbeef->pl_get_next(it, iter)) +#define PL_PREV(it, iter) (deadbeef->pl_get_prev(it, iter)) +#define SELECTED(it) (deadbeef->pl_is_selected(it)) +#define SELECT(it, sel) (deadbeef->pl_set_selected(it,sel)) +#define VSELECT(it, sel) {deadbeef->pl_set_selected(it,sel);gtk_pl_redraw_item_everywhere (it);} +#define REF(it) {if (it) deadbeef->pl_item_ref (it);} +#define UNREF(it) {if (it) deadbeef->pl_item_unref (it);} + #if HAVE_NOTIFY #define NOTIFY_DEFAULT_FORMAT "%a - %t" #endif diff --git a/plugins/gtkui/search.c b/plugins/gtkui/search.c index 8c2055d1..517f7f50 100644 --- a/plugins/gtkui/search.c +++ b/plugins/gtkui/search.c @@ -36,12 +36,12 @@ #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) -#define PL_HEAD(iter) (deadbeef->pl_get_first(iter)) -#define PL_TAIL(iter) (deadbeef->pl_get_last(iter)) -#define PL_NEXT(it, iter) (deadbeef->pl_get_next(it, iter)) -#define PL_PREV(it, iter) (deadbeef->pl_get_prev(it, iter)) -#define SELECTED(it) (deadbeef->pl_is_selected(it)) -#define SELECT(it, sel) (deadbeef->pl_set_selected(it,sel)) +//#define PL_HEAD(iter) (deadbeef->pl_get_first(iter)) +//#define PL_TAIL(iter) (deadbeef->pl_get_last(iter)) +//#define PL_NEXT(it, iter) (deadbeef->pl_get_next(it, iter)) +//#define PL_PREV(it, iter) (deadbeef->pl_get_prev(it, iter)) +//#define SELECTED(it) (deadbeef->pl_is_selected(it)) +//#define SELECT(it, sel) (deadbeef->pl_set_selected(it,sel)) extern DB_functions_t *deadbeef; // defined in gtkui.c //#define trace(...) { fprintf(stderr, __VA_ARGS__); } diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c index 9a925304..df68ba12 100644 --- a/plugins/mpgmad/mpgmad.c +++ b/plugins/mpgmad/mpgmad.c @@ -556,6 +556,7 @@ cmp3_init (DB_playItem_t *it) { if (!info->buffer.file) { return NULL; } + deadbeef->pl_item_ref (it); info->buffer.it = it; info->info.readpos = 0; if (!info->buffer.file->vfs->streaming) { @@ -907,6 +908,9 @@ static void cmp3_free (DB_fileinfo_t *_info) { mpgmad_info_t *info = (mpgmad_info_t *)_info; if (info->buffer.file) { + if (info->buffer.it) { + deadbeef->pl_item_unref (info->buffer.it); + } deadbeef->fclose (info->buffer.file); info->buffer.file = NULL; mad_synth_finish (&info->synth); @@ -108,6 +108,7 @@ streamer_move_to_nextsong (int reason) { if (it) { pl_playqueue_pop (); int r = pl_get_idx_of (it); + pl_item_unref (it); streamer_set_nextsong (r, 1); pl_global_unlock (); return 0; @@ -232,16 +233,19 @@ streamer_move_to_nextsong (int reason) { int streamer_move_to_prevsong (void) { + plt_lock (); playlist_t *plt = plt_get_curr_ptr (); pl_playqueue_clear (); if (!plt->head[PL_MAIN]) { streamer_set_nextsong (-2, 1); + plt_unlock (); return 0; } int pl_order = conf_get_int ("playback.order", 0); int pl_loop_mode = conf_get_int ("playback.loop", 0); if (pl_order == PLAYBACK_ORDER_SHUFFLE) { // shuffle if (!playlist_track) { + plt_unlock (); return streamer_move_to_nextsong (1); } else { @@ -273,6 +277,7 @@ streamer_move_to_prevsong (void) { } if (!it) { + plt_unlock (); return -1; } int r = pl_get_idx_of (it); @@ -291,15 +296,18 @@ streamer_move_to_prevsong (void) { } } if (!it) { + plt_unlock (); return -1; } int r = pl_get_idx_of (it); streamer_set_nextsong (r, 1); + plt_unlock (); return 0; } else if (pl_order == PLAYBACK_ORDER_RANDOM) { // random streamer_move_to_randomsong (); } + plt_unlock (); return -1; } @@ -505,18 +513,25 @@ streamer_thread (void *ctx) { p_stop (); mutex_lock (decodemutex); - pl_item_unref (playing_track); - playing_track = NULL; - pl_item_unref (streaming_track); - streaming_track = NULL; + if (playing_track) { + pl_item_unref (playing_track); + playing_track = NULL; + } + if (streaming_track) { + pl_item_unref (streaming_track); + streaming_track = NULL; + } mutex_unlock (decodemutex); messagepump_push (M_SONGCHANGED, 0, -1, -1); continue; } int ret = streamer_set_current (try); + if (ret < 0) { trace ("\033[0;31mfailed to play track %s, skipping (current=%p/%p)...\033[37;0m\n", try->fname, streaming_track, playlist_track); + pl_item_unref (try); + try = NULL; // remember bad song number in case of looping if (badsong == -1) { badsong = sng; @@ -527,6 +542,8 @@ streamer_thread (void *ctx) { usleep (50000); continue; } + pl_item_unref (try); + try = NULL; badsong = -1; if (pstate == 0) { p_stop (); @@ -556,8 +573,10 @@ streamer_thread (void *ctx) { plug_trigger_event (DB_EV_SONGFINISHED, 0); } streamer_set_current (NULL); - pl_item_unref (playing_track); - playing_track = NULL; + if (playing_track) { + pl_item_unref (playing_track); + playing_track = NULL; + } messagepump_push (M_SONGCHANGED, 0, from, -1); continue; } |