summaryrefslogtreecommitdiff
path: root/src/libaudcore/playlist.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libaudcore/playlist.cc')
-rw-r--r--src/libaudcore/playlist.cc113
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);