diff --git a/data/com.github.artemanufrij.playmymusic.appdata.xml b/data/com.github.artemanufrij.playmymusic.appdata.xml index 8e73f47..55c44d1 100644 --- a/data/com.github.artemanufrij.playmymusic.appdata.xml +++ b/data/com.github.artemanufrij.playmymusic.appdata.xml @@ -64,6 +64,7 @@

New:

diff --git a/schemas/com.github.artemanufrij.playmymusic.gschema.xml b/schemas/com.github.artemanufrij.playmymusic.gschema.xml index bd125ec..a9a21eb 100644 --- a/schemas/com.github.artemanufrij.playmymusic.gschema.xml +++ b/schemas/com.github.artemanufrij.playmymusic.gschema.xml @@ -100,10 +100,10 @@ Last choosed view. Last choosed view. - + true - Load Artist data like Artwork from MusicBrainz. - Load Artist data like Artwork from MusicBrainz. + Load Artwork and Cover from MusicBrainz. + Load Artwork and Cover from MusicBrainz. false diff --git a/src/Dialogs/Preferences.vala b/src/Dialogs/Preferences.vala index b1b5c4d..7831074 100644 --- a/src/Dialogs/Preferences.vala +++ b/src/Dialogs/Preferences.vala @@ -81,12 +81,12 @@ namespace PlayMyMusic.Dialogs { settings.sync_files = sync_files.active; }); - var load_artist_data_label = new Gtk.Label (_("Load Artist data from MusicBrainz")); - load_artist_data_label.halign = Gtk.Align.START; - var load_artist_data = new Gtk.Switch (); - load_artist_data.active = settings.load_artist_from_musicbrainz; - load_artist_data.notify["active"].connect (() => { - settings.load_artist_from_musicbrainz = load_artist_data.active; + var load_content_label = new Gtk.Label (_("Load Content from MusicBrainz")); + load_content_label.halign = Gtk.Align.START; + var load_content = new Gtk.Switch (); + load_content.active = settings.load_content_from_musicbrainz; + load_content.notify["active"].connect (() => { + settings.load_content_from_musicbrainz = load_content.active; }); var save_custom_covers_label = new Gtk.Label (_("Save custom Covers in Library folder")); @@ -113,8 +113,8 @@ namespace PlayMyMusic.Dialogs { grid.attach (sync_files_label, 0, 3); grid.attach (sync_files, 1, 3); grid.attach (new Gtk.Separator (Gtk.Orientation.HORIZONTAL), 0, 4, 2, 1); - grid.attach (load_artist_data_label, 0, 5); - grid.attach (load_artist_data, 1, 5); + grid.attach (load_content_label, 0, 5); + grid.attach (load_content, 1, 5); grid.attach (save_custom_covers_label, 0, 6); grid.attach (save_custom_covers, 1, 6); grid.attach (save_id3_tags_label, 0, 7); diff --git a/src/Objects/Album.vala b/src/Objects/Album.vala index f9b6422..9f30057 100644 --- a/src/Objects/Album.vala +++ b/src/Objects/Album.vala @@ -133,7 +133,7 @@ namespace PlayMyMusic.Objects { } // COVER REGION - private async void load_cover_async () { + public async void load_cover_async () { if (is_cover_loading || cover != null || this.ID == 0 || this.tracks.length () == 0) { return; } @@ -142,6 +142,8 @@ namespace PlayMyMusic.Objects { Gdk.Pixbuf? return_value = load_or_create_cover.end (res); if (return_value != null) { this.cover = return_value; + } else if (settings.load_content_from_musicbrainz) { + Services.MusicBrainzManager.instance.fill_album_cover_queue (this); } is_cover_loading = false; }); diff --git a/src/Objects/Artist.vala b/src/Objects/Artist.vala index 60bbdae..d8c1bfa 100644 --- a/src/Objects/Artist.vala +++ b/src/Objects/Artist.vala @@ -142,6 +142,16 @@ namespace PlayMyMusic.Objects { } } + public bool has_empty_album_covers () { + foreach (var album in albums) { + if (album.cover == null) { + return true; + } + } + + return false; + } + public void merge (GLib.List artists) { foreach (var artist in artists) { if (artist.ID == ID) { @@ -194,7 +204,7 @@ namespace PlayMyMusic.Objects { Gdk.Pixbuf? return_value = load_or_create_cover.end (res); if (return_value != null) { this.cover = return_value; - } else if (settings.load_artist_from_musicbrainz && !this.name.down ().contains ("various") && !this.name.down ().contains ("artist")) { + } else if (settings.load_content_from_musicbrainz && !this.name.down ().contains ("various") && !this.name.down ().contains ("artist")) { Services.MusicBrainzManager.instance.fill_artist_cover_queue (this); } is_cover_loading = false; diff --git a/src/Objects/Track.vala b/src/Objects/Track.vala index b6e10fb..973f617 100644 --- a/src/Objects/Track.vala +++ b/src/Objects/Track.vala @@ -33,7 +33,7 @@ namespace PlayMyMusic.Objects { public signal void album_changed (Album album); public signal void tags_saved (); - Album? _album = null; + Album ? _album = null; public Album album { get { if (_album == null) { @@ -43,8 +43,8 @@ namespace PlayMyMusic.Objects { } } - Playlist? _playlist = null; - public Playlist? playlist { + Playlist ? _playlist = null; + public Playlist ? playlist { get { return _playlist; } @@ -74,24 +74,25 @@ namespace PlayMyMusic.Objects { } } - public File? original_file { get; set; } + public File ? original_file { get; set; } public signal void path_not_found (); construct { library_manager = Services.LibraryManager.instance; - removed.connect (() => { - if (album != null) { - album.track_removed (this); - album.artist.track_removed (this); - } - if (playlist != null) { - playlist.track_removed (this); - } - }); + removed.connect ( + () => { + if (album != null) { + album.track_removed (this); + album.artist.track_removed (this); + } + if (playlist != null) { + playlist.track_removed (this); + } + }); } - public Track (TracksContainer? container = null) { + public Track (TracksContainer ? container = null) { if (container != null && container is Album) { set_album (container as Album); } else if (container != null && container is Playlist) { @@ -126,10 +127,8 @@ namespace PlayMyMusic.Objects { } public void save_id3_tags () { - var path = File.new_for_uri (uri); - stdout.printf ("ID3 Start\n"); var file = new TagLib.File (path.get_path ()); if (file.tag.album == this.album.title && file.tag.artist == this.album.artist.name && file.tag.year == this.album.year && file.tag.genre == genre) { return; @@ -141,8 +140,6 @@ namespace PlayMyMusic.Objects { file.tag.genre = genre; if (file.save ()) { tags_saved (); - - stdout.printf ("ID3 SAVED year:%u \n", file.tag.year); } path.dispose (); } diff --git a/src/Services/MusicBrainzManager.vala b/src/Services/MusicBrainzManager.vala index b5af47c..d7c7dcc 100644 --- a/src/Services/MusicBrainzManager.vala +++ b/src/Services/MusicBrainzManager.vala @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2017-2017 Artem Anufrij + * Copyright (c) 2017-2018 Artem Anufrij * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -31,20 +31,23 @@ namespace PlayMyMusic.Services { public static MusicBrainzManager instance { get { if (_instance == null) { - _instance = new MusicBrainzManager(); + _instance = new MusicBrainzManager (); } return _instance; } } GLib.List artists = new GLib.List (); + GLib.List albums = new GLib.List (); bool artist_thread_running = false; + bool album_thread_running = false; - private MusicBrainzManager () {} + private MusicBrainzManager () { + } - private static string? get_body_from_url (string url) { - string? return_value = null; + private static string ? get_body_from_url (string url) { + string ? return_value = null; var session = new Soup.Session.with_options ("user_agent", "PlayMyMusic/0.1.0 (https://github.com/artemanufrij/playmymusic)"); var msg = new Soup.Message ("GET", url); session.send_message (msg); @@ -65,53 +68,110 @@ namespace PlayMyMusic.Services { read_artists_queue (); } - private void read_artists_queue () { - if (artist_thread_running) { + public void fill_album_cover_queue (Objects.Album album) { + lock (albums) { + if (albums.index (album) == -1) { + albums.append (album); + } + } + read_albums_queue (); + } + + private void read_albums_queue () { + if (album_thread_running) { return; } artist_thread_running = true; - new Thread (null, () => { - Objects.Artist? first = null; - while (artists.length () > 0) { - lock (artists) { - first = artists.first ().data; - if (first != null) { - artists.remove (first); + new Thread ( + "read_albums_queue", + () => { + Objects.Album ? first = null; + + while (albums.length () > 0) { + lock (albums) { + first = albums.first ().data; + if (first != null) { + albums.remove (first); + } + } + Thread.usleep (1000000); + string url = "http://musicbrainz.org/ws/2/release/?query=release:%s AND artist:%s&fmt=json".printf (first.title.replace ("&", "%26").replace ("/", "_"), first.artist.name.replace ("&", "%26").replace ("/", "_")); + var body = get_body_from_url (url); + if (body != null) { + var release_id = Utils.MusicBrainz.get_release_id_from_artist_ws_2 (body); + stdout.printf ("RELEASE ID: %s (%s / %s)\n", release_id, first.title, first.artist.name); + var pixbuf = get_pixbuf_by_release_id (release_id); + if (pixbuf != null) { + pixbuf = LibraryManager.instance.align_and_scale_pixbuf (pixbuf, 256); + try { + if (pixbuf.save (first.cover_path, "jpeg", "quality", "100")) { + if (Settings.get_default ().save_custom_covers) { + first.set_custom_cover_file (first.cover_path); + } + first.load_cover_async.begin (); + break; + } + } catch (Error err) { + warning (err.message); + } + } } } - if (first != null && first.cover == null) { - var albums = first.albums_title.copy (); - foreach (var album in albums) { - Thread.usleep (1000000); - string url = "http://musicbrainz.org/ws/2/release/?query=release:%s AND artist:%s&fmt=json".printf (album.replace ("&", "%26").replace("/", "_"), first.name.replace ("&", "%26").replace("/", "_")); - var body = get_body_from_url (url); - if (body != null) { - var artist_id = Utils.MusicBrainz.get_artist_id_from_artist_ws_2 (body); - stdout.printf ("ARTIST ID: %s (%s / %s)\n", artist_id, album, first.name); - var pixbuf = get_pixbuf_by_artist_id (artist_id); - if (pixbuf != null) { - pixbuf = LibraryManager.instance.align_and_scale_pixbuf (pixbuf, 256); - try { - if (pixbuf.save (first.cover_path, "jpeg", "quality", "100")) { - if (Settings.get_default ().save_custom_covers) { - first.set_custom_cover_file (first.cover_path); + return null; + }); + } + + private void read_artists_queue () { + if (artist_thread_running) { + return; + } + artist_thread_running = true; + new Thread ( + "read_artists_queue", + () => { + Objects.Artist ? first = null; + while (artists.length () > 0) { + lock (artists) { + first = artists.first ().data; + if (first != null) { + artists.remove (first); + } + } + + if (first != null && (first.cover == null || first.has_empty_album_covers ())) { + var albums = first.albums_title.copy (); + foreach (var album in albums) { + Thread.usleep (1000000); + string url = "http://musicbrainz.org/ws/2/release/?query=release:%s AND artist:%s&fmt=json".printf (album.replace ("&", "%26").replace ("/", "_"), first.name.replace ("&", "%26").replace ("/", "_")); + var body = get_body_from_url (url); + if (body != null) { + var artist_id = Utils.MusicBrainz.get_artist_id_from_artist_ws_2 (body); + var release_id = Utils.MusicBrainz.get_release_id_from_artist_ws_2 (body); + stdout.printf ("ARTIST ID: %s; RELEASE ID: %s (%s / %s)\n", artist_id, release_id, album, first.name); + var pixbuf = get_pixbuf_by_artist_id (artist_id); + if (pixbuf != null) { + pixbuf = LibraryManager.instance.align_and_scale_pixbuf (pixbuf, 256); + try { + if (pixbuf.save (first.cover_path, "jpeg", "quality", "100")) { + if (Settings.get_default ().save_custom_covers) { + first.set_custom_cover_file (first.cover_path); + } + first.load_cover_async.begin (); + break; } - first.load_cover_async.begin (); - break; + } catch (Error err) { + warning (err.message); } - } catch (Error err) { - warning (err.message); } } } } } - } - artist_thread_running = false; - return null; - }); + artist_thread_running = false; + return null; + }); } public static void fill_audio_cd (PlayMyMusic.Objects.AudioCD audio_cd) { @@ -125,7 +185,7 @@ namespace PlayMyMusic.Services { parser.load_from_data (body); root = parser.get_root (); } catch (Error err) { - warning (err.message); + warning (err.message); } if (root != null) { var o = root.get_object (); @@ -164,7 +224,7 @@ namespace PlayMyMusic.Services { pixbuf.save (audio_cd.cover_path, "jpeg", "quality", "100"); audio_cd.load_cover_async.begin (); } catch (Error err) { - warning (err.message); + warning (err.message); } } } @@ -172,7 +232,38 @@ namespace PlayMyMusic.Services { } } - public Gdk.Pixbuf? get_pixbuf_by_artist_id (string id) { + public Gdk.Pixbuf ? get_pixbuf_by_release_id (string id) { + if (id == "") { + return null; + } + string url = "https://coverartarchive.org/release/%s".printf (id); + var body = get_body_from_url (url); + if (body != null) { + var parser = new Json.Parser (); + Json.Node root = null; + try { + parser.load_from_data (body); + root = parser.get_root (); + } catch (Error err) { + warning (err.message); + } + if (root != null && root.get_object ().has_member ("images")) { + var images = root.get_object ().get_member ("images").get_array (); + foreach (unowned Json.Node item in images.get_elements ()) { + var o = item.get_object (); + if (o.get_boolean_member ("front") && o.has_member ("thumbnails")) { + var thumb = o.get_member ("thumbnails").get_object (); + if (thumb.has_member ("large")) { + return get_pixbuf_from_url (thumb.get_string_member ("large")); + } + } + } + } + } + return null; + } + + public Gdk.Pixbuf ? get_pixbuf_by_artist_id (string id) { if (id == "") { return null; } @@ -185,7 +276,7 @@ namespace PlayMyMusic.Services { parser.load_from_data (body); root = parser.get_root (); } catch (Error err) { - warning (err.message); + warning (err.message); } if (root != null && root.get_object ().has_member ("relations")) { var relations = root.get_object ().get_member ("relations").get_array (); @@ -222,7 +313,7 @@ namespace PlayMyMusic.Services { try { regex = new Regex ("(?<=/wiki/)[^<]*"); } catch (Error err) { - warning (err.message); + warning (err.message); return ""; } @@ -234,7 +325,7 @@ namespace PlayMyMusic.Services { try { regex = new Regex ("(?<=\"source\":\")[^\"]*"); } catch (Error err) { - warning (err.message); + warning (err.message); return ""; } if (regex.match (body, 0, out match_info)) { @@ -252,7 +343,7 @@ namespace PlayMyMusic.Services { try { regex = new Regex ("(?<=/File:)[^<]*"); } catch (Error err) { - warning (err.message); + warning (err.message); return ""; } @@ -264,7 +355,7 @@ namespace PlayMyMusic.Services { try { regex = new Regex ("(?<=\"thumburl\":\")[^\"]*"); } catch (Error err) { - warning (err.message); + warning (err.message); return ""; } if (regex.match (body, 0, out match_info)) { @@ -276,22 +367,22 @@ namespace PlayMyMusic.Services { return ""; } - public static Gdk.Pixbuf? get_pixbuf_from_url (string url) { + public static Gdk.Pixbuf ? get_pixbuf_from_url (string url) { if (!url.has_prefix ("http")) { return null; } - Gdk.Pixbuf? return_value = null; + Gdk.Pixbuf ? return_value = null; var session = new Soup.Session.with_options ("user_agent", "PlayMyMusic/0.1.0 (https://github.com/artemanufrij/playmymusic)"); var msg = new Soup.Message ("GET", url); session.send_message (msg); if (msg.status_code == 200) { string tmp_file = GLib.Path.build_filename (GLib.Environment.get_user_cache_dir (), Random.next_int ().to_string () + ".jpg"); - var fs = FileStream.open(tmp_file, "w"); + var fs = FileStream.open (tmp_file, "w"); fs.write (msg.response_body.data, (size_t)msg.response_body.length); try { return_value = new Gdk.Pixbuf.from_file (tmp_file); } catch (Error err) { - warning (err.message); + warning (err.message); } File f = File.new_for_path (tmp_file); f.delete_async.begin (); diff --git a/src/Settings.vala b/src/Settings.vala index f373b6c..48cff02 100644 --- a/src/Settings.vala +++ b/src/Settings.vala @@ -59,7 +59,7 @@ namespace PlayMyMusic { public string [] covers { get; set; } public string library_location { get; set; } public int view_index { get; set; } - public bool load_artist_from_musicbrainz { get; set; } + public bool load_content_from_musicbrainz { get; set; } public bool use_dark_theme { get; set; } public bool save_custom_covers { get; set; } public bool save_id3_tags { get; set; } diff --git a/src/Utils/MusicBrainz.vala b/src/Utils/MusicBrainz.vala index 01040a8..811b29e 100644 --- a/src/Utils/MusicBrainz.vala +++ b/src/Utils/MusicBrainz.vala @@ -52,6 +52,27 @@ namespace PlayMyMusic.Utils { return ""; } + public static string get_release_id_from_artist_ws_2 (string body) { + var parser = new Json.Parser (); + Json.Node root = null; + try { + parser.load_from_data (body); + root = parser.get_root (); + } catch (Error err) { + warning (err.message); + } + if (root != null) { + if (root.get_object ().has_member ("releases")) { + var releases = root.get_object ().get_member ("releases").get_array (); + if (releases.get_length () > 0) { + var release = releases.get_element (0).get_object (); + return release.get_string_member ("id"); + } + } + } + return ""; + } + public static string get_large_thumbnail_from_release (string body) { var parser = new Json.Parser (); Json.Node root = null;