~vcs-imports/ffmpeg2theora/trunk

« back to all changes in this revision

Viewing changes to frontend/theoraenc/addSubtitlesDialog.py

  • Committer: j
  • Date: 2012-11-24 08:27:29 UTC
  • Revision ID: j-20121124082729-ytxmxeamew1v688s
leave note about migration to git://git.xiph.org/ffmpeg2theora.git

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
# vi:si:et:sw=2:sts=2:ts=2
3
 
 
4
 
import os
5
 
from os.path import basename
6
 
import time
7
 
import subprocess
8
 
 
9
 
import wx
10
 
#import wx.lib.langlistctrl
11
 
#from wx.lib.langlistctrl import GetWxIdentifierForLanguage
12
 
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
13
 
 
14
 
# on my box, I only get two versions of en, and two languages I'd never heard of, and keyboard input is unavailable
15
 
# 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
16
 
# translated, etc.
17
 
# After installing all locales, I don't even get some non obscure locales.
18
 
# And it doesn't seem to use ISO 639-1 tags anyway, but wxWidgets specific enums.
19
 
# Therefore, we use a "ComboBox" widget instead, and build a list of languages from a known set plus parsing
20
 
# the output of 'locale -a' to ensure we get the user's own language, if set (and also plenty of others if using
21
 
# a distro that spams the locale database with lots of unused ones); keyboard input overrides is available.
22
 
#use_langlistctrl=False
23
 
 
24
 
class SubtitlesProperties(wx.Dialog):
25
 
  def __init__(
26
 
          self, parent, ID, title,
27
 
          language, category, encoding, file, hasIconv,
28
 
          size=wx.DefaultSize, pos=wx.DefaultPosition, 
29
 
          style=wx.DEFAULT_DIALOG_STYLE,
30
 
          ):
31
 
    pre = wx.PreDialog()
32
 
    pre.Create(parent, ID, title, pos, size, style)
33
 
    self.PostCreate(pre)
34
 
 
35
 
    self.hasIconv = hasIconv
36
 
 
37
 
    # defaults
38
 
    if language == '':
39
 
      language = 'en'
40
 
    if category == '':
41
 
      category = 'SUB'
42
 
    if encoding == '':
43
 
      encoding = 'UTF-8'
44
 
 
45
 
    padding = 4
46
 
 
47
 
    mainBox = wx.BoxSizer(wx.VERTICAL)
48
 
    mainBox.AddSpacer((8, 16))
49
 
 
50
 
    # file
51
 
    self.btnSubtitlesFile = wx.Button(self, size=(380, -1))
52
 
    self.btnSubtitlesFile.SetLabel('Select...')
53
 
    self.Bind(wx.EVT_BUTTON, self.OnClickSubtitlesFile, self.btnSubtitlesFile)
54
 
    self.addProperty(mainBox, 'File', self.btnSubtitlesFile)
55
 
 
56
 
    # language
57
 
#    if use_langlistctrl:
58
 
#      self.languageWidget = wx.lib.langlistctrl.LanguageListCtrl(self, -1, style=wx.LC_REPORT, size=(380,140))
59
 
#    else:
60
 
#      self.languageWidget = wx.ComboBox(self, -1, language, (380,-1), wx.DefaultSize, self.BuildLanguagesList(), wx.CB_SIMPLE)
61
 
    self.languageWidget = wx.ComboBox(self, -1, language, (380,-1), wx.DefaultSize, self.BuildLanguagesList(), wx.CB_SIMPLE)
62
 
    self.addProperty(mainBox, 'Language', self.languageWidget, self.OnLanguageHelp)
63
 
 
64
 
    # category
65
 
    categories = ['SUB', 'CC', 'TRX', 'LRC'] # TODO: change when Silvia's list is final
66
 
    self.categoryWidget = wx.ComboBox(self, -1, category, (80,-1), wx.DefaultSize, categories, wx.CB_SIMPLE)
67
 
    self.addProperty(mainBox, 'Category', self.categoryWidget, self.OnCategoryHelp)
68
 
 
69
 
    # encoding
70
 
    if hasIconv:
71
 
      self.encodingWidget = wx.ComboBox(self, -1, encoding, (80,-1), wx.DefaultSize, self.BuildEncodingsList(self.hasIconv), wx.CB_SIMPLE)
72
 
    else:
73
 
      self.encodingWidget = wx.Choice(self, -1, (80,-1), choices=self.BuildEncodingsList(self.hasIconv))
74
 
    self.addProperty(mainBox, 'Encoding', self.encodingWidget, self.OnEncodingHelp)
75
 
 
76
 
    #Buttons
77
 
    hbox = wx.BoxSizer(wx.HORIZONTAL)
78
 
    mainBox.Add(hbox)
79
 
    hbox.AddSpacer((8, 16))
80
 
 
81
 
    hbox = wx.BoxSizer(wx.HORIZONTAL)
82
 
    mainBox.Add(hbox)
83
 
    hbox.AddSpacer((280, 10))
