Clementine-audio-player-Mac.../src/visualisations/visualisationcontainer.cpp

282 lines
8.2 KiB
C++

/* This file is part of Clementine.
Copyright 2010, 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 "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 <QHBoxLayout>
#include <QSettings>
#include <QGLWidget>
#include <QtDebug>
#include <QGraphicsProxyWidget>
#include <QMenu>
#include <QSignalMapper>
#include <QLabel>
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();
}
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_);
}