banshee r4784 - in trunk/banshee: . src/Backends/Banshee.Hal src/Backends/Banshee.Hal/Banshee.HalBackend src/Core/Banshee.Services src/Core/Banshee.Services/Banshee.Hardware src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod src/Dap/Banshee.Dap.MassStorage src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage



Author: abock
Date: Fri Nov  7 01:43:15 2008
New Revision: 4784
URL: http://svn.gnome.org/viewvc/banshee?rev=4784&view=rev

Log:
2008-11-06  Aaron Bockover  <abock gnome org>

    This commit provides my first pass at allowing for custom USB mass storage
    device profiles. It allows writing customized classes to special case
    certain devices that are just USB mass storage where extra features and
    polish are desired. As an example, basic out of the box support for the
    T-Mobile G1/Android Phone is implemented. This means the G1 should work
    out of the box with no .is_audio_player necessary or any changes to HAL

    It supports reading/syncing music purchased through the Amazon MP3 store
    on the G1 and syncing cover art along with music.

    * src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageDevice.cs:
    Moved the is_audio_player reader into new base device properties class

    * src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/KeyValueParser.cs:
    Lots of fixes for parsing the key/value file for is_audio_player

    * src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/CustomMassStorageDevice.cs:
    MassStorageDevice class that custom device support classes should derive

    * src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/AndroidDevice.cs:
    An implementation of a custom device for the T-Mobile G1/Android phone

    * src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/DeviceMapper.cs:
    Given a USB Device, find out what kind of device profile to create,
    checking a table of custom supported devices (e.g. Android devices), and
    falling back to the base MassStorageDevice that supports reading
    is_audio_player

    * src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs:
    Use the new MassStorageDevice class for reading customized properties
    that are not part of DeviceMediaCapabilities (e.g. from HAL); also when
    deleting tracks, check to see if the directory will become empty after
    removing the track, and if so, also remove the cover art file if one
    exists.

    * src/Core/Banshee.Services/Banshee.Hardware/IUsbDevice.cs: New interface
    for USB specific device properties

    * src/Core/Banshee.Services/Banshee.Hardware/IDevice.cs: Defined
    ResolveRootUsbDevice which is to return the top level USB device
    as an IUsbDevice

    * src/Core/Banshee.Services/Banshee.Hardware/VendorProductInfo.cs:
    Struct to define USB devices through vendor/product IDs

    * src/Backends/Banshee.Hal/Banshee.HalBackend/Device.cs:
    * src/Backends/Banshee.Hal/Banshee.HalBackend/UsbDevice.cs: Implement the
    new IUsbDevice support against HAL

    * src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/PodSleuthDevice.cs: Proxy
    the ResolveRootUsbDevice method now defined on IDevice



Added:
   trunk/banshee/src/Backends/Banshee.Hal/Banshee.HalBackend/UsbDevice.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/IUsbDevice.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/VendorProductInfo.cs
   trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/AndroidDevice.cs
   trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/CustomMassStorageDevice.cs
   trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/DeviceMapper.cs
   trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/KeyValueParser.cs
   trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageDevice.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Backends/Banshee.Hal/Banshee.HalBackend/Device.cs
   trunk/banshee/src/Backends/Banshee.Hal/Makefile.am
   trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/IDevice.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/IDeviceMediaCapabilities.cs
   trunk/banshee/src/Core/Banshee.Services/Makefile.am
   trunk/banshee/src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/PodSleuthDevice.cs
   trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
   trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Makefile.am

Modified: trunk/banshee/src/Backends/Banshee.Hal/Banshee.HalBackend/Device.cs
==============================================================================
--- trunk/banshee/src/Backends/Banshee.Hal/Banshee.HalBackend/Device.cs	(original)
+++ trunk/banshee/src/Backends/Banshee.Hal/Banshee.HalBackend/Device.cs	Fri Nov  7 01:43:15 2008
@@ -129,6 +129,11 @@
             return device.GetPropertyStringList (key);
         }
         
