[xiph-commits] r15140 - in trunk/subtle: . Subtitles

jmesquita at svn.xiph.org jmesquita at svn.xiph.org
Mon Jul 28 21:02:28 PDT 2008


Author: jmesquita
Date: 2008-07-28 21:02:27 -0700 (Mon, 28 Jul 2008)
New Revision: 15140

Added:
   trunk/subtle/Subtitles/Softni.py
Modified:
   trunk/subtle/Subtitles/Discoverer.py
   trunk/subtle/Subtitles/Sub.py
   trunk/subtle/Subtitles/SubRip.py
   trunk/subtle/Subtitles/Subtitles.py
   trunk/subtle/Subtitles/__init__.py
   trunk/subtle/Subtle.py
Log:
Subtitles.py/Sub.py: Add the frames on the sub (converted from the timestamp)
Subtle.py: Display the file encoding on stream list
Subtitles/Subtitles.py: Add the file encoding property to the subtitle
Subtitles/__init__.py: Add the new subtitle format to the import
Subtitles/Softni.py: First submit of the Softni subtitle format
Subtitles/SubRip.py: Added the conversion to the framerate
Subtitles/Discoverer.py: Move some things around. Now the discover should be on the subtitle module instead of in this function. Maybe we should 
trhow error instead of just doing C style ifs?



Modified: trunk/subtle/Subtitles/Discoverer.py
===================================================================
--- trunk/subtle/Subtitles/Discoverer.py	2008-07-26 19:59:13 UTC (rev 15139)
+++ trunk/subtle/Subtitles/Discoverer.py	2008-07-29 04:02:27 UTC (rev 15140)
@@ -21,6 +21,7 @@
 
 import os
 import SubRip
