patch: update fxd file when reencoding

A Mennucc <[email protected]>
Newsgroups gmane.comp.video.freevo.devel
Message-ID <[email protected]>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

hi,

I attach a patch so that , when you reencode a file, the encodingserver
also creates a new FXD file to point to the reencoded file (so as to
preserve all metadata)

unfortunately it is not 100% satisfactory: when I first wrote it , I
wrote code in line 135 in video/plugins/reencode.py
that would get the FXD file name from the attribute 'fxd_file' in the
'VideoItem' object ; but it turns out that that is always None ; so I
added some hackish code to reverse-guess the FXD file name from the
video file name .

May someone fix this fact?

a.

ps: I attach the patch for SVN freevo 1.x , and for freevo 1.9.0 : there
is a slight difference in spacing


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkykP1wACgkQ9B/tjjP8QKQWyQCdEMcmj6hWth/JO1qVsrKO9BgR
PbMAn18U2n9IUwR1RY/rUahGR90gVDFS
=rgEU
-----END PGP SIGNATURE-----

------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing.
http://p.sf.net/sfu/novell-sfdev2dev

_______________________________________________
Freevo-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-devel
reencode_create_fxd_.diff (text/x-diff, 10.3 KB)
Index: freevo-entrypoint/src/encodingcore.py
===================================================================
--- freevo-entrypoint.orig/src/encodingcore.py	2010-09-26 13:19:26.896194668 +0200
+++ freevo-entrypoint/src/encodingcore.py	2010-09-28 20:46:25.142152275 +0200
@@ -40,7 +40,7 @@
 from pprint import pformat
 from copy import copy
 from string import split, join
-from util.misc import uniquify_filename
+from util.misc import uniquify_filename, uniquify_filename_as_list
 
 import config
 import kaa.metadata
@@ -181,6 +181,7 @@
     @ivar _generateCL: function to generate the command line
     @ivar encodingopts: options for the different encoding steps
     @ivar source: source file to encode
+    @ivar fxd_file: fxd file associated to the source (or None if there is not one)
     @ivar output: output file after encoding
     @ivar name: friendly name of the job
     @ivar idnr: job id number
@@ -216,22 +217,24 @@
     @ivar threads: number of threads
     @ivar failed: has the job failed?
     """
-    def __init__(self, source, output, friendlyname, idnr, titlenum=None, rmsource=False):
+    def __init__(self, source, fxd_file, output, friendlyname, idnr, titlenum=None, rmsource=False):
         """
         Initialize an instance of an EncodingJob
         @param source: input source name