+        public IUsbDevice ResolveRootUsbDevice ()
+        {
+            return UsbDevice.Resolve (HalManager, CollectUsbDeviceStack (device).Peek ());
+        }
+        
         private static Stack<Hal.Device> CollectUsbDeviceStack (Hal.Device device)
         {
             Stack<Hal.Device> device_stack = new Stack<Hal.Device> ();

Added: trunk/banshee/src/Backends/Banshee.Hal/Banshee.HalBackend/UsbDevice.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Backends/Banshee.Hal/Banshee.HalBackend/UsbDevice.cs	Fri Nov  7 01:43:15 2008
@@ -0,0 +1,75 @@
+//
+// UsbDevice.cs
+//
+// Author:
+//   Aaron Bockover <abockover 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 Banshee.Hardware;
+
+namespace Banshee.HalBackend
+{
+    public class UsbDevice : Device, IUsbDevice
+    {
+        public new static UsbDevice Resolve (Hal.Manager manager, Hal.Device device)
+        {
+            if (device["info.subsystem"] == "usb_device" && 
+                device.PropertyExists ("usb_device.product_id") && 
+                device.PropertyExists ("usb_device.vendor_id")) {
+                return new UsbDevice (manager, device);
+            }
+            
+            return null;
+        }
+        
+        private UsbDevice (Hal.Manager manager, Hal.Device device) : base (manager, device)
+        {
+        }
+        
+        public int VendorId {
+            get { return HalDevice.GetPropertyInteger ("usb_device.vendor_id"); }
+        }
+        
+        public int ProductId {
+            get { return HalDevice.GetPropertyInteger ("usb_device.product_id"); }
+        }
+        
+        public override string Serial {
+            get { return HalDevice.PropertyExists ("usb_device.serial") 
+                ? HalDevice["usb_device.serial"] : null; }
+        }
+        
+        public double Speed {
+            get { return HalDevice.PropertyExists ("usb_device.speed") 
+                ? HalDevice.GetPropertyDouble ("usb_device.speed") : 0.0; }
+        }
+        
+        public double Version {
+            get { return HalDevice.PropertyExists ("usb_device.version") 
+                ? HalDevice.GetPropertyDouble ("usb_device.version") : 0.0; }
+        }
+    }
+}

Modified: trunk/banshee/src/Backends/Banshee.Hal/Makefile.am
==============================================================================
--- trunk/banshee/src/Backends/Banshee.Hal/Makefile.am	(original)
+++ trunk/banshee/src/Backends/Banshee.Hal/Makefile.am	Fri Nov  7 01:43:15 2008
@@ -11,6 +11,7 @@
 	Banshee.HalBackend/DiscVolume.cs \
 	Banshee.HalBackend/DiskDevice.cs \
 	Banshee.HalBackend/HardwareManager.cs \
+	Banshee.HalBackend/UsbDevice.cs \
 	Banshee.HalBackend/Volume.cs \
 	Hal/Device.cs \
 	Hal/Manager.cs \

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/IDevice.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/IDevice.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/IDevice.cs	Fri Nov  7 01:43:15 2008
@@ -49,5 +49,7 @@
         int GetPropertyInteger (string key);
         ulong GetPropertyUInt64 (string key);
         string [] GetPropertyStringList (string key);
+        
+        IUsbDevice ResolveRootUsbDevice ();
     }
 }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/IDeviceMediaCapabilities.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/IDeviceMediaCapabilities.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/IDeviceMediaCapabilities.cs	Fri Nov  7 01:43:15 2008
@@ -37,7 +37,7 @@
         int FolderDepth { get; }
         string [] AudioFolders { get; }
         string CoverArtFileType { get; }
-        string CoverArtFileName { get; }		
+        string CoverArtFileName { get; }
         string [] PlaylistFormats { get; }
         string PlaylistPath { get; }
         string [] PlaybackMimeTypes { get; }

