banshee r3809 - in trunk/banshee: . build data data/audio-profiles libbanshee src/Backends/Banshee.GStreamer src/Backends/Banshee.GStreamer/Banshee.GStreamer src/Backends/Banshee.Gnome/Banshee.GnomeBackend src/Core/Banshee.Services src/Core/Banshee.Services/Banshee.MediaEngine src/Core/Banshee.Services/Banshee.MediaProfiles src/Core/Banshee.Services/Banshee.ServiceStack src/Core/Banshee.Services/Banshee.Sources src/Core/Banshee.ThickClient/Banshee.Gui src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui src/Core/Banshee.ThickClient/ThemeIcons/22x22/actions src/Dap/Banshee.Dap src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp src/Dap/Banshee.Dap/Banshee.Dap src/Dap/Banshee.Dap/Banshee.Dap.Gui src/Libraries/Mtp/Mtp



Author: gburt
Date: Wed Apr 23 02:40:43 2008
New Revision: 3809
URL: http://svn.gnome.org/viewvc/banshee?rev=3809&view=rev

Log:
2008-04-22  Gabriel Burt  <gabriel burt gmail com>

	This commit adds transcoding support to DAPs.  Transcoded files are stored
	in ~/.config/banshee-1/transcoder/, and that folder is deleted every
	Banshee session.  One improvement over stable's transcoding is file
	transfers can happen at the same time as transcoding.

	* src/Dap/Banshee.Dap/Banshee.Dap/RemovableSource.cs: Make IsReadOnly public.

	* src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs: Enable property dialogs
	for DapSources.  Also, override AddTrack methods to first transcode if
	necessary.

	* src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs:
	Reflect updates in two parent classes.

	* src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs:  Lock use of the
	mtp device so only one operation happens at a time.  Make adding track
	work with new transcoding support.  Add fine-grained progress when adding
	tracks.

	* src/Dap/Banshee.Dap/Makefile.am:
	* src/Dap/Banshee.Dap/Banshee.Dap.Gui:
	* src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapPropertiesDialog.cs: Ported from
	stable.  Advanced properties and owner entry commented out.

	* src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs: If the Source
	has a property named 'SourceProperties.GuiHandler' that is a
	OpenPropertiesDelegate, invoke it OnSourcePropertiesAction.

	* src/Core/Banshee.ThickClient/ThemeIcons/22x22/actions:
	* src/Core/Banshee.ThickClient/ThemeIcons/22x22/actions/encode.png: Copy
	icon from stable.

	* src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileConfigurationDialog.cs:
	* src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileComboBoxConfigurable.cs:
	* src/Core/Banshee.Services/Banshee.MediaProfiles/MediaProfileManager.cs:
	* src/Core/Banshee.Services/Banshee.MediaProfiles/PipelineVariable.cs:
	* src/Core/Banshee.Services/Banshee.MediaProfiles/Profile.cs:
	* src/Core/Banshee.Services/Banshee.MediaProfiles/Pipeline.cs:
	* src/Core/Banshee.Services/Banshee.MediaProfiles/ProfileConfiguration.cs:
	Renamed *ID properties to *Id.  Also, use the ProfileConfiguration in
	several places we used to return just the Profile, since multiple
	ProfileConfigurations can share a Profile, we need to make sure this
	configurations variables are loaded when we use it.

	* src/Core/Banshee.Services/Banshee.Sources/Source.cs: Define
	OpenPropertiesDelegate.

	* src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs: Handle
	AddTracks not being synchronous (since there may be transcoding).

	* src/Core/Banshee.Services/Banshee.ServiceStack/BatchUserJob.cs: Add
	DetailedProgress that is the percent complete of the current sub-job.

	* src/Core/Banshee.Services/Banshee.ServiceStack/ServiceManager.cs: Load
	the TranscoderService.

	* src/Core/Banshee.Services/Banshee.Services.addin.xml: Define
	/Banshee/MediaEngine/Transcoder extension node.

	* src/Core/Banshee.Services/Makefile.am:
	* src/Core/Banshee.Services/Banshee.Services.mdp:
	* src/Core/Banshee.Services/Banshee.MediaEngine/ITranscoder.cs:
	* src/Core/Banshee.Services/Banshee.MediaEngine/TranscoderService.cs: New
	files that give us transcoding.  Largely ported code from stable.

	* src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfConfigurationClient.cs:
	Remove / characters from key names.

	* src/Backends/Banshee.GStreamer/Makefile.am:
	* src/Backends/Banshee.GStreamer/Banshee.GStreamer.addin.xml:
	* src/Backends/Banshee.GStreamer/Banshee.GStreamer/Transcoder.cs: Add
	GStreamer implementation of MediaEngine.ITranscoder, mostly ported from
	stable.

	* src/Backends/Banshee.GStreamer/Banshee.GStreamer/AudioCdRipper.cs: Tweak
	way Profiles are loaded to ensure they're configured.

	* src/Libraries/Mtp/Mtp/Track.cs: Remove WriteLine.

	* libbanshee/banshee-transcoder.c: Fix broken progress updates, and Gtk
	criticals.

	* build/build.environment.mk: Require Banshee.ThickClient in Banshee.Dap
	now b/c of properties dialog.

	* data/audio-profiles/*.xml.in: Add taglib/* mimetypes.

	* data/banshee-1.desktop.in.in:
	* data/mimetypes.txt: Update list of mimetypes with some ones from TagLib#
	we didn't have.


Added:
   trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/Transcoder.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/ITranscoder.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/TranscoderService.cs
   trunk/banshee/src/Core/Banshee.ThickClient/ThemeIcons/22x22/actions/
   trunk/banshee/src/Core/Banshee.ThickClient/ThemeIcons/22x22/actions/encode.png   (contents, props changed)
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapPropertiesDialog.cs   (contents, props changed)
      - copied, changed from r3804, /branches/banshee/stable/src/Core/Banshee.Base/Dap/DapPropertiesDialog.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/build/build.environment.mk
   trunk/banshee/data/audio-profiles/aac.xml.in
   trunk/banshee/data/audio-profiles/flac.xml.in
   trunk/banshee/data/audio-profiles/mp3-lame.xml.in
   trunk/banshee/data/audio-profiles/mp3-xing.xml.in
   trunk/banshee/data/audio-profiles/vorbis.xml.in
   trunk/banshee/data/audio-profiles/wavpack.xml.in
   trunk/banshee/data/audio-profiles/wma.xml.in
   trunk/banshee/data/banshee-1.desktop.in.in
   trunk/banshee/data/mimetypes.txt
   trunk/banshee/libbanshee/banshee-transcoder.c
   trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer.addin.xml
   trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/AudioCdRipper.cs
   trunk/banshee/src/Backends/Banshee.GStreamer/Makefile.am
   trunk/banshee/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfConfigurationClient.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/MediaProfileManager.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/Pipeline.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/PipelineVariable.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/Profile.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/ProfileConfiguration.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/BatchUserJob.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/ServiceManager.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Services.addin.xml
   trunk/banshee/src/Core/Banshee.Services/Banshee.Services.mdp
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
   trunk/banshee/src/Core/Banshee.Services/Makefile.am
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileComboBoxConfigurable.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileConfigurationDialog.cs
   trunk/banshee/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
   trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/RemovableSource.cs
   trunk/banshee/src/Dap/Banshee.Dap/Makefile.am
   trunk/banshee/src/Libraries/Mtp/Mtp/Track.cs

Modified: trunk/banshee/build/build.environment.mk
==============================================================================
--- trunk/banshee/build/build.environment.mk	(original)
+++ trunk/banshee/build/build.environment.mk	Wed Apr 23 02:40:43 2008
@@ -124,7 +124,7 @@
 REF_NEREID = $(LINK_BANSHEE_THICKCLIENT_DEPS)
 
 # Dap
-REF_DAP = $(LINK_BANSHEE_SERVICES_DEPS)
+REF_DAP = $(LINK_BANSHEE_SERVICES_DEPS) $(LINK_BANSHEE_THICKCLIENT_DEPS)
 LINK_DAP = -r:$(DIR_BIN)/Banshee.Dap.dll
 LINK_DAP_DEPS = $(REF_DAP) $(LINK_DAP)
 REF_DAP_MASS_STORAGE = $(LINK_BANSHEE_SERVICES_DEPS) $(LINK_DAP_DEPS)

Modified: trunk/banshee/data/audio-profiles/aac.xml.in
==============================================================================
--- trunk/banshee/data/audio-profiles/aac.xml.in	(original)
+++ trunk/banshee/data/audio-profiles/aac.xml.in	Wed Apr 23 02:40:43 2008
@@ -7,6 +7,7 @@
       <output-file-extension>m4a</output-file-extension>
       <mimetype>audio/x-m4a</mimetype>
       <mimetype>audio/mp4</mimetype>
+      <mimetype>taglib/mp4</mimetype>
       <pipeline>
         <process id="gstreamer">
         <![CDATA[

Modified: trunk/banshee/data/audio-profiles/flac.xml.in
==============================================================================
--- trunk/banshee/data/audio-profiles/flac.xml.in	(original)
+++ trunk/banshee/data/audio-profiles/flac.xml.in	Wed Apr 23 02:40:43 2008
@@ -8,6 +8,7 @@
       <mimetype>application/x-flac</mimetype>
       <mimetype>audio/flac</mimetype>
       <mimetype>audio/x-flac</mimetype>
+      <mimetype>taglib/flac</mimetype>
       <pipeline>
         <process id="gstreamer">
         <![CDATA[

Modified: trunk/banshee/data/audio-profiles/mp3-lame.xml.in
==============================================================================
--- trunk/banshee/data/audio-profiles/mp3-lame.xml.in	(original)
+++ trunk/banshee/data/audio-profiles/mp3-lame.xml.in	Wed Apr 23 02:40:43 2008
@@ -6,9 +6,11 @@
       <_description>A proprietary and older, but also popular, lossy audio format that produces larger files at lower bitrates.</_description>
       <output-file-extension>mp3</output-file-extension>
       <mimetype>audio/mp3</mimetype>
+      <mimetype>taglib/mp3</mimetype>
       <mimetype>audio/mpeg3</mimetype>
       <mimetype>audio/x-mpeg-3</mimetype>
       <mimetype>audio/x-mpeg</mimetype>
+      <mimetype>audio/mpeg</mimetype>
       <mimetype>application/x-id3</mimetype>
       <mimetype>audio/x-mp3</mimetype>
       <pipeline>

Modified: trunk/banshee/data/audio-profiles/mp3-xing.xml.in
==============================================================================
--- trunk/banshee/data/audio-profiles/mp3-xing.xml.in	(original)
+++ trunk/banshee/data/audio-profiles/mp3-xing.xml.in	Wed Apr 23 02:40:43 2008
@@ -6,6 +6,7 @@
       <_description>A proprietary and older, but also popular, lossy audio format that produces larger files at lower bitrates.</_description>
       <output-file-extension>mp3</output-file-extension>
       <mimetype>audio/mp3</mimetype>
+      <mimetype>taglib/mp3</mimetype>
       <mimetype>audio/mpeg3</mimetype>
       <mimetype>audio/x-mpeg-3</mimetype>
       <mimetype>audio/x-mpeg</mimetype>

Modified: trunk/banshee/data/audio-profiles/vorbis.xml.in
==============================================================================
--- trunk/banshee/data/audio-profiles/vorbis.xml.in	(original)
+++ trunk/banshee/data/audio-profiles/vorbis.xml.in	Wed Apr 23 02:40:43 2008
@@ -7,6 +7,7 @@
       <output-file-extension>ogg</output-file-extension>
       <mimetype>audio/x-ogg</mimetype>
       <mimetype>audio/ogg</mimetype>
+      <mimetype>taglib/ogg</mimetype>
       <mimetype>audio/x-vorbis+ogg</mimetype>
       <mimetype>audio/x-vorbis</mimetype>
       <mimetype>audio/vorbis</mimetype>

Modified: trunk/banshee/data/audio-profiles/wavpack.xml.in
==============================================================================
--- trunk/banshee/data/audio-profiles/wavpack.xml.in	(original)
+++ trunk/banshee/data/audio-profiles/wavpack.xml.in	Wed Apr 23 02:40:43 2008
@@ -7,6 +7,8 @@
       <output-file-extension>wv</output-file-extension>
       <mimetype>audio/x-wavpack</mimetype>
       <mimetype>application/x-apetag</mimetype>
+      <mimetype>taglib/ape</mimetype>
+      <mimetype>audio/x-ape</mimetype>
       <pipeline>
         <process id="gstreamer">
         <![CDATA[

Modified: trunk/banshee/data/audio-profiles/wma.xml.in
==============================================================================
--- trunk/banshee/data/audio-profiles/wma.xml.in	(original)
+++ trunk/banshee/data/audio-profiles/wma.xml.in	Wed Apr 23 02:40:43 2008
@@ -6,6 +6,7 @@
       <_description>A proprietary lossy audio format with high quality output at a lower file size than MP3. A 96 kbps WMA is equivalent to a 128 kbps MP3.</_description>
       <output-file-extension>wma</output-file-extension>
       <mimetype>audio/x-ms-wma</mimetype>
+      <mimetype>taglib/wma</mimetype>
       <pipeline>
         <process id="gstreamer">
         <![CDATA[

Modified: trunk/banshee/data/banshee-1.desktop.in.in
==============================================================================
--- trunk/banshee/data/banshee-1.desktop.in.in	(original)
+++ trunk/banshee/data/banshee-1.desktop.in.in	Wed Apr 23 02:40:43 2008
@@ -14,4 +14,4 @@
 X-GNOME-Bugzilla-Product=banshee
 X-GNOME-Bugzilla-Component=General
 X-GNOME-Bugzilla-Version= VERSION@
-MimeType=application/musepack;application/ogg;application/ram;application/sdp;application/smil;application/vnd.rn-realmedia;application/x-ape;application/x-extension-m4a;application/x-extension-mp4;application/x-flac;application/x-flash-video;application/x-id3;application/x-matroska;application/x-musepack;application/x-netshow-channel;application/x-ogg;application/x-quicktime-media-link;application/x-quicktimeplayer;application/x-shorten;application/x-smil;application/xspf+xml;audio/3gpp;audio/AMR;audio/AMR-WB;audio/ac3;audio/ape;audio/basic;audio/flac;audio/midi;audio/mp;audio/mp3;audio/mp4;audio/mp4a-latm;audio/mpc;audio/mpeg;audio/mpeg3;audio/mpegurl;audio/musepack;audio/ogg;audio/vnd.rn-realaudio;audio/vorbis;audio/x-ape;audio/x-flac;audio/x-it;audio/x-m4a;audio/x-matroska;audio/x-mod;audio/x-mp;audio/x-mp3;audio/x-mpc;audio/x-mpeg;audio/x-mpeg-3;audio/x-mpegurl;audio/x-ms-asf;audio/x-ms-asx;audio/x-ms-wax;audio/x-ms-wma;audio/x-musepack;audio/x-ogg;audio/x-pn-aiff;audio
 /x-pn-au;audio/x-pn-realaudio;audio/x-pn-realaudio-plugin;audio/x-pn-wav;audio/x-pn-windows-acm;audio/x-real-audio;audio/x-realaudio;audio/x-s3m;audio/x-sbc;audio/x-scpls;audio/x-speex;audio/x-tta;audio/x-vorbis;audio/x-wav;audio/x-wavpack;audio/x-xm;image/vnd.rn-realpix;image/x-pict;misc/ultravox;text/google-video-pointer;text/x-google-video-pointer;video/3gpp;video/dv;video/fli;video/flv;video/mp4;video/mp4v-es;video/mpeg;video/msvideo;video/quicktime;video/vivo;video/vnd.divx;video/vnd.rn-realvideo;video/vnd.vivo;video/x-anim;video/x-avi;video/x-flc;video/x-fli;video/x-flic;video/x-flv;video/x-m4v;video/x-matroska;video/x-mpeg;video/x-ms-asf;video/x-ms-wm;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvx;video/x-msvideo;video/x-nsv;video/x-ogm+ogg;video/x-theora+ogg;x-content/audio-cdda;x-content/audio-player;
+MimeType=application/musepack;application/ogg;application/ram;application/sdp;application/smil;application/vnd.rn-realmedia;application/x-ape;application/x-extension-m4a;application/x-extension-mp4;application/x-flac;application/x-flash-video;application/x-id3;application/x-matroska;application/x-musepack;application/x-netshow-channel;application/x-ogg;application/x-quicktime-media-link;application/x-quicktimeplayer;application/x-shorten;application/x-smil;application/x-troff-msvideo;application/xspf+xml;audio/3gpp;audio/AMR;audio/AMR-WB;audio/ac3;audio/ape;audio/avi;audio/basic;audio/flac;audio/midi;audio/mp;audio/mp3;audio/mp4;audio/mp4a-latm;audio/mpc;audio/mpeg;audio/mpeg3;audio/mpegurl;audio/musepack;audio/ogg;audio/vnd.rn-realaudio;audio/vorbis;audio/wav;audio/wave;audio/x-ape;audio/x-flac;audio/x-it;audio/x-m4a;audio/x-matroska;audio/x-mod;audio/x-mp;audio/x-mp3;audio/x-mpc;audio/x-mpeg;audio/x-mpeg-3;audio/x-mpegurl;audio/x-ms-asf;audio/x-ms-asx;audio/x-ms-wax;audio/
 x-ms-wma;audio/x-musepack;audio/x-ogg;audio/x-pn-aiff;audio/x-pn-au;audio/x-pn-realaudio;audio/x-pn-realaudio-plugin;audio/x-pn-wav;audio/x-pn-windows-acm;audio/x-real-audio;audio/x-realaudio;audio/x-s3m;audio/x-sbc;audio/x-scpls;audio/x-speex;audio/x-tta;audio/x-vorbis;audio/x-vorbis+ogg;audio/x-wav;audio/x-wavpack;audio/x-xm;image/avi;image/vnd.rn-realpix;image/x-pict;misc/ultravox;text/google-video-pointer;text/x-google-video-pointer;video/3gpp;video/avi;video/dv;video/fli;video/flv;video/mp4;video/mp4v-es;video/mpeg;video/msvideo;video/quicktime;video/vivo;video/vnd.divx;video/vnd.rn-realvideo;video/vnd.vivo;video/x-anim;video/x-avi;video/x-flc;video/x-fli;video/x-flic;video/x-flv;video/x-m4v;video/x-matroska;video/x-mpeg;video/x-mpg;video/x-ms-asf;video/x-ms-wm;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvx;video/x-msvideo;video/x-nsv;video/x-ogm+ogg;video/x-theora+ogg;x-content/audio-cdda;x-content/audio-player;

Modified: trunk/banshee/data/mimetypes.txt
==============================================================================
--- trunk/banshee/data/mimetypes.txt	(original)
+++ trunk/banshee/data/mimetypes.txt	Wed Apr 23 02:40:43 2008
@@ -25,12 +25,14 @@
 application/x-quicktimeplayer
 application/x-shorten
 application/x-smil
+application/x-troff-msvideo
 application/xspf+xml
 audio/3gpp
 audio/AMR
 audio/AMR-WB
 audio/ac3
 audio/ape
+audio/avi
 audio/basic
 audio/flac
 audio/midi
@@ -46,6 +48,8 @@
 audio/ogg
 audio/vnd.rn-realaudio
 audio/vorbis
+audio/wav
+audio/wave
 audio/x-ape
 audio/x-flac
 audio/x-it
@@ -78,15 +82,18 @@
 audio/x-speex
 audio/x-tta
 audio/x-vorbis
+audio/x-vorbis+ogg
 audio/x-wav
 audio/x-wavpack
 audio/x-xm
+image/avi
 image/vnd.rn-realpix
 image/x-pict
 misc/ultravox
 text/google-video-pointer
 text/x-google-video-pointer
 video/3gpp
+video/avi
 video/dv
 video/fli
 video/flv
@@ -108,6 +115,7 @@
 video/x-m4v
 video/x-matroska
 video/x-mpeg
+video/x-mpg
 video/x-ms-asf
 video/x-ms-wm
 video/x-ms-wmv

Modified: trunk/banshee/libbanshee/banshee-transcoder.c
==============================================================================
--- trunk/banshee/libbanshee/banshee-transcoder.c	(original)
+++ trunk/banshee/libbanshee/banshee-transcoder.c	Wed Apr 23 02:40:43 2008
@@ -71,12 +71,12 @@
     gint64 duration;
 
     g_return_val_if_fail(transcoder != NULL, FALSE);
-    
+
     if(!gst_element_query_duration(transcoder->pipeline, &format, &duration) ||
-        !gst_element_query_position(transcoder->conv_elem, &format, &position)) {
+        !gst_element_query_position(transcoder->sink_bin, &format, &position)) {
         return TRUE;
     }
-    
+
     if(transcoder->progress_cb != NULL) {
         transcoder->progress_cb(transcoder, (double)position / (double)duration);
     }
@@ -137,6 +137,7 @@
         case GST_MESSAGE_EOS:
             gst_element_set_state(GST_ELEMENT(transcoder->pipeline), GST_STATE_NULL);
             g_object_unref(G_OBJECT(transcoder->pipeline));
+            transcoder->pipeline = NULL;
             
             transcoder->is_transcoding = FALSE;
             gst_transcoder_stop_iterate_timeout(transcoder);
@@ -314,10 +315,13 @@
 gst_transcoder_free(GstTranscoder *transcoder)
 {
     g_return_if_fail(transcoder != NULL);
-    
-    g_object_unref(G_OBJECT(transcoder->pipeline));
     gst_transcoder_stop_iterate_timeout(transcoder);
     
+    if(GST_IS_ELEMENT(transcoder->pipeline)) {
+        gst_element_set_state(GST_ELEMENT(transcoder->pipeline), GST_STATE_NULL);
+        gst_object_unref(GST_OBJECT(transcoder->pipeline));
+    }
+
     if(transcoder->output_uri != NULL) {
         g_free(transcoder->output_uri);
         transcoder->output_uri = NULL;

Modified: trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer.addin.xml
==============================================================================
--- trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer.addin.xml	(original)
+++ trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer.addin.xml	Wed Apr 23 02:40:43 2008
@@ -16,4 +16,8 @@
     <AudioCdRipper class="Banshee.GStreamer.AudioCdRipper"/>
   </Extension>
 
+  <Extension path="/Banshee/MediaEngine/Transcoder">
+    <Transcoder class="Banshee.GStreamer.Transcoder"/>
+  </Extension>
+
 </Addin>

Modified: trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/AudioCdRipper.cs
==============================================================================
--- trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/AudioCdRipper.cs	(original)
+++ trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/AudioCdRipper.cs	Wed Apr 23 02:40:43 2008
@@ -60,18 +60,17 @@
         public void Begin (string device, bool enableErrorCorrection)
         {
             try {
-                Profile profile = ServiceManager.MediaProfileManager.GetConfiguredActiveProfile ("cd-importing");
-                if (profile != null) {
-                    encoder_pipeline = profile.Pipeline.GetProcessById ("gstreamer");
-                    output_extension = profile.OutputFileExtension;
+                ProfileConfiguration config = ServiceManager.MediaProfileManager.GetActiveProfileConfiguration ("cd-importing");
+                if (config != null) {
+                    encoder_pipeline = config.Profile.Pipeline.GetProcessById ("gstreamer");
+                    output_extension = config.Profile.OutputFileExtension;
                 }
                 
                 if (String.IsNullOrEmpty (encoder_pipeline)) {
                     throw new ApplicationException ();
                 }
                 
-                Hyena.Log.InformationFormat ("Ripping using encoder profile `{0}' with pipeline: {1}", 
-                    profile.Name, encoder_pipeline);
+                Hyena.Log.InformationFormat ("Ripping using encoder profile `{0}' with pipeline: {1}", config.Profile.Name, encoder_pipeline);
             } catch (Exception e) {
                 throw new ApplicationException (Catalog.GetString ("Could not find an encoder for ripping."), e);
             }

Added: trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/Transcoder.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/Transcoder.cs	Wed Apr 23 02:40:43 2008
@@ -0,0 +1,202 @@
+//
+// Transcoder.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.Threading;
+using System.Runtime.InteropServices;
+using Mono.Unix;
+
+using Hyena;
+using Banshee.Base;
+using Banshee.Collection;
+using Banshee.ServiceStack;
+using Banshee.MediaEngine;
+using Banshee.MediaProfiles;
+using Banshee.Configuration.Schema;
+
+namespace Banshee.GStreamer
+{
+    public class Transcoder : ITranscoder
+    {
+        public event TranscoderProgressHandler Progress;
+        public event TranscoderTrackFinishedHandler TrackFinished;
+        public event TranscoderErrorHandler Error;
+
+        private HandleRef handle;
+        private GstTranscoderProgressCallback ProgressCallback;
+        private GstTranscoderFinishedCallback FinishedCallback;
+        private GstTranscoderErrorCallback ErrorCallback;
+        private TrackInfo current_track;
+        private string error_message;
+        private SafeUri managed_output_uri;
+        
+        public Transcoder ()
+        {
+            IntPtr ptr = gst_transcoder_new();
+            
+            if(ptr == IntPtr.Zero) {
+                throw new NullReferenceException(Catalog.GetString("Could not create transcoder"));
+            }
+            
+            handle = new HandleRef(this, ptr);
+            
+            ProgressCallback = new GstTranscoderProgressCallback(OnNativeProgress);
+            FinishedCallback = new GstTranscoderFinishedCallback(OnNativeFinished);
+            ErrorCallback = new GstTranscoderErrorCallback(OnNativeError);
+            
+            gst_transcoder_set_progress_callback(handle, ProgressCallback);
+            gst_transcoder_set_finished_callback(handle, FinishedCallback);
+            gst_transcoder_set_error_callback(handle, ErrorCallback);
+        }
+
+        public void Finish ()
+        {
+            gst_transcoder_free(handle);
+            handle = new HandleRef (this, IntPtr.Zero);
+        }
+        
+        public void Cancel ()
+        {
+            gst_transcoder_cancel(handle);
+            handle = new HandleRef (this, IntPtr.Zero);
+        }
+        
+        public void TranscodeTrack (TrackInfo track, SafeUri outputUri, ProfileConfiguration config)
+        {
+            if(IsTranscoding) {
+                throw new ApplicationException("Transcoder is busy");
+            }
+        
+            Log.DebugFormat ("Transcoding {0} to {1}", track.Uri, outputUri);
+            SafeUri inputUri = track.Uri;
+            managed_output_uri = outputUri;
+            IntPtr input_uri = GLib.Marshaller.StringToPtrGStrdup(inputUri.LocalPath);
+            IntPtr output_uri = GLib.Marshaller.StringToPtrGStrdup(outputUri.LocalPath);
+            
+            error_message = null;
+            
+            current_track = track;
+            gst_transcoder_transcode(handle, input_uri, output_uri, config.Profile.Pipeline.GetProcessById("gstreamer"));
+            
+            GLib.Marshaller.Free(input_uri);
+            GLib.Marshaller.Free(output_uri);
+        }
+        
+        private void OnNativeProgress(IntPtr transcoder, double fraction)
+        {
+            OnProgress (current_track, fraction);
+        }
+        
+        private void OnNativeFinished(IntPtr transcoder)
+        {
+            OnTrackFinished (current_track, managed_output_uri);
+        }
+
+        private void OnNativeError(IntPtr transcoder, IntPtr error, IntPtr debug)
+        {
+            error_message = GLib.Marshaller.Utf8PtrToString(error);
+            
+            if(debug != IntPtr.Zero) {
+                string debug_string = GLib.Marshaller.Utf8PtrToString(debug);
+                if(!String.IsNullOrEmpty (debug_string)) {
+                    error_message = String.Format ("{0}: {1}", error_message, debug_string);
+                }
+            }
+            
+            try {
+                Banshee.IO.File.Delete (managed_output_uri);
+            } catch {}
+            
+            OnError (current_track, error_message);
+        }
+
+        protected virtual void OnProgress (TrackInfo track, double fraction)
+        {
+            TranscoderProgressHandler handler = Progress;
+            if (handler != null) {
+                handler (this, new TranscoderProgressArgs (track, fraction, track.Duration));
+            }
+        }
+        
+        protected virtual void OnTrackFinished (TrackInfo track, SafeUri outputUri)
+        {
+            TranscoderTrackFinishedHandler handler = TrackFinished;
+            if (handler != null) {
+                handler (this, new TranscoderTrackFinishedArgs (track, outputUri));
+            }
+        }
+        
+        protected virtual void OnError (TrackInfo track, string message)
+        {
+            TranscoderErrorHandler handler = Error;
+            if (handler != null) {
+                handler (this, new TranscoderErrorArgs (track, message));
+            }
+        }
+        
+        public bool IsTranscoding {
+            get { return gst_transcoder_get_is_transcoding(handle); }
+        }
+        
+        public string ErrorMessage {
+            get { return error_message; }
+        }
+
+        private delegate void GstTranscoderProgressCallback(IntPtr transcoder, double progress);
+        private delegate void GstTranscoderFinishedCallback(IntPtr transcoder);
+        private delegate void GstTranscoderErrorCallback(IntPtr transcoder, IntPtr error, IntPtr debug);
+
+        [DllImport("libbanshee")]
+        private static extern IntPtr gst_transcoder_new();
+
+        [DllImport("libbanshee")]
+        private static extern void gst_transcoder_free(HandleRef handle);
+
+        [DllImport("libbanshee")]
+        private static extern void gst_transcoder_transcode(HandleRef handle, IntPtr input_uri, 
+            IntPtr output_uri, string encoder_pipeline);
+
+        [DllImport("libbanshee")]
+        private static extern void gst_transcoder_cancel(HandleRef handle);
+
+        [DllImport("libbanshee")]
+        private static extern void gst_transcoder_set_progress_callback(HandleRef handle,
+            GstTranscoderProgressCallback cb);
+
+        [DllImport("libbanshee")]
+        private static extern void gst_transcoder_set_finished_callback(HandleRef handle, 
+            GstTranscoderFinishedCallback cb);
+
+        [DllImport("libbanshee")]
+        private static extern void gst_transcoder_set_error_callback(HandleRef handle, 
+            GstTranscoderErrorCallback cb);
+            
+        [DllImport("libbanshee")]
+        private static extern bool gst_transcoder_get_is_transcoding(HandleRef handle);
+    }
+}

Modified: trunk/banshee/src/Backends/Banshee.GStreamer/Makefile.am
==============================================================================
--- trunk/banshee/src/Backends/Banshee.GStreamer/Makefile.am	(original)
+++ trunk/banshee/src/Backends/Banshee.GStreamer/Makefile.am	Wed Apr 23 02:40:43 2008
@@ -6,7 +6,8 @@
 	Banshee.GStreamer/GstErrors.cs \
 	Banshee.GStreamer/PlayerEngine.cs \
 	Banshee.GStreamer/Service.cs \
-	Banshee.GStreamer/TagList.cs
+	Banshee.GStreamer/TagList.cs \
+	Banshee.GStreamer/Transcoder.cs
 RESOURCES = Banshee.GStreamer.addin.xml
 INSTALL_DIR = $(BACKENDS_INSTALL_DIR)
 

Modified: trunk/banshee/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfConfigurationClient.cs
==============================================================================
--- trunk/banshee/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfConfigurationClient.cs	(original)
+++ trunk/banshee/src/Backends/Banshee.Gnome/Banshee.GnomeBackend/GConfConfigurationClient.cs	Wed Apr 23 02:40:43 2008
@@ -57,17 +57,17 @@
                 return disable_gconf;
             }
         }
-        
+
         private string CreateKey (string @namespace, string part)
         {
             string hash_key = String.Format ("{0}{1}", @namespace, part);
             lock (((ICollection)key_table).SyncRoot) {
                 if (!key_table.ContainsKey (hash_key)) {
                     if (@namespace == null) {
-                        key_table.Add (hash_key, String.Format ("{0}{1}", base_key, StringUtil.CamelCaseToUnderCase (part)));
+                        key_table.Add (hash_key, String.Format ("{0}{1}", base_key, StringUtil.CamelCaseToUnderCase (part.Replace ('/', '_'))));
                     } else {
                         key_table.Add (hash_key, String.Format ("{0}{1}",
-                            base_key, StringUtil.CamelCaseToUnderCase (String.Format ("{0}/{1}", @namespace.Replace (".", "/"), part))
+                            base_key, StringUtil.CamelCaseToUnderCase (String.Format ("{0}/{1}", @namespace.Replace (".", "/"), part.Replace ('/', '_')))
                         ));
                     }
                 }

Added: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/ITranscoder.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/ITranscoder.cs	Wed Apr 23 02:40:43 2008
@@ -0,0 +1,114 @@
+//
+// ITranscoder.cs
+//
+// Author:
+//   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 Banshee.Base;
+using Banshee.MediaProfiles;
+using Banshee.Collection;
+
+namespace Banshee.MediaEngine
+{
+    public delegate void TranscoderProgressHandler (object o, TranscoderProgressArgs args);
+    public delegate void TranscoderTrackFinishedHandler (object o, TranscoderTrackFinishedArgs args);
+    public delegate void TranscoderErrorHandler (object o, TranscoderErrorArgs args);
+ 
+    public interface ITranscoder
+    {
+        event TranscoderProgressHandler Progress;
+        event TranscoderTrackFinishedHandler TrackFinished;
+        event TranscoderErrorHandler Error;
+        
+        void TranscodeTrack (TrackInfo track, SafeUri outputUri, ProfileConfiguration config);
+        void Finish ();
+        void Cancel ();
+    }
+                             
+    public sealed class TranscoderProgressArgs : EventArgs
+    {
+        public TranscoderProgressArgs (TrackInfo track, double fraction, TimeSpan totalTime)
+        {
+            this.track = track;
+            this.fraction = fraction;
+            this.total_time = totalTime;
+        }
+        
+        private double fraction;
+        public double Fraction {
+            get { return fraction; }
+        }
+
+        private TimeSpan total_time;
+        public TimeSpan TotalTime {
+            get { return total_time; }
+        }
+
+        private TrackInfo track;
+        public TrackInfo Track {
+            get { return track; }
+        }
+    }
+
+    public sealed class TranscoderTrackFinishedArgs : EventArgs
+    {
+        public TranscoderTrackFinishedArgs (TrackInfo track, SafeUri uri)
+        {
+            this.track = track;
+            this.uri = uri;
+        }
+
+        private TrackInfo track;
+        public TrackInfo Track {
+            get { return track; }
+        }
+        
+        private SafeUri uri;
+        public SafeUri Uri {
+            get { return uri; }
+        }
+    }
+    
+    public sealed class TranscoderErrorArgs : EventArgs
+    {
+        public TranscoderErrorArgs (TrackInfo track, string message)
+        {
+            this.track = track;
+            this.message = message;
+        }
+        
+        private TrackInfo track;
+        public TrackInfo Track {
+            get { return track; }
+        }
+        
+        private string message;
+        public string Message {
+            get { return message; }
+        }
+    }
+}

Added: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/TranscoderService.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaEngine/TranscoderService.cs	Wed Apr 23 02:40:43 2008
@@ -0,0 +1,257 @@
+//
+// TranscoderService.cs
+//
+// Author:
+//   Aaron Bockover <abockover novell com>
+//   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;
+
+using Mono.Unix;
+using Mono.Addins;
+
+using Banshee.Base;
+using Banshee.ServiceStack;
+using Banshee.Collection;
+using Banshee.MediaProfiles;
+
+namespace Banshee.MediaEngine
+{
+    public class TranscoderService : IService
+    {
+        public delegate void TrackTranscodedHandler (TrackInfo track, SafeUri uri);
+        public delegate void TranscodeCancelledHandler ();
+
+        private struct TranscodeContext
+        {
+            public TrackInfo Track;
+            public SafeUri OutUri;
+            public ProfileConfiguration Config;
+            public TrackTranscodedHandler Handler;
+            public TranscodeCancelledHandler CancelledHandler;
+
+            public TranscodeContext (TrackInfo track, SafeUri out_uri, ProfileConfiguration config, TrackTranscodedHandler handler, TranscodeCancelledHandler cancelledHandler)
+            {
+                Track = track;
+                OutUri = out_uri;
+                Config = config;
+                Handler = handler;
+                CancelledHandler = cancelledHandler;
+            }
+        }
+
+        private static bool transcoder_extension_queried = false;
+        private static TypeExtensionNode transcoder_extension_node = null;
+        private static TypeExtensionNode TranscoderExtensionNode {
+            get { 
+                if (!transcoder_extension_queried) {
+                    transcoder_extension_queried = true;
+                    foreach (TypeExtensionNode node in AddinManager.GetExtensionNodes (
+                        "/Banshee/MediaEngine/Transcoder")) {
+                        transcoder_extension_node = node;
+                        break;
+                    }
+                }
+                return transcoder_extension_node;
+            }
+        }
+                
+        public static bool Supported {
+            get { return TranscoderExtensionNode != null; }
+        }
+
+        private ITranscoder transcoder;
+        private BatchUserJob user_job;
+        private Queue<TranscodeContext> queue;
+        private TranscodeContext current_context;
+
+        public TranscoderService ()
+        {
+            queue = new Queue <TranscodeContext> ();
+
+            try {
+                Banshee.IO.Directory.Delete (cache_dir, true);
+            } catch {}
+
+            Banshee.IO.Directory.Create (cache_dir);
+        }
+
+        private static string cache_dir = Paths.Combine (Paths.ApplicationCache, "transcoder");
+        private static uint count = 0;
+        public static SafeUri GetTempUriFor (string extension)
+        {
+            return new SafeUri (Paths.Combine (cache_dir, String.Format ("{0}.{1}", count++, extension)));
+        }
+
+        private ITranscoder Transcoder {
+            get {
+                if (transcoder == null) {
+                    if (TranscoderExtensionNode != null) {
+                        transcoder = (ITranscoder) TranscoderExtensionNode.CreateInstance ();
+                        transcoder.TrackFinished += OnTrackFinished;
+                        transcoder.Progress += OnProgress;
+                        transcoder.Error += OnError;
+                    } else {
+                        throw new ApplicationException ("No Transcoder extension is installed");
+                    }
+                }
+                return transcoder;
+            }
+        }
+
+        private BatchUserJob UserJob {
+            get {
+                if (user_job == null) {
+                    user_job = new BatchUserJob (Catalog.GetString("Converting {0} of {1}"), Catalog.GetString("Initializing"), "encode");
+                    user_job.CancelMessage = Catalog.GetString("Files are currently being converted to another format. Would you like to stop this?");
+                    user_job.CanCancel = true;
+                    user_job.DelayShow = true;
+                    user_job.CancelRequested += OnCancelRequested;
+                    user_job.Finished += OnFinished;
+                    user_job.Register ();
+                }
+                return user_job;
+            }
+        }
+        
+        private void Reset ()
+        {
+            lock (queue) {
+                if (user_job != null) {
+                    user_job.CancelRequested -= OnCancelRequested;
+                    user_job.Finished -= OnFinished;
+                    user_job.Finish ();
+                    user_job = null;
+                }
+                
+                if (transcoder != null) {
+                    Console.WriteLine ("transcoder.Finish");
+                    transcoder.Finish ();
+                    transcoder = null;
+                }
+
+                foreach (TranscodeContext context in queue) {
+                    context.CancelledHandler ();
+                }
+
+                if (transcoding) {
+                    current_context.CancelledHandler ();
+                    transcoding = false;
+                }
+
+                queue.Clear ();
+            }
+        }
+
+        public void Enqueue (TrackInfo track, ProfileConfiguration config, TrackTranscodedHandler handler, TranscodeCancelledHandler cancelledHandler)
+        {
+            Enqueue (track, GetTempUriFor (config.Profile.OutputFileExtension), config, handler, cancelledHandler);
+        }
+
+        public void Enqueue (TrackInfo track, SafeUri out_uri, ProfileConfiguration config, TrackTranscodedHandler handler, TranscodeCancelledHandler cancelledHandler)
+        {
+            bool start = false;
+            lock (queue) {
+                start = (queue.Count == 0 && !transcoding);
+                queue.Enqueue (new TranscodeContext (track, out_uri, config, handler, cancelledHandler));
+                UserJob.Total++;
+            }
+
+            if (start)
+                ProcessQueue ();
+        }
+
+        private bool transcoding = false;
+        private void ProcessQueue ()
+        {
+            TranscodeContext context;
+            lock (queue) {
+                if (queue.Count == 0) {
+                    Reset ();
+                    return;
+                }
+
+                context = queue.Dequeue ();
+                transcoding = true;
+            }
+
+            current_context = context;
+            UserJob.Status = String.Format("{0} - {1}", context.Track.ArtistName, context.Track.TrackTitle);
+            Transcoder.TranscodeTrack (context.Track, context.OutUri, context.Config);
+        }
+
+#region Transcoder Event Handlers
+
+        private void OnTrackFinished (object o, TranscoderTrackFinishedArgs args)
+        {
+            transcoding = false;
+
+            if (user_job == null || transcoder == null) {
+                return;
+            }
+
+            UserJob.Completed++;
+            current_context.Handler (args.Track, current_context.OutUri);
+
+            ProcessQueue ();
+        }
+        
+        private void OnProgress (object o, TranscoderProgressArgs args)
+        {
+            if (user_job == null) {
+                return;
+            }
+
+            UserJob.DetailedProgress = args.Fraction;
+        }
+        
+        private void OnError (object o, TranscoderErrorArgs args)
+        {
+            Reset ();
+            Hyena.Log.Error (Catalog.GetString ("Cannot Convert File"), args.Message, true);
+        }
+
+#endregion
+                                
+#region User Job Event Handlers        
+        
+        private void OnCancelRequested (object o, EventArgs args)
+        {
+            Reset ();
+        }
+        
+        private void OnFinished (object o, EventArgs args)
+        {
+            Reset ();
+        }
+        
+#endregion
+
+        string IService.ServiceName {
+            get { return "TranscoderService"; }
+        }
+    }
+}

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/MediaProfileManager.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/MediaProfileManager.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/MediaProfileManager.cs	Wed Apr 23 02:40:43 2008
@@ -119,8 +119,8 @@
             foreach(XmlNode variable_node in node.SelectNodes("variable")) {
                 try {
                     PipelineVariable variable = new PipelineVariable(variable_node);
-                    if(!preset_variables.ContainsKey(variable.ID)) {
-                        preset_variables.Add(variable.ID, variable);
+                    if(!preset_variables.ContainsKey(variable.Id)) {
+                        preset_variables.Add(variable.Id, variable);
                     }
                 } catch {
                 }
@@ -135,15 +135,19 @@
 
             foreach(XmlNode profile_node in node.SelectNodes("profile")) {
                 try {
-                    profiles.Add(new Profile(this, profile_node));
+                    Add (new Profile(this, profile_node));
                 } catch(Exception e) {
                     Console.WriteLine(e);
                 }
             }
         }
 
+        private Dictionary<string, string> mimetype_extensions = new Dictionary<string, string> ();
         public void Add(Profile profile)
         {
+            foreach (string mimetype in profile.MimeTypes) {
+                mimetype_extensions[mimetype] = profile.OutputFileExtension;
+            }
             profiles.Add(profile);
         }
 
@@ -186,22 +190,23 @@
             }
         }
         
-        public Profile GetConfiguredActiveProfile(string id)
+        public ProfileConfiguration GetActiveProfileConfiguration (string id)
         {
-            return ProfileConfiguration.LoadActiveProfile(this, id);
+            return ProfileConfiguration.LoadActive (this, id);
         }
         
-        public Profile GetConfiguredActiveProfile(string id, string [] mimetypes)
+        public ProfileConfiguration GetActiveProfileConfiguration(string id, string [] mimetypes)
         {
-            Profile profile = GetConfiguredActiveProfile(id);
-            if(profile != null) {
-                return profile;
+            ProfileConfiguration config = GetActiveProfileConfiguration (id);
+            if(config != null) {
+                return config;
             }
             
             foreach(string mimetype in mimetypes) {
-                profile = GetProfileForMimeType(mimetype);
+                Profile profile = GetProfileForMimeType(mimetype);
                 if(profile != null) {
-                    return profile;
+                    profile.LoadConfiguration (id);
+                    return profile.Configuration;
                 }
             }
             
@@ -226,6 +231,13 @@
             return null;
         }
 
+        public string GetExtensionForMimeType (string mimetype)
+        {
+            if (mimetype_extensions.ContainsKey (mimetype))
+                return mimetype_extensions[mimetype];
+            return null;
+        }
+
         public IEnumerator<Profile> GetEnumerator()
         {
             return profiles.GetEnumerator();

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/Pipeline.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/Pipeline.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/Pipeline.cs	Wed Apr 23 02:40:43 2008
@@ -138,12 +138,12 @@
                 double ?numeric = variable.CurrentValueNumeric;
                 if(numeric != null) {
                     if(variable.CurrentValue.Contains(".")) {
-                        eval.RegisterVariable(variable.ID, numeric.Value);
+                        eval.RegisterVariable(variable.Id, numeric.Value);
                     } else {
-                        eval.RegisterVariable(variable.ID, (int)numeric.Value);
+                        eval.RegisterVariable(variable.Id, (int)numeric.Value);
                     }
                 } else {
-                    eval.RegisterVariable(variable.ID, variable.CurrentValue);
+                    eval.RegisterVariable(variable.Id, variable.CurrentValue);
                 }
             }
             
@@ -231,7 +231,7 @@
         public void AddVariable(PipelineVariable variable)
         {
             if(variables.Contains(variable)) {
-                throw new ApplicationException(String.Format("A variable with ID '{0}' already exists in this profile", variable.ID));
+                throw new ApplicationException(String.Format("A variable with ID '{0}' already exists in this profile", variable.Id));
             }
             
             variables.Add(variable);
@@ -271,7 +271,7 @@
         public IEnumerable<KeyValuePair<string, string>> Configuration {
             get {
                 foreach(PipelineVariable variable in Variables) {
-                    yield return new KeyValuePair<string, string>(variable.ID, variable.CurrentValue);
+                    yield return new KeyValuePair<string, string>(variable.Id, variable.CurrentValue);
                 }
             }
         }
@@ -279,7 +279,7 @@
         public string this[string variableName] {
             set { 
                 foreach(PipelineVariable variable in this) {
-                    if(variable.ID == variableName) {
+                    if(variable.Id == variableName) {
                         variable.CurrentValue = value;
                         break;
                     }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/PipelineVariable.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/PipelineVariable.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/PipelineVariable.cs	Wed Apr 23 02:40:43 2008
@@ -256,7 +256,7 @@
             }
         }
 
-        public string ID {
+        public string Id {
             get { return id; }
             set { id = value; }
         }
@@ -372,7 +372,7 @@
         {
             StringBuilder builder = new StringBuilder();
 
-            builder.Append(String.Format("\tID            = {0}\n", ID));
+            builder.Append(String.Format("\tID            = {0}\n", Id));
             builder.Append(String.Format("\tName          = {0}\n", Name));
             builder.Append(String.Format("\tControl Type  = {0}\n", ControlType));
             builder.Append(String.Format("\tAdvanced      = {0}\n", Advanced));

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/Profile.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/Profile.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/Profile.cs	Wed Apr 23 02:40:43 2008
@@ -61,7 +61,12 @@
         
         public void LoadConfiguration(string configurationId)
         {
-            configuration = ProfileConfiguration.Load(this, configurationId);
+            SetConfiguration (ProfileConfiguration.Load(this, configurationId));
+        }
+        
+        public void SetConfiguration(ProfileConfiguration configuration)
+        {
+            this.configuration = configuration;
             foreach(KeyValuePair<string, string> variable in configuration) {
                 pipeline[variable.Key] = variable.Value;
             }
@@ -69,7 +74,7 @@
         
         public void SaveConfiguration()
         {
-            SaveConfiguration(configuration.ID);
+            SaveConfiguration(configuration.Id);
         }
         
         public void SaveConfiguration(string configurationId)
@@ -79,7 +84,7 @@
             }
             
             foreach(PipelineVariable variable in pipeline) {
-                configuration.Add(variable.ID, variable.CurrentValue);
+                configuration.Add(variable.Id, variable.CurrentValue);
             }
             
             configuration.Save();
@@ -90,7 +95,7 @@
             return mimetypes.Contains(mimetype);
         }
         
-        public string ID {
+        public string Id {
             get { return id; }
             set { id = value; }
         }
@@ -119,10 +124,9 @@
             get { return pipeline; }
             set { pipeline = value; }
         }
-
+        
         public ProfileConfiguration Configuration {
             get { return configuration; }
-            set { configuration = value; }
         }
         
         public IList<string> MimeTypes {
@@ -133,7 +137,7 @@
         {
             StringBuilder builder = new StringBuilder();
 
-            builder.Append(String.Format("ID          = {0}\n", ID));
+            builder.Append(String.Format("ID          = {0}\n", Id));
             builder.Append(String.Format("Name        = {0}\n", Name));
             builder.Append(String.Format("Description = {0}\n", Description));
             builder.Append(String.Format("Extension   = {0}\n", OutputFileExtension));

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/ProfileConfiguration.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/ProfileConfiguration.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.MediaProfiles/ProfileConfiguration.cs	Wed Apr 23 02:40:43 2008
@@ -49,7 +49,7 @@
             return configuration;
         }
 
-        public static Profile LoadActiveProfile(MediaProfileManager manager, string id)
+        public static ProfileConfiguration LoadActive (MediaProfileManager manager, string id)
         {
             string profile_id = ConfigurationClient.Get<string>(MakeConfNamespace(id), "active_profile", string.Empty);
 
@@ -58,8 +58,9 @@
             }
 
             foreach(Profile profile in manager.GetAvailableProfiles()) {
-                if(profile.ID == profile_id) {
-                    return profile;
+                if(profile.Id == profile_id) {
+                    profile.LoadConfiguration (id);
+                    return profile.Configuration;
                 }
             }
 
@@ -68,7 +69,7 @@
         
         public static void SaveActiveProfile(Profile profile, string id)
         {
-            ConfigurationClient.Set<string>(MakeConfNamespace(id), "active_profile", profile.ID);
+            ConfigurationClient.Set<string>(MakeConfNamespace(id), "active_profile", profile.Id);
         }
         
         public ProfileConfiguration(Profile profile, string id)
@@ -124,7 +125,7 @@
             get { return variable_values[variable]; }
         }
         
-        public string ID {
+        public string Id {
             get { return id; }
         }
 
@@ -133,7 +134,11 @@
         }
         
         public Profile Profile {
-            get { return profile; }
+            get {
+                if (profile.Configuration != this)
+                    profile.SetConfiguration (this);
+                return profile;
+            }
         }
 
         protected string ConfNamespace {

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/BatchUserJob.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/BatchUserJob.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/BatchUserJob.cs	Wed Apr 23 02:40:43 2008
@@ -34,18 +34,19 @@
 {
     public class BatchUserJob : UserJob
     {
-        protected string status_format;
+        protected string title_format;
         protected int completed;
         protected int total;
 
-        public BatchUserJob (string title, string statusFormat, params string [] iconNames) : base (title, null, iconNames)
+        public BatchUserJob (string titleFormat, params string [] iconNames) : base (null, null, iconNames)
         {
-            status_format = statusFormat;
+            title_format = titleFormat;
         }
 
         public int Completed {
             get { return completed; }
             set {
+                detailed_progress = 0;
                 completed = value;
                 UpdateProgress ();
                 if (total > 0 && completed == total)
@@ -61,12 +62,23 @@
             }
         }
 
+        private double detailed_progress = 0;
+        public double DetailedProgress {
+            get { return detailed_progress; }
+            set {
+                if (value < 1.0) {
+                    detailed_progress = value;
+                    UpdateProgress ();
+                }
+            }
+        }
+
         protected void UpdateProgress ()
         {
             if (Total > 0) {
                 FreezeUpdate ();
-                Status = String.Format (status_format, completed, total);
-                Progress = (double)Completed / (double)Total;
+                Title = String.Format (title_format, completed == total ? completed : completed + 1, total);
+                Progress = Math.Max (0.00001, ((double)Completed / (double)Total) + (DetailedProgress / (double) Total));
                 ThawUpdate (true);
             }
         }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/ServiceManager.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/ServiceManager.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.ServiceStack/ServiceManager.cs	Wed Apr 23 02:40:43 2008
@@ -66,6 +66,7 @@
             RegisterService<SourceManager> ();
             RegisterService<MediaProfileManager> ();
             RegisterService<PlayerEngineService> ();
+            RegisterService<TranscoderService> ();
             RegisterService<PlaybackControllerService> ();
             RegisterService<ImportSourceManager> ();
             RegisterService<LibraryImportManager> ();

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Services.addin.xml
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Services.addin.xml	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Services.addin.xml	Wed Apr 23 02:40:43 2008
@@ -20,6 +20,10 @@
     <ExtensionNode name="AudioCdRipper"/>
   </ExtensionPoint>
 
+  <ExtensionPoint path="/Banshee/MediaEngine/Transcoder">
+    <ExtensionNode name="Transcoder"/>
+  </ExtensionPoint>
+
   <ExtensionPoint path="/Banshee/Platform/HardwareManager">
     <ExtensionNode name="HardwareManager"/>
   </ExtensionPoint>

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Services.mdp
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Services.mdp	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Services.mdp	Wed Apr 23 02:40:43 2008
@@ -1,4 +1,4 @@
-<Project name="Banshee.Services" fileversion="2.0" UseParentDirectoryAsNamespace="True" language="C#" clr-version="Net_2_0" ctype="DotNetProject">
+<Project name="Banshee.Services" fileversion="2.0" language="C#" clr-version="Net_2_0" UseParentDirectoryAsNamespace="True" ctype="DotNetProject">
   <Configurations active="Debug">
     <Configuration name="Debug" ctype="DotNetProjectConfiguration">
       <Output directory="../../../bin" assembly="Banshee.Services" />
@@ -148,6 +148,8 @@
     <File name="Banshee.Collection.Database/CachedList.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.ServiceStack/BatchUserJob.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Sources/IDiskUsageReporter.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.MediaEngine/ITranscoder.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.MediaEngine/TranscoderService.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Preferences/Root.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Preferences/Preference.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Preferences/Section.cs" subtype="Code" buildaction="Compile" />
@@ -182,4 +184,4 @@
     <AsmRefVar />
     <ProjectRefVar />
   </MonoDevelop.Autotools.MakefileInfo>
-</Project>
\ No newline at end of file
+</Project>

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/PrimarySource.cs	Wed Apr 23 02:40:43 2008
@@ -322,6 +322,7 @@
                 }
 
                 try {
+                    DeleteTrackJob.Status = String.Format ("{0} - {1}", track.ArtistName, track.TrackTitle);
                     DeleteTrack (track);
                 } catch (Exception e) {
                     Log.Exception (e);
@@ -364,9 +365,6 @@
 
             CachedList<DatabaseTrackInfo> cached_list = CachedList<DatabaseTrackInfo>.CreateFromModelSelection (model);
             AddTrackList (cached_list);
-
-            OnTracksAdded ();
-            OnUserNotifyUpdated ();
             return true;
         }
 
@@ -380,50 +378,69 @@
             get { return is_deleting; }
         }
 
+        protected virtual void AddTrackAndIncrementCount (DatabaseTrackInfo track)
+        {
+            AddTrackJob.Status = String.Format ("{0} - {1}", track.ArtistName, track.TrackTitle);
+            AddTrack (track);
+            IncrementAddedTracks ();
+        }
+
         protected virtual void AddTrackList (CachedList<DatabaseTrackInfo> list)
         {
             is_adding = true;
-            AddTrackJob.Total += (int)list.Count;
+            AddTrackJob.Total += (int) list.Count;
 
             foreach (DatabaseTrackInfo track in list) {
                 if (track == null) {
-                    AddTrackJob.Completed++;
+                    IncrementAddedTracks ();
                     continue;
                 }
 
                 try {
-                    AddTrack (track);
+                    AddTrackJob.Status = String.Format ("{0} - {1}", track.ArtistName, track.TrackTitle);
+                    AddTrackAndIncrementCount (track);
                 } catch (Exception e) {
+                    IncrementAddedTracks ();
                     Log.Exception (e);
                     ErrorSource.AddMessage (e.Message, track.Uri.ToString ());
                 }
-
-                AddTrackJob.Completed++;
-                if (AddTrackJob.Completed % 10 == 0 && !AddTrackJob.IsFinished) {
-                    OnTracksAdded ();
-                }
             }
             is_adding = false;
-
-            if (AddTrackJob.Total == AddTrackJob.Completed) {
-                add_track_job.Finish ();
-                add_track_job = null;
-            }
         }
 
-        protected override void PruneArtistsAlbums ()
+        protected void IncrementAddedTracks ()
         {
-            ServiceManager.DbConnection.Execute (prune_artists_albums_command);
-            base.PruneArtistsAlbums ();
+            bool finished = false, notify = false;
+
+            lock (this) {
+                add_track_job.Completed++;
+
+                if (add_track_job.IsFinished) {
+                    finished = true;
+                    add_track_job = null;
+                } else {
+                    add_track_job.Status = String.Empty;
+                    if (add_track_job.Completed % 10 == 0)
+                        notify = true;
+                }
+            }
+
+            if (notify || finished)
+                OnTracksAdded ();
+
+            if (finished)
+                OnUserNotifyUpdated ();
         }
 
         private BatchUserJob add_track_job;
         protected BatchUserJob AddTrackJob {
             get {
-                if (add_track_job == null) {
-                    add_track_job = new BatchUserJob (String.Format (Catalog.GetString ("Adding Items to {0}"), Name), Catalog.GetString ("Adding {0} of {1}"), Properties.GetStringList ("Icon.Name"));
-                    add_track_job.DelayShow = true;
-                    add_track_job.Register ();
+                lock (this) {
+                    if (add_track_job == null) {
+                        add_track_job = new BatchUserJob (String.Format (Catalog.GetString ("Adding {0} of {1} to {2}"), "{0}", "{1}", Name), Properties.GetStringList ("Icon.Name"));
+                        //add_track_job.DelayShow = true;
+                        add_track_job.Register ();
+                    }
                 }
                 return add_track_job;
             }
@@ -432,13 +449,24 @@
         private BatchUserJob delete_track_job;
         protected BatchUserJob DeleteTrackJob {
             get {
-                if (delete_track_job == null) {
-                    delete_track_job = new BatchUserJob (String.Format (Catalog.GetString ("Deleting Items From {0}"), Name), Catalog.GetString ("Deleting {0} of {1}"), Properties.GetStringList ("Icon.Name"));
-                    delete_track_job.DelayShow = true;
-                    delete_track_job.Register ();
+                lock (this) {
+                    if (delete_track_job == null) {
+                        delete_track_job = new BatchUserJob (String.Format (Catalog.GetString ("Deleting {0} of {1} From {0}"), "{0}", "{1}", Name),
+                                Properties.GetStringList ("Icon.Name"));
+                        //delete_track_job.DelayShow = true;
+                        delete_track_job.Register ();
+                    }
                 }
                 return delete_track_job;
             }
         }
+
+
+        protected override void PruneArtistsAlbums ()
+        {
+            ServiceManager.DbConnection.Execute (prune_artists_albums_command);
+            base.PruneArtistsAlbums ();
+        }
+
     }
 }

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	Wed Apr 23 02:40:43 2008
@@ -60,6 +60,8 @@
         public event EventHandler MessageNotify;
         public event SourceEventHandler ChildSourceAdded;
         public event SourceEventHandler ChildSourceRemoved;
+
+        public delegate void OpenPropertiesDelegate ();
         
         protected Source (string generic_name, string name, int order)
         {

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	Wed Apr 23 02:40:43 2008
@@ -54,11 +54,13 @@
 	Banshee.MediaEngine/IAudioCdRipper.cs \
 	Banshee.MediaEngine/IEqualizer.cs \
 	Banshee.MediaEngine/IPlayerEngineService.cs \
+	Banshee.MediaEngine/ITranscoder.cs \
 	Banshee.MediaEngine/NullPlayerEngine.cs \
 	Banshee.MediaEngine/PlayerEngine.cs \
 	Banshee.MediaEngine/PlayerEngineEvent.cs \
 	Banshee.MediaEngine/PlayerEngineService.cs \
 	Banshee.MediaEngine/PlayerEngineState.cs \
+	Banshee.MediaEngine/TranscoderService.cs \
 	Banshee.MediaProfiles/MediaProfileManager.cs \
 	Banshee.MediaProfiles/Pipeline.cs \
 	Banshee.MediaProfiles/PipelineVariable.cs \

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/SourceActions.cs	Wed Apr 23 02:40:43 2008
@@ -305,6 +305,11 @@
 
         private void OnSourceProperties (object o, EventArgs args)
         {
+            if (ActionSource.Properties.Contains ("SourceProperties.GuiHandler")) {
+                ActionSource.Properties.Get<Source.OpenPropertiesDelegate> ("SourceProperties.GuiHandler") ();
+                return;
+            }
+
             SmartPlaylistSource source = ActionSource as SmartPlaylistSource;
             if (source != null) {
                 Editor ed = new Editor (source);

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileComboBoxConfigurable.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileComboBoxConfigurable.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileComboBoxConfigurable.cs	Wed Apr 23 02:40:43 2008
@@ -70,10 +70,10 @@
             tag.Style = Pango.Style.Italic;
             description.Buffer.TagTable.Add(tag);
             
-            Profile profile = manager.GetConfiguredActiveProfile(configurationId);
+            ProfileConfiguration config = manager.GetActiveProfileConfiguration (configurationId);
             
-            if(profile != null) {
-                Combo.SetActiveProfile(profile);
+            if(config != null) {
+                Combo.SetActiveProfile(config.Profile);
                 SetDescription();
             }
             

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileConfigurationDialog.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileConfigurationDialog.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.MediaProfiles.Gui/ProfileConfigurationDialog.cs	Wed Apr 23 02:40:43 2008
@@ -210,10 +210,10 @@
                         throw new ApplicationException("Control could not be created");
                     }
                     
-                    variable_widgets.Add(variable.ID, control);
+                    variable_widgets.Add(variable.Id, control);
                     
                     if(variable.ControlType != PipelineVariableControlType.Check) {
-                        variable_widgets.Add(".label." + variable.ID, label);
+                        variable_widgets.Add(".label." + variable.Id, label);
                     }
 
                     control.Show();

Added: trunk/banshee/src/Core/Banshee.ThickClient/ThemeIcons/22x22/actions/encode.png
==============================================================================
Binary files (empty file) and trunk/banshee/src/Core/Banshee.ThickClient/ThemeIcons/22x22/actions/encode.png	Wed Apr 23 02:40:43 2008 differ

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	Wed Apr 23 02:40:43 2008
@@ -112,7 +112,7 @@
         }
 
         private bool had_write_error = false;
-        protected override bool IsReadOnly {
+        public override bool IsReadOnly {
             get { return volume.IsReadOnly || had_write_error; }
         }
 
@@ -133,28 +133,24 @@
             set { write_path = value; }
         }
 
-        protected override void AddTrack (DatabaseTrackInfo track)
+        protected override void AddTrackToDevice (DatabaseTrackInfo track, SafeUri fromUri)
         {
             if (track.PrimarySourceId == DbId)
                 return;
 
-            SafeUri new_uri = new SafeUri (GetTrackPath (track));
-            try {
-                // 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 (track.Uri, new_uri, false);
-
-                    DatabaseTrackInfo copied_track = new DatabaseTrackInfo (track);
-                    copied_track.PrimarySource = this;
-                    copied_track.Uri = new_uri;
-                    copied_track.Save (false);
-                }
-            } catch (System.IO.FileNotFoundException) {
-                had_write_error = true;
-                throw;
+            SafeUri new_uri = new SafeUri (GetTrackPath (track, System.IO.Path.GetExtension (fromUri.LocalPath)));
+            // 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;
+                copied_track.Save (false);
             }
         }
 
@@ -182,7 +178,7 @@
             get { return MediaCapabilities == null ? -1 : MediaCapabilities.FolderDepth; }
         }
 
-        private string GetTrackPath (TrackInfo track)
+        private string GetTrackPath (TrackInfo track, string ext)
         {
             string file_path = WritePath;
 
@@ -224,7 +220,7 @@
             */
 
             file_path = System.IO.Path.Combine (file_path, FileNamePattern.CreateFromTrackInfo (track));
