private void DeleteEmptyDirectory(GLib.File directory) { // if the directory we're dealing with is not in the // F-Spot photos directory, don't delete anything, // even if it is empty string photo_uri = SafeUri.UriToFilename(Global.PhotoUri.ToString()); bool path_matched = directory.Path.IndexOf(photo_uri) > -1; if (directory.Path.Equals(photo_uri) || !path_matched) { return; } if (DirectoryIsEmpty(directory)) { try { Log.DebugFormat("Removing empty directory: {0}", directory.Path); directory.Delete(); } catch (GLib.GException e) { // silently log the exception, but don't re-throw it // as to not annoy the user Log.Exception(e); } // check to see if the parent is empty DeleteEmptyDirectory(directory.Parent); } }
[Test] // https://bugzilla.gnome.org/show_bug.cgi?id=722731 public void TestThatInvalidTracksShouldNotBecomeCurrentTrack() { var a_valid_track = "A_boy.ogg"; var a_valid_uri = new SafeUri(Paths.Combine(TestsDir, "data", a_valid_track)); var a_track_that_doesnt_exit = "this_does_not_exist_in_the_data_folder.ogg"; var an_invalid_track = new SafeUri(Paths.Combine(TestsDir, "data", a_track_that_doesnt_exit)); TrackInfo current_track = null; WaitUntil(PlayerEvent.Error, () => { service.Open(a_valid_uri); current_track = service.CurrentTrack; Assert.IsNotNull(current_track); Assert.IsTrue(current_track.Uri.AbsolutePath.EndsWith(a_valid_track)); service.SetNextTrack(an_invalid_track); service.Play(); }); WaitUntil(PlayerEvent.StartOfStream, () => { service.Open(a_valid_uri); service.Play(); }); current_track = service.CurrentTrack; Assert.IsNotNull(current_track); var actual_filename = System.IO.Path.GetFileName(SafeUri.UriToFilename(current_track.Uri)); Assert.AreEqual(a_valid_track, actual_filename); }
private void OnImportFinished(object o, EventArgs args) { importer.Finished -= OnImportFinished; if (CanSyncPlaylists) { var insert_cmd = new Hyena.Data.Sqlite.HyenaSqliteCommand( "INSERT INTO CorePlaylistEntries (PlaylistID, TrackID) VALUES (?, ?)"); foreach (string playlist_path in PlaylistFiles) { // playlist_path has a file:// prefix, and GetDirectoryName messes it up, // so we need to convert it to a regular path string base_folder = ms_device.RootPath != null ? BaseDirectory : System.IO.Path.GetDirectoryName(SafeUri.UriToFilename(playlist_path)); IPlaylistFormat loaded_playlist = PlaylistFileUtil.Load(playlist_path, new Uri(base_folder), ms_device.RootPath); if (loaded_playlist == null) { continue; } string name = System.IO.Path.GetFileNameWithoutExtension(SafeUri.UriToFilename(playlist_path)); PlaylistSource playlist = new PlaylistSource(name, this); playlist.Save(); //Hyena.Data.Sqlite.HyenaSqliteCommand.LogAll = true; foreach (PlaylistElement element in loaded_playlist.Elements) { string track_path = element.Uri.LocalPath; long track_id = DatabaseTrackInfo.GetTrackIdForUri(new SafeUri(track_path), DbId); if (track_id == 0) { Log.DebugFormat("Failed to find track {0} in DAP library to load it into playlist {1}", track_path, playlist_path); } else { ServiceManager.DbConnection.Execute(insert_cmd, playlist.DbId, track_id); } } //Hyena.Data.Sqlite.HyenaSqliteCommand.LogAll = false; playlist.UpdateCounts(); AddChildSource(playlist); } } import_reset_event.Set(); }
protected override void OnImportRequested(string path) { try { DatabaseTrackInfo track = ImportTrack(path); if (track != null && track.TrackId > 0) { UpdateProgress(String.Format("{0} - {1}", track.DisplayArtistName, track.DisplayTrackTitle)); } else { UpdateProgress(null); } OnImportResult(track, path, null); } catch (Exception e) { LogError(SafeUri.UriToFilename(path), e); UpdateProgress(null); OnImportResult(null, path, e); } }
public bool CopyToLibraryIfAppropriate(bool force_copy) { bool copy_success = true; LibrarySource library_source = PrimarySource as LibrarySource; if (library_source == null) { // Get out, not a local Library return(false); } SafeUri old_uri = this.Uri; if (old_uri == null) { // Get out quick, no URI set yet. return(copy_success); } bool in_library = old_uri.IsLocalPath ? old_uri.AbsolutePath.StartsWith(PrimarySource.BaseDirectoryWithSeparator) : false; if (!in_library && ((library_source.HasCopyOnImport && library_source.CopyOnImport) || force_copy)) { string new_filename = PathPattern != null?PathPattern.BuildFull(PrimarySource.BaseDirectory, this, Path.GetExtension(old_uri.ToString())) : Path.Combine(PrimarySource.BaseDirectory, Path.GetFileName(SafeUri.UriToFilename(old_uri))); SafeUri new_uri = new SafeUri(new_filename); try { if (Banshee.IO.File.Exists(new_uri)) { if (Banshee.IO.File.GetSize(old_uri) == Banshee.IO.File.GetSize(new_uri)) { Hyena.Log.DebugFormat("Not copying {0} to library because there is already a file of same size at {1}", old_uri, new_uri); copy_success = false; return(copy_success); } else { string extension = Path.GetExtension(new_filename); string filename_no_ext = new_filename.Remove(new_filename.Length - extension.Length); int duplicate_index = 1; while (Banshee.IO.File.Exists(new_uri)) { new_filename = String.Format("{0} ({1}){2}", filename_no_ext, duplicate_index, extension); new_uri = new SafeUri(new_filename); duplicate_index++; } } } Banshee.IO.File.Copy(old_uri, new_uri, false); Uri = new_uri; } catch (Exception e) { Log.ErrorFormat("Exception copying into library: {0}", e); } } return(copy_success); }
private void ProcessSong(LibraryImportManager import_manager, XmlReader xml_reader) { data.total_processed++; var itunes_id = 0; var title = String.Empty; var title_sort = String.Empty; var genre = String.Empty; var artist = String.Empty; var artist_sort = String.Empty; var album_artist = String.Empty; var album_artist_sort = String.Empty; var composer = String.Empty; var album = String.Empty; var album_sort = String.Empty; var grouping = String.Empty; var year = 0; var rating = 0; var play_count = 0; var track_number = 0; var date_added = DateTime.Now; var last_played = DateTime.MinValue; SafeUri uri = null; using (xml_reader) { while (xml_reader.ReadToFollowing("key")) { xml_reader.Read(); string key = xml_reader.ReadContentAsString(); xml_reader.Read(); xml_reader.Read(); try { switch (key) { case "Track ID": itunes_id = Int32.Parse(xml_reader.ReadContentAsString()); break; case "Name": title = xml_reader.ReadContentAsString(); break; case "Sort Name": title_sort = xml_reader.ReadContentAsString(); break; case "Genre": genre = xml_reader.ReadContentAsString(); break; case "Artist": artist = xml_reader.ReadContentAsString(); break; case "Sort Artist": artist_sort = xml_reader.ReadContentAsString(); break; case "Album Artist": album_artist = xml_reader.ReadContentAsString(); break; case "Sort Album Artist": album_artist_sort = xml_reader.ReadContentAsString(); break; case "Composer": composer = xml_reader.ReadContentAsString(); break; case "Album": album = xml_reader.ReadContentAsString(); break; case "Sort Album": album_sort = xml_reader.ReadContentAsString(); break; case "Grouping": grouping = xml_reader.ReadContentAsString(); break; case "Year": year = Int32.Parse(xml_reader.ReadContentAsString()); break; case "Rating": rating = Int32.Parse(xml_reader.ReadContentAsString()) / 20; break; case "Play Count": play_count = Int32.Parse(xml_reader.ReadContentAsString()); break; case "Track Number": track_number = Int32.Parse(xml_reader.ReadContentAsString()); break; case "Date Added": date_added = DateTime.Parse(xml_reader.ReadContentAsString(), DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal); break; case "Play Date UTC": last_played = DateTime.Parse(xml_reader.ReadContentAsString(), DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal); break; case "Location": uri = ConvertToLocalUri(xml_reader.ReadContentAsString()); break; } } catch { } } } if (uri == null) { return; } UpdateUserJob(data.total_processed, data.total_songs, artist, title); try { DatabaseTrackInfo track = import_manager.ImportTrack(uri); if (track == null) { LogError(SafeUri.UriToFilename(uri), Catalog.GetString("Unable to import song.")); return; } if (!String.IsNullOrEmpty(title)) { track.TrackTitle = title; } if (!String.IsNullOrEmpty(title_sort)) { track.TrackTitleSort = title_sort; } if (!String.IsNullOrEmpty(artist)) { track.ArtistName = artist; } if (!String.IsNullOrEmpty(artist_sort)) { track.ArtistNameSort = artist_sort; } if (!String.IsNullOrEmpty(genre)) { track.Genre = genre; } if (!String.IsNullOrEmpty(album_artist)) { track.AlbumArtist = album_artist; } if (!String.IsNullOrEmpty(album_artist_sort)) { track.AlbumArtistSort = album_artist_sort; } if (!String.IsNullOrEmpty(composer)) { track.Composer = composer; } if (!String.IsNullOrEmpty(album)) { track.AlbumTitle = album; } if (!String.IsNullOrEmpty(album_sort)) { track.AlbumTitleSort = album_sort; } if (!String.IsNullOrEmpty(grouping)) { track.Grouping = grouping; } if (year > 0) { track.Year = year; } if (data.get_ratings && rating > 0 && rating <= 5) { track.Rating = rating; } if (data.get_stats && play_count > 0) { track.PlayCount = play_count; } if (track_number > 0) { track.TrackNumber = track_number; } if (data.get_stats) { track.DateAdded = date_added; } if (data.get_stats && last_played > DateTime.MinValue) { track.LastPlayed = last_played; } data.track_ids.Add(itunes_id, track.TrackId); track.Save(false); } catch (Exception e) { LogError(SafeUri.UriToFilename(uri), e); } }
protected override void ImportCore() { LibraryImportManager import_manager = ServiceManager.Get <LibraryImportManager> (); HyenaSqliteConnection conn; try { conn = new HyenaSqliteConnection(amarok_db_path); } catch (Exception e) { LogError(amarok_db_path, String.Format( "Unable to open Amarok database: {0}", e.Message)); return; } int count = 0; try { count = conn.Query <int> ("SELECT COUNT(*) FROM tags"); } catch (Exception) {} try { HyenaSqliteCommand cmd = new HyenaSqliteCommand(@" SELECT DISTINCT NULL, tags.url, tags.title, artist.name, genre.name, album.name, year.name, tags.track, tags.length FROM tags, artist, album, genre, year WHERE tags.deviceid = -1 AND tags.artist = artist.id AND tags.album = album.id AND tags.genre = genre.id AND tags.year = year.id" ); HyenaSqliteCommand stats_cmd = new HyenaSqliteCommand(@" SELECT DISTINCT (rating+rating%2)/2, playcounter, createdate, accessdate FROM statistics WHERE url = ? AND deviceid = -1"); int processed = 0; IDataReader reader = conn.Query(cmd); while (reader.Read()) { if (CheckForCanceled()) { break; } processed++; try { string path = (string)reader[1]; SafeUri uri = null; if (path.StartsWith("./")) { uri = new SafeUri(path.Substring(1)); } else if (path.StartsWith("/")) { uri = new SafeUri(path); } else { continue; } string title = (string)reader[2]; string artist = (string)reader[3]; //Console.WriteLine ("Amarok import has {0}/{1} - {2}", artist, title, uri); // the following fields are not critical and can be skipped if something goes wrong int rating = 0, playcount = 0; long created = 0, accessed = 0; // Try to read stats try { IDataReader stats_reader = conn.Query(stats_cmd, path); while (stats_reader.Read()) { rating = Convert.ToInt32(stats_reader[0]); playcount = Convert.ToInt32(stats_reader[1]); created = Convert.ToInt64(stats_reader[2]); accessed = Convert.ToInt64(stats_reader[3]); } stats_reader.Dispose(); } catch (Exception) {} UpdateUserJob(processed, count, artist, title); try { DatabaseTrackInfo track = import_manager.ImportTrack(uri); if (track == null) { throw new Exception(String.Format(Catalog.GetString("Unable to import track: {0}"), uri.AbsoluteUri)); } if (rating > 0 || playcount > 0 || created > 0 || accessed > 0) { track.Rating = rating; track.PlayCount = playcount; if (created > 0) { track.DateAdded = Hyena.DateTimeUtil.FromTimeT(created); } if (accessed > 0) { track.LastPlayed = Hyena.DateTimeUtil.FromTimeT(accessed); } track.Save(false); } } catch (Exception e) { LogError(SafeUri.UriToFilename(uri), e); } } catch (Exception e) { Hyena.Log.Exception(e); // something went wrong, skip entry } } reader.Dispose(); import_manager.NotifyAllSources(); // TODO migrating more than the podcast subscriptions (eg whether to auto sync them etc) means 1) we need to have those features // and 2) we need to depend on Migo and/or the Podcast extension DBusCommandService cmd_service = ServiceManager.Get <DBusCommandService> (); if (cmd_service != null && ServiceManager.DbConnection.TableExists("PodcastSyndications")) { foreach (string podcast_url in conn.QueryEnumerable <string> ("SELECT url FROM podcastchannels")) { cmd_service.PushFile(podcast_url.Replace("http:", "feed:")); } } } catch (Exception e) { Hyena.Log.Exception(e); LogError(amarok_db_path, Catalog.GetString("Importing from Amarok failed")); } finally { conn.Dispose(); } }
protected override void ImportCore() { LibraryImportManager import_manager = ServiceManager.Get <LibraryImportManager> (); SafeUri db_uri = rhythmbox_db_uri; // Check if library is located in the old place (.gnome2/rhythmbox/rhythmdb.db) if (!Banshee.IO.File.Exists(rhythmbox_db_uri)) { db_uri = rhythmbox_db_uri_old; } if (!IsValidXmlDocument(db_uri)) { LogError(SafeUri.UriToFilename(db_uri), "Rhythmbox library is corrupted."); return; } // Load Rhythmbox library Stream stream_db = Banshee.IO.File.OpenRead(db_uri); XmlDocument xml_doc_db = new XmlDocument(); xml_doc_db.Load(stream_db); XmlElement db_root = xml_doc_db.DocumentElement; stream_db.Close(); if (db_root == null || !db_root.HasChildNodes || db_root.Name != "rhythmdb") { LogError(SafeUri.UriToFilename(db_uri), "Unable to open Rhythmbox library."); return; } count = db_root.ChildNodes.Count; processed = 0; // Import Rhythmbox playlists if playlist file is available SafeUri rhythmbox_playlists_uri = new SafeUri(Hyena.Paths.Combine( Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".local", "share", "rhythmbox", "playlists.xml" )); bool playlists_available = Banshee.IO.File.Exists(rhythmbox_playlists_uri); // Look at the old location too if (!playlists_available) { rhythmbox_playlists_uri = new SafeUri(Hyena.Paths.Combine( Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".gnome2", "rhythmbox", "playlists.xml" )); playlists_available = Banshee.IO.File.Exists(rhythmbox_playlists_uri); } XmlElement playlists_root = null; if (playlists_available) { if (IsValidXmlDocument(rhythmbox_playlists_uri)) { Stream stream_playlists = Banshee.IO.File.OpenRead(rhythmbox_playlists_uri); XmlDocument xml_doc_playlists = new XmlDocument(); xml_doc_playlists.Load(stream_playlists); playlists_root = xml_doc_playlists.DocumentElement; stream_playlists.Close(); if (playlists_root == null || !playlists_root.HasChildNodes || playlists_root.Name != "rhythmdb-playlists") { playlists_available = false; } else { count += playlists_root.ChildNodes.Count; } } else { LogError(SafeUri.UriToFilename(rhythmbox_playlists_uri), "Rhythmbox playlists are corrupted."); playlists_available = false; } } ImportSongs(import_manager, db_root.SelectNodes("/rhythmdb/entry[@type='song']")); //ImportPodcasts (import_manager, db_root.SelectNodes ("/rhythmdb/entry[@type='podcast-post']")); if (playlists_available) { ImportStaticPlaylists(playlists_root.SelectNodes("/rhythmdb-playlists/playlist[@type='static']")); } import_manager.NotifyAllSources(); }
private void ImportSongs(LibraryImportManager manager, XmlNodeList songs) { foreach (XmlElement song in songs) { if (CheckForCanceled()) { break; } processed++; string title = String.Empty, genre = String.Empty, artist = String.Empty, album = String.Empty; int year = 0, rating = 0, play_count = 0, track_number = 0; DateTime date_added = DateTime.Now, last_played = DateTime.MinValue; SafeUri uri = null; foreach (XmlElement child in song.ChildNodes) { if (child == null || child.InnerText == null || child.InnerText == String.Empty) { continue; } try { switch (child.Name) { case "title": title = child.InnerText; break; case "genre": genre = child.InnerText; break; case "artist": artist = child.InnerText; break; case "album": album = child.InnerText; break; case "track-number": track_number = Int32.Parse(child.InnerText); break; case "location": uri = new SafeUri(child.InnerText); break; case "date": if (child.InnerText != "0") { year = (new DateTime(1, 1, 1).AddDays(Double.Parse(child.InnerText))).Year; } break; case "rating": rating = Int32.Parse(child.InnerText); break; case "play-count": play_count = Int32.Parse(child.InnerText); break; case "last-played": last_played = Hyena.DateTimeUtil.ToDateTime(Int64.Parse(child.InnerText)); break; case "first-seen": date_added = Hyena.DateTimeUtil.ToDateTime(Int64.Parse(child.InnerText));; break; } } catch (Exception) { // parsing InnerText failed } } if (uri == null) { continue; } UpdateUserJob(processed, count, artist, title); try { DatabaseTrackInfo track = manager.ImportTrack(uri); if (track == null) { LogError(SafeUri.UriToFilename(uri), Catalog.GetString("Unable to import song.")); continue; } track.TrackTitle = title; track.ArtistName = artist; track.Genre = genre; track.AlbumTitle = album; track.TrackNumber = track_number; track.Year = year; track.DateAdded = date_added; track.Rating = (rating >= 0 && rating <= 5) ? rating : 0; track.PlayCount = (play_count >= 0) ? play_count : 0; track.LastPlayed = last_played; track.Save(false); } catch (Exception e) { LogError(SafeUri.UriToFilename(uri), e); } } }
private void onStartSync(object o, EventArgs args) { Hyena.Log.Debug("Start of Sync triggered!"); var options = View.GetOptions(); // target directory to copy to Hyena.Log.DebugFormat("Target folder is set to: {0}", options.TargetFolder); // count all files for progress bar int totalFiles = 0; foreach (var playlist in options.SelectedPlaylists) { totalFiles += playlist.Tracks.Count(); } View.Progress.Text = AddinManager.CurrentLocalizer.GetString("Preparing sync"); var progress_step = 1f / totalFiles; var current_progress = 0f; // begin sync worker thread ThreadStart syncStart = delegate() { Hyena.Log.Debug("Sync thread started!"); // foreach playlist foreach (var playlist in options.SelectedPlaylists) { Stream m3u_stream = null; StreamWriter m3u_writer = null; if (options.CreateM3u) { var m3u_fileUri = new StringBuilder().Append(options.TargetFolder) .Append(Path.DirectorySeparatorChar).Append(playlist.Name) .Append(".m3u").ToString(); m3u_stream = Banshee.IO.File.OpenWrite(new SafeUri(m3u_fileUri), true); Log.DebugFormat("opened m3u playlist for writing: {0}", m3u_fileUri); m3u_writer = new StreamWriter(m3u_stream, System.Text.Encoding.UTF8); } // for each contained file foreach (var track in playlist.Tracks) { // get filename part of path var dest_path_suffix = track.GetFilepathSuffix(options.SubfolderDepth); // we dont want %20 etc. in the m3u since some android devices delete // playlists with that encoding in it (i.e. galaxy S) Hyena.Log.DebugFormat("filename for m3u file is {0}", dest_path_suffix); // assemble new Uri of target track var destUri = new SafeUri(new StringBuilder().Append(options.TargetFolder) .Append(Path.DirectorySeparatorChar) .Append(dest_path_suffix).ToString()); // create subfolders if necessary string dest_path = options.TargetFolder; var folders = track.GetSubdirectories(options.SubfolderDepth); try { for (int i = 0; i < folders.Count(); i++) { dest_path += folders [i] + "/"; Hyena.Log.DebugFormat("creating folder {0}", dest_path); if (!Banshee.IO.Directory.Exists(dest_path)) { Banshee.IO.Directory.Create(new SafeUri(dest_path)); } } } catch { // folder creation failed, this is fatal, stop // TODO display a error popup break; } // copy file to selected folder try { var destExists = Banshee.IO.File.Exists(destUri); if (options.OverwriteExisting || !destExists) { if (options.CreateSymLinks) { var trackFilePath = SafeUri.UriToFilename(track.Uri); var destFilePath = SafeUri.UriToFilename(destUri); if (track.Uri.IsLocalPath) { var target = new UnixFileInfo(trackFilePath); // symbolic links need manual deletion, // otherwise an exception is thrown in CreateSymbolicLink() if (destExists) { var dest = new UnixFileInfo(destFilePath); dest.Delete(); } target.CreateSymbolicLink(destFilePath); } else { Hyena.Log.ErrorFormat("Cannot create symlink to remote path {0} in {1}, skipping", track.Uri, destFilePath); } } else { Banshee.IO.File.Copy(track.Uri, destUri, true); } Hyena.Log.DebugFormat("Copying {0} to {1}", track.Uri, destUri); } else { Hyena.Log.Debug("Not overwriting existing file {0}", destUri); } } catch { Hyena.Log.ErrorFormat("Error copying file {0} to {1}, skipping", track.Uri, destUri); } // increment the progressbar current_progress += progress_step; if (current_progress > 1.0f) { current_progress = 1.0f; } Gtk.Application.Invoke(delegate { View.Progress.Fraction = current_progress; View.Progress.Text = AddinManager.CurrentLocalizer.GetString("Copying") + " " + track.Filepath; Gtk.Main.IterationDo(false); }); if (options.CreateM3u) { m3u_writer.Write(track.CreateM3uEntry(options.SubfolderDepth)); } } // close the m3u file before processing next playlist if (options.CreateM3u) { Hyena.Log.Debug("closing m3u filedescriptor"); m3u_writer.Close(); m3u_writer.Dispose(); } Hyena.Log.Debug("sync process finished"); } Gtk.Application.Invoke(delegate { View.Progress.Text = AddinManager.CurrentLocalizer.GetString("Done!"); View.Progress.Fraction = 1f; Gtk.Main.IterationDo(false); }); Hyena.Log.Debug("sync DONE, returning"); return; }; // end of sync worker thread syncThread = new Thread(syncStart); syncThread.Start(); return; }