Added: trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/IUsbDevice.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/IUsbDevice.cs	Fri Nov  7 01:43:15 2008
@@ -0,0 +1,40 @@
+//
+// IUsbDevice.cs
+//
+// Author:
+//   Aaron Bockover <abockover 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;
+
+namespace Banshee.Hardware
+{
+    public interface IUsbDevice : IDevice
+    {
+        int ProductId { get; }
+        int VendorId { get; }
+        double Speed { get; }
+        double Version { get; }
+    }
+}

Added: trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/VendorProductInfo.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Hardware/VendorProductInfo.cs	Fri Nov  7 01:43:15 2008
@@ -0,0 +1,96 @@
+//
+// VendorProductInfo.cs
+//
+// Author:
+//   Aaron Bockover <abockover 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;
+
+namespace Banshee.Hardware
+{
+    public struct VendorProductInfo
+    {
+        public static VendorProductInfo Zero;
+    
+        public VendorProductInfo (string vendorName, string productName, int vendorProductId)
+        {
+            vendor_name = vendorName;
+            product_name = productName;
+            VendorProductId = vendorProductId;
+        }
+    
+        public VendorProductInfo (string vendorName, string productName, 
+            short vendorId, short productId)
+        {
+            vendor_name = vendorName;
+            product_name = productName;
+            vendor_id = vendorId;
+            product_id = productId;
+        }
+        
+        public override int GetHashCode()
+        {
+            return VendorProductId;
+        }
+        
+        public override string ToString()
+        {
+            return String.Format ("{0}, {1}; Vendor ID = {2}, Product ID = {3} ({4})", 
+                VendorName, ProductName, VendorId, ProductId, VendorProductId);
+        }
+        
+        private string vendor_name;
+        public string VendorName {
+            get { return vendor_name; }
+            set { vendor_name = value; }
+        }
+        
+        private string product_name;
+        public string ProductName {
+            get { return product_name; }
+            set { product_name = value; }
+        }
+    
+        private short vendor_id;
+        public short VendorId {
+            get { return vendor_id; }
+            set { vendor_id = value; }
+        }
+        
+        private short product_id;
+        public short ProductId {
+            get { return product_id; }
+            set { product_id = value; }
+        }   
+        
+        public int VendorProductId {
+            get { return (int)(vendor_id << 16) | product_id; }
+            set {
+                vendor_id = (short)(value >> 16);
+                product_id = (short)(value & 0xffff);
+            }
+        }
+    }
+}

Modified: trunk/banshee/src/Core/Banshee.Services/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Makefile.am	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Makefile.am	Fri Nov  7 01:43:15 2008
@@ -61,7 +61,9 @@
 	Banshee.Hardware/IDiscVolume.cs \
 	Banshee.Hardware/IDiskDevice.cs \
 	Banshee.Hardware/IHardwareManager.cs \
+	Banshee.Hardware/IUsbDevice.cs \
 	Banshee.Hardware/IVolume.cs \
+	Banshee.Hardware/VendorProductInfo.cs \
 	Banshee.Library/HomeDirectoryImportSource.cs \
 	Banshee.Library/IImportSource.cs \
 	Banshee.Library/ImportSourceManager.cs \

Modified: trunk/banshee/src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/PodSleuthDevice.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/PodSleuthDevice.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/PodSleuthDevice.cs	Fri Nov  7 01:43:15 2008
@@ -357,6 +357,11 @@
             return volume.GetPropertyStringList (key);
         }
         
+        public IUsbDevice ResolveRootUsbDevice ()
+        {
+            return volume.ResolveRootUsbDevice ();
+        }
+        
 #endregion
 
     }

