Permalink
Browse files

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

  • Loading branch information...
jlindgren90 committed Mar 8, 2015
1 parent 6e5d1a0 commit 456c4eb8c849f8d273718c38ba9772f6193939db
View
@@ -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,
View
@@ -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.