Skip to content

Commit

Permalink
Integrate playlist+playback+album art to open the input file only once.
Browse files Browse the repository at this point in the history
  • Loading branch information
jlindgren90 committed Mar 8, 2015
1 parent 6e5d1a0 commit 456c4eb
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 118 deletions.
6 changes: 6 additions & 0 deletions src/libaudcore/adder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -334,6 +338,8 @@ static void add_finish (void * unused)
aud_playlist_play (playlist);
}

playlist_delay_scan (playlist, false);

FREE:
delete result;
}
Expand Down
35 changes: 34 additions & 1 deletion src/libaudcore/art.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down
7 changes: 4 additions & 3 deletions src/libaudcore/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
73 changes: 24 additions & 49 deletions src/libaudcore/playback.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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)
{
Expand All @@ -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 ();
}
Expand Down Expand Up @@ -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));
Expand All @@ -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)
Expand All @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/libaudcore/playlist-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
Loading

0 comments on commit 456c4eb

Please sign in to comment.