aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Input
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/Input')
-rw-r--r--src/plugins/Input/CMakeLists.txt49
-rw-r--r--src/plugins/Input/Input.pro26
-rw-r--r--src/plugins/Input/ffmpeg/CMakeLists.txt94
-rw-r--r--src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp342
-rw-r--r--src/plugins/Input/ffmpeg/decoder_ffmpeg.h78
-rw-r--r--src/plugins/Input/ffmpeg/decoderffmpegfactory.cpp93
-rw-r--r--src/plugins/Input/ffmpeg/decoderffmpegfactory.h54
-rw-r--r--src/plugins/Input/ffmpeg/detailsdialog.cpp103
-rw-r--r--src/plugins/Input/ffmpeg/detailsdialog.h45
-rw-r--r--src/plugins/Input/ffmpeg/detailsdialog.ui332
-rw-r--r--src/plugins/Input/ffmpeg/ffmpeg.pro35
-rw-r--r--src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_cs.ts150
-rw-r--r--src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.qmbin0 -> 2221 bytes
-rw-r--r--src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.ts149
-rw-r--r--src/plugins/Input/ffmpeg/translations/translations.qrc6
-rw-r--r--src/plugins/Input/flac/CMakeLists.txt86
-rw-r--r--src/plugins/Input/flac/decoder_flac.cpp567
-rw-r--r--src/plugins/Input/flac/decoder_flac.h124
-rw-r--r--src/plugins/Input/flac/decoderflacfactory.cpp95
-rw-r--r--src/plugins/Input/flac/decoderflacfactory.h54
-rw-r--r--src/plugins/Input/flac/detailsdialog.cpp118
-rw-r--r--src/plugins/Input/flac/detailsdialog.h49
-rw-r--r--src/plugins/Input/flac/detailsdialog.ui349
-rw-r--r--src/plugins/Input/flac/flac.pro36
-rw-r--r--src/plugins/Input/flac/translations/flac_plugin_ru.qmbin0 -> 2218 bytes
-rw-r--r--src/plugins/Input/flac/translations/flac_plugin_ru.ts154
-rw-r--r--src/plugins/Input/flac/translations/translations.qrc6
-rw-r--r--src/plugins/Input/mad/CMakeLists.txt90
-rw-r--r--src/plugins/Input/mad/decoder_mad.cpp572
-rw-r--r--src/plugins/Input/mad/decoder_mad.h95
-rw-r--r--src/plugins/Input/mad/decodermadfactory.cpp188
-rw-r--r--src/plugins/Input/mad/decodermadfactory.h53
-rw-r--r--src/plugins/Input/mad/detailsdialog.cpp294
-rw-r--r--src/plugins/Input/mad/detailsdialog.h63
-rw-r--r--src/plugins/Input/mad/detailsdialog.ui392
-rw-r--r--src/plugins/Input/mad/mad.pro39
-rw-r--r--src/plugins/Input/mad/settingsdialog.cpp107
-rw-r--r--src/plugins/Input/mad/settingsdialog.h52
-rw-r--r--src/plugins/Input/mad/settingsdialog.ui306
-rw-r--r--src/plugins/Input/mad/translations/mad_plugin_ru.qmbin0 -> 3625 bytes
-rw-r--r--src/plugins/Input/mad/translations/mad_plugin_ru.ts242
-rw-r--r--src/plugins/Input/mad/translations/translations.qrc6
-rw-r--r--src/plugins/Input/mad/ui_detailsdialog.h400
-rw-r--r--src/plugins/Input/mad/ui_settingsdialog.h245
-rw-r--r--src/plugins/Input/mpc/CMakeLists.txt86
-rw-r--r--src/plugins/Input/mpc/Makefile254
-rw-r--r--src/plugins/Input/mpc/decoder_mpc.cpp386
-rw-r--r--src/plugins/Input/mpc/decoder_mpc.h80
-rw-r--r--src/plugins/Input/mpc/decodermpcfactory.cpp95
-rw-r--r--src/plugins/Input/mpc/decodermpcfactory.h54
-rw-r--r--src/plugins/Input/mpc/detailsdialog.cpp115
-rw-r--r--src/plugins/Input/mpc/detailsdialog.h49
-rw-r--r--src/plugins/Input/mpc/detailsdialog.ui349
-rw-r--r--src/plugins/Input/mpc/mpc.pro32
-rw-r--r--src/plugins/Input/mpc/translations/mpc_plugin_ru.qmbin0 -> 2230 bytes
-rw-r--r--src/plugins/Input/mpc/translations/mpc_plugin_ru.ts149
-rw-r--r--src/plugins/Input/mpc/translations/translations.qrc6
-rw-r--r--src/plugins/Input/sndfile/CMakeLists.txt74
-rw-r--r--src/plugins/Input/sndfile/decoder_sndfile.cpp282
-rw-r--r--src/plugins/Input/sndfile/decoder_sndfile.h66
-rw-r--r--src/plugins/Input/sndfile/decodersndfilefactory.cpp126
-rw-r--r--src/plugins/Input/sndfile/decodersndfilefactory.h54
-rw-r--r--src/plugins/Input/sndfile/sndfile.pro28
-rw-r--r--src/plugins/Input/vorbis/CMakeLists.txt96
-rw-r--r--src/plugins/Input/vorbis/decoder_vorbis.cpp425
-rw-r--r--src/plugins/Input/vorbis/decoder_vorbis.h63
-rw-r--r--src/plugins/Input/vorbis/decodervorbisfactory.cpp105
-rw-r--r--src/plugins/Input/vorbis/decodervorbisfactory.h54
-rw-r--r--src/plugins/Input/vorbis/detailsdialog.cpp120
-rw-r--r--src/plugins/Input/vorbis/detailsdialog.h49
-rw-r--r--src/plugins/Input/vorbis/detailsdialog.ui384
-rw-r--r--src/plugins/Input/vorbis/translations/translations.qrc6
-rw-r--r--src/plugins/Input/vorbis/translations/vorbis_plugin_ru.qmbin0 -> 2569 bytes
-rw-r--r--src/plugins/Input/vorbis/translations/vorbis_plugin_ru.ts164
-rw-r--r--src/plugins/Input/vorbis/vorbis.pro35
75 files changed, 10124 insertions, 0 deletions
diff --git a/src/plugins/Input/CMakeLists.txt b/src/plugins/Input/CMakeLists.txt
new file mode 100644
index 000000000..8114bc092
--- /dev/null
+++ b/src/plugins/Input/CMakeLists.txt
@@ -0,0 +1,49 @@
+
+SET(USE_MAD TRUE CACHE BOOL "enable/disable mad plugin")
+SET(USE_FLAC TRUE CACHE BOOL "enable/disable flac plugin")
+SET(USE_VORBIS TRUE CACHE BOOL "enable/disable ogg vorbis plugin")
+SET(USE_FFMPEG TRUE CACHE BOOL "enable/disable ffmpeg plugin")
+SET(USE_MPC TRUE CACHE BOOL "enable/disable mpc plugin")
+SET(USE_SNDFILE TRUE CACHE BOOL "enable/disable sndfile plugin")
+
+IF(USE_MAD)
+MESSAGE( STATUS "MAD ON")
+add_subdirectory(mad)
+ELSE(USE_MAD)
+MESSAGE( STATUS "MAD OFF")
+ENDIF(USE_MAD)
+
+IF(USE_FLAC)
+MESSAGE( STATUS "FLAC ON")
+add_subdirectory(flac)
+ELSE(USE_FLAC)
+MESSAGE( STATUS "FLAC OFF")
+ENDIF(USE_FLAC)
+
+IF(USE_VORBIS)
+MESSAGE( STATUS "VORBIS ON")
+add_subdirectory(vorbis)
+ELSE(USE_VORBIS)
+MESSAGE( STATUS "VORBIS OFF")
+ENDIF(USE_VORBIS)
+
+IF(USE_FFMPEG)
+MESSAGE( STATUS "FFMPEG ON")
+add_subdirectory(ffmpeg)
+ELSE(USE_FFMPEG)
+MESSAGE( STATUS "FFMPEG OFF")
+ENDIF(USE_FFMPEG)
+
+IF(USE_MPC)
+MESSAGE( STATUS "MPC ON")
+add_subdirectory(mpc)
+ELSE(USE_MPC)
+MESSAGE( STATUS "MPC OFF")
+ENDIF(USE_MPC)
+
+IF(USE_SNDFILE)
+MESSAGE( STATUS "SNDFILE ON")
+add_subdirectory(sndfile)
+ELSE(USE_SNDFILE)
+MESSAGE( STATUS "SNDFILE OFF")
+ENDIF(USE_SNDFILE)
diff --git a/src/plugins/Input/Input.pro b/src/plugins/Input/Input.pro
new file mode 100644
index 000000000..e180229cc
--- /dev/null
+++ b/src/plugins/Input/Input.pro
@@ -0,0 +1,26 @@
+include(../../../qmmp.pri)
+
+SUBDIRS += mad vorbis sndfile
+TEMPLATE = subdirs
+
+contains(CONFIG, MUSEPACK_PLUGIN){
+ SUBDIRS += mpc
+ message(***************************)
+ message(* Musepack plugin enabled *)
+ message(***************************)
+}
+
+contains(CONFIG, FLAC_PLUGIN){
+ SUBDIRS += flac
+ message(***********************)
+ message(* FLAC plugin enabled *)
+ message(***********************)
+}
+
+contains(CONFIG, FFMPEG_PLUGIN){
+ SUBDIRS += ffmpeg
+ message(*************************)
+ message(* FFMPEG plugin enabled *)
+ message(*************************)
+}
+
diff --git a/src/plugins/Input/ffmpeg/CMakeLists.txt b/src/plugins/Input/ffmpeg/CMakeLists.txt
new file mode 100644
index 000000000..1ca0d4b7a
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/CMakeLists.txt
@@ -0,0 +1,94 @@
+project(libffmpeg)
+
+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)
+# fixes ffmpeg defines
+ADD_DEFINITIONS(-D__STDC_CONSTANT_MACROS)
+
+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}/../../../)
+
+# libffmpeg and taglib
+PKGCONFIG(libavcodec LIBAVCODEC_INCLUDE_DIR LIBAVCODEC_LINK_DIR LIBAVCODEC_LINK_FLAGS LIBAVCODEC_CFLAGS)
+PKGCONFIG(libavformat LIBAVFORMAT_INCLUDE_DIR LIBAVFORMAT_LINK_DIR LIBAVFORMAT_LINK_FLAGS LIBAVFORMAT_CFLAGS)
+PKGCONFIG(taglib TAGLIB_INCLUDE_DIR TAGLIB_LINK_DIR TAGLIB_LINK_FLAGS TAGLIB_CFLAGS)
+
+IF(NOT LIBAVCODEC_LINK_FLAGS)
+ SET(LIBAVCODEC_LINK_FLAGS -lavcodec)
+ENDIF(NOT LIBAVCODEC_LINK_FLAGS)
+
+IF(NOT LIBAVFORMAT_LINK_FLAGS)
+ SET(LIBAVFORMAT_LINK_FLAGS -lavformat)
+ENDIF(NOT LIBAVFORMAT_LINK_FLAGS)
+
+IF(NOT TAGLIB_LINK_FLAGS)
+ SET(TAGLIB_LINK_FLAGS -ltag)
+ SET(TAGLIB_INCLUDE_DIR /usr/include/taglib)
+ SET(TAGLIB_CFLAGS -I/usr/include/taglib)
+ENDIF(NOT TAGLIB_LINK_FLAGS)
+
+include_directories(${FLAC_INCLUDE_DIR} ${TAGLIB_INCLUDE_DIR})
+link_directories(${FLAC_LINK_DIR} ${TAGLIB_LINK_DIR})
+
+ADD_DEFINITIONS(${LIBAVCODEC_CFLAGS})
+ADD_DEFINITIONS(${LIBAVFORMAT_CFLAGS})
+ADD_DEFINITIONS(${TAGLIB_CFLAGS})
+
+
+SET(libffmpeg_SRCS
+ decoder_ffmpeg.cpp
+ decoderffmpegfactory.cpp
+ detailsdialog.cpp
+)
+
+SET(libffmpeg_MOC_HDRS
+ decoderffmpegfactory.h
+ decoder_ffmpeg.h
+ detailsdialog.h
+)
+
+SET(libffmpeg_RCCS translations/translations.qrc)
+
+QT4_ADD_RESOURCES(libffmpeg_RCC_SRCS ${libffmpeg_RCCS})
+
+QT4_WRAP_CPP(libffmpeg_MOC_SRCS ${libffmpeg_MOC_HDRS})
+
+# user interface
+
+
+SET(libffmpeg_UIS
+ detailsdialog.ui
+)
+
+QT4_WRAP_UI(libffmpeg_UIS_H ${libffmpeg_UIS})
+# Don't forget to include output directory, otherwise
+# the UI file won't be wrapped!
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ADD_LIBRARY(ffmpeg SHARED ${libffmpeg_SRCS} ${libffmpeg_MOC_SRCS} ${libffmpeg_UIS_H}
+ ${libffmpeg_RCC_SRCS})
+target_link_libraries(ffmpeg ${QT_LIBRARIES} -lqmmp ${LIBAVCODEC_LINK_FLAGS} ${LIBAVFORMAT_LINK_FLAGS} ${TAGLIB_LINK_FLAGS} ${TAGLIB_CFLAGS})
+install(TARGETS ffmpeg DESTINATION ${LIB_DIR}/qmmp/Input PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ)
+
diff --git a/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp b/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp
new file mode 100644
index 000000000..095f818e7
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp
@@ -0,0 +1,342 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 "constants.h"
+#include "buffer.h"
+#include "output.h"
+#include "recycler.h"
+
+#include "decoder_ffmpeg.h"
+
+// Decoder class
+
+DecoderFFmpeg::DecoderFFmpeg(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o)
+ : Decoder(parent, d, i, o)
+{
+ inited = FALSE;
+ user_stop = FALSE;
+ stat = 0;
+ output_buf = 0;
+ output_bytes = 0;
+ output_at = 0;
+ bks = 0;
+ done = FALSE;
+ finish = FALSE;
+ freq = 0;
+ bitrate = 0;
+ seekTime = -1.0;
+ totalTime = 0.0;
+ chan = 0;
+ output_size = 0;
+ ic = 0;
+ wma_outbuf = 0;
+}
+
+
+DecoderFFmpeg::~DecoderFFmpeg()
+{
+ deinit();
+ if (wma_outbuf)
+ {
+ delete [] wma_outbuf;
+ wma_outbuf = 0;
+ }
+ if (output_buf)
+ delete [] output_buf;
+ output_buf = 0;
+
+ if (ic)
+ av_close_input_file(ic);
+}
+
+
+void DecoderFFmpeg::stop()
+{
+ user_stop = TRUE;
+}
+
+
+void DecoderFFmpeg::flush(bool final)
+{
+ ulong min = final ? 0 : bks;
+
+ while ((! done && ! finish) && output_bytes > min)
+ {
+ output()->recycler()->mutex()->lock ();
+
+ while ((! done && ! finish) && output()->recycler()->full())
+ {
+ mutex()->unlock();
+
+ output()->recycler()->cond()->wait(output()->recycler()->mutex());
+
+ mutex()->lock ();
+ done = user_stop;
+ }
+
+ if (user_stop || finish)
+ {
+ inited = FALSE;
+ done = TRUE;
+ }
+ else
+ {
+ output_bytes -= produceSound(output_buf, output_bytes, bitrate, chan);
+ output_size += bks;
+ output_at = output_bytes;
+ }
+
+ if (output()->recycler()->full())
+ {
+ output()->recycler()->cond()->wakeOne();
+ }
+
+ output()->recycler()->mutex()->unlock();
+ }
+}
+
+
+bool DecoderFFmpeg::initialize()
+{
+ bks = blockSize();
+ inited = user_stop = done = finish = FALSE;
+ freq = bitrate = 0;
+ stat = chan = 0;
+ output_size = 0;
+ seekTime = -1.0;
+ totalTime = 0.0;
+
+
+ if (! input())
+ {
+ error("DecoderFFmpeg: cannot initialize. No input.");
+
+ return FALSE;
+ }
+
+ if (! output_buf)
+ output_buf = new char[globalBufferSize];
+ output_at = 0;
+ output_bytes = 0;
+
+ if (! input())
+ {
+ error("DecoderFFmpeg: cannot initialize. No input.");
+
+ return FALSE;
+ }
+
+ if (! output_buf)
+ output_buf = new char[globalBufferSize];
+ output_at = 0;
+ output_bytes = 0;
+
+ QString filename = qobject_cast<QFile*>(input())->fileName ();
+ input()->close();
+ avcodec_init();
+ avcodec_register_all();
+ av_register_all();
+
+ AVCodec *codec;
+ if (av_open_input_file(&ic, filename.toLocal8Bit(), NULL,0, NULL) < 0)
+ {
+ qDebug("DecoderFFmpeg: cannot open input file");
+ return FALSE;
+ }
+ for (wma_idx = 0; wma_idx < ic->nb_streams; wma_idx++)
+ {
+ c = ic->streams[wma_idx]->codec;
+ if (c->codec_type == CODEC_TYPE_AUDIO) break;
+ }
+
+ av_find_stream_info(ic);
+
+ codec = avcodec_find_decoder(c->codec_id);
+
+ if (!codec) return FALSE;
+ if (avcodec_open(c, codec) < 0)
+ return FALSE;
+
+ totalTime = ic->duration/AV_TIME_BASE;
+
+ configure(c->sample_rate, c->channels, 16, c->bit_rate);
+
+ bitrate = c->bit_rate;
+ chan = c->channels;
+ wma_outbuf = new uint8_t[AVCODEC_MAX_AUDIO_FRAME_SIZE*sizeof(int16_t)];
+ inited = TRUE;
+ qDebug("DecoderFFmpeg: initialize succes");
+ return TRUE;
+}
+
+
+double DecoderFFmpeg::lengthInSeconds()
+{
+ if (! inited)
+ return 0;
+
+ return totalTime;
+}
+
+
+void DecoderFFmpeg::seek(double pos)
+{
+ seekTime = pos;
+}
+
+
+void DecoderFFmpeg::deinit()
+{
+ inited = user_stop = done = finish = FALSE;
+ freq = bitrate = 0;
+ stat = chan = 0;
+ output_size = 0;
+}
+
+void DecoderFFmpeg::run()
+{
+// mpc_uint32_t vbrAcc = 0;
+// mpc_uint32_t vbrUpd = 0;
+ uint8_t *inbuf_ptr;
+ int out_size, size;
+ AVPacket pkt;
+
+ mutex()->lock ();
+
+ if (! inited)
+ {
+ mutex()->unlock();
+
+ return;
+ }
+ stat = DecoderState::Decoding;
+ mutex()->unlock();
+ {
+ dispatch(DecoderState ((DecoderState::Type) stat));
+ }
+
+ while (! done && ! finish)
+ {
+ mutex()->lock ();
+ // decode
+
+ if (seekTime >= 0.0)
+ {
+ int64_t timestamp;
+ timestamp = int64_t(seekTime)*AV_TIME_BASE;
+ if (ic->start_time != AV_NOPTS_VALUE)
+ timestamp += ic->start_time;
+ av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
+ avcodec_flush_buffers(c);
+ seekTime = -1.0;
+ }
+
+ int l = 0;
+ if (av_read_frame(ic, &pkt) < 0)
+ {
+ finish = TRUE;
+ goto end;
+ }
+ size = pkt.size;
+ inbuf_ptr = pkt.data;
+
+ out_size = 0;
+
+ while (size > 0)
+ {
+ out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*sizeof(int16_t);
+ l = avcodec_decode_audio2(c, (int16_t *)(wma_outbuf), &out_size, inbuf_ptr, size);
+
+ if(l < 0)
+ goto end;
+ ffmpeg_out(out_size);
+ size -= l;
+ inbuf_ptr += l;
+ if (pkt.data)
+ av_free_packet(&pkt);
+ }
+ bitrate = c->bit_rate/1024;
+end:
+ if (finish)
+ {
+ flush(TRUE);
+
+ if (output())
+ {
+ output()->recycler()->mutex()->lock ();
+ // end of stream
+ while (! output()->recycler()->empty() && ! user_stop)
+ {
+ output()->recycler()->cond()->wakeOne();
+ mutex()->unlock();
+ output()->recycler()->cond()->wait(output()->recycler()->mutex());
+ mutex()->lock ();
+ }
+ output()->recycler()->mutex()->unlock();
+ }
+
+ done = TRUE;
+ if (! user_stop)
+ {
+ finish = TRUE;
+ }
+ }
+
+ mutex()->unlock();
+
+ }
+
+ mutex()->lock ();
+
+ if (finish)
+ stat = DecoderState::Finished;
+ else if (user_stop)
+ stat = DecoderState::Stopped;
+
+ mutex()->unlock();
+
+ {
+ dispatch(DecoderState ((DecoderState::Type) stat));
+ }
+
+ deinit();
+}
+
+void DecoderFFmpeg::ffmpeg_out(int size)
+{
+ if (size == 0)
+ return;
+ int at = 0;
+ int to_copy = 0;
+ while (size > 0 && !user_stop)
+ {
+ to_copy = qMin(int(globalBufferSize - output_at), int(size) );
+ memmove ( (char *) (output_buf + output_at), wma_outbuf + at, to_copy);
+ at += to_copy;
+ size -= to_copy;
+ output_at += to_copy;
+ output_bytes += to_copy;
+ if (output())
+ flush();
+ }
+}
diff --git a/src/plugins/Input/ffmpeg/decoder_ffmpeg.h b/src/plugins/Input/ffmpeg/decoder_ffmpeg.h
new file mode 100644
index 000000000..956e5f32b
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/decoder_ffmpeg.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+ * Copyright (C) 2006 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_ffmeg_h
+#define __decoder_ffmeg_h
+
+extern "C"{
+#include <ffmpeg/avformat.h>
+#include <ffmpeg/avcodec.h>
+}
+#include "decoder.h"
+
+class DecoderFFmpeg : public Decoder
+{
+public:
+ DecoderFFmpeg(QObject *, DecoderFactory *, QIODevice *, Output *);
+ virtual ~DecoderFFmpeg();
+
+ // Standard Decoder API
+ bool initialize();
+ double lengthInSeconds();
+ void seek(double);
+ void stop();
+
+ // Equalizer
+ bool isEQSupported() const { return FALSE; }
+ void setEQEnabled(bool) { ; }
+ void setEQGain(int) { ; }
+ void setEQBands(int[10]) { ; }
+
+
+private:
+ // thread run function
+ void run();
+ // helper functions
+ void flush(bool = FALSE);
+ void deinit();
+ void ffmpeg_out(int size);
+
+ bool inited, user_stop;
+ int stat;
+
+ // output buffer
+ char *output_buf;
+ ulong output_bytes, output_at;
+
+ AVFormatContext *ic;
+ AVCodecContext *c;
+ uint wma_st_buff, wma_idx, wma_idx2;
+ uint8_t *wma_outbuf;
+
+ unsigned int bks;
+ bool done, finish;
+ long freq, bitrate;
+ int chan;
+ unsigned long output_size;
+ double totalTime, seekTime;
+};
+
+
+#endif // __decoder_ffmpeg_h
diff --git a/src/plugins/Input/ffmpeg/decoderffmpegfactory.cpp b/src/plugins/Input/ffmpeg/decoderffmpegfactory.cpp
new file mode 100644
index 000000000..789635a15
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/decoderffmpegfactory.cpp
@@ -0,0 +1,93 @@
+#include <QtGui>
+
+extern "C"{
+#include <ffmpeg/avformat.h>
+#include <ffmpeg/avcodec.h>
+}
+
+#include "detailsdialog.h"
+#include "decoder_ffmpeg.h"
+#include "decoderffmpegfactory.h"
+
+
+// DecoderFFmpegFactory
+
+bool DecoderFFmpegFactory::supports(const QString &source) const
+{
+
+ return (source.right(4).toLower() == ".wma" || source.right(4).toLower() == ".wav");
+}
+
+bool DecoderFFmpegFactory::canDecode(QIODevice *) const
+{
+ return FALSE;
+}
+
+const DecoderProperties DecoderFFmpegFactory::properties() const
+{
+ DecoderProperties properties;
+ properties.name = tr("WMA Files");
+ properties.filter = "*.wma *.wav";
+ properties.description = tr("WMA Files");
+ //properties.contentType = "";
+ properties.hasAbout = TRUE;
+ properties.hasSettings = FALSE;
+ return properties;
+}
+
+Decoder *DecoderFFmpegFactory::create(QObject *parent, QIODevice *input,
+ Output *output)
+{
+ return new DecoderFFmpeg(parent, this, input, output);
+}
+
+FileTag *DecoderFFmpegFactory::createTag(const QString &source)
+{
+ FileTag *ftag = new FileTag();
+ avcodec_init();
+ avcodec_register_all();
+ av_register_all();
+ AVFormatContext *in;
+
+ if (av_open_input_file(&in, source.toLocal8Bit(), NULL,0, NULL) < 0)
+ return ftag;
+ av_find_stream_info(in);
+ ftag->setValue(FileTag::ALBUM, QString::fromUtf8(in->album).trimmed());
+ ftag->setValue(FileTag::ARTIST, QString::fromUtf8(in->author).trimmed());
+ ftag->setValue(FileTag::COMMENT, QString::fromUtf8(in->comment).trimmed());
+ ftag->setValue(FileTag::GENRE, QString::fromUtf8(in->genre).trimmed());
+ ftag->setValue(FileTag::TITLE, QString::fromUtf8(in->title).trimmed());
+ ftag->setValue(FileTag::YEAR, in->year);
+ ftag->setValue(FileTag::TRACK, in->track);
+ ftag->setValue(FileTag::LENGTH ,int(in->duration/AV_TIME_BASE));
+ av_close_input_file(in);
+ return ftag;
+}
+
+QObject* DecoderFFmpegFactory::showDetails(QWidget *parent, const QString &path)
+{
+ DetailsDialog *d = new DetailsDialog(parent, path);
+ d -> show();
+ return d;
+}
+
+void DecoderFFmpegFactory::showSettings(QWidget *)
+{}
+
+void DecoderFFmpegFactory::showAbout(QWidget *parent)
+{
+ QMessageBox::about (parent, tr("About FFmpeg Audio Plugin"),
+ tr("Qmmp FFmpeg Audio Plugin")+"\n"+
+ tr("Suppored formats: WMA")+"\n"+
+ tr("Writen by: Ilya Kotov <forkotov02@hotmail.ru>"));
+}
+
+QTranslator *DecoderFFmpegFactory::createTranslator(QObject *parent)
+{
+ QTranslator *translator = new QTranslator(parent);
+ QString locale = QLocale::system().name();
+ translator->load(QString(":/ffmpeg_plugin_") + locale);
+ return translator;
+}
+
+Q_EXPORT_PLUGIN(DecoderFFmpegFactory)
diff --git a/src/plugins/Input/ffmpeg/decoderffmpegfactory.h b/src/plugins/Input/ffmpeg/decoderffmpegfactory.h
new file mode 100644
index 000000000..16b6de1dd
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/decoderffmpegfactory.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 DECODERFFMPEGFACTORY_H
+#define DECODERFFMPEGFACTORY_H
+
+#include <QObject>
+#include <QString>
+#include <QIODevice>
+#include <QWidget>
+
+#include <decoder.h>
+#include <output.h>
+#include <decoderfactory.h>
+#include <filetag.h>
+
+
+
+
+class DecoderFFmpegFactory : 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/ffmpeg/detailsdialog.cpp b/src/plugins/Input/ffmpeg/detailsdialog.cpp
new file mode 100644
index 000000000..076cd6872
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/detailsdialog.cpp
@@ -0,0 +1,103 @@
+/***************************************************************************
+ * Copyright (C) 2006 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. *
+ ***************************************************************************/
+
+extern "C"
+{
+#include <ffmpeg/avformat.h>
+#include <ffmpeg/avcodec.h>
+}
+#include <QFile>
+
+#include "detailsdialog.h"
+
+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))
+ loadInfo();
+}
+
+
+DetailsDialog::~DetailsDialog()
+{}
+
+void DetailsDialog::loadInfo()
+{
+ AVFormatContext *in;
+ avcodec_init();
+ avcodec_register_all();
+ av_register_all();
+ if (av_open_input_file(&in, m_path.toLocal8Bit(), NULL,0, NULL) < 0)
+ return;
+ av_find_stream_info(in);
+ QString string = QString::fromUtf8(in->title).trimmed();
+ ui.titleLineEdit->setText(string);
+ string = QString::fromUtf8(in->author).trimmed();
+ ui.artistLineEdit->setText(string);
+ string = QString::fromUtf8(in->album).trimmed();
+ ui.albumLineEdit->setText(string);
+ string = QString::fromUtf8(in->comment).trimmed();
+ ui.commentLineEdit->setText(string);
+ string = QString("%1").arg(in->year);
+ ui.yearLineEdit->setText(string);
+ string = QString("%1").arg(in->track);
+ ui.trackLineEdit->setText(string);
+ string = QString::fromUtf8(in->genre).trimmed();
+ ui.genreLineEdit->setText(string);
+
+ QString text;
+ text = QString("%1").arg(int(in->duration/AV_TIME_BASE)/60);
+ text +=":"+QString("%1").arg(int(in->duration/AV_TIME_BASE)%60,2,10,QChar('0'));
+ ui.lengthLabel->setText(text);
+
+
+ text = QString("%1").arg(in->file_size/1024)+" "+tr("KB");
+ ui.fileSizeLabel->setText(text);
+ text = QString("%1").arg(in->bit_rate/1000);
+ ui.bitrateLabel->setText(text+" "+tr("kbps"));
+
+ AVCodecContext *c = 0;
+ uint wma_idx;
+
+ for (wma_idx = 0; wma_idx < in->nb_streams; wma_idx++)
+ {
+ c = in->streams[wma_idx]->codec;
+ if (c->codec_type == CODEC_TYPE_AUDIO) break;
+ }
+
+ if (c)
+ {
+ text = QString("%1").arg(c->sample_rate);
+ ui.sampleRateLabel->setText(text+" "+tr("Hz"));
+ text = QString("%1").arg(c->channels);
+ ui.channelsLabel->setText(text);
+ }
+
+ av_close_input_file(in);
+}
+
+
diff --git a/src/plugins/Input/ffmpeg/detailsdialog.h b/src/plugins/Input/ffmpeg/detailsdialog.h
new file mode 100644
index 000000000..258a1bd21
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/detailsdialog.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright (C) 2006 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:
+ void loadInfo();
+ Ui::DetailsDialog ui;
+ QString m_path;
+
+};
+
+#endif
diff --git a/src/plugins/Input/ffmpeg/detailsdialog.ui b/src/plugins/Input/ffmpeg/detailsdialog.ui
new file mode 100644
index 000000000..70ed57052
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/detailsdialog.ui
@@ -0,0 +1,332 @@
+<ui version="4.0" >
+ <class>DetailsDialog</class>
+ <widget class="QDialog" name="DetailsDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>449</width>
+ <height>375</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Details</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item rowspan="2" row="1" column="0" colspan="2" >
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="minimumSize" >
+ <size>
+ <width>175</width>
+ <height>16</height>
+ </size>
+ </property>
+ <property name="title" >
+ <string>ASF Info</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="4" column="1" >
+ <widget class="QLabel" name="bitrateLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <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="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="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="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="1" column="1" >
+ <widget class="QLabel" name="sampleRateLabel" >
+ <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="0" column="1" >
+ <widget class="QLabel" name="lengthLabel" >
+ <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="2" column="1" >
+ <widget class="QLabel" name="fileSizeLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" 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>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="2" colspan="2" >
+ <widget class="QGroupBox" name="groupBox_2" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>WMA Tag</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="6" column="1" colspan="2" >
+ <widget class="QPushButton" name="pushButton" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="3" >
+ <widget class="QLineEdit" name="trackLineEdit" />
+ </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="1" >
+ <widget class="QLineEdit" name="yearLineEdit" />
+ </item>
+ <item row="4" column="0" >
+ <widget class="QLabel" name="label_25" >
+ <property name="text" >
+ <string>Year:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0" >
+ <widget class="QLabel" name="label_27" >
+ <property name="text" >
+ <string>Genre:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="label_24" >
+ <property name="text" >
+ <string>Comment:</string>
+ </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_23" >
+ <property name="text" >
+ <string>Album:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_22" >
+ <property name="text" >
+ <string>Artist:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_21" >
+ <property name="text" >
+ <string>Title:</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="titleLineEdit" />
+ </item>
+ <item row="1" column="1" colspan="3" >
+ <widget class="QLineEdit" name="artistLineEdit" />
+ </item>
+ <item row="2" column="1" colspan="3" >
+ <widget class="QLineEdit" name="albumLineEdit" />
+ </item>
+ <item row="3" column="1" colspan="3" >
+ <widget class="QLineEdit" name="commentLineEdit" />
+ </item>
+ <item row="5" column="1" colspan="2" >
+ <widget class="QLineEdit" name="genreLineEdit" />
+ </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>
+ <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>
+ </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>
diff --git a/src/plugins/Input/ffmpeg/ffmpeg.pro b/src/plugins/Input/ffmpeg/ffmpeg.pro
new file mode 100644
index 000000000..7de7c7d5b
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/ffmpeg.pro
@@ -0,0 +1,35 @@
+include(../../plugins.pri)
+
+FORMS += detailsdialog.ui
+HEADERS += decoderffmpegfactory.h \
+ detailsdialog.h \
+ decoder_ffmpeg.h
+SOURCES += detailsdialog.cpp \
+ decoder_ffmpeg.cpp \
+ decoderffmpegfactory.cpp
+
+
+QMAKE_CLEAN = ../libffmpeg.so
+
+TARGET=$$PLUGINS_PREFIX/Input/ffmpeg
+QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libffmpeg.so
+
+
+INCLUDEPATH += ../../../qmmp
+CONFIG += release \
+warn_on \
+plugin \
+link_pkgconfig
+TEMPLATE = lib
+QMAKE_LIBDIR += ../../../../lib
+LIBS += -lqmmp -L/usr/lib -I/usr/include
+DEFINES += __STDC_CONSTANT_MACROS
+PKGCONFIG += libavcodec libavformat
+#TRANSLATIONS = translations/ffmpeg_plugin_ru.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/ffmpeg/translations/ffmpeg_plugin_cs.ts b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_cs.ts
new file mode 100644
index 000000000..8f686a145
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_cs.ts
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS><TS version="1.1" language="pl">
+<defaultcodec></defaultcodec>
+<context>
+ <name>DecoderFFmpegFactory</name>
+ <message>
+ <location filename="../decoderffmpegfactory.cpp" line="33"/>
+ <source>WMA Files</source>
+ <translation>Soubory WMA</translation>
+ </message>
+ <message>
+ <location filename="../decoderffmpegfactory.cpp" line="61"/>
+ <source>About FFmpeg Audio Plugin</source>
+ <translation>O pluginu FFmpeg</translation>
+ </message>
+ <message>
+ <location filename="../decoderffmpegfactory.cpp" line="62"/>
+ <source>Qmmp FFmpeg Audio Plugin</source>
+ <translation>Vstupní plugin Qmmp FFmpeg</translation>
+ </message>
+ <message>
+ <location filename="../decoderffmpegfactory.cpp" line="63"/>
+ <source>Suppored formats: WMA</source>
+ <translation>Podporované formáty: WMA</translation>
+ </message>
+ <message>
+ <location filename="../decoderffmpegfactory.cpp" line="64"/>
+ <source>Writen by: Ilya Kotov &lt;forkotov02@hotmail.ru&gt;</source>
+ <translation>Autor: Ilja Kotov &lt;forkotov02@hotmail.ru&gt;</translation>
+ </message>
+ <message>
+ <location filename="../decoderffmpegfactory.cpp" line="19"/>
+ <source>FFmpeg Plugin</source>
+ <translation>Plugin FFmpeg</translation>
+ </message>
+</context>
+<context>
+ <name>DetailsDialog</name>
+ <message>
+ <location filename="../detailsdialog.cpp" line="81"/>
+ <source>kbps</source>
+ <translation>kbps</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="95"/>
+ <source>Hz</source>
+ <translation>Hz</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="78"/>
+ <source>KB</source>
+ <translation>KB</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="13"/>
+ <source>Details</source>
+ <translation>Podrobnosti</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="70"/>
+ <source>File size:</source>
+ <translation>Velikost souboru:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="130"/>
+ <source>-</source>
+ <translation>-</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="103"/>
+ <source>Sample rate:</source>
+ <translation>Vzorkovací frakvence:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="176"/>
+ <source>Save</source>
+ <translation>Uložit</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="186"/>
+ <source>Track number:</source>
+ <translation>Číslo stopy:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="199"/>
+ <source>Year:</source>
+ <translation>Rok:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="209"/>
+ <source>Genre:</source>
+ <translation>Žánr:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="219"/>
+ <source>Comment:</source>
+ <translation>Komentář:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="229"/>
+ <source>Album:</source>
+ <translation>Album:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="239"/>
+ <source>Artist:</source>
+ <translation>Umělec:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="249"/>
+ <source>Title:</source>
+ <translation>Název:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="290"/>
+ <source>Close</source>
+ <translation>Zavřít</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="297"/>
+ <source>File path:</source>
+ <translation>Cesta k souboru:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="120"/>
+ <source>Length:</source>
+ <translation>Délka:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="83"/>
+ <source>Channels:</source>
+ <translation>Počet kanálů:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="60"/>
+ <source>Bitrate:</source>
+ <translation>Datový tok:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="31"/>
+ <source>ASF Info</source>
+ <translation>Informace ASF</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="161"/>
+ <source>WMA Tag</source>
+ <translation>WMA tag</translation>
+ </message>
+</context>
+</TS>
diff --git a/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.qm b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.qm
new file mode 100644
index 000000000..68ceb6f8b
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.qm
Binary files differ
diff --git a/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.ts b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.ts
new file mode 100644
index 000000000..a65f434f2
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.ts
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS><TS version="1.1" language="ru">
+<context>
+ <name>DecoderFFmpegFactory</name>
+ <message>
+ <location filename="../decoderffmegfactory.cpp" line="19"/>
+ <source>FFmpeg Plugin</source>
+ <translation>Модуль FFmpeg</translation>
+ </message>
+ <message>
+ <location filename="../decoderffmegfactory.cpp" line="33"/>
+ <source>WMA Files</source>
+ <translation>Файлы WMA</translation>
+ </message>
+ <message>
+ <location filename="../decoderffmegfactory.cpp" line="61"/>
+ <source>About FFmpeg Audio Plugin</source>
+ <translation>Об аудио-модуле FFmpeg</translation>
+ </message>
+ <message>
+ <location filename="../decoderffmegfactory.cpp" line="62"/>
+ <source>Qmmp FFmpeg Audio Plugin</source>
+ <translation>Аудио-модуль FFmpeg для Qmmp</translation>
+ </message>
+ <message>
+ <location filename="../decoderffmegfactory.cpp" line="63"/>
+ <source>Suppored formats: WMA</source>
+ <translation>Поддерживаемые форматы: WMA</translation>
+ </message>
+ <message>
+ <location filename="../decoderffmegfactory.cpp" line="64"/>
+ <source>Writen by: Ilya Kotov &lt;forkotov02@hotmail.ru&gt;</source>
+ <translation>Разработчик: Илья Котов &lt;forkotov02@hotmail.ru&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>DetailsDialog</name>
+ <message>
+ <location filename="../detailsdialog.cpp" line="78"/>
+ <source>KB</source>
+ <translation>Кб</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="95"/>
+ <source>Hz</source>
+ <translation>Гц</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="31"/>
+ <source>ASF Info</source>
+ <translation>Информация ASF</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="130"/>
+ <source>-</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="60"/>
+ <source>Bitrate:</source>
+ <translation>Битовая частота:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="70"/>
+ <source>File size:</source>
+ <translation>Размер файла:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="83"/>
+ <source>Channels:</source>
+ <translation>Каналов:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="103"/>
+ <source>Sample rate:</source>
+ <translation>Дискретизация:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="120"/>
+ <source>Length:</source>
+ <translation>Длительность:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="161"/>
+ <source>WMA Tag</source>
+ <translation>WMA-тег</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="176"/>
+ <source>Save</source>
+ <translation>Сохранить</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="186"/>
+ <source>Track number:</source>
+ <translation>Номер трека:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="199"/>
+ <source>Year:</source>
+ <translation>Год:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="209"/>
+ <source>Genre:</source>
+ <translation>Жанр:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="219"/>
+ <source>Comment:</source>
+ <translation>Комментарий:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="229"/>
+ <source>Album:</source>
+ <translation>Альбом:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="239"/>
+ <source>Artist:</source>
+ <translation>Исполнитель:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="249"/>
+ <source>Title:</source>
+ <translation>Название:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="290"/>
+ <source>Close</source>
+ <translation>Закрыть</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="297"/>
+ <source>File path:</source>
+ <translation>Путь к файлу:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="81"/>
+ <source>kbps</source>
+ <translation>Кб/с</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="13"/>
+ <source>Details</source>
+ <translation>Информация</translation>
+ </message>
+</context>
+</TS>
diff --git a/src/plugins/Input/ffmpeg/translations/translations.qrc b/src/plugins/Input/ffmpeg/translations/translations.qrc
new file mode 100644
index 000000000..5e15f321d
--- /dev/null
+++ b/src/plugins/Input/ffmpeg/translations/translations.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file>ffmpeg_plugin_ru.qm</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/Input/flac/CMakeLists.txt b/src/plugins/Input/flac/CMakeLists.txt
new file mode 100644
index 000000000..24041608c
--- /dev/null
+++ b/src/plugins/Input/flac/CMakeLists.txt
@@ -0,0 +1,86 @@
+project(libflac)
+
+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}/../../../)
+
+# libflac and taglib
+PKGCONFIG(flac FLAC_INCLUDE_DIR FLAC_LINK_DIR FLAC_LINK_FLAGS FLAC_CFLAGS)
+PKGCONFIG(taglib TAGLIB_INCLUDE_DIR TAGLIB_LINK_DIR TAGLIB_LINK_FLAGS TAGLIB_CFLAGS)
+
+IF(NOT FLAC_LINK_FLAGS)
+ SET(FLAC_LINK_FLAGS -lFLAC)
+ENDIF(NOT FLAC_LINK_FLAGS)
+
+IF(NOT TAGLIB_LINK_FLAGS)
+ SET(TAGLIB_LINK_FLAGS -ltag)
+ SET(TAGLIB_INCLUDE_DIR /usr/include/taglib)
+ SET(TAGLIB_CFLAGS -I/usr/include/taglib)
+ENDIF(NOT TAGLIB_LINK_FLAGS)
+
+include_directories(${FLAC_INCLUDE_DIR} ${TAGLIB_INCLUDE_DIR})
+link_directories(${FLAC_LINK_DIR} ${TAGLIB_LINK_DIR})
+
+ADD_DEFINITIONS(${FLAC_CFLAGS})
+ADD_DEFINITIONS(${TAGLIB_CFLAGS})
+
+
+SET(libflac_SRCS
+ decoder_flac.cpp
+ decoderflacfactory.cpp
+ detailsdialog.cpp
+)
+
+SET(libflac_MOC_HDRS
+ decoderflacfactory.h
+ decoder_flac.h
+ detailsdialog.h
+)
+
+SET(libflac_RCCS translations/translations.qrc)
+
+QT4_ADD_RESOURCES(libflac_RCC_SRCS ${libflac_RCCS})
+
+QT4_WRAP_CPP(libflac_MOC_SRCS ${libflac_MOC_HDRS})
+
+# user interface
+
+
+SET(libflac_UIS
+ detailsdialog.ui
+)
+
+QT4_WRAP_UI(libflac_UIS_H ${libflac_UIS})
+# Don't forget to include output directory, otherwise
+# the UI file won't be wrapped!
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ADD_LIBRARY(flac SHARED ${libflac_SRCS} ${libflac_MOC_SRCS} ${libflac_UIS_H}
+ ${libflac_RCC_SRCS})
+target_link_libraries(flac ${QT_LIBRARIES} -lqmmp ${FLAC_LINK_FLAGS} ${FLAC_CFLAGS} ${TAGLIB_LINK_FLAGS} ${TAGLIB_CFLAGS})
+install(TARGETS flac DESTINATION ${LIB_DIR}/qmmp/Input PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ)
+
diff --git a/src/plugins/Input/flac/decoder_flac.cpp b/src/plugins/Input/flac/decoder_flac.cpp
new file mode 100644
index 000000000..b2a895bca
--- /dev/null
+++ b/src/plugins/Input/flac/decoder_flac.cpp
@@ -0,0 +1,567 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 "constants.h"
+#include "buffer.h"
+#include "output.h"
+#include "recycler.h"
+
+#include <QObject>
+#include <QIODevice>
+#include <FLAC/all.h>
+#include "decoder_flac.h"
+
+
+
+static size_t pack_pcm_signed (FLAC__byte *data,
+ const FLAC__int32 * const input[],
+ unsigned wide_samples,
+ unsigned channels, unsigned bps)
+{
+ FLAC__byte * const start = data;
+ FLAC__int32 sample;
+ const FLAC__int32 *input_;
+ unsigned samples, channel;
+ unsigned bytes_per_sample;
+ unsigned incr;
+
+ if (bps == 24)
+ bps = 32; /* we encode to 32-bit words */
+ bytes_per_sample = bps / 8;
+ incr = bytes_per_sample * channels;
+
+ for (channel = 0; channel < channels; channel++)
+ {
+ samples = wide_samples;
+ data = start + bytes_per_sample * channel;
+ input_ = input[channel];
+
+ while (samples--)
+ {
+ sample = *input_++;
+
+ switch (bps)
+ {
+ case 8:
+ data[0] = sample;
+ break;
+ case 16:
+ data[1] = (FLAC__byte)(sample >> 8);
+ data[0] = (FLAC__byte)sample;
+ break;
+ case 32:
+ data[3] = (FLAC__byte)(sample >> 16);
+ data[2] = (FLAC__byte)(sample >> 8);
+ data[1] = (FLAC__byte)sample;
+ data[0] = 0;
+ break;
+ }
+
+ data += incr;
+ }
+ }
+
+ return wide_samples * channels * bytes_per_sample;
+}
+
+static int flac_decode (void *void_data, char *buf, int buf_len) /*,
+ struct sound_params *sound_params)*/
+{
+ //struct flac_data *data = (struct flac_data *)void_data;
+ DecoderFLAC *dflac = (DecoderFLAC *) void_data;
+ unsigned to_copy;
+ int bytes_per_sample;
+ FLAC__uint64 decode_position;
+
+ bytes_per_sample = dflac->data()->bits_per_sample / 8;
+
+ /*switch (bytes_per_sample) {
+ case 1:
+ sound_params->fmt = SFMT_S8;
+ break;
+ case 2:
+ sound_params->fmt = SFMT_S16 | SFMT_LE;
+ break;
+ case 3:
+ sound_params->fmt = SFMT_S32 | SFMT_LE;
+ break;
+ }
+
+ sound_params->rate = data->sample_rate;
+ sound_params->channels = data->channels;*/
+
+ //decoder_error_clear (&data->error);
+
+ if (!dflac->data()->sample_buffer_fill)
+ {
+
+ if (FLAC__stream_decoder_get_state(dflac->data()->decoder)
+ == FLAC__STREAM_DECODER_END_OF_STREAM)
+ {
+ return 0;
+ }
+
+ if (!FLAC__stream_decoder_process_single(
+ dflac->data()->decoder))
+ {
+ return 0;
+ }
+
+ /* Count the bitrate */
+ if (!FLAC__stream_decoder_get_decode_position(
+ dflac->data()->decoder, &decode_position))
+ decode_position = 0;
+ if (decode_position > dflac->data()->last_decode_position)
+ {
+ int bytes_per_sec = bytes_per_sample * dflac->data()->sample_rate
+ * dflac->data()->channels;
+
+ dflac->data()->bitrate = int(((float)decode_position -
+ dflac->data()->last_decode_position) * 8.0 *
+ bytes_per_sec /
+ dflac->data()->sample_buffer_fill / 1000);
+ }
+
+ dflac->data()->last_decode_position = decode_position;
+ }
+
+ to_copy = qMin((unsigned)buf_len, dflac->data()->sample_buffer_fill);
+ memcpy (buf, dflac->data()->sample_buffer, to_copy);
+ memmove (dflac->data()->sample_buffer,
+ dflac->data()->sample_buffer + to_copy,
+ dflac->data()->sample_buffer_fill - to_copy);
+ dflac->data()->sample_buffer_fill -= to_copy;
+ return to_copy;
+}
+
+
+static FLAC__StreamDecoderReadStatus
+flac_callback_read (const FLAC__StreamDecoder *, FLAC__byte buffer[],
+ size_t *bytes, void *client_data)
+{
+ DecoderFLAC *dflac = (DecoderFLAC *) client_data;
+ qint64 res;
+
+ res = dflac->input()->read((char *)buffer, *bytes);
+
+ if (res > 0)
+ {
+ *bytes = res;
+ return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+ }
+ if (res == 0)
+ {
+ *bytes = res;
+ return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+ }
+
+ return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+
+}
+
+static FLAC__StreamDecoderWriteStatus
+flac_callback_write (const FLAC__StreamDecoder *, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+{
+ DecoderFLAC *dflac = (DecoderFLAC *) client_data;
+ const unsigned wide_samples = frame->header.blocksize;
+
+ if (dflac->data()->abort)
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+
+
+ dflac->data()->sample_buffer_fill = pack_pcm_signed (
+ dflac->data()->sample_buffer,
+ buffer, wide_samples,
+ dflac->data()->channels,
+ dflac->data()->bits_per_sample);
+
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+static FLAC__StreamDecoderTellStatus
+flac_callback_tell (const FLAC__StreamDecoder *, FLAC__uint64 *offset, void *client_data)
+{
+ DecoderFLAC *dflac = (DecoderFLAC *) client_data;
+ *offset = dflac->input()->pos ();
+ return FLAC__STREAM_DECODER_TELL_STATUS_OK;
+}
+
+static FLAC__StreamDecoderSeekStatus
+flac_callback_seek (const FLAC__StreamDecoder *, FLAC__uint64 offset, void *client_data)
+{
+ DecoderFLAC *dflac = (DecoderFLAC *) client_data;
+
+ return dflac->input()->seek(offset)
+ ? FLAC__STREAM_DECODER_SEEK_STATUS_OK
+ : FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+}
+
+static FLAC__StreamDecoderLengthStatus
+flac_callback_length (const FLAC__StreamDecoder *, FLAC__uint64 *stream_length, void *client_data)
+{
+ DecoderFLAC *dflac = (DecoderFLAC *) client_data;
+ *stream_length = dflac->input()->size();
+ return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+}
+
+static void
+flac_callback_metadata (const FLAC__StreamDecoder *, const FLAC__StreamMetadata *metadata, void *client_data)
+{
+ DecoderFLAC *dflac = (DecoderFLAC *) client_data;
+
+ if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
+ {
+ qDebug ("DecoderFLAC: getting metadata info");
+
+ dflac->data()->total_samples =
+ (unsigned)(metadata->data.stream_info.total_samples
+ & 0xffffffff);
+ dflac->data()->bits_per_sample =
+ metadata->data.stream_info.bits_per_sample;
+ dflac->data()->channels = metadata->data.stream_info.channels;
+ dflac->data()->sample_rate = metadata->data.stream_info.sample_rate;
+ dflac->data()->length = dflac->data()->total_samples / dflac->data()->sample_rate;
+ }
+}
+
+static FLAC__bool
+flac_callback_eof (const FLAC__StreamDecoder *, void *)
+{
+ return FALSE;
+}
+
+static void
+flac_callback_error (const FLAC__StreamDecoder *, FLAC__StreamDecoderErrorStatus status, void *client_data)
+{}
+
+// Decoder class
+
+DecoderFLAC::DecoderFLAC(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o)
+ : Decoder(parent, d, i, o)
+{
+ inited = FALSE;
+ user_stop = FALSE;
+ stat = 0;
+ output_buf = 0;
+ output_bytes = 0;
+ output_at = 0;
+ bks = 0;
+ done = FALSE;
+ finish = FALSE;
+ len = 0;
+ freq = 0;
+ bitrate = 0;
+ seekTime = -1.0;
+ totalTime = 0.0;
+ chan = 0;
+ output_size = 0;
+ m_data = 0;
+
+
+
+
+}
+
+
+DecoderFLAC::~DecoderFLAC()
+{
+ deinit();
+ if (data())
+ {
+ if (data()->decoder)
+ FLAC__stream_decoder_delete (data()->decoder);
+ delete data();
+ m_data = 0;
+ }
+
+ if (output_buf)
+ delete [] output_buf;
+ output_buf = 0;
+}
+
+
+void DecoderFLAC::stop()
+{
+ user_stop = TRUE;
+}
+
+
+void DecoderFLAC::flush(bool final)
+{
+ //qDebug("DecoderFLAC: flush()");
+ ulong min = final ? 0 : bks;
+
+ while ((! done && ! finish) && output_bytes > min)
+ {
+ output()->recycler()->mutex()->lock();
+
+ while ((! done && ! finish) && output()->recycler()->full())
+ {
+ mutex()->unlock();
+
+ output()->recycler()->cond()->wait(output()->recycler()->mutex());
+
+ mutex()->lock();
+ done = user_stop;
+ }
+
+ if (user_stop || finish)
+ {
+ inited = FALSE;
+ done = TRUE;
+ }
+ else
+ {
+ output_bytes -= produceSound(output_buf, output_bytes, bitrate, chan);
+ output_size += bks;
+ output_at = output_bytes;
+ }
+
+ if (output()->recycler()->full())
+ {
+ output()->recycler()->cond()->wakeOne();
+ }
+
+ output()->recycler()->mutex()->unlock();
+ }
+}
+
+
+bool DecoderFLAC::initialize()
+{
+ bks = blockSize();
+ inited = user_stop = done = finish = FALSE;
+ len = freq = bitrate = 0;
+ stat = chan = 0;
+ output_size = 0;
+ seekTime = -1.0;
+ totalTime = 0.0;
+
+
+ if (! input())
+ {
+ error("DecoderFLAC: cannot initialize. No input.");
+
+ return FALSE;
+ }
+
+ if (! output_buf)
+ output_buf = new char[globalBufferSize];
+ output_at = 0;
+ output_bytes = 0;
+
+ if (! input()->isOpen())
+ {
+ if (! input()->open(QIODevice::ReadOnly))
+ {
+
+ return FALSE;
+ }
+ }
+
+
+ if (! input())
+ {
+ error("DecoderFLAC: cannot initialize. No input.");
+
+ return FALSE;
+ }
+
+ if (! output_buf)
+ output_buf = new char[globalBufferSize];
+ output_at = 0;
+ output_bytes = 0;
+
+ if (! input()->isOpen())
+ {
+ if (! input()->open(QIODevice::ReadOnly))
+ {
+ return FALSE;
+ }
+ }
+ if (!m_data)
+ {
+ m_data = new flac_data;
+ m_data->decoder = NULL;
+ }
+
+ m_data->bitrate = -1;
+ m_data->abort = 0;
+ m_data->sample_buffer_fill = 0;
+ m_data->last_decode_position = 0;
+ if (!m_data->decoder)
+ {
+ qDebug("DecoderFLAC: creating FLAC__StreamDecoder");
+ m_data->decoder = FLAC__stream_decoder_new ();
+ }
+ qDebug("DecoderFLAC: setting callbacks");
+ if (FLAC__stream_decoder_init_stream(
+ m_data->decoder,
+ flac_callback_read,
+ flac_callback_seek,
+ flac_callback_tell,
+ flac_callback_length,
+ flac_callback_eof,
+ flac_callback_write,
+ flac_callback_metadata,
+ flac_callback_error,
+ this) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+ {
+ data()->ok = 0;
+ return FALSE;
+ }
+
+ if (!FLAC__stream_decoder_process_until_end_of_metadata(
+ data()->decoder))
+ {
+ data()->ok = 0;
+ return FALSE;
+ }
+ chan = data()->channels;
+ configure(data()->sample_rate, data()->channels, 16, bitrate);
+ totalTime = data()->length;
+
+ inited = TRUE;
+ qDebug("DecoderFLAC: initialize succes");
+ return TRUE;
+}
+
+
+double DecoderFLAC::lengthInSeconds()
+{
+ if (! inited)
+ return 0;
+
+ return totalTime;
+}
+
+
+void DecoderFLAC::seek(double pos)
+{
+ seekTime = pos;
+}
+
+
+void DecoderFLAC::deinit()
+{
+ if(data())
+ FLAC__stream_decoder_finish (data()->decoder);
+ inited = user_stop = done = finish = FALSE;
+ len = freq = bitrate = 0;
+ stat = chan = 0;
+ output_size = 0;
+}
+
+void DecoderFLAC::run()
+{
+ mutex()->lock ();
+
+ if (! inited)
+ {
+ mutex()->unlock();
+
+ return;
+ }
+ stat = DecoderState::Decoding;
+ mutex()->unlock();
+ {
+ dispatch(DecoderState ((DecoderState::Type) stat));
+ }
+
+ while (! done && ! finish)
+ {
+ mutex()->lock ();
+ // decode
+
+ if (seekTime >= 0.0)
+ {
+ FLAC__uint64 target_sample;
+
+ target_sample = (FLAC__uint64)((seekTime/(double)data()->length) *
+ (double)data()->total_samples);
+
+ FLAC__stream_decoder_seek_absolute(data()->decoder,
+ target_sample);
+ seekTime = -1.0;
+ }
+ len = flac_decode (this, (char *) (output_buf + output_at), bks);
+
+ if (len > 0)
+ {
+ bitrate = data()->bitrate;
+ output_at += len;
+ 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() && ! user_stop)
+ {
+ output()->recycler()->cond()->wakeOne();
+ mutex()->unlock();
+ output()->recycler()->cond()->wait(output()->recycler()->mutex());
+ mutex()->lock ();
+ }
+ output()->recycler()->mutex()->unlock();
+ }
+
+ done = TRUE;
+ if (! user_stop)
+ {
+ finish = TRUE;
+ }
+ }
+ else
+ {
+ // error in read
+ error("DecoderFLAC: Error while decoding stream, File appears to be "
+ "corrupted");
+
+ finish = TRUE;
+ }
+
+ mutex()->unlock();
+ }
+
+ mutex()->lock ();
+
+ if (finish)
+ stat = DecoderState::Finished;
+ else if (user_stop)
+ stat = DecoderState::Stopped;
+
+ mutex()->unlock();
+
+ {
+ dispatch(DecoderState ((DecoderState::Type) stat));
+ }
+
+ deinit();
+}
diff --git a/src/plugins/Input/flac/decoder_flac.h b/src/plugins/Input/flac/decoder_flac.h
new file mode 100644
index 000000000..4c85176ed
--- /dev/null
+++ b/src/plugins/Input/flac/decoder_flac.h
@@ -0,0 +1,124 @@
+/***************************************************************************
+ * Copyright (C) 2006 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_flac_h
+#define __decoder_flac_h
+
+class DecoderOgg;
+
+#include "decoder.h"
+
+#include <FLAC/all.h>
+
+#define MAX_SUPPORTED_CHANNELS 2
+
+#define SAMPLES_PER_WRITE 512
+#define SAMPLE_BUFFER_SIZE ((FLAC__MAX_BLOCK_SIZE + SAMPLES_PER_WRITE) * MAX_SUPPORTED_CHANNELS * (32/8))
+
+struct flac_data
+{
+ //FLAC__SeekableStreamDecoder *decoder;
+ FLAC__StreamDecoder *decoder;
+ struct io_stream *stream;
+ int bitrate;
+ int abort; /* abort playing (due to an error) */
+
+ unsigned length;
+ unsigned total_samples;
+
+ FLAC__byte sample_buffer[SAMPLE_BUFFER_SIZE];
+ unsigned sample_buffer_fill;
+
+ /* sound parameters */
+ unsigned bits_per_sample;
+ unsigned sample_rate;
+ unsigned channels;
+
+ FLAC__uint64 last_decode_position;
+
+ int ok; /* was this stream successfully opened? */
+ //struct decoder_error error;
+};
+
+class DecoderFLAC : public Decoder
+{
+public:
+ DecoderFLAC(QObject *, DecoderFactory *, QIODevice *, Output *);
+ virtual ~DecoderFLAC();
+
+ // Standard Decoder API
+ bool initialize();
+ double lengthInSeconds();
+ void seek(double);
+ void stop();
+
+ // Equalizer
+ bool isEQSupported() const
+ {
+ return FALSE;
+ }
+ void setEQEnabled(bool)
+ {
+ ;
+ }
+ void setEQGain(int)
+ {
+ ;
+ }
+ void setEQBands(int[10])
+ {
+ ;
+ }
+
+ struct flac_data *data()
+ {
+ return m_data;
+ }
+
+
+private:
+ // thread run function
+ void run();
+ struct flac_data *m_data;
+ // helper functions
+ void flush(bool = FALSE);
+ void deinit();
+
+ bool inited, user_stop;
+ int stat;
+
+ // output buffer
+ char *output_buf;
+ ulong output_bytes, output_at;
+
+ // FLAC Decoder
+ //FLAC__SeekableStreamDecoder *m_flacDecoder;
+ FLAC__StreamDecoder *m_flacDecoder;
+
+ unsigned int bks;
+ bool done, finish;
+ long len, freq, bitrate;
+ int chan;
+ unsigned long output_size;
+ double totalTime, seekTime;
+};
+
+
+#endif // __decoder_flac_h
diff --git a/src/plugins/Input/flac/decoderflacfactory.cpp b/src/plugins/Input/flac/decoderflacfactory.cpp
new file mode 100644
index 000000000..5abb60b39
--- /dev/null
+++ b/src/plugins/Input/flac/decoderflacfactory.cpp
@@ -0,0 +1,95 @@
+#include <QtGui>
+#include <taglib/tag.h>
+#include <taglib/fileref.h>
+
+#include "detailsdialog.h"
+#include "decoder_flac.h"
+#include "decoderflacfactory.h"
+
+
+// DecoderFLACFactory
+
+bool DecoderFLACFactory::supports(const QString &source) const
+{
+
+ return (source.right(5).toLower() == ".flac");
+}
+
+bool DecoderFLACFactory::canDecode(QIODevice *input) const
+{
+ return FALSE;
+}
+
+const DecoderProperties DecoderFLACFactory::properties() const
+{
+ DecoderProperties properties;
+ properties.name = tr("FLAC Plugin");
+ properties.filter = "*.flac";
+ properties.description = tr("FLAC Files");
+ //properties.contentType = ;
+ properties.hasAbout = TRUE;
+ properties.hasSettings = FALSE;
+ return properties;
+}
+
+Decoder *DecoderFLACFactory::create(QObject *parent, QIODevice *input,
+ Output *output)
+{
+ return new DecoderFLAC(parent, this, input, output);
+}
+
+FileTag *DecoderFLACFactory::createTag(const QString &source)
+{
+ FileTag *ftag = new FileTag();
+
+ TagLib::FileRef fileRef(source.toLocal8Bit ());
+ TagLib::Tag *tag = fileRef.tag();
+
+ if (tag && !tag->isEmpty())
+ {
+ ftag->setValue(FileTag::ALBUM,
+ QString::fromUtf8(tag->album().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::ARTIST,
+ QString::fromUtf8(tag->artist().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::COMMENT,
+ QString::fromUtf8(tag->comment().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::GENRE,
+ QString::fromUtf8(tag->genre().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::TITLE,
+ QString::fromUtf8(tag->title().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::YEAR, tag->year());
+ ftag->setValue(FileTag::TRACK, tag->track());
+ }
+
+ if (fileRef.audioProperties())
+ ftag->setValue(FileTag::LENGTH, fileRef.audioProperties()->length());
+
+ return ftag;
+}
+
+QObject* DecoderFLACFactory::showDetails(QWidget *parent, const QString &path)
+{
+ DetailsDialog *d = new DetailsDialog(parent, path);
+ d -> show();
+ return d;
+}
+
+void DecoderFLACFactory::showSettings(QWidget *)
+{}
+
+void DecoderFLACFactory::showAbout(QWidget *parent)
+{
+ QMessageBox::about (parent, tr("About FLAC Audio Plugin"),
+ tr("Qmmp FLAC Audio Plugin")+"\n"+
+ tr("Writen by: Ilya Kotov <forkotov02@hotmail.ru>"));
+}
+
+QTranslator *DecoderFLACFactory::createTranslator(QObject *parent)
+{
+ QTranslator *translator = new QTranslator(parent);
+ QString locale = QLocale::system().name();
+ translator->load(QString(":/flac_plugin_") + locale);
+ return translator;
+}
+
+Q_EXPORT_PLUGIN(DecoderFLACFactory)
diff --git a/src/plugins/Input/flac/decoderflacfactory.h b/src/plugins/Input/flac/decoderflacfactory.h
new file mode 100644
index 000000000..586bc3b33
--- /dev/null
+++ b/src/plugins/Input/flac/decoderflacfactory.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 DECODERFLACFACTORY_H
+#define DECODERFLACFACTORY_H
+
+#include <QObject>
+#include <QString>
+#include <QIODevice>
+#include <QWidget>
+
+#include <decoder.h>
+#include <output.h>
+#include <decoderfactory.h>
+#include <filetag.h>
+
+
+
+
+class DecoderFLACFactory : 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/flac/detailsdialog.cpp b/src/plugins/Input/flac/detailsdialog.cpp
new file mode 100644
index 000000000..2826b6cdb
--- /dev/null
+++ b/src/plugins/Input/flac/detailsdialog.cpp
@@ -0,0 +1,118 @@
+/***************************************************************************
+ * Copyright (C) 2006 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/flacfile.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))
+ {
+ loadFLACInfo();
+ loadTag();
+ }
+}
+
+
+DetailsDialog::~DetailsDialog()
+{}
+
+void DetailsDialog::loadFLACInfo()
+{
+ TagLib::FLAC::File f (m_path.toLocal8Bit());
+ //l.label
+ //ui. f.audioProperties()->level();
+ 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()->sampleWidth());
+ ui.sampleWidthLabel->setText(text+" "+tr("bits"));
+ 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/flac/detailsdialog.h b/src/plugins/Input/flac/detailsdialog.h
new file mode 100644
index 000000000..80c17544c
--- /dev/null
+++ b/src/plugins/Input/flac/detailsdialog.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 loadFLACInfo();
+ void loadTag();
+ Ui::DetailsDialog ui;
+ QString m_path;
+
+};
+
+#endif
diff --git a/src/plugins/Input/flac/detailsdialog.ui b/src/plugins/Input/flac/detailsdialog.ui
new file mode 100644
index 000000000..5ea739953
--- /dev/null
+++ b/src/plugins/Input/flac/detailsdialog.ui
@@ -0,0 +1,349 @@
+<ui version="4.0" >
+ <class>DetailsDialog</class>
+ <widget class="QDialog" name="DetailsDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>449</width>
+ <height>375</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Details</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item rowspan="2" row="1" column="0" colspan="2" >
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="minimumSize" >
+ <size>
+ <width>175</width>
+ <height>16</height>
+ </size>
+ </property>
+ <property name="title" >
+ <string>FLAC Info</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <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>Sample width:</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="sampleWidthLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="3" >
+ <widget class="QLineEdit" name="pathLineEdit" >
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <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="2" column="3" >
+ <widget class="QPushButton" name="pushButton_3" >
+ <property name="text" >
+ <string>Close</string>
+ </property>
+ </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="1" column="2" colspan="2" >
+ <widget class="QGroupBox" name="groupBox_2" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>FLAC Tag</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="6" column="1" colspan="2" >
+ <widget class="QPushButton" name="saveButton" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="3" >
+ <widget class="QLineEdit" name="trackLineEdit" />
+ </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="1" >
+ <widget class="QLineEdit" name="yearLineEdit" />
+ </item>
+ <item row="4" column="0" >
+ <widget class="QLabel" name="label_25" >
+ <property name="text" >
+ <string>Year:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0" >
+ <widget class="QLabel" name="label_27" >
+ <property name="text" >
+ <string>Genre:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="label_24" >
+ <property name="text" >
+ <string>Comment:</string>
+ </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_23" >
+ <property name="text" >
+ <string>Album:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_22" >
+ <property name="text" >
+ <string>Artist:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_21" >
+ <property name="text" >
+ <string>Title:</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="titleLineEdit" />
+ </item>
+ <item row="1" column="1" colspan="3" >
+ <widget class="QLineEdit" name="artistLineEdit" />
+ </item>
+ <item row="2" column="1" colspan="3" >
+ <widget class="QLineEdit" name="albumLineEdit" />
+ </item>
+ <item row="3" column="1" colspan="3" >
+ <widget class="QLineEdit" name="commentLineEdit" />
+ </item>
+ <item row="5" column="1" colspan="2" >
+ <widget class="QLineEdit" name="genreLineEdit" />
+ </item>
+ </layout>
+ </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>
diff --git a/src/plugins/Input/flac/flac.pro b/src/plugins/Input/flac/flac.pro
new file mode 100644
index 000000000..4ab46c296
--- /dev/null
+++ b/src/plugins/Input/flac/flac.pro
@@ -0,0 +1,36 @@
+# ???? ?????? ? KDevelop ?????????? qmake.
+# -------------------------------------------
+# ?????????? ???????????? ???????? ???????? ???????: ./Plugins/Input/flac
+# ???? - ??????????:
+
+include(../../plugins.pri)
+
+FORMS += detailsdialog.ui
+HEADERS += decoderflacfactory.h \
+ decoder_flac.h \
+ detailsdialog.h
+SOURCES += decoder_flac.cpp \
+ decoderflacfactory.cpp \
+ detailsdialog.cpp
+
+TARGET=$$PLUGINS_PREFIX/Input/flac
+QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libflac.so
+
+INCLUDEPATH += ../../../qmmp
+CONFIG += release \
+warn_on \
+plugin \
+link_pkgconfig
+TEMPLATE = lib
+QMAKE_LIBDIR += ../../../../lib
+LIBS += -lqmmp -L/usr/lib -I/usr/include
+PKGCONFIG += taglib flac
+#TRANSLATIONS = translations/flac_plugin_ru.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/flac/translations/flac_plugin_ru.qm b/src/plugins/Input/flac/translations/flac_plugin_ru.qm
new file mode 100644
index 000000000..fbd97d091
--- /dev/null
+++ b/src/plugins/Input/flac/translations/flac_plugin_ru.qm
Binary files differ
diff --git a/src/plugins/Input/flac/translations/flac_plugin_ru.ts b/src/plugins/Input/flac/translations/flac_plugin_ru.ts
new file mode 100644
index 000000000..a1e9b98b7
--- /dev/null
+++ b/src/plugins/Input/flac/translations/flac_plugin_ru.ts
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS><TS version="1.1" language="ru">
+<context>
+ <name>DecoderFLACFactory</name>
+ <message>
+ <location filename="../decoderflacfactory.cpp" line="21"/>
+ <source>FLAC Plugin</source>
+ <translation>Модуль FLAC</translation>
+ </message>
+ <message>
+ <location filename="../decoderflacfactory.cpp" line="35"/>
+ <source>FLAC Files</source>
+ <translation>Файлы FLAC</translation>
+ </message>
+ <message>
+ <location filename="../decoderflacfactory.cpp" line="63"/>
+ <source>About FLAC Audio Plugin</source>
+ <translation>Об аудио-модуле FLAC</translation>
+ </message>
+ <message>
+ <location filename="../decoderflacfactory.cpp" line="64"/>
+ <source>Qmmp FLAC Audio Plugin</source>
+ <translation>Аудио-модуль FLAC для Qmmp</translation>
+ </message>
+ <message>
+ <location filename="../decoderflacfactory.cpp" line="65"/>
+ <source>Writen by: Ilya Kotov &lt;forkotov02@hotmail.ru&gt;</source>
+ <translation>Разработчик: Илья Котов &lt;forkotov02@hotmail.ru&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>DetailsDialog</name>
+ <message>
+ <location filename="../detailsdialog.cpp" line="54"/>
+ <source>Hz</source>
+ <translation>Гц</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="60"/>
+ <source>bits</source>
+ <translation>бит</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="31"/>
+ <source>FLAC Info</source>
+ <translation>Информация FLAC</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="160"/>
+ <source>-</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="63"/>
+ <source>Length:</source>
+ <translation>Длительность:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="80"/>
+ <source>Sample rate:</source>
+ <translation>Частота сэмплов:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="100"/>
+ <source>Channels:</source>
+ <translation>Каналов:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="113"/>
+ <source>File size:</source>
+ <translation>Размер файла:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="123"/>
+ <source>Bitrate:</source>
+ <translation>Битовая частота:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="150"/>
+ <source>Sample width:</source>
+ <translation>Ширина кадра:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="177"/>
+ <source>File path:</source>
+ <translation>Путь к файлу:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="187"/>
+ <source>Close</source>
+ <translation>Закрыть</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="215"/>
+ <source>FLAC Tag</source>
+ <translation>FLAC-тег</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="230"/>
+ <source>Save</source>
+ <translation>Сохранить</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="240"/>
+ <source>Track number:</source>
+ <translation>Номер трека:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="253"/>
+ <source>Year:</source>
+ <translation>Год:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="263"/>
+ <source>Genre:</source>
+ <translation>Жанр:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="273"/>
+ <source>Comment:</source>
+ <translation>Комментарий:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="283"/>
+ <source>Album:</source>
+ <translation>Альбом:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="293"/>
+ <source>Artist:</source>
+ <translation>Исполнитель:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="303"/>
+ <source>Title:</source>
+ <translation>Название:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="58"/>
+ <source>kbps</source>
+ <translation>Кб/с</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="61"/>
+ <source>KB</source>
+ <translation>Кб</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="13"/>
+ <source>Details</source>
+ <translation>Информация</translation>
+ </message>
+</context>
+</TS>
diff --git a/src/plugins/Input/flac/translations/translations.qrc b/src/plugins/Input/flac/translations/translations.qrc
new file mode 100644
index 000000000..cd630dfce
--- /dev/null
+++ b/src/plugins/Input/flac/translations/translations.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file>flac_plugin_ru.qm</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/Input/mad/CMakeLists.txt b/src/plugins/Input/mad/CMakeLists.txt
new file mode 100644
index 000000000..3e4dfa9d0
--- /dev/null
+++ b/src/plugins/Input/mad/CMakeLists.txt
@@ -0,0 +1,90 @@
+project(libmad)
+
+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}/../../../)
+
+# libmad and taglib
+PKGCONFIG(mad MAD_INCLUDE_DIR MAD_LINK_DIR MAD_LINK_FLAGS MAD_CFLAGS)
+PKGCONFIG(taglib TAGLIB_INCLUDE_DIR TAGLIB_LINK_DIR TAGLIB_LINK_FLAGS TAGLIB_CFLAGS)
+
+IF(NOT MAD_LINK_FLAGS)
+ MESSAGE("Can not find mad.pc")
+ SET(MAD_LINK_FLAGS -lmad)
+ENDIF(NOT MAD_LINK_FLAGS)
+
+IF(NOT TAGLIB_LINK_FLAGS)
+ SET(TAGLIB_LINK_FLAGS -ltag)
+ SET(TAGLIB_INCLUDE_DIR /usr/include/taglib)
+ SET(TAGLIB_CFLAGS -I/usr/include/taglib)
+ENDIF(NOT TAGLIB_LINK_FLAGS)
+
+include_directories(${MAD_INCLUDE_DIR} ${TAGLIB_INCLUDE_DIR})
+link_directories(${MAD_LINK_DIR} ${TAGLIB_LINK_DIR})
+
+#ADD_DEFINITIONS(${MAD_CFLAGS})
+ADD_DEFINITIONS(${TAGLIB_CFLAGS})
+
+
+SET(libmad_SRCS
+ decoder_mad.cpp
+ decodermadfactory.cpp
+ detailsdialog.cpp
+ settingsdialog.cpp
+)
+
+SET(libmad_MOC_HDRS
+ settingsdialog.h
+ decodermadfactory.h
+ decoder_mad.h
+ detailsdialog.h
+)
+
+SET(libmad_RCCS translations/translations.qrc)
+
+QT4_ADD_RESOURCES(libmad_RCC_SRCS ${libmad_RCCS})
+
+QT4_WRAP_CPP(libmad_MOC_SRCS ${libmad_MOC_HDRS})
+
+# user interface
+
+
+SET(libmad_UIS
+ detailsdialog.ui
+ settingsdialog.ui
+)
+
+QT4_WRAP_UI(libmad_UIS_H ${libmad_UIS})
+# Don't forget to include output directory, otherwise
+# the UI file won't be wrapped!
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ADD_LIBRARY(mad SHARED ${libmad_SRCS} ${libmad_MOC_SRCS} ${libmad_UIS_H}
+ ${libmad_RCC_SRCS})
+
+target_link_libraries(mad ${QT_LIBRARIES} -lqmmp ${MAD_LINK_FLAGS} ${TAGLIB_LINK_FLAGS} ${TAGLIB_CFLAGS})
+install(TARGETS mad DESTINATION ${LIB_DIR}/qmmp/Input PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ)
diff --git a/src/plugins/Input/mad/decoder_mad.cpp b/src/plugins/Input/mad/decoder_mad.cpp
new file mode 100644
index 000000000..6b4c2569a
--- /dev/null
+++ b/src/plugins/Input/mad/decoder_mad.cpp
@@ -0,0 +1,572 @@
+#include <QtGui>
+
+#include "decoder_mad.h"
+#include "constants.h"
+#include "buffer.h"
+#include "output.h"
+
+#include <math.h>
+#include <stdio.h>
+
+# define XING_MAGIC (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g')
+
+
+DecoderMAD::DecoderMAD(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o)
+ : Decoder(parent, d, i, o)
+{
+ inited = false;
+ user_stop = false;
+ done = false;
+ finish = false;
+ derror = false;
+ eof = false;
+ useeq = false;
+ totalTime = 0.;
+ seekTime = -1.;
+ channels = 0;
+ bks = 0;
+ bitrate = 0;
+ freq = 0;
+ len = 0;
+ input_buf = 0;
+ input_bytes = 0;
+ output_buf = 0;
+ output_bytes = 0;
+ output_at = 0;
+ output_size = 0;
+}
+
+DecoderMAD::~DecoderMAD()
+{
+ wait();
+ deinit();
+ mutex()->lock();
+ if (input_buf)
+ {
+ qDebug("DecoderMAD: deleting input_buf");
+ delete [] input_buf;
+ }
+ input_buf = 0;
+
+ if (output_buf)
+ {
+ qDebug("DecoderMAD: deleting output_buf");
+ delete [] output_buf;
+ }
+ output_buf = 0;
+ mutex()->unlock();
+}
+
+bool DecoderMAD::initialize()
+{
+ bks = blockSize();
+
+ inited = false;
+ user_stop = false;
+ done = false;
+ finish = false;
+ derror = false;
+ eof = false;
+ totalTime = 0.;
+ seekTime = -1.;
+ channels = 0;
+ bitrate = 0;
+ freq = 0;
+ len = 0;
+ input_bytes = 0;
+ output_bytes = 0;
+ output_at = 0;
+ output_size = 0;
+
+ if (! input())
+ {
+ error("DecoderMAD: cannot initialize. No input.");
+ return FALSE;
+ }
+
+ if (! input_buf)
+ input_buf = new char[globalBufferSize];
+
+ if (! output_buf)
+ output_buf = new char[globalBufferSize];
+
+ if (! input()->isOpen())
+ {
+ if (! input()->open(QIODevice::ReadOnly))
+ {
+ error("DecoderMAD: Failed to open input. Error " +
+ QString::number(input()->isOpen()) + ".");
+ return FALSE;
+ }
+ }
+
+ mad_stream_init(&stream);
+ mad_frame_init(&frame);
+ mad_synth_init(&synth);
+
+ if (! findHeader())
+ {
+ qDebug("DecoderMAD: Cannot find a valid MPEG header.");
+ return FALSE;
+ }
+ configure(freq, channels, 16, bitrate);
+
+ inited = TRUE;
+ return TRUE;
+}
+
+
+void DecoderMAD::deinit()
+{
+ if(!inited)
+ return;
+
+ mad_synth_finish(&synth);
+ mad_frame_finish(&frame);
+ mad_stream_finish(&stream);
+
+ inited = false;
+ user_stop = false;
+ done = false;
+ finish = false;
+ derror = false;
+ eof = false;
+ useeq = false;
+ totalTime = 0.;
+ seekTime = -1.;
+ channels = 0;
+ bks = 0;
+ bitrate = 0;
+ freq = 0;
+ len = 0;
+ input_bytes = 0;
+ output_bytes = 0;
+ output_at = 0;
+ output_size = 0;
+}
+
+bool DecoderMAD::findXingHeader(struct mad_bitptr ptr, unsigned int bitlen)
+{
+ if (bitlen < 64 || mad_bit_read(&ptr, 32) != XING_MAGIC)
+ goto fail;
+
+ xing.flags = mad_bit_read(&ptr, 32);
+ bitlen -= 64;
+
+ if (xing.flags & XING_FRAMES)
+ {
+ if (bitlen < 32)
+ goto fail;
+
+ xing.frames = mad_bit_read(&ptr, 32);
+ bitlen -= 32;
+ }
+
+ if (xing.flags & XING_BYTES)
+ {
+ if (bitlen < 32)
+ goto fail;
+
+ xing.bytes = mad_bit_read(&ptr, 32);
+ bitlen -= 32;
+ }
+
+ if (xing.flags & XING_TOC)
+ {
+ int i;
+
+ if (bitlen < 800)
+ goto fail;
+
+ for (i = 0; i < 100; ++i)
+ xing.toc[i] = mad_bit_read(&ptr, 8);
+
+ bitlen -= 800;
+ }
+
+ if (xing.flags & XING_SCALE)
+ {
+ if (bitlen < 32)
+ goto fail;
+
+ xing.scale = mad_bit_read(&ptr, 32);
+ bitlen -= 32;
+ }
+
+ return true;
+
+fail:
+ xing.flags = 0;
+ xing.frames = 0;
+ xing.bytes = 0;
+ xing.scale = 0;
+ return false;
+}
+
+bool DecoderMAD::findHeader()
+{
+ bool result = false;
+ int count = 0;
+
+ while (1)
+ {
+ if (input_bytes < globalBufferSize)
+ {
+ int bytes = input()->read(input_buf + input_bytes,
+ globalBufferSize - input_bytes);
+ if (bytes <= 0)
+ {
+ if (bytes == -1)
+ result = false;
+ ;
+ break;
+ }
+ input_bytes += bytes;
+ }
+
+ mad_stream_buffer(&stream, (unsigned char *) input_buf, input_bytes);
+
+ bool done = false;
+ while (! done)
+ {
+ if (mad_frame_decode(&frame, &stream) != -1)
+ done = true;
+ else if (!MAD_RECOVERABLE(stream.error))
+ {
+ qWarning("DecoderMAD: Can't decode frame");
+ break;
+ }
+
+ count++;
+ }
+
+ findXingHeader(stream.anc_ptr, stream.anc_bitlen);
+ result = done;
+ if ((stream.error != MAD_ERROR_BUFLEN))
+ break;
+
+ input_bytes = &input_buf[input_bytes] - (char *) stream.next_frame;
+ memmove(input_buf, stream.next_frame, input_bytes);
+ }
+
+ if (result && count)
+ {
+ freq = frame.header.samplerate;
+ channels = MAD_NCHANNELS(&frame.header);
+ bitrate = frame.header.bitrate / 1000;
+ calcLength(&frame.header);
+ }
+
+ return result;
+}
+
+void DecoderMAD::calcLength(struct mad_header *header)
+{
+ if (! input() || input()->isSequential())
+ return;
+
+ totalTime = 0.;
+ if (xing.flags & XING_FRAMES)
+ {
+ mad_timer_t timer;
+
+ timer = header->duration;
+ mad_timer_multiply(&timer, xing.frames);
+
+ totalTime = double(mad_timer_count(timer, MAD_UNITS_MILLISECONDS)) / 1000.;
+ }
+ else if (header->bitrate > 0)
+ totalTime = input()->size() * 8 / header->bitrate;
+}
+
+double DecoderMAD::lengthInSeconds()
+{
+ if (! inited)
+ return 0.;
+ return totalTime;
+}
+
+void DecoderMAD::seek(double pos)
+{
+ seekTime = pos;
+}
+
+void DecoderMAD::stop()
+{
+ user_stop = TRUE;
+}
+
+void DecoderMAD::flush(bool final)
+{
+ ulong min = final ? 0 : bks;
+
+ while ((! done && ! finish) && output_bytes > min)
+ {
+ output()->recycler()->mutex()->lock();
+
+ while ((! done && ! finish) && output()->recycler()->full())
+ {
+ mutex()->unlock();
+ output()->recycler()->cond()->wait(output()->recycler()->mutex());
+
+ mutex()->lock();
+ done = user_stop;
+ }
+
+ if (user_stop || finish)
+ {
+ inited = FALSE;
+ done = TRUE;
+ }
+ else
+ {
+ output_bytes -= produceSound(output_buf, output_bytes, bitrate, channels);
+ output_size += bks;
+ output_at = output_bytes;
+ }
+
+ if (output()->recycler()->full())
+ {
+ output()->recycler()->cond()->wakeOne();
+ }
+
+ output()->recycler()->mutex()->unlock();
+ }
+}
+
+void DecoderMAD::run()
+{
+ mutex()->lock();
+
+ if (! inited)
+ {
+ mutex()->unlock();
+ return;
+ }
+
+ DecoderState::Type stat = DecoderState::Decoding;
+
+ mutex()->unlock();
+
+ dispatch(stat);
+
+ while (! done && ! finish && ! derror)
+ {
+ mutex()->lock();
+
+ if (seekTime >= 0.0)
+ {
+ long seek_pos = long(seekTime * input()->size() / totalTime);
+ input()->seek(seek_pos);
+ output_size = long(seekTime) * long(freq * channels * 16 / 2);
+ input_bytes = 0;
+ output_at = 0;
+ output_bytes = 0;
+ eof = false;
+ }
+
+ finish = eof;
+
+ if (! eof)
+ {
+ if (stream.next_frame && seekTime == -1.)
+ {
+ input_bytes = &input_buf[input_bytes] - (char *) stream.next_frame;
+ memmove(input_buf, stream.next_frame, input_bytes);
+ }
+
+ if (input_bytes < globalBufferSize)
+ {
+ int len = input()->read((char *) input_buf + input_bytes,
+ globalBufferSize - input_bytes);
+
+ if (len == 0)
+ {
+ eof = true;
+ }
+ else if (len < 0)
+ {
+ derror = true;
+ break;
+ }
+
+ input_bytes += len;
+ }
+
+ mad_stream_buffer(&stream, (unsigned char *) input_buf, input_bytes);
+ }
+
+ seekTime = -1.;
+
+ mutex()->unlock();
+
+ // decode
+ while (! done && ! finish && ! derror)
+ {
+ if (mad_frame_decode(&frame, &stream) == -1)
+ {
+ if (stream.error == MAD_ERROR_BUFLEN)
+ break;
+
+ // error in decoding
+ if (! MAD_RECOVERABLE(stream.error))
+ {
+ derror = true;
+ break;
+ }
+ continue;
+ }
+
+ mutex()->lock();
+
+ if (seekTime >= 0.)
+ {
+ mutex()->unlock();
+ break;
+ }
+
+ if (useeq)
+ {
+ unsigned int nch, ch, ns, s, sb;
+
+ nch = MAD_NCHANNELS(&frame.header);
+ ns = MAD_NSBSAMPLES(&frame.header);
+
+ for (ch = 0; ch < nch; ++ch)
+ for (s = 0; s < ns; ++s)
+ for (sb = 0; sb < 32; ++sb)
+ frame.sbsample[ch][s][sb] =
+ mad_f_mul(frame.sbsample[ch][s][sb], eqbands[sb]);
+ }
+
+ mad_synth_frame(&synth, &frame);
+ madOutput();
+ mutex()->unlock();
+ }
+ }
+
+ mutex()->lock();
+
+ if (! user_stop && eof)
+ {
+ flush(TRUE);
+
+ if (output())
+ {
+ output()->recycler()->mutex()->lock();
+ // end of stream
+ while (! output()->recycler()->empty() && ! user_stop)
+ {
+ output()->recycler()->cond()->wakeOne();
+ mutex()->unlock();
+ output()->recycler()->cond()->wait(output()->recycler()->mutex());
+ mutex()->lock();
+ }
+ output()->recycler()->mutex()->unlock();
+ }
+
+ done = TRUE;
+ if (! user_stop)
+ finish = TRUE;
+ }
+
+ if (finish)
+ stat = DecoderState::Finished;
+ else if (user_stop)
+ stat = DecoderState::Stopped;
+
+ mutex()->unlock();
+
+ dispatch(stat);
+
+ if (input())
+ input()->close();
+ deinit();
+
+}
+
+static inline signed int scale(mad_fixed_t sample)
+{
+ /* round */
+ sample += (1L << (MAD_F_FRACBITS - 16));
+
+ /* clip */
+ if (sample >= MAD_F_ONE)
+ sample = MAD_F_ONE - 1;
+ else if (sample < -MAD_F_ONE)
+ sample = -MAD_F_ONE;
+
+ /* quantize */
+ return sample >> (MAD_F_FRACBITS + 1 - 16);
+}
+
+static inline signed long fix_sample(unsigned int bits, mad_fixed_t sample)
+{
+ mad_fixed_t quantized, check;
+ // clip
+ quantized = sample;
+ check = (sample >> MAD_F_FRACBITS) + 1;
+ if (check & ~1)
+ {
+ if (sample >= MAD_F_ONE)
+ quantized = MAD_F_ONE - 1;
+ else if (sample < -MAD_F_ONE)
+ quantized = -MAD_F_ONE;
+ }
+ // quantize
+ quantized &= ~((1L << (MAD_F_FRACBITS + 1 - bits)) - 1);
+ // scale
+ return quantized >> (MAD_F_FRACBITS + 1 - bits);
+}
+
+enum mad_flow DecoderMAD::madOutput()
+{
+ unsigned int samples, channels;
+ mad_fixed_t const *left, *right;
+
+ samples = synth.pcm.length;
+ channels = synth.pcm.channels;
+ left = synth.pcm.samples[0];
+ right = synth.pcm.samples[1];
+
+
+ bitrate = frame.header.bitrate / 1000;
+ done = user_stop;
+
+ while (samples-- && !user_stop)
+ {
+ signed int sample;
+
+ if (output_bytes + 4096 > globalBufferSize)
+ flush();
+
+ sample = fix_sample(16, *left++);
+ *(output_buf + output_at++) = ((sample >> 0) & 0xff);
+ *(output_buf + output_at++) = ((sample >> 8) & 0xff);
+ output_bytes += 2;
+
+ if (channels == 2)
+ {
+ sample = fix_sample(16, *right++);
+ *(output_buf + output_at++) = ((sample >> 0) & 0xff);
+ *(output_buf + output_at++) = ((sample >> 8) & 0xff);
+ output_bytes += 2;
+ }
+ }
+
+ if (done || finish)
+ {
+ return MAD_FLOW_STOP;
+ }
+
+ return MAD_FLOW_CONTINUE;
+}
+
+enum mad_flow DecoderMAD::madError(struct mad_stream *stream,
+ struct mad_frame *)
+{
+ if (MAD_RECOVERABLE(stream->error))
+ return MAD_FLOW_CONTINUE;
+ qFatal("MADERROR!\n");
+ return MAD_FLOW_STOP;
+}
diff --git a/src/plugins/Input/mad/decoder_mad.h b/src/plugins/Input/mad/decoder_mad.h
new file mode 100644
index 000000000..ecbb160cb
--- /dev/null
+++ b/src/plugins/Input/mad/decoder_mad.h
@@ -0,0 +1,95 @@
+// Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com>
+//
+// Use, modification and distribution is allowed without limitation,
+// warranty, or liability of any kind.
+//
+
+#ifndef __decoder_mad_h
+#define __decoder_mad_h
+
+class DecoderMAD;
+
+#include "decoder.h"
+#include "decodermadfactory.h"
+
+extern "C" {
+#include <mad.h>
+}
+
+
+class DecoderMAD : public Decoder
+{
+public:
+ DecoderMAD(QObject *parent = 0, DecoderFactory *d = 0,
+ QIODevice *i = 0, Output *o = 0);
+ virtual ~DecoderMAD();
+
+ // standard decoder API
+ bool initialize();
+ double lengthInSeconds();
+ void seek(double);
+ void stop();
+
+ // Equalizer
+ //bool isEQSupported() const { return TRUE; }
+ //void setEQEnabled(bool);
+ //void setEQ(const EqPreset &);
+
+ static const int maxDecodeRetries;
+ static const int maxFrameSize;
+ static const int maxFrameCheck;
+ static const int initialFrameSize;
+
+
+private:
+ // thread run function
+ void run();
+
+ enum mad_flow madOutput();
+ enum mad_flow madError(struct mad_stream *, struct mad_frame *);
+
+ // helper functions
+ void flush(bool = FALSE);
+ void deinit();
+ bool findHeader();
+ bool findXingHeader(struct mad_bitptr, unsigned int);
+ void calcLength(struct mad_header *);
+
+ bool inited, user_stop, done, finish, derror, eof, useeq;
+ double totalTime, seekTime;
+ int channels;
+ long bitrate, freq, len;
+ unsigned int bks;
+ mad_fixed_t eqbands[32];
+
+ // file input buffer
+ char *input_buf;
+ unsigned long input_bytes;
+
+ // output buffer
+ char *output_buf;
+ unsigned long output_bytes, output_at, output_size;
+
+ // MAD decoder
+ struct {
+ int flags;
+ unsigned long frames;
+ unsigned long bytes;
+ unsigned char toc[100];
+ long scale;
+ } xing;
+
+ enum {
+ XING_FRAMES = 0x0001,
+ XING_BYTES = 0x0002,
+ XING_TOC = 0x0004,
+ XING_SCALE = 0x0008
+ };
+
+ struct mad_stream stream;
+ struct mad_frame frame;
+ struct mad_synth synth;
+};
+
+
+#endif // __decoder_mad_h
diff --git a/src/plugins/Input/mad/decodermadfactory.cpp b/src/plugins/Input/mad/decodermadfactory.cpp
new file mode 100644
index 000000000..8bb04aca1
--- /dev/null
+++ b/src/plugins/Input/mad/decodermadfactory.cpp
@@ -0,0 +1,188 @@
+#include <QtGui>
+#include <QDialog>
+#include <QMessageBox>
+#include <mad.h>
+#include <taglib/tag.h>
+#include <taglib/fileref.h>
+#include <taglib/id3v1tag.h>
+#include <taglib/id3v2tag.h>
+#include <taglib/apetag.h>
+#include <taglib/tfile.h>
+#include <taglib/mpegfile.h>
+
+#include "detailsdialog.h"
+#include "settingsdialog.h"
+#include "decoder_mad.h"
+#include "decodermadfactory.h"
+
+// DecoderMADFactory
+
+bool DecoderMADFactory::supports(const QString &source) const
+{
+ QString ext = source.right(4).toLower();
+ return ext == ".mp1" || ext == ".mp2" || ext == ".mp3";
+}
+
+bool DecoderMADFactory::canDecode(QIODevice *input) const
+{
+ char buf[16 * 512];
+
+ if (input->peek(buf,sizeof(buf)) == sizeof(buf))
+ {
+ struct mad_stream stream;
+ struct mad_header header;
+ int dec_res;
+
+ mad_stream_init (&stream);
+ mad_header_init (&header);
+ mad_stream_buffer (&stream, (unsigned char *) buf, sizeof(buf));
+ stream.error = MAD_ERROR_NONE;
+
+ while ((dec_res = mad_header_decode(&header, &stream)) == -1
+ && MAD_RECOVERABLE(stream.error))
+ ;
+ return dec_res != -1 ? TRUE: FALSE;
+ }
+ return FALSE;
+}
+
+const DecoderProperties DecoderMADFactory::properties() const
+{
+ DecoderProperties properties;
+ properties.name = tr("MPEG Plugin");
+ properties.filter = "*.mp1 *.mp2 *.mp3";
+ properties.description = tr("MPEG Files");
+ properties.contentType = "audio/mp3;audio/mpeg";
+ properties.hasAbout = TRUE;
+ properties.hasSettings = TRUE;
+ return properties;
+}
+
+Decoder *DecoderMADFactory::create(QObject *parent, QIODevice *input, Output *output)
+{
+ return new DecoderMAD(parent, this, input, output);
+}
+
+FileTag *DecoderMADFactory::createTag(const QString &source)
+{
+ FileTag *ftag = new FileTag();
+ TagLib::Tag *tag = 0;
+ TagLib::MPEG::File fileRef(source.toLocal8Bit ());
+
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ settings.beginGroup("MAD");
+ QTextCodec *codec_v1 =
+ QTextCodec::codecForName(settings.value("ID3v1_encoding","UTF-8" )
+ .toByteArray ());
+ QTextCodec *codec_v2 =
+ QTextCodec::codecForName(settings.value("ID3v2_encoding","UTF-8" )
+ .toByteArray ());
+ if (!codec_v1)
+ codec_v1 = QTextCodec::codecForName ("UTF-8");
+ if (!codec_v2)
+ codec_v2 = QTextCodec::codecForName ("UTF-8");
+
+ QTextCodec *codec = 0;
+
+ uint tag_array[3];
+ tag_array[0] = settings.value("tag_1", SettingsDialog::ID3v2).toInt();
+ tag_array[1] = settings.value("tag_2", SettingsDialog::Disabled).toInt();
+ tag_array[2] = settings.value("tag_3", SettingsDialog::Disabled).toInt();
+
+
+ for (int i = 0; i < 3; ++i)
+ {
+ switch ((uint) tag_array[i])
+ {
+ case SettingsDialog::ID3v1:
+ {
+ codec = codec_v1;
+ tag = fileRef.ID3v1Tag();
+ break;
+ }
+ case SettingsDialog::ID3v2:
+ {
+ codec = codec_v2;
+ tag = fileRef.ID3v2Tag();
+ break;
+ }
+ case SettingsDialog::APE:
+ {
+ codec = QTextCodec::codecForName ("UTF-8");
+ tag = fileRef.APETag();
+ break;
+ }
+ case SettingsDialog::Disabled:
+ {
+ break;
+ }
+ }
+ if(tag && !tag->isEmpty())
+ break;
+ }
+ settings.endGroup();
+
+ if (tag && codec)
+ {
+ bool utf = codec->name ().contains("UTF");
+ TagLib::String album = tag->album();
+ TagLib::String artist = tag->artist();
+ TagLib::String comment = tag->comment();
+ TagLib::String genre = tag->genre();
+ TagLib::String title = tag->title();
+
+ ftag->setValue(FileTag::ALBUM,
+ codec->toUnicode(album.toCString(utf)).trimmed());
+ ftag->setValue(FileTag::ARTIST,
+ codec->toUnicode(artist.toCString(utf)).trimmed());
+ ftag->setValue(FileTag::COMMENT,
+ codec->toUnicode(comment.toCString(utf)).trimmed());
+ ftag->setValue(FileTag::GENRE,
+ codec->toUnicode(genre.toCString(utf)).trimmed());
+ ftag->setValue(FileTag::TITLE,
+ codec->toUnicode(title.toCString(utf)).trimmed());
+ ftag->setValue(FileTag::YEAR,
+ tag->year());
+ ftag->setValue(FileTag::TRACK,
+ tag->track());
+ }
+ if (fileRef.audioProperties())
+ ftag->setValue(FileTag::LENGTH,fileRef.audioProperties()->length());
+ return ftag;
+}
+
+QObject* DecoderMADFactory::showDetails(QWidget *parent, const QString &path)
+{
+ DetailsDialog *d = new DetailsDialog(parent, path);
+ d -> show();
+ return d;
+}
+
+void DecoderMADFactory::showSettings(QWidget *parent)
+{
+ SettingsDialog *s = new SettingsDialog(parent);
+ s -> show();
+}
+
+void DecoderMADFactory::showAbout(QWidget *parent)
+{
+ QMessageBox::about (parent, tr("About MPEG Audio Plugin"),
+ tr("Qmmp MPEG Audio Plugin")+"\n"+
+ tr("Compiled against libmad version:")+" "+
+ QString("%1.%2.%3%4").arg(MAD_VERSION_MAJOR)
+ .arg(MAD_VERSION_MINOR)
+ .arg(MAD_VERSION_PATCH).arg(MAD_VERSION_EXTRA)+"\n"+
+ tr("Writen by: Ilya Kotov <forkotov02@hotmail.ru>")+"\n"+
+ tr("Source code based on mq3 progect")
+ );
+}
+
+QTranslator *DecoderMADFactory::createTranslator(QObject *parent)
+{
+ QTranslator *translator = new QTranslator(parent);
+ QString locale = QLocale::system().name();
+ translator->load(QString(":/mad_plugin_") + locale);
+ return translator;
+}
+
+Q_EXPORT_PLUGIN(DecoderMADFactory)
diff --git a/src/plugins/Input/mad/decodermadfactory.h b/src/plugins/Input/mad/decodermadfactory.h
new file mode 100644
index 000000000..2c7da8e47
--- /dev/null
+++ b/src/plugins/Input/mad/decodermadfactory.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 DECODERMADFACTORY_H
+#define DECODERMADFACTORY_H
+
+#include <QObject>
+#include <QString>
+#include <QIODevice>
+#include <QWidget>
+
+#include <decoder.h>
+#include <output.h>
+#include <decoderfactory.h>
+
+
+
+
+class DecoderMADFactory : 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/mad/detailsdialog.cpp b/src/plugins/Input/mad/detailsdialog.cpp
new file mode 100644
index 000000000..af9b466cd
--- /dev/null
+++ b/src/plugins/Input/mad/detailsdialog.cpp
@@ -0,0 +1,294 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 <QTextCodec>
+#include <QSettings>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+
+#include <taglib/tag.h>
+#include <taglib/fileref.h>
+#include <taglib/id3v1tag.h>
+#include <taglib/id3v2tag.h>
+#include <taglib/apetag.h>
+#include <taglib/tfile.h>
+#include <taglib/mpegfile.h>
+#include <taglib/mpegheader.h>
+#include <taglib/mpegproperties.h>
+
+#include "detailsdialog.h"
+
+DetailsDialog::DetailsDialog(QWidget *parent, const QString &path)
+ : QDialog(parent)
+{
+ ui.setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose);
+ m_path = path;
+ setWindowTitle (path.section('/',-1));
+ ui.pathLineEdit->setText(m_path);
+
+ if (!QFile::exists(m_path))
+ return;
+
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ settings.beginGroup("MAD");
+ m_codec_v1 =
+ QTextCodec::codecForName(settings.value("ID3v1_encoding","UTF-8" )
+ .toByteArray ());
+ m_codec_v2 =
+ QTextCodec::codecForName(settings.value("ID3v2_encoding","UTF-8" )
+ .toByteArray ());
+ if (!m_codec_v1)
+ m_codec_v1 = QTextCodec::codecForName ("UTF-8");
+ if (!m_codec_v2)
+ m_codec_v2 = QTextCodec::codecForName ("UTF-8");
+
+ QString tag_name = settings.value("current_tag","ID3v2").toString ();
+
+ if (tag_name == "ID3v1")
+ ui.id3v1RadioButton->setChecked(TRUE);
+ else if (tag_name == "ID3v2")
+ ui.id3v2RadioButton->setChecked(TRUE);
+ else if (tag_name == "APE")
+ ui.apeRadioButton->setChecked(TRUE);
+ else
+ ui.id3v2RadioButton->setChecked(TRUE);
+
+ settings.endGroup();
+
+ loadMPEGInfo();
+ QFileInfo info(m_path);
+ m_rw = info.isWritable();
+ loadTag();
+ connect(ui.saveButton, SIGNAL(clicked()), SLOT(save()));
+ connect(ui.createButton, SIGNAL(clicked()), SLOT(create()));
+ connect(ui.deleteButton, SIGNAL(clicked()), SLOT(deleteTag()));
+ connect(ui.id3v1RadioButton, SIGNAL(clicked()), SLOT(loadTag()));
+ connect(ui.id3v2RadioButton, SIGNAL(clicked()), SLOT(loadTag()));
+ connect(ui.apeRadioButton, SIGNAL(clicked()), SLOT(loadTag()));
+}
+
+
+DetailsDialog::~DetailsDialog()
+{}
+
+void DetailsDialog::loadMPEGInfo()
+{
+ TagLib::MPEG::File f (m_path.toLocal8Bit());
+ //l.label
+ //ui. f.audioProperties()->level();
+ QString text;
+ text = QString("%1").arg(f.audioProperties()->layer());
+ ui.levelLabel->setText("MPEG layer "+text); //TODO: add MPEG version
+ text = QString("%1").arg(f.audioProperties()->bitrate());
+ ui.bitRateLabel->setText(text+" "+tr("kbps"));
+ text = QString("%1").arg(f.audioProperties()->sampleRate());
+ ui.sampleRateLabel->setText(text+" "+tr("Hz"));
+ switch (f.audioProperties()->channelMode())
+ {
+ case TagLib::MPEG::Header::Stereo:
+ ui.modeLabel->setText("Stereo");
+ break;
+ case TagLib::MPEG::Header::JointStereo:
+ ui.modeLabel->setText("Joint stereo");
+ break;
+ case TagLib::MPEG::Header::DualChannel:
+ ui.modeLabel->setText("Dual channel");
+ break;
+ case TagLib::MPEG::Header::SingleChannel:
+ ui.modeLabel->setText("Single channel");
+ break;
+ }
+ text = QString("%1 "+tr("KB")).arg(f.length()/1024);
+ ui.fileSizeLabel->setText(text);
+ /*if (f.audioProperties()->protectionEnabled())
+ ui.errProtectionLabel->setText(tr("Yes"));
+ else
+ ui.errProtectionLabel->setText(tr("No"));*/
+ if (f.audioProperties()->isCopyrighted())
+ ui.copyrightLabel->setText(tr("Yes"));
+ else
+ ui.copyrightLabel->setText(tr("No"));
+ if (f.audioProperties()->isOriginal())
+ ui.originalLabel->setText(tr("Yes"));
+ else
+ ui.originalLabel->setText(tr("No"));
+}
+
+void DetailsDialog::loadTag()
+{
+ TagLib::MPEG::File f (m_path.toLocal8Bit());
+ QTextCodec *codec = QTextCodec::codecForName ("UTF-8");
+ TagLib::Tag *tag = 0;
+
+ if (selectedTag() == TagLib::MPEG::File::ID3v1)
+ {
+ tag = f.ID3v1Tag();
+ codec = m_codec_v1;
+ ui.tagGroupBox->setTitle(tr("ID3v1 Tag"));
+ }
+ else if (selectedTag() == TagLib::MPEG::File::ID3v2)
+ {
+ tag = f.ID3v2Tag();
+ codec = m_codec_v2;
+ ui.tagGroupBox->setTitle(tr("ID3v2 Tag"));
+ }
+ else if (selectedTag() == TagLib::MPEG::File::APE)
+ {
+ ui.tagGroupBox->setTitle(tr("APE Tag"));
+ tag = f.APETag();
+ }
+ ui.saveButton->setEnabled(tag && m_rw);
+ ui.createButton->setEnabled(!tag && m_rw);
+ ui.deleteButton->setEnabled(tag && m_rw);
+ ui.tagsWidget->setEnabled(tag);
+ //clear old values
+ ui.titleLineEdit->clear();
+ ui.artistLineEdit->clear();
+ ui.albumLineEdit->clear();
+ ui.commentLineEdit->clear();
+ ui.yearLineEdit->clear();
+ ui.trackLineEdit->clear();
+ ui.genreLineEdit->clear();
+
+ if (tag)
+ {
+ bool utf = codec->name().contains("UTF");
+ TagLib::String title = tag->title();
+ TagLib::String artist = tag->artist();
+ TagLib::String album = tag->album();
+ TagLib::String comment = tag->comment();
+ TagLib::String genre = tag->genre();
+ QString string = codec->toUnicode(title.toCString(utf)).trimmed();
+ ui.titleLineEdit->setText(string);
+ string = codec->toUnicode(artist.toCString(utf)).trimmed();
+ ui.artistLineEdit->setText(string);
+ string = codec->toUnicode(album.toCString(utf)).trimmed();
+ ui.albumLineEdit->setText(string);
+ string = codec->toUnicode(comment.toCString(utf)).trimmed();
+ ui.commentLineEdit->setText(string);
+ string = QString("%1").arg(tag->year());
+ ui.yearLineEdit->setText(string);
+ string = QString("%1").arg(tag->track());
+ ui.trackLineEdit->setText(string);
+ string = codec->toUnicode(genre.toCString(utf)).trimmed();
+ ui.genreLineEdit->setText(string);
+ }
+}
+
+void DetailsDialog::save()
+{
+ TagLib::MPEG::File* f = new TagLib::MPEG::File(m_path.toLocal8Bit());
+ TagLib::String::Type type = TagLib::String::Latin1;
+
+ QTextCodec *codec = 0;
+ TagLib::Tag *tag = 0;
+
+ if (selectedTag() == TagLib::MPEG::File::ID3v1)
+ {
+ codec = m_codec_v1;
+ tag = f->ID3v1Tag(TRUE);
+ if (codec->name().contains("UTF"))
+ {
+ delete f;
+ loadTag();
+ }
+ }
+ if (selectedTag() == TagLib::MPEG::File::ID3v2)
+ {
+ codec = m_codec_v2;
+ tag = f->ID3v2Tag(TRUE);
+ if (codec->name().contains("UTF"))
+ {
+ TagLib::ID3v2::FrameFactory *factory = TagLib::ID3v2::FrameFactory::instance();
+ factory->setDefaultTextEncoding(TagLib::String::UTF8);
+ f->setID3v2FrameFactory(factory);
+ type = TagLib::String::UTF8;
+ }
+ }
+ if (selectedTag() == TagLib::MPEG::File::APE)
+ {
+ codec = QTextCodec::codecForName ("UTF-8");
+ tag = f->APETag(TRUE);
+ type = TagLib::String::UTF8;
+ }
+
+ tag->setTitle(TagLib::String(codec->fromUnicode(ui.titleLineEdit->text()).constData(), type));
+ tag->setArtist(TagLib::String(codec->fromUnicode(ui.artistLineEdit->text()).constData(), type));
+ tag->setAlbum(TagLib::String(codec->fromUnicode(ui.albumLineEdit->text()).constData(), type));
+ tag->setComment(TagLib::String(codec->fromUnicode(ui.commentLineEdit->text()).constData(), type));
+ tag->setGenre(TagLib::String(codec->fromUnicode(ui.genreLineEdit->text()).constData(), type));
+ tag->setYear(ui.yearLineEdit->text().toUInt());
+ tag->setTrack(ui.trackLineEdit->text().toUInt());
+
+ f->save(selectedTag(), FALSE);
+ delete f;
+ loadTag();
+}
+
+void DetailsDialog::create()
+{
+ TagLib::MPEG::File *f = new TagLib::MPEG::File (m_path.toLocal8Bit());
+ TagLib::Tag *tag = 0;
+ if (selectedTag() == TagLib::MPEG::File::ID3v1)
+ tag = f->ID3v1Tag(TRUE);
+ else if (selectedTag() == TagLib::MPEG::File::ID3v2)
+ tag = f->ID3v2Tag(TRUE);
+ else if (selectedTag() == TagLib::MPEG::File::APE)
+ tag = f->APETag(TRUE);
+
+ f->save(selectedTag(), FALSE);
+ delete f;
+ loadTag();
+ ui.tagsWidget->setEnabled(TRUE);
+ ui.saveButton->setEnabled(m_rw);
+}
+
+void DetailsDialog::deleteTag()
+{
+ TagLib::MPEG::File *f = new TagLib::MPEG::File (m_path.toLocal8Bit());
+ f->strip(selectedTag());
+ delete f;
+ loadTag();
+}
+
+uint DetailsDialog::selectedTag()
+{
+ if (ui.id3v1RadioButton->isChecked())
+ return TagLib::MPEG::File::ID3v1;
+ else if (ui.id3v2RadioButton->isChecked())
+ return TagLib::MPEG::File::ID3v2;
+ else if (ui.apeRadioButton->isChecked())
+ return TagLib::MPEG::File::APE;
+ return TagLib::MPEG::File::ID3v2;
+}
+
+void DetailsDialog::closeEvent (QCloseEvent *)
+{
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ settings.beginGroup("MAD");
+ if (ui.id3v1RadioButton->isChecked())
+ settings.setValue("current_tag","ID3v1");
+ else if (ui.id3v2RadioButton->isChecked())
+ settings.setValue("current_tag","ID3v2");
+ else if (ui.apeRadioButton->isChecked())
+ settings.setValue("current_tag","APE");
+ settings.endGroup();
+}
diff --git a/src/plugins/Input/mad/detailsdialog.h b/src/plugins/Input/mad/detailsdialog.h
new file mode 100644
index 000000000..bc92724a3
--- /dev/null
+++ b/src/plugins/Input/mad/detailsdialog.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 QTextCodec;
+
+class DetailsDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ DetailsDialog(QWidget *parent = 0, const QString &path = 0);
+
+ ~DetailsDialog();
+
+protected:
+ virtual void closeEvent (QCloseEvent *);
+
+private slots:
+ void save();
+ void create();
+ void deleteTag();
+ void loadTag();
+
+private:
+ void loadMPEGInfo();
+ uint selectedTag();
+ //void loadTag();
+ //void loadID3v2Tag();
+ Ui::DetailsDialog ui;
+ QString m_path;
+ QTextCodec *m_codec_v1;
+ QTextCodec *m_codec_v2;
+ bool m_rw;
+
+};
+
+#endif
diff --git a/src/plugins/Input/mad/detailsdialog.ui b/src/plugins/Input/mad/detailsdialog.ui
new file mode 100644
index 000000000..6f9a00c31
--- /dev/null
+++ b/src/plugins/Input/mad/detailsdialog.ui
@@ -0,0 +1,392 @@
+<ui version="4.0" >
+ <class>DetailsDialog</class>
+ <widget class="QDialog" name="DetailsDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>593</width>
+ <height>402</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Details</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" colspan="3" >
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QLabel" name="label_28" >
+ <property name="text" >
+ <string>File path:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="pathLineEdit" >
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item rowspan="2" row="1" column="0" >
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QGroupBox" name="groupBox_3" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Tag Choice</string>
+ </property>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QRadioButton" name="id3v1RadioButton" >
+ <property name="text" >
+ <string>ID3v1</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="id3v2RadioButton" >
+ <property name="text" >
+ <string>ID3v2</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="apeRadioButton" >
+ <property name="text" >
+ <string>APE</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="minimumSize" >
+ <size>
+ <width>200</width>
+ <height>16</height>
+ </size>
+ </property>
+ <property name="title" >
+ <string>MPEG Info</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>MPEG level:</string>
+ </property>
+ <property name="textFormat" >
+ <enum>Qt::AutoText</enum>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLabel" name="levelLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>Bit rate:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLabel" name="bitRateLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" 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="2" column="1" >
+ <widget class="QLabel" name="sampleRateLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" 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="3" column="1" >
+ <widget class="QLabel" name="fileSizeLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" >
+ <widget class="QLabel" name="label_6" >
+ <property name="text" >
+ <string>Mode:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1" >
+ <widget class="QLabel" name="modeLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0" >
+ <widget class="QLabel" name="label_8" >
+ <property name="text" >
+ <string>Copyright:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" >
+ <widget class="QLabel" name="copyrightLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0" >
+ <widget class="QLabel" name="label_9" >
+ <property name="text" >
+ <string>Original:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1" >
+ <widget class="QLabel" name="originalLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="1" colspan="2" >
+ <widget class="QGroupBox" name="tagGroupBox" >
+ <property name="title" >
+ <string>ID3v1 Tag</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QWidget" native="1" name="tagsWidget" >
+ <property name="enabled" >
+ <bool>true</bool>
+ </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::AlignRight|Qt::AlignTrailing|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::AlignRight|Qt::AlignTrailing|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::AlignRight|Qt::AlignTrailing|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::AlignRight|Qt::AlignTrailing|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::AlignRight|Qt::AlignTrailing|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::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" colspan="3" >
+ <widget class="QLineEdit" name="genreLineEdit" />
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QPushButton" name="createButton" >
+ <property name="text" >
+ <string>Create</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="deleteButton" >
+ <property name="text" >
+ <string>Delete</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="saveButton" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <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="2" >
+ <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>
diff --git a/src/plugins/Input/mad/mad.pro b/src/plugins/Input/mad/mad.pro
new file mode 100644
index 000000000..7a320b370
--- /dev/null
+++ b/src/plugins/Input/mad/mad.pro
@@ -0,0 +1,39 @@
+# ???? ?????? ? KDevelop ?????????? qmake.
+# -------------------------------------------
+# ?????????? ???????????? ???????? ???????? ???????: ./Plugins/Input/mad
+# ???? - ??????????:
+
+include(../../plugins.pri)
+
+
+FORMS += detailsdialog.ui \
+ settingsdialog.ui
+HEADERS += decodermadfactory.h \
+ decoder_mad.h \
+ detailsdialog.h \
+ settingsdialog.h
+SOURCES += decoder_mad.cpp \
+ decodermadfactory.cpp \
+ detailsdialog.cpp \
+ settingsdialog.cpp
+
+TARGET=$$PLUGINS_PREFIX/Input/mad
+QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libmad.so
+
+INCLUDEPATH += ../../../qmmp
+CONFIG += release \
+warn_on \
+plugin \
+link_pkgconfig
+TEMPLATE = lib
+QMAKE_LIBDIR += ../../../../lib
+LIBS += -lqmmp
+PKGCONFIG += taglib mad
+#TRANSLATIONS = translations/mad_plugin_ru.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/mad/settingsdialog.cpp b/src/plugins/Input/mad/settingsdialog.cpp
new file mode 100644
index 000000000..667e8598a
--- /dev/null
+++ b/src/plugins/Input/mad/settingsdialog.cpp
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 <QTextCodec>
+#include <QSettings>
+#include <QDir>
+
+#include "settingsdialog.h"
+
+SettingsDialog::SettingsDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ ui.setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose);
+ findCodecs();
+ foreach (QTextCodec *codec, codecs)
+ {
+ ui.id3v1EncComboBox->addItem(codec->name());
+ ui.id3v2EncComboBox->addItem(codec->name());
+ }
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ settings.beginGroup("MAD");
+ int pos = ui.id3v1EncComboBox->findText
+ (settings.value("ID3v1_encoding","UTF-8").toString());
+ ui.id3v1EncComboBox->setCurrentIndex(pos);
+ pos = ui.id3v2EncComboBox->findText
+ (settings.value("ID3v2_encoding","UTF-8").toString());
+ ui.id3v2EncComboBox->setCurrentIndex(pos);
+
+ ui.firstTagComboBox->setCurrentIndex(settings.value("tag_1", ID3v2).toInt());
+ ui.secondTagComboBox->setCurrentIndex(settings.value("tag_2", Disabled).toInt());
+ ui.thirdTagComboBox->setCurrentIndex(settings.value("tag_3", Disabled).toInt());
+
+ settings.endGroup();
+ connect(ui.okButton, SIGNAL(clicked()), SLOT(writeSettings()));
+}
+
+
+SettingsDialog::~SettingsDialog()
+{}
+
+void SettingsDialog::writeSettings()
+{
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ settings.beginGroup("MAD");
+ settings.setValue("ID3v1_encoding", ui.id3v1EncComboBox->currentText());
+ settings.setValue("ID3v2_encoding", ui.id3v2EncComboBox->currentText());
+ settings.setValue("tag_1", ui.firstTagComboBox->currentIndex());
+ settings.setValue("tag_2", ui.secondTagComboBox->currentIndex());
+ settings.setValue("tag_3", ui.thirdTagComboBox->currentIndex());
+ settings.endGroup();
+ accept();
+}
+
+void SettingsDialog::findCodecs()
+{
+ QMap<QString, QTextCodec *> codecMap;
+ QRegExp iso8859RegExp("ISO[- ]8859-([0-9]+).*");
+
+ foreach (int mib, QTextCodec::availableMibs())
+ {
+ QTextCodec *codec = QTextCodec::codecForMib(mib);
+
+ QString sortKey = codec->name().toUpper();
+ int rank;
+
+ if (sortKey.startsWith("UTF-8"))
+ {
+ rank = 1;
+ }
+ else if (sortKey.startsWith("UTF-16"))
+ {
+ rank = 2;
+ }
+ else if (iso8859RegExp.exactMatch(sortKey))
+ {
+ if (iso8859RegExp.cap(1).size() == 1)
+ rank = 3;
+ else
+ rank = 4;
+ }
+ else
+ {
+ rank = 5;
+ }
+ sortKey.prepend(QChar('0' + rank));
+
+ codecMap.insert(sortKey, codec);
+ }
+ codecs = codecMap.values();
+}
diff --git a/src/plugins/Input/mad/settingsdialog.h b/src/plugins/Input/mad/settingsdialog.h
new file mode 100644
index 000000000..2ad1ed188
--- /dev/null
+++ b/src/plugins/Input/mad/settingsdialog.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 SETTINGSDIALOG_H
+#define SETTINGSDIALOG_H
+
+#include <QDialog>
+
+
+#include "ui_settingsdialog.h"
+
+/**
+ @author Ilya Kotov <forkotov02@hotmail.ru>
+*/
+class SettingsDialog : public QDialog
+{
+Q_OBJECT
+public:
+ SettingsDialog(QWidget *parent = 0);
+
+ ~SettingsDialog();
+
+ enum TagType {ID3v1 = 0, ID3v2, APE, Disabled};
+
+private slots:
+ void writeSettings();
+
+private:
+ void findCodecs();
+
+ Ui::SettingsDialog ui;
+ QList<QTextCodec *> codecs;
+
+};
+
+#endif
diff --git a/src/plugins/Input/mad/settingsdialog.ui b/src/plugins/Input/mad/settingsdialog.ui
new file mode 100644
index 000000000..3ace8fcec
--- /dev/null
+++ b/src/plugins/Input/mad/settingsdialog.ui
@@ -0,0 +1,306 @@
+<ui version="4.0" >
+ <class>SettingsDialog</class>
+ <widget class="QDialog" name="SettingsDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>242</width>
+ <height>303</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>MPEG Plugin Settings</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QGroupBox" name="groupBox_2" >
+ <property name="title" >
+ <string>Tag Priority</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QLabel" name="label_15_2" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>First:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="firstTagComboBox" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <item>
+ <property name="text" >
+ <string>ID3v1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>ID3v2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>APE</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Disabled</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QLabel" name="label_15_3" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Second:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="secondTagComboBox" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <item>
+ <property name="text" >
+ <string>ID3v1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>ID3v2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>APE</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Disabled</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QLabel" name="label_15_4" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Third:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="thirdTagComboBox" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <item>
+ <property name="text" >
+ <string>ID3v1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>ID3v2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>APE</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Disabled</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="title" >
+ <string>Encodings</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_17_2_2" >
+ <property name="text" >
+ <string>ID3v1 encoding:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="id3v1EncComboBox" />
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_18_2_2" >
+ <property name="text" >
+ <string>ID3v2 encoding:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="id3v2EncComboBox" />
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>131</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="okButton" >
+ <property name="text" >
+ <string>OK</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancelButton" >
+ <property name="text" >
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>cancelButton</sender>
+ <signal>clicked()</signal>
+ <receiver>SettingsDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>336</x>
+ <y>210</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>179</x>
+ <y>224</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/Input/mad/translations/mad_plugin_ru.qm b/src/plugins/Input/mad/translations/mad_plugin_ru.qm
new file mode 100644
index 000000000..16bea746b
--- /dev/null
+++ b/src/plugins/Input/mad/translations/mad_plugin_ru.qm
Binary files differ
diff --git a/src/plugins/Input/mad/translations/mad_plugin_ru.ts b/src/plugins/Input/mad/translations/mad_plugin_ru.ts
new file mode 100644
index 000000000..6406f6045
--- /dev/null
+++ b/src/plugins/Input/mad/translations/mad_plugin_ru.ts
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS><TS version="1.1" language="ru">
+<context>
+ <name>DecoderMADFactory</name>
+ <message>
+ <location filename="../decodermadfactory.cpp" line="27"/>
+ <source>MPEG Plugin</source>
+ <translation>Модуль MPEG</translation>
+ </message>
+ <message>
+ <location filename="../decodermadfactory.cpp" line="39"/>
+ <source>MPEG Files</source>
+ <translation>Файлы MPEG</translation>
+ </message>
+ <message>
+ <location filename="../decodermadfactory.cpp" line="68"/>
+ <source>About MPEG Audio Plugin</source>
+ <translation>Об аудио-модуле MPEG</translation>
+ </message>
+ <message>
+ <location filename="../decodermadfactory.cpp" line="69"/>
+ <source>Qmmp MPEG Audio Plugin</source>
+ <translation>Аудио-модуль MPEG для Qmmp</translation>
+ </message>
+ <message>
+ <location filename="../decodermadfactory.cpp" line="70"/>
+ <source>Compiled against libmad version:</source>
+ <translation>Собрано с версией libmad:</translation>
+ </message>
+ <message>
+ <location filename="../decodermadfactory.cpp" line="74"/>
+ <source>Writen by: Ilya Kotov &lt;forkotov02@hotmail.ru&gt;</source>
+ <translation>Разработчик: Илья Котов &lt;forkotov02@hotmail.ru&gt;</translation>
+ </message>
+ <message>
+ <location filename="../decodermadfactory.cpp" line="76"/>
+ <source>Source code based on mq3 progect</source>
+ <translation>Исходный код основан на проекте mq3</translation>
+ </message>
+</context>
+<context>
+ <name>DetailsDialog</name>
+ <message>
+ <location filename="../detailsdialog.cpp" line="79"/>
+ <source>Hz</source>
+ <translation>Гц</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="106"/>
+ <source>Yes</source>
+ <translation>Есть</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="108"/>
+ <source>No</source>
+ <translation>Нет</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="192"/>
+ <source>ID3v1 Tag</source>
+ <translation>ID3v1-тег</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="442"/>
+ <source>Save</source>
+ <translation>Сохранить</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="351"/>
+ <source>Track number:</source>
+ <translation>Номер трека:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="364"/>
+ <source>Year:</source>
+ <translation>Год:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="374"/>
+ <source>Genre:</source>
+ <translation>Жанр:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="384"/>
+ <source>Comment:</source>
+ <translation>Комментарий:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="394"/>
+ <source>Album:</source>
+ <translation>Альбом:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="404"/>
+ <source>Artist:</source>
+ <translation>Исполнитель:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="414"/>
+ <source>Title:</source>
+ <translation>Название:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="321"/>
+ <source>Close</source>
+ <translation>Закрыть</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="336"/>
+ <source>ID3v2 Tag</source>
+ <translation>ID3v2-тег</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="31"/>
+ <source>MPEG Info</source>
+ <translation>Информация MPEG</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="164"/>
+ <source>-</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="171"/>
+ <source>Original:</source>
+ <translation>Оригинальный:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="147"/>
+ <source>Copyright:</source>
+ <translation>Авторские права:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="137"/>
+ <source>Mode:</source>
+ <translation>Режим:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="59"/>
+ <source>File size:</source>
+ <translation>Размер файла:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="76"/>
+ <source>Sample rate:</source>
+ <translation>Дискретизация:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="86"/>
+ <source>Bit rate:</source>
+ <translation>Битовая частота:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="117"/>
+ <source>MPEG level:</source>
+ <translation>Уровень MPEG:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="452"/>
+ <source>File path:</source>
+ <translation>Путь к файлу:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="95"/>
+ <source>KB</source>
+ <translation>Кб</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="13"/>
+ <source>Details</source>
+ <translation>Информация</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="77"/>
+ <source>kbps</source>
+ <translation>Кб/с</translation>
+ </message>
+</context>
+<context>
+ <name>SettingsDialog</name>
+ <message>
+ <location filename="../settingsdialog.ui" line="25"/>
+ <source>ID3 Tags</source>
+ <translation>ID3-теги</translation>
+ </message>
+ <message>
+ <location filename="../settingsdialog.ui" line="45"/>
+ <source>Default tag version:</source>
+ <translation>Версия тегов по умолчанию:</translation>
+ </message>
+ <message>
+ <location filename="../settingsdialog.ui" line="62"/>
+ <source>ID3v1</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../settingsdialog.ui" line="67"/>
+ <source>ID3v2</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../settingsdialog.ui" line="90"/>
+ <source>Enable ID3v1</source>
+ <translation>Использовать ID3v1</translation>
+ </message>
+ <message>
+ <location filename="../settingsdialog.ui" line="97"/>
+ <source>Enable ID3v2</source>
+ <translation>Использовать ID3v2</translation>
+ </message>
+ <message>
+ <location filename="../settingsdialog.ui" line="112"/>
+ <source>ID3v1 encoding:</source>
+ <translation>Кодировка ID3v1:</translation>
+ </message>
+ <message>
+ <location filename="../settingsdialog.ui" line="165"/>
+ <source>Default</source>
+ <translation>По-умолчанию</translation>
+ </message>
+ <message>
+ <location filename="../settingsdialog.ui" line="154"/>
+ <source>ID3v2 encoding:</source>
+ <translation>Кодировка ID3v2:</translation>
+ </message>
+ <message>
+ <location filename="../settingsdialog.ui" line="212"/>
+ <source>OK</source>
+ <translation>Применить</translation>
+ </message>
+ <message>
+ <location filename="../settingsdialog.ui" line="219"/>
+ <source>Cancel</source>
+ <translation>Отмена</translation>
+ </message>
+ <message>
+ <location filename="../settingsdialog.ui" line="13"/>
+ <source>MPEG Plugin Settings</source>
+ <translation>Настройка модуля MPEG</translation>
+ </message>
+</context>
+</TS>
diff --git a/src/plugins/Input/mad/translations/translations.qrc b/src/plugins/Input/mad/translations/translations.qrc
new file mode 100644
index 000000000..34dbabbca
--- /dev/null
+++ b/src/plugins/Input/mad/translations/translations.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file>mad_plugin_ru.qm</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/Input/mad/ui_detailsdialog.h b/src/plugins/Input/mad/ui_detailsdialog.h
new file mode 100644
index 000000000..d630be894
--- /dev/null
+++ b/src/plugins/Input/mad/ui_detailsdialog.h
@@ -0,0 +1,400 @@
+/********************************************************************************
+** Form generated from reading ui file 'detailsdialog.ui'
+**
+** Created: Thu Feb 7 00:21:43 2008
+** by: Qt User Interface Compiler version 4.3.0
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_DETAILSDIALOG_H
+#define UI_DETAILSDIALOG_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QDialog>
+#include <QtGui/QGridLayout>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QPushButton>
+#include <QtGui/QRadioButton>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QWidget>
+
+class Ui_DetailsDialog
+{
+public:
+ QGridLayout *gridLayout;
+ QHBoxLayout *hboxLayout;
+ QLabel *label_28;
+ QLineEdit *pathLineEdit;
+ QVBoxLayout *vboxLayout;
+ QGroupBox *groupBox_3;
+ QHBoxLayout *hboxLayout1;
+ QRadioButton *id3v1RadioButton;
+ QRadioButton *id3v2RadioButton;
+ QRadioButton *apeRadioButton;
+ QGroupBox *groupBox;
+ QGridLayout *gridLayout1;
+ QLabel *label;
+ QLabel *levelLabel;
+ QLabel *label_2;
+ QLabel *bitRateLabel;
+ QLabel *label_3;
+ QLabel *sampleRateLabel;
+ QLabel *label_5;
+ QLabel *fileSizeLabel;
+ QLabel *label_6;
+ QLabel *modeLabel;
+ QLabel *label_8;
+ QLabel *copyrightLabel;
+ QLabel *label_9;
+ QLabel *originalLabel;
+ QGroupBox *tagGroupBox;
+ QVBoxLayout *vboxLayout1;
+ QWidget *tagsWidget;
+ QGridLayout *gridLayout2;
+ QLabel *label_21;
+ QLineEdit *titleLineEdit;
+ QLabel *label_22;
+ QLineEdit *artistLineEdit;
+ QLabel *label_23;
+ QLineEdit *albumLineEdit;
+ QLabel *label_24;
+ QLineEdit *commentLineEdit;
+ QLabel *label_25;
+ QLineEdit *yearLineEdit;
+ QLabel *label_26;
+ QLineEdit *trackLineEdit;
+ QLabel *label_27;
+ QLineEdit *genreLineEdit;
+ QHBoxLayout *hboxLayout2;
+ QPushButton *createButton;
+ QPushButton *deleteButton;
+ QPushButton *saveButton;
+ QSpacerItem *spacerItem;
+ QPushButton *pushButton_3;
+
+ void setupUi(QDialog *DetailsDialog)
+ {
+ if (DetailsDialog->objectName().isEmpty())
+ DetailsDialog->setObjectName(QString::fromUtf8("DetailsDialog"));
+ QSize size(593, 402);
+ size = size.expandedTo(DetailsDialog->minimumSizeHint());
+ DetailsDialog->resize(size);
+ gridLayout = new QGridLayout(DetailsDialog);
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+ hboxLayout = new QHBoxLayout();
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+ label_28 = new QLabel(DetailsDialog);
+ label_28->setObjectName(QString::fromUtf8("label_28"));
+ label_28->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter);
+
+ hboxLayout->addWidget(label_28);
+
+ pathLineEdit = new QLineEdit(DetailsDialog);
+ pathLineEdit->setObjectName(QString::fromUtf8("pathLineEdit"));
+ pathLineEdit->setReadOnly(true);
+
+ hboxLayout->addWidget(pathLineEdit);
+
+
+ gridLayout->addLayout(hboxLayout, 0, 0, 1, 3);
+
+ vboxLayout = new QVBoxLayout();
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+ groupBox_3 = new QGroupBox(DetailsDialog);
+ groupBox_3->setObjectName(QString::fromUtf8("groupBox_3"));
+ QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ sizePolicy.setHorizontalStretch(0);
+ sizePolicy.setVerticalStretch(0);
+ sizePolicy.setHeightForWidth(groupBox_3->sizePolicy().hasHeightForWidth());
+ groupBox_3->setSizePolicy(sizePolicy);
+ hboxLayout1 = new QHBoxLayout(groupBox_3);
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+ id3v1RadioButton = new QRadioButton(groupBox_3);
+ id3v1RadioButton->setObjectName(QString::fromUtf8("id3v1RadioButton"));
+
+ hboxLayout1->addWidget(id3v1RadioButton);
+
+ id3v2RadioButton = new QRadioButton(groupBox_3);
+ id3v2RadioButton->setObjectName(QString::fromUtf8("id3v2RadioButton"));
+
+ hboxLayout1->addWidget(id3v2RadioButton);
+
+ apeRadioButton = new QRadioButton(groupBox_3);
+ apeRadioButton->setObjectName(QString::fromUtf8("apeRadioButton"));
+
+ hboxLayout1->addWidget(apeRadioButton);
+
+
+ vboxLayout->addWidget(groupBox_3);
+
+ groupBox = new QGroupBox(DetailsDialog);
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
+ groupBox->setMinimumSize(QSize(200, 16));
+ gridLayout1 = new QGridLayout(groupBox);
+ gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
+ label = new QLabel(groupBox);
+ label->setObjectName(QString::fromUtf8("label"));
+ label->setTextFormat(Qt::AutoText);
+ label->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout1->addWidget(label, 0, 0, 1, 1);
+
+ levelLabel = new QLabel(groupBox);
+ levelLabel->setObjectName(QString::fromUtf8("levelLabel"));
+
+ gridLayout1->addWidget(levelLabel, 0, 1, 1, 1);
+
+ label_2 = new QLabel(groupBox);
+ label_2->setObjectName(QString::fromUtf8("label_2"));
+ label_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout1->addWidget(label_2, 1, 0, 1, 1);
+
+ bitRateLabel = new QLabel(groupBox);
+ bitRateLabel->setObjectName(QString::fromUtf8("bitRateLabel"));
+
+ gridLayout1->addWidget(bitRateLabel, 1, 1, 1, 1);
+
+ label_3 = new QLabel(groupBox);
+ label_3->setObjectName(QString::fromUtf8("label_3"));
+ label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout1->addWidget(label_3, 2, 0, 1, 1);
+
+ sampleRateLabel = new QLabel(groupBox);
+ sampleRateLabel->setObjectName(QString::fromUtf8("sampleRateLabel"));
+
+ gridLayout1->addWidget(sampleRateLabel, 2, 1, 1, 1);
+
+ label_5 = new QLabel(groupBox);
+ label_5->setObjectName(QString::fromUtf8("label_5"));
+ label_5->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout1->addWidget(label_5, 3, 0, 1, 1);
+
+ fileSizeLabel = new QLabel(groupBox);
+ fileSizeLabel->setObjectName(QString::fromUtf8("fileSizeLabel"));
+
+ gridLayout1->addWidget(fileSizeLabel, 3, 1, 1, 1);
+
+ label_6 = new QLabel(groupBox);
+ label_6->setObjectName(QString::fromUtf8("label_6"));
+ label_6->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout1->addWidget(label_6, 4, 0, 1, 1);
+
+ modeLabel = new QLabel(groupBox);
+ modeLabel->setObjectName(QString::fromUtf8("modeLabel"));
+
+ gridLayout1->addWidget(modeLabel, 4, 1, 1, 1);
+
+ label_8 = new QLabel(groupBox);
+ label_8->setObjectName(QString::fromUtf8("label_8"));
+ label_8->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout1->addWidget(label_8, 5, 0, 1, 1);
+
+ copyrightLabel = new QLabel(groupBox);
+ copyrightLabel->setObjectName(QString::fromUtf8("copyrightLabel"));
+
+ gridLayout1->addWidget(copyrightLabel, 5, 1, 1, 1);
+
+ label_9 = new QLabel(groupBox);
+ label_9->setObjectName(QString::fromUtf8("label_9"));
+ label_9->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout1->addWidget(label_9, 6, 0, 1, 1);
+
+ originalLabel = new QLabel(groupBox);
+ originalLabel->setObjectName(QString::fromUtf8("originalLabel"));
+
+ gridLayout1->addWidget(originalLabel, 6, 1, 1, 1);
+
+
+ vboxLayout->addWidget(groupBox);
+
+
+ gridLayout->addLayout(vboxLayout, 1, 0, 2, 1);
+
+ tagGroupBox = new QGroupBox(DetailsDialog);
+ tagGroupBox->setObjectName(QString::fromUtf8("tagGroupBox"));
+ vboxLayout1 = new QVBoxLayout(tagGroupBox);
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
+ tagsWidget = new QWidget(tagGroupBox);
+ tagsWidget->setObjectName(QString::fromUtf8("tagsWidget"));
+ tagsWidget->setEnabled(true);
+ gridLayout2 = new QGridLayout(tagsWidget);
+ gridLayout2->setObjectName(QString::fromUtf8("gridLayout2"));
+ label_21 = new QLabel(tagsWidget);
+ label_21->setObjectName(QString::fromUtf8("label_21"));
+ label_21->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout2->addWidget(label_21, 0, 0, 1, 1);
+
+ titleLineEdit = new QLineEdit(tagsWidget);
+ titleLineEdit->setObjectName(QString::fromUtf8("titleLineEdit"));
+
+ gridLayout2->addWidget(titleLineEdit, 0, 1, 1, 3);
+
+ label_22 = new QLabel(tagsWidget);
+ label_22->setObjectName(QString::fromUtf8("label_22"));
+ label_22->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout2->addWidget(label_22, 1, 0, 1, 1);
+
+ artistLineEdit = new QLineEdit(tagsWidget);
+ artistLineEdit->setObjectName(QString::fromUtf8("artistLineEdit"));
+
+ gridLayout2->addWidget(artistLineEdit, 1, 1, 1, 3);
+
+ label_23 = new QLabel(tagsWidget);
+ label_23->setObjectName(QString::fromUtf8("label_23"));
+ label_23->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout2->addWidget(label_23, 2, 0, 1, 1);
+
+ albumLineEdit = new QLineEdit(tagsWidget);
+ albumLineEdit->setObjectName(QString::fromUtf8("albumLineEdit"));
+
+ gridLayout2->addWidget(albumLineEdit, 2, 1, 1, 3);
+
+ label_24 = new QLabel(tagsWidget);
+ label_24->setObjectName(QString::fromUtf8("label_24"));
+ label_24->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout2->addWidget(label_24, 3, 0, 1, 1);
+
+ commentLineEdit = new QLineEdit(tagsWidget);
+ commentLineEdit->setObjectName(QString::fromUtf8("commentLineEdit"));
+
+ gridLayout2->addWidget(commentLineEdit, 3, 1, 1, 3);
+
+ label_25 = new QLabel(tagsWidget);
+ label_25->setObjectName(QString::fromUtf8("label_25"));
+ label_25->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout2->addWidget(label_25, 4, 0, 1, 1);
+
+ yearLineEdit = new QLineEdit(tagsWidget);
+ yearLineEdit->setObjectName(QString::fromUtf8("yearLineEdit"));
+
+ gridLayout2->addWidget(yearLineEdit, 4, 1, 1, 1);
+
+ label_26 = new QLabel(tagsWidget);
+ label_26->setObjectName(QString::fromUtf8("label_26"));
+ label_26->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout2->addWidget(label_26, 4, 2, 1, 1);
+
+ trackLineEdit = new QLineEdit(tagsWidget);
+ trackLineEdit->setObjectName(QString::fromUtf8("trackLineEdit"));
+
+ gridLayout2->addWidget(trackLineEdit, 4, 3, 1, 1);
+
+ label_27 = new QLabel(tagsWidget);
+ label_27->setObjectName(QString::fromUtf8("label_27"));
+ label_27->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ gridLayout2->addWidget(label_27, 5, 0, 1, 1);
+
+ genreLineEdit = new QLineEdit(tagsWidget);
+ genreLineEdit->setObjectName(QString::fromUtf8("genreLineEdit"));
+
+ gridLayout2->addWidget(genreLineEdit, 5, 1, 1, 3);
+
+
+ vboxLayout1->addWidget(tagsWidget);
+
+ hboxLayout2 = new QHBoxLayout();
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
+ createButton = new QPushButton(tagGroupBox);
+ createButton->setObjectName(QString::fromUtf8("createButton"));
+
+ hboxLayout2->addWidget(createButton);
+
+ deleteButton = new QPushButton(tagGroupBox);
+ deleteButton->setObjectName(QString::fromUtf8("deleteButton"));
+
+ hboxLayout2->addWidget(deleteButton);
+
+ saveButton = new QPushButton(tagGroupBox);
+ saveButton->setObjectName(QString::fromUtf8("saveButton"));
+ saveButton->setEnabled(false);
+
+ hboxLayout2->addWidget(saveButton);
+
+
+ vboxLayout1->addLayout(hboxLayout2);
+
+
+ gridLayout->addWidget(tagGroupBox, 1, 1, 1, 2);
+
+ spacerItem = new QSpacerItem(111, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+ gridLayout->addItem(spacerItem, 2, 1, 1, 1);
+
+ pushButton_3 = new QPushButton(DetailsDialog);
+ pushButton_3->setObjectName(QString::fromUtf8("pushButton_3"));
+
+ gridLayout->addWidget(pushButton_3, 2, 2, 1, 1);
+
+
+ retranslateUi(DetailsDialog);
+ QObject::connect(pushButton_3, SIGNAL(clicked()), DetailsDialog, SLOT(close()));
+
+ QMetaObject::connectSlotsByName(DetailsDialog);
+ } // setupUi
+
+ void retranslateUi(QDialog *DetailsDialog)
+ {
+ DetailsDialog->setWindowTitle(QApplication::translate("DetailsDialog", "Details", 0, QApplication::UnicodeUTF8));
+ label_28->setText(QApplication::translate("DetailsDialog", "File path:", 0, QApplication::UnicodeUTF8));
+ groupBox_3->setTitle(QApplication::translate("DetailsDialog", "Tag Choice", 0, QApplication::UnicodeUTF8));
+ id3v1RadioButton->setText(QApplication::translate("DetailsDialog", "ID3v1", 0, QApplication::UnicodeUTF8));
+ id3v2RadioButton->setText(QApplication::translate("DetailsDialog", "ID3v2", 0, QApplication::UnicodeUTF8));
+ apeRadioButton->setText(QApplication::translate("DetailsDialog", "APE", 0, QApplication::UnicodeUTF8));
+ groupBox->setTitle(QApplication::translate("DetailsDialog", "MPEG Info", 0, QApplication::UnicodeUTF8));
+ label->setText(QApplication::translate("DetailsDialog", "MPEG level:", 0, QApplication::UnicodeUTF8));
+ levelLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8));
+ label_2->setText(QApplication::translate("DetailsDialog", "Bit rate:", 0, QApplication::UnicodeUTF8));
+ bitRateLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8));
+ label_3->setText(QApplication::translate("DetailsDialog", "Sample rate:", 0, QApplication::UnicodeUTF8));
+ sampleRateLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8));
+ label_5->setText(QApplication::translate("DetailsDialog", "File size:", 0, QApplication::UnicodeUTF8));
+ fileSizeLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8));
+ label_6->setText(QApplication::translate("DetailsDialog", "Mode:", 0, QApplication::UnicodeUTF8));
+ modeLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8));
+ label_8->setText(QApplication::translate("DetailsDialog", "Copyright:", 0, QApplication::UnicodeUTF8));
+ copyrightLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8));
+ label_9->setText(QApplication::translate("DetailsDialog", "Original:", 0, QApplication::UnicodeUTF8));
+ originalLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8));
+ tagGroupBox->setTitle(QApplication::translate("DetailsDialog", "ID3v1 Tag", 0, QApplication::UnicodeUTF8));
+ label_21->setText(QApplication::translate("DetailsDialog", "Title:", 0, QApplication::UnicodeUTF8));
+ label_22->setText(QApplication::translate("DetailsDialog", "Artist:", 0, QApplication::UnicodeUTF8));
+ label_23->setText(QApplication::translate("DetailsDialog", "Album:", 0, QApplication::UnicodeUTF8));
+ label_24->setText(QApplication::translate("DetailsDialog", "Comment:", 0, QApplication::UnicodeUTF8));
+ label_25->setText(QApplication::translate("DetailsDialog", "Year:", 0, QApplication::UnicodeUTF8));
+ label_26->setText(QApplication::translate("DetailsDialog", "Track number:", 0, QApplication::UnicodeUTF8));
+ label_27->setText(QApplication::translate("DetailsDialog", "Genre:", 0, QApplication::UnicodeUTF8));
+ createButton->setText(QApplication::translate("DetailsDialog", "Create", 0, QApplication::UnicodeUTF8));
+ deleteButton->setText(QApplication::translate("DetailsDialog", "Delete", 0, QApplication::UnicodeUTF8));
+ saveButton->setText(QApplication::translate("DetailsDialog", "Save", 0, QApplication::UnicodeUTF8));
+ pushButton_3->setText(QApplication::translate("DetailsDialog", "Close", 0, QApplication::UnicodeUTF8));
+ Q_UNUSED(DetailsDialog);
+ } // retranslateUi
+
+};
+
+namespace Ui {
+ class DetailsDialog: public Ui_DetailsDialog {};
+} // namespace Ui
+
+#endif // UI_DETAILSDIALOG_H
diff --git a/src/plugins/Input/mad/ui_settingsdialog.h b/src/plugins/Input/mad/ui_settingsdialog.h
new file mode 100644
index 000000000..47cdac64f
--- /dev/null
+++ b/src/plugins/Input/mad/ui_settingsdialog.h
@@ -0,0 +1,245 @@
+/********************************************************************************
+** Form generated from reading ui file 'settingsdialog.ui'
+**
+** Created: Thu Feb 7 00:21:43 2008
+** by: Qt User Interface Compiler version 4.3.0
+**
+** WARNING! All changes made in this file will be lost when recompiling ui file!
+********************************************************************************/
+
+#ifndef UI_SETTINGSDIALOG_H
+#define UI_SETTINGSDIALOG_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QComboBox>
+#include <QtGui/QDialog>
+#include <QtGui/QGroupBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QPushButton>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QVBoxLayout>
+
+class Ui_SettingsDialog
+{
+public:
+ QVBoxLayout *vboxLayout;
+ QGroupBox *groupBox_2;
+ QVBoxLayout *vboxLayout1;
+ QHBoxLayout *hboxLayout;
+ QLabel *label_15_2;
+ QComboBox *firstTagComboBox;
+ QHBoxLayout *hboxLayout1;
+ QLabel *label_15_3;
+ QComboBox *secondTagComboBox;
+ QHBoxLayout *hboxLayout2;
+ QLabel *label_15_4;
+ QComboBox *thirdTagComboBox;
+ QGroupBox *groupBox;
+ QVBoxLayout *vboxLayout2;
+ QHBoxLayout *hboxLayout3;
+ QLabel *label_17_2_2;
+ QComboBox *id3v1EncComboBox;
+ QHBoxLayout *hboxLayout4;
+ QLabel *label_18_2_2;
+ QComboBox *id3v2EncComboBox;
+ QHBoxLayout *hboxLayout5;
+ QSpacerItem *spacerItem;
+ QPushButton *okButton;
+ QPushButton *cancelButton;
+
+ void setupUi(QDialog *SettingsDialog)
+ {
+ if (SettingsDialog->objectName().isEmpty())
+ SettingsDialog->setObjectName(QString::fromUtf8("SettingsDialog"));
+ QSize size(242, 303);
+ size = size.expandedTo(SettingsDialog->minimumSizeHint());
+ SettingsDialog->resize(size);
+ vboxLayout = new QVBoxLayout(SettingsDialog);
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+ groupBox_2 = new QGroupBox(SettingsDialog);
+ groupBox_2->setObjectName(QString::fromUtf8("groupBox_2"));
+ vboxLayout1 = new QVBoxLayout(groupBox_2);
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
+ hboxLayout = new QHBoxLayout();
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+ label_15_2 = new QLabel(groupBox_2);
+ label_15_2->setObjectName(QString::fromUtf8("label_15_2"));
+ QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sizePolicy.setHorizontalStretch(0);
+ sizePolicy.setVerticalStretch(0);
+ sizePolicy.setHeightForWidth(label_15_2->sizePolicy().hasHeightForWidth());
+ label_15_2->setSizePolicy(sizePolicy);
+ label_15_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ hboxLayout->addWidget(label_15_2);
+
+ firstTagComboBox = new QComboBox(groupBox_2);
+ firstTagComboBox->setObjectName(QString::fromUtf8("firstTagComboBox"));
+
+ hboxLayout->addWidget(firstTagComboBox);
+
+
+ vboxLayout1->addLayout(hboxLayout);
+
+ hboxLayout1 = new QHBoxLayout();
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+ label_15_3 = new QLabel(groupBox_2);
+ label_15_3->setObjectName(QString::fromUtf8("label_15_3"));
+ sizePolicy.setHeightForWidth(label_15_3->sizePolicy().hasHeightForWidth());
+ label_15_3->setSizePolicy(sizePolicy);
+ label_15_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ hboxLayout1->addWidget(label_15_3);
+
+ secondTagComboBox = new QComboBox(groupBox_2);
+ secondTagComboBox->setObjectName(QString::fromUtf8("secondTagComboBox"));
+
+ hboxLayout1->addWidget(secondTagComboBox);
+
+
+ vboxLayout1->addLayout(hboxLayout1);
+
+ hboxLayout2 = new QHBoxLayout();
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
+ label_15_4 = new QLabel(groupBox_2);
+ label_15_4->setObjectName(QString::fromUtf8("label_15_4"));
+ sizePolicy.setHeightForWidth(label_15_4->sizePolicy().hasHeightForWidth());
+ label_15_4->setSizePolicy(sizePolicy);
+ label_15_4->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ hboxLayout2->addWidget(label_15_4);
+
+ thirdTagComboBox = new QComboBox(groupBox_2);
+ thirdTagComboBox->setObjectName(QString::fromUtf8("thirdTagComboBox"));
+
+ hboxLayout2->addWidget(thirdTagComboBox);
+
+
+ vboxLayout1->addLayout(hboxLayout2);
+
+
+ vboxLayout->addWidget(groupBox_2);
+
+ groupBox = new QGroupBox(SettingsDialog);
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
+ vboxLayout2 = new QVBoxLayout(groupBox);
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
+ hboxLayout3 = new QHBoxLayout();
+ hboxLayout3->setSpacing(6);
+ hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
+ hboxLayout3->setContentsMargins(0, 0, 0, 0);
+ label_17_2_2 = new QLabel(groupBox);
+ label_17_2_2->setObjectName(QString::fromUtf8("label_17_2_2"));
+ label_17_2_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ hboxLayout3->addWidget(label_17_2_2);
+
+ id3v1EncComboBox = new QComboBox(groupBox);
+ id3v1EncComboBox->setObjectName(QString::fromUtf8("id3v1EncComboBox"));
+
+ hboxLayout3->addWidget(id3v1EncComboBox);
+
+
+ vboxLayout2->addLayout(hboxLayout3);
+
+ hboxLayout4 = new QHBoxLayout();
+ hboxLayout4->setSpacing(6);
+ hboxLayout4->setObjectName(QString::fromUtf8("hboxLayout4"));
+ hboxLayout4->setContentsMargins(0, 0, 0, 0);
+ label_18_2_2 = new QLabel(groupBox);
+ label_18_2_2->setObjectName(QString::fromUtf8("label_18_2_2"));
+ label_18_2_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+
+ hboxLayout4->addWidget(label_18_2_2);
+
+ id3v2EncComboBox = new QComboBox(groupBox);
+ id3v2EncComboBox->setObjectName(QString::fromUtf8("id3v2EncComboBox"));
+
+ hboxLayout4->addWidget(id3v2EncComboBox);
+
+
+ vboxLayout2->addLayout(hboxLayout4);
+
+
+ vboxLayout->addWidget(groupBox);
+
+ hboxLayout5 = new QHBoxLayout();
+ hboxLayout5->setSpacing(6);
+ hboxLayout5->setObjectName(QString::fromUtf8("hboxLayout5"));
+ hboxLayout5->setContentsMargins(0, 0, 0, 0);
+ spacerItem = new QSpacerItem(131, 31, QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+ hboxLayout5->addItem(spacerItem);
+
+ okButton = new QPushButton(SettingsDialog);
+ okButton->setObjectName(QString::fromUtf8("okButton"));
+
+ hboxLayout5->addWidget(okButton);
+
+ cancelButton = new QPushButton(SettingsDialog);
+ cancelButton->setObjectName(QString::fromUtf8("cancelButton"));
+
+ hboxLayout5->addWidget(cancelButton);
+
+
+ vboxLayout->addLayout(hboxLayout5);
+
+
+ retranslateUi(SettingsDialog);
+ QObject::connect(cancelButton, SIGNAL(clicked()), SettingsDialog, SLOT(reject()));
+
+ firstTagComboBox->setCurrentIndex(0);
+ secondTagComboBox->setCurrentIndex(0);
+ thirdTagComboBox->setCurrentIndex(0);
+
+
+ QMetaObject::connectSlotsByName(SettingsDialog);
+ } // setupUi
+
+ void retranslateUi(QDialog *SettingsDialog)
+ {
+ SettingsDialog->setWindowTitle(QApplication::translate("SettingsDialog", "MPEG Plugin Settings", 0, QApplication::UnicodeUTF8));
+ groupBox_2->setTitle(QApplication::translate("SettingsDialog", "Tag Priority", 0, QApplication::UnicodeUTF8));
+ label_15_2->setText(QApplication::translate("SettingsDialog", "First:", 0, QApplication::UnicodeUTF8));
+ firstTagComboBox->clear();
+ firstTagComboBox->insertItems(0, QStringList()
+ << QApplication::translate("SettingsDialog", "ID3v1", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("SettingsDialog", "ID3v2", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("SettingsDialog", "APE", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("SettingsDialog", "Disabled", 0, QApplication::UnicodeUTF8)
+ );
+ label_15_3->setText(QApplication::translate("SettingsDialog", "Second:", 0, QApplication::UnicodeUTF8));
+ secondTagComboBox->clear();
+ secondTagComboBox->insertItems(0, QStringList()
+ << QApplication::translate("SettingsDialog", "ID3v1", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("SettingsDialog", "ID3v2", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("SettingsDialog", "APE", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("SettingsDialog", "Disabled", 0, QApplication::UnicodeUTF8)
+ );
+ label_15_4->setText(QApplication::translate("SettingsDialog", "Third:", 0, QApplication::UnicodeUTF8));
+ thirdTagComboBox->clear();
+ thirdTagComboBox->insertItems(0, QStringList()
+ << QApplication::translate("SettingsDialog", "ID3v1", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("SettingsDialog", "ID3v2", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("SettingsDialog", "APE", 0, QApplication::UnicodeUTF8)
+ << QApplication::translate("SettingsDialog", "Disabled", 0, QApplication::UnicodeUTF8)
+ );
+ groupBox->setTitle(QApplication::translate("SettingsDialog", "Encodings", 0, QApplication::UnicodeUTF8));
+ label_17_2_2->setText(QApplication::translate("SettingsDialog", "ID3v1 encoding:", 0, QApplication::UnicodeUTF8));
+ label_18_2_2->setText(QApplication::translate("SettingsDialog", "ID3v2 encoding:", 0, QApplication::UnicodeUTF8));
+ okButton->setText(QApplication::translate("SettingsDialog", "OK", 0, QApplication::UnicodeUTF8));
+ cancelButton->setText(QApplication::translate("SettingsDialog", "Cancel", 0, QApplication::UnicodeUTF8));
+ Q_UNUSED(SettingsDialog);
+ } // retranslateUi
+
+};
+
+namespace Ui {
+ class SettingsDialog: public Ui_SettingsDialog {};
+} // namespace Ui
+
+#endif // UI_SETTINGSDIALOG_H
diff --git a/src/plugins/Input/mpc/CMakeLists.txt b/src/plugins/Input/mpc/CMakeLists.txt
new file mode 100644
index 000000000..dccd6dd6b
--- /dev/null
+++ b/src/plugins/Input/mpc/CMakeLists.txt
@@ -0,0 +1,86 @@
+project(libmpc)
+
+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}/../../../)
+
+# libmpc and taglib
+PKGCONFIG(taglib TAGLIB_INCLUDE_DIR TAGLIB_LINK_DIR TAGLIB_LINK_FLAGS TAGLIB_CFLAGS)
+
+IF(NOT TAGLIB_LINK_FLAGS)
+ SET(TAGLIB_LINK_FLAGS -ltag)
+ SET(TAGLIB_INCLUDE_DIR /usr/include/taglib)
+ SET(TAGLIB_CFLAGS -I/usr/include/taglib)
+ENDIF(NOT TAGLIB_LINK_FLAGS)
+
+include_directories(${FLAC_INCLUDE_DIR} ${TAGLIB_INCLUDE_DIR})
+link_directories(${FLAC_LINK_DIR} ${TAGLIB_LINK_DIR})
+
+ADD_DEFINITIONS(${TAGLIB_CFLAGS})
+
+
+SET(libmpc_SRCS
+ decoder_mpc.cpp
+ decodermpcfactory.cpp
+ detailsdialog.cpp
+)
+
+SET(libmpc_MOC_HDRS
+ decodermpcfactory.h
+ decoder_mpc.h
+ detailsdialog.h
+)
+
+SET(libmpc_RCCS translations/translations.qrc)
+
+QT4_ADD_RESOURCES(libmpc_RCC_SRCS ${libmpc_RCCS})
+
+QT4_WRAP_CPP(libmpc_MOC_SRCS ${libmpc_MOC_HDRS})
+
+# user interface
+
+
+SET(libmpc_UIS
+ detailsdialog.ui
+)
+
+QT4_WRAP_UI(libmpc_UIS_H ${libmpc_UIS})
+# Don't forget to include output directory, otherwise
+# the UI file won't be wrapped!
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ADD_LIBRARY(mpc SHARED ${libmpc_SRCS} ${libmpc_MOC_SRCS} ${libmpc_UIS_H}
+ ${libmpc_RCC_SRCS})
+target_link_libraries(mpc ${QT_LIBRARIES} -lqmmp -lmpcdec ${TAGLIB_LINK_FLAGS} ${TAGLIB_CFLAGS})
+install(TARGETS mpc DESTINATION ${LIB_DIR}/qmmp/Input PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ)
+
+# clean remaining files
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
+ "CMakeCache.txt;Makefile;cmake_install.cmake"
+)
+
diff --git a/src/plugins/Input/mpc/Makefile b/src/plugins/Input/mpc/Makefile
new file mode 100644
index 000000000..7aa3ee7b3
--- /dev/null
+++ b/src/plugins/Input/mpc/Makefile
@@ -0,0 +1,254 @@
+#############################################################################
+# Makefile for building: libmpc.so
+# Generated by qmake (2.01a) (Qt 4.3.1) on: Thu Feb 7 14:07:02 2008
+# Project: mpc.pro
+# Template: lib
+# Command: /usr/local/Trolltech/Qt-4.3.1/bin/qmake -unix -o Makefile mpc.pro
+#############################################################################
+
+####### Compiler, tools and options
+
+CC = gcc
+CXX = g++
+DEFINES = -DQT_NO_DEBUG -DQT_PLUGIN -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED
+CFLAGS = -pipe -O2 -I/usr/include/taglib -Wall -W -D_REENTRANT -fPIC $(DEFINES)
+CXXFLAGS = -pipe -O2 -I/usr/include/taglib -Wall -W -D_REENTRANT -fPIC $(DEFINES)
+INCPATH = -I/usr/local/Trolltech/Qt-4.3.1/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.3.1/include/QtCore -I/usr/local/Trolltech/Qt-4.3.1/include/QtCore -I/usr/local/Trolltech/Qt-4.3.1/include/QtGui -I/usr/local/Trolltech/Qt-4.3.1/include/QtGui -I/usr/local/Trolltech/Qt-4.3.1/include -I../../../qmmp -I.build/moc -I.build/ui
+LINK = g++
+LFLAGS = -Wl,-rpath,/usr/local/Trolltech/Qt-4.3.1/lib -shared
+LIBS = $(SUBLIBS) -L../../../../lib -L/usr/local/Trolltech/Qt-4.3.1/lib -lqmmp -L/usr/lib -lmpcdec -I/usr/include -ltag -lQtGui -L/usr/local/Trolltech/Qt-4.3.1/lib -L/usr/X11R6/lib -lpng -lSM -lICE -pthread -pthread -lXi -lXrender -lXrandr -lXfixes -lXcursor -lXinerama -lfreetype -lfontconfig -lXext -lX11 -lQtCore -lz -lm -pthread -lgthread-2.0 -lglib-2.0 -lrt -ldl -lpthread
+AR = ar cqs
+RANLIB =
+QMAKE = /usr/local/Trolltech/Qt-4.3.1/bin/qmake
+TAR = tar -cf
+COMPRESS = gzip -9f
+COPY = cp -f
+SED = sed
+COPY_FILE = $(COPY)
+COPY_DIR = $(COPY) -r
+INSTALL_FILE = install -m 644 -p
+INSTALL_DIR = $(COPY_DIR)
+INSTALL_PROGRAM = install -m 755 -p
+DEL_FILE = rm -f
+SYMLINK = ln -sf
+DEL_DIR = rmdir
+MOVE = mv -f
+CHK_DIR_EXISTS= test -d
+MKDIR = mkdir -p
+
+####### Output directory
+
+OBJECTS_DIR = .build/obj/
+
+####### Files
+
+SOURCES = decoder_mpc.cpp \
+ decodermpcfactory.cpp \
+ detailsdialog.cpp .build/moc/moc_decodermpcfactory.cpp \
+ .build/moc/moc_detailsdialog.cpp
+OBJECTS = .build/obj/decoder_mpc.o \
+ .build/obj/decodermpcfactory.o \
+ .build/obj/detailsdialog.o \
+ .build/obj/moc_decodermpcfactory.o \
+ .build/obj/moc_detailsdialog.o
+DIST = /usr/local/Trolltech/Qt-4.3.1/mkspecs/common/g++.conf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/common/unix.conf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/common/linux.conf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/qconfig.pri \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt_functions.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt_config.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/exclusive_builds.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/default_pre.prf \
+ ../../../../qmmp.pri \
+ ../../plugins.pri \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/release.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/default_post.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/link_pkgconfig.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/warn_on.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/unix/thread.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/moc.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/resources.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/uic.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/yacc.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/lex.prf \
+ mpc.pro
+QMAKE_TARGET = mpc
+DESTDIR = ../../../../lib/qmmp/Input/
+TARGET = libmpc.so
+TARGETD = libmpc.so
+
+first: all
+####### Implicit rules
+
+.SUFFIXES: .o .c .cpp .cc .cxx .C
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
+
+####### Build rules
+
+all: Makefile ../../../../lib/qmmp/Input/$(TARGET)
+
+../../../../lib/qmmp/Input/$(TARGET): .build/ui/ui_detailsdialog.h $(OBJECTS) $(SUBLIBS) $(OBJCOMP)
+ @$(CHK_DIR_EXISTS) ../../../../lib/qmmp/Input/ || $(MKDIR) ../../../../lib/qmmp/Input/
+ -$(DEL_FILE) $(TARGET)
+ $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS) $(OBJCOMP)
+ -$(MOVE) $(TARGET) ../../../../lib/qmmp/Input/
+
+
+
+Makefile: mpc.pro /usr/local/Trolltech/Qt-4.3.1/mkspecs/linux-g++/qmake.conf /usr/local/Trolltech/Qt-4.3.1/mkspecs/common/g++.conf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/common/unix.conf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/common/linux.conf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/qconfig.pri \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt_functions.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt_config.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/exclusive_builds.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/default_pre.prf \
+ ../../../../qmmp.pri \
+ ../../plugins.pri \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/release.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/default_post.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/link_pkgconfig.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/warn_on.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/unix/thread.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/moc.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/resources.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/uic.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/yacc.prf \
+ /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/lex.prf \
+ /usr/local/Trolltech/Qt-4.3.1/lib/libQtGui.prl \
+ /usr/local/Trolltech/Qt-4.3.1/lib/libQtCore.prl
+ $(QMAKE) -unix -o Makefile mpc.pro
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/common/g++.conf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/common/unix.conf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/common/linux.conf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/qconfig.pri:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt_functions.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt_config.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/exclusive_builds.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/default_pre.prf:
+../../../../qmmp.pri:
+../../plugins.pri:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/release.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/default_post.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/link_pkgconfig.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/warn_on.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/unix/thread.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/moc.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/resources.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/uic.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/yacc.prf:
+/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/lex.prf:
+/usr/local/Trolltech/Qt-4.3.1/lib/libQtGui.prl:
+/usr/local/Trolltech/Qt-4.3.1/lib/libQtCore.prl:
+qmake: FORCE
+ @$(QMAKE) -unix -o Makefile mpc.pro
+
+dist:
+ @$(CHK_DIR_EXISTS) .build/obj/mpc1.0.0 || $(MKDIR) .build/obj/mpc1.0.0
+ $(COPY_FILE) --parents $(SOURCES) $(DIST) .build/obj/mpc1.0.0/ && $(COPY_FILE) --parents decodermpcfactory.h decoder_mpc.h detailsdialog.h .build/obj/mpc1.0.0/ && $(COPY_FILE) --parents decoder_mpc.cpp decodermpcfactory.cpp detailsdialog.cpp .build/obj/mpc1.0.0/ && $(COPY_FILE) --parents detailsdialog.ui .build/obj/mpc1.0.0/ && (cd `dirname .build/obj/mpc1.0.0` && $(TAR) mpc1.0.0.tar mpc1.0.0 && $(COMPRESS) mpc1.0.0.tar) && $(MOVE) `dirname .build/obj/mpc1.0.0`/mpc1.0.0.tar.gz . && $(DEL_FILE) -r .build/obj/mpc1.0.0
+
+
+clean:compiler_clean
+ -$(DEL_FILE) $(OBJECTS)
+ -$(DEL_FILE) ../../../../lib/qmmp/Input/libmpc.so
+ -$(DEL_FILE) *~ core *.core
+
+
+####### Sub-libraries
+
+distclean: clean
+ -$(DEL_FILE) $(TARGET)
+ -$(DEL_FILE) Makefile
+
+
+mocclean: compiler_moc_header_clean compiler_moc_source_clean
+
+mocables: compiler_moc_header_make_all compiler_moc_source_make_all
+
+compiler_moc_header_make_all: .build/moc/moc_decodermpcfactory.cpp .build/moc/moc_detailsdialog.cpp
+compiler_moc_header_clean:
+ -$(DEL_FILE) .build/moc/moc_decodermpcfactory.cpp .build/moc/moc_detailsdialog.cpp
+.build/moc/moc_decodermpcfactory.cpp: decodermpcfactory.h
+ /usr/local/Trolltech/Qt-4.3.1/bin/moc $(DEFINES) $(INCPATH) decodermpcfactory.h -o .build/moc/moc_decodermpcfactory.cpp
+
+.build/moc/moc_detailsdialog.cpp: .build/ui/ui_detailsdialog.h \
+ detailsdialog.h
+ /usr/local/Trolltech/Qt-4.3.1/bin/moc $(DEFINES) $(INCPATH) detailsdialog.h -o .build/moc/moc_detailsdialog.cpp
+
+compiler_rcc_make_all:
+compiler_rcc_clean:
+compiler_image_collection_make_all: qmake_image_collection.cpp
+compiler_image_collection_clean:
+ -$(DEL_FILE) qmake_image_collection.cpp
+compiler_moc_source_make_all:
+compiler_moc_source_clean:
+compiler_uic_make_all: .build/ui/ui_detailsdialog.h
+compiler_uic_clean:
+ -$(DEL_FILE) .build/ui/ui_detailsdialog.h
+.build/ui/ui_detailsdialog.h: detailsdialog.ui
+ /usr/local/Trolltech/Qt-4.3.1/bin/uic detailsdialog.ui -o .build/ui/ui_detailsdialog.h
+
+compiler_yacc_decl_make_all:
+compiler_yacc_decl_clean:
+compiler_yacc_impl_make_all:
+compiler_yacc_impl_clean:
+compiler_lex_make_all:
+compiler_lex_clean:
+compiler_clean: compiler_moc_header_clean compiler_uic_clean
+
+####### Compile
+
+.build/obj/decoder_mpc.o: decoder_mpc.cpp decoder_mpc.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/decoder_mpc.o decoder_mpc.cpp
+
+.build/obj/decodermpcfactory.o: decodermpcfactory.cpp detailsdialog.h \
+ .build/ui/ui_detailsdialog.h \
+ decoder_mpc.h \
+ decodermpcfactory.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/decodermpcfactory.o decodermpcfactory.cpp
+
+.build/obj/detailsdialog.o: detailsdialog.cpp detailsdialog.h \
+ .build/ui/ui_detailsdialog.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/detailsdialog.o detailsdialog.cpp
+
+.build/obj/moc_decodermpcfactory.o: .build/moc/moc_decodermpcfactory.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/moc_decodermpcfactory.o .build/moc/moc_decodermpcfactory.cpp
+
+.build/obj/moc_detailsdialog.o: .build/moc/moc_detailsdialog.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/moc_detailsdialog.o .build/moc/moc_detailsdialog.cpp
+
+####### Install
+
+install_target: first FORCE
+ @$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/lib/qmmp/Input/ || $(MKDIR) $(INSTALL_ROOT)/lib/qmmp/Input/
+ -$(INSTALL_PROGRAM) "../../../../lib/qmmp/Input/$(TARGET)" "$(INSTALL_ROOT)/lib/qmmp/Input/$(TARGET)"
+ -strip --strip-unneeded "$(INSTALL_ROOT)/lib/qmmp/Input/$(TARGET)"
+
+uninstall_target: FORCE
+ -$(DEL_FILE) "$(INSTALL_ROOT)/lib/qmmp/Input/$(TARGET)"
+ -$(DEL_DIR) $(INSTALL_ROOT)/lib/qmmp/Input/
+
+
+install: install_target FORCE
+
+uninstall: uninstall_target FORCE
+
+FORCE:
+
diff --git a/src/plugins/Input/mpc/decoder_mpc.cpp b/src/plugins/Input/mpc/decoder_mpc.cpp
new file mode 100644
index 000000000..10591a384
--- /dev/null
+++ b/src/plugins/Input/mpc/decoder_mpc.cpp
@@ -0,0 +1,386 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 "constants.h"
+#include "buffer.h"
+#include "output.h"
+#include "recycler.h"
+
+#include "decoder_mpc.h"
+
+// this function used from xmms
+inline static void copyBuffer(MPC_SAMPLE_FORMAT* pInBuf, char* pOutBuf, unsigned pLength)
+{
+ unsigned pSize = 16;
+ int clipMin = -1 << (pSize - 1);
+ int clipMax = (1 << (pSize - 1)) - 1;
+ int floatScale = 1 << (pSize - 1);
+ for (unsigned n = 0; n < 2 * pLength; n++)
+ {
+ int val;
+#ifdef MPC_FIXED_POINT
+ val = shiftSigned(pInBuf[n], pSize - MPC_FIXED_POINT_SCALE_SHIFT);
+#else
+ val = (int) (pInBuf[n] * floatScale);
+#endif
+ if (val < clipMin)
+ val = clipMin;
+ else if (val > clipMax)
+ val = clipMax;
+ unsigned shift = 0;
+ do
+ {
+ pOutBuf[n * 2 + (shift / 8)] = (unsigned char) ((val >> shift) & 0xFF);
+ shift += 8;
+ }
+ while (shift < pSize);
+ }
+}
+
+// mpc callbacks
+
+static mpc_int32_t mpc_callback_read (void *data, void *buffer, mpc_int32_t size)
+{
+ DecoderMPC *dmpc = (DecoderMPC *) data;
+ qint64 res;
+
+ res = dmpc->input()->read((char *)buffer, size);
+
+ return res;
+}
+
+static mpc_bool_t mpc_callback_seek (void *data, mpc_int32_t offset)
+{
+ DecoderMPC *dmpc = (DecoderMPC *) data;
+
+ return dmpc->input()->seek(offset); // ? TRUE : FALSE;
+}
+
+static mpc_int32_t mpc_callback_tell (void *data)
+{
+ DecoderMPC *dmpc = (DecoderMPC *) data;
+ return dmpc->input()->pos ();
+}
+
+static mpc_bool_t mpc_callback_canseek (void *data)
+{
+ DecoderMPC *dmpc = (DecoderMPC *) data;
+ return !dmpc->input()->isSequential () ;
+}
+
+static mpc_int32_t mpc_callback_get_size (void *data)
+{
+ DecoderMPC *dmpc = (DecoderMPC *) data;
+ return dmpc->input()->size();
+}
+
+// Decoder class
+
+DecoderMPC::DecoderMPC(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o)
+ : Decoder(parent, d, i, o)
+{
+ inited = FALSE;
+ user_stop = FALSE;
+ stat = 0;
+ output_buf = 0;
+ output_bytes = 0;
+ output_at = 0;
+ bks = 0;
+ done = FALSE;
+ finish = FALSE;
+ len = 0;
+ freq = 0;
+ bitrate = 0;
+ seekTime = -1.0;
+ totalTime = 0.0;
+ chan = 0;
+ output_size = 0;
+ m_data = 0;
+
+
+
+
+}
+
+
+DecoderMPC::~DecoderMPC()
+{
+ deinit();
+ if(data())
+ {
+ delete data();
+ m_data = 0;
+ }
+ if (output_buf)
+ delete [] output_buf;
+ output_buf = 0;
+}
+
+
+void DecoderMPC::stop()
+{
+ user_stop = TRUE;
+}
+
+
+void DecoderMPC::flush(bool final)
+{
+ ulong min = final ? 0 : bks;
+
+ while ((! done && ! finish) && output_bytes > min)
+ {
+ output()->recycler()->mutex()->lock ();
+
+ while ((! done && ! finish) && output()->recycler()->full())
+ {
+ mutex()->unlock();
+
+ output()->recycler()->cond()->wait(output()->recycler()->mutex());
+
+ mutex()->lock ();
+ done = user_stop;
+ }
+
+ if (user_stop || finish)
+ {
+ inited = FALSE;
+ done = TRUE;
+ }
+ else
+ {
+ output_bytes -= produceSound(output_buf, output_bytes, bitrate, chan);
+ output_size += bks;
+ output_at = output_bytes;
+ }
+
+ if (output()->recycler()->full())
+ {
+ output()->recycler()->cond()->wakeOne();
+ }
+
+ output()->recycler()->mutex()->unlock();
+ }
+}
+
+
+bool DecoderMPC::initialize()
+{
+ bks = blockSize();
+ inited = user_stop = done = finish = FALSE;
+ len = freq = bitrate = 0;
+ stat = chan = 0;
+ output_size = 0;
+ seekTime = -1.0;
+ totalTime = 0.0;
+
+
+ if (! input())
+ {
+ error("DecoderMPC: cannot initialize. No input.");
+
+ return FALSE;
+ }
+
+ if (! output_buf)
+ output_buf = new char[globalBufferSize];
+ output_at = 0;
+ output_bytes = 0;
+
+ if (! input())
+ {
+ error("DecoderMPC: cannot initialize. No input.");
+
+ return FALSE;
+ }
+
+ if (! output_buf)
+ output_buf = new char[globalBufferSize];
+ output_at = 0;
+ output_bytes = 0;
+
+ if (! input()->isOpen())
+ {
+ if (! input()->open(QIODevice::ReadOnly))
+ {
+ error("DecoderMPC: cannot open input.");
+ return FALSE;
+ }
+ }
+ if (!m_data)
+ {
+ m_data = new mpc_data;
+ }
+
+ qDebug("DecoderMPC: setting callbacks");
+ m_data->reader.read = mpc_callback_read;
+ m_data->reader.seek = mpc_callback_seek;
+ m_data->reader.tell = mpc_callback_tell;
+ m_data->reader.canseek = mpc_callback_canseek;
+ m_data->reader.get_size = mpc_callback_get_size;
+ m_data->reader.data = this;
+
+ mpc_streaminfo_init (&m_data->info);
+
+ if (mpc_streaminfo_read (&m_data->info, &m_data->reader) != ERROR_CODE_OK)
+ return FALSE;
+ chan = data()->info.channels;
+ configure(data()->info.sample_freq, chan, 16, data()->info.bitrate);
+
+ mpc_decoder_setup (&data()->decoder, &data()->reader);
+
+ //mpc_decoder_scale_output (&data()->decoder, 3.0);
+
+ if (!mpc_decoder_initialize (&data()->decoder, &data()->info))
+ {
+ error("DecoderMPC: cannot get info.");
+ return FALSE;
+ }
+ totalTime = mpc_streaminfo_get_length(&data()->info);
+ inited = TRUE;
+ qDebug("DecoderMPC: initialize succes");
+ return TRUE;
+}
+
+
+double DecoderMPC::lengthInSeconds()
+{
+ if (! inited)
+ return 0;
+
+ return totalTime;
+}
+
+
+void DecoderMPC::seek(double pos)
+{
+ seekTime = pos;
+}
+
+
+void DecoderMPC::deinit()
+{
+ //FLAC__stream_decoder_finish (data()->decoder);
+ inited = user_stop = done = finish = FALSE;
+ len = freq = bitrate = 0;
+ stat = chan = 0;
+ output_size = 0;
+}
+
+void DecoderMPC::run()
+{
+ mpc_uint32_t vbrAcc = 0;
+ mpc_uint32_t vbrUpd = 0;
+ mutex()->lock ();
+
+ if (! inited)
+ {
+ mutex()->unlock();
+
+ return;
+ }
+ stat = DecoderState::Decoding;
+ mutex()->unlock();
+ {
+ dispatch(DecoderState ((DecoderState::Type) stat));
+ }
+
+ while (! done && ! finish)
+ {
+ mutex()->lock ();
+ // decode
+
+ if (seekTime >= 0.0)
+ {
+ mpc_decoder_seek_seconds(&data()->decoder, seekTime);
+ seekTime = -1.0;
+ }
+ MPC_SAMPLE_FORMAT buffer[MPC_DECODER_BUFFER_LENGTH];
+
+ len = mpc_decoder_decode (&data()->decoder, buffer, &vbrAcc, &vbrUpd);
+
+ copyBuffer(buffer, (char *) (output_buf + output_at), len);
+
+ len = len * 4;
+
+ if (len > 0)
+ {
+ bitrate = vbrUpd * data()->info.sample_freq / 1152;
+ output_at += len;
+ 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() && ! user_stop)
+ {
+ output()->recycler()->cond()->wakeOne();
+ mutex()->unlock();
+ output()->recycler()->cond()->wait(output()->recycler()->mutex());
+ mutex()->lock ();
+ }
+ output()->recycler()->mutex()->unlock();
+ }
+
+ done = TRUE;
+ if (! user_stop)
+ {
+ finish = TRUE;
+ }
+ }
+ else
+ {
+ // error in read
+ error("DecoderMPC: Error while decoding stream, File appears to be "
+ "corrupted");
+
+ finish = TRUE;
+ }
+
+ mutex()->unlock();
+ }
+
+ mutex()->lock ();
+
+ if (finish)
+ stat = DecoderState::Finished;
+ else if (user_stop)
+ stat = DecoderState::Stopped;
+
+ mutex()->unlock();
+
+ {
+ dispatch(DecoderState ((DecoderState::Type) stat));
+ }
+
+ deinit();
+}
diff --git a/src/plugins/Input/mpc/decoder_mpc.h b/src/plugins/Input/mpc/decoder_mpc.h
new file mode 100644
index 000000000..3b17b100e
--- /dev/null
+++ b/src/plugins/Input/mpc/decoder_mpc.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ * Copyright (C) 2006 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_mpc_h
+#define __decoder_mpc_h
+
+#include <mpcdec/mpcdec.h>
+
+#include "decoder.h"
+
+struct mpc_data
+{
+ mpc_decoder decoder;
+ mpc_reader reader;
+ mpc_streaminfo info;
+};
+
+class DecoderMPC : public Decoder
+{
+public:
+ DecoderMPC(QObject *, DecoderFactory *, QIODevice *, Output *);
+ virtual ~DecoderMPC();
+
+ // Standard Decoder API
+ bool initialize();
+ double lengthInSeconds();
+ void seek(double);
+ void stop();
+
+ // Equalizer
+ bool isEQSupported() const { return FALSE; }
+ void setEQEnabled(bool) { ; }
+ void setEQGain(int) { ; }
+ void setEQBands(int[10]) { ; }
+
+ struct mpc_data *data() { return m_data; }
+
+
+private:
+ // thread run function
+ void run();
+ struct mpc_data *m_data;
+ // helper functions
+ void flush(bool = FALSE);
+ void deinit();
+
+ bool inited, user_stop;
+ int stat;
+
+ // output buffer
+ char *output_buf;
+ ulong output_bytes, output_at;
+
+ unsigned int bks;
+ bool done, finish;
+ long len, freq, bitrate;
+ int chan;
+ unsigned long output_size;
+ double totalTime, seekTime;
+};
+
+
+#endif // __decoder_mpc_h
diff --git a/src/plugins/Input/mpc/decodermpcfactory.cpp b/src/plugins/Input/mpc/decodermpcfactory.cpp
new file mode 100644
index 000000000..f2874a08d
--- /dev/null
+++ b/src/plugins/Input/mpc/decodermpcfactory.cpp
@@ -0,0 +1,95 @@
+#include <QtGui>
+#include <taglib/tag.h>
+#include <taglib/fileref.h>
+
+#include "detailsdialog.h"
+#include "decoder_mpc.h"
+#include "decodermpcfactory.h"
+
+
+// DecoderMPCFactory
+
+bool DecoderMPCFactory::supports(const QString &source) const
+{
+
+ return (source.right(4).toLower() == ".mpc");
+}
+
+bool DecoderMPCFactory::canDecode(QIODevice *) const
+{
+ return FALSE;
+}
+
+const DecoderProperties DecoderMPCFactory::properties() const
+{
+ DecoderProperties properties;
+ properties.name = tr("Musepack Plugin");
+ properties.filter = "*.mpc";
+ properties.description = tr("Musepack Files");
+ //properties.contentType = ;
+ properties.hasAbout = TRUE;
+ properties.hasSettings = FALSE;
+ return properties;
+}
+
+Decoder *DecoderMPCFactory::create(QObject *parent, QIODevice *input,
+ Output *output)
+{
+ return new DecoderMPC(parent, this, input, output);
+}
+
+FileTag *DecoderMPCFactory::createTag(const QString &source)
+{
+ FileTag *ftag = new FileTag();
+
+ TagLib::FileRef fileRef(source.toLocal8Bit ());
+ TagLib::Tag *tag = fileRef.tag();
+
+ if (tag && !tag->isEmpty())
+ {
+ ftag->setValue(FileTag::ALBUM,
+ QString::fromUtf8(tag->album().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::ARTIST,
+ QString::fromUtf8(tag->artist().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::COMMENT,
+ QString::fromUtf8(tag->comment().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::GENRE,
+ QString::fromUtf8(tag->genre().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::TITLE,
+ QString::fromUtf8(tag->title().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::YEAR, tag->year());
+ ftag->setValue(FileTag::TRACK, tag->track());
+ }
+
+ if (fileRef.audioProperties())
+ ftag->setValue(FileTag::LENGTH, fileRef.audioProperties()->length());
+
+ return ftag;
+}
+
+QObject* DecoderMPCFactory::showDetails(QWidget *parent, const QString &path)
+{
+ DetailsDialog *d = new DetailsDialog(parent, path);
+ d -> show();
+ return d;
+}
+
+void DecoderMPCFactory::showSettings(QWidget *)
+{}
+
+void DecoderMPCFactory::showAbout(QWidget *parent)
+{
+ QMessageBox::about (parent, tr("About Musepack Audio Plugin"),
+ tr("Qmmp Musepack Audio Plugin")+"\n"+
+ tr("Writen by: Ilya Kotov <forkotov02@hotmail.ru>"));
+}
+
+QTranslator *DecoderMPCFactory::createTranslator(QObject *parent)
+{
+ QTranslator *translator = new QTranslator(parent);
+ QString locale = QLocale::system().name();
+ translator->load(QString(":/mpc_plugin_") + locale);
+ return translator;
+}
+
+Q_EXPORT_PLUGIN(DecoderMPCFactory)
diff --git a/src/plugins/Input/mpc/decodermpcfactory.h b/src/plugins/Input/mpc/decodermpcfactory.h
new file mode 100644
index 000000000..0f8dda55f
--- /dev/null
+++ b/src/plugins/Input/mpc/decodermpcfactory.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 DECODERMPCFACTORY_H
+#define DECODERMPCFACTORY_H
+
+#include <QObject>
+#include <QString>
+#include <QIODevice>
+#include <QWidget>
+
+#include <decoder.h>
+#include <output.h>
+#include <decoderfactory.h>
+#include <filetag.h>
+
+
+
+
+class DecoderMPCFactory : 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/mpc/detailsdialog.cpp b/src/plugins/Input/mpc/detailsdialog.cpp
new file mode 100644
index 000000000..472046717
--- /dev/null
+++ b/src/plugins/Input/mpc/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/mpc/detailsdialog.h b/src/plugins/Input/mpc/detailsdialog.h
new file mode 100644
index 000000000..70540bda1
--- /dev/null
+++ b/src/plugins/Input/mpc/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/mpc/detailsdialog.ui b/src/plugins/Input/mpc/detailsdialog.ui
new file mode 100644
index 000000000..918dd3abf
--- /dev/null
+++ b/src/plugins/Input/mpc/detailsdialog.ui
@@ -0,0 +1,349 @@
+<ui version="4.0" >
+ <class>DetailsDialog</class>
+ <widget class="QDialog" name="DetailsDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>449</width>
+ <height>375</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Details</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item rowspan="2" row="1" column="0" colspan="2" >
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="minimumSize" >
+ <size>
+ <width>175</width>
+ <height>16</height>
+ </size>
+ </property>
+ <property name="title" >
+ <string>Musepack Info</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <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="0" column="1" colspan="3" >
+ <widget class="QLineEdit" name="pathLineEdit" >
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <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="2" column="3" >
+ <widget class="QPushButton" name="pushButton_3" >
+ <property name="text" >
+ <string>Close</string>
+ </property>
+ </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="1" column="2" colspan="2" >
+ <widget class="QGroupBox" name="groupBox_2" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Musepack Tag</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="6" column="1" colspan="2" >
+ <widget class="QPushButton" name="saveButton" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="3" >
+ <widget class="QLineEdit" name="trackLineEdit" />
+ </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="1" >
+ <widget class="QLineEdit" name="yearLineEdit" />
+ </item>
+ <item row="4" column="0" >
+ <widget class="QLabel" name="label_25" >
+ <property name="text" >
+ <string>Year:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0" >
+ <widget class="QLabel" name="label_27" >
+ <property name="text" >
+ <string>Genre:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="label_24" >
+ <property name="text" >
+ <string>Comment:</string>
+ </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_23" >
+ <property name="text" >
+ <string>Album:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_22" >
+ <property name="text" >
+ <string>Artist:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_21" >
+ <property name="text" >
+ <string>Title:</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="titleLineEdit" />
+ </item>
+ <item row="1" column="1" colspan="3" >
+ <widget class="QLineEdit" name="artistLineEdit" />
+ </item>
+ <item row="2" column="1" colspan="3" >
+ <widget class="QLineEdit" name="albumLineEdit" />
+ </item>
+ <item row="3" column="1" colspan="3" >
+ <widget class="QLineEdit" name="commentLineEdit" />
+ </item>
+ <item row="5" column="1" colspan="2" >
+ <widget class="QLineEdit" name="genreLineEdit" />
+ </item>
+ </layout>
+ </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>
diff --git a/src/plugins/Input/mpc/mpc.pro b/src/plugins/Input/mpc/mpc.pro
new file mode 100644
index 000000000..f1a50683d
--- /dev/null
+++ b/src/plugins/Input/mpc/mpc.pro
@@ -0,0 +1,32 @@
+include(../../plugins.pri)
+
+FORMS += detailsdialog.ui
+HEADERS += decodermpcfactory.h \
+ decoder_mpc.h \
+ detailsdialog.h
+SOURCES += decoder_mpc.cpp \
+ decodermpcfactory.cpp \
+ detailsdialog.cpp
+
+TARGET=$$PLUGINS_PREFIX/Input/mpc
+QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libmpc.so
+
+
+INCLUDEPATH += ../../../qmmp
+CONFIG += release \
+warn_on \
+plugin \
+link_pkgconfig
+TEMPLATE = lib
+QMAKE_LIBDIR += ../../../../lib
+LIBS += -lqmmp -L/usr/lib -lmpcdec -I/usr/include
+PKGCONFIG += taglib
+#TRANSLATIONS = translations/mpc_plugin_ru.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/mpc/translations/mpc_plugin_ru.qm b/src/plugins/Input/mpc/translations/mpc_plugin_ru.qm
new file mode 100644
index 000000000..0eb8c1533
--- /dev/null
+++ b/src/plugins/Input/mpc/translations/mpc_plugin_ru.qm
Binary files differ
diff --git a/src/plugins/Input/mpc/translations/mpc_plugin_ru.ts b/src/plugins/Input/mpc/translations/mpc_plugin_ru.ts
new file mode 100644
index 000000000..53ecd8dc8
--- /dev/null
+++ b/src/plugins/Input/mpc/translations/mpc_plugin_ru.ts
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS><TS version="1.1" language="ru">
+<context>
+ <name>DecoderMPCFactory</name>
+ <message>
+ <location filename="../decodermpcfactory.cpp" line="21"/>
+ <source>Musepack Plugin</source>
+ <translation>Модуль Musepack</translation>
+ </message>
+ <message>
+ <location filename="../decodermpcfactory.cpp" line="35"/>
+ <source>Musepack Files</source>
+ <translation>Файлы Musepack</translation>
+ </message>
+ <message>
+ <location filename="../decodermpcfactory.cpp" line="63"/>
+ <source>About Musepack Audio Plugin</source>
+ <translation>Об аудио-модуле Musepack</translation>
+ </message>
+ <message>
+ <location filename="../decodermpcfactory.cpp" line="64"/>
+ <source>Qmmp Musepack Audio Plugin</source>
+ <translation>Аудио-модуль Musepack для Qmmp</translation>
+ </message>
+ <message>
+ <location filename="../decodermpcfactory.cpp" line="65"/>
+ <source>Writen by: Ilya Kotov &lt;forkotov02@hotmail.ru&gt;</source>
+ <translation>Разработчик: Илья Котов &lt;forkotov02@hotmail.ru&gt;</translation>
+ </message>
+</context>
+<context>
+ <name>DetailsDialog</name>
+ <message>
+ <location filename="../detailsdialog.cpp" line="52"/>
+ <source>Hz</source>
+ <translation>Гц</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="31"/>
+ <source>Musepack Info</source>
+ <translation>Информация Musepack</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="160"/>
+ <source>-</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="63"/>
+ <source>Length:</source>
+ <translation>Длительность:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="80"/>
+ <source>Sample rate:</source>
+ <translation>Дискретизация:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="100"/>
+ <source>Channels:</source>
+ <translation>Каналов:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="113"/>
+ <source>File size:</source>
+ <translation>Размер файла:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="123"/>
+ <source>Bitrate:</source>
+ <translation>Битовая частота:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="150"/>
+ <source>Stream version:</source>
+ <translation>Версия потока:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="177"/>
+ <source>File path:</source>
+ <translation>Путь к файлу:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="187"/>
+ <source>Close</source>
+ <translation>Закрыть</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="215"/>
+ <source>Musepack Tag</source>
+ <translation>Musepack-тег</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="230"/>
+ <source>Save</source>
+ <translation>Сохранить</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="240"/>
+ <source>Track number:</source>
+ <translation>Номер трека:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="253"/>
+ <source>Year:</source>
+ <translation>Год:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="263"/>
+ <source>Genre:</source>
+ <translation>Жанр:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="273"/>
+ <source>Comment:</source>
+ <translation>Комментарий:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="283"/>
+ <source>Album:</source>
+ <translation>Альбом:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="293"/>
+ <source>Artist:</source>
+ <translation>Исполнитель:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="303"/>
+ <source>Title:</source>
+ <translation>Название:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="13"/>
+ <source>Details</source>
+ <translation>Информация</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="56"/>
+ <source>kbps</source>
+ <translation>Кб/с</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="59"/>
+ <source>KB</source>
+ <translation>Кб</translation>
+ </message>
+</context>
+</TS>
diff --git a/src/plugins/Input/mpc/translations/translations.qrc b/src/plugins/Input/mpc/translations/translations.qrc
new file mode 100644
index 000000000..cc88de9ce
--- /dev/null
+++ b/src/plugins/Input/mpc/translations/translations.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file>mpc_plugin_ru.qm</file>
+ </qresource>
+</RCC>
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
diff --git a/src/plugins/Input/vorbis/CMakeLists.txt b/src/plugins/Input/vorbis/CMakeLists.txt
new file mode 100644
index 000000000..baf5bad8c
--- /dev/null
+++ b/src/plugins/Input/vorbis/CMakeLists.txt
@@ -0,0 +1,96 @@
+project(libvorbis)
+
+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}/../../../)
+
+# libvorbis and taglib
+PKGCONFIG(ogg OGG_INCLUDE_DIR OGG_LINK_DIR OGG_LINK_FLAGS OGG_CFLAGS)
+PKGCONFIG(vorbis VORBIS_INCLUDE_DIR VORBIS_LINK_DIR VORBIS_LINK_FLAGS VORBIS_CFLAGS)
+PKGCONFIG(vorbisfile VORBISFILE_INCLUDE_DIR VORBISFILE_LINK_DIR VORBISFILE_LINK_FLAGS VORBISFILE_CFLAGS)
+
+PKGCONFIG(taglib TAGLIB_INCLUDE_DIR TAGLIB_LINK_DIR TAGLIB_LINK_FLAGS TAGLIB_CFLAGS)
+
+IF(NOT OGG_LINK_FLAGS)
+ SET(OGG_LINK_FLAGS -logg)
+ENDIF(NOT OGG_LINK_FLAGS)
+
+IF(NOT VORBIS_LINK_FLAGS)
+ SET(VORBIS_LINK_FLAGS -lvorbis)
+ENDIF(NOT VORBIS_LINK_FLAGS)
+
+IF(NOT VORBISFILE_LINK_FLAGS)
+ SET(VORBISFILE_LINK_FLAGS -lvorbisfile)
+ENDIF(NOT VORBISFILE_LINK_FLAGS)
+
+IF(NOT TAGLIB_LINK_FLAGS)
+ SET(TAGLIB_LINK_FLAGS -ltag)
+ SET(TAGLIB_INCLUDE_DIR /usr/include/taglib)
+ SET(TAGLIB_CFLAGS -I/usr/include/taglib)
+ENDIF(NOT TAGLIB_LINK_FLAGS)
+
+include_directories(${VORBIS_INCLUDE_DIR} ${TAGLIB_INCLUDE_DIR})
+link_directories(${VORBIS_LINK_DIR} ${TAGLIB_LINK_DIR})
+
+#ADD_DEFINITIONS(${VORBIS_CFLAGS})
+ADD_DEFINITIONS(${TAGLIB_CFLAGS})
+
+
+SET(libvorbis_SRCS
+ decoder_vorbis.cpp
+ decodervorbisfactory.cpp
+ detailsdialog.cpp
+)
+
+SET(libvorbis_MOC_HDRS
+ decodervorbisfactory.h
+ decoder_vorbis.h
+ detailsdialog.h
+)
+
+SET(libvorbis_RCCS translations/translations.qrc)
+
+QT4_ADD_RESOURCES(libvorbis_RCC_SRCS ${libvorbis_RCCS})
+
+QT4_WRAP_CPP(libvorbis_MOC_SRCS ${libvorbis_MOC_HDRS})
+
+# user interface
+
+
+SET(libvorbis_UIS
+ detailsdialog.ui
+)
+
+QT4_WRAP_UI(libvorbis_UIS_H ${libvorbis_UIS})
+# Don't forget to include output directory, otherwise
+# the UI file won't be wrapped!
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ADD_LIBRARY(vorbis SHARED ${libvorbis_SRCS} ${libvorbis_MOC_SRCS} ${libvorbis_UIS_H}
+ ${libvorbis_RCC_SRCS})
+target_link_libraries(vorbis ${QT_LIBRARIES} -lqmmp ${VORBIS_LINK_FLAGS} ${VORBISFILE_LINK_FLAGS} ${OGG_LINK_FLAGS} ${TAGLIB_LINK_FLAGS} ${TAGLIB_CFLAGS})
+install(TARGETS vorbis DESTINATION ${LIB_DIR}/qmmp/Input PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ)
diff --git a/src/plugins/Input/vorbis/decoder_vorbis.cpp b/src/plugins/Input/vorbis/decoder_vorbis.cpp
new file mode 100644
index 000000000..31fb99c6f
--- /dev/null
+++ b/src/plugins/Input/vorbis/decoder_vorbis.cpp
@@ -0,0 +1,425 @@
+// Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com>
+//
+// Use, modification and distribution is allowed without limitation,
+// warranty, or liability of any kind.
+//
+
+#include "decoder_vorbis.h"
+#include "constants.h"
+#include "buffer.h"
+#include "output.h"
+#include "recycler.h"
+#include "filetag.h"
+
+#include <QObject>
+#include <QIODevice>
+
+
+// ic functions for OggVorbis
+
+static size_t oggread (void *buf, size_t size, size_t nmemb, void *src)
+{
+ if (! src) return 0;
+
+ DecoderVorbis *dogg = (DecoderVorbis *) src;
+ int len = dogg->input()->read((char *) buf, (size * nmemb));
+ return len / size;
+}
+
+
+static int oggseek(void *src, int64_t offset, int whence)
+{
+ DecoderVorbis *dogg = (DecoderVorbis *) src;
+
+ if ( dogg->input()->isSequential ())
+ return -1;
+
+ long start = 0;
+ switch (whence)
+ {
+ case SEEK_END:
+ start = dogg->input()->size();
+ break;
+
+ case SEEK_CUR:
+ start = dogg->input()->pos();
+ break;
+
+ case SEEK_SET:
+ default:
+ start = 0;
+ }
+
+ if (dogg->input()->seek(start + offset))
+ return 0;
+ return -1;
+}
+
+
+static int oggclose(void *src)
+{
+ DecoderVorbis *dogg = (DecoderVorbis *) src;
+ dogg->input()->close();
+ return 0;
+}
+
+
+static long oggtell(void *src)
+{
+ DecoderVorbis *dogg = (DecoderVorbis *) src;
+ long t = dogg->input()->pos();
+ return t;
+}
+
+
+// Decoder class
+
+DecoderVorbis::DecoderVorbis(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o)
+ : Decoder(parent, d, i, o)
+{
+ inited = FALSE;
+ user_stop = FALSE;
+ stat = 0;
+ output_buf = 0;
+ output_bytes = 0;
+ output_at = 0;
+ bks = 0;
+ done = FALSE;
+ finish = FALSE;
+ len = 0;
+ freq = 0;
+ bitrate = 0;
+ seekTime = -1.0;
+ totalTime = 0.0;
+ chan = 0;
+ output_size = 0;
+}
+
+
+DecoderVorbis::~DecoderVorbis()
+{
+ deinit();
+
+ if (output_buf)
+ delete [] output_buf;
+ output_buf = 0;
+}
+
+
+void DecoderVorbis::stop()
+{
+ user_stop = TRUE;
+}
+
+
+void DecoderVorbis::flush(bool final)
+{
+ ulong min = final ? 0 : bks;
+
+ while ((! done && ! finish) && output_bytes > min)
+ {
+ output()->recycler()->mutex()->lock ();
+
+ while ((! done && ! finish) && output()->recycler()->full())
+ {
+ mutex()->unlock();
+
+ output()->recycler()->cond()->wait(output()->recycler()->mutex());
+
+ mutex()->lock ();
+ done = user_stop;
+ }
+
+ if (user_stop || finish)
+ {
+ inited = FALSE;
+ done = TRUE;
+ }
+ else
+ {
+ /*ulong sz = output_bytes < bks ? output_bytes : bks;
+ Buffer *b = output()->recycler()->get();
+
+ memcpy(b->data, output_buf, sz);
+ if (sz != bks) memset(b->data + sz, 0, bks - sz);
+
+ b->nbytes = bks;
+ b->rate = bitrate;
+ output_size += b->nbytes;
+ output()->recycler()->add();
+
+ output_bytes -= sz;
+ memmove(output_buf, output_buf + sz, output_bytes);*/
+ output_bytes -= produceSound(output_buf, output_bytes, bitrate, chan);
+ output_size += bks;
+ output_at = output_bytes;
+ }
+
+ if (output()->recycler()->full())
+ {
+ output()->recycler()->cond()->wakeOne();
+ }
+
+ output()->recycler()->mutex()->unlock();
+ }
+}
+
+
+bool DecoderVorbis::initialize()
+{
+ qDebug("DecoderVorbis: initialize");
+ bks = blockSize();
+
+ inited = user_stop = done = finish = FALSE;
+ len = freq = bitrate = 0;
+ stat = chan = 0;
+ output_size = 0;
+ seekTime = -1.0;
+ totalTime = 0.0;
+ if (! input())
+ {
+ qDebug("DecoderVorbis: cannot initialize. No input");
+
+ return FALSE;
+ }
+
+ if (! output_buf)
+ output_buf = new char[globalBufferSize];
+ output_at = 0;
+ output_bytes = 0;
+
+ if (! input()->isOpen())
+ {
+ if (! input()->open(QIODevice::ReadOnly))
+ {
+ qWarning(qPrintable("DecoderVorbis: failed to open input. " +
+ input()->errorString () + "."));
+ return FALSE;
+ }
+ }
+
+ ov_callbacks oggcb =
+ {
+ oggread,
+ oggseek,
+ oggclose,
+ oggtell
+ };
+ if (ov_open_callbacks(this, &oggfile, NULL, 0, oggcb) < 0)
+ {
+ qWarning("DecoderVorbis: cannot open stream");
+
+ return FALSE;
+ }
+
+ freq = 0;
+ bitrate = ov_bitrate(&oggfile, -1) / 1000;
+ chan = 0;
+
+ totalTime = long(ov_time_total(&oggfile, 0));
+ totalTime = totalTime < 0 ? 0 : totalTime;
+
+ vorbis_info *ogginfo = ov_info(&oggfile, -1);
+ if (ogginfo)
+ {
+ freq = ogginfo->rate;
+ chan = ogginfo->channels;
+ }
+
+ configure(freq, chan, 16, bitrate);
+
+ inited = TRUE;
+ return TRUE;
+}
+
+
+double DecoderVorbis::lengthInSeconds()
+{
+ if (! inited)
+ return 0;
+
+ return totalTime;
+}
+
+
+void DecoderVorbis::seek(double pos)
+{
+ seekTime = pos;
+}
+
+
+void DecoderVorbis::deinit()
+{
+ if (inited)
+ ov_clear(&oggfile);
+ inited = user_stop = done = finish = FALSE;
+ len = freq = bitrate = 0;
+ stat = chan = 0;
+ output_size = 0;
+}
+
+void DecoderVorbis::updateTags()
+{
+ int i;
+ vorbis_comment *comments;
+
+ FileTag tag;
+ comments = ov_comment (&oggfile, -1);
+ for (i = 0; i < comments->comments; i++)
+ {
+ if (!strncasecmp(comments->user_comments[i], "title=",
+ strlen ("title=")))
+ tag.setValue(FileTag::TITLE, QString::fromUtf8(comments->user_comments[i]
+ + strlen ("title=")));
+ else if (!strncasecmp(comments->user_comments[i],
+ "artist=", strlen ("artist=")))
+ tag.setValue(FileTag::ARTIST,
+ QString::fromUtf8(comments->user_comments[i]
+ + strlen ("artist=")));
+ else if (!strncasecmp(comments->user_comments[i],
+ "album=", strlen ("album=")))
+ tag.setValue(FileTag::ALBUM,
+ QString::fromUtf8(comments->user_comments[i]
+ + strlen ("album=")));
+ else if (!strncasecmp(comments->user_comments[i],
+ "comment=", strlen ("comment=")))
+ tag.setValue(FileTag::COMMENT,
+ QString::fromUtf8(comments->user_comments[i]
+ + strlen ("comment=")));
+ else if (!strncasecmp(comments->user_comments[i],
+ "genre=", strlen ("genre=")))
+ tag.setValue(FileTag::GENRE, QString::fromUtf8 (comments->user_comments[i]
+ + strlen ("genre=")));
+ else if (!strncasecmp(comments->user_comments[i],
+ "tracknumber=",
+ strlen ("tracknumber=")))
+ tag.setValue(FileTag::TRACK, atoi (comments->user_comments[i]
+ + strlen ("tracknumber=")));
+ else if (!strncasecmp(comments->user_comments[i],
+ "track=", strlen ("track=")))
+ tag.setValue(FileTag::TRACK, atoi (comments->user_comments[i]
+ + strlen ("track=")));
+ else if (!strncasecmp(comments->user_comments[i],
+ "date=", strlen ("date=")))
+ tag.setValue(FileTag::YEAR, atoi (comments->user_comments[i]
+ + strlen ("date=")));
+
+ }
+ tag.setValue(FileTag::LENGTH, uint(totalTime));
+ dispatch(tag);
+}
+
+void DecoderVorbis::run()
+{
+ mutex()->lock ();
+
+ if (! inited)
+ {
+ mutex()->unlock();
+
+ return;
+ }
+
+ //stat = DecoderEvent::Decoding;
+ stat = DecoderState::Decoding;
+ mutex()->unlock();
+
+ {
+ //DecoderEvent e((DecoderEvent::Type) stat);
+ //dispatch(e);
+ //DecoderStatus st ((DecoderStatus::Type) stat);
+ dispatch(DecoderState ((DecoderState::Type) stat));
+
+ //emit statusChanged(stat);
+ }
+
+ int section = 0;
+ int last_section = -1;
+
+ while (! done && ! finish)
+ {
+ mutex()->lock ();
+ // decode
+
+ if (seekTime >= 0.0)
+ {
+ ov_time_seek(&oggfile, double(seekTime));
+ seekTime = -1.0;
+
+ output_size = long(ov_time_tell(&oggfile)) * long(freq * chan * 2);
+ }
+ len = -1;
+ while (len < 0)
+ {
+ len = ov_read(&oggfile, (char *) (output_buf + output_at), bks, 0, 2, 1,
+ &section);
+ }
+ if (section != last_section)
+ updateTags();
+ last_section = section;
+
+ if (len > 0)
+ {
+ bitrate = ov_bitrate_instant(&oggfile) / 1000;
+
+ output_at += len;
+ 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() && ! user_stop)
+ {
+ output()->recycler()->cond()->wakeOne();
+ mutex()->unlock();
+ output()->recycler()->cond()->wait(output()->recycler()->mutex());
+ mutex()->lock ();
+ }
+ output()->recycler()->mutex()->unlock();
+ }
+
+ done = TRUE;
+ if (! user_stop)
+ {
+ finish = TRUE;
+ }
+ }
+ else
+ {
+ // error in read
+ error("DecoderVorbis: Error while decoding stream, File appears to be "
+ "corrupted");
+
+ finish = TRUE;
+ }
+
+ mutex()->unlock();
+ }
+
+ mutex()->lock ();
+
+ if (finish)
+ stat = DecoderState::Finished;
+ else if (user_stop)
+ stat = DecoderState::Stopped;
+
+ mutex()->unlock();
+
+ {
+ /*DecoderEvent e((DecoderEvent::Type) stat);
+ dispatch(e);*/
+ //DecoderStatus st ((DecoderStatus::Type) stat);
+ //emit statusChanged(st);
+ dispatch(DecoderState ((DecoderState::Type) stat));
+ }
+
+ deinit();
+}
diff --git a/src/plugins/Input/vorbis/decoder_vorbis.h b/src/plugins/Input/vorbis/decoder_vorbis.h
new file mode 100644
index 000000000..091d856ff
--- /dev/null
+++ b/src/plugins/Input/vorbis/decoder_vorbis.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com>
+//
+// Use, modification and distribution is allowed without limitation,
+// warranty, or liability of any kind.
+//
+
+#ifndef __decoder_vorbis_h
+#define __decoder_vorbis_h
+
+#include "decoder.h"
+
+#include <vorbis/vorbisfile.h>
+
+
+class DecoderVorbis : public Decoder
+{
+public:
+ DecoderVorbis(QObject *, DecoderFactory *, QIODevice *, Output *);
+ virtual ~DecoderVorbis();
+
+ // Standard Decoder API
+ bool initialize();
+ double lengthInSeconds();
+ void seek(double);
+ void stop();
+
+ // Equalizer
+ bool isEQSupported() const { return FALSE; }
+ void setEQEnabled(bool) { ; }
+ void setEQGain(int) { ; }
+ void setEQBands(int[10]) { ; }
+
+
+private:
+ // thread run function
+ void run();
+
+ // helper functions
+ void flush(bool = FALSE);
+ void deinit();
+
+ void updateTags();
+
+ bool inited, user_stop;
+ int stat;
+
+ // output buffer
+ char *output_buf;
+ ulong output_bytes, output_at;
+
+ // OggVorbis Decoder
+ OggVorbis_File oggfile;
+
+ unsigned int bks;
+ bool done, finish;
+ long len, freq, bitrate;
+ int chan;
+ unsigned long output_size;
+ double totalTime, seekTime;
+};
+
+
+#endif // __decoder_vorbis_h
diff --git a/src/plugins/Input/vorbis/decodervorbisfactory.cpp b/src/plugins/Input/vorbis/decodervorbisfactory.cpp
new file mode 100644
index 000000000..c3b31ec52
--- /dev/null
+++ b/src/plugins/Input/vorbis/decodervorbisfactory.cpp
@@ -0,0 +1,105 @@
+#include <QtGui>
+#include <taglib/tag.h>
+#include <taglib/fileref.h>
+#include <tag.h>
+
+#include "detailsdialog.h"
+#include "decoder_vorbis.h"
+#include "decodervorbisfactory.h"
+
+
+// DecoderOggFactory
+
+bool DecoderVorbisFactory::supports(const QString &source) const
+{
+ return source.right(4).toLower() == ".ogg";
+}
+
+bool DecoderVorbisFactory::canDecode(QIODevice *input) const
+{
+ char buf[36];
+ if (input->peek(buf, 36) == 36 && !memcmp(buf, "OggS", 4)
+ && !memcmp(buf + 29, "vorbis", 6))
+ return TRUE;
+
+ return FALSE;
+}
+
+const DecoderProperties DecoderVorbisFactory::properties() const
+{
+ DecoderProperties properties;
+ properties.name = tr("Ogg Vorbis Plugin");
+ properties.filter = "*.ogg";
+ properties.description = tr("Ogg Vorbis Files");
+ properties.contentType = "application/ogg;audio/x-vorbis+ogg";
+ properties.hasAbout = TRUE;
+ properties.hasSettings = FALSE;
+ return properties;
+}
+
+Decoder *DecoderVorbisFactory::create(QObject *parent, QIODevice *input,
+ Output *output)
+{
+ return new DecoderVorbis(parent, this, input, output);
+}
+
+FileTag *DecoderVorbisFactory::createTag(const QString &source)
+{
+ FileTag *ftag = new FileTag();
+
+ TagLib::FileRef fileRef(source.toLocal8Bit ());
+ TagLib::Tag *tag = fileRef.tag();
+
+ if (tag && !tag->isEmpty())
+ {
+ ftag->setValue(FileTag::ALBUM,
+ QString::fromUtf8(tag->album().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::ARTIST,
+ QString::fromUtf8(tag->artist().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::COMMENT,
+ QString::fromUtf8(tag->comment().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::GENRE,
+ QString::fromUtf8(tag->genre().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::TITLE,
+ QString::fromUtf8(tag->title().toCString(TRUE)).trimmed());
+ ftag->setValue(FileTag::YEAR, tag->year());
+ ftag->setValue(FileTag::TRACK, tag->track());
+ }
+
+ if (fileRef.audioProperties())
+ ftag->setValue(FileTag::LENGTH, fileRef.audioProperties()->length());
+
+ return ftag;
+}
+
+QObject* DecoderVorbisFactory::showDetails(QWidget *parent, const QString &path)
+{
+ DetailsDialog *d = new DetailsDialog(parent, path);
+ d -> show();
+ return d;
+}
+
+void DecoderVorbisFactory::showSettings(QWidget *)
+{
+ /*SettingsDialog *s = new SettingsDialog(parent);
+ s -> show();*/
+}
+
+void DecoderVorbisFactory::showAbout(QWidget *parent)
+{
+ QMessageBox::about (parent, tr("About Ogg Vorbis Audio Plugin"),
+ tr("Qmmp Ogg Vorbis Audio Plugin")+"\n"+
+ tr("Writen by: Ilya Kotov <forkotov02@hotmail.ru>")+"\n"+
+ tr("Source code based on mq3 progect")
+ );
+}
+
+QTranslator *DecoderVorbisFactory::createTranslator(QObject *parent)
+{
+ QTranslator *translator = new QTranslator(parent);
+ QString locale = QLocale::system().name();
+ translator->load(QString(":/vorbis_plugin_") + locale);
+ return translator;
+}
+
+Q_EXPORT_PLUGIN(DecoderVorbisFactory)
diff --git a/src/plugins/Input/vorbis/decodervorbisfactory.h b/src/plugins/Input/vorbis/decodervorbisfactory.h
new file mode 100644
index 000000000..6830fc102
--- /dev/null
+++ b/src/plugins/Input/vorbis/decodervorbisfactory.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 DECODERVORBISFACTORY_H
+#define DECODERVORBISFACTORY_H
+
+#include <QObject>
+#include <QString>
+#include <QIODevice>
+#include <QWidget>
+
+#include <decoder.h>
+#include <output.h>
+#include <decoderfactory.h>
+#include <filetag.h>
+
+
+
+
+class DecoderVorbisFactory : 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/vorbis/detailsdialog.cpp b/src/plugins/Input/vorbis/detailsdialog.cpp
new file mode 100644
index 000000000..bbe441703
--- /dev/null
+++ b/src/plugins/Input/vorbis/detailsdialog.cpp
@@ -0,0 +1,120 @@
+/***************************************************************************
+ * 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/vorbisfile.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))
+ {
+ loadVorbisInfo();
+ loadTag();
+ }
+}
+
+
+DetailsDialog::~DetailsDialog()
+{}
+
+void DetailsDialog::loadVorbisInfo()
+{
+ TagLib::Ogg::Vorbis::File f (m_path.toLocal8Bit());
+ //l.label
+ //ui. f.audioProperties()->level();
+ 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()->bitrateNominal());
+ ui.nominalLabel->setText(text+" "+tr("kbps"));
+ text = QString("%1").arg(f.audioProperties()->bitrateMaximum());
+ ui.maximumLabel->setText(text+" "+tr("kbps"));
+ text = QString("%1").arg(f.audioProperties()->bitrateMinimum());
+ ui.minimumLabel->setText(text+" "+tr("kbps"));
+ 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/vorbis/detailsdialog.h b/src/plugins/Input/vorbis/detailsdialog.h
new file mode 100644
index 000000000..94d4243b8
--- /dev/null
+++ b/src/plugins/Input/vorbis/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 loadVorbisInfo();
+ void loadTag();
+ Ui::DetailsDialog ui;
+ QString m_path;
+
+};
+
+#endif
diff --git a/src/plugins/Input/vorbis/detailsdialog.ui b/src/plugins/Input/vorbis/detailsdialog.ui
new file mode 100644
index 000000000..1804ab268
--- /dev/null
+++ b/src/plugins/Input/vorbis/detailsdialog.ui
@@ -0,0 +1,384 @@
+<ui version="4.0" >
+ <class>DetailsDialog</class>
+ <widget class="QDialog" name="DetailsDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>536</width>
+ <height>375</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Details</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item rowspan="2" row="1" column="0" colspan="2" >
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="minimumSize" >
+ <size>
+ <width>220</width>
+ <height>16</height>
+ </size>
+ </property>
+ <property name="title" >
+ <string>Ogg Vorbis Info</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="2" column="1" >
+ <widget class="QLabel" name="fileSizeLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QLabel" name="channelsLabel" >
+ <property name="layoutDirection" >
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <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" >
+ <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" >
+ <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="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="4" column="0" colspan="2" >
+ <widget class="QGroupBox" name="groupBox_3" >
+ <property name="title" >
+ <string>Bit Rate</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignHCenter</set>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="1" column="1" >
+ <widget class="QLabel" name="maximumLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QLabel" name="minimumLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_9" >
+ <property name="layoutDirection" >
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text" >
+ <string>Minimum:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLabel" name="nominalLabel" >
+ <property name="text" >
+ <string>-</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_8" >
+ <property name="text" >
+ <string>Maximum:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_7" >
+ <property name="text" >
+ <string>Nominal:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </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>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="3" >
+ <widget class="QLineEdit" name="pathLineEdit" >
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <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="2" column="3" >
+ <widget class="QPushButton" name="pushButton_3" >
+ <property name="text" >
+ <string>Close</string>
+ </property>
+ </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="1" column="2" colspan="2" >
+ <widget class="QGroupBox" name="groupBox_2" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Ogg Vorbis Tag</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="6" column="1" colspan="2" >
+ <widget class="QPushButton" name="saveButton" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="3" >
+ <widget class="QLineEdit" name="trackLineEdit" />
+ </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="1" >
+ <widget class="QLineEdit" name="yearLineEdit" />
+ </item>
+ <item row="4" column="0" >
+ <widget class="QLabel" name="label_25" >
+ <property name="text" >
+ <string>Year:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0" >
+ <widget class="QLabel" name="label_27" >
+ <property name="text" >
+ <string>Genre:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="label_24" >
+ <property name="text" >
+ <string>Comment:</string>
+ </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_23" >
+ <property name="text" >
+ <string>Album:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_22" >
+ <property name="text" >
+ <string>Artist:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_21" >
+ <property name="text" >
+ <string>Title:</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="titleLineEdit" />
+ </item>
+ <item row="1" column="1" colspan="3" >
+ <widget class="QLineEdit" name="artistLineEdit" />
+ </item>
+ <item row="2" column="1" colspan="3" >
+ <widget class="QLineEdit" name="albumLineEdit" />
+ </item>
+ <item row="3" column="1" colspan="3" >
+ <widget class="QLineEdit" name="commentLineEdit" />
+ </item>
+ <item row="5" column="1" colspan="2" >
+ <widget class="QLineEdit" name="genreLineEdit" />
+ </item>
+ </layout>
+ </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>
diff --git a/src/plugins/Input/vorbis/translations/translations.qrc b/src/plugins/Input/vorbis/translations/translations.qrc
new file mode 100644
index 000000000..c5cacdfb0
--- /dev/null
+++ b/src/plugins/Input/vorbis/translations/translations.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file>vorbis_plugin_ru.qm</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/Input/vorbis/translations/vorbis_plugin_ru.qm b/src/plugins/Input/vorbis/translations/vorbis_plugin_ru.qm
new file mode 100644
index 000000000..a6a3a77b7
--- /dev/null
+++ b/src/plugins/Input/vorbis/translations/vorbis_plugin_ru.qm
Binary files differ
diff --git a/src/plugins/Input/vorbis/translations/vorbis_plugin_ru.ts b/src/plugins/Input/vorbis/translations/vorbis_plugin_ru.ts
new file mode 100644
index 000000000..16cf81ea3
--- /dev/null
+++ b/src/plugins/Input/vorbis/translations/vorbis_plugin_ru.ts
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS><TS version="1.1" language="ru">
+<context>
+ <name>DecoderVorbisFactory</name>
+ <message>
+ <location filename="../decodervorbisfactory.cpp" line="21"/>
+ <source>Ogg Vorbis Plugin</source>
+ <translation>Модуль Ogg Vorbis</translation>
+ </message>
+ <message>
+ <location filename="../decodervorbisfactory.cpp" line="34"/>
+ <source>Ogg Vorbis Files</source>
+ <translation>Файлы Ogg Vorbis</translation>
+ </message>
+ <message>
+ <location filename="../decodervorbisfactory.cpp" line="64"/>
+ <source>About Ogg Vorbis Audio Plugin</source>
+ <translation>Об аудио-модуле Ogg Vorbis</translation>
+ </message>
+ <message>
+ <location filename="../decodervorbisfactory.cpp" line="65"/>
+ <source>Qmmp Ogg Vorbis Audio Plugin</source>
+ <translation>Аудио-модуль Ogg Vorbis для Qmmp</translation>
+ </message>
+ <message>
+ <location filename="../decodervorbisfactory.cpp" line="66"/>
+ <source>Writen by: Ilya Kotov &lt;forkotov02@hotmail.ru&gt;</source>
+ <translation>Разработчик: Илья Котов &lt;forkotov02@hotmail.ru&gt;</translation>
+ </message>
+ <message>
+ <location filename="../decodervorbisfactory.cpp" line="68"/>
+ <source>Source code based on mq3 progect</source>
+ <translation>Исходный код основан на проекте mq3</translation>
+ </message>
+</context>
+<context>
+ <name>DetailsDialog</name>
+ <message>
+ <location filename="../detailsdialog.cpp" line="54"/>
+ <source>Hz</source>
+ <translation>Гц</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="265"/>
+ <source>Save</source>
+ <translation>Сохранить</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="275"/>
+ <source>Track number:</source>
+ <translation>Номер трека:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="288"/>
+ <source>Year:</source>
+ <translation>Год:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="298"/>
+ <source>Genre:</source>
+ <translation>Жанр:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="308"/>
+ <source>Comment:</source>
+ <translation>Комментарий:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="318"/>
+ <source>Album:</source>
+ <translation>Альбом:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="328"/>
+ <source>Artist:</source>
+ <translation>Исполнитель:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="338"/>
+ <source>Title:</source>
+ <translation>Название:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="222"/>
+ <source>Close</source>
+ <translation>Закрыть</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="162"/>
+ <source>-</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="192"/>
+ <source>File size:</source>
+ <translation>Размер файла:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="77"/>
+ <source>Sample rate:</source>
+ <translation>Дискретизация:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="212"/>
+ <source>File path:</source>
+ <translation>Путь к файлу:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="31"/>
+ <source>Ogg Vorbis Info</source>
+ <translation>Информация Ogg Vorbis</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="60"/>
+ <source>Length:</source>
+ <translation>Длительность:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="97"/>
+ <source>Channels:</source>
+ <translation>Каналов:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="120"/>
+ <source>Bit Rate</source>
+ <translation>Битовая частота</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="152"/>
+ <source>Minimum:</source>
+ <translation>Минимальная:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="169"/>
+ <source>Maximum:</source>
+ <translation>Максимальная:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="179"/>
+ <source>Nominal:</source>
+ <translation>Номинальная:</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="250"/>
+ <source>Ogg Vorbis Tag</source>
+ <translation>Оgg Vorbis-тег</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="62"/>
+ <source>kbps</source>
+ <translation>Кб/с</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.cpp" line="63"/>
+ <source>KB</source>
+ <translation>Кб</translation>
+ </message>
+ <message>
+ <location filename="../detailsdialog.ui" line="13"/>
+ <source>Details</source>
+ <translation>Информация</translation>
+ </message>
+</context>
+</TS>
diff --git a/src/plugins/Input/vorbis/vorbis.pro b/src/plugins/Input/vorbis/vorbis.pro
new file mode 100644
index 000000000..afd7b6510
--- /dev/null
+++ b/src/plugins/Input/vorbis/vorbis.pro
@@ -0,0 +1,35 @@
+# ???? ?????? ? KDevelop ?????????? qmake.
+# -------------------------------------------
+# ?????????? ???????????? ???????? ???????? ???????: ./Plugins/Input/ogg
+# ???? - ??????????:
+
+include(../../plugins.pri)
+
+FORMS += detailsdialog.ui
+HEADERS += decodervorbisfactory.h \
+ decoder_vorbis.h \
+ detailsdialog.h
+SOURCES += decoder_vorbis.cpp \
+ decodervorbisfactory.cpp \
+ detailsdialog.cpp
+
+TARGET=$$PLUGINS_PREFIX/Input/vorbis
+QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libvorbis.so
+
+INCLUDEPATH += ../../../qmmp
+CONFIG += release \
+warn_on \
+plugin \
+link_pkgconfig
+TEMPLATE = lib
+QMAKE_LIBDIR += ../../../../lib
+LIBS += -lqmmp -L/usr/lib
+PKGCONFIG += taglib ogg vorbisfile vorbis
+#TRANSLATIONS = translations/vorbis_plugin_ru.ts
+#RESOURCES = translations/translations.qrc
+
+isEmpty (LIB_DIR){
+LIB_DIR = /lib
+}
+target.path = $$LIB_DIR/qmmp/Input
+INSTALLS += target