Added: trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/AndroidDevice.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/AndroidDevice.cs	Fri Nov  7 01:43:15 2008
@@ -0,0 +1,102 @@
+//
+// AndroidDevice.cs
+//
+// Author:
+//   Aaron Bockover <abockover 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 Banshee.Hardware;
+
+namespace Banshee.Dap.MassStorage
+{
+    public class AndroidDevice : CustomMassStorageDevice
+    {
+        private static string [] playback_mime_types = new string [] {
+            "audio/mpeg",
+            "audio/mp4",
+            "audio/aac",
+            "audio/x-ms-wma",
+            "application/ogg",
+            "audio/x-wav",
+            "audio/vnd.rn-realaudio",
+            "audio/3gpp",
+            "audio/x-midi"
+        };
+        
+        private static string [] audio_folders = new string [] {
+            "Music/",
+            "amazonmp3/"
+        };
+        
+        public AndroidDevice (VendorProductInfo productInfo, MassStorageSource source) 
+            : base (productInfo, source)
+        {
+        }
+        
+        public override bool LoadDeviceConfiguration ()
+        {
+            return true;
+        }
+        
+        private string name;
+        public override string Name {
+            get { 
+                if (name == null) {
+                    name = Source.UsbDevice.Name;
+                    if (String.IsNullOrEmpty (Name)) {
+                        name = base.Name ?? "Android Phone";
+                    }
+                }
+                
+                return name;
+            }
+        }
+        
+        public override string[] AudioFolders {
+            get { return audio_folders; }
+        }
+        
+        public override string [] PlaybackMimeTypes {
+            get { return playback_mime_types; }
+        }
+        
+        // Cover art information gleaned from Android's Music application
+        // packages/apps/Music/src/com/android/music/MusicUtils.java
+        // <3 open source
+        
+        public override string CoverArtFileName {
+            get { return "AlbumArt.jpg"; }
+        }
+        
+        public override string CoverArtFileType {
+            get { return "jpeg"; }
+        }
+        
+        public override int CoverArtSize {
+            get { return 320; }
+        }
+    }
+}

Added: trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/CustomMassStorageDevice.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/CustomMassStorageDevice.cs	Fri Nov  7 01:43:15 2008
@@ -0,0 +1,49 @@
+//
+// CustomMassStorageDevice.cs
+//
+// Author:
+//   Aaron Bockover <abockover 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 Banshee.Hardware;
+
+namespace Banshee.Dap.MassStorage
+{   
+    public class CustomMassStorageDevice : MassStorageDevice
+    {       
+        private VendorProductInfo product_info;
+        
+        public CustomMassStorageDevice (VendorProductInfo productInfo, MassStorageSource source) 
+            : base (source)
+        {
+            product_info = productInfo;
+        }
+        
+        public override string Name {
+            get { return product_info.ProductName; }
+        }
+    }
+}

Added: trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/DeviceMapper.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/DeviceMapper.cs	Fri Nov  7 01:43:15 2008
@@ -0,0 +1,71 @@
+//
+// DeviceMapper.cs
+//
+// Author:
+//   Aaron Bockover <abockover 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 Banshee.Hardware;
+
+namespace Banshee.Dap.MassStorage
+{
+    internal static class DeviceMapper
+    {
+        private static DeviceMap [] devices = new DeviceMap [] {
+            new DeviceMap (typeof (AndroidDevice), "HTC", "T-Mobile G1", 0x0bb4, 0x0c01)
+        };
+    
+        public static MassStorageDevice Map (MassStorageSource source)
+        {
+            foreach (DeviceMap map in devices) {
+                if (map.VendorProductInfo.VendorId == source.UsbDevice.VendorId && 
+                    map.VendorProductInfo.ProductId == source.UsbDevice.ProductId) {
+                    return (CustomMassStorageDevice)Activator.CreateInstance (map.DeviceType, 
+                        new object [] { map.VendorProductInfo, source });
+                }
+            }
+            
+            return new MassStorageDevice (source);
+        }
+        
+        private struct DeviceMap
+        {
+            public DeviceMap (Type type, VendorProductInfo vpi)
+            {
+                DeviceType = type;
+                VendorProductInfo = vpi;
+            }
+            
+            public DeviceMap (Type type, string vendor, string product, short vendorId, short productId)
+            {
+                DeviceType = type;
+                VendorProductInfo = new VendorProductInfo (vendor, product, vendorId, productId);
+            }
+            
+            public VendorProductInfo VendorProductInfo;
+            public Type DeviceType;
+        }
+    }
+}