+        @param fxd_file: fxd file associated to the source (or None if there is not one)
         @param output: output file name
         @param friendlyname: name of the job
         @param idnr: job id number
         @param titlenum: titlenum number to re-encode
         @param rmsource: remove the source
         """
-        _debug_('encodingcore.EncodingJob.__init__(%s, %s, %s, %s, %s, %s)' % \
-            (source, output, friendlyname, idnr, titlenum, rmsource), 2)
+        _debug_('encodingcore.EncodingJob.__init__(%s, %s, %s, %s, %s, %s, %s)' % \
+            (source, fxd_file, output, friendlyname, idnr, titlenum, rmsource), 2)
         #currently only MEncoder can be used, but who knows what will happen in the future :)
         self._generateCL = self._GenerateCLMencoder
         self.encodingopts = EncodingOptions()
         self.source = source
+        self.fxd_file = fxd_file
         #note that we strip the extension from the self.output file name
         self.output = output
         self.temp_output = None #temporary output file for mencoder job
@@ -1097,7 +1100,8 @@
 
         output = self.currentjob.full_output_file_name()
         # check eventually that there is no file by the same name
-        unique_output = uniquify_filename(output)
+        unique_output_as_list = uniquify_filename_as_list(output)
+        unique_output = join(unique_output_as_list, '')
 
         if hasattr(self.currentjob,'thread'):
             if self.currentjob.thread.returncode:
@@ -1111,17 +1115,36 @@
 
         if self.currentjob.status == status.vpassfinal:
             _debug_('Job %s finished' % self.currentjob.idnr, DINFO)
-            if self.currentjob.rmsource:
-                _debug_('Removing source: %s' % self.currentjob.source)
-                try:
-                    os.remove(self.currentjob.source)
-                except OSError :
-                    _debug_('Cannot remove file '+self.currentjob.source, DWARNING)
             #
+            #print 'FXD in encoding core',self.currentjob.fxd_file
             try:
                 os.rename(self.currentjob.temp_output, unique_output)
-            except OSError :
-                _debug_('Cannot rename file to remove ~incomplete~ suffix '+self.currentjob.temp_output, DWARNING)
+                if self.currentjob.fxd_file:
+                    new_fxd_file=join(unique_output_as_list[:-1],'')+'.fxd'
+                    assert( self.currentjob.fxd_file != new_fxd_file)
+                    new_fxd_file_f=open(new_fxd_file,'w')
+                    #create new FXD pointing at the new reencoded file
+                    for a in open(self.currentjob.fxd_file):
+                        if '<file id' in a:
+                            #if '/' in a: usually only the basename is present in FXD files
+                            #    a=a.replace('>'+self.currentjob.source+'<',
+                            #                '>'+unique_output+'<')
+                            #else:
+                            a=a.replace('>'+os.path.basename(self.currentjob.source)+'<',
+                                        '>'+os.path.basename(unique_output)+'<')
+                        elif '<movie title' in a:
+                            #add the uniquifier token to the title as well, to distinguish the new FXD easily in the GUI
+                            a=a.replace('">',' '+unique_output_as_list[-2]+'">')
+                        new_fxd_file_f.write(a)
+                    new_fxd_file_f.close()
+                if self.currentjob.rmsource:
+                    _debug_('Removing source: %s' % self.currentjob.source)
+                    os.remove(self.currentjob.source)
+                    if self.currentjob.fxd_file:
+                        #FIXME SHOULD CHECK THAT THIS FXD FILE DOES NOT CONTAIN MULTIPLE SOURCES
+                        os.remove(self.currentjob.fxd_file)
+            except OSError, e :
+                _debug_('While doing the finishing part of a reencoding, OSError:'+str(e), DWARNING)
 
             #we are done with this job, remove it
             del self.qlist[0]
@@ -1183,8 +1206,7 @@
             if len(sys.argv) >= 4:
                 title = sys.argv[3]
 
-    encjob = EncodingJob(None, 'test.avi', 'lala', 456789)
-    encjob.source = source
+    encjob = EncodingJob(source, None, 'test.avi', 'lala', 456789)
     encjob.titlenum = titlenum
     if command == '--identify':
         encjob._identify()
Index: freevo-entrypoint/src/helpers/encodingserver.py
===================================================================
--- freevo-entrypoint.orig/src/helpers/encodingserver.py	2010-09-26 13:19:32.656194049 +0200
+++ freevo-entrypoint/src/helpers/encodingserver.py	2010-09-26 22:40:12.729846384 +0200
@@ -127,10 +127,11 @@
 
 
     @kaa.rpc.expose('initEncodingJob')
-    def _initEncodingJob(self, source, output, friendlyname='', chapter=None, rmsource=False):
+    def _initEncodingJob(self, source, fxd_file, output, friendlyname='', chapter=None, rmsource=False):
         """
         Initialise an encoding job
         @param source: source file to encode
+        @param fxd_file: fxd file associated to the source (or None if there is not one)
         @param output: output file to encode
         @param friendlyname: encoding job title
         @param chapter: chapter number to encode
@@ -146,7 +147,7 @@
         # devide or random number by 100 :)
         idnr = int((time.time() / random.random()) / 100)
         _debug_('idnr=%s' % (idnr), 2)
-        self.jobs[idnr] = EncodingJob(source, output, friendlyname, idnr, chapter, rmsource)
+        self.jobs[idnr] = EncodingJob(source, fxd_file, output, friendlyname, idnr, chapter, rmsource)
         _debug_('Initialized job %s (idnr: %s)' % (friendlyname, idnr), DINFO)
         if self.jobs[idnr].failed:
             return (False, 0)
Index: freevo-entrypoint/src/video/plugins/reencode.py
===================================================================
--- freevo-entrypoint.orig/src/video/plugins/reencode.py	2010-09-26 14:31:52.996197601 +0200
+++ freevo-entrypoint/src/video/plugins/reencode.py	2010-09-28 20:37:15.347203667 +0200
@@ -58,6 +58,7 @@
         self.server = EncodingClientActions()
         self.title = ''
         self.source = ''