84
 
    self.btnCancel = wx.Button(self, wx.ID_CANCEL)
85
 
    self.btnCancel.SetLabel('Cancel')
86
 
    hbox.Add(self.btnCancel, 0, wx.EXPAND|wx.ALL, padding)
87
 
 
88
 
    self.btnOK = wx.Button(self, wx.ID_OK)
89
 
    self.btnOK.SetDefault()
90
 
    self.btnOK.Disable()
91
 
    self.btnOK.SetLabel('OK')
92
 
    hbox.Add(self.btnOK, 0, wx.EXPAND|wx.ALL, padding)
93
 
 
94
 
    hbox = wx.BoxSizer(wx.HORIZONTAL)
95
 
    mainBox.Add(hbox)
96
 
    hbox.AddSpacer((8, 8))
97
 
 
98
 
    self.SetSizerAndFit(mainBox)
99
 
 
100
 
    # preselect file, if any
101
 
    if file and file != '' and os.path.exists(file):
102
 
      self.selectSubtitlesFile(file)
103
 
 
104
 
  def addProperty(self, mainBox, name, widget, help=None):
105
 
    padding = 4
106
 
    vspacer = 40
107
 
    hspacer = 80
108
 
 
109
 
    hbox = wx.BoxSizer(wx.HORIZONTAL)
110
 
    mainBox.Add(hbox, 0, padding)
111
 
    hbox.AddSpacer((8, 8))
112
 
    label = wx.StaticText(self, -1, name)
113
 
    label.SetMinSize((hspacer,vspacer))
114
 
    hbox.Add(label, 0, wx.EXPAND|wx.ALL, padding)
115
 
    hbox.Add(widget, 0, padding)
116
 
    if help:
117
 
      hbox.AddSpacer((16, 0))
118
 
      btnHelp = wx.Button(self, size=(80, -1))
119
 
      btnHelp.SetLabel('More info...')
120
 
      self.Bind(wx.EVT_BUTTON, help, btnHelp)
121
 
      hbox.Add(btnHelp, 0, padding)
122
 
    hbox.AddSpacer((8, 8))
123
 
 
124
 
  def OnCategoryHelp(self, event):
125
 
    self.DisplayHelp(
126
 
      'The category is a string representing the semantics of the text in a Kate stream.\n'+
127
 
      'These codes include:\n'+
128
 
      '  SUB: text subtitles\n'+
129
 
      '  CC: closed captions\n'+
130
 
      '  TRX: transcript of a speech\n'+
131
 
      '  LRC: lyrics\n'+
132
 
      'If the category needed is not available in the list, a custom one may be entered.\n')
133
 
 
134
 
  def OnLanguageHelp(self, event):
135
 
    self.DisplayHelp(
136
 
      'Language is an ISO 639-1 or RFC 3066 language tag.\n'+
137
 
      'Usually, these are two letter language tags (eg, "en", or "de"), '+
138
 
      'optionally followed by a hypen (or underscore) and a country code (eg, "en_GB", "de_DE")\n'+
139
 
      'If the language tag needed is not available in the list, a custom one may be entered.\n')
140
 
 
141
 
  def OnEncodingHelp(self, event):
142
 
    iconv_blurb = ''
143
 
    if self.hasIconv:
144
 
      iconv_blurb = 'ffmpeg2theora was built with iconv support, so can also convert any encoding that is supported by iconv.\n'
145
 
    self.DisplayHelp(
146
 
      'Kate streams are encoded in UTF-8 (a Unicode character encoding that allows to represent '+
147
 
      'pretty much any existing script.\n'+
148
 
      'If the input file is not already encoded in UTF-8, it will need converting to UTF-8 first.\n'+
149
 
      'ffmpeg2theora can convert ISO-8859-1 (also known as latin1) encoding directly.\n'+
150
 
      iconv_blurb+
151
 
      'Files in other encodings will have to be converted manually in order to be used. See the '+
152
 
      'subtitles.txt documentation for more information on how to manually convert files.\n')
153
 
 
154
 
  def DisplayHelp(self, msg):
155
 
    wx.MessageBox(msg, 'More info...', style=wx.OK|wx.CENTRE)
156
 
 
157
 
  def OnClickSubtitlesFile(self, event):
158
 
    wildcard = "SubRip files|*.SRT;*.srt|All Files (*.*)|*.*"
159
 
    dialogOptions = dict()
160
 
    dialogOptions['message'] = 'Add subtitles..'
161
 
    dialogOptions['wildcard'] = wildcard
162
 
    dialog = wx.FileDialog(self, **dialogOptions)
163
 
    if dialog.ShowModal() == wx.ID_OK:
164
 
      filename = dialog.GetFilename()
165
 
      dirname = dialog.GetDirectory()
166
 
      self.selectSubtitlesFile(os.path.join(dirname, filename))
167
 
    else:
168
 
      filename=None
169
 
    dialog.Destroy()
170
 
    return filename