Added: trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/KeyValueParser.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/KeyValueParser.cs	Fri Nov  7 01:43:15 2008
@@ -0,0 +1,120 @@
+//
+// KeyValueParser.cs
+//
+// Author:
+//   Aaron Bockover <abockover 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.IO;
+using System.Text;
+using System.Collections.Generic;
+
+namespace Banshee.Dap.MassStorage
+{
+    internal class KeyValueParser : Dictionary<string, string []>
+    {
+        private StreamReader reader;
+        private StringBuilder builder = new StringBuilder (64);
+        private List<string> values = new List<string> (8);
+        private string key;
+
+        public KeyValueParser (StreamReader reader)
+        {
+            this.reader = reader;
+            Parse ();
+        }
+
+        private void Parse ()
+        {
+            bool in_value = false;
+            char c;
+
+            while ((c = Read ()) != Char.MaxValue) {
+                if (!in_value && c == '=') {
+                    key = Collect ();
+                    if (!String.IsNullOrEmpty (key)) {
+                        in_value = true;
+                    } else {
+                        key = null;
+                    }
+                } else if (Char.IsWhiteSpace (c) || c == ',') {
+                    if (!in_value) {
+                        continue;
+                    }
+
+                    string value = Collect ();
+                    if (!String.IsNullOrEmpty (value)) {
+                        values.Add (value);
+                    }
+
+                    if (c == '\n') {
+                        Commit ();
+                        in_value = false;
+                    }
+                } else {
+                    if (c == '\\') {
+                        c = Read ();
+                    }
+
+                    if (c != '\n') {
+                        builder.Append (c);
+                    }
+                }
+            }
+
+            Commit ();
+        }
+
+        private void Commit ()
+        {
+            if (!String.IsNullOrEmpty (key) && values.Count > 0) {
+                if (ContainsKey (key)) {
+                    this[key] = values.ToArray ();
+                } else {
+                    Add (key, values.ToArray ());
+                }
+            }
+
+            key = null;
+            values.Clear ();
+        }
+
+        private string Collect ()
+        {
+            if (builder.Length == 0) {
+                return null;
+            }
+
+            string value = builder.ToString ();
+            builder.Remove (0, builder.Length);
+            return value;
+        }
+
+        private char Read ()
+        {
+            return (char)reader.Read ();
+        }
+    }
+}

