def get_id3info(url): ''' Function fetches data about mp3 files over HTTP. @param url: mp3 file address. @return bitrate, title, artist, id3tags_file ''' if not is_ServerSupportHTTPRange(url): log.warning("Server does not support HTTPRANGE! [%s]" % url) return [0, "", "", ""] url = url.replace(' ', '%20') # may not be needed req = urllib2.Request(url, headers=config.generic_http_headers) urlObj = urllib2.urlopen(req, timeout=config.get_id3info_timeout) tmpfile = utils.get_rand_filename(config.temp_dir) stringIO = StringIO() while True: stringIO.write(urlObj.read(8192)) with open(tmpfile, 'wb') as f: f.write(stringIO.getvalue()) try: audio = MP3(tmpfile) break except EOFError: # We still didn't fetch all the ID3 data. pass # log.debug("metadata is not in this %d KB chunk or not supported." % len(stringIO.getvalue())) except mutagen.mp3.HeaderNotFoundError: log.debug("HeaderNotFoundError: can't sync to an MPEG frame") stringIO.close() return [0, "", "", ""] stringIO.close() try: audioID3 = EasyID3(tmpfile) except mutagen.id3.ID3NoHeaderError: log.debug("no ID3data found (mutagen.id3.ID3NoHeaderError).") return [audio.info.bitrate, "", "", ""] except mutagen.id3.ID3BadUnsynchData: log.debug("Bad ID3 Unsynch Data (mutagen.id3.ID3BadUnsynchData)") return [audio.info.bitrate, "", "", ""] title = utils.fix_faulty_unicode( audioID3.get('title')[0]) if audioID3.get('title') else "" artist = utils.fix_faulty_unicode( audioID3.get('artist')[0]) if audioID3.get('artist') else "" return [audio.info.bitrate, title, artist, tmpfile]
def get_id3info(url): ''' Function fetches data about mp3 files over HTTP. @param url: mp3 file address. @return bitrate, title, artist, id3tags_file ''' if not is_ServerSupportHTTPRange(url): log.warning("Server does not support HTTPRANGE! [%s]" % url) return [0, "", "", ""] url = url.replace(' ', '%20') # may not be needed req = urllib2.Request(url, headers=config.generic_http_headers) urlObj = urllib2.urlopen(req, timeout=config.get_id3info_timeout) tmpfile = utils.get_rand_filename(config.temp_dir) stringIO = StringIO() while True: stringIO.write(urlObj.read(8192)) with open(tmpfile, 'wb') as f: f.write(stringIO.getvalue()) try: audio = MP3(tmpfile) break except EOFError: # We still didn't fetch all the ID3 data. pass # log.debug("metadata is not in this %d KB chunk or not supported." % len(stringIO.getvalue())) except mutagen.mp3.HeaderNotFoundError: log.debug("HeaderNotFoundError: can't sync to an MPEG frame") stringIO.close() return [0, "", "", ""] stringIO.close() try: audioID3 = EasyID3(tmpfile) except mutagen.id3.ID3NoHeaderError: log.debug("no ID3data found (mutagen.id3.ID3NoHeaderError).") return [audio.info.bitrate, "", "", ""] except mutagen.id3.ID3BadUnsynchData: log.debug("Bad ID3 Unsynch Data (mutagen.id3.ID3BadUnsynchData)") return [audio.info.bitrate, "", "", ""] title = utils.fix_faulty_unicode(audioID3.get('title')[0]) if audioID3.get('title') else "" artist = utils.fix_faulty_unicode(audioID3.get('artist')[0]) if audioID3.get('artist') else "" return [audio.info.bitrate, title, artist, tmpfile]
def init_widgets(self): self.title = QtGui.QLineEdit( utils.fix_faulty_unicode(self.easyID3Obj['title'][0]) ) if 'title' in self.easyID3Obj.keys() else QtGui.QLineEdit("") self.artist = QtGui.QLineEdit( utils.fix_faulty_unicode(self.easyID3Obj['artist'][0]) ) if 'artist' in self.easyID3Obj.keys() else QtGui.QLineEdit("") self.album = QtGui.QLineEdit( utils.fix_faulty_unicode(self.easyID3Obj['album'][0]) ) if 'album' in self.easyID3Obj.keys() else QtGui.QLineEdit("") self.date = QtGui.QLineEdit( self.easyID3Obj['date'] [0]) if 'date' in self.easyID3Obj.keys() else QtGui.QLineEdit("") self.original_title = unicode(self.title.displayText()) self.original_artist = unicode(self.artist.displayText()) self.original_album = unicode(self.album.displayText()) self.original_date = unicode(self.date.displayText()) pixmap = QtGui.QPixmap( self.pix_path) if self.pix_path else QtGui.QPixmap( self.empty_cdbox_path) if self.pix_path: fs = os.path.getsize(self.pix_path) s = tr("(%sx%s, %sKB)") % (pixmap.width(), pixmap.height(), fs / 1024) if fs > 250 * 1024: # 250KB s = '<b>%s</b>' % s if fs > 500 * 1024: # 250KB s = '<font color="green">%s</font>' % s self.albumArtData = QtGui.QLabel(s) else: self.albumArtData = QtGui.QLabel('') if max(pixmap.width(), pixmap.height()) > 200: pixmap = pixmap.scaled( 200, 200, aspectRatioMode=QtCore.Qt.KeepAspectRatio, transformMode=QtCore.Qt.SmoothTransformation) self.albumArtLayout = QtGui.QVBoxLayout() self.albumArt = QtGui.QLabel() self.albumArt.setPixmap(pixmap) self.albumArt.setStyleSheet( "border-style:solid; border-color:#999792; border-width:1px;") self.albumArtLayout.addWidget(self.albumArt, alignment=QtCore.Qt.AlignCenter) self.albumArtLayout.addWidget(self.albumArtData, alignment=QtCore.Qt.AlignCenter) self.remove_albumart_button = QtGui.QPushButton( QtGui.QIcon(r'pics\cancel.png'), "") self.remove_albumart_button.clicked.connect(self.remove_albumart_slot) self.remove_albumart_button.setFlat(True) if not self.pix_path: self.remove_albumart_button.setEnabled(False) # Row Layouts buttonLayout = QtGui.QHBoxLayout() applyButton = QtGui.QPushButton(tr("Apply")) applyButton.clicked.connect(self.slot_apply) closeButton = QtGui.QPushButton(tr("Dismiss")) closeButton.clicked.connect(self.close) buttonLayout.addWidget(applyButton) buttonLayout.addWidget(closeButton) self.changeImageButton = QtGui.QPushButton(tr("Fetch From The Web")) self.changeImageButton.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.changeImageButton.clicked.connect(self.slot_changeImage) self.loadLocalImageButton = QtGui.QPushButton( tr("Choose Image Locally")) self.loadLocalImageButton.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.loadLocalImageButton.clicked.connect(self.slot_loadLocalImage) self.loadFreeDBButton = QtGui.QPushButton(tr("Load From MusicBrainz")) self.loadFreeDBButton.clicked.connect(self.slot_loadFreeDBButton) self.restoreOriginalButton = QtGui.QPushButton(tr("Restore Original")) self.restoreOriginalButton.clicked.connect(self.slot_restoreOriginal) # Layouts mainLayout = QtGui.QVBoxLayout() formLayout = QtGui.QHBoxLayout() ### RIGHT ### rightLayout = QtGui.QVBoxLayout() basicTagsGroup = QtGui.QGroupBox(tr("ID3 Tags")) layout = QtGui.QFormLayout() layout.addRow(tr("Title:"), self.title) layout.addRow(tr("Artist:"), self.artist) layout.addRow(tr("Album:"), self.album) layout.addRow(tr("Date:"), self.date) buttons = QtGui.QHBoxLayout() buttons.addWidget(self.loadFreeDBButton) buttons.addWidget(self.restoreOriginalButton) layout.addRow(buttons) basicTagsGroup.setLayout(layout) albumArtGroup = QtGui.QGroupBox(tr("Album Art")) layout = QtGui.QGridLayout() layout.addLayout(self.albumArtLayout, 0, 0, 1, 3, QtCore.Qt.AlignCenter) layout.addWidget(self.changeImageButton, 1, 0) layout.addWidget(self.loadLocalImageButton, 1, 1) layout.addWidget(self.remove_albumart_button, 1, 2) albumArtGroup.setLayout(layout) rightLayout.addWidget(basicTagsGroup) rightLayout.addWidget(albumArtGroup) ### LEFT ### self.changeLyricsButton = QtGui.QPushButton( tr("Load Lyrics From The Web")) self.changeLyricsButton.clicked.connect(self.slot_changeLyrics) self.changeLyricsButton.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.deleteLyricsButton = QtGui.QPushButton( QtGui.QIcon(r'pics\cancel.png'), "") self.deleteLyricsButton.setFlat(True) self.deleteLyricsButton.clicked.connect(self.slot_deleteLyrics) self.lyrics_left_button = QtGui.QPushButton("<<") self.lyrics_left_button.setEnabled(False) self.lyrics_left_button.clicked.connect(self.slot_lyrics_left_button) self.lyrics_right_button = QtGui.QPushButton(">>") self.lyrics_right_button.setEnabled(False) self.lyrics_right_button.clicked.connect(self.slot_lyrics_right_button) self.changeLyricsLabel = QtGui.QLabel( tr("* Loaded from file's tags *" )) if self.originalLyrics else QtGui.QLabel("") self.changeLyricsLabel.setFrameStyle(QtGui.QFrame.Panel | QtGui.QFrame.Sunken) self.changeLyricsLabel.setWordWrap(True) self.lyrics = QtGui.QPlainTextEdit(self.originalLyrics) leftLayout = QtGui.QGroupBox(tr("Lyrics")) self.lyricsGroupBox = leftLayout # For manipulating the title name layout = QtGui.QVBoxLayout() layout.addWidget(self.lyrics) inner_layout = QtGui.QHBoxLayout() inner_layout.addWidget(self.lyrics_left_button) inner_layout.addWidget(self.changeLyricsLabel) inner_layout.addWidget(self.lyrics_right_button) layout.addLayout(inner_layout) inner_layout = QtGui.QHBoxLayout() inner_layout.addWidget(self.changeLyricsButton) inner_layout.addWidget(self.deleteLyricsButton, alignment=QtCore.Qt.AlignRight) layout.addLayout(inner_layout) leftLayout.setLayout(layout) ### Exit Counter Layout ### exitCounterLayout = QtGui.QHBoxLayout() self.exitCounterLabel = QtGui.QLabel( tr("<h1>Closing window in %d seconds...</h1>") % (config.id3_noask_wait_interval + 1)) self.exitCounterButton = QtGui.QPushButton(tr("Don't close")) self.exitCounterButton.clicked.connect(self.slot_close_cancel) exitCounterLayout.addWidget(self.exitCounterLabel) exitCounterLayout.addWidget(self.exitCounterButton) ### OTHERS ### formLayout.addLayout(rightLayout) formLayout.addWidget(leftLayout) mainLayout.addLayout(formLayout) if self.id3_action == 'noask': mainLayout.addLayout(exitCounterLayout) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout)
def init_widgets(self): self.title = QtGui.QLineEdit(utils.fix_faulty_unicode(self.easyID3Obj['title'][0])) if 'title' in self.easyID3Obj.keys() else QtGui.QLineEdit("") self.artist = QtGui.QLineEdit(utils.fix_faulty_unicode(self.easyID3Obj['artist'][0])) if 'artist' in self.easyID3Obj.keys() else QtGui.QLineEdit("") self.album = QtGui.QLineEdit(utils.fix_faulty_unicode(self.easyID3Obj['album'][0])) if 'album' in self.easyID3Obj.keys() else QtGui.QLineEdit("") self.date = QtGui.QLineEdit(self.easyID3Obj['date'][0]) if 'date' in self.easyID3Obj.keys() else QtGui.QLineEdit("") self.original_title = unicode(self.title.displayText()) self.original_artist = unicode(self.artist.displayText()) self.original_album = unicode(self.album.displayText()) self.original_date = unicode(self.date.displayText()) pixmap = QtGui.QPixmap(self.pix_path) if self.pix_path else QtGui.QPixmap(self.empty_cdbox_path) if self.pix_path: fs = os.path.getsize(self.pix_path) s = tr("(%sx%s, %sKB)") % (pixmap.width(), pixmap.height(), fs/1024) if fs > 250*1024: # 250KB s = '<b>%s</b>' % s if fs > 500*1024: # 250KB s = '<font color="green">%s</font>' % s self.albumArtData = QtGui.QLabel(s) else: self.albumArtData = QtGui.QLabel('') if max(pixmap.width(), pixmap.height()) > 200: pixmap = pixmap.scaled(200, 200, aspectRatioMode=QtCore.Qt.KeepAspectRatio, transformMode=QtCore.Qt.SmoothTransformation) self.albumArtLayout = QtGui.QVBoxLayout() self.albumArt = QtGui.QLabel() self.albumArt.setPixmap(pixmap) self.albumArt.setStyleSheet("border-style:solid; border-color:#999792; border-width:1px;") self.albumArtLayout.addWidget(self.albumArt, alignment=QtCore.Qt.AlignCenter) self.albumArtLayout.addWidget(self.albumArtData, alignment=QtCore.Qt.AlignCenter) self.remove_albumart_button = QtGui.QPushButton(QtGui.QIcon(r'pics\cancel.png'), "") self.remove_albumart_button.clicked.connect(self.remove_albumart_slot) self.remove_albumart_button.setFlat(True) if not self.pix_path: self.remove_albumart_button.setEnabled(False) # Row Layouts buttonLayout = QtGui.QHBoxLayout() applyButton = QtGui.QPushButton(tr("Apply")) applyButton.clicked.connect(self.slot_apply) closeButton = QtGui.QPushButton(tr("Dismiss")) closeButton.clicked.connect(self.close) buttonLayout.addWidget(applyButton) buttonLayout.addWidget(closeButton) self.changeImageButton = QtGui.QPushButton(tr("Fetch From The Web")) self.changeImageButton.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.changeImageButton.clicked.connect(self.slot_changeImage) self.loadLocalImageButton = QtGui.QPushButton(tr("Choose Image Locally")) self.loadLocalImageButton.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.loadLocalImageButton.clicked.connect(self.slot_loadLocalImage) self.loadFreeDBButton = QtGui.QPushButton(tr("Load From MusicBrainz")) self.loadFreeDBButton.clicked.connect(self.slot_loadFreeDBButton) self.restoreOriginalButton = QtGui.QPushButton(tr("Restore Original")) self.restoreOriginalButton.clicked.connect(self.slot_restoreOriginal) # Layouts mainLayout = QtGui.QVBoxLayout() formLayout = QtGui.QHBoxLayout() ### RIGHT ### rightLayout = QtGui.QVBoxLayout() basicTagsGroup = QtGui.QGroupBox(tr("ID3 Tags")) layout = QtGui.QFormLayout() layout.addRow(tr("Title:"), self.title) layout.addRow(tr("Artist:"), self.artist) layout.addRow(tr("Album:"), self.album) layout.addRow(tr("Date:"), self.date) buttons = QtGui.QHBoxLayout() buttons.addWidget(self.loadFreeDBButton) buttons.addWidget(self.restoreOriginalButton) layout.addRow(buttons) basicTagsGroup.setLayout(layout) albumArtGroup = QtGui.QGroupBox(tr("Album Art")) layout = QtGui.QGridLayout() layout.addLayout(self.albumArtLayout, 0, 0, 1, 3, QtCore.Qt.AlignCenter) layout.addWidget(self.changeImageButton, 1, 0) layout.addWidget(self.loadLocalImageButton, 1, 1) layout.addWidget(self.remove_albumart_button, 1, 2) albumArtGroup.setLayout(layout) rightLayout.addWidget(basicTagsGroup) rightLayout.addWidget(albumArtGroup) ### LEFT ### self.changeLyricsButton = QtGui.QPushButton(tr("Load Lyrics From The Web")) self.changeLyricsButton.clicked.connect(self.slot_changeLyrics) self.changeLyricsButton.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.deleteLyricsButton = QtGui.QPushButton(QtGui.QIcon(r'pics\cancel.png'), "") self.deleteLyricsButton.setFlat(True) self.deleteLyricsButton.clicked.connect(self.slot_deleteLyrics) self.lyrics_left_button = QtGui.QPushButton("<<") self.lyrics_left_button.setEnabled(False) self.lyrics_left_button.clicked.connect(self.slot_lyrics_left_button) self.lyrics_right_button = QtGui.QPushButton(">>") self.lyrics_right_button.setEnabled(False) self.lyrics_right_button.clicked.connect(self.slot_lyrics_right_button) self.changeLyricsLabel = QtGui.QLabel(tr("* Loaded from file's tags *")) if self.originalLyrics else QtGui.QLabel("") self.changeLyricsLabel.setFrameStyle(QtGui.QFrame.Panel | QtGui.QFrame.Sunken) self.changeLyricsLabel.setWordWrap(True) self.lyrics = QtGui.QPlainTextEdit(self.originalLyrics) leftLayout = QtGui.QGroupBox(tr("Lyrics")) self.lyricsGroupBox = leftLayout # For manipulating the title name layout = QtGui.QVBoxLayout() layout.addWidget(self.lyrics) inner_layout = QtGui.QHBoxLayout() inner_layout.addWidget(self.lyrics_left_button) inner_layout.addWidget(self.changeLyricsLabel) inner_layout.addWidget(self.lyrics_right_button) layout.addLayout(inner_layout) inner_layout = QtGui.QHBoxLayout() inner_layout.addWidget(self.changeLyricsButton) inner_layout.addWidget(self.deleteLyricsButton, alignment=QtCore.Qt.AlignRight) layout.addLayout(inner_layout) leftLayout.setLayout(layout) ### Exit Counter Layout ### exitCounterLayout = QtGui.QHBoxLayout() self.exitCounterLabel = QtGui.QLabel(tr("<h1>Closing window in %d seconds...</h1>") % (config.id3_noask_wait_interval+1)) self.exitCounterButton = QtGui.QPushButton(tr("Don't close")) self.exitCounterButton.clicked.connect(self.slot_close_cancel) exitCounterLayout.addWidget(self.exitCounterLabel) exitCounterLayout.addWidget(self.exitCounterButton) ### OTHERS ### formLayout.addLayout(rightLayout) formLayout.addWidget(leftLayout) mainLayout.addLayout(formLayout) if self.id3_action == 'noask': mainLayout.addLayout(exitCounterLayout) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout)