banshee r4651 - in trunk/banshee: . src/Core/Banshee.Core src/Core/Banshee.Core/Banshee.IO src/Core/Banshee.Core/Banshee.Streaming src/Core/Banshee.Services/Banshee.Collection.Database src/Core/Banshee.Services/Banshee.Metadata.Embedded src/Core/Banshee.ThickClient/Banshee.Library.Gui src/Libraries/Hyena.Gui/Hyena.Gui



Author: gburt
Date: Fri Oct  3 20:34:53 2008
New Revision: 4651
URL: http://svn.gnome.org/viewvc/banshee?rev=4651&view=rev

Log:
2008-10-03  Gabriel Burt  <gabriel burt gmail com>

	This patch adds support for importing all white-listed file formats, even
	if TagLib# can't process them.  That includes mov, flv, mkv, divx, and
	more (BGO #524595).

	* src/Core/Banshee.ThickClient/Banshee.Library.Gui/FileImportSource.cs:
	Update to use new ExtensionSet class.

	* src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs:
	Use ExtensionSet class, move the IsWhiteListedFile check to the actual
	ImportTrack method because its public and we don't want API-consumers to
	be able to bypass the whitelist check.

	* src/Core/Banshee.Services/Banshee.Metadata.Embedded/EmbeddedQueryJob.cs:
	* src/Core/Banshee.Core/Banshee.Streaming/SaveTrackMetadataJob.cs:
	StreamTagger.ProcessUri will return null now if TagLib# can't process a
	file, instead of throwing an exception.  Adjust users of that method
	accordingly.

	* src/Core/Banshee.Core/Makefile.am:
	* src/Core/Banshee.Core/Banshee.Core.csproj:
	* src/Core/Banshee.Core/Banshee.IO/ExtensionSet.cs: New simple class that
	takes an array of strings/extensions and can tell you if a give file
	has one of the extensions in the set.

	* src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs: Catch TagLib#'s
	exceptions in ProcessUri and return null.  Change MergeTrackInfo to accept
	a null TagLib.File argument, and use a ExtensionSet of several video
	extensions that might not work in taglib#, so we can properly mark such
	files as videos.

	* src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs: Change GetFileFilter
	helper to take an IEnumerable<string> intead of a string array.



Added:
   trunk/banshee/src/Core/Banshee.Core/Banshee.IO/ExtensionSet.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Core/Banshee.Core/Banshee.Core.csproj
   trunk/banshee/src/Core/Banshee.Core/Banshee.Streaming/SaveTrackMetadataJob.cs
   trunk/banshee/src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs
   trunk/banshee/src/Core/Banshee.Core/Makefile.am
   trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Metadata.Embedded/EmbeddedQueryJob.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Library.Gui/FileImportSource.cs
   trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs

Modified: trunk/banshee/src/Core/Banshee.Core/Banshee.Core.csproj
==============================================================================
--- trunk/banshee/src/Core/Banshee.Core/Banshee.Core.csproj	(original)
+++ trunk/banshee/src/Core/Banshee.Core/Banshee.Core.csproj	Fri Oct  3 20:34:53 2008
@@ -99,6 +99,7 @@
     <Compile Include="Banshee.Collection\CacheableItem.cs" />
     <Compile Include="Banshee.IO\DirectoryScannerPipelineElement.cs" />
     <Compile Include="Banshee.Configuration\MemoryConfigurationClient.cs" />
+    <Compile Include="Banshee.IO\ExtensionSet.cs" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="Resources\contributors.xml">

Added: trunk/banshee/src/Core/Banshee.Core/Banshee.IO/ExtensionSet.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Core/Banshee.IO/ExtensionSet.cs	Fri Oct  3 20:34:53 2008
@@ -0,0 +1,63 @@
+//
+// ExtensionSet.cs
+//
+// Authors:
+//   Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2008 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+
+namespace Banshee.IO
+{
+    public class ExtensionSet
+    {
+        private string [] extensions;
+
+        public ExtensionSet (params string [] extensions)
+        {
+            this.extensions = extensions;
+            Array.Sort<string> (extensions);
+        }
+
+        public bool IsMatchingFile (string path)
+        {
+            if (String.IsNullOrEmpty (path)) {
+                return false;
+            }
+            
+            int index = path.LastIndexOf ('.');
+            if (index < 0 || index == path.Length || index == path.Length - 1) {
+                return false;
+            }
+            
+            return Array.BinarySearch<string> (extensions, 
+                path.Substring (index + 1).ToLower ()) >= 0;
+        }
+
+        public IEnumerable<string> List {
+            get { return extensions; }
+        }
+    }
+}

Modified: trunk/banshee/src/Core/Banshee.Core/Banshee.Streaming/SaveTrackMetadataJob.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Core/Banshee.Streaming/SaveTrackMetadataJob.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Core/Banshee.Streaming/SaveTrackMetadataJob.cs	Fri Oct  3 20:34:53 2008
@@ -63,6 +63,10 @@
         
             // Note: this should be kept in sync with the metadata read in StreamTagger.cs
             TagLib.File file = StreamTagger.ProcessUri (track.Uri);
+            if (file == null) {
+                return;
+            }
+            
             file.Tag.Performers = new string [] { track.ArtistName };
             file.Tag.Album = track.AlbumTitle;
             file.Tag.AlbumArtists = track.AlbumArtist == null ? new string [0] : new string [] {track.AlbumArtist};

Modified: trunk/banshee/src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Core/Banshee.Streaming/StreamTagger.cs	Fri Oct  3 20:34:53 2008
@@ -29,6 +29,7 @@
 using System;
 using System.Text.RegularExpressions;
 
+using Banshee.IO;
 using Banshee.Base;
 using Banshee.Collection;
 
@@ -36,17 +37,25 @@
 {
     public static class StreamTagger
     {
+        // This is a short list of video types that TagLib# might not support but that
+        // we want to make sure are recognized as videos
+        private static readonly ExtensionSet VideoExtensions = new ExtensionSet (
+            "avi", "divx", "dv", "f4p", "f4v", "flv", "m4v", "mkv", "mov", "ogv", "qt");
+        
         public static TagLib.File ProcessUri (SafeUri uri)
         {
-            TagLib.File file = Banshee.IO.DemuxVfs.OpenFile (uri.IsLocalPath ? uri.LocalPath : uri.AbsoluteUri, 
-                null, TagLib.ReadStyle.Average);
-
-            if ((file.Properties.MediaTypes & TagLib.MediaTypes.Audio) == 0 && 
-                (file.Properties.MediaTypes & TagLib.MediaTypes.Video) == 0) {
-                throw new TagLib.UnsupportedFormatException ("File does not contain video or audio");
+            try {
+                TagLib.File file = Banshee.IO.DemuxVfs.OpenFile (uri.IsLocalPath ? uri.LocalPath : uri.AbsoluteUri, 
+                    null, TagLib.ReadStyle.Average);
+    
+                if ((file.Properties.MediaTypes & TagLib.MediaTypes.Audio) == 0 && 
+                    (file.Properties.MediaTypes & TagLib.MediaTypes.Video) == 0) {
+                    throw new TagLib.UnsupportedFormatException ("File does not contain video or audio");
+                }
+                return file;
+            } catch (Exception) {
+                return null;
             }
-            
-            return file;
         }
 
         private static string Choose (string priority, string fallback)
@@ -109,41 +118,49 @@
             // Performers[] (track artists), AlbumArtists[], Composers[], Genres[]
 
             // Note: this should be kept in sync with the metadata written in SaveTrackMetadataJob.cs
-            track.Uri = new SafeUri (file.Name);
-            track.MimeType = file.MimeType;
+
+            if (file != null) {
+                track.Uri = new SafeUri (file.Name);
+                track.MimeType = file.MimeType;
+                track.BitRate  = file.Properties.AudioBitrate;
+                track.Duration = file.Properties.Duration;
+                
+                FindTrackMediaAttributes (track, file);
+    
+                track.ArtistName = Choose (file.Tag.JoinedPerformers, track.ArtistName, preferTrackInfo);
+                track.AlbumTitle = Choose (file.Tag.Album, track.AlbumTitle, preferTrackInfo);
+                track.AlbumArtist = Choose (file.Tag.FirstAlbumArtist, track.AlbumArtist, preferTrackInfo);
+                track.IsCompilation = IsCompilation (file.Tag);
+                
+                track.TrackTitle = Choose (file.Tag.Title, track.TrackTitle, preferTrackInfo);
+                track.Genre = Choose (file.Tag.FirstGenre, track.Genre, preferTrackInfo);
+                track.Composer = Choose (file.Tag.FirstComposer, track.Composer, preferTrackInfo);
+                track.Conductor = Choose (file.Tag.Conductor, track.Conductor, preferTrackInfo);
+                track.Grouping = Choose (file.Tag.Grouping, track.Grouping, preferTrackInfo);
+                track.Copyright = Choose (file.Tag.Copyright, track.Copyright, preferTrackInfo);
+                track.Comment = Choose (file.Tag.Comment, track.Comment, preferTrackInfo);
+    
+                track.TrackNumber = Choose ((int)file.Tag.Track, track.TrackNumber, preferTrackInfo);
+                track.TrackCount = Choose ((int)file.Tag.TrackCount, track.TrackCount, preferTrackInfo);
+                track.DiscNumber = Choose ((int)file.Tag.Disc, track.DiscNumber, preferTrackInfo);
+                track.DiscCount = Choose ((int)file.Tag.DiscCount, track.DiscCount, preferTrackInfo);
+                track.Year = Choose ((int)file.Tag.Year, track.Year, preferTrackInfo);
+                track.Bpm = Choose ((int)file.Tag.BeatsPerMinute, track.Bpm, preferTrackInfo);
+            } else {
+                track.MediaAttributes = TrackMediaAttributes.AudioStream;
+                if (VideoExtensions.IsMatchingFile (track.Uri.LocalPath)) {
+                    track.MediaAttributes = TrackMediaAttributes.VideoStream;
+                }
+            }
+
             track.FileSize = Banshee.IO.File.GetSize (track.Uri);
             track.FileModifiedStamp = Banshee.IO.File.GetModifiedTime (track.Uri);
             track.LastSyncedStamp = DateTime.Now;
-            track.BitRate  = file.Properties.AudioBitrate;
-            track.Duration = file.Properties.Duration;
-            
-            FindTrackMediaAttributes (track, file);
-
-            track.ArtistName = Choose (file.Tag.JoinedPerformers, track.ArtistName, preferTrackInfo);
-            track.AlbumTitle = Choose (file.Tag.Album, track.AlbumTitle, preferTrackInfo);
-            track.AlbumArtist = Choose (file.Tag.FirstAlbumArtist, track.AlbumArtist, preferTrackInfo);
-            track.IsCompilation = IsCompilation (file.Tag);
-            
-            track.TrackTitle = Choose (file.Tag.Title, track.TrackTitle, preferTrackInfo);
-            track.Genre = Choose (file.Tag.FirstGenre, track.Genre, preferTrackInfo);
-            track.Composer = Choose (file.Tag.FirstComposer, track.Composer, preferTrackInfo);
-            track.Conductor = Choose (file.Tag.Conductor, track.Conductor, preferTrackInfo);
-            track.Grouping = Choose (file.Tag.Grouping, track.Grouping, preferTrackInfo);
-            track.Copyright = Choose (file.Tag.Copyright, track.Copyright, preferTrackInfo);
-            track.Comment = Choose (file.Tag.Comment, track.Comment, preferTrackInfo);
-
-            track.TrackNumber = Choose ((int)file.Tag.Track, track.TrackNumber, preferTrackInfo);
-            track.TrackCount = Choose ((int)file.Tag.TrackCount, track.TrackCount, preferTrackInfo);
-            track.DiscNumber = Choose ((int)file.Tag.Disc, track.DiscNumber, preferTrackInfo);
-            track.DiscCount = Choose ((int)file.Tag.DiscCount, track.DiscCount, preferTrackInfo);
-            track.Year = Choose ((int)file.Tag.Year, track.Year, preferTrackInfo);
-            track.Bpm = Choose ((int)file.Tag.BeatsPerMinute, track.Bpm, preferTrackInfo);
 
             if (String.IsNullOrEmpty (track.TrackTitle)) {
                 try {
-                    string filename = System.IO.Path.GetFileName (track.Uri.LocalPath);
+                    string filename = System.IO.Path.GetFileNameWithoutExtension (track.Uri.LocalPath);
                     if (!String.IsNullOrEmpty (filename)) {
-                        filename = filename.Substring (0, filename.LastIndexOf ('.'));
                         track.TrackTitle = filename;
                     }
                 } catch {}

Modified: trunk/banshee/src/Core/Banshee.Core/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Banshee.Core/Makefile.am	(original)
+++ trunk/banshee/src/Core/Banshee.Core/Makefile.am	Fri Oct  3 20:34:53 2008
@@ -44,6 +44,7 @@
 	Banshee.IO/DemuxVfs.cs \
 	Banshee.IO/Directory.cs \
 	Banshee.IO/DirectoryScannerPipelineElement.cs \
+	Banshee.IO/ExtensionSet.cs \
 	Banshee.IO/File.cs \
 	Banshee.IO/IDemuxVfs.cs \
 	Banshee.IO/IDirectory.cs \

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseImportManager.cs	Fri Oct  3 20:34:53 2008
@@ -52,7 +52,7 @@
         // used to see if we should allow the file to be processed by TagLib. The
         // point is to rule out, at the path level, files that we won't support.
         
-        public static readonly string [] WhiteListFileExtensions = new string [] {
+        public static readonly Banshee.IO.ExtensionSet WhiteListFileExtensions = new Banshee.IO.ExtensionSet (
             "3g2",  "3gp",  "3gp2", "3gpp", "aac",  "ac3",  "aif",  "aifc", 
             "aiff", "al",   "alaw", "ape",  "asf",  "asx",  "au",   "avi", 
             "cda",  "cdr",  "divx", "dv",   "flac", "flv",  "gvi",  "gvp", 
@@ -65,26 +65,11 @@
             "u",    "vfw",  "vob",  "wav",  "wave", "wax",  "wm",   "wma",  
             "wmd",  "wmv",  "wmx",  "wv",   "wvc",  "wvx",  "yuv",  "f4v",  
             "f4a",  "f4b"
-        };
-
-        static DatabaseImportManager ()
-        {
-            Array.Sort<string> (WhiteListFileExtensions);
-        }
+        );
 
         public static bool IsWhiteListedFile (string path)
         {
-            if (String.IsNullOrEmpty (path)) {
-                return false;
-            }
-            
-            int index = path.LastIndexOf ('.');
-            if (index < 0 || index == path.Length || index == path.Length - 1) {
-                return false;
-            }
-            
-            return Array.BinarySearch<string> (WhiteListFileExtensions, 
-                path.Substring (index + 1).ToLower ()) >= 0;
+            return WhiteListFileExtensions.IsMatchingFile (path);
         }
 
         public delegate PrimarySource TrackPrimarySourceChooser (DatabaseTrackInfo track);
@@ -138,11 +123,6 @@
 
         protected override void OnImportRequested (string path)
         {
-            if (!IsWhiteListedFile (path)) {
-                UpdateProgress (null);
-                return;
-            }
-
             try {
                 DatabaseTrackInfo track = ImportTrack (path);
                 if (track != null && track.TrackId > 0) {
@@ -173,8 +153,11 @@
 
         public DatabaseTrackInfo ImportTrack (SafeUri uri)
         {
-            DatabaseTrackInfo track = null;
-            
+            if (!IsWhiteListedFile (uri.LocalPath)) {
+                UpdateProgress (null);
+                return null;
+            }
+
             if (DatabaseTrackInfo.ContainsUri (uri, Paths.MakePathRelative (uri.AbsolutePath, BaseDirectory) ?? uri.AbsoluteUri, PrimarySourceIds)) {
                 // TODO add DatabaseTrackInfo.SyncedStamp property, and if the file has been
                 // updated since the last sync, fetch its metadata into the db.
@@ -182,13 +165,16 @@
                 return null;
             }
 
+            DatabaseTrackInfo track = null;
+
             // TODO note, there is deadlock potential here b/c of locking of shared commands and blocking
             // because of transactions.  Needs to be fixed in HyenaDatabaseConnection.
             //ServiceManager.DbConnection.BeginTransaction ();
             try {
-                TagLib.File file = StreamTagger.ProcessUri (uri);
                 track = new DatabaseTrackInfo ();
-                StreamTagger.TrackInfoMerge (track, file);
+                track.Uri = uri;
+                StreamTagger.TrackInfoMerge (track, StreamTagger.ProcessUri (uri));
+                
                 track.PrimarySource = trackPrimarySourceChooser (track);
 
                 if (track.PrimarySource is Banshee.Library.LibrarySource) {

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Metadata.Embedded/EmbeddedQueryJob.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Metadata.Embedded/EmbeddedQueryJob.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Metadata.Embedded/EmbeddedQueryJob.cs	Fri Oct  3 20:34:53 2008
@@ -89,7 +89,7 @@
         protected IPicture [] GetEmbeddedPictures(SafeUri uri)
         {
             TagLib.File file = StreamTagger.ProcessUri(uri);            
-            return file.Tag.Pictures;            
+            return file == null ? null : file.Tag.Pictures;            
         }
         
         protected int GetPictureIndexToUse(IPicture [] pictures)

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Library.Gui/FileImportSource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Library.Gui/FileImportSource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Library.Gui/FileImportSource.cs	Fri Oct  3 20:34:53 2008
@@ -49,7 +49,7 @@
             
             chooser.AddButton (Stock.Cancel, ResponseType.Cancel);
             chooser.AddButton (Stock.Open, ResponseType.Ok);
-            chooser.AddFilter (Hyena.Gui.GtkUtilities.GetFileFilter (Catalog.GetString ("Media Files"), Banshee.Collection.Database.DatabaseImportManager.WhiteListFileExtensions));
+            chooser.AddFilter (Hyena.Gui.GtkUtilities.GetFileFilter (Catalog.GetString ("Media Files"), Banshee.Collection.Database.DatabaseImportManager.WhiteListFileExtensions.List));
             chooser.SelectMultiple = true;
             chooser.DefaultResponse = ResponseType.Ok;
             

Modified: trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs	Fri Oct  3 20:34:53 2008
@@ -64,7 +64,7 @@
             return true;
         }
         
-        public static FileFilter GetFileFilter (string name, string [] extensions)
+        public static FileFilter GetFileFilter (string name, System.Collections.Generic.IEnumerable<string> extensions)
         {
             FileFilter filter = new FileFilter ();
             filter.Name = name;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]