?? metabundle.cpp
字號:
// Max Howell <max.howell@methylblue.com>, (C) 2004// Alexandre Pereira de Oliveira <aleprj@gmail.com>, (C) 2005, 2006// Gábor Lehel <illissius@gmail.com>, (C) 2005, 2006// Shane King <kde@dontletsstart.com>, (C) 2006// Peter C. Ndikuwera <pndiku@gmail.com>, (C) 2006// License: GNU General Public License V2#define DEBUG_PREFIX "MetaBundle"#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include <time.h>#include <sys/time.h>#include <sys/types.h>#include <fcntl.h>#include "amarok.h"#include "amarokconfig.h"#include "debug.h"#include "collectiondb.h"#include "metabundlesaver.h"#include <kapplication.h>#include <kfilemetainfo.h>#include <kio/global.h>#include <kio/job.h>#include <kio/jobclasses.h>#include <kio/netaccess.h>#include <kmdcodec.h>#include <qdeepcopy.h>#include <qfile.h> //decodePath()#include <taglib/attachedpictureframe.h>#include <taglib/fileref.h>#include <taglib/id3v1genres.h> //used to load genre list#include <taglib/mpegfile.h>#include <taglib/tag.h>#include <taglib/tstring.h>#include <taglib/tlist.h>#include <taglib/apetag.h>#include <taglib/id3v2tag.h>#include <taglib/id3v1tag.h>#include <taglib/mpcfile.h>#include <taglib/mpegfile.h>#include <taglib/oggfile.h>#include <taglib/oggflacfile.h>#include <taglib/vorbisfile.h>#include <taglib/flacfile.h>#include <taglib/textidentificationframe.h>#include <taglib/uniquefileidentifierframe.h>#include <taglib/xiphcomment.h>#include <config.h>#ifdef HAVE_MP4V2#include "metadata/mp4/mp4file.h"#include "metadata/mp4/mp4tag.h"#else#include "metadata/m4a/mp4file.h"#include "metadata/m4a/mp4itunestag.h"#endif#include "lastfm.h"#include "metabundle.h"#include "podcastbundle.h"namespace Amarok { KURL detachedKURL( const KURL &url ) { KURL urlCopy; if (!url.isEmpty()) urlCopy = KURL(url.url()); return urlCopy; }}MetaBundle::EmbeddedImage::EmbeddedImage( const TagLib::ByteVector& data, const TagLib::String& description ) : m_description( TStringToQString( description ) ){ m_data.duplicate( data.data(), data.size() );}const QCString &MetaBundle::EmbeddedImage::hash() const{ if( m_hash.isEmpty() ) { m_hash = KMD5( m_data ).hexDigest(); } return m_hash;}bool MetaBundle::EmbeddedImage::save( const QDir& dir ) const{ QFile file( dir.filePath( hash() ) ); if( file.open( IO_WriteOnly | IO_Raw ) ) { const Q_LONG s = file.writeBlock( m_data.data(), m_data.size() ); if( s >= 0 && Q_ULONG( s ) == m_data.size() ) { debug() << "EmbeddedImage::save " << file.name() << endl; return true; } file.remove(); } debug() << "EmbeddedImage::save failed! " << file.name() << endl; return false;}/// These are untranslated and used for storing/retrieving XML playlistconst QString &MetaBundle::exactColumnName( int c ) //static{ // construct static qstrings to avoid constructing them all the time static QString columns[] = { "Filename", "Title", "Artist", "AlbumArtist", "Composer", "Year", "Album", "DiscNumber", "Track", "BPM", "Genre", "Comment", "Directory", "Type", "Length", "Bitrate", "SampleRate", "Score", "Rating", "PlayCount", "LastPlayed", "Mood", "Filesize" }; static QString error( "ERROR" ); if ( c >= 0 && c < NUM_COLUMNS ) return columns[c]; else return error;}const QString MetaBundle::prettyColumnName( int index ) //static{ switch( index ) { case Filename: return i18n( "Filename" ); case Title: return i18n( "Title" ); case Artist: return i18n( "Artist" ); case AlbumArtist:return i18n( "Album Artist"); case Composer: return i18n( "Composer" ); case Year: return i18n( "Year" ); case Album: return i18n( "Album" ); case DiscNumber: return i18n( "Disc Number" ); case Track: return i18n( "Track" ); case Bpm: return i18n( "BPM" ); case Genre: return i18n( "Genre" ); case Comment: return i18n( "Comment" ); case Directory: return i18n( "Directory" ); case Type: return i18n( "Type" ); case Length: return i18n( "Length" ); case Bitrate: return i18n( "Bitrate" ); case SampleRate: return i18n( "Sample Rate" ); case Score: return i18n( "Score" ); case Rating: return i18n( "Rating" ); case PlayCount: return i18n( "Play Count" ); case LastPlayed: return i18n( "Column name", "Last Played" ); case Mood: return i18n( "Mood" ); case Filesize: return i18n( "File Size" ); } return "This is a bug.";}int MetaBundle::columnIndex( const QString &name ){ for( int i = 0; i < NUM_COLUMNS; ++i ) if( exactColumnName( i ).lower() == name.lower() ) return i; return -1;}MetaBundle::MetaBundle() : m_uniqueId( QString::null ) , m_year( Undetermined ) , m_discNumber( Undetermined ) , m_track( Undetermined ) , m_bpm( Undetermined ) , m_bitrate( Undetermined ) , m_length( Undetermined ) , m_sampleRate( Undetermined ) , m_score( Undetermined ) , m_rating( Undetermined ) , m_playCount( Undetermined ) , m_lastPlay( abs( Undetermined ) ) , m_filesize( Undetermined ) , m_moodbar( 0 ) , m_type( other ) , m_exists( true ) , m_isValidMedia( true ) , m_isCompilation( false ) , m_notCompilation( false ) , m_safeToSave( false ) , m_waitingOnKIO( 0 ) , m_tempSavePath( QString::null ) , m_origRenamedSavePath( QString::null ) , m_tempSaveDigest( 0 ) , m_saveFileref( 0 ) , m_podcastBundle( 0 ) , m_lastFmBundle( 0 ) , m_isSearchDirty(true) , m_searchColumns( Undetermined ){ init();}MetaBundle::MetaBundle( const KURL &url, bool noCache, TagLib::AudioProperties::ReadStyle readStyle, EmbeddedImageList* images ) : m_url( url ) , m_uniqueId( QString::null ) , m_year( Undetermined ) , m_discNumber( Undetermined ) , m_track( Undetermined ) , m_bpm( Undetermined ) , m_bitrate( Undetermined ) , m_length( Undetermined ) , m_sampleRate( Undetermined ) , m_score( Undetermined ) , m_rating( Undetermined ) , m_playCount( Undetermined ) , m_lastPlay( abs( Undetermined ) ) , m_filesize( Undetermined ) , m_moodbar( 0 ) , m_type( other ) , m_exists( isFile() && QFile::exists( url.path() ) ) , m_isValidMedia( false ) , m_isCompilation( false ) , m_notCompilation( false ) , m_safeToSave( false ) , m_waitingOnKIO( 0 ) , m_tempSavePath( QString::null ) , m_origRenamedSavePath( QString::null ) , m_tempSaveDigest( 0 ) , m_saveFileref( 0 ) , m_podcastBundle( 0 ) , m_lastFmBundle( 0 ) , m_isSearchDirty(true) , m_searchColumns( Undetermined ){ if ( exists() ) { if ( !noCache ) m_isValidMedia = CollectionDB::instance()->bundleForUrl( this ); if ( !isValidMedia() || ( !m_podcastBundle && m_length <= 0 ) ) readTags( readStyle, images ); } else { // if it's a podcast we might get some info this way CollectionDB::instance()->bundleForUrl( this ); m_bitrate = m_length = m_sampleRate = Unavailable; }}//StreamProvider ctorMetaBundle::MetaBundle( const QString& title, const QString& streamUrl, const int bitrate, const QString& genre, const QString& streamName, const KURL& url ) : m_url ( url ) , m_genre ( genre ) , m_streamName( streamName ) , m_streamUrl ( streamUrl ) , m_uniqueId( QString::null ) , m_year( 0 ) , m_discNumber( 0 ) , m_track( 0 ) , m_bpm( Undetermined ) , m_bitrate( bitrate ) , m_length( Irrelevant ) , m_sampleRate( Unavailable ) , m_score( Undetermined ) , m_rating( Undetermined ) , m_playCount( Undetermined ) , m_lastPlay( abs( Undetermined ) ) , m_filesize( Undetermined ) , m_moodbar( 0 ) , m_type( other ) , m_exists( true ) , m_isValidMedia( false ) , m_isCompilation( false ) , m_notCompilation( false ) , m_safeToSave( false ) , m_waitingOnKIO( 0 ) , m_tempSavePath( QString::null ) , m_origRenamedSavePath( QString::null ) , m_tempSaveDigest( 0 ) , m_saveFileref( 0 ) , m_podcastBundle( 0 ) , m_lastFmBundle( 0 ) , m_isSearchDirty( true ) , m_searchColumns( Undetermined ){ if( title.contains( '-' ) ) { m_title = title.section( '-', 1, 1 ).stripWhiteSpace(); m_artist = title.section( '-', 0, 0 ).stripWhiteSpace(); } else { m_title = title; m_artist = streamName; //which is sort of correct.. }}MetaBundle::MetaBundle( const MetaBundle &bundle ) : m_moodbar( 0 ){ *this = bundle;}MetaBundle::~MetaBundle(){ delete m_podcastBundle; delete m_lastFmBundle; if( m_moodbar != 0 ) delete m_moodbar;}MetaBundle&MetaBundle::operator=( const MetaBundle& bundle ){ m_url = bundle.m_url; m_title = bundle.m_title; m_artist = bundle.m_artist; m_albumArtist = bundle.m_albumArtist; m_composer = bundle.m_composer; m_album = bundle.m_album; m_comment = bundle.m_comment; m_genre = bundle.m_genre; m_streamName = bundle.m_streamName; m_streamUrl = bundle.m_streamUrl; m_uniqueId = bundle.m_uniqueId; m_year = bundle.m_year; m_discNumber = bundle.m_discNumber; m_track = bundle.m_track; m_bpm = bundle.m_bpm; m_bitrate = bundle.m_bitrate; m_length = bundle.m_length; m_sampleRate = bundle.m_sampleRate; m_score = bundle.m_score; m_rating = bundle.m_rating; m_playCount = bundle.m_playCount; m_lastPlay = bundle.m_lastPlay; m_filesize = bundle.m_filesize; m_type = bundle.m_type; m_exists = bundle.m_exists; m_isValidMedia = bundle.m_isValidMedia; m_isCompilation = bundle.m_isCompilation; m_notCompilation = bundle.m_notCompilation; m_safeToSave = bundle.m_safeToSave; m_waitingOnKIO = bundle.m_waitingOnKIO; m_tempSavePath = bundle.m_tempSavePath; m_origRenamedSavePath = bundle.m_origRenamedSavePath; m_tempSaveDigest = bundle.m_tempSaveDigest; m_saveFileref = bundle.m_saveFileref; if( bundle.m_moodbar != 0) { if( m_moodbar == 0 ) m_moodbar = new Moodbar( this ); *m_moodbar = *bundle.m_moodbar; } else { // If m_moodbar != 0, it's initialized for a reason // Deleting it makes the PrettySlider code more ugly, // since it'd have to reconnect the jobEvent() signal. if( m_moodbar != 0 ) m_moodbar->reset(); }// delete m_podcastBundle; why does this crash Amarok? apparently m_podcastBundle isn't always initialized. m_podcastBundle = 0; if( bundle.m_podcastBundle ) setPodcastBundle( *bundle.m_podcastBundle );// delete m_lastFmBundle; same as above m_lastFmBundle = 0; if( bundle.m_lastFmBundle ) setLastFmBundle( *bundle.m_lastFmBundle ); m_isSearchDirty = true; return *this;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -