[xiph-commits] r16336 - in trunk/ffmpeg2theora: . frontend frontend/theoraenc src

j at svn.xiph.org j at svn.xiph.org
Sun Jul 26 00:33:09 PDT 2009


Author: j
Date: 2009-07-26 00:33:08 -0700 (Sun, 26 Jul 2009)
New Revision: 16336

Added:
   trunk/ffmpeg2theora/frontend/theoraenc/addSubtitlesDialog.py
Modified:
   trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py
   trunk/ffmpeg2theora/frontend/theoraenc/addVideoDialog.py
   trunk/ffmpeg2theora/frontend/theoraenc/theoraenc.py
   trunk/ffmpeg2theora/src/ffmpeg2theora.c
   trunk/ffmpeg2theora/src/subtitles.c
   trunk/ffmpeg2theora/src/subtitles.h
   trunk/ffmpeg2theora/src/theorautils.c
   trunk/ffmpeg2theora/subtitles.txt
Log:
add subtitles to python frontend

Modified: trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py
===================================================================
--- trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py	2009-07-25 22:52:38 UTC (rev 16335)
+++ trunk/ffmpeg2theora/frontend/Simple Theora Encoder.py	2009-07-26 07:33:08 UTC (rev 16336)
@@ -119,6 +119,16 @@
       if key in options and options[key]:
         settings.append('--%s' % key)
         settings.append("%s" % float(options[key]))
+    if 'subtitles' in options and options['subtitles']:
+      for s in options['subtitles']:
+        settings.append('--subtitles')
+        settings.append('%s' % s['file'])
+        settings.append('--subtitles-language')
+        settings.append('%s' % s['language'])
+        settings.append('--subtitles-category')
+        settings.append('%s' % s['category'])
+        settings.append('--subtitles-encoding')
+        settings.append('%s' % s['encoding'])
     return settings
 
   def addItemThread(self, item):
@@ -167,7 +177,7 @@
     self.removeItem.Enable()
   
   def OnClickAdd(self, event):
-    result = addVideoDialog(self)
+    result = addVideoDialog(self, theoraenc.hasKate)
     time.sleep(0.5)
     if result['ok']:
       self.addItemToQueue(result['videoFile'], result)

Added: trunk/ffmpeg2theora/frontend/theoraenc/addSubtitlesDialog.py
===================================================================
--- trunk/ffmpeg2theora/frontend/theoraenc/addSubtitlesDialog.py	                        (rev 0)
+++ trunk/ffmpeg2theora/frontend/theoraenc/addSubtitlesDialog.py	2009-07-26 07:33:08 UTC (rev 16336)
@@ -0,0 +1,242 @@
+# -*- coding: utf-8 -*-
+# vi:si:et:sw=2:sts=2:ts=2
+
+import os
+from os.path import basename
+import time
+
+import wx
+#import wx.lib.langlistctrl
+#from wx.lib.langlistctrl import GetWxIdentifierForLanguage
+from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
+
+# on my box, I only get two versions of en, and two languages I'd never heard of, and keyboard input is unavailable
+# to override for a language not in the list, so we don't use it, though it'd be nice as languages names would be
+# translated, etc.
+# After installing all locales, I don't even get some non obscure locales.
+# And it doesn't seem to use ISO 639-1 tags anyway, but wxWidgets specific enums.
+# Therefore, we use a "ComboBox" widget instead, and build a list of languages from a known set plus parsing
+# the output of 'locale -a' to ensure we get the user's own language, if set (and also plenty of others if using
+# a distro that spams the locale database with lots of unused ones); keyboard input overrides is available.
+#use_langlistctrl=False
+
+class SubtitlesProperties(wx.Dialog):
+  def __init__(
+          self, parent, ID, title,
+          language, category, encoding, file,
+          size=wx.DefaultSize, pos=wx.DefaultPosition, 
+          style=wx.DEFAULT_DIALOG_STYLE,
+          ):
+    pre = wx.PreDialog()
+    pre.Create(parent, ID, title, pos, size, style)
+    self.PostCreate(pre)
+
+    # defaults
+    if language == '':
+      language = 'en'
+    if category == '':
+      category = 'SUB'
+    if encoding == '':
+      encoding = 'UTF-8'
+
+    padding = 4
+
+    mainBox = wx.BoxSizer(wx.VERTICAL)
+    mainBox.AddSpacer((8, 16))
+
+    # file
+    self.btnSubtitlesFile = wx.Button(self, size=(380, -1))
+    self.btnSubtitlesFile.SetLabel('Select...')
+    self.Bind(wx.EVT_BUTTON, self.OnClickSubtitlesFile, self.btnSubtitlesFile)
+    self.addProperty(mainBox, 'File', self.btnSubtitlesFile)
+
+    # language
+#    if use_langlistctrl:
+#      self.languageWidget = wx.lib.langlistctrl.LanguageListCtrl(self, -1, style=wx.LC_REPORT, size=(380,140))
+#    else:
+#      self.languageWidget = wx.ComboBox(self, -1, language, (380,-1), wx.DefaultSize, self.BuildLanguagesList(), wx.CB_SIMPLE)
+    self.languageWidget = wx.ComboBox(self, -1, language, (380,-1), wx.DefaultSize, self.BuildLanguagesList(), wx.CB_SIMPLE)
+    self.addProperty(mainBox, 'Language', self.languageWidget, self.OnLanguageHelp)
+
+    # category
+    categories = ['SUB', 'CC', 'TRX', 'LRC'] # TODO: change when Silvia's list is final
+    self.categoryWidget = wx.ComboBox(self, -1, category, (80,-1), wx.DefaultSize, categories, wx.CB_SIMPLE)
+    self.addProperty(mainBox, 'Category', self.categoryWidget, self.OnCategoryHelp)
+
+    # encoding
+    encodings = ['UTF-8', 'ISO-8859-1']
+    self.encodingWidget = wx.Choice(self, -1, (80,-1), choices=encodings, name=encoding)
+    self.addProperty(mainBox, 'Encoding', self.encodingWidget, self.OnEncodingHelp)
+
+    #Buttons
+    hbox = wx.BoxSizer(wx.HORIZONTAL)
+    mainBox.Add(hbox)
+    hbox.AddSpacer((8, 16))
+
+    hbox = wx.BoxSizer(wx.HORIZONTAL)
+    mainBox.Add(hbox)
+    hbox.AddSpacer((280, 10))
+    self.btnCancel = wx.Button(self, wx.ID_CANCEL)
+    self.btnCancel.SetLabel('Cancel')
+    hbox.Add(self.btnCancel, 0, wx.EXPAND|wx.ALL, padding)
+
+    self.btnOK = wx.Button(self, wx.ID_OK)
+    self.btnOK.SetDefault()
+    self.btnOK.Disable()
+    self.btnOK.SetLabel('OK')
+    hbox.Add(self.btnOK, 0, wx.EXPAND|wx.ALL, padding)
+
+    hbox = wx.BoxSizer(wx.HORIZONTAL)
+    mainBox.Add(hbox)
+    hbox.AddSpacer((8, 8))
+
+    self.SetSizerAndFit(mainBox)
+
+    # preselect file, if any
+    if file and file != '' and os.path.exists(file):
+      self.selectSubtitlesFile(file)
+
+  def addProperty(self, mainBox, name, widget, help=None):
+    padding = 4
+    vspacer = 40
+    hspacer = 80
+
+    hbox = wx.BoxSizer(wx.HORIZONTAL)
+    mainBox.Add(hbox, 0, padding)
+    hbox.AddSpacer((8, 8))
+    label = wx.StaticText(self, -1, name)
+    label.SetMinSize((hspacer,vspacer))
+    hbox.Add(label, 0, wx.EXPAND|wx.ALL, padding)
+    hbox.Add(widget, 0, padding)
+    if help:
+      hbox.AddSpacer((16, 0))
+      btnHelp = wx.Button(self, size=(80, -1))
+      btnHelp.SetLabel('More info...')
+      self.Bind(wx.EVT_BUTTON, help, btnHelp)
+      hbox.Add(btnHelp, 0, padding)
+    hbox.AddSpacer((8, 8))
+
+  def OnCategoryHelp(self, event):
+    self.DisplayHelp(
+      'The category is a string representing the semantics of the text in a Kate stream.\n'+
+      'These codes include:\n'+
+      '  SUB: text subtitles\n'+
+      '  CC: closed captions\n'+
+      '  TRX: transcript of a speech\n'+
+      '  LRC: lyrics\n'+
+      'If the category needed is not available in the list, a custom one may be entered.\n')
+
+  def OnLanguageHelp(self, event):
+    self.DisplayHelp(
+      'Language is an ISO 639-1 or RFC 3066 language tag.\n'+
+      'Usually, these are two letter language tags (eg, "en", or "de"), '+
+      'optionally followed by a hypen (or underscore) and a country code (eg, "en_GB", "de_DE")\n'+
+      'If the language tag needed is not available in the list, a custom one may be entered.\n')
+
+  def OnEncodingHelp(self, event):
+    self.DisplayHelp(
+      'Kate streams are encoded in UTF-8 (a Unicode character encoding that allows to represent '+
+      'pretty much any existing script.\n'+
+      'If the input file is not already encoded in UTF-8, it will need converting to UTF-8 first.\n'+
+      'ffmpeg2theora can convert ISO-8859-1 (also known as latin1) encoding directly.\n'+
+      'Files in other encodings will have to be converted manually in order to be used. See the '+
+      'subtitles.txt documentation for more information on how to manually convert files.\n')
+
+  def DisplayHelp(self, msg):
+    wx.MessageBox(msg, 'More info...', style=wx.OK|wx.CENTRE)
+
+  def OnClickSubtitlesFile(self, event):
+    wildcard = "SubRip files|*.SRT;*.srt|All Files (*.*)|*.*"
+    dialogOptions = dict()
+    dialogOptions['message'] = 'Add subtitles..'
+    dialogOptions['wildcard'] = wildcard
+    dialog = wx.FileDialog(self, **dialogOptions)
+    if dialog.ShowModal() == wx.ID_OK:
+      filename = dialog.GetFilename()
+      dirname = dialog.GetDirectory()
+      self.selectSubtitlesFile(os.path.join(dirname, filename))
+    else:
+      filename=None
+    dialog.Destroy()
+    return filename
+
+  def selectSubtitlesFile(self, subtitlesFile):
+      self.subtitlesFile = subtitlesFile
+      lValue = subtitlesFile
+      lLength = 45
+      if len(lValue) > lLength:
+        lValue = "..." + lValue[-lLength:]
+      self.btnSubtitlesFile.SetLabel(lValue)
+      self.btnOK.Enable()
+
+  def BuildLanguagesList(self):
+    # start with a known basic set
+    languages = ['en', 'ja', 'de', 'fr', 'it', 'es', 'cy', 'ar', 'cn', 'pt', 'ru']
+    # add in whatever's known from 'locale -a' - this works fine if locale isn't found,
+    # but i'm not sure what that'll do if we get another program named locale that spews
+    # random stuff to stdout :)
+    f = os.popen('locale -a')
+    line = f.readline()
+    while line:
+      line = self.ExtractLanguage(line)
+      if line != '' and line != 'C' and line != 'POSIX':
+        languages.append(line)
+      line = f.readline()
+    f.close()
+    #oneliner from german python forum => unique list
+    languages = [languages[i] for i in xrange(len(languages)) if languages[i] not in languages[:i]]
+    languages.sort()
+    return languages
+
+  def ExtractLanguage(self, line):
+    line = line.split('.')[0] # stop at a dot
+    line = line.split(' ')[0] # stop at a space
+    line = line.split('@')[0] # stop at a @
+    line = line.split('\t')[0] # stop at a tab
+    line = line.split('\n')[0] # stop at a newline
+    line = line.split('\r')[0] # Mac or Windows
+    return line
+
+def addSubtitlesPropertiesDialog(parent, language, category, encoding, file):
+  dlg = SubtitlesProperties(parent, -1, "Add subtitles", language, category, encoding, file, size=(490, 560), style=wx.DEFAULT_DIALOG_STYLE)
+  dlg.CenterOnScreen()
+  val = dlg.ShowModal()
+  result = dict()
+  if val == wx.ID_OK:
+    result['ok'] = True
+    result['subtitlesFile'] = dlg.subtitlesFile
+#    if use_langlistctrl:
+#      result['subtitlesLanguage'] = GetWxIdentifierForLanguage(dlg.languageWidget.GetLanguage())
+#    else:
+#      result['subtitlesLanguage'] = dlg.languageWidget.GetValue()
+    result['subtitlesLanguage'] = dlg.languageWidget.GetValue()
+    result['subtitlesCategory'] = dlg.categoryWidget.GetValue()
+    result['subtitlesEncoding'] = dlg.encodingWidget.GetStringSelection()
+    print result
+  else:
+    result['ok'] = False
+  dlg.Destroy()
+  return result
+
+
+class SubtitlesList(wx.ListCtrl, ListCtrlAutoWidthMixin):
+  def __init__(self, parent):
+    wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT)
+    ListCtrlAutoWidthMixin.__init__(self)
+
+    self.ClearAll()
+    self.InsertColumn(0, "Language")
+    self.InsertColumn(1, "Category")
+    self.InsertColumn(2, "Encoding")
+    self.InsertColumn(3, "Name")
+    self.SetColumnWidth(0, 80)
+    self.SetColumnWidth(1, 80)
+    self.SetColumnWidth(2, 80)
+    self.SetColumnWidth(3, 80)
+
+  def ResizeFilenameColumn(self):
+    if self.GetItemCount() > 0:
+      self.resizeLastColumn(1024)
+    else:
+      self.resizeLastColumn(0)
+

Modified: trunk/ffmpeg2theora/frontend/theoraenc/addVideoDialog.py
===================================================================
--- trunk/ffmpeg2theora/frontend/theoraenc/addVideoDialog.py	2009-07-25 22:52:38 UTC (rev 16335)
+++ trunk/ffmpeg2theora/frontend/theoraenc/addVideoDialog.py	2009-07-26 07:33:08 UTC (rev 16336)
@@ -1,15 +1,16 @@
 # -*- coding: utf-8 -*-
-# vi:si:et:sw=2:sts=2:ts=2
+# vi:si:et:sw=2:sts=2:ts=2
 
 import os
 from os.path import basename
 import time
+from addSubtitlesDialog import addSubtitlesPropertiesDialog, SubtitlesList
 
 import wx
 
 class AddVideoDialog(wx.Dialog):
   def __init__(
-          self, parent, ID, title, size=wx.DefaultSize, pos=wx.DefaultPosition, 
+          self, parent, ID, title, hasKate, size=wx.DefaultSize, pos=wx.DefaultPosition, 
           style=wx.DEFAULT_DIALOG_STYLE,
           ):
     
@@ -145,6 +146,54 @@
     hbox = wx.BoxSizer(wx.HORIZONTAL)
     mainBox.Add(hbox)
 
