aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Input/aac
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2008-10-25 20:58:48 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2008-10-25 20:58:48 +0000
commitbed87bc89a1258d3b3dc429f3df114c8c2655a6a (patch)
tree358e8d37a910fd5b6cfbf5b32adaa8130da9a4a7 /src/plugins/Input/aac
parentf36b2f8d5c85c4c2a32a1dd884c57735f50e3b87 (diff)
downloadqmmp-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.pro39
-rw-r--r--src/plugins/Input/aac/aacfile.cpp120
-rw-r--r--src/plugins/Input/aac/aacfile.h46
-rw-r--r--src/plugins/Input/aac/decoder_aac.cpp328
-rw-r--r--src/plugins/Input/aac/decoder_aac.h78
-rw-r--r--src/plugins/Input/aac/decoderaacfactory.cpp121
-rw-r--r--src/plugins/Input/aac/decoderaacfactory.h54
-rw-r--r--src/plugins/Input/aac/detailsdialog.cpp115
-rw-r--r--src/plugins/Input/aac/detailsdialog.h49
-rw-r--r--src/plugins/Input/aac/detailsdialog.ui347
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>