+import Softni
 
 def discoverer(file):
     """
@@ -32,5 +33,8 @@
     # Test for SubRip
     if SubRip.discover(file):
         return SubRip.SubRip(file)
+    # Test for Softni
+    if Softni.discover(file):
+        return Softni.Softni(file)
         
     return None

Added: trunk/subtle/Subtitles/Softni.py
===================================================================
--- trunk/subtle/Subtitles/Softni.py	                        (rev 0)
+++ trunk/subtle/Subtitles/Softni.py	2008-07-29 04:02:27 UTC (rev 15140)
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+#
+#       Softni.py
+#       
+#       Copyright 2008 Joao Mesquita <jmesquita at gmail.com>
+#       
+#       This program is free software; you can redistribute it and/or modify
+#       it under the terms of the GNU General Public License as published by
+#       the Free Software Foundation; either version 3 of the License, or
+#       (at your option) any later version.
+#       
+#       This program is distributed in the hope that it will be useful,
+#       but WITHOUT ANY WARRANTY; without even the implied warranty of
+#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#       GNU General Public License for more details.
+#       
+#       You should have received a copy of the GNU General Public License
+#       along with this program; if not, write to the Free Software
+#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+#       MA 02110-1301, USA.
+
+
+# This implementation is on real BAD alpha stage and should not be
+# considered by any chance ready for production.
+# A lot of study is still needed to transform the frames into timestamp
+# since this format is a bit funky.
+
+import os
+import string
+import re
+import codecs
+
+# This is not the best option since we rely on Linux-only
+# Make use of file command to check on the file type
+try:
+    import magic
+except:
+    print "We need python-magic, otherwise, this format will not be \
+    supported"
+    sys.exit(1)
+
+from random import randint
+
+from Subtitles import Subtitles
+from Sub import *
+
+FRAMERATE=25.00
+
+def discover(file):
+    """
+        Every subtitle should have a discover function
+        and return true if it should handle the requested
+        file.
+    """
+
+    m = magic.open(magic.MAGIC_COMPRESS | magic.MAGIC_MIME)
+    status = m.load()
+
+    if m.file(file).split('/')[0] == "text":
+        # Open file and read it
+        fd = open(file, "r")
+        data = fd.read()
+        fd.close()
+    else:
+        return
+
+    # Test for SubRip by matching the header
+    rawstr = r"""^(?P<sub>.*\r?\n)*?
+            ^(?P<ts_from>\d{2}:\d{2}:\d{2}.\d{2})\\(?P<ts_to>\d{2}:\d{2}:\d{2}.\d{2})"""
+
+    regex = re.compile(rawstr,  re.MULTILINE| re.VERBOSE)
+
+    if regex.search(data):
+        return True
+    return
+    
+class Softni(Subtitles):
+    """
+        This class handles the Softni file format
+    """
+    def __init__(self, filename):
+        Subtitles.__init__(self,filename)
+        
+        # Set the file encoding
+        m = magic.open(magic.MAGIC_COMPRESS | magic.MAGIC_MIME)
+        status = m.load()
+        self.encoding = m.file(filename).split('/')[1].split('=')[1]
+        
+        self.subType="Softni"
+
+        self._loadFromFile(filename)
+        return
+
+    def _loadFromFile(self, file):
+        """
+            Parse and load the subtitle using a string
+            as input
+        """
+        regex = re.compile(r"""^(?P<ts_from>\d{2}:\d{2}:\d{2}.\d{2})\\(?P<ts_to>\d{2}:\d{2}:\d{2}.\d{2})""", re.MULTILINE)
+  
+        # We reopen the file here so we can
+        # iterate over the lines
+        fd = codecs.open(file, "r", self.encoding)
+        str = fd.readlines()
+        fd.close()
+        
+        # Lets set the data structure like we need it
+        info = []
+        buffer = ""
+        for line in str:
+            if regex.search(line):
+                info.append(tuple([buffer] + line.split('\\')))
+                buffer=""
+            else:
+                buffer+=line
+        
+        # Iterate all the subs and create the
+        # sub objects
+        sub_count = 0
+        for sub in info:
+            text = sub[0]
+            stime = sub[1]
+            etime = sub[2]
+            TS = Sub(text)
+            TS.start_time = self._softniFormat2Timestamp(stime)
+            TS.end_time = self._softniFormat2Timestamp(etime)
+            TS.start_frame = self._softniFormat2Frame(stime)
+            TS.end_frame = self._softniFormat2Frame(etime)
+            TS.number = sub_count
+            sub_count += 1
+            self.subs[int(self._softniFormat2Timestamp(stime))]=TS
+        self.updateKeys()
+        return
+    
+    def _softniFormat2Frame(self, softniFormat):
+        """
+            Convert Softni frame format to cumulative frame counting
+        """
+        frames = ((float(softniFormat[0:2])*60*60) + \
+                (float(softniFormat[3:5])*60) + \
+                float(softniFormat[6:8]) * FRAMERATE) + \
+                float(softniFormat[9:11])
+        return frames
+        
+    def _softniFormat2Timestamp(self, softniFormat):
+        """
+            Convert Softni frame format to cumulative frame counting
+        """ 
+        timestamp = (float(softniFormat[0:2])*60*60) + \
+                (float(softniFormat[3:5])*60) + \
+                float(softniFormat[6:8]) + \
+                (float(softniFormat[9:11])/FRAMERATE)
+        return timestamp*1000

Modified: trunk/subtle/Subtitles/Sub.py
===================================================================
--- trunk/subtle/Subtitles/Sub.py	2008-07-26 19:59:13 UTC (rev 15139)
+++ trunk/subtle/Subtitles/Sub.py	2008-07-29 04:02:27 UTC (rev 15140)
@@ -37,7 +37,9 @@
         # when there is at least one line
         self.nLines = 1
         self.start_time=None
+        self.start_frame=0
         self.end_time=None
+        self.end_frame=0
         self.number=None
         self._processText(text)
 

Modified: trunk/subtle/Subtitles/SubRip.py
===================================================================
--- trunk/subtle/Subtitles/SubRip.py	2008-07-26 19:59:13 UTC (rev 15139)
+++ trunk/subtle/Subtitles/SubRip.py	2008-07-29 04:02:27 UTC (rev 15140)
@@ -22,24 +22,28 @@
 import os
 import string
 import re
+import codecs
 
+# This is not the best option since we rely on Linux-only
+# Make use of file command to check on the file type
+try:
+    import magic
+except:
+    print "We need python-magic, otherwise, this format will not be \
+    supported"
+    sys.exit(1)
+
 from Subtitles import Subtitles
 from Sub import *
 
+FRAMERATE=25.00
+
 def discover(file):
     """
         Every subtitle should have a discover function
         and return true if it should handle the requested
         file.
-    """
-    # This is not the best option since we rely on Linux-only
-    # Make use of file command to check on the file type
-    try:
-        import magic
-    except:
-        print "We need python-magic, otherwise, this format will not be \
-        supported"
-        return
+    """ 
 
     m = magic.open(magic.MAGIC_COMPRESS | magic.MAGIC_MIME)
     status = m.load()
@@ -53,9 +57,10 @@
         return
     
     # Test for SubRip by matching the header
-    regex = re.compile("""^(?P<counter>\d+)\s*
-                        ^(?P<ts_from>\d{2}:\d{2}:\d{2},\d{3})\s*-->\s*(?P<ts_to>\d{2}:\d{2}:\d{2},\d{3})\r?""",re.MULTILINE|re.VERBOSE)
-    if regex.match(data):
+    rawstr = r"""^(?P<counter>\d+)\s*
+                ^(?P<ts_from>\d{2}:\d{2}:\d{2},\d{3})\s*-->\s*(?P<ts_to>\d{2}:\d{2}:\d{2},\d{3})\r?"""
+    regex = re.compile(rawstr,re.MULTILINE| re.VERBOSE)
+    if regex.search(data):
         return True
     return
 
@@ -68,11 +73,16 @@
     # Load subtitles from file.
     def __init__(self, filename):
         Subtitles.__init__(self,filename)
-        FILE=os.open(filename, os.O_RDONLY)
-        FS=os.fstat(FILE)
-        DATA=os.read(FILE,FS.st_size)
-        os.close(FILE)
         
+        # Set the file encoding
+        m = magic.open(magic.MAGIC_COMPRESS | magic.MAGIC_MIME)
+        status = m.load()
+        self.encoding = m.file(filename).split('/')[1].split('=')[1]
+        
+        FILE = codecs.open(filename, 'r', self.encoding)
+        DATA = FILE.read()
+        FILE.close()
+        
         self.subType="SubRip"
 
         self._subSRTLoadFromString(DATA)
@@ -150,6 +160,8 @@
             #TS.text=Text
             TS.start_time=ST
             TS.end_time=ET
+            TS.start_frame=ST*FRAMERATE/1000
+            TS.end_frame=ET*FRAMERATE/1000
             TS.number = num_sub
             self.subs[int(ST)]=TS
         self.updateKeys()

Modified: trunk/subtle/Subtitles/Subtitles.py
===================================================================
--- trunk/subtle/Subtitles/Subtitles.py	2008-07-26 19:59:13 UTC (rev 15139)
+++ trunk/subtle/Subtitles/Subtitles.py	2008-07-29 04:02:27 UTC (rev 15140)
@@ -41,6 +41,7 @@
         self.filename = FN
         # TODO: Support more subtitles types
         self.subType = None
+        self.encoding = None
         return
 
     ## Delete subtitle.

Modified: trunk/subtle/Subtitles/__init__.py
===================================================================
--- trunk/subtle/Subtitles/__init__.py	2008-07-26 19:59:13 UTC (rev 15139)
+++ trunk/subtle/Subtitles/__init__.py	2008-07-29 04:02:27 UTC (rev 15140)
@@ -18,5 +18,5 @@
 #       along with this program; if not, write to the Free Software
 #       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 #       MA 02110-1301, USA.
-__all__=["Subtitles", "SubRip","Discoverer","Line"]
+__all__=["Subtitles", "SubRip","Softni","Discoverer","Line"]
 

Modified: trunk/subtle/Subtle.py
===================================================================
--- trunk/subtle/Subtle.py	2008-07-26 19:59:13 UTC (rev 15139)
+++ trunk/subtle/Subtle.py	2008-07-29 04:02:27 UTC (rev 15140)
@@ -157,19 +157,27 @@
             self.subsListStore = gtk.ListStore(gobject.TYPE_UINT,
                                                 gobject.TYPE_UINT,
                                                 gobject.TYPE_UINT,
+                                                gobject.TYPE_UINT,
+                                                gobject.TYPE_UINT,
                                                 gobject.TYPE_STRING)
             SUBLIST.set_model(self.subsListStore)
             cell = gtk.CellRendererText()
             tvcolumn = gtk.TreeViewColumn('#', cell, text = 0)
             SUBLIST.append_column(tvcolumn)
             cell = gtk.CellRendererText()
-            tvcolumn = gtk.TreeViewColumn('Start', cell, text = 1)
+            tvcolumn = gtk.TreeViewColumn('Start Time', cell, text = 1)
             SUBLIST.append_column(tvcolumn)
             cell = gtk.CellRendererText()
-            tvcolumn = gtk.TreeViewColumn('End', cell, text = 2)
+            tvcolumn = gtk.TreeViewColumn('End Time', cell, text = 2)
             SUBLIST.append_column(tvcolumn)
             cell = gtk.CellRendererText()
-            tvcolumn = gtk.TreeViewColumn('Text', cell, text = 3)
+            tvcolumn = gtk.TreeViewColumn('Start Frame', cell, text = 3)
+            SUBLIST.append_column(tvcolumn)
+            cell = gtk.CellRendererText()
+            tvcolumn = gtk.TreeViewColumn('End Frame', cell, text = 4)
+            SUBLIST.append_column(tvcolumn)
+            cell = gtk.CellRendererText()
+            tvcolumn = gtk.TreeViewColumn('Text', cell, text = 5)
             tvcolumn.set_resizable(True)
             SUBLIST.append_column(tvcolumn)
         #WND=self.windowStreams.get_widget("STREAM_WINDOW")
@@ -449,6 +457,9 @@
             child = self.streamsTreeStore.append(iter)
             self.streamsTreeStore.set(child, 0, "Type: " + sub.subType, \
                     1, self.Subtitles.index(sub))
+            child = self.streamsTreeStore.append(iter)
+            self.streamsTreeStore.set(child, 0, "Encoding: " + sub.encoding, \
+                    1, self.Subtitles.index(sub))
         for mInfo in self.media:
             iter = self.streamsTreeStore.append(None)
             self.streamsTreeStore.set(iter, 0, mInfo.source, 1, self.media.index(mInfo))
@@ -666,7 +677,9 @@
             self.subsListStore.set(iter,0, j, 
                                         1, int(S.start_time),
                                         2, int(S.end_time),
-                                        3, str(S.getSubText()))
+                                        3, int(S.start_frame),
+                                        4, int(S.end_frame),
+                                        5, str(S.getSubText()))
             j +=1
 
 
@@ -676,10 +689,10 @@
         if self.PFileName[-4:]!=".spf":
             self.PFileName=self.PFileName+".spf"
         PXML=ProjectXML()
-        PXML.addHeadInfo("title", "Soufleur development version")
+        PXML.addHeadInfo("title", "Subtle development version")
         PXML.addHeadInfo("desc", "This is version current at development stage.")
-        PXML.addHeadInfo("author", "DarakuTenshi")
-        PXML.addHeadInfo("email", "otaky at ukr.net")
+        PXML.addHeadInfo("author", "Joao Mesquita")
+        PXML.addHeadInfo("email", "jmesquita at gmail.com")
         PXML.addHeadInfo("info", "Sample of save function")
         for i in self.media:
             PXML.addMedia(i)



More information about the commits mailing list