Added: trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageDevice.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageDevice.cs	Fri Nov  7 01:43:15 2008
@@ -0,0 +1,162 @@
+//
+// MassStorageDevice.cs
+//
+// Author:
+//   Aaron Bockover <abockover 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.IO;
+using System.Collections.Generic;
+
+using Hyena;
+
+using Banshee.Base;
+using Banshee.Hardware;
+
+namespace Banshee.Dap.MassStorage
+{
+    public class MassStorageDevice : IDeviceMediaCapabilities
+    {
+        private MassStorageSource source;
+        protected MassStorageSource Source {
+            get { return source; }
+        }
+        
+        public MassStorageDevice (MassStorageSource source)
+        {
+            this.source = source;
+        }
+        
+        public virtual bool LoadDeviceConfiguration ()
+        {
+            string path = IsAudioPlayerPath;
+            StreamReader reader = null;
+            
+            if (!File.Exists (path)) {
+                return false;
+            }
+            
+            try {
+                foreach (var item in new KeyValueParser (reader = new StreamReader (path))) {
+                    try {
+                        switch (item.Key) {
+                            case "name": name = item.Value[0]; break;
+                            
+                            case "cover_art_file_type": cover_art_file_type = item.Value[0].ToLower (); break;
+                            case "cover_art_file_name": cover_art_file_name = item.Value[0]; break;
+                            case "cover_art_size": Int32.TryParse (item.Value[0], out cover_art_size); break;
+                            
+                            case "folder_depth": Int32.TryParse (item.Value[0], out folder_depth); break;
+                            case "audio_folders": audio_folders = item.Value; break;
+                            
+                            case "output_formats": playback_mime_types = item.Value; break;
+                            
+                            case "playlist_format": playlist_formats = item.Value; break;
+                            case "playlist_path": playlist_path = item.Value[0]; break;
+                            
+                            default:
+                                throw new ApplicationException ("unsupported key");    
+                        }
+                    } catch (Exception e) {
+                        Log.Exception ("Invalid .is_audio_player item " + item.Key, e);
+                    }
+                }
+            } catch (Exception e) {
+                Log.Exception ("Error parsing " + path, e);
+            } finally {
+                if (reader != null) {
+                    reader.Dispose ();
+                }
+            }
+            
+            has_is_audio_player_file = true;
+            
+            return true;
+        }
+        
+        private bool has_is_audio_player_file;
+        public bool HasIsAudioPlayerFile {
+            get { return has_is_audio_player_file; }
+        }
+        
+        private string IsAudioPlayerPath {
+            get { return System.IO.Path.Combine (source.Volume.MountPoint, ".is_audio_player"); }
+        }
+        
+        private string name;
+        public virtual string Name {
+            get { return name ?? source.Volume.Name; }
+        }
+        
+        private int cover_art_size;
+        public virtual int CoverArtSize { 
+            get { return cover_art_size; } 
+        }
+        
+        private int folder_depth;
+        public virtual int FolderDepth { 
+            get { return folder_depth; } 
+        }
+        
+        private string [] audio_folders = new string[0];
+        public virtual string [] AudioFolders { 
+            get { return audio_folders; } 
+        }
+        
+        private string cover_art_file_type;
+        public virtual string CoverArtFileType { 
+            get { return cover_art_file_type; } 
+        }
+        
+        private string cover_art_file_name;
+        public virtual string CoverArtFileName { 
+            get { return cover_art_file_name; } 
+        }
+        
+        private string [] playlist_formats;
+        public virtual string [] PlaylistFormats { 
+            get { return playlist_formats; } 
+        }
+        
+        private string playlist_path;
+        public virtual string PlaylistPath { 
+            get { return playlist_path; } 
+        }
+        
+        private string [] playback_mime_types;
+        public virtual string [] PlaybackMimeTypes { 
+            get { return playback_mime_types; } 
+        }
+        
+        public virtual string DeviceType {
+            get { return "mass-storage"; }
+        }
+        
+        public bool IsType (string type)
+        {
+            return type == DeviceType;
+        }
+    }
+}