+        self.fxd_file = None
         self.output = ''
         self.resetprofile()
         self.timeslice = [ None, None ]
@@ -132,6 +133,7 @@
             self.item = item
             self.title = item.name
             self.source = item.filename
+            self.fxd_file = item.fxd_file
             #this is temporarily set , since it is called too often
             #(even when browsing a directory ot TV recordings)
             self.output = '(to be set later)'
@@ -460,9 +462,21 @@
 
         #we are going to create a job and send it to the encoding server, this can take some time while analyzing
 
+        #HACKISH CODE, this should be set somewhere else, but is not;
+        #so it is guessed here
+        if self.fxd_file == None:
+            self.fxd_file = os.path.splitext(self.source)[0]+'.fxd'
+            if not os.path.exists(self.fxd_file):
+                _debug_('Tried to guess the fxd file name but it does not exist: '+str(self.fxd_file), DWARNING)
+                self.fxd_file = None
+            elif os.path.basename(self.source) not in open(self.fxd_file).read():
+                _debug_('The guessed fxd file does not reference the required source: '+str(self.fxd_file)+' , '+str(self.source), DWARNING)
+                self.fxd_file = None
+        #print 'FXD in reencode.py',self.fxd_file
+
         box = PopupBox(text=_('Please wait, analyzing video...'))
         box.show()
-        (status, resp) = self.server.initEncodingJob(self.source, self.output, self.title)
+        (status, resp) = self.server.initEncodingJob(self.source, self.fxd_file, self.output, self.title)
         idnr = resp
         _debug_('initEncodingJob:status:%s resp:%s' % (status, resp))
         if not status:
Index: freevo-entrypoint/src/util/misc.py
===================================================================
--- freevo-entrypoint.orig/src/util/misc.py	2010-09-27 21:21:42.404576773 +0200
+++ freevo-entrypoint/src/util/misc.py	2010-09-27 21:32:57.880572222 +0200
@@ -55,7 +55,11 @@
     extensions must have a 'dot' in front). If 'filename' is not an
     absolute path, the directory is specified in 'directory'.  
     Example usage: uniquify_filename('/sbin/mkfs')
-    """        
+    """
+    return string.join(uniquify_filename_as_list(filename,directory,extensions), '')
+
+def uniquify_filename_as_list(filename,directory=None,extensions=None):
+    "same as uniquify_filename() , but returns (directory,separator,filename,uniquifier,extension)"
     assert type(extensions) == tuple or type(extensions) == list or \
         extensions == None
     if directory == None:
@@ -83,7 +87,7 @@
     while (filename+uniquifier) in files:
         N = N + 1
         uniquifier = '(%d)' % N
-    return directory+os.path.sep+filename+uniquifier+ext
+    return directory,os.path.sep,filename,uniquifier,ext
 
 
 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560
reencode_create_fxd_--svn.diff (text/x-diff, 10.1 KB)
Index: helpers/encodingserver.py
===================================================================
--- helpers/encodingserver.py	(revisione 11691)
+++ helpers/encodingserver.py	(copia locale)
@@ -127,10 +127,11 @@
 
 
     @kaa.rpc.expose('initEncodingJob')
