/* This file is part of Clementine. Copyright 2010, David Sansome 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 "config.h" #include "projectmvisualisation.h" #include "visualisationcontainer.h" #include "visualisationoverlay.h" #include "visualisationselector.h" #include "engines/gstengine.h" #include "ui/iconloader.h" #include "ui/screensaver.h" #include #include #include #include #include #include #include #include #include const char* VisualisationContainer::kSettingsGroup = "Visualisations"; const int VisualisationContainer::kDefaultWidth = 828; const int VisualisationContainer::kDefaultHeight = 512; const int VisualisationContainer::kDefaultFps = 35; const int VisualisationContainer::kDefaultTextureSize = 512; VisualisationContainer::VisualisationContainer(QWidget *parent) : QGraphicsView(parent), initialised_(false), engine_(NULL), vis_(new ProjectMVisualisation(this)), overlay_(new VisualisationOverlay), selector_(new VisualisationSelector(this)), overlay_proxy_(NULL), menu_(new QMenu(this)), fps_(kDefaultFps), size_(kDefaultTextureSize) { QSettings s; s.beginGroup(kSettingsGroup); if (!restoreGeometry(s.value("geometry").toByteArray())) { resize(kDefaultWidth, kDefaultHeight); } fps_ = s.value("fps", kDefaultFps).toInt(); size_ = s.value("size", kDefaultTextureSize).toInt(); QShortcut* close = new QShortcut(QKeySequence::Close, this); connect(close, SIGNAL(activated()), SLOT(close())); } void VisualisationContainer::Init() { setWindowTitle(tr("Clementine Visualization")); setWindowIcon(QIcon(":/icon.png")); // Set up the graphics view setScene(vis_); setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); setViewportUpdateMode(QGraphicsView::FullViewportUpdate); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setFrameStyle(QFrame::NoFrame); // Add the overlay overlay_proxy_ = scene()->addWidget(overlay_); connect(overlay_, SIGNAL(OpacityChanged(qreal)), SLOT(ChangeOverlayOpacity(qreal))); connect(overlay_, SIGNAL(ShowPopupMenu(QPoint)), SLOT(ShowPopupMenu(QPoint))); ChangeOverlayOpacity(0.0); vis_->SetTextureSize(size_); SizeChanged(); // Selector selector_->SetVisualisation(vis_); // Settings menu menu_->addAction(IconLoader::Load("view-fullscreen"), tr("Toggle fullscreen"), this, SLOT(ToggleFullscreen())); QMenu* fps_menu = menu_->addMenu(tr("Framerate")); QSignalMapper* fps_mapper = new QSignalMapper(this); QActionGroup* fps_group = new QActionGroup(this); AddMenuItem(tr("Low (15 fps)"), 15, fps_, fps_group, fps_mapper); AddMenuItem(tr("Medium (25 fps)"), 25, fps_, fps_group, fps_mapper); AddMenuItem(tr("High (35 fps)"), 35, fps_, fps_group, fps_mapper); AddMenuItem(tr("Super high (60 fps)"), 60, fps_, fps_group, fps_mapper); fps_menu->addActions(fps_group->actions()); connect(fps_mapper, SIGNAL(mapped(int)), SLOT(SetFps(int))); QMenu* quality_menu = menu_->addMenu(tr("Quality")); QSignalMapper* quality_mapper = new QSignalMapper(this); QActionGroup* quality_group = new QActionGroup(this); AddMenuItem(tr("Low (256x256)"), 256, size_, quality_group, quality_mapper); AddMenuItem(tr("Medium (512x512)"), 512, size_, quality_group, quality_mapper); AddMenuItem(tr("High (1024x1024)"), 1024, size_, quality_group, quality_mapper); quality_menu->addActions(quality_group->actions()); connect(quality_mapper, SIGNAL(mapped(int)), SLOT(SetQuality(int))); menu_->addAction(tr("Select visualizations..."), selector_, SLOT(show())); menu_->addSeparator(); menu_->addAction(IconLoader::Load("application-exit"), tr("Close visualization"), this, SLOT(hide())); } void VisualisationContainer::AddMenuItem(const QString &name, int value, int def, QActionGroup* group, QSignalMapper *mapper) { QAction* action = group->addAction(name); action->setCheckable(true); action->setChecked(value == def); mapper->setMapping(action, value); connect(action, SIGNAL(triggered()), mapper, SLOT(map())); } void VisualisationContainer::SetEngine(GstEngine* engine) { engine_ = engine; #ifdef HAVE_GSTREAMER if (isVisible()) engine_->AddBufferConsumer(vis_); #endif } void VisualisationContainer::showEvent(QShowEvent* e) { if (!initialised_) { Init(); initialised_ = true; } QGraphicsView::showEvent(e); update_timer_.start(1000 / fps_, this); #ifdef HAVE_GSTREAMER if (engine_) engine_->AddBufferConsumer(vis_); #endif } void VisualisationContainer::hideEvent(QHideEvent* e) { QGraphicsView::hideEvent(e); update_timer_.stop(); #ifdef HAVE_GSTREAMER if (engine_) engine_->RemoveBufferConsumer(vis_); #endif } void VisualisationContainer::resizeEvent(QResizeEvent* e) { QGraphicsView::resizeEvent(e); SizeChanged(); } void VisualisationContainer::SizeChanged() { // Save the geometry QSettings s; s.beginGroup(kSettingsGroup); s.setValue("geometry", saveGeometry()); // Resize the scene if (scene()) scene()->setSceneRect(QRect(QPoint(0, 0), size())); // Resize the overlay if (overlay_) overlay_->resize(size()); } void VisualisationContainer::timerEvent(QTimerEvent* e) { QGraphicsView::timerEvent(e); if (e->timerId() == update_timer_.timerId()) scene()->update(); } void VisualisationContainer::SetActions(QAction *previous, QAction *play_pause, QAction *stop, QAction *next) { overlay_->SetActions(previous, play_pause, stop, next); } void VisualisationContainer::SongMetadataChanged(const Song &metadata) { overlay_->SetSongTitle(QString("%1 - %2").arg(metadata.artist(), metadata.title())); } void VisualisationContainer::Stopped() { overlay_->SetSongTitle(tr("Clementine")); } void VisualisationContainer::ChangeOverlayOpacity(qreal value) { overlay_proxy_->setOpacity(value); // Hide the cursor if the overlay is hidden if (value < 0.5) viewport()->setCursor(Qt::BlankCursor); else viewport()->unsetCursor(); } void VisualisationContainer::enterEvent(QEvent* e) { QGraphicsView::enterEvent(e); overlay_->SetVisible(true); } void VisualisationContainer::leaveEvent(QEvent* e) { QGraphicsView::leaveEvent(e); overlay_->SetVisible(false); } void VisualisationContainer::mouseMoveEvent(QMouseEvent* e) { QGraphicsView::mouseMoveEvent(e); overlay_->SetVisible(true); } void VisualisationContainer::mouseDoubleClickEvent(QMouseEvent* e) { QGraphicsView::mouseDoubleClickEvent(e); ToggleFullscreen(); } void VisualisationContainer::contextMenuEvent(QContextMenuEvent *event) { QGraphicsView::contextMenuEvent(event); ShowPopupMenu(event->pos()); } void VisualisationContainer::keyReleaseEvent(QKeyEvent *event) { if (event->matches(QKeySequence::Close) || event->key() == Qt::Key_Escape) { if (isFullScreen()) ToggleFullscreen(); else hide(); return; } QGraphicsView::keyReleaseEvent(event); } void VisualisationContainer::ToggleFullscreen() { setWindowState(windowState() ^ Qt::WindowFullScreen); Screensaver* screensaver = Screensaver::GetScreensaver(); if (screensaver) isFullScreen() ? screensaver->Inhibit() : screensaver->Uninhibit(); } void VisualisationContainer::SetFps(int fps) { fps_ = fps; // Save settings QSettings s; s.beginGroup(kSettingsGroup); s.setValue("fps", fps_); update_timer_.stop(); update_timer_.start(1000 / fps_, this); } void VisualisationContainer::ShowPopupMenu(const QPoint &pos) { menu_->popup(mapToGlobal(pos)); } void VisualisationContainer::SetQuality(int size) { size_ = size; // Save settings QSettings s; s.beginGroup(kSettingsGroup); s.setValue("size", size_); vis_->SetTextureSize(size_); }