diff options
| author | vovanec <vovanec@90c681e8-e032-0410-971d-27865f9a5e38> | 2008-02-07 13:36:34 +0000 |
|---|---|---|
| committer | vovanec <vovanec@90c681e8-e032-0410-971d-27865f9a5e38> | 2008-02-07 13:36:34 +0000 |
| commit | 06d1877811fa6aa97dddc0e03bcde4e766928c87 (patch) | |
| tree | c25462d0e58c3d58c728664440412bf4f16a49ec /src/plugins/Input/sndfile | |
| parent | 3f6b60f23c44a8ba8dd97ca6f41a16e2af7ef2f7 (diff) | |
| download | qmmp-06d1877811fa6aa97dddc0e03bcde4e766928c87.tar.gz qmmp-06d1877811fa6aa97dddc0e03bcde4e766928c87.tar.bz2 qmmp-06d1877811fa6aa97dddc0e03bcde4e766928c87.zip | |
new directory structure
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@232 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/plugins/Input/sndfile')
| -rw-r--r-- | src/plugins/Input/sndfile/CMakeLists.txt | 74 | ||||
| -rw-r--r-- | src/plugins/Input/sndfile/decoder_sndfile.cpp | 282 | ||||
| -rw-r--r-- | src/plugins/Input/sndfile/decoder_sndfile.h | 66 | ||||
| -rw-r--r-- | src/plugins/Input/sndfile/decodersndfilefactory.cpp | 126 | ||||
| -rw-r--r-- | src/plugins/Input/sndfile/decodersndfilefactory.h | 54 | ||||
| -rw-r--r-- | src/plugins/Input/sndfile/sndfile.pro | 28 |
6 files changed, 630 insertions, 0 deletions
diff --git a/src/plugins/Input/sndfile/CMakeLists.txt b/src/plugins/Input/sndfile/CMakeLists.txt new file mode 100644 index 000000000..974db398e --- /dev/null +++ b/src/plugins/Input/sndfile/CMakeLists.txt @@ -0,0 +1,74 @@ +project(libsndfile) + +cmake_minimum_required(VERSION 2.4.0) + + +INCLUDE(UsePkgConfig) +INCLUDE(FindQt4) + +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt plugin +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(QT_INCLUDES + ${QT_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR}/../../../ +) + +# libqmmp +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) + +# libsndfile +PKGCONFIG(sndfile SNDFILE_INCLUDE_DIR SNDFILE_LINK_DIR SNDFILE_LINK_FLAGS SNDFILE_CFLAGS) + +IF(NOT SNDFILE_LINK_FLAGS) + SET(SNDFILE_LINK_FLAGS -lsndfile) + SET(SNDFILE_INCLUDE_DIR /usr/include) + SET(SNDFILE_CFLAGS -I/usr/include) +ENDIF(NOT SNDFILE_LINK_FLAGS) + +include_directories(${SNDFILE_INCLUDE_DIR}) +link_directories(${SNDFILE_LINK_DIR}) + +ADD_DEFINITIONS(${SNDFILE_CFLAGS}) + + +SET(libsndfile_SRCS + decoder_sndfile.cpp + decodersndfilefactory.cpp +) + +SET(libsndfile_MOC_HDRS + decodersndfilefactory.h + decoder_sndfile.h +) + +#SET(libsndfile_RCCS translations/translations.qrc) + +#QT4_ADD_RESOURCES(libsndfile_RCC_SRCS ${libsndfile_RCCS}) + +QT4_WRAP_CPP(libsndfile_MOC_SRCS ${libsndfile_MOC_HDRS}) + + +# Don't forget to include output directory, otherwise +# the UI file won't be wrapped! +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +ADD_LIBRARY(sndfile SHARED ${libsndfile_SRCS} ${libsndfile_MOC_SRCS} ${libsndfile_UIS_H} + ${libsndfile_RCC_SRCS}) + +target_link_libraries(sndfile ${QT_LIBRARIES} -lqmmp ${SNDFILE_LINK_FLAGS}) +install(TARGETS sndfile DESTINATION ${LIB_DIR}/qmmp/Input) + + + diff --git a/src/plugins/Input/sndfile/decoder_sndfile.cpp b/src/plugins/Input/sndfile/decoder_sndfile.cpp new file mode 100644 index 000000000..b4baa2ba4 --- /dev/null +++ b/src/plugins/Input/sndfile/decoder_sndfile.cpp @@ -0,0 +1,282 @@ +/*************************************************************************** + * 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 <QObject> +#include <QFile> +#include <QFileInfo> + + + +#include "constants.h" +#include "buffer.h" +#include "output.h" +#include "recycler.h" + +#include "decoder_sndfile.h" + +// Decoder class + +DecoderSndFile::DecoderSndFile(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; + bks = 0; + m_done = FALSE; + m_finish = FALSE; + m_freq = 0; + m_bitrate = 0; + m_seekTime = -1.0; + m_totalTime = 0.0; + m_chan = 0; + m_output_size = 0; + m_buf = 0; + m_sndfile = 0; +} + + +DecoderSndFile::~DecoderSndFile() +{ + deinit(); +} + + +void DecoderSndFile::stop() +{ + m_user_stop = TRUE; +} + + +void DecoderSndFile::flush(bool final) +{ + ulong min = final ? 0 : 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 += bks; + m_output_at = m_output_bytes; + } + + if (output()->recycler()->full()) + { + output()->recycler()->cond()->wakeOne(); + } + + output()->recycler()->mutex()->unlock(); + } +} + + +bool DecoderSndFile::initialize() +{ + bks = blockSize(); + m_inited = m_user_stop = m_done = m_finish = FALSE; + m_freq = m_bitrate = 0; + m_output_size = 0; + m_seekTime = -1.0; + m_totalTime = 0.0; + SF_INFO snd_info; + + + if (! input()) + { + error("DecoderSndFile: cannot initialize. No input."); + + return FALSE; + } + + if (! m_output_buf) + m_output_buf = new char[globalBufferSize]; + m_output_at = 0; + m_output_bytes = 0; + + QString filename = qobject_cast<QFile*>(input())->fileName (); + input()->close(); + + memset (&snd_info, 0, sizeof(snd_info)); + snd_info.format=0; + m_sndfile = sf_open(filename.toLocal8Bit(), SFM_READ, &snd_info); + if (!m_sndfile) + { + qWarning("DecoderSndFile: failed to open: %s", qPrintable(filename)); + return FALSE; + } + + m_freq = snd_info.samplerate; + m_chan = snd_info.channels; + + m_totalTime = (double) snd_info.frames / m_freq; + + m_bitrate = QFileInfo(filename).size () * 8.0 / m_totalTime / 1000.0 + 0.5; + + configure(m_freq, m_chan, 16, m_bitrate); + m_buf = new short[blockSize() / sizeof(short)]; + m_inited = TRUE; + qDebug("DecoderSndFile: detected format: %08X", snd_info.format); + qDebug("DecoderSndFile: initialize succes"); + return TRUE; +} + + +double DecoderSndFile::lengthInSeconds() +{ + if (! m_inited) + return 0; + + return m_totalTime; +} + + +void DecoderSndFile::seek(double pos) +{ + m_seekTime = pos; +} + + +void DecoderSndFile::deinit() +{ + m_inited = m_user_stop = m_done = m_finish = FALSE; + m_freq = m_bitrate = m_chan = 0; + m_output_size = 0; + if (m_inited) + { + delete m_buf; + m_buf = 0; + sf_close(m_sndfile); + m_sndfile = 0; + } +} + +void DecoderSndFile::run() +{ + + long len = 0; + int stat = 0; + + mutex()->lock (); + + if (! m_inited) + { + mutex()->unlock(); + + return; + } + + stat = DecoderState::Decoding; + mutex()->unlock(); + + { + dispatch(DecoderState ((DecoderState::Type) stat)); + } + + while (! m_done && ! m_finish) + { + mutex()->lock (); + // decode + + if (m_seekTime >= 0.0) + { + m_output_size = sf_seek(m_sndfile, m_freq*m_seekTime, SEEK_SET); + m_seekTime = -1.0; + } + + len = sizeof(short)* sf_read_short (m_sndfile, m_buf, blockSize() / sizeof(short)); + + if (len > 0) + { + memmove((char *)(m_output_buf + m_output_at), (char *) m_buf, len); + m_output_at += len; + m_output_bytes += len; + + if (output()) + flush(); + } + else if (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 + error("DecoderSndFile: Error while decoding stream, File appears to be " + "corrupted"); + + m_finish = TRUE; + } + + mutex()->unlock(); + } + + mutex()->lock (); + + if (m_finish) + stat = DecoderState::Finished; + else if (m_user_stop) + stat = DecoderState::Stopped; + + mutex()->unlock(); + + dispatch(DecoderState ((DecoderState::Type) stat)); + deinit(); +} + diff --git a/src/plugins/Input/sndfile/decoder_sndfile.h b/src/plugins/Input/sndfile/decoder_sndfile.h new file mode 100644 index 000000000..53bb8fd81 --- /dev/null +++ b/src/plugins/Input/sndfile/decoder_sndfile.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * 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 DECODER_AUDIOFILE_H +#define DECODER_AUDIOFILE_H + +extern "C"{ +#include <sndfile.h> +} +#include "decoder.h" + + +class DecoderSndFile : public Decoder +{ +public: + DecoderSndFile(QObject *, DecoderFactory *, QIODevice *, Output *); + virtual ~DecoderSndFile(); + + // Standard Decoder API + bool initialize(); + double lengthInSeconds(); + void seek(double); + void stop(); + + +private: + // thread run function + void run(); + // helper functions + void flush(bool = FALSE); + void deinit(); + + // output buffer + char *m_output_buf; + + SNDFILE *m_sndfile; + ulong m_output_bytes, m_output_at; + //struct sndfile_data *m_data; + short *m_buf; + unsigned int bks; + bool m_done, m_finish, m_inited, m_user_stop; + long m_freq, m_bitrate; + int m_chan; + unsigned long m_output_size; + double m_totalTime, m_seekTime; +}; + + +#endif // DECODER_SNDFILE_H diff --git a/src/plugins/Input/sndfile/decodersndfilefactory.cpp b/src/plugins/Input/sndfile/decodersndfilefactory.cpp new file mode 100644 index 000000000..b918d32fc --- /dev/null +++ b/src/plugins/Input/sndfile/decodersndfilefactory.cpp @@ -0,0 +1,126 @@ +/*************************************************************************** + * 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 <QtGui> +#include <sndfile.h> + +#include "decoder_sndfile.h" +#include "decodersndfilefactory.h" + + +// DecoderSndFileFactory + +bool DecoderSndFileFactory::supports(const QString &source) const +{ + + return (source.right(4).toLower() == ".wav") || + (source.right(3).toLower() == ".au") || + (source.right(4).toLower() == ".snd") || + (source.right(4).toLower() == ".aif") || + (source.right(5).toLower() == ".aiff") || + (source.right(5).toLower() == ".8svx") || + (source.right(4).toLower() == ".wav") || + (source.right(4).toLower() == ".sph") || + (source.right(3).toLower() == ".sf") || + (source.right(4).toLower() == ".voc"); +} + +bool DecoderSndFileFactory::canDecode(QIODevice *) const +{ + return FALSE; +} + +const DecoderProperties DecoderSndFileFactory::properties() const +{ + DecoderProperties properties; + properties.name = tr("Sndfile Plugin"); + properties.filter = "*.wav *.au *.snd *.aif *.aiff *.8svx *.sph *.sf *.voc"; + properties.description = tr("PCM Files"); + //properties.contentType = ""; + properties.hasAbout = TRUE; + properties.hasSettings = FALSE; + return properties; +} + +Decoder *DecoderSndFileFactory::create(QObject *parent, QIODevice *input, + Output *output) +{ + return new DecoderSndFile(parent, this, input, output); +} + +FileTag *DecoderSndFileFactory::createTag(const QString &source) +{ + FileTag *ftag = new FileTag(); + SF_INFO snd_info; + SNDFILE *sndfile = 0; + memset (&snd_info, 0, sizeof(snd_info)); + snd_info.format = 0; + sndfile = sf_open(source.toLocal8Bit(), SFM_READ, &snd_info); + if (!sndfile) + return ftag; + + if (sf_get_string(sndfile, SF_STR_TITLE)) + { + char* title = strdup(sf_get_string(sndfile, SF_STR_TITLE)); + ftag->setValue(FileTag::TITLE, QString::fromUtf8(title).trimmed()); + } + if (sf_get_string(sndfile, SF_STR_ARTIST)) + { + char* artist = strdup(sf_get_string(sndfile, SF_STR_ARTIST)); + ftag->setValue(FileTag::ARTIST, QString::fromUtf8(artist).trimmed()); + } + if (sf_get_string(sndfile, SF_STR_COMMENT)) + { + char* comment = strdup(sf_get_string(sndfile, SF_STR_COMMENT)); + ftag->setValue(FileTag::COMMENT, QString::fromUtf8(comment).trimmed()); + } + + ftag->setValue(FileTag::LENGTH ,int(snd_info.frames / snd_info.samplerate)); + + sf_close(sndfile); + return ftag; +} + +QObject* DecoderSndFileFactory::showDetails(QWidget *parent, const QString &path) +{ + return 0; +} + +void DecoderSndFileFactory::showSettings(QWidget *) +{} + +void DecoderSndFileFactory::showAbout(QWidget *parent) +{ + char version [128] ; + sf_command (NULL, SFC_GET_LIB_VERSION, version, sizeof (version)) ; + QMessageBox::about (parent, tr("About Sndfile Audio Plugin"), + tr("Qmmp Sndfile Audio Plugin")+"\n"+ + tr("Compiled against")+" "+QString(version)+"\n" + + tr("Writen by: Ilya Kotov <forkotov02@hotmail.ru>")); +} + +QTranslator *DecoderSndFileFactory::createTranslator(QObject *parent) +{ + QTranslator *translator = new QTranslator(parent); + QString locale = QLocale::system().name(); + translator->load(QString(":/sndfile_plugin_") + locale); + return translator; +} + +Q_EXPORT_PLUGIN(DecoderSndFileFactory) diff --git a/src/plugins/Input/sndfile/decodersndfilefactory.h b/src/plugins/Input/sndfile/decodersndfilefactory.h new file mode 100644 index 000000000..8439594fb --- /dev/null +++ b/src/plugins/Input/sndfile/decodersndfilefactory.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * 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 DECODERSNDFILEFACTORY_H +#define DECODERSNDFILEFACTORY_H + +#include <QObject> +#include <QString> +#include <QIODevice> +#include <QWidget> + +#include <decoder.h> +#include <output.h> +#include <decoderfactory.h> +#include <filetag.h> + + + + +class DecoderSndFileFactory : 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 *); + FileTag *createTag(const QString &source); + 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/sndfile/sndfile.pro b/src/plugins/Input/sndfile/sndfile.pro new file mode 100644 index 000000000..701ea58fb --- /dev/null +++ b/src/plugins/Input/sndfile/sndfile.pro @@ -0,0 +1,28 @@ +include(../../plugins.pri) + +HEADERS += decodersndfilefactory.h \ + decoder_sndfile.h +SOURCES += decoder_sndfile.cpp \ + decodersndfilefactory.cpp + +TARGET=$$PLUGINS_PREFIX/Input/sndfile +QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libsndfile.so + +INCLUDEPATH += ../../../qmmp +CONFIG += release \ +warn_on \ +plugin \ +link_pkgconfig +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib +LIBS += -lqmmp -L/usr/lib -I/usr/include + +PKGCONFIG += sndfile +#TRANSLATIONS = translations/ffmpeg_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty (LIB_DIR){ +LIB_DIR = /lib +} +target.path = $$LIB_DIR/qmmp/Input +INSTALLS += target |
