/* This file is part of the KDE project * Copyright (C) 2001, 2002 Rolf Magnus <ramagnus@kde.org> * Copyright (C) 2002 Ryan Cumming <bodnar42@phalynx.dhs.org> * Copyright (C) 2003 Scott Wheeler <wheeler@kde.org> * * 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 version 2. * * 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; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "config.h" #include "tdefile_mp3.h" #include <kprocess.h> #include <tdelocale.h> #include <kgenericfactory.h> #include <kstringvalidator.h> #include <kdebug.h> #include <tqdict.h> #include <tqvalidator.h> #include <tqcstring.h> #include <tqfile.h> #include <tqdatetime.h> #include <tstring.h> #include <tag.h> #include <mpegfile.h> #include <id3v1genres.h> #include <id3v2framefactory.h> typedef KGenericFactory<KMp3Plugin> Mp3Factory; K_EXPORT_COMPONENT_FACTORY(tdefile_mp3, Mp3Factory( "tdefile_mp3" )) KMp3Plugin::KMp3Plugin(TQObject *parent, const char *name, const TQStringList &args) : KFilePlugin(parent, name, args) { kdDebug(7034) << "mp3 plugin for mimetype " << name << endl; KFileMimeTypeInfo *info = addMimeTypeInfo(name); // id3 group KFileMimeTypeInfo::GroupInfo *group = addGroupInfo(info, "id3", i18n("ID3 Tag")); setAttributes(group, KFileMimeTypeInfo::Addable | KFileMimeTypeInfo::Removable); KFileMimeTypeInfo::ItemInfo *item; item = addItemInfo(group, "Title", i18n("Title"), TQVariant::String); setAttributes(item, KFileMimeTypeInfo::Modifiable); setHint(item, KFileMimeTypeInfo::Name); item = addItemInfo(group, "Artist", i18n("Artist"), TQVariant::String); setAttributes(item, KFileMimeTypeInfo::Modifiable); setHint(item, KFileMimeTypeInfo::Author); item = addItemInfo(group, "Album", i18n("Album"), TQVariant::String); setAttributes(item, KFileMimeTypeInfo::Modifiable); item = addItemInfo(group, "Date", i18n("Year"), TQVariant::String); setAttributes(item, KFileMimeTypeInfo::Modifiable); item = addItemInfo(group, "Comment", i18n("Comment"), TQVariant::String); setAttributes(item, KFileMimeTypeInfo::Modifiable); setHint(item, KFileMimeTypeInfo::Description); item = addItemInfo(group, "Tracknumber", i18n("Track"), TQVariant::Int); setAttributes(item, KFileMimeTypeInfo::Modifiable); item = addItemInfo(group, "Genre", i18n("Genre"), TQVariant::String); setAttributes(item, KFileMimeTypeInfo::Modifiable); // technical group group = addGroupInfo(info, "Technical", i18n("Technical Details")); item = addItemInfo(group, "Version", i18n("Version"), TQVariant::Int); setPrefix(item, i18n("MPEG ")); item = addItemInfo(group, "Layer", i18n("Layer"), TQVariant::Int); item = addItemInfo(group, "CRC", i18n("CRC"), TQVariant::Bool); item = addItemInfo(group, "Bitrate", i18n("Bitrate"), TQVariant::Int); setAttributes(item, KFileMimeTypeInfo::Averaged); setHint(item, KFileMimeTypeInfo::Bitrate); setSuffix(item, i18n(" kbps")); item = addItemInfo(group, "Sample Rate", i18n("Sample Rate"), TQVariant::Int); setSuffix(item, i18n("Hz")); item = addItemInfo(group, "Channels", i18n("Channels"), TQVariant::Int); item = addItemInfo(group, "Copyright", i18n("Copyright"), TQVariant::Bool); item = addItemInfo(group, "Original", i18n("Original"), TQVariant::Bool); item = addItemInfo(group, "Length", i18n("Length"), TQVariant::Int); setAttributes(item, KFileMimeTypeInfo::Cummulative); setUnit(item, KFileMimeTypeInfo::Seconds); item = addItemInfo(group, "Emphasis", i18n("Emphasis"), TQVariant::String); } bool KMp3Plugin::readInfo(KFileMetaInfo &info, uint what) { kdDebug(7034) << "mp3 plugin readInfo\n"; bool readId3 = false; bool readTech = false; typedef enum KFileMetaInfo::What What; if(what & (KFileMetaInfo::Fastest | KFileMetaInfo::DontCare | KFileMetaInfo::ContentInfo)) { readId3 = true; } if(what & (KFileMetaInfo::Fastest | KFileMetaInfo::DontCare | KFileMetaInfo::TechnicalInfo)) { readTech = true; } if(!readId3 && !readTech) return true; if ( info.path().isEmpty() ) // remote file return false; TagLib::MPEG::File file(TQFile::encodeName(info.path()).data(), readTech); if(!file.isOpen()) { kdDebug(7034) << "Couldn't open " << file.name() << endl; return false; } if(readId3) { KFileMetaInfoGroup id3group = appendGroup(info, "id3"); TQString date = file.tag()->year() > 0 ? TQString::number(file.tag()->year()) : TQString(); TQString track = file.tag()->track() > 0 ? TQString::number(file.tag()->track()) : TQString(); TQString title = TQString(TStringToQString(file.tag()->title())).stripWhiteSpace(); if (!title.isEmpty()) appendItem(id3group, "Title", title); TQString artist = TQString(TStringToQString(file.tag()->artist())).stripWhiteSpace(); if (!artist.isEmpty()) appendItem(id3group, "Artist", artist); TQString album = TQString(TStringToQString(file.tag()->album())).stripWhiteSpace(); if (!album.isEmpty()) appendItem(id3group, "Album", album); appendItem(id3group, "Date", date); TQString comment = TQString(TStringToQString(file.tag()->comment())).stripWhiteSpace(); if (!comment.isEmpty()) appendItem(id3group, "Comment", comment); appendItem(id3group, "Tracknumber", track); TQString genre = TQString(TStringToQString(file.tag()->genre())).stripWhiteSpace(); if (!genre.isEmpty()) appendItem(id3group, "Genre", genre); } if(readTech) { KFileMetaInfoGroup techgroup = appendGroup(info, "Technical"); TQString version; switch(file.audioProperties()->version()) { case TagLib::MPEG::Header::Version1: version = "1.0"; break; case TagLib::MPEG::Header::Version2: version = "2.0"; break; case TagLib::MPEG::Header::Version2_5: version = "2.5"; break; } // CRC and Emphasis aren't yet implemented in TagLib (not that I think anyone cares) appendItem(techgroup, "Version", version); appendItem(techgroup, "Layer", file.audioProperties()->layer()); // appendItem(techgroup, "CRC", file.audioProperties()->crc()); appendItem(techgroup, "Bitrate", file.audioProperties()->bitrate()); appendItem(techgroup, "Sample Rate", file.audioProperties()->sampleRate()); appendItem(techgroup, "Channels", file.audioProperties()->channels()); appendItem(techgroup, "Copyright", TQVariant(file.audioProperties()->isCopyrighted())); appendItem(techgroup, "Original", TQVariant(file.audioProperties()->isOriginal())); appendItem(techgroup, "Length", file.audioProperties()->length()); // appendItem(techgroup, "Emphasis", file.audioProperties()->empahsis()); } kdDebug(7034) << "reading finished\n"; return true; } /** * Do translation between KFileMetaInfo items and TagLib::String in a tidy way. */ class Translator { public: Translator(const KFileMetaInfo &info) : m_info(info) {} TagLib::String operator[](const char *key) const { return QStringToTString(m_info["id3"][key].value().toString()); } int toInt(const char *key) const { return m_info["id3"][key].value().toInt(); } private: const KFileMetaInfo &m_info; }; bool KMp3Plugin::writeInfo(const KFileMetaInfo &info) const { TagLib::ID3v2::FrameFactory::instance()->setDefaultTextEncoding(TagLib::String::UTF8); TagLib::MPEG::File file(TQFile::encodeName(info.path()).data(), false); if(!file.isOpen() || !TagLib::File::isWritable(file.name())) { kdDebug(7034) << "couldn't open " << info.path() << endl; return false; } Translator t(info); file.tag()->setTitle(t["Title"]); file.tag()->setArtist(t["Artist"]); file.tag()->setAlbum(t["Album"]); file.tag()->setYear(t.toInt("Date")); file.tag()->setComment(t["Comment"]); file.tag()->setTrack(t.toInt("Tracknumber")); file.tag()->setGenre(t["Genre"]); file.save(); return true; } /** * A validator that will suggest a list of strings, but allow for free form * strings as well. */ class ComboValidator : public KStringListValidator { public: ComboValidator(const TQStringList &list, bool rejecting, bool fixupEnabled, TQObject *parent, const char *name) : KStringListValidator(list, rejecting, fixupEnabled, parent, name) { } virtual TQValidator::State validate(TQString &, int &) const { return TQValidator::Acceptable; } }; TQValidator *KMp3Plugin::createValidator(const TQString & /* mimetype */, const TQString &group, const TQString &key, TQObject *parent, const char *name) const { kdDebug(7034) << "making a validator for " << group << "/" << key << endl; if(key == "Tracknumber" || key == "Date") { return new TQIntValidator(0, 9999, parent, name); } if(key == "Genre") { TQStringList l; TagLib::StringList genres = TagLib::ID3v1::genreList(); for(TagLib::StringList::ConstIterator it = genres.begin(); it != genres.end(); ++it) { l.append(TStringToQString((*it))); } return new ComboValidator(l, false, true, parent, name); } return 0; } #include "tdefile_mp3.moc"