Create or load moodbar data for songs
This commit is contained in:
parent
10a3594590
commit
51229b88c5
|
@ -198,6 +198,10 @@ set(SOURCES
|
|||
library/librarywatcher.cpp
|
||||
library/sqlrow.cpp
|
||||
|
||||
moodbar/moodbarcontroller.cpp
|
||||
moodbar/moodbarloader.cpp
|
||||
moodbar/moodbarpipeline.cpp
|
||||
|
||||
musicbrainz/acoustidclient.cpp
|
||||
musicbrainz/chromaprinter.cpp
|
||||
musicbrainz/musicbrainzclient.cpp
|
||||
|
@ -459,6 +463,10 @@ set(HEADERS
|
|||
library/libraryviewcontainer.h
|
||||
library/librarywatcher.h
|
||||
|
||||
moodbar/moodbarcontroller.h
|
||||
moodbar/moodbarloader.h
|
||||
moodbar/moodbarpipeline.h
|
||||
|
||||
musicbrainz/acoustidclient.h
|
||||
musicbrainz/musicbrainzclient.h
|
||||
musicbrainz/tagfetcher.h
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include "globalsearch/globalsearch.h"
|
||||
#include "library/library.h"
|
||||
#include "library/librarybackend.h"
|
||||
#include "moodbar/moodbarcontroller.h"
|
||||
#include "moodbar/moodbarloader.h"
|
||||
#include "playlist/playlistbackend.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
#include "podcasts/gpoddersync.h"
|
||||
|
@ -55,7 +57,9 @@ Application::Application(QObject* parent)
|
|||
device_manager_(NULL),
|
||||
podcast_updater_(NULL),
|
||||
podcast_downloader_(NULL),
|
||||
gpodder_sync_(NULL)
|
||||
gpodder_sync_(NULL),
|
||||
moodbar_loader_(NULL),
|
||||
moodbar_controller_(NULL)
|
||||
{
|
||||
tag_reader_client_ = new TagReaderClient(this);
|
||||
MoveToNewThread(tag_reader_client_);
|
||||
|
@ -86,6 +90,8 @@ Application::Application(QObject* parent)
|
|||
podcast_updater_ = new PodcastUpdater(this, this);
|
||||
podcast_downloader_ = new PodcastDownloader(this, this);
|
||||
gpodder_sync_ = new GPodderSync(this, this);
|
||||
moodbar_loader_ = new MoodbarLoader(this);
|
||||
moodbar_controller_ = new MoodbarController(this, this);
|
||||
|
||||
library_->Init();
|
||||
library_->StartThreads();
|
||||
|
|
|
@ -34,6 +34,8 @@ class InternetModel;
|
|||
class Library;
|
||||
class LibraryBackend;
|
||||
class LibraryModel;
|
||||
class MoodbarController;
|
||||
class MoodbarLoader;
|
||||
class Player;
|
||||
class PlaylistBackend;
|
||||
class PodcastDownloader;
|
||||
|
@ -69,6 +71,8 @@ public:
|
|||
PodcastUpdater* podcast_updater() const { return podcast_updater_; }
|
||||
PodcastDownloader* podcast_downloader() const { return podcast_downloader_; }
|
||||
GPodderSync* gpodder_sync() const { return gpodder_sync_; }
|
||||
MoodbarLoader* moodbar_loader() const { return moodbar_loader_; }
|
||||
MoodbarController* moodbar_controller() const { return moodbar_controller_; }
|
||||
|
||||
LibraryBackend* library_backend() const;
|
||||
LibraryModel* library_model() const;
|
||||
|
@ -105,6 +109,8 @@ private:
|
|||
PodcastUpdater* podcast_updater_;
|
||||
PodcastDownloader* podcast_downloader_;
|
||||
GPodderSync* gpodder_sync_;
|
||||
MoodbarLoader* moodbar_loader_;
|
||||
MoodbarController* moodbar_controller_;
|
||||
|
||||
QList<QObject*> objects_in_threads_;
|
||||
QList<QThread*> threads_;
|
||||
|
|
|
@ -277,6 +277,9 @@ QString GetConfigPath(ConfigPath config) {
|
|||
|
||||
case Path_NetworkCache:
|
||||
return GetConfigPath(Path_Root) + "/networkcache";
|
||||
|
||||
case Path_MoodbarCache:
|
||||
return GetConfigPath(Path_Root) + "/moodbarcache";
|
||||
|
||||
case Path_GstreamerRegistry:
|
||||
return GetConfigPath(Path_Root) +
|
||||
|
|
|
@ -108,6 +108,7 @@ namespace Utilities {
|
|||
Path_GstreamerRegistry,
|
||||
Path_DefaultMusicLibrary,
|
||||
Path_LocalSpotifyBlob,
|
||||
Path_MoodbarCache,
|
||||
};
|
||||
QString GetConfigPath(ConfigPath config);
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "moodbarcontroller.h"
|
||||
#include "moodbarloader.h"
|
||||
#include "core/application.h"
|
||||
#include "core/logging.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
|
||||
MoodbarController::MoodbarController(Application* app, QObject* parent)
|
||||
: QObject(parent),
|
||||
app_(app)
|
||||
{
|
||||
connect(app_->playlist_manager(),
|
||||
SIGNAL(CurrentSongChanged(Song)), SLOT(CurrentSongChanged(Song)));
|
||||
}
|
||||
|
||||
void MoodbarController::CurrentSongChanged(const Song& song) {
|
||||
QByteArray data;
|
||||
MoodbarPipeline* pipeline = NULL;
|
||||
app_->moodbar_loader()->Load(song.url(), &data, &pipeline);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MOODBARCONTROLLER_H
|
||||
#define MOODBARCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class Application;
|
||||
class Song;
|
||||
|
||||
class MoodbarController : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MoodbarController(Application* app, QObject* parent = 0);
|
||||
|
||||
private slots:
|
||||
void CurrentSongChanged(const Song& song);
|
||||
|
||||
private:
|
||||
Application* app_;
|
||||
};
|
||||
|
||||
#endif // MOODBARCONTROLLER_H
|
|
@ -0,0 +1,117 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "moodbarloader.h"
|
||||
#include "moodbarpipeline.h"
|
||||
#include "core/closure.h"
|
||||
#include "core/utilities.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QUrl>
|
||||
|
||||
MoodbarLoader::MoodbarLoader(QObject* parent)
|
||||
: QObject(parent),
|
||||
cache_(new QNetworkDiskCache(this))
|
||||
{
|
||||
cache_->setCacheDirectory(Utilities::GetConfigPath(Utilities::Path_MoodbarCache));
|
||||
cache_->setMaximumCacheSize(1024 * 1024); // 1MB - enough for 333 moodbars
|
||||
}
|
||||
|
||||
MoodbarLoader::~MoodbarLoader() {
|
||||
}
|
||||
|
||||
MoodbarLoader::Result MoodbarLoader::Load(
|
||||
const QUrl& url, QByteArray* data, MoodbarPipeline** async_pipeline) {
|
||||
if (url.scheme() != "file") {
|
||||
return CannotLoad;
|
||||
}
|
||||
|
||||
// Are we in the middle of loading this moodbar already?
|
||||
if (active_requests_.contains(url)) {
|
||||
*async_pipeline = active_requests_[url];
|
||||
return WillLoadAsync;
|
||||
}
|
||||
|
||||
// Check if a mood file exists for this file already
|
||||
const QString filename(url.toLocalFile());
|
||||
const QFileInfo file_info(filename);
|
||||
const QString dir_path(file_info.dir().path());
|
||||
|
||||
QStringList parts(file_info.fileName().split('.'));
|
||||
parts.removeLast();
|
||||
parts.append("mood");
|
||||
const QString mood_filename(parts.join("."));
|
||||
|
||||
QStringList possible_mood_files;
|
||||
possible_mood_files << dir_path + "/." + mood_filename
|
||||
<< dir_path + "/" + mood_filename;
|
||||
|
||||
foreach (const QString& possible_mood_file, possible_mood_files) {
|
||||
QFile f(possible_mood_file);
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
qLog(Info) << "Loading moodbar data from" << possible_mood_file;
|
||||
*data = f.readAll();
|
||||
return Loaded;
|
||||
}
|
||||
}
|
||||
|
||||
// Maybe it exists in the cache?
|
||||
QIODevice* cache_device = cache_->data(url);
|
||||
if (cache_device) {
|
||||
qLog(Info) << "Loading cached moodbar data for" << filename;
|
||||
*data = cache_device->readAll();
|
||||
delete cache_device;
|
||||
return Loaded;
|
||||
}
|
||||
|
||||
// There was no existing file, analyze the audio file and create one.
|
||||
MoodbarPipeline* pipeline = new MoodbarPipeline(filename);
|
||||
if (!pipeline->Start()) {
|
||||
delete pipeline;
|
||||
return CannotLoad;
|
||||
}
|
||||
|
||||
qLog(Info) << "Creating moodbar data for" << filename;
|
||||
|
||||
active_requests_[filename] = pipeline;
|
||||
NewClosure(pipeline, SIGNAL(Finished(bool)),
|
||||
this, SLOT(RequestFinished(MoodbarPipeline*,QUrl)),
|
||||
pipeline, url);
|
||||
|
||||
*async_pipeline = pipeline;
|
||||
return WillLoadAsync;
|
||||
}
|
||||
|
||||
void MoodbarLoader::RequestFinished(MoodbarPipeline* request, const QUrl& url) {
|
||||
if (request->success()) {
|
||||
qLog(Info) << "Moodbar data generated successfully for" << url.toLocalFile();
|
||||
|
||||
// Save the data in the cache
|
||||
QNetworkCacheMetaData metadata;
|
||||
metadata.setUrl(url);
|
||||
|
||||
QIODevice* cache_file = cache_->prepare(metadata);
|
||||
cache_file->write(request->data());
|
||||
cache_->insert(cache_file);
|
||||
}
|
||||
|
||||
// Remove the request from the active list and delete it
|
||||
active_requests_.take(url);
|
||||
request->deleteLater();
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MOODBARLOADER_H
|
||||
#define MOODBARLOADER_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
|
||||
class QNetworkDiskCache;
|
||||
class QUrl;
|
||||
|
||||
class MoodbarPipeline;
|
||||
|
||||
class MoodbarLoader : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MoodbarLoader(QObject* parent = 0);
|
||||
~MoodbarLoader();
|
||||
|
||||
enum Result {
|
||||
// The URL isn't a local file or the moodbar plugin was not available -
|
||||
// moodbar data can never be loaded.
|
||||
CannotLoad,
|
||||
|
||||
// Moodbar data was loaded and returned.
|
||||
Loaded,
|
||||
|
||||
// Moodbar data will be loaded in the background, a MoodbarPipeline* was
|
||||
// was returned that you can connect to the Finished() signal on.
|
||||
WillLoadAsync
|
||||
};
|
||||
|
||||
Result Load(const QUrl& url, QByteArray* data, MoodbarPipeline** async_pipeline);
|
||||
|
||||
private slots:
|
||||
void RequestFinished(MoodbarPipeline* request, const QUrl& filename);
|
||||
|
||||
private:
|
||||
QNetworkDiskCache* cache_;
|
||||
|
||||
QMap<QUrl, MoodbarPipeline*> active_requests_;
|
||||
};
|
||||
|
||||
#endif // MOODBARLOADER_H
|
|
@ -0,0 +1,202 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "moodbarpipeline.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
bool MoodbarPipeline::sIsAvailable = false;
|
||||
|
||||
MoodbarPipeline::MoodbarPipeline(const QString& local_filename)
|
||||
: QObject(NULL),
|
||||
local_filename_(local_filename),
|
||||
pipeline_(NULL),
|
||||
convert_element_(NULL),
|
||||
bus_callback_id_(0),
|
||||
success_(false)
|
||||
{
|
||||
}
|
||||
|
||||
MoodbarPipeline::~MoodbarPipeline() {
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
bool MoodbarPipeline::IsAvailable() {
|
||||
if (!sIsAvailable) {
|
||||
GstElementFactory* factory = gst_element_factory_find("fftwspectrum");
|
||||
if (!factory) {
|
||||
return false;
|
||||
}
|
||||
gst_object_unref(factory);
|
||||
|
||||
factory = gst_element_factory_find("moodbar");
|
||||
if (!factory) {
|
||||
return false;
|
||||
}
|
||||
gst_object_unref(factory);
|
||||
|
||||
sIsAvailable = true;
|
||||
}
|
||||
|
||||
return sIsAvailable;
|
||||
}
|
||||
|
||||
GstElement* MoodbarPipeline::CreateElement(const QString& factory_name) {
|
||||
GstElement* ret = gst_element_factory_make(factory_name.toAscii().constData(), NULL);
|
||||
|
||||
if (ret) {
|
||||
gst_bin_add(GST_BIN(pipeline_), ret);
|
||||
} else {
|
||||
qLog(Warning) << "Unable to create gstreamer element" << factory_name;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MoodbarPipeline::Start() {
|
||||
if (pipeline_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pipeline_ = gst_pipeline_new("moodbar-pipeline");
|
||||
|
||||
GstElement* filesrc = CreateElement("filesrc");
|
||||
GstElement* decodebin = CreateElement("decodebin");
|
||||
convert_element_ = CreateElement("audioconvert");
|
||||
GstElement* fftwspectrum = CreateElement("fftwspectrum");
|
||||
GstElement* moodbar = CreateElement("moodbar");
|
||||
GstElement* appsink = CreateElement("appsink");
|
||||
|
||||
if (!filesrc || !convert_element_ || !fftwspectrum || !moodbar || !appsink) {
|
||||
pipeline_ = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Join them together
|
||||
gst_element_link(filesrc, decodebin);
|
||||
gst_element_link_many(convert_element_, fftwspectrum, moodbar, appsink, NULL);
|
||||
|
||||
// Set properties
|
||||
g_object_set(filesrc, "location", local_filename_.toUtf8().constData(), NULL);
|
||||
g_object_set(fftwspectrum, "def-size", 2048,
|
||||
"def-step", 1024,
|
||||
"hiquality", true, NULL);
|
||||
g_object_set(moodbar, "height", 1,
|
||||
"max-width", 1000, NULL);
|
||||
|
||||
// Connect signals
|
||||
g_signal_connect(decodebin, "new-decoded-pad", G_CALLBACK(NewPadCallback), this);
|
||||
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)), BusCallbackSync, this);
|
||||
bus_callback_id_ = gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)), BusCallback, this);
|
||||
|
||||
// Set appsink callbacks
|
||||
GstAppSinkCallbacks callbacks;
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.new_buffer = NewBufferCallback;
|
||||
|
||||
gst_app_sink_set_callbacks(reinterpret_cast<GstAppSink*>(appsink), &callbacks, this, NULL);
|
||||
|
||||
// Start playing
|
||||
gst_element_set_state(pipeline_, GST_STATE_PLAYING);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MoodbarPipeline::ReportError(GstMessage* msg) {
|
||||
GError* error;
|
||||
gchar* debugs;
|
||||
|
||||
gst_message_parse_error(msg, &error, &debugs);
|
||||
QString message = QString::fromLocal8Bit(error->message);
|
||||
|
||||
g_error_free(error);
|
||||
free(debugs);
|
||||
|
||||
qLog(Error) << "Error processing" << local_filename_ << ":" << message;
|
||||
}
|
||||
|
||||
void MoodbarPipeline::NewPadCallback(GstElement*, GstPad* pad, gboolean, gpointer data) {
|
||||
MoodbarPipeline* self = reinterpret_cast<MoodbarPipeline*>(data);
|
||||
GstPad* const audiopad = gst_element_get_pad(self->convert_element_, "sink");
|
||||
|
||||
if (GST_PAD_IS_LINKED(audiopad)) {
|
||||
qLog(Warning) << "audiopad is already linked, unlinking old pad";
|
||||
gst_pad_unlink(audiopad, GST_PAD_PEER(audiopad));
|
||||
}
|
||||
|
||||
gst_pad_link(pad, audiopad);
|
||||
gst_object_unref(audiopad);
|
||||
}
|
||||
|
||||
GstFlowReturn MoodbarPipeline::NewBufferCallback(GstAppSink* app_sink, gpointer data) {
|
||||
MoodbarPipeline* self = reinterpret_cast<MoodbarPipeline*>(data);
|
||||
|
||||
GstBuffer* buffer = gst_app_sink_pull_buffer(app_sink);
|
||||
self->data_.append(reinterpret_cast<const char*>(buffer->data), buffer->size);
|
||||
gst_buffer_unref(buffer);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
gboolean MoodbarPipeline::BusCallback(GstBus*, GstMessage* msg, gpointer data) {
|
||||
MoodbarPipeline* self = reinterpret_cast<MoodbarPipeline*>(data);
|
||||
|
||||
switch (GST_MESSAGE_TYPE(msg)) {
|
||||
case GST_MESSAGE_ERROR:
|
||||
self->ReportError(msg);
|
||||
self->Stop(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return GST_BUS_DROP;
|
||||
}
|
||||
|
||||
GstBusSyncReply MoodbarPipeline::BusCallbackSync(GstBus*, GstMessage* msg, gpointer data) {
|
||||
MoodbarPipeline* self = reinterpret_cast<MoodbarPipeline*>(data);
|
||||
|
||||
switch (GST_MESSAGE_TYPE(msg)) {
|
||||
case GST_MESSAGE_EOS:
|
||||
self->Stop(true);
|
||||
break;
|
||||
|
||||
case GST_MESSAGE_ERROR:
|
||||
self->ReportError(msg);
|
||||
self->Stop(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return GST_BUS_PASS;
|
||||
}
|
||||
|
||||
void MoodbarPipeline::Stop(bool success) {
|
||||
success_ = success;
|
||||
emit Finished(success);
|
||||
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void MoodbarPipeline::Cleanup() {
|
||||
if (pipeline_) {
|
||||
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)), NULL, NULL);
|
||||
g_source_remove(bus_callback_id_);
|
||||
gst_object_unref(pipeline_);
|
||||
pipeline_ = NULL;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MOODBARPIPELINE_H
|
||||
#define MOODBARPIPELINE_H
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QObject>
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/app/gstappsink.h>
|
||||
|
||||
// Creates moodbar data for a single local music file.
|
||||
class MoodbarPipeline : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MoodbarPipeline(const QString& local_filename);
|
||||
~MoodbarPipeline();
|
||||
|
||||
static bool IsAvailable();
|
||||
|
||||
bool Start();
|
||||
|
||||
bool success() const { return success_; }
|
||||
const QByteArray& data() const { return data_; }
|
||||
|
||||
signals:
|
||||
void Finished(bool success);
|
||||
|
||||
private:
|
||||
GstElement* CreateElement(const QString& factory_name);
|
||||
|
||||
void ReportError(GstMessage* message);
|
||||
void Stop(bool success);
|
||||
void Cleanup();
|
||||
|
||||
static void NewPadCallback(GstElement*, GstPad* pad, gboolean, gpointer data);
|
||||
static GstFlowReturn NewBufferCallback(GstAppSink* app_sink, gpointer self);
|
||||
static gboolean BusCallback(GstBus*, GstMessage* msg, gpointer data);
|
||||
static GstBusSyncReply BusCallbackSync(GstBus*, GstMessage* msg, gpointer data);
|
||||
|
||||
private:
|
||||
static bool sIsAvailable;
|
||||
|
||||
QString local_filename_;
|
||||
GstElement* pipeline_;
|
||||
GstElement* convert_element_;
|
||||
|
||||
guint bus_callback_id_;
|
||||
|
||||
bool success_;
|
||||
QByteArray data_;
|
||||
};
|
||||
|
||||
#endif // MOODBARPIPELINE_H
|
Loading…
Reference in New Issue