diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2008-10-25 20:58:48 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2008-10-25 20:58:48 +0000 |
| commit | bed87bc89a1258d3b3dc429f3df114c8c2655a6a (patch) | |
| tree | 358e8d37a910fd5b6cfbf5b32adaa8130da9a4a7 /src/plugins/Input/aac | |
| parent | f36b2f8d5c85c4c2a32a1dd884c57735f50e3b87 (diff) | |
| download | qmmp-bed87bc89a1258d3b3dc429f3df114c8c2655a6a.tar.gz qmmp-bed87bc89a1258d3b3dc429f3df114c8c2655a6a.tar.bz2 qmmp-bed87bc89a1258d3b3dc429f3df114c8c2655a6a.zip | |
aac plugin
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@601 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/plugins/Input/aac')
| -rw-r--r-- | src/plugins/Input/aac/aac.pro | 39 | ||||
| -rw-r--r-- | src/plugins/Input/aac/aacfile.cpp | 120 | ||||
| -rw-r--r-- | src/plugins/Input/aac/aacfile.h | 46 | ||||
| -rw-r--r-- | src/plugins/Input/aac/decoder_aac.cpp | 328 | ||||
| -rw-r--r-- | src/plugins/Input/aac/decoder_aac.h | 78 | ||||
| -rw-r--r-- | src/plugins/Input/aac/decoderaacfactory.cpp | 121 | ||||
| -rw-r--r-- | src/plugins/Input/aac/decoderaacfactory.h | 54 | ||||
| -rw-r--r-- | src/plugins/Input/aac/detailsdialog.cpp | 115 | ||||
| -rw-r--r-- | src/plugins/Input/aac/detailsdialog.h | 49 | ||||
| -rw-r--r-- | src/plugins/Input/aac/detailsdialog.ui | 347 |
10 files changed, 1297 insertions, 0 deletions
diff --git a/src/plugins/Input/aac/aac.pro b/src/plugins/Input/aac/aac.pro new file mode 100644 index 000000000..5bc0cb38a --- /dev/null +++ b/src/plugins/Input/aac/aac.pro @@ -0,0 +1,39 @@ +include(../../plugins.pri) + +FORMS += detailsdialog.ui +HEADERS += decoderaacfactory.h \ + decoder_aac.h \ + detailsdialog.h \ + aacfile.h +SOURCES += decoder_aac.cpp \ + decoderaacfactory.cpp \ + detailsdialog.cpp \ + aacfile.cpp + +TARGET =$$PLUGINS_PREFIX/Input/aac +QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libaac.so + + +INCLUDEPATH += ../../../ +CONFIG += release \ +warn_on \ +plugin \ +link_pkgconfig +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib +LIBS += -lqmmp -lfaad -L/usr/lib -I/usr/include +PKGCONFIG += taglib +#TRANSLATIONS = translations/mpc_plugin_ru.ts +# translations/mpc_plugin_uk_UA.ts +# translations/mpc_plugin_zh_CN.ts +# translations/mpc_plugin_zh_TW.ts +# translations/mpc_plugin_cs.ts +# translations/mpc_plugin_de.ts +#RESOURCES = translations/translations.qrc + +isEmpty(LIB_DIR){ + LIB_DIR = /lib +} + +target.path = $$LIB_DIR/qmmp/Input +INSTALLS += target diff --git a/src/plugins/Input/aac/aacfile.cpp b/src/plugins/Input/aac/aacfile.cpp new file mode 100644 index 000000000..9cf3184d8 --- /dev/null +++ b/src/plugins/Input/aac/aacfile.cpp @@ -0,0 +1,120 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * 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 2 of the License, 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <QIODevice> + +#include <neaacdec.h> + +#include "aacfile.h" + +#define MAX_CHANNELS 6 + +static int adts_sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,7350,0,0,0}; + +AACFile::AACFile(QIODevice *i) +{ + m_length = 0; + m_bitrate = 0; + m_input = i; + parseADTS(); +} + +AACFile::~AACFile() +{ +} + +qint64 AACFile::length() +{ + return m_length; +} + +quint32 AACFile::bitrate() +{ + return m_bitrate; +} + +void AACFile::parseADTS() +{ + uchar *buf = new uchar[FAAD_MIN_STREAMSIZE*MAX_CHANNELS]; + qint64 buf_at = 0; + int frames, frame_length; + int t_framelength = 0; + int samplerate = 0; + float frames_per_sec, bytes_per_frame; + qint64 pos = m_input->pos(); + + m_input->seek(0); + + buf_at = m_input->read((char *)buf, FAAD_MIN_STREAMSIZE*MAX_CHANNELS); + + for (int i = 0; i < buf_at - 1; i++) + { + if (buf[i] == 0xff && (buf[i+1]&0xf6) == 0xf0) + { + memmove (buf, buf + i, buf_at - i); + buf_at -= i; + break; + } + } + + /* Read all frames to ensure correct time and bitrate */ + for (frames = 0; /* */; frames++) + { + //qDebug("frame header = %d", buf[0]); + buf_at += m_input->read((char *)buf + buf_at, FAAD_MIN_STREAMSIZE*MAX_CHANNELS - buf_at); + + if (buf_at > 7) + { + /* check syncword */ + if (!((buf[0] == 0xFF)&&((buf[1] & 0xF6) == 0xF0))) + break; + + if (frames == 0) + samplerate = adts_sample_rates[(buf[2]&0x3c)>>2]; + + frame_length = ((((unsigned int)buf[3] & 0x3)) << 11) + | (((unsigned int)buf[4]) << 3) | (buf[5] >> 5); + + t_framelength += frame_length; + + if (frame_length > buf_at) + break; + + buf_at -= frame_length; + memmove(buf, buf + frame_length, buf_at); + } + else + { + break; + } + } + m_input->seek(pos); + frames_per_sec = (float)samplerate/1024.0f; + if (frames != 0) + bytes_per_frame = (float)t_framelength/(float)(frames*1000); + else + bytes_per_frame = 0; + m_bitrate = (quint32)(8. * bytes_per_frame * frames_per_sec + 0.5); + + if (frames_per_sec != 0) + m_length = frames/frames_per_sec; + else + m_length = 1; +} diff --git a/src/plugins/Input/aac/aacfile.h b/src/plugins/Input/aac/aacfile.h new file mode 100644 index 000000000..2d2ca1db5 --- /dev/null +++ b/src/plugins/Input/aac/aacfile.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * 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 2 of the License, 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef AACFILE_H +#define AACFILE_H + +class QIODevice; + +/** + @author Ilya Kotov <forkotov02@hotmail.ru> +*/ +class AACFile +{ +public: + AACFile(QIODevice *i); + + ~AACFile(); + + qint64 length(); + quint32 bitrate(); + +private: + void parseADTS(); + qint64 m_length; + quint32 m_bitrate; + QIODevice *m_input; + +}; + +#endif diff --git a/src/plugins/Input/aac/decoder_aac.cpp b/src/plugins/Input/aac/decoder_aac.cpp new file mode 100644 index 000000000..114c39a18 --- /dev/null +++ b/src/plugins/Input/aac/decoder_aac.cpp @@ -0,0 +1,328 @@ +/*************************************************************************** + * Copyright (C) 2006-2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * 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 2 of the License, 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + + +#include <QObject> +#include <QIODevice> +#include <QtGlobal> + +#include <qmmp/constants.h> +#include <qmmp/buffer.h> +#include <qmmp/output.h> +#include <qmmp/recycler.h> + +#include "decoder_aac.h" +#include "aacfile.h" + +#define AAC_BUFFER_SIZE 4096 + +// Decoder class + +DecoderAAC::DecoderAAC(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o) + : Decoder(parent, d, i, o) +{ + m_inited = FALSE; + m_user_stop = FALSE; + m_output_buf = 0; + m_output_bytes = 0; + m_output_at = 0; + m_bks = 0; + m_done = FALSE; + m_finish = FALSE; + m_len = 0; + m_freq = 0; + m_bitrate = 0; + m_seekTime = -1.0; + m_totalTime = 0.0; + m_chan = 0; + m_output_size = 0; + m_data = 0; + m_input_buf = 0; + m_input_at = 0; +} + + +DecoderAAC::~DecoderAAC() +{ + deinit(); + if (data()) + { + if (data()->handle) + NeAACDecClose (data()->handle); + delete data(); + m_data = 0; + } + if (m_output_buf) + delete [] m_output_buf; + if (m_input_buf) + delete [] m_input_buf; + m_output_buf = 0; + m_input_buf = 0; +} + + +void DecoderAAC::stop() +{ + m_user_stop = TRUE; +} + + +void DecoderAAC::flush(bool final) +{ + ulong min = final ? 0 : m_bks; + + while ((! m_done && ! m_finish) && m_output_bytes > min) + { + output()->recycler()->mutex()->lock (); + + while ((! m_done && ! m_finish) && output()->recycler()->full()) + { + mutex()->unlock(); + + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + + mutex()->lock (); + m_done = m_user_stop; + } + + if (m_user_stop || m_finish) + { + m_inited = FALSE; + m_done = TRUE; + } + else + { + m_output_bytes -= produceSound(m_output_buf, m_output_bytes, m_bitrate, m_chan); + m_output_size += m_bks; + m_output_at = m_output_bytes; + } + + if (output()->recycler()->full()) + { + output()->recycler()->cond()->wakeOne(); + } + + output()->recycler()->mutex()->unlock(); + } +} + + +bool DecoderAAC::initialize() +{ + m_bks = Buffer::size(); + m_inited = m_user_stop = m_done = m_finish = FALSE; + m_len = m_freq = m_bitrate = 0; + //chan = 0; + m_output_size = 0; + m_seekTime = -1.0; + m_totalTime = 0.0; + + + if (!input()) + { + qWarning("DecoderAAC: cannot initialize. No input."); + return FALSE; + } + if (!m_input_buf) + m_input_buf = new char[AAC_BUFFER_SIZE]; + + if (!m_output_buf) + m_output_buf = new char[globalBufferSize]; + m_output_at = 0; + m_output_bytes = 0; + m_input_at = 0; + + if (!input()->isOpen()) + { + if (!input()->open(QIODevice::ReadOnly)) + { + qWarning("DecoderAAC: unable to open input."); + return FALSE; + } + } + + if (!m_data) + m_data = new aac_data; + + data()->handle = NeAACDecOpen(); + + NeAACDecConfigurationPtr conf; + conf = NeAACDecGetCurrentConfiguration(data()->handle); + conf->downMatrix = 1; + conf->defSampleRate = 44100; + conf->dontUpSampleImplicitSBR = 0; + conf->defObjectType = LC; + conf->outputFormat = FAAD_FMT_16BIT; + NeAACDecSetConfiguration(data()->handle, conf); + m_input_at = input()->read((char *)m_input_buf, AAC_BUFFER_SIZE); + for (int i = 0; i < m_input_at - 1; i++) + { + if ((uchar)m_input_buf[i] == 0xff && ((uchar)m_input_buf[i+1]&0xf6) == 0xf0) + { + memmove (m_input_buf, m_input_buf + i, AAC_BUFFER_SIZE - i); + m_input_at -= i; + break; + } + } + AACFile aac_file(input()); + m_totalTime = aac_file.length(); + m_bitrate = aac_file.bitrate(); + + int res = NeAACDecInit (data()->handle, (unsigned char*) m_input_buf, m_input_at, &m_freq, &m_chan); + memmove(m_input_buf, m_input_buf + res, m_input_at - res); + m_input_at -= res; + + configure(m_freq, m_chan, 16); + + m_inited = TRUE; + qDebug("DecoderAAC: initialize succes"); + return TRUE; +} + +qint64 DecoderAAC::aac_decode(void *out) +{ + NeAACDecFrameInfo frame_info; + qint64 size = 0, to_read, read; + out = 0; + bool eof = FALSE; + + while (size <= 0 && !eof) + { + if (m_input_at < AAC_BUFFER_SIZE) + { + to_read = AAC_BUFFER_SIZE - m_input_at; + read = input()->read((char *) (m_input_buf + m_input_at), to_read); + eof = (read != to_read); + m_input_at += read; + } + + out = NeAACDecDecode(data()->handle, &frame_info, (uchar *)m_input_buf, m_input_at); + memmove(m_input_buf, m_input_buf + frame_info.bytesconsumed, m_input_at - frame_info.bytesconsumed); + m_input_at -= frame_info.bytesconsumed; + + if ((size = frame_info.samples * 2) > 0) + memcpy((void *) (m_output_buf + m_output_at), out, size); + } + return size; +} + +qint64 DecoderAAC::lengthInSeconds() +{ + if (!m_inited) + return 0; + + return m_totalTime; +} + + +void DecoderAAC::seek(qint64 pos) +{ + m_seekTime = pos; +} + + +void DecoderAAC::deinit() +{ + m_inited = m_user_stop = m_done = m_finish = FALSE; + m_len = m_freq = m_bitrate = 0; + m_chan = 0; + m_output_size = 0; +} + +void DecoderAAC::run() +{ + m_prebuf_pos = 0; + m_prebuf_size = 0; + mutex()->lock (); + if (!m_inited) + { + mutex()->unlock(); + return; + } + mutex()->unlock(); + + while (!m_done && !m_finish) + { + mutex()->lock (); + // decode + + if (m_seekTime >= 0.0) + { + //mpc_decoder_seek_seconds(&data()->decoder, seekTime); + input()->seek(m_seekTime * input()->size() / m_totalTime); + m_input_at = 0; + m_seekTime = -1.0; + } + + m_prebuf_size = aac_decode(m_prebuf2); + m_len = m_prebuf_size; + + if (m_len > 0) + { + //qDebug("flush"); + //bitrate = vbrUpd * data()->info.sample_freq / 1152; + m_output_at += m_len; + m_output_bytes += m_len; + + if (output()) + flush(); + + } + else if (m_len == 0) + { + flush(TRUE); + + if (output()) + { + output()->recycler()->mutex()->lock (); + // end of stream + while (!output()->recycler()->empty() && !m_user_stop) + { + output()->recycler()->cond()->wakeOne(); + mutex()->unlock(); + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + mutex()->lock (); + } + output()->recycler()->mutex()->unlock(); + } + + m_done = TRUE; + if (!m_user_stop) + { + m_finish = TRUE; + } + } + else + { + // error in read + qWarning("DecoderAAC: Error while decoding stream, file appears to be corrupted"); + m_finish = TRUE; + } + + mutex()->unlock(); + } + mutex()->lock (); + + if (m_finish) + finish(); + + mutex()->unlock(); + deinit(); +} diff --git a/src/plugins/Input/aac/decoder_aac.h b/src/plugins/Input/aac/decoder_aac.h new file mode 100644 index 000000000..5a1d698ea --- /dev/null +++ b/src/plugins/Input/aac/decoder_aac.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2006-2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * 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 2 of the License, 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef DECODER_AAC_H +#define DECODER_AAC_H + + +#include <neaacdec.h> + +#include <qmmp/decoder.h> + +struct aac_data +{ + NeAACDecHandle handle; +}; + +class DecoderAAC : public Decoder +{ +public: + DecoderAAC(QObject *, DecoderFactory *, QIODevice *, Output *); + virtual ~DecoderAAC(); + + // Standard Decoder API + bool initialize(); + qint64 lengthInSeconds(); + void seek(qint64); + void stop(); + + struct aac_data *data() + { + return m_data; + } + + +private: + // thread run function + void run(); + struct aac_data *m_data; + // helper functions + void flush(bool = FALSE); + void deinit(); + qint64 aac_decode(void *out); + + bool m_inited, m_user_stop; + + // output buffer + char *m_output_buf, *m_input_buf; + void *m_prebuf2; + qint64 m_output_bytes, m_output_at, m_input_at, m_prebuf_pos, m_prebuf_size; + + unsigned int m_bks; + bool m_done, m_finish; + long unsigned int m_len, m_freq, m_bitrate; + unsigned char m_chan; + unsigned long m_output_size; + double m_frameSize; //frame size in bytes + qint64 m_totalTime, m_seekTime; +}; + + +#endif // __decoder_aac_h diff --git a/src/plugins/Input/aac/decoderaacfactory.cpp b/src/plugins/Input/aac/decoderaacfactory.cpp new file mode 100644 index 000000000..2f5b621ee --- /dev/null +++ b/src/plugins/Input/aac/decoderaacfactory.cpp @@ -0,0 +1,121 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * 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 2 of the License, 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <QtGui> +#include <QFile> + +#include "aacfile.h" +#include "detailsdialog.h" +#include "decoder_aac.h" +#include "decoderaacfactory.h" + + +// DecoderAACFactory + +bool DecoderAACFactory::supports(const QString &source) const +{ + + return (source.right(4).toLower() == ".aac") + || (source.right(4).toLower() == ".m4a"); +} + +bool DecoderAACFactory::canDecode(QIODevice *) const +{ + return FALSE; +} + +const DecoderProperties DecoderAACFactory::properties() const +{ + DecoderProperties properties; + properties.name = tr("AAC Plugin"); + properties.filter = "*.aac"; + properties.description = tr("AAC Files"); + //properties.contentType = ; + properties.hasAbout = TRUE; + properties.hasSettings = FALSE; + return properties; +} + +Decoder *DecoderAACFactory::create(QObject *parent, QIODevice *input, + Output *output, const QString &) +{ + return new DecoderAAC(parent, this, input, output); +} + +QList<FileInfo *> DecoderAACFactory::createPlayList(const QString &fileName) +{ + FileInfo *info = new FileInfo(fileName); + + /*TagLib::FileRef fileRef(fileName.toLocal8Bit ()); + TagLib::Tag *tag = fileRef.tag(); + if (tag && !tag->isEmpty()) + { + info->setMetaData(Qmmp::ALBUM, + QString::fromUtf8(tag->album().toCString(TRUE)).trimmed()); + info->setMetaData(Qmmp::ARTIST, + QString::fromUtf8(tag->artist().toCString(TRUE)).trimmed()); + info->setMetaData(Qmmp::COMMENT, + QString::fromUtf8(tag->comment().toCString(TRUE)).trimmed()); + info->setMetaData(Qmmp::GENRE, + QString::fromUtf8(tag->genre().toCString(TRUE)).trimmed()); + info->setMetaData(Qmmp::TITLE, + QString::fromUtf8(tag->title().toCString(TRUE)).trimmed()); + info->setMetaData(Qmmp::YEAR, tag->year()); + info->setMetaData(Qmmp::TRACK, tag->track()); + } + if (fileRef.audioProperties()) + info->setLength(fileRef.audioProperties()->length());*/ + QFile file(fileName); + if(file.open(QIODevice::ReadOnly)) + { + AACFile aac_file(&file); + info->setLength(aac_file.length()); + } + QList <FileInfo*> list; + list << info; + return list; +} + +QObject* DecoderAACFactory::showDetails(QWidget *parent, const QString &path) +{ + /*DetailsDialog *d = new DetailsDialog(parent, path); + d -> show();*/ + return 0; +} + +void DecoderAACFactory::showSettings(QWidget *) +{} + +void DecoderAACFactory::showAbout(QWidget *parent) +{ + QMessageBox::about (parent, tr("About AAC Audio Plugin"), + tr("Qmmp AAC Audio Plugin")+"\n"+ + tr("Writen by: Ilya Kotov <forkotov02@hotmail.ru>")); +} + +QTranslator *DecoderAACFactory::createTranslator(QObject *parent) +{ + QTranslator *translator = new QTranslator(parent); + QString locale = QLocale::system().name(); + translator->load(QString(":/aac_plugin_") + locale); + return translator; +} + +Q_EXPORT_PLUGIN(DecoderAACFactory) diff --git a/src/plugins/Input/aac/decoderaacfactory.h b/src/plugins/Input/aac/decoderaacfactory.h new file mode 100644 index 000000000..eb4fb6276 --- /dev/null +++ b/src/plugins/Input/aac/decoderaacfactory.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2006-2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * 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 2 of the License, 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef DECODERAACFACTORY_H +#define DECODERAACFACTORY_H + +#include <QObject> +#include <QString> +#include <QIODevice> +#include <QWidget> + +#include <qmmp/decoder.h> +#include <qmmp/output.h> +#include <qmmp/decoderfactory.h> +#include <qmmp/fileinfo.h> + + + + +class DecoderAACFactory : public QObject, + DecoderFactory +{ +Q_OBJECT +Q_INTERFACES(DecoderFactory); + +public: + bool supports(const QString &source) const; + bool canDecode(QIODevice *input) const; + const DecoderProperties properties() const; + Decoder *create(QObject *, QIODevice *, Output *, const QString &); + QList<FileInfo *> createPlayList(const QString &fileName); + QObject* showDetails(QWidget *parent, const QString &path); + void showSettings(QWidget *parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); +}; + +#endif diff --git a/src/plugins/Input/aac/detailsdialog.cpp b/src/plugins/Input/aac/detailsdialog.cpp new file mode 100644 index 000000000..472046717 --- /dev/null +++ b/src/plugins/Input/aac/detailsdialog.cpp @@ -0,0 +1,115 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * 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 2 of the License, 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include <taglib/tag.h> +#include <taglib/fileref.h> +#include <taglib/mpcfile.h> + +#include <QFile> +#include <QFileInfo> + +#include "detailsdialog.h" + +#define QStringToTString_qt4(s) TagLib::String(s.toUtf8().constData(), TagLib::String::UTF8) + +DetailsDialog::DetailsDialog(QWidget *parent, const QString &path) + : QDialog(parent) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + m_path = path; + setWindowTitle (path.section('/',-1)); + path.section('/',-1); + ui.pathLineEdit->setText(m_path); + if(QFile::exists(m_path)) + { + loadMPCInfo(); + loadTag(); + } +} + + +DetailsDialog::~DetailsDialog() +{} + +void DetailsDialog::loadMPCInfo() +{ + TagLib::MPC::File f (m_path.toLocal8Bit()); + QString text; + text = QString("%1").arg(f.audioProperties()->length()/60); + text +=":"+QString("%1").arg(f.audioProperties()->length()%60,2,10,QChar('0')); + ui.lengthLabel->setText(text); + text = QString("%1").arg(f.audioProperties()->sampleRate()); + ui.sampleRateLabel->setText(text+" "+tr("Hz")); + text = QString("%1").arg(f.audioProperties()->channels()); + ui.channelsLabel->setText(text); + text = QString("%1").arg(f.audioProperties()->bitrate()); + ui.bitrateLabel->setText(text+" "+tr("kbps")); + text = QString("%1").arg(f.audioProperties()->mpcVersion()); + ui.versionLabel->setText(text); + text = QString("%1 "+tr("KB")).arg(f.length()/1024); + ui.fileSizeLabel->setText(text); +} + +void DetailsDialog::loadTag() +{ + TagLib::FileRef f (m_path.toLocal8Bit()); + + if (f.tag()) + { //TODO: load codec name from config + + TagLib::String title = f.tag()->title(); + TagLib::String artist = f.tag()->artist(); + TagLib::String album = f.tag()->album(); + TagLib::String comment = f.tag()->comment(); + TagLib::String genre = f.tag()->genre(); + QString string = QString::fromUtf8(title.toCString(TRUE)).trimmed(); + ui.titleLineEdit->setText(string); + string = QString::fromUtf8(artist.toCString(TRUE)).trimmed(); + ui.artistLineEdit->setText(string); + string = QString::fromUtf8(album.toCString(TRUE)).trimmed(); + ui.albumLineEdit->setText(string); + string = QString::fromUtf8(comment.toCString(TRUE)).trimmed(); + ui.commentLineEdit->setText(string); + string = QString("%1").arg(f.tag()->year()); + ui.yearLineEdit->setText(string); + string = QString("%1").arg(f.tag()->track()); + ui.trackLineEdit->setText(string); + string = QString::fromUtf8(genre.toCString(TRUE)).trimmed(); + ui.genreLineEdit->setText(string); + } + QFileInfo info(m_path); + ui.saveButton->setEnabled(info.isWritable()); + connect(ui.saveButton, SIGNAL(clicked()), SLOT(saveTag())); +} + +void DetailsDialog::saveTag() +{ + TagLib::FileRef f (m_path.toLocal8Bit()); + + f.tag()->setTitle(QStringToTString_qt4(ui.titleLineEdit->text())); + f.tag()->setArtist(QStringToTString_qt4(ui.artistLineEdit->text())); + f.tag()->setAlbum(QStringToTString_qt4(ui.albumLineEdit->text())); + f.tag()->setComment(QStringToTString_qt4(ui.commentLineEdit->text())); + f.tag()->setGenre(QStringToTString_qt4(ui.genreLineEdit->text())); + f.tag()->setYear(ui.yearLineEdit->text().toUInt()); + f.tag()->setTrack(ui.trackLineEdit->text().toUInt()); + + f.save(); +} diff --git a/src/plugins/Input/aac/detailsdialog.h b/src/plugins/Input/aac/detailsdialog.h new file mode 100644 index 000000000..70540bda1 --- /dev/null +++ b/src/plugins/Input/aac/detailsdialog.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * 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 2 of the License, 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef DETAILSDIALOG_H +#define DETAILSDIALOG_H + +#include <QDialog> + +#include "ui_detailsdialog.h" + +/** + @author Ilya Kotov <forkotov02@hotmail.ru> +*/ +class DetailsDialog : public QDialog +{ +Q_OBJECT +public: + DetailsDialog(QWidget *parent = 0, const QString &path = 0); + + ~DetailsDialog(); + +private slots: + void saveTag(); + +private: + void loadMPCInfo(); + void loadTag(); + Ui::DetailsDialog ui; + QString m_path; + +}; + +#endif diff --git a/src/plugins/Input/aac/detailsdialog.ui b/src/plugins/Input/aac/detailsdialog.ui new file mode 100644 index 000000000..618300c10 --- /dev/null +++ b/src/plugins/Input/aac/detailsdialog.ui @@ -0,0 +1,347 @@ +<ui version="4.0" > + <class>DetailsDialog</class> + <widget class="QDialog" name="DetailsDialog" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>545</width> + <height>374</height> + </rect> + </property> + <property name="windowTitle" > + <string>Details</string> + </property> + <layout class="QGridLayout" > + <item row="0" column="0" > + <widget class="QLabel" name="label_28" > + <property name="text" > + <string>File path:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1" colspan="3" > + <widget class="QLineEdit" name="pathLineEdit" > + <property name="readOnly" > + <bool>true</bool> + </property> + </widget> + </item> + <item rowspan="2" row="1" column="0" colspan="2" > + <widget class="QGroupBox" name="groupBox" > + <property name="minimumSize" > + <size> + <width>0</width> + <height>16</height> + </size> + </property> + <property name="title" > + <string>Musepack Info</string> + </property> + <layout class="QGridLayout" > + <property name="leftMargin" > + <number>8</number> + </property> + <property name="topMargin" > + <number>8</number> + </property> + <property name="rightMargin" > + <number>8</number> + </property> + <property name="bottomMargin" > + <number>8</number> + </property> + <property name="horizontalSpacing" > + <number>6</number> + </property> + <property name="verticalSpacing" > + <number>6</number> + </property> + <item row="6" column="0" > + <spacer> + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" > + <size> + <width>74</width> + <height>151</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="1" colspan="2" > + <widget class="QLabel" name="fileSizeLabel" > + <property name="text" > + <string>-</string> + </property> + </widget> + </item> + <item row="0" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>Length:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1" colspan="2" > + <widget class="QLabel" name="lengthLabel" > + <property name="text" > + <string>-</string> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label_3" > + <property name="text" > + <string>Sample rate:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="1" colspan="2" > + <widget class="QLabel" name="sampleRateLabel" > + <property name="text" > + <string>-</string> + </property> + </widget> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="label_10" > + <property name="layoutDirection" > + <enum>Qt::LeftToRight</enum> + </property> + <property name="text" > + <string>Channels:</string> + </property> + <property name="textFormat" > + <enum>Qt::PlainText</enum> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="label_5" > + <property name="text" > + <string>File size:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="4" column="0" > + <widget class="QLabel" name="label_2" > + <property name="text" > + <string>Bitrate:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="1" colspan="2" > + <widget class="QLabel" name="channelsLabel" > + <property name="layoutDirection" > + <enum>Qt::LeftToRight</enum> + </property> + <property name="text" > + <string>-</string> + </property> + </widget> + </item> + <item row="4" column="1" colspan="2" > + <widget class="QLabel" name="bitrateLabel" > + <property name="text" > + <string>-</string> + </property> + </widget> + </item> + <item row="5" column="0" > + <widget class="QLabel" name="label_4" > + <property name="text" > + <string>Stream version:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="5" column="1" colspan="2" > + <widget class="QLabel" name="versionLabel" > + <property name="text" > + <string>-</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="1" column="2" colspan="2" > + <widget class="QGroupBox" name="groupBox_2" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title" > + <string>APE Tag</string> + </property> + <layout class="QGridLayout" > + <item row="0" column="0" > + <widget class="QLabel" name="label_21" > + <property name="text" > + <string>Title:</string> + </property> + <property name="alignment" > + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1" colspan="3" > + <widget class="QLineEdit" name="titleLineEdit" /> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label_22" > + <property name="text" > + <string>Artist:</string> + </property> + <property name="alignment" > + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="1" colspan="3" > + <widget class="QLineEdit" name="artistLineEdit" /> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="label_23" > + <property name="text" > + <string>Album:</string> + </property> + <property name="alignment" > + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="1" colspan="3" > + <widget class="QLineEdit" name="albumLineEdit" /> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="label_24" > + <property name="text" > + <string>Comment:</string> + </property> + <property name="alignment" > + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="1" colspan="3" > + <widget class="QLineEdit" name="commentLineEdit" /> + </item> + <item row="4" column="0" > + <widget class="QLabel" name="label_25" > + <property name="text" > + <string>Year:</string> + </property> + <property name="alignment" > + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="4" column="1" > + <widget class="QLineEdit" name="yearLineEdit" /> + </item> + <item row="4" column="2" > + <widget class="QLabel" name="label_26" > + <property name="text" > + <string>Track number:</string> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="4" column="3" > + <widget class="QLineEdit" name="trackLineEdit" /> + </item> + <item row="5" column="0" > + <widget class="QLabel" name="label_27" > + <property name="text" > + <string>Genre:</string> + </property> + <property name="alignment" > + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="5" column="1" colspan="2" > + <widget class="QLineEdit" name="genreLineEdit" /> + </item> + <item row="6" column="1" > + <widget class="QPushButton" name="saveButton" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>Save</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="2" column="2" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>111</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="3" > + <widget class="QPushButton" name="pushButton_3" > + <property name="text" > + <string>Close</string> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>pushButton_3</sender> + <signal>clicked()</signal> + <receiver>DetailsDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel" > + <x>623</x> + <y>353</y> + </hint> + <hint type="destinationlabel" > + <x>539</x> + <y>352</y> + </hint> + </hints> + </connection> + </connections> +</ui> |
