Permalink
Browse files

Integrate playlist+playback+album art to open the input file only once.

  • Loading branch information...
1 parent 6e5d1a0 commit 456c4eb8c849f8d273718c38ba9772f6193939db @jlindgren90 jlindgren90 committed Mar 8, 2015
@@ -324,6 +324,10 @@ static void add_finish (void * unused)
aud_playlist_set_title (playlist, result->title);
}
+ /* temporarily disable scanning this playlist; the intent is to avoid
+ * scanning until the currently playing entry is known, at which time it
+ * can be scanned more efficiently (album art read in the same pass). */
+ playlist_delay_scan (playlist, true);
playlist_entry_insert_batch_raw (playlist, result->at, std::move (result->items));
if (result->play && aud_playlist_entry_count (playlist) > count)
@@ -334,6 +338,8 @@ static void add_finish (void * unused)
aud_playlist_play (playlist);
}
+ playlist_delay_scan (playlist, false);
+
FREE:
delete result;
}
View
@@ -59,6 +59,10 @@ static SimpleHash<String, ArtItem> art_items;
static String current_ref;
static QueuedFunc queued_requests;
+static String current_cached;
+static Index<char> current_data;
+static String current_art_file;
+
static void get_queued_cb (const String & key, ArtItem & item, void * list)
{
if (item.flag == FLAG_DONE)
@@ -145,7 +149,17 @@ static ArtItem * art_item_get (const String & file, bool * queued)
item = art_items.add (file, ArtItem ());
item->refcount = 1; /* temporary reference */
- scanner_request (new ScanRequest (file, SCAN_IMAGE, request_callback));
+ if (file == current_cached)
+ {
+ item->data = std::move (current_data);
+ item->art_file = std::move (current_art_file);
+ item->flag = FLAG_DONE;
+
+ queued_requests.queue (send_requests, nullptr);
+ current_cached = String ();
+ }
+ else
+ scanner_request (new ScanRequest (file, SCAN_IMAGE, request_callback));
}
if (queued)
@@ -177,6 +191,14 @@ static void release_current (void)
aud_art_unref (current_ref);
current_ref = String ();
}
+
+ pthread_mutex_lock (& mutex);
+
+ current_cached = String ();
+ current_data.clear ();
+ current_art_file = String ();
+
+ pthread_mutex_unlock (& mutex);
}
void art_init (void)
@@ -200,6 +222,17 @@ void art_cleanup (void)
AUDWARN ("Album art reference count not zero at exit!\n");
}
+void art_cache_current (const String & filename, Index<char> && data, String && art_file)
+{
+ pthread_mutex_lock (& mutex);
+
+ current_cached = filename;
+ current_data = std::move (data);
+ current_art_file = std::move (art_file);
+
+ pthread_mutex_unlock (& mutex);
+}
+
EXPORT const Index<char> * aud_art_request_data (const char * file, bool * queued)
{
const Index<char> * data = nullptr;
@@ -40,6 +40,7 @@ void adder_cleanup ();
/* art.cc */
void art_init ();
void art_cleanup ();
+void art_cache_current (const String & filename, Index<char> && data, String && art_file);
/* art-search.cc */
String art_search (const char * filename);
@@ -91,9 +92,9 @@ void playback_play (int seek_time, bool pause);
void playback_stop (bool exiting = false);
bool playback_check_serial (int serial);
-bool playback_set_info (int entry, const String & filename,
- PluginHandle * decoder, Tuple && tuple);
-void playback_set_file (VFSFile && file);
+void playback_set_info (int entry, Tuple && tuple);
+void playback_setup_decode (const String & filename, InputPlugin * ip,
+ VFSFile && file, String && error);
/* probe.cc */
bool open_input_file (const char * filename, const char * mode,
@@ -68,14 +68,13 @@ struct PlaybackControl {
struct PlaybackInfo {
// set by playback_set_info
- String filename;
- PluginHandle * decoder = nullptr;
- Tuple tuple;
-
int entry = -1;
+ Tuple tuple;
String title;
- // set by playback_set_file
+ // set by playback_setup_decode
+ String filename;
+ InputPlugin * ip = nullptr;
VFSFile file;
// set by playback thread
@@ -89,7 +88,6 @@ struct PlaybackInfo {
int samplerate = 0;
int channels = 0;
- bool file_in_use = false;
bool ready = false;
bool ended = false;
bool error = false;
@@ -143,17 +141,12 @@ bool playback_check_serial (int serial)
}
// called from the playlist to update the tuple for the current song
-bool playback_set_info (int entry, const String & filename, PluginHandle * decoder, Tuple && tuple)
+void playback_set_info (int entry, Tuple && tuple)
{
// do nothing if the playback thread is lagging behind;
// in that case, playback_set_info() will get called again anyway
if (! lock_if (in_sync))
- return false;
-
- if (! pb_info.filename)
- pb_info.filename = filename;
- if (! pb_info.decoder)
- pb_info.decoder = decoder;
+ return;
if (tuple && tuple != pb_info.tuple)
{
@@ -176,18 +169,19 @@ bool playback_set_info (int entry, const String & filename, PluginHandle * decod
}
unlock ();
- return true;
}
-// called from the playlist to allow reuse of this file handle
-void playback_set_file (VFSFile && file)
+// called from the playlist to set up decoding data
+void playback_setup_decode (const String & filename, InputPlugin * ip,
+ VFSFile && file, String && error)
{
if (! lock_if (in_sync))
return;
- // don't touch file handle if playback thread is already using it
- if (! pb_info.file_in_use)
- pb_info.file = std::move (file);
+ pb_info.filename = filename;
+ pb_info.ip = ip;
+ pb_info.file = std::move (file);
+ pb_info.error_s = std::move (error);
unlock ();
}
@@ -312,20 +306,20 @@ static void run_playback ()
{
// due to mutex ordering, we cannot call into the playlist while locked;
// instead, playback_entry_read() calls back into playback_set_info()
- if (! playback_entry_read (pb_state.playback_serial, pb_info.error_s))
+ playback_entry_read (pb_state.playback_serial);
+
+ if (! lock_if (in_sync))
+ return;
+
+ // check that we have all the necessary data
+ if (! pb_info.filename || ! pb_info.tuple || ! pb_info.ip ||
+ (! pb_info.ip->input_info.keys[InputKey::Scheme] && ! pb_info.file))
{
pb_info.error = true;
+ unlock ();
return;
}
- InputPlugin * ip;
- VFSFile file;
-
- lock ();
-
- // playback_set_info() should always set this info
- assert (pb_info.filename && pb_info.decoder && pb_info.tuple);
-
// get various other bits of info from the tuple
pb_info.length = pb_info.tuple.get_int (Tuple::Length);
pb_info.time_offset = aud::max (0, pb_info.tuple.get_int (Tuple::StartTime));
@@ -336,31 +330,12 @@ static void run_playback ()
if (pb_info.time_offset > 0 && pb_control.seek < 0)
pb_control.seek = 0;
- // reuse playlist file handle if possible
- file = std::move (pb_info.file);
- pb_info.file_in_use = true;
-
unlock ();
- // load input plugin
- if (! (ip = (InputPlugin *) aud_plugin_get_header (pb_info.decoder)))
- {
- pb_info.error = true;
- pb_info.error_s = String (_("Error loading plugin"));
- return;
- }
-
- // open input file
- if (! open_input_file (pb_info.filename, "r", ip, file, & pb_info.error_s))
- {
- pb_info.error = true;
- return;
- }
-
while (1)
{
// hand off control to input plugin
- if (! ip->play (pb_info.filename, file))
+ if (! pb_info.ip->play (pb_info.filename, pb_info.file))
pb_info.error = true;
// close audio (no-op if it wasn't opened)
@@ -385,7 +360,7 @@ static void run_playback ()
break;
// rewind file pointer before repeating
- if (file.fseek (0, VFS_SEEK_SET) != 0)
+ if (pb_info.file.fseek (0, VFS_SEEK_SET) != 0)
{
pb_info.error = true;
break;
@@ -34,12 +34,13 @@ bool playlist_get_modified (int playlist);
void playlist_load_state ();
void playlist_save_state ();
+void playlist_delay_scan (int playlist, bool delay);
void playlist_entry_insert_batch_raw (int playlist, int at, Index<PlaylistAddItem> && items);
bool playlist_prev_song (int playlist);
bool playlist_next_song (int playlist, bool repeat);
-bool playback_entry_read (int serial, String & error);
+void playback_entry_read (int serial);
void playback_entry_set_tuple (int serial, Tuple && tuple);
/* playlist-files.c */
Oops, something went wrong.

0 comments on commit 456c4eb

Please sign in to comment.