-            file_path += System.IO.Path.GetExtension (track.Uri.LocalPath);
+            file_path += ext;
 
             return file_path;
         }

Modified: trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs	Wed Apr 23 02:40:43 2008
@@ -179,8 +179,10 @@
                     writer.Write ("foo");
                 }
                 Track mtp_track = new Track (System.IO.Path.GetFileName (empty_file.LocalPath), 3);
-                mtp_device.UploadTrack (empty_file.AbsolutePath, mtp_track, mtp_device.MusicFolder);
-                mtp_device.Remove (mtp_track);
+                lock (mtp_device) {
+                    mtp_device.UploadTrack (empty_file.AbsolutePath, mtp_track, mtp_device.MusicFolder);
+                    mtp_device.Remove (mtp_track);
+                }
             } finally {
                 Banshee.IO.File.Delete (empty_file);
             }
@@ -191,14 +193,18 @@
         public override void Rename (string newName)
         {
             base.Rename (newName);
-            mtp_device.Name = newName;
+            lock (mtp_device) {
+                mtp_device.Name = newName;
+            }
         }
 
         public override long BytesUsed {
             get {
 				long count = 0;
-				foreach (DeviceStorage s in mtp_device.GetStorage ()) {
-					count += (long) s.MaxCapacity - (long) s.FreeSpaceInBytes;
+                lock (mtp_device) {
+                    foreach (DeviceStorage s in mtp_device.GetStorage ()) {
+                        count += (long) s.MaxCapacity - (long) s.FreeSpaceInBytes;
+                    }
                 }
 				return count;
             }
@@ -207,26 +213,31 @@
         public override long BytesCapacity {
             get {
 				long count = 0;
-				foreach (DeviceStorage s in mtp_device.GetStorage ()) {
-					count += (long) s.MaxCapacity;
+                lock (mtp_device) {
+                    foreach (DeviceStorage s in mtp_device.GetStorage ()) {
+                        count += (long) s.MaxCapacity;
+                    }
                 }
 				return count;
             }
         }
 
-        protected override bool IsReadOnly {
+        public override bool IsReadOnly {
             get { return false; }
         }
 
-        protected override void AddTrack (DatabaseTrackInfo track)
+        protected override void AddTrackToDevice (DatabaseTrackInfo track, SafeUri fromUri)
         {
             if (track.PrimarySourceId == DbId)
                 return;
 
-            Track mtp_track = TrackInfoToMtpTrack (track);
+            Track mtp_track = TrackInfoToMtpTrack (track, fromUri);
             bool video = (track.MediaAttributes & TrackMediaAttributes.VideoStream) != 0;
-            Console.WriteLine ("Sending track {0}, is video? {1}", track, video);
-            mtp_device.UploadTrack (track.Uri.AbsolutePath, mtp_track, video ? mtp_device.VideoFolder : mtp_device.MusicFolder);
+            Console.WriteLine ("Sending file {0}, is video? {1}", fromUri.LocalPath, video);
+            // TODO send callback for smoother progress bar
+            lock (mtp_device) {
+                mtp_device.UploadTrack (fromUri.LocalPath, mtp_track, video ? mtp_device.VideoFolder : mtp_device.MusicFolder, OnUploadProgress);
+            }
 
             MtpTrackInfo new_track = new MtpTrackInfo (mtp_track);
             new_track.PrimarySource = this;
@@ -234,15 +245,23 @@
             track_map[new_track.TrackId] = mtp_track;
         }
 
+        private int OnUploadProgress (ulong sent, ulong total, IntPtr data)
+        {
+            AddTrackJob.DetailedProgress = (double) sent / (double) total;
+            return 0;
+        }
+
         protected override void DeleteTrack (DatabaseTrackInfo track)
         {
-            mtp_device.Remove (track_map [track.TrackId]);
-            track_map.Remove (track.TrackId);
+            lock (mtp_device) {
+                mtp_device.Remove (track_map [track.TrackId]);
+                track_map.Remove (track.TrackId);
+            }
         }
 
-        public Track TrackInfoToMtpTrack (TrackInfo track)
+        public Track TrackInfoToMtpTrack (TrackInfo track, SafeUri fromUri)
         {
-			Track f = new Track (System.IO.Path.GetFileName (track.Uri.LocalPath), (ulong) track.FileSize);
+			Track f = new Track (System.IO.Path.GetFileName (fromUri.LocalPath), (ulong) Banshee.IO.File.GetSize (fromUri));
 			f.Album = track.AlbumTitle;
 			f.Artist = track.ArtistName;
 			f.Duration = (uint)track.Duration.TotalMilliseconds;
@@ -258,7 +277,10 @@
         public override void Dispose ()
         {
 			base.Dispose ();
-			mtp_device.Dispose ();
+            lock (mtp_device) {
+                mtp_device.Dispose ();
+            }
+            mtp_device = null;
             mtp_source = null;
         }
 

Copied: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapPropertiesDialog.cs (from r3804, /branches/banshee/stable/src/Core/Banshee.Base/Dap/DapPropertiesDialog.cs)
==============================================================================
--- /branches/banshee/stable/src/Core/Banshee.Base/Dap/DapPropertiesDialog.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapPropertiesDialog.cs	Wed Apr 23 02:40:43 2008
@@ -1,30 +1,31 @@
-/***************************************************************************
- *  DapPropertiesDialog.cs
- *
- *  Copyright (C) 2005-2006 Novell, Inc.
- *  Written by Aaron Bockover <aaron abock org>
- ****************************************************************************/
-
-/*  THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW: 
- *
- *  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.
- */
+//
+// DapPropertiesDialog.cs
+//
+// Authors:
+//   Aaron Bockover <abockover novell com>
+//   Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2005-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 Mono.Unix;
@@ -33,14 +34,14 @@
 using Banshee.Base;
 using Banshee.Widgets;
 using Banshee.Sources;
-using Banshee.AudioProfiles.Gui;
+using Banshee.ServiceStack;
+using Banshee.MediaProfiles.Gui;
 
 namespace Banshee.Dap
 {
     public class DapPropertiesDialog : Dialog
     {
         private DapSource source;
-        private DapDevice device;
         private Entry nameEntry;
         private Entry ownerEntry;
         
@@ -51,21 +52,20 @@
         
         public DapPropertiesDialog(DapSource source) : base(
             // Translators: {0} is the name assigned to a Digital Audio Player by its owner
-            String.Format(Catalog.GetString("{0} Properties"), source.Device.Name),
+            String.Format(Catalog.GetString("{0} Properties"), source.Name),
             null,
             DialogFlags.Modal | DialogFlags.NoSeparator,
             Stock.Close,
             ResponseType.Close)
         {
             this.source = source;
-            this.device = source.Device;
             
             HBox iconbox = new HBox();
             iconbox.Spacing = 10;
-            Image icon = new Image();
-            icon.Yalign = 0.0f;
-            icon.Pixbuf = device.GetIcon(48);
-            iconbox.PackStart(icon, false, false, 0);
+            //Image icon = new Image (source.Properties.Get<string> ("Icon.Names")[0], IconSize.Dialog);
+            //icon.Yalign = 0.0f;
+            //icon.Pixbuf = device.GetIcon(48);
+            //iconbox.PackStart(icon, false, false, 0);
             
             VBox box = new VBox();
             box.Spacing = 10;
@@ -74,28 +74,28 @@
             table.ColumnSpacing = 10;
             table.RowSpacing = 5;
             
-            if(!device.IsReadOnly && device.CanSetName) {
-                nameEntry = table.AddEntry(Catalog.GetString("Device name"), device.Name);
+            if(!source.IsReadOnly && source.CanRename) {
+                nameEntry = table.AddEntry(Catalog.GetString("Device name"), source.Name);
                 nameEntry.Changed += OnEntryChanged;
             } else {
-                table.AddLabel(Catalog.GetString("Device name"), device.Name);
+                table.AddLabel(Catalog.GetString("Device name"), source.Name);
             }
             
-            if(device.ShowOwner) {
+            /*if(device.ShowOwner) {
                 if(!device.IsReadOnly && device.CanSetOwner) {
                     ownerEntry = table.AddEntry(Catalog.GetString("Owner name"), device.Owner);
                     ownerEntry.Changed += OnEntryChanged;
                 } else {
                     table.AddLabel(Catalog.GetString("Owner name"), device.Owner);
                 }
-            }
+            }*/
             
-            if(!device.IsReadOnly) {   
+            if(!source.IsReadOnly) {
                 try {
                     VBox profile_description_box = new VBox();
-                    ProfileComboBoxConfigurable profile_box = new ProfileComboBoxConfigurable(Globals.AudioProfileManager, 
-                        device.Uuid, profile_description_box);
-                    profile_box.Combo.MimeTypeFilter = device.SupportedPlaybackMimeTypes;
+                    ProfileComboBoxConfigurable profile_box = new ProfileComboBoxConfigurable(ServiceManager.MediaProfileManager, 
+                        source.UniqueId, profile_description_box);
+                    profile_box.Combo.MimeTypeFilter = source.AcceptableMimeTypes;
                     table.AddWidget(Catalog.GetString("Encode to"), profile_box);
                     table.AddWidget(null, profile_description_box);
                     profile_description_box.Show();
@@ -106,7 +106,7 @@
                 }
             }
             
-            table.AddWidget(Catalog.GetString("Volume usage"), UsedProgressBar);
+            table.AddWidget(Catalog.GetString("Capacity used"), UsedProgressBar);
     
             box.PackStart(table, true, true, 0);
             
@@ -114,13 +114,13 @@
             extTable.ColumnSpacing = 10;
             extTable.RowSpacing = 5;
             
-            foreach(DapDevice.Property property in device.Properties) {
+            /*foreach(DapDevice.Property property in device.Properties) {
                 extTable.AddLabel(property.Name, property.Value);
             }
             
             Expander expander = new Expander(Catalog.GetString("Advanced details"));
             expander.Add(extTable);
-            box.PackStart(expander, false, false, 0);
+            box.PackStart(expander, false, false, 0); */
             
             BorderWidth = 10;
             Resizable = false;
@@ -128,12 +128,27 @@
             iconbox.ShowAll();
             VBox.Add(iconbox);
         }
+
+        public void RunDialog ()
+        {
+            Run ();
+
+            if (!String.IsNullOrEmpty (name_update)) {
+                source.Rename (name_update);
+            }
+
+            Destroy ();
+        }
         
         private ProgressBar UsedProgressBar {
             get {
                 ProgressBar usedBar = new ProgressBar();
-                usedBar.Fraction = source.DiskUsageFraction;
-                usedBar.Text = source.DiskUsageString + " " + source.DiskAvailableString;
+                usedBar.Fraction = (double)source.BytesUsed / (double)source.BytesCapacity;
+                usedBar.Text = String.Format (
+                    Catalog.GetString("{0} of {1}"),
+                    new Hyena.Query.FileSizeQueryValue (source.BytesUsed).ToUserQuery (),
+                    new Hyena.Query.FileSizeQueryValue (source.BytesCapacity).ToUserQuery ()
+                );
                 return usedBar;
             }
         }

Modified: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs	Wed Apr 23 02:40:43 2008
@@ -38,12 +38,15 @@
 using Banshee.Collection;
 using Banshee.Collection.Database;
 using Banshee.Hardware;
+using Banshee.MediaEngine;
+using Banshee.MediaProfiles;
 
 namespace Banshee.Dap
 {
     public abstract class DapSource : RemovableSource
     {
         protected IDevice device;
+        protected string [] acceptable_mimetypes;
 
         internal IDevice Device {
             get { return device; }
@@ -64,8 +67,14 @@
                 Properties.SetStringList ("Icon.Name", FallbackIcon);
             }
 
-            if (String.IsNullOrEmpty (Name)) Name = device.Name;
+            Properties.Set<string> ("SourcePropertiesActionLabel", Catalog.GetString ("Device Properties"));
+            Properties.Set<OpenPropertiesDelegate> ("SourceProperties.GuiHandler", delegate { new DapPropertiesDialog (this).RunDialog (); });
+
             GenericName = IsMediaDevice ? Catalog.GetString ("Audio Player") : Catalog.GetString ("Media Device");
+            if (String.IsNullOrEmpty (Name))
+                Name = device.Name;
+
+            acceptable_mimetypes = (MediaCapabilities != null) ? MediaCapabilities.PlaybackMimeTypes : new string [] {"taglib/mp3"};
         }
 
         bool initialized = false;
@@ -81,6 +90,47 @@
 
         protected abstract bool Initialize (IDevice device);
 
+        protected bool TrackNeedsTranscoding (TrackInfo track)
+        {
+            foreach (string mimetype in AcceptableMimeTypes) {
+                if (ServiceManager.MediaProfileManager.GetExtensionForMimeType (track.MimeType) == ServiceManager.MediaProfileManager.GetExtensionForMimeType (mimetype)) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        private ProfileConfiguration preferred_config;
+        private ProfileConfiguration PreferredConfiguration {
+            get {
+                if (preferred_config == null) {
+                    preferred_config = ServiceManager.MediaProfileManager.GetActiveProfileConfiguration (UniqueId, acceptable_mimetypes);
+                }
+                return preferred_config;
+            }
+        }
+
+        protected override void AddTrackAndIncrementCount (DatabaseTrackInfo track)
+        {
+            if (TrackNeedsTranscoding (track)) {
+                ServiceManager.Get <TranscoderService> ().Enqueue (track, PreferredConfiguration, delegate (TrackInfo ti, SafeUri outUri) {
+                    AddTrackJob.Status = String.Format ("{0} - {1}", track.ArtistName, track.TrackTitle);
+                    try {
+                        AddTrackToDevice (track, outUri);
+                    } catch (Exception e) {
+                        Log.Exception (e);
+                    }
+                    IncrementAddedTracks ();
+                }, delegate { IncrementAddedTracks (); });
+            } else {
+                AddTrackToDevice (track, track.Uri);
+                IncrementAddedTracks ();
+            }
+        }
+
+        protected abstract void AddTrackToDevice (DatabaseTrackInfo track, SafeUri fromUri);
+
         protected virtual bool IsMediaDevice {
             get { return device.MediaCapabilities != null; }
         }
@@ -93,6 +143,14 @@
             get { return device.MediaCapabilities; }
         }
 
+        public string [] AcceptableMimeTypes {
+            get { return acceptable_mimetypes; }
+        }
+
+        public override bool HasProperties {
+            get { return true; }
+        }
+
         public override void AddChildSource (Source child)
         {
             if (initialized && child is Banshee.Playlist.AbstractPlaylistSource) {

Modified: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/RemovableSource.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/RemovableSource.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/RemovableSource.cs	Wed Apr 23 02:40:43 2008
@@ -129,7 +129,7 @@
         {
         }
 
-        protected abstract bool IsReadOnly { get; }
+        public abstract bool IsReadOnly { get; }
         
         public abstract long BytesUsed { get; }
         public abstract long BytesCapacity { get; }

Modified: trunk/banshee/src/Dap/Banshee.Dap/Makefile.am
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Makefile.am	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Makefile.am	Wed Apr 23 02:40:43 2008
@@ -4,6 +4,7 @@
 INSTALL_DIR = $(EXTENSIONS_INSTALL_DIR)
 
 SOURCES =  \
+	Banshee.Dap.Gui/DapPropertiesDialog.cs \
 	Banshee.Dap/DapService.cs \
 	Banshee.Dap/DapSource.cs \
 	Banshee.Dap/RemovableSource.cs

Modified: trunk/banshee/src/Libraries/Mtp/Mtp/Track.cs
==============================================================================
--- trunk/banshee/src/Libraries/Mtp/Mtp/Track.cs	(original)
+++ trunk/banshee/src/Libraries/Mtp/Mtp/Track.cs	Wed Apr 23 02:40:43 2008
@@ -168,8 +168,6 @@
             if (ext.Length > 0)
                 ext = ext.Substring (1, ext.Length - 1);
 
-            Console.WriteLine ("DetectFileType for {0} is {1}", track.FileName, ext);
-
             FileType type = (FileType) Enum.Parse (typeof(FileType), ext, true);
             //if (type == null)
             //    return FileType.UNKNOWN;



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