Initialise gstreamer in the background instead of blocking the UI

This commit is contained in:
David Sansome 2010-08-27 13:57:39 +00:00
parent c7472eda59
commit 75b70b4acb
5 changed files with 81 additions and 30 deletions

View File

@ -45,6 +45,7 @@
#include <QCoreApplication>
#include <QTimeLine>
#include <QDir>
#include <QtConcurrentRun>
#include <gst/gst.h>
@ -85,6 +86,8 @@ GstEngine::GstEngine()
}
GstEngine::~GstEngine() {
initialising_.waitForFinished();
current_pipeline_.reset();
// Destroy scope delay queue
@ -135,18 +138,17 @@ bool GstEngine::Init() {
SetEnv("GST_REGISTRY", registry_filename);
}
// GStreamer initialization
GError *err;
if ( !gst_init_check( NULL, NULL, &err ) ) {
qWarning("GStreamer could not be initialized");
return false;
}
initialising_ = QtConcurrent::run(this, &GstEngine::InitialiseGstreamer);
return true;
}
void GstEngine::InitialiseGstreamer() {
gst_init(NULL, NULL);
#ifdef HAVE_IMOBILEDEVICE
afcsrc_register_static();
#endif
return true;
}
void GstEngine::ReloadSettings() {
@ -174,6 +176,8 @@ void GstEngine::ReloadSettings() {
bool GstEngine::CanDecode(const QUrl &url) {
initialising_.waitForFinished();
// We had some bug reports claiming that video files cause crashes in canDecode(),
// so don't try to decode them
if ( url.path().toLower().endsWith( ".mov" ) ||
@ -400,6 +404,8 @@ void GstEngine::UpdateScope() {
}
void GstEngine::StartPreloading(const QUrl& url) {
initialising_.waitForFinished();
if (autocrossfade_enabled_) {
// Have to create a new pipeline so we can crossfade between the two
@ -422,6 +428,8 @@ void GstEngine::StartPreloading(const QUrl& url) {
}
bool GstEngine::Load(const QUrl& url, Engine::TrackChangeType change) {
initialising_.waitForFinished();
Engine::Base::Load(url, change);
// Clementine just crashes when asked to load a file that doesn't exist on
@ -495,6 +503,8 @@ void GstEngine::StartFadeout() {
bool GstEngine::Play( uint offset ) {
initialising_.waitForFinished();
QFuture<GstStateChangeReturn> future = current_pipeline_->SetState(GST_STATE_PLAYING);
BoundFutureWatcher<GstStateChangeReturn, uint>* watcher =
new BoundFutureWatcher<GstStateChangeReturn, uint>(offset, this);
@ -708,6 +718,8 @@ GstElement* GstEngine::CreateElement(const QString& factoryName, GstElement* bin
GstEngine::PluginDetailsList
GstEngine::GetPluginList(const QString& classname) const {
const_cast<GstEngine*>(this)->initialising_.waitForFinished();
PluginDetailsList ret;
GstRegistry* registry = gst_registry_get_default();
@ -733,6 +745,8 @@ GstEngine::PluginDetailsList
}
shared_ptr<GstEnginePipeline> GstEngine::CreatePipeline() {
initialising_.waitForFinished();
shared_ptr<GstEnginePipeline> ret(new GstEnginePipeline(this));
ret->set_output_device(sink_, device_);
ret->set_replaygain(rg_enabled_, rg_mode_, rg_preamp_, rg_compression_);

View File

@ -25,6 +25,7 @@
#include "enginebase.h"
#include "bufferconsumer.h"
#include <QFuture>
#include <QHash>
#include <QList>
#include <QString>
@ -130,6 +131,7 @@ class GstEngine : public Engine::Base, public BufferConsumer {
static void SetEnv(const char* key, const QString& value);
PluginDetailsList GetPluginList(const QString& classname) const;
void InitialiseGstreamer();
void StartFadeout();
@ -151,6 +153,8 @@ class GstEngine : public Engine::Base, public BufferConsumer {
static const char* kHypnotoadPipeline;
QFuture<void> initialising_;
QString sink_;
QString device_;

View File

@ -96,6 +96,8 @@
#include <cmath>
#include <QTime>
using boost::shared_ptr;
using boost::scoped_ptr;
@ -148,13 +150,19 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
track_position_timer_(new QTimer(this)),
was_maximized_(false)
{
QTime t;
t.start();
// Wait for the database thread to start - lots of stuff depends on it.
database_->Start(true);
qDebug() << t.restart() << "database startup";
// Create some objects in the database thread
playlist_backend_ = database_->CreateInThread<PlaylistBackend>();
playlist_backend_->SetDatabase(database_->Worker());
qDebug() << t.restart() << "playlist backend";
// Create stuff that needs the database
radio_model_ = new RadioModel(database_, network, task_manager_, this);
player_ = new Player(playlists_, radio_model_->GetLastFMService(), engine, this);
@ -164,6 +172,8 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
radio_model_->SetSettingsDialog(settings_dialog_.get());
devices_ = new DeviceManager(database_, task_manager_, this),
qDebug() << t.restart() << "other shit";
// Initialise the UI
ui_->setupUi(this);
ui_->multi_loading_indicator->SetTaskManager(task_manager_);
@ -177,9 +187,13 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
ui_->tabs->setDocumentMode(false);
#endif
qDebug() << t.restart() << "ui";
// Start initialising the player
player_->Init();
qDebug() << t.restart() << "player";
#ifdef HAVE_GSTREAMER
if (GstEngine* engine = qobject_cast<GstEngine*>(player_->GetEngine())) {
settings_dialog_->SetGstEngine(engine);
@ -217,6 +231,8 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
cover_manager_->Init();
qDebug() << t.restart() << "models";
// Icons
ui_->action_about->setIcon(IconLoader::Load("help-about"));
ui_->action_add_file->setIcon(IconLoader::Load("document-open"));
@ -245,6 +261,8 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
ui_->action_update_library->setIcon(IconLoader::Load("view-refresh"));
ui_->action_rain->setIcon(IconLoader::Load("weather-showers-scattered"));
qDebug() << t.restart() << "icons";
// File view connections
connect(ui_->file_view, SIGNAL(AddToPlaylist(QList<QUrl>)), SLOT(AddFilesToPlaylist(QList<QUrl>)));
connect(ui_->file_view, SIGNAL(Load(QList<QUrl>)), SLOT(LoadFilesToPlaylist(QList<QUrl>)));
@ -416,6 +434,8 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
ui_->action_shuffle->setShortcut(QKeySequence());
#endif
qDebug() << t.restart() << "connections";
playlist_delete_->setVisible(false); // TODO
connect(ui_->playlist, SIGNAL(UndoRedoActionsChanged(QAction*,QAction*)),
@ -445,6 +465,8 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
connect(saved_radio, SIGNAL(ShowAddStreamDialog()),
add_stream_dialog_.get(), SLOT(show()));
qDebug() << t.restart() << "more connections";
#ifdef Q_OS_DARWIN
mac::SetApplicationHandler(this);
#endif
@ -477,6 +499,8 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
wiimotedev_shortcuts_ = new WiimotedevShortcuts(player_, this);
#endif
qDebug() << t.restart() << "tray";
// Global shortcuts
connect(global_shortcuts_, SIGNAL(Play()), player_, SLOT(Play()));
connect(global_shortcuts_, SIGNAL(Pause()), player_, SLOT(Pause()));
@ -539,13 +563,19 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
connect(ui_->action_hypnotoad, SIGNAL(toggled(bool)), ui_->now_playing, SLOT(AllHail(bool)));
NowPlayingWidgetPositionChanged(ui_->now_playing->show_above_status_bar());
qDebug() << t.restart() << "stuff";
// Load theme
StyleSheetLoader* css_loader = new StyleSheetLoader(this);
css_loader->SetStyleSheet(this, ":mainwindow.css");
qDebug() << t.restart() << "theme";
// Load playlists
playlists_->Init(library_->backend(), playlist_backend_, ui_->playlist_sequence);
qDebug() << t.restart() << "load playlists";
// Load settings
settings_.beginGroup(kSettingsGroup);
@ -579,12 +609,16 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
show();
#endif
qDebug() << t.restart() << "load settings";
QShortcut* close_window_shortcut = new QShortcut(this);
close_window_shortcut->setKey(Qt::CTRL + Qt::Key_W);
connect(close_window_shortcut, SIGNAL(activated()), SLOT(SetHiddenInTray()));
library_->Init();
library_->StartThreads();
qDebug() << t.restart() << "start library";
}
MainWindow::~MainWindow() {

View File

@ -42,6 +42,7 @@
SettingsDialog::SettingsDialog(QWidget* parent)
: QDialog(parent),
gst_engine_(NULL),
ui_(new Ui_SettingsDialog),
loading_settings_(false),
pretty_popup_(new OSDPretty(OSDPretty::Mode_Draggable))
@ -280,6 +281,22 @@ void SettingsDialog::showEvent(QShowEvent*) {
QSettings s;
loading_settings_ = true;
#ifdef HAVE_GSTREAMER
if (ui_->gst_plugin->count() == 0 && gst_engine_) {
GstEngine::PluginDetailsList list = gst_engine_->GetOutputsList();
ui_->gst_plugin->setItemData(0, GstEngine::kAutoSink);
foreach (const GstEngine::PluginDetails& details, list) {
if (details.name == "autoaudiosink")
continue;
ui_->gst_plugin->addItem(details.long_name, details.name);
}
ui_->gst_group->setEnabled(true);
ui_->replaygain_group->setEnabled(true);
}
#endif // HAVE_GSTREAMER
// Behaviour
s.beginGroup(MainWindow::kSettingsGroup);
ui_->b_show_tray_icon_->setChecked(s.value("showtray", true).toBool());
@ -456,22 +473,6 @@ void SettingsDialog::ShowTrayIconToggled(bool on) {
ui_->b_remember_->setChecked(true);
}
#ifdef HAVE_GSTREAMER
void SettingsDialog::SetGstEngine(const GstEngine *engine) {
GstEngine::PluginDetailsList list = engine->GetOutputsList();
ui_->gst_plugin->setItemData(0, GstEngine::kAutoSink);
foreach (const GstEngine::PluginDetails& details, list) {
if (details.name == "autoaudiosink")
continue;
ui_->gst_plugin->addItem(details.long_name, details.name);
}
ui_->gst_group->setEnabled(true);
ui_->replaygain_group->setEnabled(true);
}
#endif // HAVE_GSTREAMER
void SettingsDialog::GstPluginChanged(int index) {
#ifdef HAVE_GSTREAMER
QString name = ui_->gst_plugin->itemData(index).toString();

View File

@ -31,9 +31,7 @@ class Ui_SettingsDialog;
class WiimotedevShortcutsConfig;
#endif
#ifdef HAVE_GSTREAMER
class GstEngine;
#endif
class GstEngine;
class SettingsDialog : public QDialog {
Q_OBJECT
@ -57,9 +55,7 @@ class SettingsDialog : public QDialog {
void SetLibraryDirectoryModel(LibraryDirectoryModel* model);
void SetGlobalShortcutManager(GlobalShortcuts* manager);
#ifdef HAVE_GSTREAMER
void SetGstEngine(const GstEngine* engine);
#endif
void SetGstEngine(const GstEngine* engine) { gst_engine_ = engine; }
void OpenAtPage(Page page);
@ -90,6 +86,8 @@ class SettingsDialog : public QDialog {
#ifdef ENABLE_WIIMOTEDEV
WiimotedevShortcutsConfig* wiimotedev_config_;
#endif
const GstEngine* gst_engine_;
Ui_SettingsDialog* ui_;
bool loading_settings_;