~ubuntu-branches/ubuntu/raring/soundconverter/raring-201211220242

« back to all changes in this revision

Viewing changes to src/soundconverter.py

  • Committer: Bazaar Package Importer
  • Author(s): William Grant
  • Date: 2008-01-10 18:55:34 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20080110185534-wg4bzthe3vuiwyx2
Tags: 0.9.8-0ubuntu1
* New upstream release. (LP: #181611)
* debian/control:
  - Depend on gstreamer0.10-plugins-base. (LP: #154617)
  - Don't Suggest gstreamer0.10-lame. It's not in an official
    repository.
  - Bump Standards-Version to 3.7.3.
  - Migrate to official Homepage field. 
* debian/patches/fix-desktop-file.patch: Drop Encoding and duplicate Name
  fields from soundconverter.desktop.

Show diffs side-by-side

added added

removed removed

Lines of Context:
93
93
Kamil Páral <ripper42 gmail.com > (Czech)
94
94
Stefano Luciani <luciani.fa tiscali.it > (Italian)
95
95
Martin Seifert <martinseifert fastmail.fm> (German)
 
96
Nizar Kerkeni <nizar.kerkeni gmail.com>(Arabic)
 
97
amenudo (Basque)
 
98
rainofchaos (Simplified Chinese)
 
99
Pavol Klačanský (Slovak)
 
100
Moshe Basanchig <moshe.basanchig gmail.com> (Hebrew)
96
101
""")
97
102
 
98
103
# Names of columns in the file list
112
117
        "application/x-shockwave-flash",
113
118
)
114
119
 
 
120
# custom filename patterns
 
121
english_patterns = "Artist Album Title Track Total Genre Date Year"
 
122
 
 
123
# traductors: only if it does make sense.
 
124
locale_patterns = _("Artist Album Title Track Total Genre Date Year")
 
125
 
 
126
patterns_formats = (
 
127
        "%(artist)s",
 
128
        "%(album)s",
 
129
        "%(title)s",
 
130
        "%(track-number)02d",
 
131
        "%(track-count)02d",
 
132
        "%(genre)s",
 
133
        "%(date)s",
 
134
        "%(year)s",
 
135
)
 
136
 
 
137
# add english and locale
 
138
custom_patterns = english_patterns + " " + locale_patterns
 
139
# convert to list
 
140
custom_patterns = [ "{%s}" % p for p in custom_patterns.split()]
 
141
# and finally to dict, thus removing doubles 
 
142
custom_patterns = dict(zip(custom_patterns, patterns_formats*2))
 
143
 
 
144
locale_patterns_dict = dict(zip(
 
145
        [ p.lower() for p in english_patterns.split()],
 
146
        [ "{%s}" % p for p in locale_patterns.split()] ))
 
147
 
115
148
# add here the formats not containing tags 
116
149
# not to bother searching in them
117
150
tag_blacklist = (
132
165
)
133
166
 
134
167
def beautify_uri(uri):
 
168
        uri = unquote_filename(uri)
135
169
        if uri.startswith("file://"):
136
170
                return uri[7:]
137
171
        return uri
146
180
        if str(uri)[-1] != '/':
147
181
                uri = uri.append_string("/")
148
182
 
149
 
        filelist = []   
 
183
        filelist = []  
150
184
 
151
185
        try:
152
186
                dirlist = gnomevfs.open_directory(uri)
186
220
                        pass
187
221
                except :
188
222
                        return False
189
 
        return True     
 
223
        return True  
190
224
 
191
225
def vfs_unlink(filename):
192
226
        gnomevfs.unlink(gnomevfs.URI(filename))
264
298
 
265
299
 
266
300
encoders = ( 
267
 
        ("flacenc",   "FLAC"), 
268
 
        ("wavenc",    "WAV"),
 
301
        ("flacenc",             "FLAC"), 
 
302
        ("wavenc",              "WAV"),
269
303
        ("vorbisenc", "Ogg Vorbis"),
270
 
        ("oggmux",    "Ogg Vorbis"),
271
 
        ("id3v2mux",  "MP3 Tags"),
272
 
        ("xingmux",   ""),
273
 
        ("lame",      "MP3"))
 
304
        ("oggmux",              "Ogg Vorbis"),
 
305
        ("id3v2mux",    "MP3 Tags"),
 
306
        ("xingmux",             ""),
 
307
        ("lame",                        "MP3"))
274
308
 
275
309
for encoder, name in encoders:
276
310
        have_it = True
347
381
        
348
382
                self.tags = {
349
383
                        "track-number": 0,
350
 
                        "title":  "Unknown Title",
 
384
                        "title":        "Unknown Title",
351
385
                        "artist": "Unknown Artist",
352
 
                        "album":  "Unknown Album",
 
386
                        "album":        "Unknown Album",
353
387
                }
354
388
                self.have_tags = False
355
389
                self.tags_read = False
356
 
                self.duration = 0       
 
390
                self.duration = 0  
357
391
                self.mime_type = None 
358
 
          
 
392
                
359
393
        def get_uri(self):
360
394
                return self.uri
361
395
                
404
438
                else:
405
439
                        self.exists = os.path.exists
406
440
 
407
 
        # This is useful for unit testing.                
 
441
        # This is useful for unit testing.                      
408
442
        def set_exists(self, exists):
409
443
                self.exists = exists
410
444
 
429
463
        
430
464
        def get_target_name(self, sound_file):
431
465
 
432
 
                #if "ssh" in sound_file.uri:
433
 
                #       import pdb; pdb.set_trace()
434
 
 
435
466
                u = gnomevfs.URI(sound_file.get_uri())
436
467
                root, ext = os.path.splitext(u.path)
437
468
                if u.host_port:
473
504
                        folder = root
474
505
                else:
475
506
                        folder = self.folder
476
 
                result = os.path.join(folder, urllib.quote(result))
 
507
                result = os.path.join(folder, urllib.quote(result.encode('utf-8')))
477
508
 
478
509
                return result
479
510
 
493
524
 
494
525
        def show_exception(self, exception):
495
526
                self.show("<b>%s</b>" % markup_escape(exception.primary),
496
 
                                  exception.secondary)
 
527
                                        exception.secondary)
497
528
 
498
529
 
499
530
class ErrorPrinter:
732
763
        
733
764
        def work(self):
734
765
                #if self.pipeline.get_state() == gst.STATE_NULL:
735
 
                #       log("error: pipeline.state == null")
 
766
                #  log("error: pipeline.state == null")
736
767
                        #return False
737
768
                #print "work:", self
738
769
                #time.sleep(0.01)
739
770
                if self.eos:
740
 
                        #print "  got eos:", self.sound_file.get_filename_for_display()
 
771
                        #print "        got eos:", self.sound_file.get_filename_for_display()
741
772
                        return False
742
773
                return True
743
774
 
775
806
                elif t == gst.MESSAGE_EOS:
776
807
                        self.eos = True
777
808
                elif t == gst.MESSAGE_TAG:
778
 
                        self.found_tag(self, "", message.parse_tag())   
 
809
                        self.found_tag(self, "", message.parse_tag())  
779
810
                return True
780
811
 
781
812
        def play(self):
899
930
        def get_duration(self):
900
931
                """ return the total duration of the sound file """
901
932
                #if not self.pipeline:
902
 
                #       return 0
 
933
                #  return 0
903
934
                self.query_duration()
904
935
                return self.sound_file.duration
905
936
        
923
954
 
924
955
 
925
956
        def found_tag(self, decoder, something, taglist):
926
 
                debug("found_tags:", self.sound_file.get_filename_for_display())
 
957
                #debug("found_tags:", self.sound_file.get_filename_for_display())
927
958
                #debug("\ttitle=%s" % (taglist["title"]))
928
 
                for k in taglist.keys():
 
959
                """for k in taglist.keys():
929
960
                        debug("\t%s=%s" % (k, taglist[k]))
930
961
                        if isinstance(taglist[k], gst.Date):
931
962
                                taglist["year"] = taglist[k].year
932
963
                                taglist["date"] = "%04d-%02d-%02d" % (taglist[k].year,
933
 
                                                                        taglist[k].month, taglist[k].day)
 
964
                                                                        taglist[k].month, taglist[k].day)"""
934
965
                        
935
966
                self.sound_file.add_tags(taglist)
936
967
 
988
1019
                self.delete_original = delete_original
989
1020
 
990
1021
        #def setup(self):
991
 
        #       self.init()
992
 
        #       self.play()
 
1022
        #  self.init()
 
1023
        #  self.play()
993
1024
 
994
1025
        def init(self):
995
1026
                #print "Converter.init()"
1145
1176
                        self.widget.append_column(column)
1146
1177
        
1147
1178
        def drag_data_received(self, widget, context, x, y, selection, 
1148
 
                                                   mime_id, time):
 
1179
                                                         mime_id, time):
1149
1180
 
1150
1181
                if mime_id >= 0 and mime_id < len(self.drop_mime_types):
1151
1182
                        file_list = []
1188
1219
                if not self.tagreaders.is_running():
1189
1220
                        self.tagreaders.run()
1190
1221
        
1191
 
        def add_uris(self, uris, base=None):
 
1222
        def add_uris(self, uris, base=None, filter=None):
1192
1223
 
1193
1224
                files = []
1194
1225
 
1202
1233
 
1203
1234
                        if info.type == gnomevfs.FILE_TYPE_DIRECTORY:
1204
1235
                                filelist = vfs_walk(gnomevfs.URI(uri))
 
1236
                                if filter:
 
1237
                                        filelist = [f for f in filelist if f.lower().endswith(filter)]
1205
1238
                                
1206
1239
                                for f in filelist:
1207
 
                                        #f = f[len(base)+1:]
1208
1240
                                        files.append(f)
1209
1241
                        else:
1210
1242
                                files.append(uri)
1217
1249
                        if sound_file.get_uri() in self.filelist:
1218
1250
                                log(_("file already present: '%s'") % sound_file.get_uri())
1219
1251
                                continue 
1220
 
                        #print "adding: '%s'" % sound_file.get_filename_for_display()
1221
1252
                        self.filelist[sound_file.get_uri()] = True
1222
1253
 
1223
1254
                        typefinder = TypeFinder(sound_file)
1233
1264
 
1234
1265
        def format_cell(self, sound_file):
1235
1266
                
1236
 
                template_tags    = "%(artist)s - <i>%(album)s</i> - <b>%(title)s</b>\n<small>%(filename)s</small>"
 
1267
                template_tags            = "%(artist)s - <i>%(album)s</i> - <b>%(title)s</b>\n<small>%(filename)s</small>"
1237
1268
                template_loading = "<i>%s</i>\n<small>%%(filename)s</small>" \
1238
1269
                                                        % _("loading tags...")
1239
1270
                template_notags  = '<span foreground="red">%s</span>\n<small>%%(filename)s</small>' \
1335
1366
        }
1336
1367
 
1337
1368
        sensitive_names = ["vorbis_quality", "choose_folder", "create_subfolders",
1338
 
                                           "subfolder_pattern"]
 
1369
                                                 "subfolder_pattern"]
1339
1370
 
1340
1371
        def __init__(self, glade):
1341
1372
                self.gconf = gconf.client_get_default()
1361
1392
                self.set_widget_initial_values(glade)
1362
1393
                self.set_sensitive()
1363
1394
 
 
1395
                tips = gtk.Tooltips()
 
1396
                tip = _("Available patterns:")
 
1397
                for k in locale_patterns_dict.values():
 
1398
                        tip += "\n" + k
 
1399
                tips.set_tip(self.custom_filename, tip)
 
1400
 
1364
1401
 
1365
1402
        def convert_setting_from_old_version(self):
1366
1403
                """ try to convert previous settings"""
1408
1445
 
1409
1446
                mime_type = self.get_string("output-mime-type")
1410
1447
 
1411
 
                widgets = {             "audio/x-vorbis": (have_vorbisenc, "output_mime_type_ogg_vorbis"),
1412
 
                                                "audio/x-flac"  : (have_flacenc, "output_mime_type_flac"),
1413
 
                                                "audio/x-wav"   : (have_wavenc, "output_mime_type_wav"),
1414
 
                                                "audio/mpeg"    : (have_lame, "output_mime_type_mp3"),
 
1448
                widgets = {              "audio/x-vorbis": (have_vorbisenc, "output_mime_type_ogg_vorbis"),
 
1449
                                                "audio/x-flac"  : (have_flacenc, "output_mime_type_flac"),
 
1450
                                                "audio/x-wav"           : (have_wavenc, "output_mime_type_wav"),
 
1451
                                                "audio/mpeg"            : (have_lame, "output_mime_type_mp3"),
1415
1452
                                        }
1416
1453
 
1417
1454
                # desactivate output if encoder plugin is not present
1509
1546
        def update_example(self):
1510
1547
                sound_file = SoundFile(os.path.expanduser("~/foo/bar.flac"))
1511
1548
                sound_file.add_tags({
1512
 
                        "date": "<b>{Date}</b>", 
1513
 
                        "year": "<b>{Year}</b>", 
1514
 
                        "genre": "<b>{Genre}</b>", 
1515
 
                        "artist": "<b>{Artist}</b>", 
1516
 
                        "title": "<b>{Title}</b>", 
1517
 
                        "album": "<b>{Album}</b>",
1518
1549
                        "track-number": 1L,
1519
1550
                        "track-count": 99L,
1520
1551
                })
1521
 
                self.example.set_markup(self.generate_filename(sound_file, for_display=True))
 
1552
                sound_file.add_tags(locale_patterns_dict)
 
1553
 
 
1554
                s = markup_escape(self.generate_filename(sound_file, for_display=True))
 
1555
                p = 0
 
1556
                replaces = []
 
1557
 
 
1558
                while 1:
 
1559
                        b = s.find('{', p)
 
1560
                        if b == -1:
 
1561
                                break
 
1562
                        e = s.find('}',b)
 
1563
                        
 
1564
                        tag = s[b:e+1]
 
1565
                        if tag.lower() in [v.lower() for v in locale_patterns_dict.values()]:
 
1566
                                k = tag
 
1567
                                l = k.replace("{","<b>{")
 
1568
                                l = l.replace("}","}</b>")
 
1569
                                replaces.append([k,l])
 
1570
                        else:
 
1571
                                k = tag
 
1572
                                l = k.replace("{","<span foreground=\"red\"><i>{")
 
1573
                                l = l.replace("}","}</i></span>")
 
1574
                                replaces.append([k,l])
 
1575
                        p = b+1
 
1576
                        
 
1577
                for k,l in replaces:
 
1578
                        s = s.replace(k, l)
 
1579
 
 
1580
                self.example.set_markup(s)
1522
1581
                
1523
1582
                markup = "<small>%s</small>" % (_("Target bitrate: %s") % 
1524
1583
                                        self.get_bitrate_from_settings())
1552
1611
                        return generator.get_target_name(sound_file)
1553
1612
        
1554
1613
        def process_custom_pattern(self, pattern):
1555
 
                patterns = {
1556
 
                        "{Artist}": "%(artist)s",
1557
 
                        "{Album}": "%(album)s",
1558
 
                        "{Title}": "%(title)s",
1559
 
                        "{Track}": "%(track-number)02d",
1560
 
                        "{Total}": "%(track-count)02d",
1561
 
                        "{Genre}": "%(genre)s",
1562
 
                        "{Date}": "%(date)s",
1563
 
                        "{Year}": "%(year)s",
1564
 
                }
1565
1614
                
1566
 
                for k in patterns:
1567
 
                        pattern = pattern.replace(k, patterns[k])
 
1615
                for k in custom_patterns:
 
1616
                        pattern = pattern.replace(k, custom_patterns[k])
1568
1617
                return pattern
1569
1618
 
1570
1619
        def set_sensitive(self):
1737
1786
                quality_to_preset = {
1738
1787
                        "cbr": {64:0, 96:1, 128:2, 192:3, 256:4},
1739
1788
                        "abr": {64:0, 96:1, 128:2, 192:3, 256:4},
1740
 
                        "vbr": {9:0,   7:1,       5:2,   3:3,   1:4}, # inverted !
 
1789
                        "vbr": {9:0,     7:1,            5:2,           3:3,    1:4}, # inverted !
1741
1790
                }
1742
1791
                        
1743
1792
                if quality in quality_to_preset[mode]:
1804
1853
                except gnomevfs.InvalidURIError:
1805
1854
                        log("Invalid URI: '%s'" % output_filename)
1806
1855
                        return
1807
 
                                
 
1856
                
 
1857
                # do not overwrite source file !!
 
1858
                if output_filename == sound_file.get_uri():
 
1859
                        error.show(_("Cannot overwrite source file(s)!"), "")
 
1860
                        raise ConverterQueueCanceled()
 
1861
                
1808
1862
                if exists:
1809
1863
                        if self.overwrite_action != None:
1810
1864
                                result = self.overwrite_action
1848
1902
                                raise ConverterQueueCanceled()
1849
1903
                        
1850
1904
                c = Converter(sound_file, output_filename, 
1851
 
                                          self.window.prefs.get_string("output-mime-type"),
1852
 
                                          self.window.prefs.get_int("delete-original"))
 
1905
                                                self.window.prefs.get_string("output-mime-type"),
 
1906
                                                self.window.prefs.get_int("delete-original"))
1853
1907
                c.set_vorbis_quality(self.window.prefs.get_float("vorbis-quality"))
1854
1908
                
1855
1909
                quality = {
1905
1959
                self.window.conversion_ended()
1906
1960
                total_time = self.run_finish_time - self.run_start_time
1907
1961
                self.window.set_status(_("Conversion done, in %s") % 
1908
 
                                                           self.format_time(total_time))
 
1962
                                                                 self.format_time(total_time))
1909
1963
 
1910
1964
        def format_time(self, seconds):
1911
1965
                units = [(86400, "d"),
2038
2092
                self.addfolderchooser.set_select_multiple(True)
2039
2093
                self.addfolderchooser.set_local_only(not use_gnomevfs)
2040
2094
 
 
2095
 
 
2096
                self.combo = gtk.ComboBox()
 
2097
                #self.combo.connect("changed",self.on_combo_changed)
 
2098
                self.store = gtk.ListStore(str)
 
2099
                self.combo.set_model(self.store)
 
2100
                combo_rend = gtk.CellRendererText()
 
2101
                self.combo.pack_start(combo_rend, True)
 
2102
                self.combo.add_attribute(combo_rend, 'text', 0)
 
2103
        
 
2104
                # get all (gstreamer) knew files Todo
 
2105
                for files in filepattern:
 
2106
                        self.store.append(["%s (%s)" %(files[0],files[1])])
 
2107
 
 
2108
                self.combo.set_active(0)
 
2109
                self.addfolderchooser.set_extra_widget(self.combo)
 
2110
 
2041
2111
                self.connect(glade, [self.prefs])
2042
2112
                
2043
2113
                self.about.set_property("name", NAME)
2087
2157
                if ret == gtk.RESPONSE_OK:
2088
2158
                        files = []
2089
2159
                        #for uri in self.addchooser.get_uris():
2090
 
                        #       files.append(SoundFile(uri))
 
2160
                        #  files.append(SoundFile(uri))
2091
2161
                        #self.filelist.add_files(files)
2092
2162
                        self.filelist.add_uris(self.addchooser.get_uris())
2093
2163
                self.set_sensitive()
2097
2167
                ret = self.addfolderchooser.run()
2098
2168
                self.addfolderchooser.hide()
2099
2169
                if ret == gtk.RESPONSE_OK:
 
2170
                        
2100
2171
                        folders = self.addfolderchooser.get_uris()
2101
2172
                        
2102
 
                        self.filelist.add_uris(folders)
 
2173
                        filter = None
 
2174
                        if self.combo.get_active():
 
2175
                                filter = os.path.splitext(filepattern[self.combo.get_active()] 
 
2176
                                                [1]) [1]
 
2177
 
 
2178
                        
 
2179
                        self.filelist.add_uris(folders, filter = filter)
2103
2180
 
2104
2181
                        #base,notused = os.path.split(os.path.commonprefix(folders))
2105
2182
                        #filelist = []
2106
2183
                        #files = []
2107
2184
                        #for folder in folders:
2108
 
                        #       filelist.extend(vfs_walk(gnomevfs.URI(folder)))
 
2185
                        #  filelist.extend(vfs_walk(gnomevfs.URI(folder)))
2109
2186
                        #for f in filelist:
2110
 
                        #       f = f[len(base)+1:]
2111
 
                        #       files.append(SoundFile(base+"/", f))
 
2187
                        #  f = f[len(base)+1:]
 
2188
                        #  files.append(SoundFile(base+"/", f))
2112
2189
                        #self.filelist.add_files(files)
2113
2190
                self.set_sensitive()
2114
2191
 
2126
2203
                                self.converter.add(sound_file)
2127
2204
                except ConverterQueueCanceled:
2128
2205
                        log(_("canceling conversion."))
 
2206
                        self.conversion_ended()
 
2207
                        self.set_status(_("Conversion canceled"))
2129
2208
                else:
2130
2209
                        self.set_status("")
2131
2210
                        self.converter.run()
2221
2300
                self.set_widget_sensitive("remove", 
2222
2301
                        self.filelist_selection.count_selected_rows() > 0)
2223
2302
                self.set_widget_sensitive("convert_button", 
2224
 
                                                                  self.filelist.is_nonempty())
 
2303
                                                                        self.filelist.is_nonempty())
2225
2304
 
2226
2305
                self._lock_convert_button = True
2227
2306
                self.sensitive_widgets["convert_button"].set_active(
2297
2376
                        keys = input_file.keys()
2298
2377
                        keys.sort()
2299
2378
                        for key in keys:
2300
 
                                print "  %s: %s" % (key, input_file[key])
 
2379
                                print "         %s: %s" % (key, input_file[key])
2301
2380
 
2302
2381
 
2303
2382
class CliProgress:
2384
2463
        for short_arg, long_arg, func, doc in options:
2385
2464
                print
2386
2465
                if short_arg[-1] == ":":
2387
 
                        print "  -%s arg, --%sarg" % (short_arg[:1], long_arg)
 
2466
                        print "         -%s arg, --%sarg" % (short_arg[:1], long_arg)
2388
2467
                else:
2389
 
                        print "  -%s, --%s" % (short_arg[:1], long_arg)
 
2468
                        print "         -%s, --%s" % (short_arg[:1], long_arg)
2390
2469
                for line in textwrap.wrap(doc):
2391
 
                        print "    %s" % line
 
2470
                        print "                 %s" % line
2392
2471
        sys.exit(0)
2393
2472
 
2394
2473