diff --git a/src/AudioObject.vala b/src/AudioObject.vala index b80934a9d..4c0146bdb 100644 --- a/src/AudioObject.vala +++ b/src/AudioObject.vala @@ -6,11 +6,122 @@ public class Music.AudioObject : Object { public string uri { get; construct; } public Gdk.Texture texture { get; set; } - public string artist { get; set; } + public string artist { get; set; default = _("Unknown Artist"); } public string title { get; set; } public int64 duration { get; set; default = 0; } + private static Gst.PbUtils.Discoverer discoverer; + + static construct { + try { + discoverer = new Gst.PbUtils.Discoverer ((Gst.ClockTime) (5 * Gst.SECOND)); + discoverer.finished.connect (discoverer.stop); + } catch (Error e) { + critical ("Unable to start Gstreamer Discoverer: %s", e.message); + } + } + public AudioObject (string uri) { - Object (uri: uri); + Object ( + title: uri, + uri: uri + ); + } + + construct { + discoverer.start (); + discoverer.discover_uri_async (uri); + discoverer.discovered.connect (update_metadata); + } + + private void update_metadata (Gst.PbUtils.DiscovererInfo info, Error? err) { + string info_uri = info.get_uri (); + switch (info.get_result ()) { + case Gst.PbUtils.DiscovererResult.URI_INVALID: + critical ("Couldn't read metadata for '%s': invalid URI.", info_uri); + return; + case Gst.PbUtils.DiscovererResult.ERROR: + critical ("Couldn't read metadata for '%s': %s", info_uri, err.message); + return; + case Gst.PbUtils.DiscovererResult.TIMEOUT: + critical ("Couldn't read metadata for '%s': Discovery timed out.", info_uri); + return; + case Gst.PbUtils.DiscovererResult.BUSY: + critical ("Couldn't read metadata for '%s': Already discovering a file.", info_uri); + return; + case Gst.PbUtils.DiscovererResult.MISSING_PLUGINS: + critical ("Couldn't read metadata for '%s': Missing plugins.", info_uri); + return; + default: + break; + } + + if (info_uri == uri) { + unowned Gst.TagList? tag_list = info.get_tags (); + + string _title; + tag_list.get_string (Gst.Tags.TITLE, out _title); + if (_title != null) { + title = _title; + } + + string _artist; + tag_list.get_string (Gst.Tags.ARTIST, out _artist); + if (_artist != null) { + artist = _artist; + } + + var sample = get_cover_sample (tag_list); + if (sample != null) { + var buffer = sample.get_buffer (); + + if (buffer != null) { + texture = Gdk.Texture.for_pixbuf (get_pixbuf_from_buffer (buffer)); + } + } + } + } + + private Gst.Sample? get_cover_sample (Gst.TagList tag_list) { + Gst.Sample cover_sample = null; + Gst.Sample sample; + for (int i = 0; tag_list.get_sample_index (Gst.Tags.IMAGE, i, out sample); i++) { + var caps = sample.get_caps (); + unowned Gst.Structure caps_struct = caps.get_structure (0); + int image_type = Gst.Tag.ImageType.UNDEFINED; + caps_struct.get_enum ("image-type", typeof (Gst.Tag.ImageType), out image_type); + if (image_type == Gst.Tag.ImageType.UNDEFINED && cover_sample == null) { + cover_sample = sample; + } else if (image_type == Gst.Tag.ImageType.FRONT_COVER) { + return sample; + } + } + + return cover_sample; + } + + private Gdk.Pixbuf? get_pixbuf_from_buffer (Gst.Buffer buffer) { + Gst.MapInfo map_info; + + if (!buffer.map (out map_info, Gst.MapFlags.READ)) { + warning ("Could not map memory buffer"); + return null; + } + + Gdk.Pixbuf pix = null; + + try { + var loader = new Gdk.PixbufLoader (); + + if (loader.write (map_info.data) && loader.close ()) { + pix = loader.get_pixbuf (); + } + } catch (Error err) { + warning ("Error processing image data: %s", err.message); + } + + buffer.unmap (map_info); + + return pix; } } diff --git a/src/PlaybackManager.vala b/src/PlaybackManager.vala index 4b842c172..3e54a1a40 100644 --- a/src/PlaybackManager.vala +++ b/src/PlaybackManager.vala @@ -18,7 +18,6 @@ public class Music.PlaybackManager : Object { } private dynamic Gst.Element playbin; - private Gst.PbUtils.Discoverer discoverer; private uint progress_timer = 0; private Settings settings; @@ -33,14 +32,6 @@ public class Music.PlaybackManager : Object { bus.add_watch (0, bus_callback); bus.enable_sync_message_emission (); - try { - discoverer = new Gst.PbUtils.Discoverer ((Gst.ClockTime) (5 * Gst.SECOND)); - discoverer.discovered.connect (update_metadata); - discoverer.finished.connect (discoverer.stop); - } catch (Error e) { - critical ("Unable to start Gstreamer Discoverer: %s", e.message); - } - queue_liststore.items_changed.connect (() => { var shuffle_action_action = (SimpleAction) GLib.Application.get_default ().lookup_action (Application.ACTION_SHUFFLE); shuffle_action_action.set_enabled (queue_liststore.get_n_items () > 1); @@ -77,14 +68,9 @@ public class Music.PlaybackManager : Object { } public void queue_files (File[] files) { - discoverer.start (); foreach (unowned var file in files) { if (file.query_exists ()) { var audio_object = new AudioObject (file.get_uri ()); - audio_object.title = audio_object.uri; - - discoverer.discover_uri_async (audio_object.uri); - queue_liststore.append (audio_object); } } @@ -112,70 +98,6 @@ public class Music.PlaybackManager : Object { } } - private void update_metadata (Gst.PbUtils.DiscovererInfo info, Error? err) { - string uri = info.get_uri (); - switch (info.get_result ()) { - case Gst.PbUtils.DiscovererResult.URI_INVALID: - critical ("Couldn't read metadata for '%s': invalid URI.", uri); - return; - case Gst.PbUtils.DiscovererResult.ERROR: - critical ("Couldn't read metadata for '%s': %s", uri, err.message); - return; - case Gst.PbUtils.DiscovererResult.TIMEOUT: - critical ("Couldn't read metadata for '%s': Discovery timed out.", uri); - return; - case Gst.PbUtils.DiscovererResult.BUSY: - critical ("Couldn't read metadata for '%s': Already discovering a file.", uri); - return; - case Gst.PbUtils.DiscovererResult.MISSING_PLUGINS: - critical ("Couldn't read metadata for '%s': Missing plugins.", uri); - return; - default: - break; - } - - EqualFunc equal_func = (a, b) => { - return ((AudioObject) a).uri == ((AudioObject) b).uri; - }; - - var temp_audio_object = new AudioObject (uri); - - uint position = -1; - queue_liststore.find_with_equal_func (temp_audio_object, equal_func, out position); - - if (position != -1) { - var audio_object = (AudioObject) queue_liststore.get_item (position); - audio_object.duration = (int64) info.get_duration (); - - unowned Gst.TagList? tag_list = info.get_tags (); - - string _title; - tag_list.get_string (Gst.Tags.TITLE, out _title); - if (_title != null) { - audio_object.title = _title; - } - - string _artist; - tag_list.get_string (Gst.Tags.ARTIST, out _artist); - if (_artist != null) { - audio_object.artist = _artist; - } else if (_title != null) { // Don't set artist for files without tags - audio_object.artist = _("Unknown"); - } - - var sample = get_cover_sample (tag_list); - if (sample != null) { - var buffer = sample.get_buffer (); - - if (buffer != null) { - audio_object.texture = Gdk.Texture.for_pixbuf (get_pixbuf_from_buffer (buffer)); - } - } - } else { - critical ("Couldn't find '%s' in queue", uri); - } - } - private bool bus_callback (Gst.Bus bus, Gst.Message message) { switch (message.type) { case Gst.MessageType.EOS: @@ -306,47 +228,4 @@ public class Music.PlaybackManager : Object { previous_action.set_enabled (previous_sensitive); } - - private Gst.Sample? get_cover_sample (Gst.TagList tag_list) { - Gst.Sample cover_sample = null; - Gst.Sample sample; - for (int i = 0; tag_list.get_sample_index (Gst.Tags.IMAGE, i, out sample); i++) { - var caps = sample.get_caps (); - unowned Gst.Structure caps_struct = caps.get_structure (0); - int image_type = Gst.Tag.ImageType.UNDEFINED; - caps_struct.get_enum ("image-type", typeof (Gst.Tag.ImageType), out image_type); - if (image_type == Gst.Tag.ImageType.UNDEFINED && cover_sample == null) { - cover_sample = sample; - } else if (image_type == Gst.Tag.ImageType.FRONT_COVER) { - return sample; - } - } - - return cover_sample; - } - - private Gdk.Pixbuf? get_pixbuf_from_buffer (Gst.Buffer buffer) { - Gst.MapInfo map_info; - - if (!buffer.map (out map_info, Gst.MapFlags.READ)) { - warning ("Could not map memory buffer"); - return null; - } - - Gdk.Pixbuf pix = null; - - try { - var loader = new Gdk.PixbufLoader (); - - if (loader.write (map_info.data) && loader.close ()) { - pix = loader.get_pixbuf (); - } - } catch (Error err) { - warning ("Error processing image data: %s", err.message); - } - - buffer.unmap (map_info); - - return pix; - } }