conduit r1721 - in branches/gnome-2-24: conduit/datatypes conduit/gtkui conduit/modules conduit/modules/iPodModule conduit/utils test/python-tests



Author: arosenfeld
Date: Wed Sep 10 03:53:07 2008
New Revision: 1721
URL: http://svn.gnome.org/viewvc/conduit?rev=1721&view=rev

Log:
Merged changes from trunk SVN revision 1720.



Modified:
   branches/gnome-2-24/conduit/datatypes/Audio.py
   branches/gnome-2-24/conduit/datatypes/Video.py
   branches/gnome-2-24/conduit/gtkui/SimpleConfigurator.py
   branches/gnome-2-24/conduit/modules/AudioVideoConverterModule.py
   branches/gnome-2-24/conduit/modules/iPodModule/iPodModule.py
   branches/gnome-2-24/conduit/utils/MediaFile.py
   branches/gnome-2-24/test/python-tests/TestCoreConvertAudioVideo.py

Modified: branches/gnome-2-24/conduit/datatypes/Audio.py
==============================================================================
--- branches/gnome-2-24/conduit/datatypes/Audio.py	(original)
+++ branches/gnome-2-24/conduit/datatypes/Audio.py	Wed Sep 10 03:53:07 2008
@@ -8,7 +8,8 @@
 
 PRESET_ENCODINGS = {
     "ogg":{"acodec":"vorbisenc","format":"oggmux","file_extension":"ogg"},
-    "wav":{"acodec":"wavenc","file_extension":"wav"}
+    "wav":{"acodec":"wavenc","file_extension":"wav"},
+    "mp3":{"acodec":"lame", "file_extension": "mp3"},
     }
 
 def mimetype_is_audio(mimetype):

Modified: branches/gnome-2-24/conduit/datatypes/Video.py
==============================================================================
--- branches/gnome-2-24/conduit/datatypes/Video.py	(original)
+++ branches/gnome-2-24/conduit/datatypes/Video.py	Wed Sep 10 03:53:07 2008
@@ -8,7 +8,7 @@
 # "arate":44100, "abitrate":"64k"
 # "fps":15
 PRESET_ENCODINGS = {
-    "divx":{"vcodec":"xvidenc", "acodec":"lame", "format":"avimux", "vtag":"DIVX", "file_extension":"avi", },
+    "divx":{"vcodec":"xvidenc", "acodec":"lame", "format":"avimux", "vtag":"DIVX", "file_extension":"avi", "mimetype": "video/x-msvideo"},
     #breaks on single channel audio files because ffmpeg vorbis encoder only suuport stereo
     "ogg":{"vcodec":"theoraenc", "acodec":"vorbisenc", "format":"oggmux", "file_extension":"ogg"},
     #needs mencoder or ffmpeg compiled with mp3 support
@@ -36,7 +36,7 @@
         MediaFile.MediaFile.__init__(self, URI, **kwargs)
 
     def get_video_duration(self):
-        return _get_metadata('duration')
+        return self._get_metadata('duration')
 
     def get_video_size(self):
-        return _get_metadata('width'),_get_metadata('height')
+        return self._get_metadata('width'), self._get_metadata('height')

Modified: branches/gnome-2-24/conduit/gtkui/SimpleConfigurator.py
==============================================================================
--- branches/gnome-2-24/conduit/gtkui/SimpleConfigurator.py	(original)
+++ branches/gnome-2-24/conduit/gtkui/SimpleConfigurator.py	Wed Sep 10 03:53:07 2008
@@ -20,8 +20,8 @@
                     "InitialValue" : value or function
                     }
                 ]
+                
     Or, alternatively:
-        
 
         maps = [
                     {
@@ -29,6 +29,7 @@
                     "Kind" : "text", "check" or "list",
                     "Callback" : function,
                     "InitialValue" : value or function
+                    "Values": list if Kind = "list"
                     }
                 ]        
     """
@@ -50,7 +51,8 @@
         self.dialogParent = window
         #the child widget to contain the custom settings
         self.customSettings = gtk.Table(rows=0, columns=2)
-        self.customSettings.set_row_spacings(8)
+        self.customSettings.set_row_spacings(4)
+        self.customSettings.set_border_width(4)
         
         #The dialog is loaded from a glade file
         gladeFile = os.path.join(conduit.SHARED_DATA_DIR, "conduit.glade")
@@ -123,6 +125,8 @@
         """
         #For each item in the mappings list create the appropriate widget
         for l in self.mappings:
