Bonsoir
Je suis en train de me faire une petite bibliothèque musicale , mais j'ai eu des soucis via Exaile.
En voulant extraire la musique et la convertir par la même occasion, on peut tomber sur un petit pépin:
Les valeurs "
Très élevée, Élevée, Moyenne et Basse" pour déterminer la qualité de la conversion, ne sont pas reconnues par Exaile car elles sont en Français.
En le lançant depuis une console, on peut voir par exemple:
Traceback (most recent call last):
File "/usr/lib64/python2.5/threading.py", line 486, in __bootstrap_inner
self.run()
File "/usr/lib64/python2.5/threading.py", line 446, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib64/exaile/xl/cd_import.py", line 180, in do_import
self.import_track(song)
File "/usr/lib64/exaile/xl/common.py", line 191, in wrapper
return func(self,*__args,**__kw)
File "/usr/lib64/exaile/xl/cd_import.py", line 218, in import_track
self.pipeline = self.get_pipeline(song.track, song.io_loc)
File "/usr/lib64/exaile/xl/cd_import.py", line 127, in get_pipeline
encoder = 'vorbisenc quality=%0.1f ! oggmux' % (formatdict[format][quality],)
KeyError: 'Moyenne'
Donc le soucis se crée vers la fin, quand Exaile doit choisir la qualité.
J'ai bien sûr essayé avec toutes les autres options Très élevée, Elevée et basse = toujours le même pb.
Il faut donc modifier le fichier
/usr/lib64/exaile/xl/cd_import.py et remplacer:
- Medium, par
Moyenne.
- Low par
Basse.
(Les deux autres ne passent pas car les accents font pas bon ménage et je ne sais pas comment faire pour qu'ils soient acceptés.)
# Copyright (C) 2006 Adam Olsen
#
# 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
import pygtk
pygtk.require('2.0')
import gtk, gobject
import pygst
pygst.require('0.10')
import gst
from gettext import gettext as _
import string, os
import xlmisc, common, media, library
# some info for every import format (a bit ugly perhaps)
formatdict = {
"MP3": {
"Very High":192,
"High":160,
"Medium":128,
"Low":64,
"ext":"mp3",
"plugin":"lame"
},
"MP3 VBR": {
"Very High":192,
"High":160,
"Medium":128,
"Low":64,
"ext":"mp3",
"plugin":"lame"
},
"Ogg Vorbis": {
"Very High":0.8,
"High":0.6,
"Moyenne":0.4,
"Basse":0.2,
"ext":"ogg",
"plugin":"vorbisenc"
},
"FLAC": {
"Very High":8,
"High": 6,
"Moyenne": 4,
"Low": 2,
"ext":"flac",
"plugin":"flacenc"
}
}
def check_import_formats():
"""
Return a list of supported encoding formats for importing
"""
ret = []
for format, caps in formatdict.iteritems():
try:
x = gst.element_factory_find(caps["plugin"])
except gst.PluginNotFoundError:
continue
ret.append(format)
return ret
class CDImporter(object):
"""
Imports CDs
"""
def __init__(self, exaile):
"""
Initialize
"""
self.exaile = exaile
self.xml = exaile.xml
self.settings = exaile.settings
self.importing = False
self.gst_running = False
self.overwrite_answer = None
self.pipeline = None
def get_pipeline(self, tracknum, dest):
"""
Construct a gstreamer pipeline either from a list of presets
or from a string given by the user.
"""
if self.settings.get_boolean('import/use_custom', False):
mapping = dict(dest=dest)
import_custom = self.settings.get_string('import/custom', '')
template = string.Template(import_custom)
try:
cmd = template.substitute(mapping)
except KeyError, e:
xlmisc.log('Could not substitute $' + e)
return
return gst.parse_launch(cmd)
else:
format = self.settings.get_str('import/format')
quality = self.settings.get_str('import/quality')
vbr = self.settings.get_boolean('import/vbr', False)
if format == 'MP3':
encoder = 'lame bitrate=%d ! id3mux v1-tag=1' % (formatdict[format][quality],)
elif format == 'MP3 VBR':
encoder = 'lame vbr=4 vbr-mean-bitrate=%d ! id3mux v1-tag=1 v2-tag=1' % \
(formatdict[format][quality],)
elif format == 'Ogg Vorbis':
encoder = 'vorbisenc quality=%0.1f ! oggmux' % (formatdict[format][quality],)
elif format == 'FLAC':
encodern = 'flacenc quality=%d' % (formatdict[format][quality],)
else:
xlmisc.log("Unknown import format")
return None
source = "cdparanoiasrc track=%d" % (tracknum,)
sink = "filesink location=\"%s\"" % (dest,)
cmd = '%s ! audioconvert ! %s ! %s' % (source, encoder, sink)
try:
pipe = gst.parse_launch(cmd)
except Exception, e:
xlmisc.log("Could not construct gstreamer pipe:" + str(e))
return pipe
@common.threaded
def do_import(self, songs):
"""
Start importing the given songs
"""
if not self.exaile.settings.get_str('import/location', '') \
or not self.exaile.settings.get_str('import/naming', ''):
gobject.idle_add(common.error, self.exaile.window,
_('Please set the import settings'
' in the Preferences dialog before importing '
'anything.'))
return
import_xml = gtk.glade.XML('exaile.glade', 'ImportDialog', 'exaile')
dialog = import_xml.get_widget('ImportDialog')
dialog.set_transient_for(self.exaile.window)
dialog.show_all()
bar = import_xml.get_widget('import_progressbar')
label = import_xml.get_widget('import_status')
stop_button = import_xml.get_widget('import_stop_button')
stop_button.connect('clicked', lambda *e: self.stop_import())
self.importing = True
self.overwrite_answer = None
for i, song in enumerate(songs):
if not self.importing: break
# TRANSLATORS: CD import status
bar.set_text(_("Track %(current)d/%(total)d") % {
'current': i + 1,
'total': len(songs)
})
bar.set_fraction(float(i)/len(songs))
label.set_markup('<big>' + song.title + '</big>')
self.import_track(song)
while self.gst_running:
continue
dialog.destroy()
return
@common.synchronized
def import_track(self, song):
"""
Imports one track using a gstreamer pipeline
"""
song.loc = self.make_dest(song)
if not song.loc:
xlmisc.log('Could not construct destination filename for ' + str(song))
try:
if not os.path.exists(os.path.dirname(song.io_loc)):
os.makedirs(os.path.dirname(song.io_loc))
if os.path.exists(song.io_loc):
if self.overwrite_answer != "yes_all" \
and self.overwrite_answer != "no_all":
self.overwrite_answer = None
gobject.idle_add(ask_overwrite, self, self.exaile.window, song)
while not self.overwrite_answer:
pass
if self.overwrite_answer == "yes" \
or self.overwrite_answer == "yes_all":
pass
elif self.overwrite_answer == "no" \
or self.overwrite_answer == "no_all":
return
except os.error, e:
xlmisc.log('Could not create directory "' +
os.path.dirname(song.io_loc) + '": ' + e.args[1])
self.pipeline = self.get_pipeline(song.track, song.io_loc)
if not self.pipeline:
xlmisc.log('Could not construct gstreamer pipeline, check your settings!')
bus = self.pipeline.get_bus()
bus.add_signal_watch()
bus.connect('message::error', self.gst_error_cb)
bus.connect('message::eos', self.gst_eos_cb, song)
self.gst_running = True
self.pipeline.set_state(gst.STATE_PLAYING)
return
def tag_track(self, track):
"""
Use the track's metadata to tag the file
"""
media.write_tag(track)
return
def add_track(self, track):
"""
Add a track to the library
"""
dir = [os.path.dirname(track.io_loc)]
self.exaile.library_manager.update_library_add(dir)
return
def make_dest(self, song):
"""
Constructs the destination filename using the
metadata and preferences
"""
location = self.settings.get_str('import/location', '')
naming = self.settings.get_str('import/naming', '')
pref = self.settings.get_str('import/format', 'MP3')
if not pref or not location:
return ''
extension = formatdict[pref]['ext']
# TODO: this mapping should be more complete (e.g. cd number?)
mapping = dict(artist=song.artist, album=song.album, title=song.title,\
ext=extension, num=(song.track or ''), date=song.date)
template = string.Template(naming)
try:
ret = template.substitute(mapping)
except KeyError, e:
xlmisc.log('Could not substitute $' + e)
ret = os.path.join(location, ret)
return ret
def gst_error_cb(self, bus, msg, *args):
"""
If Gstreamer encounters an error, handle it here
(Right now all we do is print to the log and stop)
"""
error = None
debug = None
(error, debug) = msg.parse_error()
xlmisc.log('gstreamer error: ' + error.message)
self.stop_import()
return
def gst_eos_cb(self, bus, msg, track):
"""
Stop the pipeline when EOS is reached, tag the track and add to library
"""
self.pipeline.set_state(gst.STATE_NULL)
self.gst_running = False
self.tag_track(track)
self.add_track(track)
return
def stop_import(self):
"""
Stop importing when stop button is clicked
"""
self.pipeline.set_state(gst.STATE_NULL)
self.gst_running = False
self.importing = False
def ask_overwrite(importer, parent, path):
"""
Throws up a dialog asking whether the user wants to overwrite an
existing file, with yes/no/yes to all/no to all alternatives
"""
dialog = gtk.Dialog(_('Overwrite file'), parent,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(_('Yes to All'), gtk.RESPONSE_OK,
gtk.STOCK_YES, gtk.RESPONSE_YES,
gtk.STOCK_NO, gtk.RESPONSE_NO,
_('No to All'), gtk.RESPONSE_CLOSE))
image = gtk.image_new_from_stock(gtk.STOCK_DIALOG_QUESTION,
gtk.ICON_SIZE_DIALOG)
text = gtk.Label(_('The file %s already exists, do you want to '
'overwrite it?') % (path,))
text.set_line_wrap(True)
hb = gtk.HBox(spacing=8)
hb.pack_start(image)
hb.pack_start(text)
dialog.vbox.pack_start(hb)
dialog.vbox.show_all()
response = dialog.run()
if response == gtk.RESPONSE_YES:
importer.overwrite_answer = "yes"
elif response == gtk.RESPONSE_NO:
importer.overwrite_answer = "no"
elif response == gtk.RESPONSE_OK:
importer.overwrite_answer = "yes_all"
elif response == gtk.RESPONSE_CLOSE or \
response == gtk.RESPONSE_DELETE_EVENT:
importer.overwrite_answer = "no_all"
dialog.destroy()
return False
Ensuite, on redémarre Exaile, et c'est bon.
PS: Si cette solution ne convient pas car trop crade, dites le moi que je supprime le sujet 🙂
PS2: Et s vous avez une astuce pour les accents ça serait sympa 🙂
Merci