diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1dcdcee08..cc8fb13f3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -311,6 +311,7 @@ set(SOURCES transcoder/transcoderoptionsdialog.cpp transcoder/transcoderoptionsflac.cpp transcoder/transcoderoptionsmp3.cpp + transcoder/transcoderoptionsopus.cpp transcoder/transcoderoptionsspeex.cpp transcoder/transcoderoptionsvorbis.cpp transcoder/transcoderoptionswma.cpp @@ -701,6 +702,7 @@ set(UI transcoder/transcoderoptionsdialog.ui transcoder/transcoderoptionsflac.ui transcoder/transcoderoptionsmp3.ui + transcoder/transcoderoptionsopus.ui transcoder/transcoderoptionsspeex.ui transcoder/transcoderoptionsvorbis.ui transcoder/transcoderoptionswma.ui diff --git a/src/core/song.cpp b/src/core/song.cpp index 35d2b217f..a8ddf260f 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -531,7 +531,7 @@ void Song::InitFromFilePartial(const QString& filename) { QString suffix = info.suffix().toLower(); if (suffix == "mp3" || suffix == "ogg" || suffix == "flac" || suffix == "mpc" || suffix == "m4a" || suffix == "aac" || suffix == "wma" || suffix == "mp4" - || suffix == "spx" || suffix == "wav") { + || suffix == "spx" || suffix == "wav" || suffix == "opus") { d->valid_ = true; } else { d->valid_ = false; diff --git a/src/transcoder/transcoder.cpp b/src/transcoder/transcoder.cpp index a67f1038a..5727c253e 100644 --- a/src/transcoder/transcoder.cpp +++ b/src/transcoder/transcoder.cpp @@ -233,6 +233,7 @@ QList Transcoder::GetAllPresets() { ret << PresetForFileType(Song::Type_OggSpeex); ret << PresetForFileType(Song::Type_Asf); ret << PresetForFileType(Song::Type_Wav); + ret << PresetForFileType(Song::Type_OggOpus); return ret; } @@ -250,6 +251,8 @@ TranscoderPreset Transcoder::PresetForFileType(Song::FileType type) { return TranscoderPreset(type, "Ogg Flac", "ogg", "audio/x-flac", "application/ogg"); case Song::Type_OggSpeex: return TranscoderPreset(type, "Ogg Speex", "spx", "audio/x-speex", "application/ogg"); + case Song::Type_OggOpus: + return TranscoderPreset(type, "Ogg Opus", "opus", "audio/x-opus", "application/ogg"); case Song::Type_Asf: return TranscoderPreset(type, "Windows Media audio", "wma", "audio/x-wma", "video/x-ms-asf"); case Song::Type_Wav: @@ -407,12 +410,13 @@ bool Transcoder::StartJob(const Job &job) { if (!state->pipeline_) return false; // Create all the elements - GstElement* src = CreateElement("filesrc", state->pipeline_); - GstElement* decode = CreateElement("decodebin2", state->pipeline_); - GstElement* convert = CreateElement("audioconvert", state->pipeline_); - GstElement* codec = CreateElementForMimeType("Codec/Encoder/Audio", job.preset.codec_mimetype_, state->pipeline_); - GstElement* muxer = CreateElementForMimeType("Codec/Muxer", job.preset.muxer_mimetype_, state->pipeline_); - GstElement* sink = CreateElement("filesink", state->pipeline_); + GstElement* src = CreateElement("filesrc", state->pipeline_); + GstElement* decode = CreateElement("decodebin2", state->pipeline_); + GstElement* convert = CreateElement("audioconvert", state->pipeline_); + GstElement* resample = CreateElement("audioresample", state->pipeline_); + GstElement* codec = CreateElementForMimeType("Codec/Encoder/Audio", job.preset.codec_mimetype_, state->pipeline_); + GstElement* muxer = CreateElementForMimeType("Codec/Muxer", job.preset.muxer_mimetype_, state->pipeline_); + GstElement* sink = CreateElement("filesink", state->pipeline_); if (!src || !decode || !convert || !sink) return false; @@ -432,11 +436,11 @@ bool Transcoder::StartJob(const Job &job) { // Join them together gst_element_link(src, decode); if (codec && muxer) - gst_element_link_many(convert, codec, muxer, sink, NULL); + gst_element_link_many(convert, resample, codec, muxer, sink, NULL); else if (codec) - gst_element_link_many(convert, codec, sink, NULL); + gst_element_link_many(convert, resample, codec, sink, NULL); else if (muxer) - gst_element_link_many(convert, muxer, sink, NULL); + gst_element_link_many(convert, resample, muxer, sink, NULL); // Set properties g_object_set(src, "location", job.input.toUtf8().constData(), NULL); diff --git a/src/transcoder/transcoderoptionsdialog.cpp b/src/transcoder/transcoderoptionsdialog.cpp index f0e3661c8..bcf8419c4 100644 --- a/src/transcoder/transcoderoptionsdialog.cpp +++ b/src/transcoder/transcoderoptionsdialog.cpp @@ -21,6 +21,7 @@ #include "transcoderoptionsmp3.h" #include "transcoderoptionsspeex.h" #include "transcoderoptionsvorbis.h" +#include "transcoderoptionsopus.h" #include "transcoderoptionswma.h" #include "ui_transcoderoptionsdialog.h" @@ -37,6 +38,7 @@ TranscoderOptionsDialog::TranscoderOptionsDialog(Song::FileType type, QWidget* p case Song::Type_Mp4: options_ = new TranscoderOptionsAAC(this); break; case Song::Type_Mpeg: options_ = new TranscoderOptionsMP3(this); break; case Song::Type_OggVorbis: options_ = new TranscoderOptionsVorbis(this); break; + case Song::Type_OggOpus: options_ = new TranscoderOptionsOpus(this); break; case Song::Type_OggSpeex: options_ = new TranscoderOptionsSpeex(this); break; case Song::Type_Asf: options_ = new TranscoderOptionsWma(this); break; default: diff --git a/src/transcoder/transcoderoptionsopus.cpp b/src/transcoder/transcoderoptionsopus.cpp new file mode 100644 index 000000000..d055eabe5 --- /dev/null +++ b/src/transcoder/transcoderoptionsopus.cpp @@ -0,0 +1,51 @@ +/* This file is part of Clementine. + Copyright 2013, Martin Brodbeck + + Clementine 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 3 of the License, or + (at your option) any later version. + + Clementine 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 Clementine. If not, see . +*/ + +#include "transcoderoptionsopus.h" +#include "ui_transcoderoptionsopus.h" + +#include + +// TODO: Add more options than only bitrate as soon as gst doesn't crash +// anymore while using the cbr parmameter (like cbr=false) + +const char* TranscoderOptionsOpus::kSettingsGroup = "Transcoder/opusenc"; + +TranscoderOptionsOpus::TranscoderOptionsOpus(QWidget* parent) + : TranscoderOptionsInterface(parent), + ui_(new Ui_TranscoderOptionsOpus) +{ + ui_->setupUi(this); +} + +TranscoderOptionsOpus::~TranscoderOptionsOpus() { + delete ui_; +} + +void TranscoderOptionsOpus::Load() { + QSettings s; + s.beginGroup(kSettingsGroup); + + ui_->bitrate_slider->setValue(s.value("bitrate", 128000).toInt() / 1000); +} + +void TranscoderOptionsOpus::Save() { + QSettings s; + s.beginGroup(kSettingsGroup); + + s.setValue("bitrate", ui_->bitrate_slider->value() * 1000); +} diff --git a/src/transcoder/transcoderoptionsopus.h b/src/transcoder/transcoderoptionsopus.h new file mode 100644 index 000000000..ee2dd0507 --- /dev/null +++ b/src/transcoder/transcoderoptionsopus.h @@ -0,0 +1,39 @@ +/* This file is part of Clementine. + Copyright 2013, Martin Brodbeck + + Clementine 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 3 of the License, or + (at your option) any later version. + + Clementine 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 Clementine. If not, see . +*/ + +#ifndef TRANSCODEROPTIONSOPUS_H +#define TRANSCODEROPTIONSOPUS_H + +#include "transcoderoptionsinterface.h" + +class Ui_TranscoderOptionsOpus; + +class TranscoderOptionsOpus : public TranscoderOptionsInterface { +public: + TranscoderOptionsOpus(QWidget* parent = 0); + ~TranscoderOptionsOpus(); + + void Load(); + void Save(); + +private: + static const char* kSettingsGroup; + + Ui_TranscoderOptionsOpus* ui_; +}; + +#endif // TRANSCODEROPTIONSOPUS_H diff --git a/src/transcoder/transcoderoptionsopus.ui b/src/transcoder/transcoderoptionsopus.ui new file mode 100644 index 000000000..dd6587ba9 --- /dev/null +++ b/src/transcoder/transcoderoptionsopus.ui @@ -0,0 +1,94 @@ + + + TranscoderOptionsOpus + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + Bitrate + + + + + + + + + 6 + + + 510 + + + 128 + + + Qt::Horizontal + + + + + + + kbps + + + 320 + + + 128 + + + + + + + + + + + bitrate_slider + valueChanged(int) + bitrate_spinbox + setValue(int) + + + 166 + 25 + + + 323 + 24 + + + + + bitrate_spinbox + valueChanged(int) + bitrate_slider + setValue(int) + + + 325 + 14 + + + 190 + 31 + + + + + diff --git a/src/transcoder/transcodersettingspage.cpp b/src/transcoder/transcodersettingspage.cpp index 0e5ef3013..508194e68 100644 --- a/src/transcoder/transcodersettingspage.cpp +++ b/src/transcoder/transcodersettingspage.cpp @@ -38,6 +38,7 @@ void TranscoderSettingsPage::Load() { ui_->transcoding_speex->Load(); ui_->transcoding_vorbis->Load(); ui_->transcoding_wma->Load(); + ui_->transcoding_opus->Load(); } void TranscoderSettingsPage::Save() { @@ -47,4 +48,5 @@ void TranscoderSettingsPage::Save() { ui_->transcoding_speex->Save(); ui_->transcoding_vorbis->Save(); ui_->transcoding_wma->Save(); + ui_->transcoding_opus->Load(); } diff --git a/src/transcoder/transcodersettingspage.ui b/src/transcoder/transcodersettingspage.ui index a00e39b82..5b7e0621b 100644 --- a/src/transcoder/transcodersettingspage.ui +++ b/src/transcoder/transcodersettingspage.ui @@ -125,6 +125,22 @@ + + + Opus + + + + 0 + + + 0 + + + + + + @@ -166,6 +182,12 @@
transcoder/transcoderoptionswma.h
1 + + TranscoderOptionsOpus + QWidget +
transcoder/transcoderoptionsopus.h
+ 1 +