+    # subtitles ('add' button and list)
+    hbox = wx.BoxSizer(wx.HORIZONTAL)
+    mainBox.Add(hbox)
+    label = wx.StaticText(self, -1, "Subtitles")
+    hbox.AddSpacer((12, 10))
+    hbox.Add(label, 0, wx.EXPAND|wx.ALL, padding)
+
+    hbox = wx.BoxSizer(wx.HORIZONTAL)
+    mainBox.Add(hbox)
+
+    hbox.AddSpacer((section_padding, 10))
+
+    if hasKate:
+      vbox = wx.BoxSizer(wx.VERTICAL)
+      hbox.Add(vbox)
+
+      subtitlesButtons_hbox = wx.BoxSizer(wx.HORIZONTAL)
+      vbox.Add(subtitlesButtons_hbox)
+
+      self.btnSubtitlesAdd = wx.Button(self, size=(120, -1))
+      self.btnSubtitlesAdd.SetLabel('Add...')
+      self.Bind(wx.EVT_BUTTON, self.OnClickSubtitlesAdd, self.btnSubtitlesAdd)
+      subtitlesButtons_hbox.Add(self.btnSubtitlesAdd, 0, wx.EXPAND|wx.ALL, padding)
+
+      self.btnSubtitlesRemove = wx.Button(self, size=(120, -1))
+      self.btnSubtitlesRemove.SetLabel('Remove')
+      self.Bind(wx.EVT_BUTTON, self.OnClickSubtitlesRemove, self.btnSubtitlesRemove)
+      self.btnSubtitlesRemove.Disable()
+      subtitlesButtons_hbox.Add(self.btnSubtitlesRemove, 0, wx.EXPAND|wx.ALL, padding)
+
+      self.btnSubtitlesProperties = wx.Button(self, size=(120, -1))
+      self.btnSubtitlesProperties.SetLabel('Properties')
+      self.Bind(wx.EVT_BUTTON, self.OnClickSubtitlesProperties, self.btnSubtitlesProperties)
+      self.btnSubtitlesProperties.Disable()
+      subtitlesButtons_hbox.Add(self.btnSubtitlesProperties, 0, wx.EXPAND|wx.ALL, padding)
+
+      #self.subtitles = wx.ListCtrl(self, -1, style=wx.LC_REPORT)
+      self.subtitles = SubtitlesList(self)
+      self.subtitles.Bind(wx.EVT_LIST_ITEM_SELECTED, self.CheckSubtitlesSelection)
+      self.subtitles.Bind(wx.EVT_LEFT_DCLICK, self.OnClickSubtitlesProperties)
+      self.subtitles.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.CheckSubtitlesSelection)
+      self.subtitles.Bind(wx.EVT_KILL_FOCUS, self.CheckSubtitlesSelection)
+      vbox.Add(self.subtitles, 0, wx.EXPAND|wx.ALL, padding)
+
+    else:
+      self.subtitles = None
+      hbox.Add(wx.StaticText(self, -1, "ffmpeg2theora doesn't seem to be built with subtitles support.\nSee documentation for how to enable subtitles.\n"))
+
     '''
     #Metadata
     label = wx.StaticText(self, -1, "Metadata")
@@ -257,14 +306,61 @@
   def selectVideoFile(self, videoFile):
         self.videoFile = videoFile
         lValue = videoFile
-        lLenght = 45
-        if len(lValue) > lLenght:
-          lValue = "..." + lValue[-lLenght:]
+        lLength = 45
+        if len(lValue) > lLength:
+          lValue = "..." + lValue[-lLength:]
         self.btnVideoFile.SetLabel(lValue)
         self.btnOK.Enable()
 
-def addVideoDialog(parent):
-  dlg = AddVideoDialog(parent, -1, "Add Video", size=(490, 560), style=wx.DEFAULT_DIALOG_STYLE)
+  def CheckSubtitlesSelection(self, event):
+    idx=self.subtitles.GetFirstSelected()
+    if idx<0:
+      self.btnSubtitlesRemove.Disable()
+      self.btnSubtitlesProperties.Disable()
+    else:
+      self.btnSubtitlesRemove.Enable()
+      self.btnSubtitlesProperties.Enable()
+    self.subtitles.ResizeFilenameColumn()
+
+  def OnClickSubtitlesAdd(self, event):
+    self.subtitles.Append(['', '', '', ''])
+    if not self.ChangeSubtitlesProperties(self.subtitles.GetItemCount()-1):
+      self.subtitles.DeleteItem(self.subtitles.GetItemCount()-1)
+    self.subtitles.ResizeFilenameColumn()
+
+  def OnClickSubtitlesRemove(self, event):
+    while 1:
+      idx=self.subtitles.GetFirstSelected()
+      if idx<0:
+         break
+      self.subtitles.DeleteItem(idx)
+    self.CheckSubtitlesSelection(event)
+
+  def OnClickSubtitlesProperties(self, event):
+    idx=self.subtitles.GetFirstSelected()
+    if idx<0:
+       return
+    self.ChangeSubtitlesProperties(idx)
+
+  def ChangeSubtitlesProperties(self, idx):
+    language = self.subtitles.GetItem(idx, 0).GetText()
+    category = self.subtitles.GetItem(idx, 1).GetText()
+    encoding = self.subtitles.GetItem(idx, 2).GetText()
+    file = self.subtitles.GetItem(idx, 3).GetText()
+    result = addSubtitlesPropertiesDialog(self, language, category, encoding, file)
+    time.sleep(0.5) # why ? race condition ?
+    if result['ok']:
+      self.subtitles.SetStringItem(idx, 0, result['subtitlesLanguage'])
+      self.subtitles.SetStringItem(idx, 1, result['subtitlesCategory'])
+      self.subtitles.SetStringItem(idx, 2, result['subtitlesEncoding'])
+      self.subtitles.SetStringItem(idx, 3, result['subtitlesFile'])
+      return True
+    else:
+      return False
+
+
+def addVideoDialog(parent, hasKate):
+  dlg = AddVideoDialog(parent, -1, "Add Video", hasKate, size=(490, 560), style=wx.DEFAULT_DIALOG_STYLE)
   dlg.CenterOnScreen()
   val = dlg.ShowModal()
   result = dict()
@@ -274,6 +370,16 @@
     for key in ('width', 'height', 'videoquality', 'videobitrate', 'framerate',
                 'audioquality', 'audiobitrate', 'samplerate'):
       result[key] = getattr(dlg, key).GetValue()
+    # subtitles
+    if dlg.subtitles:
+      for idx in range(dlg.subtitles.GetItemCount()):
+        if not 'subtitles' in result:
+          result['subtitles'] = []
+        language = dlg.subtitles.GetItem(idx, 0).GetText()
+        category = dlg.subtitles.GetItem(idx, 1).GetText()
+        encoding = dlg.subtitles.GetItem(idx, 2).GetText()
+        file = dlg.subtitles.GetItem(idx, 3).GetText()
+        result['subtitles'].append({'encoding':encoding, 'language':language, 'category':category, 'file':file})
     print result
   else:
     result['ok'] = False

Modified: trunk/ffmpeg2theora/frontend/theoraenc/theoraenc.py
===================================================================
--- trunk/ffmpeg2theora/frontend/theoraenc/theoraenc.py	2009-07-25 22:52:38 UTC (rev 16335)
+++ trunk/ffmpeg2theora/frontend/theoraenc/theoraenc.py	2009-07-26 07:33:08 UTC (rev 16336)
@@ -13,6 +13,32 @@
 
 resourcePath = abspath(dirname(__file__))
 
+def probe_ffmpeg2theora():
+  appname = 'ffmpeg2theora'
+  if os.name == 'nt':
+    appname = appname + '.exe'
+  ffmpeg2theora = join(resourcePath, appname)
+  if not exists(ffmpeg2theora):
+    # ffmpeg2theora is likely in $resourcePath/../.. since we're in frontend
+    ffmpeg2theora = join(resourcePath, join('../../', appname))
+    if not exists(ffmpeg2theora):
+      ffmpeg2theora = join('./', appname)
+      if not exists(ffmpeg2theora):
+        ffmpeg2theora = appname
+  return ffmpeg2theora
+
+def probe_kate(ffmpeg2theora):
+  hasKate = False
+  cmd = ffmpeg2theora + ' --help'
+  f = os.popen(cmd)
+  line = f.readline()
+  while line:
+    if line.find('Subtitles options:') >= 0:
+      hasKate = True
+    line = f.readline()
+  f.close()
+  return hasKate
+
 def timestr(seconds):
   hours   = int(seconds/3600)
   minutes = int((seconds-( hours*3600 ))/60)
@@ -22,20 +48,15 @@
 class TheoraEnc:
   settings = []
   p = None
+
   def __init__(self, inputFile, outputFile, updateGUI):
     self.inputFile = inputFile
     self.outputFile = outputFile
     self.updateGUI = updateGUI
-    appname = 'ffmpeg2theora'
-    if os.name == 'nt':
-      appname = appname + '.exe'
-    self.ffmpeg2theora = join(resourcePath, appname)
-    if not exists(self.ffmpeg2theora):
-      self.ffmpeg2theora = appname
   
   def commandline(self):
     cmd = []
-    cmd.append(self.ffmpeg2theora)
+    cmd.append(ffmpeg2theora)
     cmd.append('--frontend')
     for e in self.settings:
       cmd.append(e)
@@ -74,23 +95,33 @@
     line = f.readline()
     info = dict()
     status = ''
+    self.warning_timeout = 0
     while line:
+      now = time.time()
       try:
         data = simplejson.loads(line)
         for key in data:
           info[key] = data[key]
-        if 'position' in info:
-          if 'duration' in info and float(info['duration']):
-            encoded =  "encoding % 3d %% done " % ((float(info['position']) / float(info['duration'])) * 100)
-          else:
-            encoded = "encoded %s/" % timestr(float(info['position']))
-          if float(info['remaining'])>0:
-            status = encoded + '/ '+ timestr(float(info['remaining']))
-          else:
-            status = encoded
+        if 'WARNING' in info:
+          status = info['WARNING']
+          self.warning_timeout = now + 3
+          del info['WARNING']
         else:
-          status = "encoding.."
-        self.updateGUI(status)
+          status=None
+          if now >= self.warning_timeout:
+            if 'position' in info:
+              if 'duration' in info and float(info['duration']):
+                encoded =  "encoding % 3d %% done " % ((float(info['position']) / float(info['duration'])) * 100)
+              else:
+                encoded = "encoded %s/" % timestr(float(info['position']))
+              if float(info['remaining'])>0:
+                status = encoded + '/ '+ timestr(float(info['remaining']))
+              else:
+                status = encoded
+            else:
+              status = "encoding.."
+        if status != None:
+          self.updateGUI(status)
       except:
         pass
       line = f.readline()
@@ -102,3 +133,6 @@
       self.updateGUI(info.get('result', 'Encoding failed.'))
       return False
 
+ffmpeg2theora = probe_ffmpeg2theora()
+hasKate = probe_kate(ffmpeg2theora)
+

Modified: trunk/ffmpeg2theora/src/ffmpeg2theora.c
===================================================================
--- trunk/ffmpeg2theora/src/ffmpeg2theora.c	2009-07-25 22:52:38 UTC (rev 16335)
+++ trunk/ffmpeg2theora/src/ffmpeg2theora.c	2009-07-26 07:33:08 UTC (rev 16336)
@@ -857,7 +857,7 @@
               info.with_kate=1;
             }
         }
-        else if (load_subtitles(ks,this->ignore_non_utf8)>0) {
+        else if (load_subtitles(ks,this->ignore_non_utf8,info.frontend)>0) {
 #ifdef DEBUG
             printf("Muxing Kate stream %d from %s as %s %s\n",
                 i,ks->filename,
@@ -1350,7 +1350,7 @@
                     t = 0;
                   }
                   if (utf8 && t >= 0)
-                    add_subtitle_for_stream(this->kate_streams, this->n_kate_streams, pkt.stream_index, t, duration, utf8, utf8len);
+                    add_subtitle_for_stream(this->kate_streams, this->n_kate_streams, pkt.stream_index, t, duration, utf8, utf8len, info.frontend);
                   if (allocated_utf8) free(allocated_utf8);
                 }
                 else {
@@ -1640,7 +1640,7 @@
         "             supported are " SUPPORTED_ENCODINGS "\n"
         "      --subtitles-language language    set subtitles language (de, en_GB, etc)\n"
         "      --subtitles-category category    set subtitles category (default \"subtitles\")\n"
-        "      --subtitles-ignore-non-utf8      ignores any non utf-8 sequence in utf-8 text\n"
+        "      --subtitles-ignore-non-utf8      ignores any non UTF-8 sequence in UTF-8 text\n"
         "      --nosubtitles                    disables subtitles from input\n"
         "\n"
 #endif
@@ -1900,11 +1900,11 @@
                             info.with_kate=1;
                             break;
                         case SUBTITLES_ENCODING_FLAG:
-                            if (!strcmp(optarg,"utf-8")) set_subtitles_encoding(convert,ENC_UTF8);
-                            if (!strcmp(optarg,"utf8")) set_subtitles_encoding(convert,ENC_UTF8);
-                            else if (!strcmp(optarg,"iso-8859-1")) set_subtitles_encoding(convert,ENC_ISO_8859_1);
-                            else if (!strcmp(optarg,"latin1")) set_subtitles_encoding(convert,ENC_ISO_8859_1);
-                            else report_unknown_subtitle_encoding(optarg);
+                            if (!strcasecmp(optarg,"utf-8")) set_subtitles_encoding(convert,ENC_UTF8);
+                            else if (!strcasecmp(optarg,"utf8")) set_subtitles_encoding(convert,ENC_UTF8);
+                            else if (!strcasecmp(optarg,"iso-8859-1")) set_subtitles_encoding(convert,ENC_ISO_8859_1);
+                            else if (!strcasecmp(optarg,"latin1")) set_subtitles_encoding(convert,ENC_ISO_8859_1);
+                            else report_unknown_subtitle_encoding(optarg, info.frontend);
                             flag = -1;
                             break;
                         case SUBTITLES_IGNORE_NON_UTF8_FLAG:

Modified: trunk/ffmpeg2theora/src/subtitles.c
===================================================================
--- trunk/ffmpeg2theora/src/subtitles.c	2009-07-25 22:52:38 UTC (rev 16335)
+++ trunk/ffmpeg2theora/src/subtitles.c	2009-07-26 07:33:08 UTC (rev 16336)
@@ -26,6 +26,7 @@
 #include <getopt.h>
 #include <math.h>
 #include <errno.h>
+#include <stdarg.h>
 
 #include "libavformat/avformat.h"
 
@@ -37,6 +38,26 @@
 #include "subtitles.h"
 
 
+static void warn(FILE *frontend, const char *file, unsigned int line, const char *format,...)
+{
+  va_list ap;
+  va_start(ap,format);
+  if (frontend) {
+    fprintf(frontend,"{\"WARNING\": \"");
+    vfprintf(frontend,format,ap);
+    fprintf(frontend,"\"}\n");
+  }
+  else {
+    if (file)
+      fprintf(stderr, "WARNING - %s:%u: ", file, line);
+    else
+      fprintf(stderr, "WARNING - ");
+    vfprintf(stderr,format,ap);
+    fprintf(stderr,"\n");
+  }
+  va_end(ap);
+}
+
 /**
   * adds a new kate stream structure
   */
@@ -125,11 +146,13 @@
 }
 
 
-void report_unknown_subtitle_encoding(const char *name)
+void report_unknown_subtitle_encoding(const char *name, FILE *frontend)
 {
-  fprintf(stderr, "Unknown character encoding: %s\n",name);
-  fprintf(stderr, "Valid character encodings are:\n");
-  fprintf(stderr, "  " SUPPORTED_ENCODINGS "\n");
+  warn(frontend, NULL, 0, "Unknown character encoding: %s",name);
+  if (!frontend) {
+    fprintf(stderr, "Valid character encodings are:\n");
+    fprintf(stderr, "  " SUPPORTED_ENCODINGS "\n");
+  }
 }
 
 #ifdef HAVE_KATE
@@ -152,7 +175,7 @@
 }
 
 /* very simple implementation when no iconv */
-static char *convert_subtitle_to_utf8(F2T_ENCODING encoding,char *text,int ignore_non_utf8)
+static char *convert_subtitle_to_utf8(F2T_ENCODING encoding,char *text,int ignore_non_utf8, FILE *frontend)
 {
   size_t nbytes;
   char *ptr;
@@ -163,10 +186,10 @@
 
   switch (encoding) {
     case ENC_UNSET:
-      /* we don't know what encoding this is, assume utf-8 and we'll yell if it ain't */
+      /* we don't know what encoding this is, assume UTF-8 and we'll yell if it ain't */
       /* fall through */
     case ENC_UTF8:
-      /* nothing to do, already in utf-8 */
+      /* nothing to do, already in UTF-8 */
       if (ignore_non_utf8) {
         /* actually, give the user the option of just ignoring non UTF8 characters */
         char *wptr;
@@ -175,7 +198,7 @@
         nbytes = strlen(text)+1;
         newtext=(char*)malloc(nbytes);
         if (!newtext) {
-          fprintf(stderr, "WARNING - Memory allocation failed - cannot convert text\n");
+          warn(frontend, NULL, 0, "Memory allocation failed - cannot convert text");
           return NULL;
         }
         ptr = text;
@@ -187,7 +210,7 @@
             /* valid character */
             ret=kate_text_set_character(kate_utf8, ret, &wptr, &wlen0);
             if (ret<0) {
-              fprintf(stderr, "WARNING - failed to filter utf8 text: %s\n", text);
+              warn(frontend, NULL, 0, "Failed to filter utf8 text: %s", text);
               free(newtext);
               return NULL;
             }
@@ -202,7 +225,7 @@
         }
 
         if (errors) {
-          fprintf(stderr, "WARNING - Found non utf8 character(s) in string %s, scrubbed out\n", text);
+          warn(frontend, NULL, 0, "Found non utf8 character(s) in string %s, scrubbed out", text);
         }
       }
       else {
@@ -219,7 +242,7 @@
       }
       newtext=(char*)malloc(1+nbytes);
       if (!newtext) {
-        fprintf(stderr, "WARNING - Memory allocation failed - cannot convert text\n");
+        warn(frontend, NULL, 0, "Memory allocation failed - cannot convert text");
         return NULL;
       }
       nbytes=0;
@@ -235,7 +258,7 @@
       newtext[nbytes++]=0;
       break;
     default:
-      fprintf(stderr, "ERROR: encoding %d not handled in conversion!\n", encoding);
+      warn(frontend, NULL, 0, "encoding %d not handled in conversion!", encoding);
       newtext = strdup("");
       break;
   }
@@ -252,7 +275,7 @@
 
 #endif
 
-int load_subtitles(ff2theora_kate_stream *this, int ignore_non_utf8)
+int load_subtitles(ff2theora_kate_stream *this, int ignore_non_utf8, FILE *frontend)
 {
 #ifdef HAVE_KATE
     enum { need_id, need_timing, need_text };
@@ -274,13 +297,13 @@
     this->subtitles = NULL;
 
     if (!this->filename) {
-        fprintf(stderr,"WARNING - No subtitles file to load from\n");
+        warn(frontend, NULL, 0, "No subtitles file to load from");
         return -1;
     }
 
     f = fopen(this->filename, "r");
     if (!f) {
-        fprintf(stderr,"WARNING - Failed to open subtitles file %s (%s)\n", this->filename, strerror(errno));
+        warn(frontend, NULL, 0, "Failed to open subtitles file %s (%s)", this->filename, strerror(errno));
         return -1;
     }
 
@@ -302,13 +325,13 @@
           else {
             ret=sscanf(str,"%d\n",&id);
             if (ret!=1 || id<0) {
-              fprintf(stderr,"WARNING - %s:%u: Syntax error: %s\n",this->filename,line,str);
+              warn(frontend, this->filename, line, "Syntax error: %s",str);
               fclose(f);
               free(this->subtitles);
               return -1;
             }
             if (id!=last_seen_id+1) {
-              fprintf(stderr,"WARNING - %s:%u: non consecutive ids: %s - pretending not to have noticed\n",this->filename,line,str);
+              warn(frontend, this->filename, line, "Non consecutive ids: %s - pretending not to have noticed",str);
             }
             last_seen_id=id;
             need=need_timing;
@@ -318,7 +341,7 @@
         case need_timing:
           ret=sscanf(str,"%d:%d:%d%*[.,]%d --> %d:%d:%d%*[.,]%d\n",&h0,&m0,&s0,&ms0,&h1,&m1,&s1,&ms1);
           if (ret!=8 || (h0|m0|s0|ms0)<0 || (h1|m1|s1|ms1)<0) {
-            fprintf(stderr,"WARNING - %s:%u: Syntax error: %s\n",this->filename,line,str);
+            warn(frontend, this->filename, line, "Syntax error: %s",str);
             fclose(f);
             free(this->subtitles);
             return -1;
@@ -335,8 +358,9 @@
             remove_last_newline(text);
 
             /* we want all text to be UTF8 */
-            utf8=convert_subtitle_to_utf8(this->subtitles_encoding,text,ignore_non_utf8);
+            utf8=convert_subtitle_to_utf8(this->subtitles_encoding,text,ignore_non_utf8, frontend);
             if (!utf8) {
+              warn(frontend, this->filename, line, "Failed to get UTF-8 text");
               fclose(f);
               free(this->subtitles);
               return -1;
@@ -347,7 +371,7 @@
             this->subtitles = (ff2theora_subtitle*)realloc(this->subtitles, (this->num_subtitles+1)*sizeof(ff2theora_subtitle));
             if (!this->subtitles) {
               free(utf8);
-              fprintf(stderr, "Out of memory\n");
+              warn(frontend, NULL, 0, "Out of memory");
               fclose(f);
               free(this->subtitles);
               return -1;
@@ -355,8 +379,9 @@
             ret=kate_text_validate(kate_utf8,utf8,len+1);
             if (ret<0) {
               if (!warned) {
-                fprintf(stderr,"WARNING - %s:%u: subtitle %s is not valid utf-8\n",this->filename,line,utf8);
-                fprintf(stderr,"  further invalid subtitles will NOT be flagged\n");
+                warn(frontend, this->filename, line, "subtitle is not valid UTF-8: %s",utf8);
+                if (!frontend)
+                  fprintf(stderr,"  further invalid subtitles will NOT be flagged\n");
                 warned=1;
               }
             }
@@ -377,7 +402,7 @@
             /* in case of very long subtitles */
             len=strlen(text);
             if (len+strlen(str) >= sizeof(text)) {
-              fprintf(stderr,"WARNING - %s:%u: subtitle text is too long - truncated\n",this->filename,line);
+              warn(frontend, this->filename, line, "Subtitle text is too long - truncated");
             }
             strncpy(text+len,str,sizeof(text)-len);
             text[sizeof(text)-1]=0;
@@ -390,10 +415,13 @@
 
     fclose(f);
 
+#if 0
+    // there seems to be quite a lot of files like this, so disable this test.
     if (need!=need_id) {
       /* shouldn't be a problem though, but warn */
-      fprintf(stderr,"WARNING - %s:%u: missing data in %s - truncated file ?\n",this->filename,line,this->filename);
+      warn(frontend, this->filename, line, "Missing data in - truncated file ?");
     }
+#endif
 
     /* fprintf(stderr,"  %u subtitles loaded.\n", this->num_subtitles); */
 
@@ -403,7 +431,7 @@
 #endif
 }
 
-int add_subtitle_for_stream(ff2theora_kate_stream *streams, int nstreams, int idx, float t, float duration, const char *utf8, size_t utf8len)
+int add_subtitle_for_stream(ff2theora_kate_stream *streams, int nstreams, int idx, float t, float duration, const char *utf8, size_t utf8len, FILE *frontend)
 {
 #ifdef HAVE_KATE
   int n, ret;
@@ -412,19 +440,19 @@
     if (idx == ks->stream_index) {
       ks->subtitles = (ff2theora_subtitle*)realloc(ks->subtitles, (ks->num_subtitles+1)*sizeof(ff2theora_subtitle));
       if (!ks->subtitles) {
-        fprintf(stderr, "Out of memory\n");
+        warn(frontend, NULL, 0, "Out of memory");
         return -1;
       }
       ret=kate_text_validate(kate_utf8,utf8,utf8len);
       if (ret<0) {
-        fprintf(stderr,"WARNING - stream %d: subtitle %s is not valid UTF-8\n",idx,utf8);
+        warn(frontend, NULL, 0, "stream %d: subtitle %s is not valid UTF-8",idx,utf8);
       }
       else {
         /* make a copy */
         size_t len = utf8len;
         char *utf8copy = (char*)malloc(utf8len);
         if (!utf8copy) {
-	  fprintf(stderr, "Out of memory\n");
+	  warn(frontend, NULL, 0, "Out of memory");
 	  return -1;
         }
         memcpy(utf8copy, utf8, utf8len);

Modified: trunk/ffmpeg2theora/src/subtitles.h
===================================================================
--- trunk/ffmpeg2theora/src/subtitles.h	2009-07-25 22:52:38 UTC (rev 16335)
+++ trunk/ffmpeg2theora/src/subtitles.h	2009-07-26 07:33:08 UTC (rev 16336)
@@ -16,16 +16,16 @@
 #define SUPPORTED_ENCODINGS "utf-8, utf8, iso-8859-1, latin1"
 
 extern void add_kate_stream(ff2theora this);
-extern int load_subtitles(ff2theora_kate_stream *this, int ignore_non_utf8);
+extern int load_subtitles(ff2theora_kate_stream *this, int ignore_non_utf8, FILE *frontend);
 extern void free_subtitles(ff2theora this);
 
 extern void add_subtitles_stream(ff2theora this,int stream_index,const char *language,const char *category);
-extern int add_subtitle_for_stream(ff2theora_kate_stream *streams, int nstreams, int idx, float t, float duration, const char *utf8, size_t utf8len);
+extern int add_subtitle_for_stream(ff2theora_kate_stream *streams, int nstreams, int idx, float t, float duration, const char *utf8, size_t utf8len, FILE *frontend);
 extern void set_subtitles_file(ff2theora this,const char *filename);
 extern void set_subtitles_language(ff2theora this,const char *language);
 extern void set_subtitles_category(ff2theora this,const char *category);
 extern void set_subtitles_encoding(ff2theora this,F2T_ENCODING encoding);
-extern void report_unknown_subtitle_encoding(const char *name);
+extern void report_unknown_subtitle_encoding(const char *name, FILE *frontend);
 
 #endif
 

Modified: trunk/ffmpeg2theora/src/theorautils.c
===================================================================
--- trunk/ffmpeg2theora/src/theorautils.c	2009-07-25 22:52:38 UTC (rev 16335)
+++ trunk/ffmpeg2theora/src/theorautils.c	2009-07-26 07:33:08 UTC (rev 16336)
@@ -152,7 +152,6 @@
  */
 void add_fisbone_packet (oggmux_info *info) {
     ogg_packet op;
-    int n;
 
     if (!info->audio_only) {
         memset (&op, 0, sizeof (op));
@@ -211,6 +210,7 @@
 
 #ifdef HAVE_KATE
     if (info->with_kate) {
+        int n;
         for (n=0; n<info->n_kate_streams; ++n) {
             oggmux_kate_stream *ks=info->kate_streams+n;
         memset (&op, 0, sizeof (op));
@@ -294,8 +294,8 @@
 
     /* initialize kate if we have subtitles */
     if (info->with_kate) {
+#ifdef HAVE_KATE
         int ret, n;
-#ifdef HAVE_KATE
         for (n=0; n<info->n_kate_streams; ++n) {
             oggmux_kate_stream *ks=info->kate_streams+n;
             ogg_stream_init (&ks->ko, rand ());    /* oops, add one ot the above */

Modified: trunk/ffmpeg2theora/subtitles.txt
===================================================================
--- trunk/ffmpeg2theora/subtitles.txt	2009-07-25 22:52:38 UTC (rev 16335)
+++ trunk/ffmpeg2theora/subtitles.txt	2009-07-26 07:33:08 UTC (rev 16336)
@@ -2,7 +2,7 @@
 
  * Overview
  * Subtitles related options
- * Converting non-utf-8 files to utf-8
+ * Converting non-UTF-8 files to UTF-8
  * Examples
  * Playing subtitles
 
@@ -11,9 +11,9 @@
  * Overview
 
 Subtitles are read from SubRip (.srt) format files and converted to
-Kate streams. Those SubRip files must be encoded in utf-8 (7 bit ASCII
-is a subset of utf-8 so is valid input as well). See below for more
-information on converting SubRip files with other encodings to utf-8.
+Kate streams. Those SubRip files must be encoded in UTF-8 (7 bit ASCII
+is a subset of UTF-8 so is valid input as well). See below for more
+information on converting SubRip files with other encodings to UTF-8.
 
 Subtitles support requires libkate, available from:
 http://code.google.com/p/libkate
@@ -36,7 +36,7 @@
  * Subtitles related options
 
 --subtitles <file>
-   Loads subtitles from a file, which must be an utf-8 encoded SubRip
+   Loads subtitles from a file, which must be an UTF-8 encoded SubRip
    (.srt) file
 
 --subtitles-language <language>
@@ -57,19 +57,19 @@
 
 --subtitles-encoding <encoding>
   Sets the encoding of the relevant input file. Allowed encodings are
-  utf-8, utf8, iso-8859-1, and latin1. The first two are synonymous and
+  UTF-8, UTF8, iso-8859-1, and latin1. The first two are synonymous and
   yield no conversion. The latter two are synonymous and convert from
-  iso-8859-1 to utf-8.
+  iso-8859-1 to UTF-8.
   If the input file is in another encoding, a separate step is needed
-  to convert the input file to utf-8. See below for more information on
-  converting other encoding to utf-8.
-  If unspecified, the default is utf-8.
+  to convert the input file to UTF-8. See below for more information on
+  converting other encoding to UTF-8.
+  If unspecified, the default is UTF-8.
 
 --subtitles-ignore-non-utf8
-  Any invalid sequence in utf-8 text will be ignored. This may be useful
-  when using an utf-8 file with stray non utf-8 characters. This is not
-  a substitute for converting a non utf-8 file to utf-8, however, as the
-  non utf-8 sequence will be missing from the output stream.
+  Any invalid sequence in UTF-8 text will be ignored. This may be useful
+  when using an UTF-8 file with stray non UTF-8 characters. This is not
+  a substitute for converting a non UTF-8 file to UTF-8, however, as the
+  non UTF-8 sequence will be missing from the output stream.
 
 --nosubtitles
   Subtitle streams from the input file will not be converted. Subtitles
@@ -77,15 +77,15 @@
 
 
 
- * Converting non-utf-8 files to utf-8
+ * Converting non-UTF-8 files to UTF-8
 
-If you have SubRip files in another format than utf-8, you can use the
-iconv or recode programs to convert them to utf-8 so ffmpeg2theora can
+If you have SubRip files in another format than UTF-8, you can use the
+iconv or recode programs to convert them to UTF-8 so ffmpeg2theora can
 read them.
 
    * iconv
-      If you have a file called subtitles.srt which is not in utf-8,
-      you can convert it to utf-8 with the command:
+      If you have a file called subtitles.srt which is not in UTF-8,
+      you can convert it to UTF-8 with the command:
 
          iconv -t utf-8 -f ENCODING subtitles.srt > subtitles.utf8.srt
 
@@ -95,18 +95,18 @@
       encoding, replace ENCODING with UCS-2BE.
 
       This will create a new file called subtitles.utf8.srt, which will
-      be the equivalent of the input file, but in utf-8 format, so it
+      be the equivalent of the input file, but in UTF-8 format, so it
       can be used as input to ffmpeg2theora.
 
-      To view a list of all the encodings iconv can convert to utf-8,
+      To view a list of all the encodings iconv can convert to UTF-8,
       see the output of `iconv -l'.
 
    * recode
 
-      If you have a file called subtitles.srt which is not in utf-8,
-      you can convert it to utf-8 with the command:
+      If you have a file called subtitles.srt which is not in UTF-8,
+      you can convert it to UTF-8 with the command:
 
-         recode ENCODING..utf-8 < subtitles.srt > subtitles.utf8.srt
+         recode ENCODING..UTF-8 < subtitles.srt > subtitles.utf8.srt
 
       Substitute ENCODING with the actual encoding of the input file.
       For instance, if your input file is in Shift-JIS encoding, replace
@@ -114,10 +114,10 @@
       replace ENCODING with BIG5.
 
       This will create a new file called subtitles.utf8.srt, which will
-      be the equivalent of the input file, but in utf-8 format, so it
+      be the equivalent of the input file, but in UTF-8 format, so it
       can be used as input to ffmpeg2theora.
 
-      To view a list of all the encodings recode can convert to utf-8,
+      To view a list of all the encodings recode can convert to UTF-8,
       see the output of `recode -l'.
 
 
@@ -148,5 +148,5 @@
 
 At the moment, only VLC has playback support for Kate streams. However, the
 libkate distribution includes patches for other players and media frameworks
-(MPlayer, GStreamer).
+(MPlayer, GStreamer, liboggplay).
 



More information about the commits mailing list