diff options
| author | vovanec <vovanec@90c681e8-e032-0410-971d-27865f9a5e38> | 2008-02-07 13:36:34 +0000 |
|---|---|---|
| committer | vovanec <vovanec@90c681e8-e032-0410-971d-27865f9a5e38> | 2008-02-07 13:36:34 +0000 |
| commit | 06d1877811fa6aa97dddc0e03bcde4e766928c87 (patch) | |
| tree | c25462d0e58c3d58c728664440412bf4f16a49ec /src/plugins/Input/ffmpeg | |
| parent | 3f6b60f23c44a8ba8dd97ca6f41a16e2af7ef2f7 (diff) | |
| download | qmmp-06d1877811fa6aa97dddc0e03bcde4e766928c87.tar.gz qmmp-06d1877811fa6aa97dddc0e03bcde4e766928c87.tar.bz2 qmmp-06d1877811fa6aa97dddc0e03bcde4e766928c87.zip | |
new directory structure
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@232 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/plugins/Input/ffmpeg')
| -rw-r--r-- | src/plugins/Input/ffmpeg/CMakeLists.txt | 94 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp | 342 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/decoder_ffmpeg.h | 78 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/decoderffmpegfactory.cpp | 93 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/decoderffmpegfactory.h | 54 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/detailsdialog.cpp | 103 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/detailsdialog.h | 45 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/detailsdialog.ui | 332 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/ffmpeg.pro | 35 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_cs.ts | 150 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.qm | bin | 0 -> 2221 bytes | |||
| -rw-r--r-- | src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.ts | 149 | ||||
| -rw-r--r-- | src/plugins/Input/ffmpeg/translations/translations.qrc | 6 |
13 files changed, 1481 insertions, 0 deletions
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 <forkotov02@hotmail.ru></source> + <translation>Autor: Ilja Kotov <forkotov02@hotmail.ru></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 Binary files differnew file mode 100644 index 000000000..68ceb6f8b --- /dev/null +++ b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.qm 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 <forkotov02@hotmail.ru></source> + <translation>Разработчик: Илья Котов <forkotov02@hotmail.ru></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> |
