diff options
Diffstat (limited to 'src/libaudcore/playlist.cc')
-rw-r--r-- | src/libaudcore/playlist.cc | 113 |
1 files changed, 48 insertions, 65 deletions
diff --git a/src/libaudcore/playlist.cc b/src/libaudcore/playlist.cc index a2b413c..9bfc718 100644 --- a/src/libaudcore/playlist.cc +++ b/src/libaudcore/playlist.cc @@ -112,7 +112,6 @@ struct Entry { void format (); void set_tuple (Tuple && new_tuple); - void set_failed (const String & new_error); String filename; PluginHandle * decoder; @@ -217,16 +216,17 @@ void Entry::format () void Entry::set_tuple (Tuple && new_tuple) { - /* Hack: We cannot refresh segmented entries (since their info is read from - * the cue sheet when it is first loaded), so leave them alone. -jlindgren */ - if (tuple.get_value_type (Tuple::StartTime) == Tuple::Int) + /* Since 3.8, cuesheet entries are handled differently. The entry filename + * points to the .cue file, and the path to the actual audio file is stored + * in the Tuple::AudioFile. If Tuple::AudioFile is not set, then assume + * that the playlist was created by an older version of Audacious, and + * revert to the former behavior (don't refresh this entry). */ + if (tuple.is_set (Tuple::StartTime) && ! tuple.is_set (Tuple::AudioFile)) return; - scanned = (bool) new_tuple; - failed = false; error = String (); - if (! new_tuple) + if (! new_tuple.valid ()) new_tuple.set_filename (filename); length = aud::max (0, new_tuple.get_int (Tuple::Length)); @@ -248,21 +248,12 @@ void PlaylistData::set_entry_tuple (Entry * entry, Tuple && tuple) selected_length += entry->length; } -void Entry::set_failed (const String & new_error) -{ - scanned = true; - failed = true; - error = new_error; -} - Entry::Entry (PlaylistAddItem && item) : filename (item.filename), decoder (item.decoder), number (-1), length (0), shuffle_num (0), - scanned (false), - failed (false), selected (false), queued (false) { @@ -351,14 +342,6 @@ static void update (void *) hook_call ("playlist update", aud::to_ptr (level)); } -static void send_playback_info (Entry * entry) -{ - // if the entry was not scanned or failed to scan, we must still call - // playback_set_info() in order to update the entry number - Tuple tuple = (entry->scanned && ! entry->failed) ? entry->tuple.ref () : Tuple (); - playback_set_info (entry->number, std::move (tuple)); -} - static void queue_update (UpdateLevel level, PlaylistData * p, int at, int count, int flags = 0) { if (p) @@ -369,7 +352,7 @@ static void queue_update (UpdateLevel level, PlaylistData * p, int at, int count if (level >= Metadata) { if (p == playing_playlist && p->position) - send_playback_info (p->position); + playback_set_info (p->position->number, p->position->tuple.ref ()); p->modified = true; } @@ -497,12 +480,15 @@ static ScanItem * scan_list_find_request (ScanRequest * request) static void scan_queue_entry (PlaylistData * playlist, Entry * entry, bool for_playback = false) { int flags = 0; - if (! entry->scanned || entry->failed) + if (! entry->tuple.valid ()) flags |= SCAN_TUPLE; if (for_playback) flags |= (SCAN_IMAGE | SCAN_FILE); - auto request = new ScanRequest (entry->filename, flags, scan_finish, entry->decoder); + /* scanner uses Tuple::AudioFile from existing tuple, if valid */ + auto request = new ScanRequest (entry->filename, flags, scan_finish, + entry->decoder, (flags & SCAN_TUPLE) ? Tuple () : entry->tuple.ref ()); + scan_list.append (new ScanItem (playlist, entry, request, for_playback)); /* playback entry will be scanned by the playback thread */ @@ -558,7 +544,8 @@ static bool scan_queue_next_entry () Entry * entry = playlist->entries[scan_row ++].get (); // blacklist stdin - if (! entry->scanned && ! scan_list_find_entry (entry) && + if (entry->tuple.state () == Tuple::Initial && + ! scan_list_find_entry (entry) && strncmp (entry->filename, "stdin://", 8)) { scan_queue_entry (playlist, entry); @@ -611,14 +598,20 @@ static void scan_finish (ScanRequest * request) if (! entry->decoder) entry->decoder = request->decoder; - if ((! entry->scanned || entry->failed) && request->tuple) + if (! entry->tuple.valid () && request->tuple.valid ()) { playlist->set_entry_tuple (entry, std::move (request->tuple)); queue_update (Metadata, playlist, entry->number, 1, DelayedUpdate); } - if (! entry->decoder || ! entry->scanned) - entry->set_failed (request->error); + if (! entry->decoder || ! entry->tuple.valid ()) + entry->error = request->error; + + if (entry->tuple.state () == Tuple::Initial) + { + entry->tuple.set_state (Tuple::Failed); + queue_update (Metadata, playlist, entry->number, 1, DelayedUpdate); + } delete item; @@ -690,8 +683,7 @@ static Entry * get_entry (int playlist_num, int entry_num, return entry; // check whether requested data (decoder and/or tuple) has been read - if ((! need_decoder || entry->decoder) && - (! need_tuple || (entry->scanned && ! entry->failed))) + if ((! need_decoder || entry->decoder) && (! need_tuple || entry->tuple.valid ())) return entry; // start scan if not already running ... @@ -717,6 +709,8 @@ static void start_playback (int seek_time, bool pause) playback_play (seek_time, pause); + // playback always begins with a rescan of the current entry in order to + // open the file, ensure a valid tuple, and read album art scan_cancel (playing_playlist->position); scan_queue_entry (playing_playlist, playing_playlist->position, true); } @@ -752,6 +746,7 @@ void playlist_init () hook_associate ("set metadata_on_play", (HookFunction) playlist_trigger_scan, nullptr); hook_associate ("set generic_title_format", (HookFunction) playlist_reformat_titles, nullptr); hook_associate ("set leading_zero", (HookFunction) playlist_reformat_titles, nullptr); + hook_associate ("set show_hours", (HookFunction) playlist_reformat_titles, nullptr); hook_associate ("set metadata_fallbacks", (HookFunction) playlist_reformat_titles, nullptr); hook_associate ("set show_numbers_in_pl", (HookFunction) playlist_reformat_titles, nullptr); } @@ -772,9 +767,12 @@ void playlist_end () hook_dissociate ("set metadata_on_play", (HookFunction) playlist_trigger_scan); hook_dissociate ("set generic_title_format", (HookFunction) playlist_reformat_titles); hook_dissociate ("set leading_zero", (HookFunction) playlist_reformat_titles); + hook_dissociate ("set show_hours", (HookFunction) playlist_reformat_titles); hook_dissociate ("set metadata_fallbacks", (HookFunction) playlist_reformat_titles); hook_dissociate ("set show_numbers_in_pl", (HookFunction) playlist_reformat_titles); + playlist_cache_clear (); + ENTER; /* playback should already be stopped */ @@ -1239,9 +1237,7 @@ EXPORT PluginHandle * aud_playlist_entry_get_decoder (int playlist_num, { ENTER; - const bool wait = (mode == Wait || mode == WaitGuess); - - Entry * entry = get_entry (playlist_num, entry_num, wait, false); + Entry * entry = get_entry (playlist_num, entry_num, (mode == Wait), false); PluginHandle * decoder = entry ? entry->decoder : nullptr; if (error) @@ -1255,14 +1251,8 @@ EXPORT Tuple aud_playlist_entry_get_tuple (int playlist_num, int entry_num, { ENTER; - const bool wait = (mode == Wait || mode == WaitGuess); - const bool guess = (mode == Guess || mode == WaitGuess); - - Entry * entry = get_entry (playlist_num, entry_num, false, wait); - - Tuple tuple; - if (entry && ((entry->scanned && ! entry->failed) || guess)) - tuple = entry->tuple.ref (); + Entry * entry = get_entry (playlist_num, entry_num, false, (mode == Wait)); + Tuple tuple = entry ? entry->tuple.ref () : Tuple (); if (error) * error = entry ? entry->error : String (); @@ -1660,27 +1650,19 @@ struct CompareData { PlaylistTupleCompareFunc tuple_compare; }; -static int compare_cb (const SmartPtr<Entry> & a, const SmartPtr<Entry> & b, void * _data) +static void sort_entries (Index<SmartPtr<Entry>> & entries, CompareData * data) { - CompareData * data = (CompareData *) _data; - - int diff = 0; - - if (data->filename_compare) - diff = data->filename_compare (a->filename, b->filename); - else if (data->tuple_compare) - diff = data->tuple_compare (a->tuple, b->tuple); - - if (diff) - return diff; - - /* preserve order of "equal" entries */ - return a->number - b->number; + entries.sort ([data] (const SmartPtr<Entry> & a, const SmartPtr<Entry> & b) { + if (data->filename_compare) + return data->filename_compare (a->filename, b->filename); + else + return data->tuple_compare (a->tuple, b->tuple); + }); } static void sort (PlaylistData * playlist, CompareData * data) { - playlist->entries.sort (compare_cb, data); + sort_entries (playlist->entries, data); number_entries (playlist, 0, playlist->entries.len ()); queue_update (Structure, playlist, 0, playlist->entries.len ()); @@ -1698,7 +1680,7 @@ static void sort_selected (PlaylistData * playlist, CompareData * data) selected.append (std::move (entry)); } - selected.sort (compare_cb, data); + sort_entries (selected, data); int i = 0; for (auto & entry : playlist->entries) @@ -1718,7 +1700,7 @@ static bool entries_are_scanned (PlaylistData * playlist, bool selected) if (selected && ! entry->selected) continue; - if (! entry->scanned) + if (entry->tuple.state () == Tuple::Initial) { aud_ui_show_error (_("The playlist cannot be sorted because " "metadata scanning is still in progress (or has been disabled).")); @@ -2231,12 +2213,12 @@ DecodeInfo playback_entry_read (int serial) item->handled_by_playback = true; LEAVE; - scanner_run (request); + request->run (); ENTER; if ((entry = get_playback_entry (serial))) { - send_playback_info (entry); + playback_set_info (entry->number, entry->tuple.ref ()); art_cache_current (entry->filename, std::move (request->image_data), std::move (request->image_file)); @@ -2258,7 +2240,8 @@ void playback_entry_set_tuple (int serial, Tuple && tuple) ENTER; Entry * entry = get_playback_entry (serial); - if (entry) + /* don't update cuesheet entries with stream metadata */ + if (entry && ! entry->tuple.is_set (Tuple::StartTime)) { playing_playlist->set_entry_tuple (entry, std::move (tuple)); queue_update (Metadata, playing_playlist, entry->number, 1); |