171
 
 
172
 
  def selectSubtitlesFile(self, subtitlesFile):
173
 
      self.subtitlesFile = subtitlesFile
174
 
      lValue = subtitlesFile
175
 
      lLength = 45
176
 
      if len(lValue) > lLength:
177
 
        lValue = "..." + lValue[-lLength:]
178
 
      self.btnSubtitlesFile.SetLabel(lValue)
179
 
      self.btnOK.Enable()
180
 
 
181
 
  def BuildLanguagesList(self):
182
 
    # start with a known basic set
183
 
    languages = ['en', 'ja', 'de', 'fr', 'it', 'es', 'cy', 'ar', 'cn', 'pt', 'ru']
184
 
    # add in whatever's known from 'locale -a' - this works fine if locale isn't found,
185
 
    # but i'm not sure what that'll do if we get another program named locale that spews
186
 
    # random stuff to stdout :)
187
 
    p = subprocess.Popen(['locale', '-a'], shell=False, stdout=subprocess.PIPE, close_fds=True)
188
 
    data, err = p.communicate()
189
 
 
190
 
    for line in data.strip().split('\n'):
191
 
      line = self.ExtractLanguage(line)
192
 
      if line != '' and line != 'C' and line != 'POSIX' and line not in languages:
193
 
        languages.append(line)
194
 
    languages.sort()
195
 
    return languages
196
 
 
197
 
  def ExtractLanguage(self, line):
198
 
    line = line.split('.')[0] # stop at a dot
199
 
    line = line.split(' ')[0] # stop at a space
200
 
    line = line.split('@')[0] # stop at a @
201
 
    line = line.split('\t')[0] # stop at a tab
202
 
    line = line.split('\n')[0] # stop at a newline
203
 
    line = line.split('\r')[0] # Mac or Windows
204
 
    return line
205
 
 
206
 
  def BuildEncodingsList(self, hasIconv):
207
 
    # start with a known basic set, that ffmpeg2theora can handle without iconv
208
 
    encodings = ['UTF-8', 'ISO-8859-1']
209
 
 
210
 
    # this creates a *huge* spammy list with my version of iconv...
211
 
    if hasIconv:
212
 
      # add in whatever iconv knows about
213
 
      p = subprocess.Popen(['iconv', '-l'], shell=False, stdout=subprocess.PIPE, close_fds=True)
214
 
      data, stderr = p.communicate()
215
 
      for line in data.strip().split('\n'):
216
 
        line = line.split('/')[0] # stop at a /
217
 
        if not line in encodings:
218
 
          encodings.append(line)
219
 
    return encodings
220
 
 
221
 
def addSubtitlesPropertiesDialog(parent, language, category, encoding, file, hasIconv):
222
 
  dlg = SubtitlesProperties(parent, -1, "Add subtitles", language, category, encoding, file, hasIconv, size=(490, 560), style=wx.DEFAULT_DIALOG_STYLE)
223
 
  dlg.CenterOnScreen()
224
 
  val = dlg.ShowModal()
225
 
  result = dict()
226
 
  if val == wx.ID_OK:
227
 
    result['ok'] = True
228
 
    result['subtitlesFile'] = dlg.subtitlesFile
229
 
#    if use_langlistctrl:
230
 
#      result['subtitlesLanguage'] = GetWxIdentifierForLanguage(dlg.languageWidget.GetLanguage())
231
 
#    else:
232
 
#      result['subtitlesLanguage'] = dlg.languageWidget.GetValue()
233
 
    result['subtitlesLanguage'] = dlg.languageWidget.GetValue()
234
 
    result['subtitlesCategory'] = dlg.categoryWidget.GetValue()
235
 
    if hasIconv:
236
 
      result['subtitlesEncoding'] = dlg.encodingWidget.GetValue()
237
 
    else:
238
 
      result['subtitlesEncoding'] = dlg.encodingWidget.GetStringSelection()
239
 
    print result
240
 
  else:
241
 
    result['ok'] = False
242
 
  dlg.Destroy()
243
 
  return result
244
 
 
245
 
 
246
 
class SubtitlesList(wx.ListCtrl, ListCtrlAutoWidthMixin):
247
 
  def __init__(self, parent):
248
 
    wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT)
249
 
    ListCtrlAutoWidthMixin.__init__(self)
250
 
 
251
 
    self.ClearAll()
252
 
    self.InsertColumn(0, "Language")
253
 
    self.InsertColumn(1, "Category")
254
 
    self.InsertColumn(2, "Encoding")
255
 
    self.InsertColumn(3, "Name")
256
 
    self.SetColumnWidth(0, 80)
257
 
    self.SetColumnWidth(1, 80)
258
 
    self.SetColumnWidth(2, 80)
259
 
    self.SetColumnWidth(3, 80)
260
 
 
261
 
  def ResizeFilenameColumn(self):
262
 
    if self.GetItemCount() > 0:
263
 
      self.resizeLastColumn(1024)
264
 
    else:
265
 
      self.resizeLastColumn(0)
266