-    def _initEncodingJob(self, source, output, friendlyname='', chapter=None, rmsource=False):
+    def _initEncodingJob(self, source, fxd_file, output, friendlyname='', chapter=None, rmsource=False):
         """
         Initialise an encoding job
         @param source: source file to encode
+        @param fxd_file: fxd file associated to the source (or None if there is not one)
         @param output: output file to encode
         @param friendlyname: encoding job title
         @param chapter: chapter number to encode
@@ -146,7 +147,7 @@
         # devide or random number by 100 :)
         idnr = int((time.time() / random.random()) / 100)
         _debug_('idnr=%s' % (idnr), 2)
-        self.jobs[idnr] = EncodingJob(source, output, friendlyname, idnr, chapter, rmsource)
+        self.jobs[idnr] = EncodingJob(source, fxd_file, output, friendlyname, idnr, chapter, rmsource)
         _debug_('Initialized job %s (idnr: %s)' % (friendlyname, idnr), DINFO)
         if self.jobs[idnr].failed:
             return (False, 0)
Index: video/plugins/reencode.py
===================================================================
--- video/plugins/reencode.py	(revisione 11691)
+++ video/plugins/reencode.py	(copia locale)
@@ -58,6 +58,7 @@
         self.server = EncodingClientActions()
         self.title = ''
         self.source = ''
+        self.fxd_file = None
         self.output = ''
         self.resetprofile()
         self.timeslice = [ None, None ]
@@ -132,6 +133,7 @@
             self.item = item
             self.title = item.name
             self.source = item.filename
+            self.fxd_file = item.fxd_file
             #this is temporarily set , since it is called too often
             #(even when browsing a directory ot TV recordings)
             self.output = '(to be set later)'
@@ -461,9 +463,21 @@
 
         #we are going to create a job and send it to the encoding server, this can take some time while analyzing
 
+        #HACKISH CODE, this should be set somewhere else, but is not;
+        #so it is guessed here
+        if self.fxd_file == None:
+            self.fxd_file = os.path.splitext(self.source)[0]+'.fxd'
+            if not os.path.exists(self.fxd_file):
+                _debug_('Tried to guess the fxd file name but it does not exist: '+str(self.fxd_file), DWARNING)
+                self.fxd_file = None
+            elif os.path.basename(self.source) not in open(self.fxd_file).read():
+                _debug_('The guessed fxd file does not reference the required source: '+str(self.fxd_file)+' , '+str(self.source), DWARNING)
+                self.fxd_file = None
+        #print 'FXD in reencode.py',self.fxd_file
+
         box = PopupBox(text=_('Please wait, analyzing video...'))
         box.show()
-        (status, resp) = self.server.initEncodingJob(self.source, self.output, self.title)
+        (status, resp) = self.server.initEncodingJob(self.source, self.fxd_file, self.output, self.title)
         idnr = resp
         _debug_('initEncodingJob:status:%s resp:%s' % (status, resp))
         if not status:
Index: encodingcore.py
===================================================================
--- encodingcore.py	(revisione 11691)
+++ encodingcore.py	(copia locale)
@@ -40,7 +40,7 @@
 from pprint import pprint, pformat
 from copy import copy
 from string import split, join
-from util.misc import uniquify_filename
+from util.misc import uniquify_filename, uniquify_filename_as_list
 
 import config
 import kaa.metadata
@@ -182,6 +182,7 @@
     @ivar _generateCL: function to generate the command line
     @ivar encodingopts: options for the different encoding steps
     @ivar source: source file to encode
+    @ivar fxd_file: fxd file associated to the source (or None if there is not one)
     @ivar output: output file after encoding
     @ivar name: friendly name of the job
     @ivar idnr: job id number
@@ -217,22 +218,24 @@
     @ivar threads: number of threads
     @ivar failed: has the job failed?
     """
-    def __init__(self, source, output, friendlyname, idnr, titlenum=None, rmsource=False):
+    def __init__(self, source, fxd_file, output, friendlyname, idnr, titlenum=None, rmsource=False):
         """
         Initialize an instance of an EncodingJob
         @param source: input source name
+        @param fxd_file: fxd file associated to the source (or None if there is not one)
         @param output: output file name
         @param friendlyname: name of the job
         @param idnr: job id number
         @param titlenum: titlenum number to re-encode
         @param rmsource: remove the source
         """
-        _debug_('encodingcore.EncodingJob.__init__(%s, %s, %s, %s, %s, %s)' % \
-            (source, output, friendlyname, idnr, titlenum, rmsource), 2)
+        _debug_('encodingcore.EncodingJob.__init__(%s, %s, %s, %s, %s, %s, %s)' % \
+            (source, fxd_file, output, friendlyname, idnr, titlenum, rmsource), 2)
         #currently only MEncoder can be used, but who knows what will happen in the future :)
         self._generateCL = self._GenerateCLMencoder
         self.encodingopts = EncodingOptions()
         self.source = source
+        self.fxd_file = fxd_file
         #note that we strip the extension from the self.output file name
         self.output = output
         self.temp_output = None #temporary output file for mencoder job
@@ -1076,7 +1079,8 @@
 
         output = self.currentjob.full_output_file_name()
         # check eventually that there is no file by the same name
