443 lines
11 KiB
C++
443 lines
11 KiB
C++
/***************************************************************************
|
|
|
|
source::worx raDIYo
|
|
Copyright © 2020-2022 c.holzheuer
|
|
c.holzheuer@sourceworx.org
|
|
|
|
This program 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 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
#include <QDebug>
|
|
#include <QAction>
|
|
#include <QCoreApplication>
|
|
#include <QMouseEvent>
|
|
#include <QPainter>
|
|
#include <QTime>
|
|
#include <QTimer>
|
|
#include <QMediaPlayer>
|
|
#include <QUrl>
|
|
#include <QFileInfo>
|
|
#include <QStyle>
|
|
#include <QFileDialog>
|
|
#include <QStandardPaths>
|
|
#include <QMessageBox>
|
|
#include <QFontDatabase>
|
|
|
|
//#include <QHoverEvent>
|
|
//#include <QPointF>
|
|
|
|
//#include <algorithm> // std::swap
|
|
//#include <iostream>
|
|
|
|
#include <swradiyomainwidget.h>
|
|
#include <ui_swradiyomainwidget.h>
|
|
#include <swcontrolstates.h>
|
|
|
|
#include <swplayercontrol.h>
|
|
#include <swsendercontrol.h>
|
|
#include <swsongscontrol.h>
|
|
#include <swshutdowncontrol.h>
|
|
#include <swclockcontrol.h>
|
|
#include <swalarmcontrol.h>
|
|
#include <swsetupcontrol.h>
|
|
#include <swusbcontrol.h>
|
|
#include <swbluetoothcontrol.h>
|
|
|
|
#include <SWPiGPIO.h>
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
static QString formatTime( qint64 timeMilliSeconds )
|
|
{
|
|
qint64 seconds = timeMilliSeconds / 1000;
|
|
const qint64 minutes = seconds / 60;
|
|
seconds -= minutes * 60;
|
|
return QStringLiteral("%1:%2")
|
|
.arg(minutes, 2, 10, QLatin1Char('0'))
|
|
.arg(seconds, 2, 10, QLatin1Char('0'));
|
|
}
|
|
*/
|
|
|
|
/**
|
|
* @brief SWRaDIYoMainWidget --doku begins here ---
|
|
* @param parent
|
|
*
|
|
* contains copy-writen material from qt example code:
|
|
* @see shaped clock example
|
|
* @see embedded/flipdigits example
|
|
*
|
|
*/
|
|
|
|
SWRaDIYoMainWidget::SWRaDIYoMainWidget( QWidget *parent )
|
|
: SWRaDIYoBaseWidget( parent )
|
|
{
|
|
|
|
setupFonts();
|
|
setupUi( this );
|
|
|
|
|
|
/// Setup Controls: 'RaDIYo' Buttons
|
|
/// Reihenfolge beachten, die iost wichtig für
|
|
/// die button-asuwahl per dial
|
|
|
|
_controller.addButton( _buttonPlay, PlayerControl, "play" );
|
|
_controller.addButton( _buttonSender, SenderControl, "sender" );
|
|
_controller.addButton( _buttonSongs, SongsControl, "songs" );
|
|
_controller.addButton( _buttonUSB, UsbControl, "usb" );
|
|
//_controller.addButton( _buttonBlueTooth, SWBLUETOOTHCONTROL, "bluetooth" );
|
|
|
|
_controller.addButton( _buttonClock, ClockControl, "clock" );
|
|
_controller.addButton( _buttonAlarm, AlarmControl, "alarm" );
|
|
_controller.addButton( _buttonSetup, SetupControl, "setup" );
|
|
_controller.addButton( _buttonShutdown, ShutdownControl, "shutdown" );
|
|
|
|
/// Alle Controls, schön vorsortiert.
|
|
_senderControl = new SWSenderControl( this );
|
|
_songsControl = new SWSongsControl( this );
|
|
_playerControl = new SWPlayerControl( this );
|
|
|
|
|
|
_controller.addControl( PlayerControl, _playerControl );
|
|
_controller.addControl( SenderControl, _senderControl );
|
|
_controller.addControl( SongsControl, _songsControl );
|
|
_controller.addControl( UsbControl, new SWUSBControl( this ) );
|
|
_controller.addControl( ClockControl, new SWClockControl( this ) );
|
|
_controller.addControl( AlarmControl, new SWAlarmControl( this ) );
|
|
_controller.addControl( SetupControl, new SWSetupControl( this ) );
|
|
_controller.addControl( ShutdownControl, new SWShutdownControl( this ) );
|
|
//_controller.addControl( SWBLUETOOTHCONTROL] = new SWBlueToothControl( this );
|
|
|
|
connect( &_raDIYoButtons, &QButtonGroup::idClicked, this, &SWControlStates::onIdActivated );
|
|
/// play button hat ne sonderstellung
|
|
connect( _buttonPlay, &QPushButton::clicked, this, &SWControlStates::onVolumeButtonClicked );
|
|
|
|
|
|
/// Setup Controls: Fake Dials unter Win, echte für Linux
|
|
setupDials();
|
|
|
|
/// startup
|
|
loadSettings();
|
|
|
|
/// bei untätigkeit kommt wieder die Uhr
|
|
_idleTimer.setInterval( raDIYo::IdleTimeOut );
|
|
_idleTimer.setSingleShot( true );
|
|
connect( &_idleTimer, &QTimer::timeout, this, &SWRaDIYoMainWidget::onIdleTimeOut );
|
|
|
|
/// Setup Controls: Volume
|
|
connect( _volumeWidget, SIGNAL(valueChanged(int)), this, SLOT(onVolumeValueChanged(int)) );
|
|
|
|
|
|
QString defSender =_settings.value( raDIYo::KeyDefaultSender ).toString();
|
|
_nowPlaying = SWPlayableItem( defSender, SWPlayableItem::WebStream, raDIYo::DefaultVolume );
|
|
onVolumeValueChanged( _nowPlaying.volume );
|
|
|
|
/// wir nehmen den default-sender
|
|
_currentTitle->setText( _nowPlaying.title );
|
|
|
|
/// not least
|
|
_version->setText( raDIYo::Version );
|
|
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief ~SWRaDIYoMainWidget Destructor.
|
|
*/
|
|
|
|
SWRaDIYoMainWidget::~SWRaDIYoMainWidget()
|
|
{
|
|
|
|
|
|
}
|
|
|
|
void SWRaDIYoMainWidget::setCurrentControl( SWAbstractControl* control )
|
|
{
|
|
_currentCtrl = control;
|
|
_currentCtrl->show();
|
|
}
|
|
|
|
void SWRaDIYoMainWidget::setupDials()
|
|
{
|
|
|
|
/* FIX!
|
|
* Schaltschema bei Click:
|
|
* Radio aus / Uhr -click-> Radio ein
|
|
* Radio ein -click-> Radio aus / Uhr
|
|
* Radio aus / Uhr -turn-> Radio ein / VolumeDislay
|
|
* Radio ein -turn-> Radio ein / VolumeDislay
|
|
*/
|
|
|
|
|
|
// Prinzip: Clicks (also 'drücken' in echt) schalten weiter, drehen schaltet auch weiter
|
|
// wenn das control mit 'drehen' nix anfangen kann, wie z.B. das FlipClock control
|
|
|
|
//#ifdef Q_OS_LINUX
|
|
|
|
// Linux, kompiliert auch unter Win
|
|
_dialLeft = new PiGPIORotaryDial( 13, 6, 5, this );
|
|
_dialRight = new PiGPIORotaryDial( 22, 27, 17, this );
|
|
|
|
connect( _dialLeft, SIGNAL(clicked()), _controller, SLOT(onSenderButtonClicked()) );
|
|
connect( _dialRight, SIGNAL(clicked()), _controller, SLOT(onVolumeButtonClicked()) );
|
|
connect( _dialLeft, SIGNAL(valueChanged(int)), _controller, SLOT(onSenderValueChanged(int)) );
|
|
connect( _dialRight, SIGNAL(valueChanged(int)), _volumeWidget, SLOT(onDialValueChanged(int)) );
|
|
|
|
//#endif
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
qDebug() << " --- Q_OS_WIN";
|
|
/// Setup Controls: Fake Dials
|
|
|
|
connect( &_dialDialog.leftDial().pushButton(), &QPushButton::clicked, _controller, &SWControlStates::onSenderButtonClicked );
|
|
connect( &_dialDialog.leftDial().dial(), &QDial::valueChanged, _controller, &SWControlStates::onSenderValueChanged );
|
|
connect( &_dialDialog.rightDial().pushButton(), &QPushButton::clicked, _controller, &SWControlStates::onVolumeButtonClicked );
|
|
|
|
connect( &_dialDialog.rightDial().dial(), &QDial::valueChanged, _volumeWidget, &SWVolumeWidget::onDialValueChanged );
|
|
|
|
_dialDialog.show();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
QSettings& SWRaDIYoMainWidget::settings()
|
|
{
|
|
return _settings;
|
|
}
|
|
|
|
|
|
/// ???
|
|
void SWRaDIYoMainWidget::onIdleTimeOut()
|
|
{
|
|
qDebug() << "--- onIdleTimeOut";
|
|
// swap back
|
|
//swapControls( IDClockControl );
|
|
}
|
|
|
|
|
|
void SWRaDIYoMainWidget::swapControls( int newID )
|
|
{
|
|
|
|
/// FIX! ButtonGroup anpassen!!!
|
|
/*
|
|
qDebug() << "Fade IN" << newID << " Fade OUT: " << _currentCtrlID;
|
|
|
|
// ausblenden
|
|
currentControl().fadeOut();
|
|
_raDIYoButtons.button( _currentCtrlID )->setChecked( false );
|
|
|
|
// alte ID merken
|
|
_lastControlID = _currentCtrlID;
|
|
|
|
// einblenden
|
|
_currentCtrlID = newID;
|
|
_raDIYoButtons.button( newID )->setChecked( true );
|
|
currentControl().fadeIn();
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief onIDTriggered
|
|
* @param newID
|
|
*/
|
|
|
|
void SWRaDIYoMainWidget::onIDTriggered( int newID )
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void SWRaDIYoMainWidget::onVolumeValueChanged( int value )
|
|
{
|
|
|
|
/// 'setValue( value )' reicht hier nicht,
|
|
/// denn der neue Wert muss weiter gereicht
|
|
/// werden, also 'onDialValueChanged'
|
|
|
|
_volumeWidget->onDialValueChanged( value );
|
|
_playerControl->onDialValueChanged( value );
|
|
_dialDialog.rightDial().dial().setValue( value );
|
|
//_dialRight.setValue( value );
|
|
|
|
}
|
|
|
|
|
|
// ...
|
|
void SWRaDIYoMainWidget::onEntryActivated( SWPlayableItem item )
|
|
{
|
|
qDebug() << "--:onEntryActivated: " << item.title << ": " << item.urlText;
|
|
|
|
// Das SIGNAL kommt von einem Control, also schalten wir wieder
|
|
// zurück auf die Buttons
|
|
|
|
_isCtrlActive = false;
|
|
// mehrfache ansagen ignorieren
|
|
if( _nowPlaying.urlText == item.urlText )
|
|
return;
|
|
|
|
// merken
|
|
_nowPlaying = item;
|
|
// abschalten ...
|
|
_isPlayerActive = false;
|
|
// ... und wieder anschalten
|
|
togglePlayMode();
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief startPlaying: von aussen und von innen
|
|
* @param title<
|
|
* @param urlText
|
|
* @param startnow
|
|
*/
|
|
|
|
void SWRaDIYoMainWidget::togglePlayMode()
|
|
{
|
|
/*
|
|
_isPlayerActive = !_isPlayerActive;
|
|
|
|
//QString fullUrl = raDIYo::SngDir + urlText;
|
|
qDebug() << "\n\n+++ togglePlayMode(): " << _currentCtrlID << " :" << _nowPlaying.title << " Url: " << _nowPlaying.urlText << "\n\n";
|
|
|
|
//FIX!
|
|
//QString color = _isPlayerActive ? "rgb(181,181,181)" : "rgb(69,69,69);";
|
|
//_currentTitle->setStyleSheet( _titleCss.arg( color ) );
|
|
_currentTitle->setText( _nowPlaying.title );
|
|
|
|
_buttonPlay->setStyleSheet( _isPlayerActive ? _buttonPauseCss : _buttonPlayCss ) ;
|
|
//_buttonPlay->setStyleSheet( _buttonPauseCss ) ;
|
|
|
|
// FIX! das haut nicht hin
|
|
if( !_isPlayerActive )
|
|
{
|
|
qDebug() << " --- Player OFF";
|
|
_playerControl->stopPlaying();
|
|
/// SpectrumDisplay abschalten, aber nur wenn eingeschaltet war
|
|
if( _currentCtrlID == IDPlayerControl )
|
|
swapControls( _lastControlID );
|
|
return;
|
|
}
|
|
|
|
qDebug() << " --- Player ON";
|
|
swapControls( IDPlayerControl );
|
|
|
|
_playerControl->startPlaying( _nowPlaying.urlText );
|
|
*/
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Fonts explicit laden, _vor_ setupUi
|
|
*/
|
|
|
|
void SWRaDIYoMainWidget::setupFonts()
|
|
{
|
|
|
|
QStringList fontList = QDir( raDIYo::FontDir ).entryList();
|
|
for( const QString& fontName : fontList )
|
|
QFontDatabase::addApplicationFont( raDIYo::FontDir + fontName );
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief loadSettings: die Einstellungen laden
|
|
*/
|
|
|
|
void SWRaDIYoMainWidget::loadSettings()
|
|
{
|
|
/// Dss ist die Bildschirmgröße des Raspi 7 inch displays
|
|
resize( SWScreenLargeX, SWScreenLargeY );
|
|
|
|
|
|
/// hier sind wir auch für die voreinstellungen zuständig: falls
|
|
/// nicht vorhanden, default setzen
|
|
if( !_settings.contains( raDIYo::KeySongsDir ) )
|
|
_settings.setValue( raDIYo::KeySongsDir, QDir::homePath() + raDIYo::SongsDir );
|
|
|
|
/// default Sender belegen
|
|
if( !_settings.contains( raDIYo::KeyDefaultSender ) )
|
|
_settings.setValue( raDIYo::KeyDefaultSender, raDIYo::DefaultSender );
|
|
|
|
/// Wir lesen die Hard-Kodierte Senderliste und schreiben sie in die
|
|
/// settings datenbank
|
|
if( !_settings.contains( raDIYo::KeySenderList ) )
|
|
{
|
|
QString senderList = readResource( raDIYo::ResSenderList );
|
|
// oder doch lieber in ein FILE?
|
|
_settings.setValue( raDIYo::KeySenderList, senderList );
|
|
}
|
|
|
|
// setup list controls
|
|
_senderControl->loadEntryList( _settings.value( raDIYo::KeySenderList ).toString() );
|
|
_songsControl->loadEntryList( _settings.value( raDIYo::KeySongsDir ).toString() );
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief setAlarm @todo implementation
|
|
*/
|
|
void SWRaDIYoMainWidget::setAlarm()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief saveSettings @todo implementation
|
|
*/
|
|
|
|
void SWRaDIYoMainWidget::saveSettings()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief onShutDown
|
|
* @todo implementation
|
|
* @todo shutdown der hardware -> use linux 'sudo kill me'
|
|
*/
|
|
|
|
void SWRaDIYoMainWidget::onShutDown()
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
// wir wollen sterben
|
|
::exit( 0 );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|