Modified: trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs	Fri Nov  7 01:43:15 2008
@@ -50,29 +50,38 @@
 {
     public class MassStorageSource : DapSource
     {
-        private Banshee.Collection.Gui.ArtworkManager artwork_manager = ServiceManager.Get<Banshee.Collection.Gui.ArtworkManager> ();
-        protected IVolume volume;
+        private Banshee.Collection.Gui.ArtworkManager artwork_manager 
+            = ServiceManager.Get<Banshee.Collection.Gui.ArtworkManager> ();
+        
+        private MassStorageDevice ms_device;
+        private IVolume volume;
+        private IUsbDevice usb_device;
 
         public override void DeviceInitialize (IDevice device)
         {
             base.DeviceInitialize (device);
             
-            this.volume = device as IVolume;
-            if (volume == null)
+            volume = device as IVolume;
+            if (volume == null || (usb_device = volume.ResolveRootUsbDevice ()) == null) {
                 throw new InvalidDeviceException ();
+            }
+            
+            ms_device = DeviceMapper.Map (this);
+            try {
+                if (!ms_device.LoadDeviceConfiguration ()) {
+                    ms_device = null;
+                }
+            } catch {
+                ms_device = null;
+            }
 
-            // TODO set up a ui for selecting volumes we want mounted/shown within Banshee
-            // (so people don't have to touch .is_audio_player, and so we can give them a harddrive icon
-            // instead of pretending they are DAPs).
-            if (!HasMediaCapabilities && !HasIsAudioPlayerFile)
+            if (!HasMediaCapabilities && ms_device == null) {
                 throw new InvalidDeviceException ();
-
-            if (HasIsAudioPlayerFile)
-                ParseIsAudioPlayerFile ();
-
+            }
+            
             // Ignore iPods, except ones with .is_audio_player files
             if (MediaCapabilities != null && MediaCapabilities.IsType ("ipod")) {
-                if (HasIsAudioPlayerFile) {
+                if (ms_device != null && ms_device.HasIsAudioPlayerFile) {
                     Log.Information (
                         "Mass Storage Support Loading iPod",
                         "The USB mass storage audio player support is loading an iPod because it has an .is_audio_player file. " +
@@ -83,7 +92,7 @@
                 }
             }
 
-            Name = volume.Name;
+            Name = ms_device == null ? volume.Name : ms_device.Name;
             mount_point = volume.MountPoint;
 
             Initialize ();
@@ -183,34 +192,27 @@
         public IVolume Volume {
             get { return volume; }
         }
+        
+        public IUsbDevice UsbDevice {
+            get { return usb_device; }
+        }
 
         private string mount_point;
         public override string BaseDirectory {
             get { return mount_point; }
         }
 
-        private bool? has_is_audio_player_file = null;
-        private bool HasIsAudioPlayerFile {
-            get {
-                if (has_is_audio_player_file == null)
-                    has_is_audio_player_file = File.Exists (new SafeUri (IsAudioPlayerPath));
-                return has_is_audio_player_file.Value;
-            }
-        }
-
         protected override IDeviceMediaCapabilities MediaCapabilities {
             get {
-                return (volume.Parent == null)
-                    ? base.MediaCapabilities
-                    : volume.Parent.MediaCapabilities ?? base.MediaCapabilities;
+                return ms_device ?? (
+                    volume.Parent == null
+                        ? base.MediaCapabilities
+                        : volume.Parent.MediaCapabilities ?? base.MediaCapabilities
+                );
             }
         }
 
-        protected string IsAudioPlayerPath {
-            get { return System.IO.Path.Combine (volume.MountPoint, ".is_audio_player"); }
-        }
-
-        #region Properties and Methods for Supporting Syncing of Playlists
+#region Properties and Methods for Supporting Syncing of Playlists
 
         private string playlists_path;
         private string PlaylistsPath {
@@ -315,8 +317,8 @@
             }
         }
 
-        #endregion
-        
+#endregion
+
         public override long BytesUsed {
             get { return BytesCapacity - volume.Available; }
         }
@@ -351,7 +353,7 @@
         protected string [] AudioFolders {
             get {
                 if (audio_folders == null) {
-                    audio_folders = HasMediaCapabilities ? MediaCapabilities.AudioFolders : new string [] {};
+                    audio_folders = HasMediaCapabilities ? MediaCapabilities.AudioFolders : new string[0];
                 }
                 return audio_folders;
             }
@@ -483,6 +485,25 @@
         protected override void DeleteTrack (DatabaseTrackInfo track)
         {
             try {
+                string track_file = System.IO.Path.GetFileName (track.Uri.LocalPath);
+                string track_dir = System.IO.Path.GetDirectoryName (track.Uri.LocalPath);
+                int files = 0;
+                
+                // Count how many files remain in the track's directory,
+                // excluding self or cover art
+                foreach (string file in System.IO.Directory.GetFiles (track_dir)) {
+                    string relative = System.IO.Path.GetFileName (file);
+                    if (relative != track_file && relative != CoverArtFileName) {
+                        files++;
+                    }
+                }
+                
+                // If we are the last track, go ahead and delete the artwork
+                // to ensure that the directory tree can get trimmed away too
+                if (files == 0) {
+                    System.IO.File.Delete (Paths.Combine (track_dir, CoverArtFileName));
+                }
+                
                 Banshee.IO.Utilities.DeleteFileTrimmingParentDirectories (track.Uri);
             } catch (System.IO.FileNotFoundException) {
             } catch (System.IO.DirectoryNotFoundException) {
@@ -547,75 +568,5 @@
 
             return file_path;
         }
-
-        private void ParseIsAudioPlayerFile ()
-        {
-            // Allow the HAL values to be overridden by corresponding key=value pairs in .is_audio_player
-            System.IO.StreamReader reader = null;
-            try {
-                reader = new System.IO.StreamReader (IsAudioPlayerPath);
-
-                string line;
-                while ((line = reader.ReadLine ()) != null) {
-                    string [] pieces = line.Split ('=');
-                    if (line.StartsWith ("#") || pieces == null || pieces.Length != 2)
-                        continue;
-
-                    string key = pieces[0];
-                    string val = pieces[1];
-
-                    switch (key) {
-                    case "audio_folders":
-                        AudioFolders = val.Split (',');
-                        break;
-
-                    case "output_formats":
-                        AcceptableMimeTypes = val.Split (',');
-                        for (int i = 0; i < AcceptableMimeTypes.Length; i++) {
-                            AcceptableMimeTypes[i] = AcceptableMimeTypes[i].Trim ();
-                        }
-                        break;
-
-                    case "folder_depth":
-                        FolderDepth = Int32.Parse (val);
-                        break;
-    
-                    case "playlist_format":
-                        PlaylistFormats = val.Split (',');
-                        for (int i = 0; i < PlaylistFormats.Length; i++) {
-                            PlaylistFormats[i] = PlaylistFormats[i].Trim ();
-                        }
-                        break;
-
-                    case "playlist_path":
-                        playlists_path = System.IO.Path.Combine (WritePath, val);
-                        playlists_path = playlists_path.Replace ("%File", String.Empty);
-                        break;
-
-                    case "cover_art_file_type":
-                        CoverArtFileType = val.ToLower ();
-                        break;
-
-                    case "cover_art_file_name":
-                        CoverArtFileName = val;
-                        break;
-
-                    case "cover_art_size":
-                        CoverArtSize = Int32.Parse (val);
-                        break;
-
-                    case "input_formats":
-                    default:
-                        Log.DebugFormat ("Unsupported .is_audio_player key: {0}", key);
-                        break;
-                    }
-                }
-            } catch (Exception e) {
-                Log.Exception ("Error parsing .is_audio_player file", e);
-            } finally {
-                if (reader != null)
-                    reader.Close ();
-            }
-        }
     }
 }

Modified: trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Makefile.am
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Makefile.am	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Makefile.am	Fri Nov  7 01:43:15 2008
@@ -3,7 +3,13 @@
 LINK = $(REF_DAP_MASS_STORAGE)
 INSTALL_DIR = $(EXTENSIONS_INSTALL_DIR)
 
-SOURCES = Banshee.Dap.MassStorage/MassStorageSource.cs
+SOURCES =  \
+	Banshee.Dap.MassStorage/AndroidDevice.cs \
+	Banshee.Dap.MassStorage/CustomMassStorageDevice.cs \
+	Banshee.Dap.MassStorage/DeviceMapper.cs \
+	Banshee.Dap.MassStorage/KeyValueParser.cs \
+	Banshee.Dap.MassStorage/MassStorageDevice.cs \
+	Banshee.Dap.MassStorage/MassStorageSource.cs
 
 RESOURCES = Banshee.Dap.MassStorage.addin.xml
 



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