-        unique_output = uniquify_filename(output)
+        unique_output_as_list = uniquify_filename_as_list(output)
+        unique_output = join(unique_output_as_list, '')
 
         if hasattr(self.currentjob,'thread'):
             if self.currentjob.thread.returncode:
@@ -1090,17 +1094,36 @@
 
         if self.currentjob.status == status.vpassfinal:
             _debug_('Job %s finished' % self.currentjob.idnr, DINFO)
-            if self.currentjob.rmsource:
-                _debug_('Removing source: %s' % self.currentjob.source)
-                try:
-                    os.remove(self.currentjob.source)
-                except OSError :
-                    _debug_('Cannot remove file '+self.currentjob.source, DWARNING)
             #
+            #print 'FXD in encoding core',self.currentjob.fxd_file
             try:
                 os.rename(self.currentjob.temp_output, unique_output)
-            except OSError :
-                _debug_('Cannot rename file to remove ~incomplete~ suffix '+self.currentjob.temp_output, DWARNING)
+                if self.currentjob.fxd_file:
+                    new_fxd_file=join(unique_output_as_list[:-1],'')+'.fxd'
+                    assert( self.currentjob.fxd_file != new_fxd_file)
+                    new_fxd_file_f=open(new_fxd_file,'w')
+                    #create new FXD pointing at the new reencoded file
+                    for a in open(self.currentjob.fxd_file):
+                        if '<file id' in a:
+                            #if '/' in a: usually only the basename is present in FXD files
+                            #    a=a.replace('>'+self.currentjob.source+'<',
+                            #                '>'+unique_output+'<')
+                            #else:
+                            a=a.replace('>'+os.path.basename(self.currentjob.source)+'<',
+                                        '>'+os.path.basename(unique_output)+'<')
+                        elif '<movie title' in a:
+                            #add the uniquifier token to the title as well, to distinguish the new FXD easily in the GUI
+                            a=a.replace('">',' '+unique_output_as_list[-2]+'">')
+                        new_fxd_file_f.write(a)
+                    new_fxd_file_f.close()
+                if self.currentjob.rmsource:
+                    _debug_('Removing source: %s' % self.currentjob.source)
+                    os.remove(self.currentjob.source)
+                    if self.currentjob.fxd_file:
+                        #FIXME SHOULD CHECK THAT THIS FXD FILE DOES NOT CONTAIN MULTIPLE SOURCES
+                        os.remove(self.currentjob.fxd_file)
+            except OSError, e :
+                _debug_('While doing the finishing part of a reencoding, OSError:'+str(e), DWARNING)
 
             #we are done with this job, remove it
             del self.qlist[0]
@@ -1162,8 +1185,7 @@
             if len(sys.argv) >= 4:
                 title = sys.argv[3]
 
-    encjob = EncodingJob(None, 'test.avi', 'lala', 456789)
-    encjob.source = source
+    encjob = EncodingJob(source, None, 'test.avi', 'lala', 456789)
     encjob.titlenum = titlenum
     if command == '--identify':
         encjob._identify()
Index: util/misc.py
===================================================================
--- util/misc.py	(revisione 11691)
+++ util/misc.py	(copia locale)
@@ -53,9 +53,13 @@
     If 'extensions' contains a list of extensions, then only files in
     the directory with those extensions are considered (note that the
     extensions must have a 'dot' in front). If 'filename' is not an
-    absolute path, the directory is specified in 'directory'.
+    absolute path, the directory is specified in 'directory'.  
     Example usage: uniquify_filename('/sbin/mkfs')
     """
+    return string.join(uniquify_filename_as_list(filename,directory,extensions), '')
+
+def uniquify_filename_as_list(filename,directory=None,extensions=None):
+    "same as uniquify_filename() , but returns (directory,separator,filename,uniquifier,extension)"
     assert type(extensions) == tuple or type(extensions) == list or \
         extensions == None
     if directory == None:
@@ -83,7 +87,7 @@
     while (filename+uniquifier) in files:
         N = N + 1
         uniquifier = '(%d)' % N
-    return directory+os.path.sep+filename+uniquifier+ext
+    return directory,os.path.sep,filename,uniquifier,ext
 
 
 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.