protected override void AddTrackToDevice(DatabaseTrackInfo track, SafeUri fromUri) { if (track.PrimarySourceId == DbId) { return; } SafeUri new_uri = new SafeUri(GetTrackPath(track, System.IO.Path.GetExtension(fromUri))); // If it already is on the device but it's out of date, remove it //if (File.Exists(new_uri) && File.GetLastWriteTime(track.Uri.LocalPath) > File.GetLastWriteTime(new_uri)) //RemoveTrack(new MassStorageTrackInfo(new SafeUri(new_uri))); if (!File.Exists(new_uri)) { Directory.Create(System.IO.Path.GetDirectoryName(new_uri.LocalPath)); File.Copy(fromUri, new_uri, false); DatabaseTrackInfo copied_track = new DatabaseTrackInfo(track); copied_track.PrimarySource = this; copied_track.Uri = new_uri; // Write the metadata in db to the file on the DAP if it has changed since file was modified // to ensure that when we load it next time, it's data will match what's in the database // and the MetadataHash will actually match. We do this by comparing the time // stamps on files for last update of the db metadata vs the sync to file. // The equals on the inequality below is necessary for podcasts who often have a sync and // update time that are the same to the second, even though the album metadata has changed in the // DB to the feedname instead of what is in the file. It should be noted that writing the metadata // is a small fraction of the total copy time anyway. if (track.LastSyncedStamp >= Hyena.DateTimeUtil.ToDateTime(track.FileModifiedStamp)) { Log.DebugFormat("Copying Metadata to File Since Sync time >= Updated Time"); bool write_metadata = Metadata.SaveTrackMetadataService.WriteMetadataEnabled.Value; bool write_ratings = Metadata.SaveTrackMetadataService.WriteRatingsEnabled.Value; bool write_playcounts = Metadata.SaveTrackMetadataService.WritePlayCountsEnabled.Value; Banshee.Streaming.StreamTagger.SaveToFile(copied_track, write_metadata, write_ratings, write_playcounts); } copied_track.Save(false); } if (CoverArtSize > -1 && !String.IsNullOrEmpty(CoverArtFileType) && !String.IsNullOrEmpty(CoverArtFileName) && (FolderDepth == -1 || FolderDepth > 0)) { SafeUri cover_uri = new SafeUri(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(new_uri.LocalPath), CoverArtFileName)); string coverart_id = track.ArtworkId; if (!File.Exists(cover_uri) && CoverArtSpec.CoverExists(coverart_id)) { if (CoverArtFileType == "jpg" || CoverArtFileType == "jpeg") { SafeUri local_cover_uri = new SafeUri(Banshee.Base.CoverArtSpec.GetPath(coverart_id)); Banshee.IO.File.Copy(local_cover_uri, cover_uri, false); } else { Gdk.Pixbuf pic = null; try { byte[] bytes = null; ThreadAssist.BlockingProxyToMain(() => { pic = artwork_manager.LookupScalePixbuf(coverart_id, CoverArtSize); bytes = pic.SaveToBuffer(CoverArtFileType); }); if (bytes != null) { System.IO.Stream cover_art_file = File.OpenWrite(cover_uri, true); cover_art_file.Write(bytes, 0, bytes.Length); cover_art_file.Close(); } else { Log.Error("Cover art {0} had no bytes", coverart_id); } } catch (GLib.GException) { Log.DebugFormat("Could not convert cover art to {0}, unsupported filetype?", CoverArtFileType); } finally { Banshee.Collection.Gui.ArtworkManager.DisposePixbuf(pic); } } } } }
/// <summary> /// Constructor -- creates a new temporary LiveRadio Plugin source and sets itself as the plugin's source /// Any tracks that have remained in the source from a previous (interrupted) session are purged /// </summary> /// <param name="plugin"> /// A <see cref="ILiveRadioPlugin"/> -- the plugin the source is created for /// </param> public LiveRadioPluginSource(ILiveRadioPlugin plugin) : base(AddinManager.CurrentLocalizer.GetString("LiveRadioPlugin") + plugin.Name, plugin.Name, "live-radio-plugin-" + plugin.Name.ToLower(), sort_order) { TypeUniqueId = "live-radio-" + plugin.Name; IsLocal = false; Gdk.Pixbuf icon = new Gdk.Pixbuf(System.Reflection.Assembly.GetExecutingAssembly() .GetManifestResourceStream("LiveRadioIcon.svg")); SetIcon(icon); plugin.SetLiveRadioPluginSource(this); this.plugin = plugin; AfterInitialized(); Properties.Set <bool> ("Nereid.SourceContentsPropagate", true); Properties.SetString("TrackView.ColumnControllerXml", String.Format(@" <column-controller> <!--<column modify-default=""IndicatorColumn""> <renderer type=""Banshee.Podcasting.Gui.ColumnCellPodcastStatusIndicator"" /> </column>--> <add-default column=""IndicatorColumn"" /> <add-default column=""GenreColumn"" /> <column modify-default=""GenreColumn""> <visible>false</visible> </column> <add-default column=""TitleColumn"" /> <column modify-default=""TitleColumn""> <title>{0}</title> <long-title>{0}</long-title> </column> <add-default column=""ArtistColumn"" /> <column modify-default=""ArtistColumn""> <title>{1}</title> <long-title>{1}</long-title> </column> <add-default column=""CommentColumn"" /> <column modify-default=""CommentColumn""> <title>{2}</title> <long-title>{2}</long-title> </column> <add-default column=""RatingColumn"" /> <add-default column=""PlayCountColumn"" /> <add-default column=""LastPlayedColumn"" /> <add-default column=""LastSkippedColumn"" /> <add-default column=""DateAddedColumn"" /> <add-default column=""UriColumn"" /> <sort-column direction=""asc"">genre</sort-column> </column-controller>", AddinManager.CurrentLocalizer.GetString("Station"), AddinManager.CurrentLocalizer.GetString("Creator"), AddinManager.CurrentLocalizer.GetString("Description") )); ServiceManager.PlayerEngine.TrackIntercept += OnPlayerEngineTrackIntercept; TrackEqualHandler = delegate(DatabaseTrackInfo a, TrackInfo b) { RadioTrackInfo radio_track = b as RadioTrackInfo; return(radio_track != null && DatabaseTrackInfo.TrackEqual(radio_track.ParentTrack as DatabaseTrackInfo, a)); }; source_contents = new LiveRadioPluginSourceContents(plugin); source_contents.SetSource(this); Properties.Set <ISourceContents> ("Nereid.SourceContents", source_contents); this.PurgeTracks(); }
/// <summary> /// Parses the response to a query request and fills the results cache /// </summary> /// <param name="xml_response"> /// A <see cref="XmlDocument"/> -- the XML document containing the response to the query request /// </param> /// <param name="request_type"> /// A <see cref="LiveRadioRequestType"/> -- the type of the request /// </param> /// <param name="query"> /// A <see cref="System.String"/> -- the requested query, freetext or the genre name /// </param> private void ParseXmlResponse(XmlDocument xml_response, LiveRadioRequestType request_type, string query) { string tunein_url = ""; XmlNodeList XML_tunein_nodes = xml_response.GetElementsByTagName("tunein"); foreach (XmlNode node in XML_tunein_nodes) { XmlAttributeCollection xml_attributes = node.Attributes; try { tunein_url = xml_attributes.GetNamedItem("base").InnerText; break; } catch (Exception e) { Log.Warning("[ShoutCastPlugin] <ParseXmlResponse> ERROR: ", e); RaiseErrorReturned("XML Parse Error", e.Message); return; } } XmlNodeList XML_station_nodes = xml_response.GetElementsByTagName("station"); string key; if (request_type == LiveRadioRequestType.ByGenre) { key = "Genre:" + query; if (!cached_results.ContainsKey(key)) { cached_results[key] = new List <DatabaseTrackInfo> (XML_station_nodes.Count); } } else { key = query; if (!cached_results.ContainsKey(key)) { cached_results[key] = new List <DatabaseTrackInfo> (XML_station_nodes.Count); } } cached_results[key].Clear(); foreach (XmlNode node in XML_station_nodes) { XmlAttributeCollection xml_attributes = node.Attributes; try { string name = xml_attributes.GetNamedItem("name").InnerText; string media_type = xml_attributes.GetNamedItem("mt").InnerText; string id = xml_attributes.GetNamedItem("id").InnerText; string genre = xml_attributes.GetNamedItem("genre").InnerText; string now_playing = xml_attributes.GetNamedItem("ct").InnerText; string bitrate = xml_attributes.GetNamedItem("br").InnerText; int id_int; int bitrate_int; if (!Int32.TryParse(id.Trim(), out id_int)) { continue; //Something wrong with id, skip this } DatabaseTrackInfo new_station = new DatabaseTrackInfo(); new_station.Uri = new SafeUri(play_url + tunein_url + "?id=" + id); new_station.ArtistName = "www.shoutcast.com"; new_station.Genre = genre; new_station.TrackTitle = name; new_station.Comment = now_playing; new_station.AlbumTitle = now_playing; new_station.MimeType = media_type; new_station.ExternalId = id_int; new_station.PrimarySource = source; new_station.IsLive = true; Int32.TryParse(bitrate.Trim(), out bitrate_int); new_station.BitRate = bitrate_int; new_station.IsLive = true; cached_results[key].Add(new_station); } catch (Exception e) { Log.Warning("[ShoutCastPlugin] <ParseXmlResponse> ERROR: ", e); RaiseErrorReturned("XML Parse Error", e.Message); continue; } } }
private void MigrateLegacyIfNeeded() { if (DatabaseConfigurationClient.Client.Get <int> ("Podcast", "Version", 0) == 0) { if (ServiceManager.DbConnection.TableExists("Podcasts") && ServiceManager.DbConnection.Query <int> ("select count(*) from podcastsyndications") == 0) { Hyena.Log.Information("Migrating Podcast Feeds and Items"); ServiceManager.DbConnection.Execute(@" INSERT INTO PodcastSyndications (FeedID, Title, Url, Link, Description, ImageUrl, LastBuildDate, AutoDownload, IsSubscribed) SELECT PodcastFeedID, Title, FeedUrl, Link, Description, Image, strftime(""%s"", LastUpdated), SyncPreference, 1 FROM PodcastFeeds "); ServiceManager.DbConnection.Execute(@" INSERT INTO PodcastItems (ItemID, FeedID, Title, Link, PubDate, Description, Author, Active, Guid) SELECT PodcastID, PodcastFeedID, Title, Link, strftime(""%s"", PubDate), Description, Author, Active, Url FROM Podcasts "); // Note: downloaded*3 is because the value was 0 or 1, but is now 0 or 3 (FeedDownloadStatus.None/Downloaded) ServiceManager.DbConnection.Execute(@" INSERT INTO PodcastEnclosures (ItemID, LocalPath, Url, MimeType, FileSize, DownloadStatus) SELECT PodcastID, LocalPath, Url, MimeType, Length, Downloaded*3 FROM Podcasts "); // Finally, move podcast items from the Music Library to the Podcast source int [] primary_source_ids = new int [] { ServiceManager.SourceManager.MusicLibrary.DbId }; int moved = 0; foreach (FeedEnclosure enclosure in FeedEnclosure.Provider.FetchAllMatching("LocalPath IS NOT NULL AND LocalPath != ''")) { SafeUri uri = new SafeUri(enclosure.LocalPath); int track_id = DatabaseTrackInfo.GetTrackIdForUri(uri, primary_source_ids); if (track_id > 0) { PodcastTrackInfo pi = new PodcastTrackInfo(DatabaseTrackInfo.Provider.FetchSingle(track_id)); pi.Item = enclosure.Item; pi.Track.PrimarySourceId = source.DbId; pi.SyncWithFeedItem(); pi.Track.Save(false); moved++; } } if (moved > 0) { ServiceManager.SourceManager.MusicLibrary.Reload(); source.Reload(); } Hyena.Log.Information("Done Migrating Podcast Feeds and Items"); } DatabaseConfigurationClient.Client.Set <int> ("Podcast", "Version", 1); } if (DatabaseConfigurationClient.Client.Get <int> ("Podcast", "Version", 0) < 3) { // We were using the Link as the fallback if the actual Guid was missing, but that was a poor choice // since it is not always unique. We now use the title and pubdate combined. ServiceManager.DbConnection.Execute("UPDATE PodcastItems SET Guid = NULL"); foreach (FeedItem item in FeedItem.Provider.FetchAll()) { item.Guid = null; if (item.Feed == null || FeedItem.Exists(item.Feed.DbId, item.Guid)) { item.Delete(false); } else { item.Save(); } } DatabaseConfigurationClient.Client.Set <int> ("Podcast", "Version", 3); } // Intentionally skpping 4 here because this needs to get run again for anybody who ran it // before it was fixed, but only once if you never ran it if (DatabaseConfigurationClient.Client.Get <int> ("Podcast", "Version", 0) < 5) { ReplaceNewlines("CoreTracks", "Title"); ReplaceNewlines("CoreTracks", "TitleLowered"); ReplaceNewlines("PodcastItems", "Title"); ReplaceNewlines("PodcastItems", "Description"); DatabaseConfigurationClient.Client.Set <int> ("Podcast", "Version", 5); } // Initialize the new StrippedDescription field if (DatabaseConfigurationClient.Client.Get <int> ("Podcast", "Version", 0) < 6) { foreach (FeedItem item in FeedItem.Provider.FetchAll()) { item.UpdateStrippedDescription(); item.Save(); } DatabaseConfigurationClient.Client.Set <int> ("Podcast", "Version", 6); } }
/// <summary> /// Adds a track to is source. Does not actually set the tracks source. /// </summary> /// <param name="track"> /// A <see cref="DatabaseTrackInfo"/> -- the track to be added to its set source /// </param> public override void AddTrack(DatabaseTrackInfo track) { track.CanSaveToDatabase = false; track.PrimarySource = this; track.Save(); }
public override bool DeleteTrackHook(DatabaseTrackInfo track) { return(true); }
private void OnMerge(object o, EventArgs a) { var discs = library.BooksModel.SelectedItems.OrderBy(d => d.Title).ToList(); var author = DatabaseArtistInfo.Provider.FetchSingle((discs[0] as DatabaseAlbumInfo).ArtistId); var dialog = new HigMessageDialog( ServiceManager.Get <GtkElementsService> ().PrimaryWindow, DialogFlags.DestroyWithParent, MessageType.Question, ButtonsType.OkCancel, String.Format(Catalog.GetPluralString( "Merge the {0} selected discs into one book?", "Merge the {0} selected discs into one book?", discs.Count), discs.Count), Catalog.GetString( "This will ensure the disc numbers are all " + "set properly, and then set the author and book title for all tracks " + "on all these discs to the values below") ); var table = new SimpleTable <int> (); var author_entry = new Entry() { Text = discs[0].ArtistName }; table.AddRow(0, new Label(Catalog.GetString("Author:")) { Xalign = 0 }, author_entry ); var trimmings = new char [] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', '-' }; var title_entry = new Entry() { Text = discs[0].Title.Trim(trimmings) }; table.AddRow(1, new Label(Catalog.GetString("Book Title:")) { Xalign = 0 }, title_entry ); dialog.LabelVBox.PackStart(table, false, false, 0); dialog.ShowAll(); var response = dialog.Run(); string title = title_entry.Text; string author_name = author_entry.Text; dialog.Destroy(); if (response == (int)Gtk.ResponseType.Ok && !String.IsNullOrEmpty(title)) { if (author_name != author.Name) { author = DatabaseArtistInfo.FindOrCreate(author_name, null); } var book = DatabaseAlbumInfo.FindOrCreate(author, title, null, false); int disc_num = 1; foreach (DatabaseAlbumInfo disc in discs) { // Update the disc num/count field for all tracks on this 'book' (actually just one disc of a book) ServiceManager.DbConnection.Execute( @"UPDATE CoreTracks SET AlbumID = ?, Disc = ?, DiscCount = ?, DateUpdatedStamp = ? WHERE PrimarySourceID = ? AND AlbumID = ?", book.DbId, disc_num++, discs.Count, DateTime.Now, library.DbId, disc.DbId ); } // Update the MetadataHash for all those tracks DatabaseTrackInfo.UpdateMetadataHash( book.Title, author.Name, String.Format("PrimarySourceId = {0} AND AlbumID = {1}", library.DbId, book.DbId) ); library.NotifyTracksChanged(); } }
protected override void AddTrackToDevice(DatabaseTrackInfo track, SafeUri fromUri) { if (track.PrimarySourceId == DbId) { return; } lock (mtp_device) { Track mtp_track = TrackInfoToMtpTrack(track, fromUri); bool video = track.HasAttribute(TrackMediaAttributes.VideoStream); mtp_device.UploadTrack(fromUri.LocalPath, mtp_track, GetFolderForTrack(track), OnUploadProgress); // Add/update album art if (!video) { string key = MakeAlbumKey(track.AlbumArtist, track.AlbumTitle); if (!album_cache.ContainsKey(key)) { // LIBMTP 1.0.3 BUG WORKAROUND // In libmtp.c the 'LIBMTP_Create_New_Album' function invokes 'create_new_abstract_list'. // The latter calls strlen on the 'name' parameter without null checking. If AlbumTitle is // null, this causes a sigsegv. Lets be safe and always pass non-null values. Album album = new Album(mtp_device, track.AlbumTitle ?? "", track.AlbumArtist ?? "", track.Genre ?? "", track.Composer ?? ""); album.AddTrack(mtp_track); if (supports_jpegs && can_sync_albumart) { ArtworkManager art = ServiceManager.Get <ArtworkManager> (); Exception ex = null; Gdk.Pixbuf pic = null; byte[] bytes = null; uint width = 0, height = 0; ThreadAssist.BlockingProxyToMain(() => { try { pic = art.LookupScalePixbuf(track.ArtworkId, thumb_width); if (pic != null) { bytes = pic.SaveToBuffer("jpeg"); width = (uint)pic.Width; height = (uint)pic.Height; } } catch (Exception e) { ex = e; } }); try { if (ex != null) { throw ex; } if (bytes != null) { ArtworkManager.DisposePixbuf(pic); album.Save(bytes, width, height); album_cache [key] = album; } } catch (Exception e) { Log.Debug("Failed to create MTP Album", e.Message); } } else { album.Save(); album_cache[key] = album; } } else { Album album = album_cache[key]; album.AddTrack(mtp_track); album.Save(); } } MtpTrackInfo new_track = new MtpTrackInfo(mtp_device, mtp_track); new_track.PrimarySource = this; new_track.Save(false); track_map[new_track.TrackId] = mtp_track; } }
private void TryToFixNonMp3Metadata() { if (already_fixed || mp3_imported_tracks.Count != mp3_count || non_mp3_queue.Count <= 0) { return; } already_fixed = true; // FIXME: this is all pretty lame. Amazon doesn't have any metadata on the PDF // files, which is a shame. So I attempt to figure out the best common metadata // from the already imported tracks in the album, and then forcefully persist // this in the database. When Taglib# supports reading/writing PDF, we can // persist this back the the PDF file, and support it for importing like normal. var artist_name = MostCommon <TrackInfo, string> (mp3_imported_tracks, track => track.AlbumArtist) ?? MostCommon <TrackInfo, string> (mp3_imported_tracks, track => track.ArtistName); var album_title = MostCommon <TrackInfo, string> (mp3_imported_tracks, track => track.AlbumTitle); var genre = MostCommon <TrackInfo, string> (mp3_imported_tracks, track => track.Genre); var copyright = MostCommon <TrackInfo, string> (mp3_imported_tracks, track => track.Copyright); var year = MostCommon <TrackInfo, int> (mp3_imported_tracks, track => track.Year); var track_count = MostCommon <TrackInfo, int> (mp3_imported_tracks, track => track.TrackCount); var disc_count = MostCommon <TrackInfo, int> (mp3_imported_tracks, track => track.DiscCount); while (non_mp3_queue.Count > 0) { var downloader = non_mp3_queue.Dequeue(); var track = new DatabaseTrackInfo() { AlbumArtist = artist_name, ArtistName = artist_name, AlbumTitle = album_title, TrackTitle = downloader.Track.Title, TrackCount = track_count, DiscCount = disc_count, Year = year, Genre = genre, Copyright = copyright, Uri = new SafeUri(downloader.LocalPath), MediaAttributes = TrackMediaAttributes.ExternalResource, PrimarySource = ServiceManager.SourceManager.MusicLibrary }; track.CopyToLibraryIfAppropriate(true); if (downloader.FileExtension == "pdf") { track.MimeType = "application/pdf"; Application.Invoke(delegate { ServiceManager.DbConnection.BeginTransaction(); try { track.Save(); ServiceManager.DbConnection.CommitTransaction(); } catch { ServiceManager.DbConnection.RollbackTransaction(); throw; } }); } } }
private void SetCurrentTrack(DatabaseTrackInfo track) { enabled_cache.Clear(); current_track = track; }
protected override void LoadFromDevice() { // Translators: {0} is the file currently being loaded // and {1} is the total # of files that will be loaded. string format = Catalog.GetString("Reading File - {0} of {1}"); track_map = new Dictionary <long, Track> (); try { List <Track> files = null; lock (mtp_device) { files = mtp_device.GetAllTracks(delegate(ulong current, ulong total, IntPtr data) { SetStatus(String.Format(format, current + 1, total), false); return(0); }); } /*if (user_event.IsCancelRequested) { * return; * }*/ // Delete any empty albums lock (mtp_device) { foreach (Album album in mtp_device.GetAlbums()) { if (album.Count == 0) { album.Remove(); } } } // Translators: {0} is the track currently being loaded // and {1} is the total # of tracks that will be loaded. format = Catalog.GetString("Loading Track - {0} of {1}"); for (int current = 0, total = files.Count; current < total; ++current) { SetStatus(String.Format(format, current + 1, total), false); Track mtp_track = files [current]; long track_id; if ((track_id = DatabaseTrackInfo.GetTrackIdForUri(MtpTrackInfo.GetPathFromMtpTrack(mtp_track), DbId)) > 0) { track_map[track_id] = mtp_track; } else { MtpTrackInfo track = new MtpTrackInfo(mtp_device, mtp_track); track.PrimarySource = this; track.Save(false); track_map[track.TrackId] = mtp_track; } } Hyena.Data.Sqlite.HyenaSqliteCommand insert_cmd = new Hyena.Data.Sqlite.HyenaSqliteCommand( @"INSERT INTO CorePlaylistEntries (PlaylistID, TrackID) SELECT ?, TrackID FROM CoreTracks WHERE PrimarySourceID = ? AND ExternalID = ?"); // Translators: {0} is the playlist currently being loaded // and {1} is the total # of playlists that will be loaded. format = Catalog.GetString("Loading Playlist - {0} of {1}"); lock (mtp_device) { var playlists = mtp_device.GetPlaylists(); if (playlists != null) { for (int current = 0, total = playlists.Count; current < total; ++current) { MTP.Playlist playlist = playlists [current]; SetStatus(String.Format(format, current + 1, total), false); Track mtp_track = files [current]; PlaylistSource pl_src = new PlaylistSource(playlist.Name, this); pl_src.Save(); // TODO a transaction would make sense here (when the threading issue is fixed) foreach (uint id in playlist.TrackIds) { ServiceManager.DbConnection.Execute(insert_cmd, pl_src.DbId, this.DbId, id); } pl_src.UpdateCounts(); AddChildSource(pl_src); } } } } catch (Exception e) { Log.Error(e); } OnTracksAdded(); }
public void EnqueueUri(string uri, bool prepend) { EnqueueId(DatabaseTrackInfo.GetTrackIdForUri(uri), prepend, false); }
public void Add(DatabaseTrackInfo track) { AddTrack(track); }
protected override void LoadFromDevice() { track_map = new Dictionary <int, Track> (); try { List <Track> files = null; lock (mtp_device) { files = mtp_device.GetAllTracks(delegate(ulong current, ulong total, IntPtr data) { //user_event.Progress = (double)current / total; // Translators: {0} is the name of the MTP audio device (eg Gabe's Zen Player), {1} is the // track currently being loaded, and {2} is the total # of tracks that will be loaded. SetStatus(String.Format(Catalog.GetString("Loading {0} - {1} of {2}"), Name, current, total), false); return(0); }); } /*if (user_event.IsCancelRequested) { * return; * }*/ // Delete any empty albums lock (mtp_device) { foreach (Album album in mtp_device.GetAlbums()) { if (album.Count == 0) { album.Remove(); } } } foreach (Track mtp_track in files) { int track_id; if ((track_id = DatabaseTrackInfo.GetTrackIdForUri(MtpTrackInfo.GetPathFromMtpTrack(mtp_track), DbId)) > 0) { track_map[track_id] = mtp_track; } else { MtpTrackInfo track = new MtpTrackInfo(mtp_device, mtp_track); track.PrimarySource = this; track.Save(false); track_map[track.TrackId] = mtp_track; } } Hyena.Data.Sqlite.HyenaSqliteCommand insert_cmd = new Hyena.Data.Sqlite.HyenaSqliteCommand( @"INSERT INTO CorePlaylistEntries (PlaylistID, TrackID) SELECT ?, TrackID FROM CoreTracks WHERE PrimarySourceID = ? AND ExternalID = ?"); lock (mtp_device) { var playlists = mtp_device.GetPlaylists(); if (playlists != null) { foreach (MTP.Playlist playlist in playlists) { PlaylistSource pl_src = new PlaylistSource(playlist.Name, this); pl_src.Save(); // TODO a transaction would make sense here (when the threading issue is fixed) foreach (uint id in playlist.TrackIds) { ServiceManager.DbConnection.Execute(insert_cmd, pl_src.DbId, this.DbId, id); } pl_src.UpdateCounts(); AddChildSource(pl_src); } } } } catch (Exception e) { Log.Exception(e); } OnTracksAdded(); }
private string GetTrackArtworkId(DatabaseTrackInfo track) { return(PodcastService.ArtworkIdFor(PodcastTrackInfo.From(track).Feed)); }
private object GetPodcastInfoObject(DatabaseTrackInfo track) { return(new PodcastTrackInfo(track)); }