2018-02-27 18:06:05 +01:00
|
|
|
/*
|
|
|
|
Strawberry Music Player
|
|
|
|
This file was part of Clementine.
|
|
|
|
Copyright 2010, David Sansome <me@davidsansome.com>
|
|
|
|
|
|
|
|
Strawberry 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.
|
|
|
|
|
|
|
|
Strawberry 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 Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
#include "config.h"
|
|
|
|
|
2021-06-20 19:04:08 +02:00
|
|
|
#include <chrono>
|
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QObject>
|
|
|
|
#include <QWidget>
|
|
|
|
#include <QVariant>
|
|
|
|
#include <QString>
|
|
|
|
#include <QTimer>
|
|
|
|
#include <QBoxLayout>
|
|
|
|
#include <QLayout>
|
2019-07-08 22:27:45 +02:00
|
|
|
#include <QMenu>
|
|
|
|
#include <QAction>
|
|
|
|
#include <QActionGroup>
|
2018-05-01 00:41:33 +02:00
|
|
|
#include <QSettings>
|
|
|
|
#include <QtEvents>
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
#include "analyzercontainer.h"
|
2018-05-01 00:41:33 +02:00
|
|
|
|
|
|
|
#include "analyzerbase.h"
|
2018-02-27 18:06:05 +01:00
|
|
|
#include "blockanalyzer.h"
|
2019-02-04 21:34:12 +01:00
|
|
|
#include "boomanalyzer.h"
|
|
|
|
#include "rainbowanalyzer.h"
|
2023-01-12 07:33:34 +01:00
|
|
|
#include "sonogram.h"
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
#include "core/logging.h"
|
2020-02-08 03:40:30 +01:00
|
|
|
#include "engine/enginebase.h"
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2021-06-20 19:04:08 +02:00
|
|
|
using namespace std::chrono_literals;
|
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
const char *AnalyzerContainer::kSettingsGroup = "Analyzer";
|
|
|
|
const char *AnalyzerContainer::kSettingsFramerate = "framerate";
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
// Framerates
|
|
|
|
const int AnalyzerContainer::kLowFramerate = 20;
|
|
|
|
const int AnalyzerContainer::kMediumFramerate = 25;
|
|
|
|
const int AnalyzerContainer::kHighFramerate = 30;
|
|
|
|
const int AnalyzerContainer::kSuperHighFramerate = 60;
|
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
AnalyzerContainer::AnalyzerContainer(QWidget *parent)
|
2018-02-27 18:06:05 +01:00
|
|
|
: QWidget(parent),
|
|
|
|
current_framerate_(kMediumFramerate),
|
|
|
|
context_menu_(new QMenu(this)),
|
|
|
|
context_menu_framerate_(new QMenu(tr("Framerate"), this)),
|
|
|
|
group_(new QActionGroup(this)),
|
|
|
|
group_framerate_(new QActionGroup(this)),
|
|
|
|
double_click_timer_(new QTimer(this)),
|
|
|
|
ignore_next_click_(false),
|
|
|
|
current_analyzer_(nullptr),
|
|
|
|
engine_(nullptr) {
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
QHBoxLayout *layout = new QHBoxLayout(this);
|
2018-02-27 18:06:05 +01:00
|
|
|
setLayout(layout);
|
|
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
|
|
// Init framerate sub-menu
|
|
|
|
AddFramerate(tr("Low (%1 fps)").arg(kLowFramerate), kLowFramerate);
|
|
|
|
AddFramerate(tr("Medium (%1 fps)").arg(kMediumFramerate), kMediumFramerate);
|
|
|
|
AddFramerate(tr("High (%1 fps)").arg(kHighFramerate), kHighFramerate);
|
|
|
|
AddFramerate(tr("Super high (%1 fps)").arg(kSuperHighFramerate), kSuperHighFramerate);
|
|
|
|
|
|
|
|
context_menu_->addMenu(context_menu_framerate_);
|
|
|
|
context_menu_->addSeparator();
|
|
|
|
|
|
|
|
AddAnalyzerType<BlockAnalyzer>();
|
2019-02-04 21:34:12 +01:00
|
|
|
AddAnalyzerType<BoomAnalyzer>();
|
|
|
|
AddAnalyzerType<Rainbow::NyanCatAnalyzer>();
|
|
|
|
AddAnalyzerType<Rainbow::RainbowDashAnalyzer>();
|
2023-01-12 07:33:34 +01:00
|
|
|
AddAnalyzerType<Sonogram>();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
2021-01-26 16:48:04 +01:00
|
|
|
disable_action_ = context_menu_->addAction(tr("No analyzer"), this, &AnalyzerContainer::DisableAnalyzer);
|
2018-02-27 18:06:05 +01:00
|
|
|
disable_action_->setCheckable(true);
|
|
|
|
group_->addAction(disable_action_);
|
|
|
|
|
|
|
|
context_menu_->addSeparator();
|
|
|
|
|
|
|
|
double_click_timer_->setSingleShot(true);
|
2021-06-20 19:04:08 +02:00
|
|
|
double_click_timer_->setInterval(250ms);
|
2021-01-26 16:48:04 +01:00
|
|
|
QObject::connect(double_click_timer_, &QTimer::timeout, this, &AnalyzerContainer::ShowPopupMenu);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
Load();
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
void AnalyzerContainer::mouseReleaseEvent(QMouseEvent *e) {
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2023-04-22 19:13:42 +02:00
|
|
|
if (engine_->type() != EngineBase::Type::GStreamer) {
|
2021-08-23 21:21:08 +02:00
|
|
|
return;
|
|
|
|
}
|
2019-04-20 22:24:11 +02:00
|
|
|
|
2019-11-11 00:01:39 +01:00
|
|
|
if (e->button() == Qt::RightButton) {
|
2020-07-18 04:09:36 +02:00
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
|
|
context_menu_->popup(e->globalPosition().toPoint());
|
|
|
|
#else
|
2018-02-27 18:06:05 +01:00
|
|
|
context_menu_->popup(e->globalPos());
|
2020-07-18 04:09:36 +02:00
|
|
|
#endif
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AnalyzerContainer::ShowPopupMenu() {
|
|
|
|
context_menu_->popup(last_click_pos_);
|
|
|
|
}
|
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
void AnalyzerContainer::wheelEvent(QWheelEvent *e) {
|
2020-05-29 17:42:40 +02:00
|
|
|
emit WheelEvent(e->angleDelta().y());
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
void AnalyzerContainer::SetEngine(EngineBase *engine) {
|
2021-08-23 21:21:08 +02:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
if (current_analyzer_) current_analyzer_->set_engine(engine);
|
|
|
|
engine_ = engine;
|
2021-08-23 21:21:08 +02:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AnalyzerContainer::DisableAnalyzer() {
|
|
|
|
delete current_analyzer_;
|
|
|
|
current_analyzer_ = nullptr;
|
|
|
|
|
|
|
|
Save();
|
|
|
|
}
|
|
|
|
|
2021-01-26 16:48:04 +01:00
|
|
|
void AnalyzerContainer::ChangeAnalyzer(const int id) {
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
QObject *instance = analyzer_types_[id]->newInstance(Q_ARG(QWidget*, this));
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
if (!instance) {
|
2020-10-17 17:29:09 +02:00
|
|
|
qLog(Warning) << "Couldn't initialize a new" << analyzer_types_[id]->className();
|
2018-02-27 18:06:05 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete current_analyzer_;
|
|
|
|
current_analyzer_ = qobject_cast<Analyzer::Base*>(instance);
|
|
|
|
current_analyzer_->set_engine(engine_);
|
|
|
|
// Even if it is not supposed to happen, I don't want to get a dbz error
|
|
|
|
current_framerate_ = current_framerate_ == 0 ? kMediumFramerate : current_framerate_;
|
2022-04-01 22:30:00 +02:00
|
|
|
current_analyzer_->ChangeTimeout(1000 / current_framerate_);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
layout()->addWidget(current_analyzer_);
|
|
|
|
|
|
|
|
Save();
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AnalyzerContainer::ChangeFramerate(int new_framerate) {
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
if (current_analyzer_) {
|
|
|
|
// Even if it is not supposed to happen, I don't want to get a dbz error
|
|
|
|
new_framerate = new_framerate == 0 ? kMediumFramerate : new_framerate;
|
2022-04-01 22:30:00 +02:00
|
|
|
current_analyzer_->ChangeTimeout(1000 / new_framerate);
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
// notify the current analyzer that the framerate has changed
|
|
|
|
current_analyzer_->framerateChanged();
|
|
|
|
}
|
|
|
|
SaveFramerate(new_framerate);
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AnalyzerContainer::Load() {
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
QSettings s;
|
|
|
|
s.beginGroup(kSettingsGroup);
|
2019-02-04 21:34:12 +01:00
|
|
|
QString type = s.value("type", "BlockAnalyzer").toString();
|
|
|
|
current_framerate_ = s.value(kSettingsFramerate, kMediumFramerate).toInt();
|
|
|
|
s.endGroup();
|
2018-02-27 18:06:05 +01:00
|
|
|
|
|
|
|
// Analyzer
|
|
|
|
if (type.isEmpty()) {
|
|
|
|
DisableAnalyzer();
|
|
|
|
disable_action_->setChecked(true);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (int i = 0; i < analyzer_types_.count(); ++i) {
|
|
|
|
if (type == analyzer_types_[i]->className()) {
|
|
|
|
ChangeAnalyzer(i);
|
|
|
|
actions_[i]->setChecked(true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Framerate
|
2021-03-21 04:49:22 +01:00
|
|
|
QList<QAction*> actions = group_framerate_->actions();
|
2018-02-27 18:06:05 +01:00
|
|
|
for (int i = 0; i < framerate_list_.count(); ++i) {
|
|
|
|
if (current_framerate_ == framerate_list_[i]) {
|
|
|
|
ChangeFramerate(current_framerate_);
|
2021-03-21 04:47:11 +01:00
|
|
|
actions[i]->setChecked(true);
|
2018-02-27 18:06:05 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2021-01-26 16:48:04 +01:00
|
|
|
void AnalyzerContainer::SaveFramerate(const int framerate) {
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2018-05-01 00:41:33 +02:00
|
|
|
// For now, framerate is common for all analyzers. Maybe each analyzer should have its own framerate?
|
2018-02-27 18:06:05 +01:00
|
|
|
current_framerate_ = framerate;
|
|
|
|
QSettings s;
|
|
|
|
s.beginGroup(kSettingsGroup);
|
|
|
|
s.setValue(kSettingsFramerate, current_framerate_);
|
2019-02-04 21:34:12 +01:00
|
|
|
s.endGroup();
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AnalyzerContainer::Save() {
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
QSettings s;
|
|
|
|
s.beginGroup(kSettingsGroup);
|
|
|
|
s.setValue("type", current_analyzer_ ? current_analyzer_->metaObject()->className() : QVariant());
|
2019-02-04 21:34:12 +01:00
|
|
|
s.endGroup();
|
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|
|
|
|
|
2021-06-12 20:53:23 +02:00
|
|
|
void AnalyzerContainer::AddFramerate(const QString &name, const int framerate) {
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2019-07-08 22:27:45 +02:00
|
|
|
QAction *action = context_menu_framerate_->addAction(name);
|
2018-02-27 18:06:05 +01:00
|
|
|
group_framerate_->addAction(action);
|
|
|
|
framerate_list_ << framerate;
|
|
|
|
action->setCheckable(true);
|
2021-08-25 02:55:00 +02:00
|
|
|
QObject::connect(action, &QAction::triggered, this, [this, framerate]() { ChangeFramerate(framerate); } );
|
2019-02-04 21:34:12 +01:00
|
|
|
|
2018-02-27 18:06:05 +01:00
|
|
|
}
|