+            if "Title" in l:
+                label = gtk.Label(l["Title"])
             if 'Kind' in l:
                 kind = l['Kind']
                 widget = {'text': gtk.Entry,
@@ -172,7 +176,7 @@
             row = table.get_property('n-rows') + 1
             table.resize(row, 2)
             if label:
-                table.attach(label, 0, 1, row - 1, row)
+                table.attach(label, 0, 1, row - 1, row, xpadding = 8)
                 table.attach(widget, 1, 2, row - 1, row)
             else:
-                table.attach(widget, 0, 2, row - 1, row)
+                table.attach(widget, 0, 2, row - 1, row, xpadding = 8)

Modified: branches/gnome-2-24/conduit/modules/AudioVideoConverterModule.py
==============================================================================
--- branches/gnome-2-24/conduit/modules/AudioVideoConverterModule.py	(original)
+++ branches/gnome-2-24/conduit/modules/AudioVideoConverterModule.py	Wed Sep 10 03:53:07 2008
@@ -1,6 +1,8 @@
 import re
 import logging
 import threading
+import tempfile
+import os
 log = logging.getLogger("modules.AVConverter")
 
 import conduit
@@ -14,7 +16,6 @@
 
 try:
     import gst
-    from gst.extend import discoverer
     from gst import Pipeline
     MODULES = {
         "AudioVideoConverter" :  { "type": "converter" }
@@ -54,21 +55,18 @@
     specified, the other is calculated to keep the video proportional.    
 '''
 
+PROGRESS_WAIT = 2.5
+
 class GStreamerConversionPipeline(Pipeline):
     """
     Converts between different multimedia formats.
     This class is event-based and needs a mainloop to work properly.
     Emits the 'converted' signal when conversion is finished.
-    Heavily based from gst.extend.discoverer
+    Heavily based on gst.extend.discoverer
 
     The 'converted' callback has one boolean argument, which is True if the
     file was successfully converted.
     """
-    
-    #TODO: Although this is based more on Discoverer, it might be better to base
-    # on some ideas from utils.GstMetadata, especially the pipeline reutilization
-    # (might be a temporary fix to the need to run the discover to get media 
-    # information then the conversion pipeline)
 
     __gsignals__ = {
         'converted' : (gobject.SIGNAL_RUN_FIRST,
@@ -79,8 +77,6 @@
     
     def __init__(self, **kwargs):        
         Pipeline.__init__(self)
-        #if 'file_mux' not in kwargs:
-        #    raise Exception('Output file format not specified')        
         self._has_video_enc = ('vcodec' in kwargs) or ('vcodec_pass1' in kwargs) or ('vcodec_pass2' in kwargs)
         self._has_audio_enc = 'acodec' in kwargs
         if not self._has_video_enc and not self._has_audio_enc:
@@ -126,18 +122,18 @@
             # Dont link videoscale to ffmpegcolorspace yet
             self._video_queue.link(self._video_scale)
             self._video_ffmpegcolorspace.link(self._video_enc)
-            #TODO: Add dynamic video scaling, thus removing the need to run
-            # the discoverer before conversion
             if ('width' in kwargs) or ('height' in kwargs):
                 log.debug("Video dimensions specified")
                 resolution = []                
                 if 'width' in kwargs:
                     width = kwargs['width']
+                    # Make sure it works with all encoders
                     resolution.append('width=%s' % (width - width % 2))
                 if 'height' in kwargs:
                     height = kwargs['height']
                     resolution.append('height=%s' % (height - height % 2))
-                caps = gst.caps_from_string('video/x-raw-yuv,%s;video/x-raw-yuv,%s' % (','.join(resolution), ','.join(resolution)))
+                resolution = ','.join(resolution)
+                caps = gst.caps_from_string('video/x-raw-yuv,%s;video/x-raw-rgb,%s' % (resolution, resolution))
                 self._video_scale.link_filtered(self._video_ffmpegcolorspace, caps)
             else:
                 self._video_scale.link(self._video_ffmpegcolorspace)
@@ -149,7 +145,6 @@
             self._video_pad = None
         if self._has_audio_enc and self._pass != 1:
             self._audio_queue = gst.element_factory_make('queue')
-            #TODO: Add audio rate and sampler            
             self._audio_convert = gst.element_factory_make('audioconvert')
             self._audio_resample = gst.element_factory_make('audioresample')
             self._audio_rate = gst.element_factory_make('audiorate')            
@@ -163,16 +158,13 @@
         else:
             self._audio_pad = None
             
-    def _finished(self, success=False):        
-        log.debug("Conversion finished")
+    def _finished(self, success=False):
         self._success = success
         self.bus.remove_signal_watch()
         gobject.idle_add(self._stop)
-        gobject.source_remove(self.watch)
         return False
 
     def _stop(self):
-        log.debug('Conversion stop')
         self.set_state(gst.STATE_READY)
         self.emit('converted', self._success)
 
@@ -182,12 +174,9 @@
             # conversion?
             log.debug("Conversion sucessfull")
             self._finished(True)
-        #elif message.type == gst.MESSAGE_TAG:
-        #    for key in message.parse_tag().keys():
-        #        self.tags[key] = message.structure[key]
         elif message.type == gst.MESSAGE_ERROR:
             log.debug("Conversion error")
-            self._finished()        
+            self._finished()     
             
     def _dbin_decoded_pad(self, dbin, pad, is_last):
         caps = pad.get_caps()
@@ -215,10 +204,9 @@
         try:
             (pos, format) = self.query_position(gst.FORMAT_TIME)
             (dur, format) = self.query_duration(gst.FORMAT_TIME)
-            log.debug("Conversion progress %.2f%%" % (float(pos)*100.0/dur))
             return (pos/float(gst.SECOND), dur/float(gst.SECOND))
         except gst.QueryError:
-            log.debug("QUERY ERROR")
+            log.debug("Conversion query ERROR")
             return (0.0, 0.0)
                 
     def convert(self):
@@ -227,49 +215,37 @@
         self.bus.add_signal_watch()
         self.bus.connect("message", self._bus_message_cb)
         log.debug("Starting conversion")
-        self.watch  = gobject.timeout_add(2000, self.progress)
         if not self.set_state(gst.STATE_PLAYING):
             self._finished()
             
 class GStreamerConverter():
-    def __init__(self, filename):
-        self.filename = filename
-
-    def get_stream_info(self, needs_audio = False, needs_video = False):                
-        def discovered(discoverer, valid):
-            self.valid = valid
-            event.set()        
-        event = threading.Event()    
-        log.debug("Getting stream information file: %s" % self.filename)
-        self.info = discoverer.Discoverer(self.filename)
-        self.info.connect('discovered', discovered)
-        self.info.discover()
-        event.wait()        
-        if not self.valid:
-            raise Exception('Not a valid media file')
-        if needs_video and not self.info.is_video:
-            raise Exception("Not a valid video file")
-        if needs_audio and not self.info.is_audio:
-            raise Exception("Not a valid audio file")            
-        if self.info.is_video:
-            return (self.info.videowidth, self.info.videoheight, \
-                self.info.videolength / gst.SECOND)
-        elif self.info.is_audio:            
-            return (self.info.audiolength / gst.SECOND)
-        else:
-            raise Exception
-            
     def _run_pipeline(self, **kwargs):
         def converted(converter, success):
             if not success:
                 raise Exception
             self.success = success
-            event.set()            
+            event.set()
         event = threading.Event()
         pipeline = GStreamerConversionPipeline(**kwargs)
         pipeline.connect("converted", converted)
         pipeline.convert()
-        event.wait()        
+        current_thread = threading.currentThread()
+        check_progress = False
+        while not event.isSet():
+            # Dont print an error message if we havent yet started the conversion
+            if check_progress:
+                (time, total) = pipeline.progress()
+                if total:
+                    log.debug("Conversion progress: %.2f%%" % (100.0 * time/total))
+            event.wait(PROGRESS_WAIT)
+			# FIXME: A little hackish, but works.
+            if hasattr(current_thread, 'cancelled'):
+                if current_thread.cancelled:
+                    pipeline.set_state(gst.STATE_NULL)      
+                    pipeline = None
+                    return False
+            check_progress = True
+        pipeline = None
         return self.success
 
     def convert(self, **kwargs):
@@ -292,89 +268,103 @@
                             "file,file/audio"           :   self.file_to_audio
                             }
 
+    def _get_output_file(self, input_file, **kwargs):
+        # We are not checking the contents of keep_converted, because it is a 
+        # string, not a bool, even if it was a bool in the args
+        use_temp = not kwargs.has_key("keep_converted")
+        if not use_temp:
+            try:
+                (input_folder, input_filename) = os.path.split(input_file)
+                output_folder = os.path.join(input_folder, "Converted Files")
+                if not os.path.exists(output_folder):
+                    os.mkdir(output_folder)
+                output_file = os.path.join(output_folder, input_filename)
+                if 'file_extension' in kwargs:
+                    output_file = os.path.splitext(output_file)[0] + '.' + kwargs['file_extension']
+                #TODO: If the file already exists, we could probably not convert it,
+                # because it could've been converted before
+                #if os.path.is_file(output_file):
+                #    return video
+            except Exception, e:
+                log.debug("Using temp folder as a fallback: %s" % e)
+                use_temp = True
+        if use_temp:
+            output_file = tempfile.mkstemp(suffix='conduit')[1]
+            if kwargs.has_key("file_extension"):
+                output_file += '.' + kwargs["file_extension"]
+        log.debug("Using output_file = %s", output_file)
+        return output_file
+        
     def transcode_video(self, video, **kwargs):
-        #mimetype = video.get_mimetype()
-        #if not Video.mimetype_is_video(mimetype):
-        #    log.debug("File %s is not video type: %s" % (video,mimetype))
-        #    return None
-        input_file = video.get_local_uri()
-        
-        log.debug("Creating GStreamer converter")
-
-        gst_converter = GStreamerConverter(input_file) 
-        #try:
-        log.debug("Getting video information")
-        (w, h, duration) = gst_converter.get_stream_info(needs_video = True)
-        #except:
-        #    log.debug("Error getting video information")
-        #    return None
-
-        log.debug("Input Video %s: size=%swx%sh, duration=%ss" % (input_file,w,h,duration))
-
+        #FIXME: This code fails with flv. Should we add an exception?
+        mimetype = video.get_mimetype()
+        if not Video.mimetype_is_video(mimetype):
+            log.debug("File %s is not video type: %s" % (video,mimetype))
+            return None
+        
+        kwargs['in_file'] = video.get_local_uri()
+        kwargs['out_file'] = self._get_output_file(kwargs['in_file'], **kwargs)
+        if os.path.exists(kwargs['out_file']):
+            return Video.Video(kwargs['out_file'])
+        
+        #Check if we need to convert the video
+        if kwargs.get('mimetype', None) == mimetype:
+            #Check if the video is smaller or equal then the required dimensions
+            #If it does, we dont need to convert it
+            width = kwargs.get('width', None)
+            height = kwargs.get('height', None)
+            if width or height:
+                (video_width, video_height) = video.get_video_size()
+                if (not width or video_width <= width) and \
+                   (not height or video_height <= height):
+                    log.debug("Video matches the required dimensions, not converting")
+                    return video
+            else:
+                #There is no required dimensions, and we match the mimetype,
+                #so we dont convert it
+                log.debug("Video matches the mimetype, not converting")
+                return video
+        
         if 'width' in kwargs and 'height' in kwargs:
+            (width, height) = video.get_video_size()
+            if not width and not height:
+                log.debug("Can't get video dimensions")
+                return None
             kwargs['width'],kwargs['height'] = Utils.get_proportional_resize(
                             desiredW=int(kwargs['width']),
                             desiredH=int(kwargs['height']),
-                            currentW=int(w),
-                            currentH=int(h)
+                            currentW=int(width),
+                            currentH=int(height)
                             )
-
-        #TODO: Test folder_location code
-        #if kwargs.has_key("folder_location"):
-        #    output_file = kwargs.has_key("folder_location")
-        #    if not os.path.isdir(output_file):
-        #        log.debug("Output location not a folder")
-        #        return None
-        #    output_file = os.path.join(output_file, os.path.basename(input_file))
-        #    log.debug("Using output_file = %s", output_file)
-        #else:
-        
-        #create output file
-        output_file = video.to_tempfile()
-        if kwargs.has_key("file_extension"):
-            video.force_new_file_extension(".%s" % kwargs["file_extension"])
-        kwargs['in_file'] = input_file
-        kwargs['out_file'] = output_file
-        sucess = gst_converter.convert(**kwargs)
+            log.debug("Scaling video to %swx%sh" % (kwargs['width'],kwargs['height']))
+        
+        gst_converter = GStreamerConverter()
+        sucess = gst_converter.convert(**kwargs)       
         
         if not sucess:
-            log.debug("Error transcoding video\n%s" % output)
+            log.debug("Error transcoding video\n")
             return None
-
-        return video
+        
+        return Video.Video(kwargs['out_file'])
 
     def transcode_audio(self, audio, **kwargs):
         mimetype = audio.get_mimetype()
         if not Audio.mimetype_is_audio(mimetype):
             log.debug("File %s is not audio type: %s" % (audio,mimetype))
             return None
-        input_file = audio.get_local_uri()
-
-
-        gst_converter = GStreamerConverter(input_file)
-        try:
-            duration = gst_converter.get_stream_info(needs_audio = True)
-        except:
-            log.debug("Error getting audio information")
-            return None
-
-        log.debug("Input Audio %s: duration=%ss" % (input_file,duration))
-
-        #create output file
-        output_file = audio.to_tempfile()
-        if kwargs.has_key("file_extension"):
-            audio.force_new_file_extension(".%s" % kwargs["file_extension"])
+        
+        kwargs['in_file'] = audio.get_local_uri()
+        kwargs['out_file'] = self._get_output_file(kwargs['in_file'], **kwargs)
 
         #convert audio
-        kwargs['in_file'] = input_file
-        kwargs['out_file'] = output_file
+        gst_converter = GStreamerConverter()
         sucess = gst_converter.convert(**kwargs)
         
         if not sucess:
-            log.debug("Error transcoding audio\n%s" % output)
+            log.debug("Error transcoding audio\n")
             return None
 
-        return audio
+        return Audio.Audio(kwargs['out_file'])
 
     def file_to_audio(self, f, **kwargs):
         mimetype = f.get_mimetype()

Modified: branches/gnome-2-24/conduit/modules/iPodModule/iPodModule.py
==============================================================================
--- branches/gnome-2-24/conduit/modules/iPodModule/iPodModule.py	(original)
+++ branches/gnome-2-24/conduit/modules/iPodModule/iPodModule.py	Wed Sep 10 03:53:07 2008
@@ -574,7 +574,6 @@
 
     def set_info_from_video(self, video):
         self.set_info_from_file(video)
-        #FIXME: Movie should be a choice between Movie, MusicVideo, TvShow and Podcast
         self.track['mediatype'] = {'movie': gpod.ITDB_MEDIATYPE_MOVIE,
                                    'musicvideo': gpod.ITDB_MEDIATYPE_MUSICVIDEO,
                                    'tvshow': gpod.ITDB_MEDIATYPE_TVSHOW,
@@ -599,7 +598,6 @@
             if mount_point in self.__db_list:
                 log.debug('Getting DB in cache for %s' % (mount_point))
                 db = self.__db_list[mount_point]
-                #self.__db_locks[db][1] += 1
             else:
                 if mount_point:
                     log.debug('Creating DB for %s' % mount_point)
@@ -616,15 +614,14 @@
     @classmethod
     def release_db(self, db):
         assert db in self.__db_locks
+        # We dont do nothing here yet, but we could use to release resources.
+        # The db is automatically removed from the list because of the weak 
+        # reference.
         log.debug('Releasing DB for %s' % db)
-        #self.__db_locks[db][1] -= 1
 
     @classmethod
     def lock_db(self, db):
         assert db in self.__db_locks
-        #if self.__db_locks[db][1] == 1:
-        #    log.debug('Not locking DB for %s' % db)
-        #    return
         log.debug('Locking DB %s' % db)
         self.__db_locks[db].acquire()
 
@@ -632,8 +629,6 @@
     def unlock_db(self, db):
         assert db in self.__db_locks
         log.debug('Unlocking DB %s' % db)
-        #lock = self.__db_locks[db][0]
-        #if lock.locked():
         self.__db_locks[db].release()
 
 class IPodMediaTwoWay(IPodBase):
@@ -651,6 +646,7 @@
         #self.tracks = {}
         self.tracks_id = {}
         self.track_args = {}
+        self.keep_converted = True
 
     def refresh(self):
         DataProvider.TwoWay.refresh(self)
@@ -723,23 +719,33 @@
             return a
         #Get an array of encodings, so it can be indexed inside a combobox
         self.config_encodings = [dict_update({'name': name}, value) for name, value in self.encodings.iteritems()]
-        initial = None
+        initial_enc = None
         for encoding in self.config_encodings:
             if encoding['name'] == self.encoding:
-                initial = encoding.get('description', None) or encoding['name']
+                initial_enc = encoding.get('description', None) or encoding['name']
 
         def selectEnc(index, text):
             self.encoding = self.config_encodings[index]['name']
             log.debug('Encoding %s selected' % self.encoding)
             
+        def selectKeep(value):
+            self.keep_converted = value
+            log.debug("Keep converted selected: %s" % (value))
+            
         return [
                     {
                     "Name" : self.FORMAT_CONVERSION_STRING,
                     "Kind" : "list",
                     "Callback" : selectEnc,
                     "Values" : [encoding.get('description', None) or encoding['name'] for encoding in self.config_encodings],
-                    "InitialValue" : initial
-                    }
+                    "InitialValue" : initial_enc
+                    },
+                    
+                    {"Name" : _("Keep converted files"),
+                     "Kind" : "check",
+                     "Callback" : selectKeep,
+                     "InitialValue" : self.keep_converted
+                    },
                 ]        
 
     def configure(self, window):
@@ -751,13 +757,25 @@
     def set_configuration(self, config):
         if 'encoding' in config:
             self.encoding = config['encoding']
+        if 'keep_converted' in config:
+            self.keep_converted = config['keep_converted']
 
     def get_configuration(self):
-        return {'encoding':self.encoding}
+        return {'encoding':self.encoding,
+                'keep_converted': self.keep_converted}
 
     def get_input_conversion_args(self):
         try:
-            return self.encodings[self.encoding]
+            args = self.encodings[self.encoding]
+            # FIXME
+            # If we pass the bool in the args, it will become a string, and 
+            # will always return True later in the converter.
+            # So we only pass it if is True. When it's False, not being there
+            # tells the converter it isn't True.
+            # I'm not sure it was supposed to work like this.
+            if self.keep_converted:
+                args['keep_converted'] = True
+            return args
         except KeyError:
             return {}
 
@@ -774,7 +792,7 @@
 
 class IPodMusicTwoWay(IPodMediaTwoWay):
 
-    _name_ = "Music"
+    _name_ = "iPod Music"
     _description_ = "Sync your iPod music"
     _module_type_ = "twoway"
     _in_type_ = "file/audio"
@@ -792,13 +810,24 @@
         self.encoding = 'aac'
 
 IPOD_VIDEO_ENCODINGS = {
-    "mp4_x264":{"description": "MP4 (H.264)","vcodec":"x264enc", "acodec":"faac", "format":"ffmux_mp4", "file_extension":"m4v", "width": 320, "height": 240},
-    "mp4_xvid":{"description": "MP4 (XVid)","vcodec":"xvidenc", "acodec":"faac", "format":"ffmux_mp4", "file_extension":"m4v", "width": 320, "height": 240},
+    #FIXME: Add iPod mpeg4 restrictions. Follow:
+    # http://rob.opendot.cl/index.php/useful-stuff/ffmpeg-x264-encoding-guide/
+    "mp4_x264":{"description": "MP4 (Better quality - H.264)","vcodec":"x264enc", "acodec":"faac", 
+        "format":"ffmux_mp4", "file_extension":"m4v", "width": 320, "height": 240, 
+        "mimetype": "video/mp4"},
+    #FIXME: Two-pass encoding is not working. The first pass never finishes.
+    #"mp4_x264_twopass":{"description": "MP4 (H.264, Two-pass EXPERIMENTAL)", 
+    #    "vcodec_pass1":"x264enc pass=1", "vcodec_pass2":"x264enc pass=2", 
+    #    "acodec":"faac", "format":"ffmux_mp4", "file_extension":"m4v", 
+    #    "width": 320, "height": 240, "mimetype": "video/mp4", 'twopass':True},
+    "mp4_xvid":{"description": "MP4 (Faster conversion - XVid)","vcodec":"ffenc_mpeg4", "acodec":"faac",
+        "format":"ffmux_mp4", "file_extension":"m4v", "width": 320, "height": 240, 
+        "mimetype": "video/mp4"},
     }
 
 class IPodVideoTwoWay(IPodMediaTwoWay):
 
-    _name_ = "Video"
+    _name_ = "iPod Video"
     _description_ = "Sync your iPod videos"
     _module_type_ = "twoway"
     _in_type_ = "file/video"
@@ -852,6 +881,7 @@
         IPodMediaTwoWay.set_configuration(self, config)
         if 'video_kind' in config:
             self.encoding = config['video_kind']
+        self._update_track_args()
 
     def get_configuration(self):
         config = IPodMediaTwoWay.get_configuration(self)

Modified: branches/gnome-2-24/conduit/utils/MediaFile.py
==============================================================================
--- branches/gnome-2-24/conduit/utils/MediaFile.py	(original)
+++ branches/gnome-2-24/conduit/utils/MediaFile.py	Wed Sep 10 03:53:07 2008
@@ -7,7 +7,7 @@
 try:
     import gst
     from gst.extend import discoverer
-    GST_AVAILABLE = False
+    GST_AVAILABLE = True
 except ImportError:
     GST_AVAILABLE = False
 
@@ -46,11 +46,10 @@
             tags['channels'] = info.audiochannels
         return tags
 
-    def _get_metadata(self, name):
-        if GST_AVAILABLE:
-            tags = self.get_media_tags()
-            if name in tags:
-                return tags[name]
+    def _get_metadata(self, name):        
+        tags = self.get_media_tags()
+        if name in tags:
+            return tags[name]
         return None
 
     def __getattr__(self, name):
@@ -68,4 +67,6 @@
         Descendants should override this function to provide their own tags,
         or merge with these tags.
         '''
-        return self.gst_tags
+        if GST_AVAILABLE:
+            return self.gst_tags
+        return None

Modified: branches/gnome-2-24/test/python-tests/TestCoreConvertAudioVideo.py
==============================================================================
--- branches/gnome-2-24/test/python-tests/TestCoreConvertAudioVideo.py	(original)
+++ branches/gnome-2-24/test/python-tests/TestCoreConvertAudioVideo.py	Wed Sep 10 03:53:07 2008
@@ -10,6 +10,7 @@
 import conduit.datatypes.File as File
 import conduit.datatypes.Video as Video
 import conduit.datatypes.Audio as Audio
+import conduit.modules.iPodModule.iPodModule as iPodModule
 import conduit.utils as Utils
 import conduit.Exceptions as Exceptions
 
@@ -19,11 +20,15 @@
 ok("Video Conversion exists", tc.conversion_exists("file","file/video") == True)
 ok("Audio Conversion exists", tc.conversion_exists("file","file/audio") == True)
 
+VIDEO_ENCODINGS = Video.PRESET_ENCODINGS
+VIDEO_ENCODINGS.update(iPodModule.IPOD_VIDEO_ENCODINGS)
+
 TEST = (
 #name.list          #encodings to test  #available encodings
-("video",           ('divx','flv','ogg'),          Video.PRESET_ENCODINGS      ),
-("audio",           ('ogg',),           Audio.PRESET_ENCODINGS      ),
+("video",           ('divx', 'flv', 'ogg', 'mp4_x264', 'mp4_xvid'), VIDEO_ENCODINGS),
+("audio",           ('ogg','mp3'),           Audio.PRESET_ENCODINGS      ),
 )
+mainloop = gobject.MainLoop()
 
 def convert():    
     for name, test_encodings, all_encodings in TEST:
@@ -41,14 +46,13 @@
                     ok("%s: Conversion OK" % name, newdata != None and newdata.exists(), False)
                 except Exceptions.ConversionError:
                     ok("%s: Conversion Failed" % name, False, False)
-    finished()           
-    mainloop.quit()
-    return False
+    gobject.idle_add(mainloop.quit)
+    finished()
 
 def idle_cb():
     threading.Thread(target=convert).start()
+    return False
 
-mainloop = gobject.MainLoop()
 gobject.idle_add(idle_cb)
 mainloop.run()
 



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