diff --git a/JustAudio.pro b/JustAudio.pro index 0ea749c..6edcb5b 100644 --- a/JustAudio.pro +++ b/JustAudio.pro @@ -17,16 +17,16 @@ SOURCES += main.cpp\ gui/ui.cpp\ gui/icon.cpp \ io/aud_file.cpp \ - io/conf.cpp \ - io/idm.cpp \ - io/int.cpp + io/conf.cpp \ + io/idm.cpp \ + io/int.cpp HEADERS += gui/ui.h\ gui/icon.h \ io/aud_file.h \ - io/conf.h \ - io/idm.h \ - io/int.h + io/conf.h \ + io/idm.h \ + io/int.h RESOURCES += icon_files.qrc diff --git a/app_logo.ico b/app_logo.ico index 72d8b75..9cfd016 100644 Binary files a/app_logo.ico and b/app_logo.ico differ diff --git a/gui/icon.cpp b/gui/icon.cpp index d8146bd..e68c0fd 100644 --- a/gui/icon.cpp +++ b/gui/icon.cpp @@ -17,29 +17,73 @@ Icon::Icon(IconType t, QWidget *parent) : QToolButton(parent) stateChanged(QMediaPlayer::StoppedState); setToolTip(tr("Pause/Play")); - connect(this, SIGNAL(clicked()), this, SLOT(buttonClicked())); - break; } case MENU: { - loadImg(":/menu"); + loadImg(":/svg/menu"); setToolTip(tr("Menu")); break; } case OPEN: { - loadImg(":/open"); + loadImg(":/svg/open"); setToolTip(tr("Open File")); - connect(this, SIGNAL(clicked()), this, SLOT(buttonClicked())); + break; + } + case STOP: + { + loadImg(":/svg/stop"); + setToolTip(tr("Stop")); + + break; + } + case PREV: + { + loadImg(":/svg/prev"); + setToolTip(tr("Previous File")); + + break; + } + case NEXT: + { + loadImg(":/svg/next"); + setToolTip(tr("Next File")); + + break; + } + case VOL_UP: + { + loadImg(":/svg/volume_up"); + setToolTip(tr("Volume Up")); + + break; + } + case VOL_DOWN: + { + loadImg(":/svg/volume_down"); + setToolTip(tr("Volume Down")); + + break; + } + case RESTORE: + { + loadImg(":/svg/restore"); + setToolTip(tr("Restore")); break; } } - type = t; + if (t != MENU) + { + connect(this, SIGNAL(clicked()), this, SLOT(buttonClicked())); + } + + type = t; + volSlider = 0; } void Icon::buttonClicked() @@ -59,6 +103,30 @@ void Icon::buttonClicked() { emit open(); } + else if (type == NEXT) + { + emit next(); + } + else if (type == PREV) + { + emit prev(); + } + else if (type == STOP) + { + emit stop(); + } + else if ((type == VOL_DOWN) && volSlider) + { + volSlider->setValue(volSlider->value() - 1); + } + else if ((type == VOL_UP) && volSlider) + { + volSlider->setValue(volSlider->value() + 1); + } + else if (type == RESTORE) + { + emit restore(); + } } void Icon::paintEvent(QPaintEvent *) @@ -75,11 +143,11 @@ void Icon::stateChanged(QMediaPlayer::State state) if (state == QMediaPlayer::PlayingState) { - loadImg(":/pause"); + loadImg(":/svg/pause"); } else { - loadImg(":/play"); + loadImg(":/svg/play"); } } @@ -89,3 +157,8 @@ void Icon::loadImg(const QString &path) update(); } + +void Icon::setSlider(QSlider *slider) +{ + volSlider = slider; +} diff --git a/gui/icon.h b/gui/icon.h index f0f56f8..0bf6f83 100644 --- a/gui/icon.h +++ b/gui/icon.h @@ -12,6 +12,7 @@ #include #include #include +#include class Icon : public QToolButton { @@ -23,11 +24,19 @@ public: { PAUSE_PLAY, MENU, - OPEN + OPEN, + STOP, + PREV, + NEXT, + VOL_UP, + VOL_DOWN, + RESTORE }; Icon(IconType t, QWidget *parent = 0); + void setSlider(QSlider *slider); + public slots: void stateChanged(QMediaPlayer::State state); @@ -37,6 +46,7 @@ private: IconType type; QMediaPlayer::State playerState; QString svgFile; + QSlider *volSlider; void paintEvent(QPaintEvent *); void loadImg(const QString &path); @@ -51,6 +61,10 @@ signals: void play(); void settings(); void open(); + void next(); + void prev(); + void stop(); + void restore(); }; #endif // ICON_H diff --git a/gui/ui.cpp b/gui/ui.cpp index c51e9ce..4a3df29 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -2,10 +2,17 @@ Ui::Ui(const QStringList &args, QWidget *parent) : QWidget(parent) { - QWidget *btnWid = new QWidget(this); - QHBoxLayout *btnLayout = new QHBoxLayout(btnWid); - QVBoxLayout *mainLayout = new QVBoxLayout(this); + QWidget *btnWid = new QWidget(this); + QHBoxLayout *btnLayout = new QHBoxLayout(btnWid); + QVBoxLayout *mainLayout = new QVBoxLayout(this); + Icon *trayPausePlay = new Icon(Icon::PAUSE_PLAY, this); + Icon *trayOpen = new Icon(Icon::OPEN, this); + Icon *trayStop = new Icon(Icon::STOP, this); + Icon *trayNext = new Icon(Icon::NEXT, this); + Icon *trayPrev = new Icon(Icon::PREV, this); + Icon *trayRestore = new Icon(Icon::RESTORE, this); + trayMenu = new QMenu(this); fileName = new QLabel(this); slider = new QSlider(this); menu = new QMenu(this); @@ -13,6 +20,9 @@ Ui::Ui(const QStringList &args, QWidget *parent) : QWidget(parent) settings = new Icon(Icon::MENU, this); pausePlay = new Icon(Icon::PAUSE_PLAY, this); open = new Icon(Icon::OPEN, this); + stop = new Icon(Icon::STOP, this); + next = new Icon(Icon::NEXT, this); + prev = new Icon(Icon::PREV, this); player = new QMediaPlayer(this); ioDev = new AudFile(this); conf = new Conf(this); @@ -29,22 +39,44 @@ Ui::Ui(const QStringList &args, QWidget *parent) : QWidget(parent) fileName->setFont(fnt); slider->setOrientation(Qt::Horizontal); trayIcon->show(); + trayIcon->setContextMenu(trayMenu); conf->populateOptionsMenu(menu, this); player->setVolume(conf->getVolume()); + trayMenu->addAction(new MenuItem(trayPausePlay->toolTip(), trayPausePlay, this)); + trayMenu->addAction(new MenuItem(trayOpen->toolTip(), trayOpen, this)); + trayMenu->addAction(new MenuItem(trayStop->toolTip(), trayStop, this)); + trayMenu->addAction(new MenuItem(trayNext->toolTip(), trayNext, this)); + trayMenu->addAction(new MenuItem(trayPrev->toolTip(), trayPrev, this)); + trayMenu->addAction(new MenuItem(trayRestore->toolTip(), trayRestore, this)); + btnLayout->addWidget(prev); btnLayout->addWidget(pausePlay); + btnLayout->addWidget(stop); + btnLayout->addWidget(next); btnLayout->addWidget(open); btnLayout->addWidget(settings); mainLayout->addWidget(fileName); mainLayout->addWidget(slider); mainLayout->addWidget(btnWid, 0, Qt::AlignCenter); + connect(trayRestore, SIGNAL(restore()), this, SLOT(showNormal())); + connect(trayPausePlay, SIGNAL(pause()), player, SLOT(pause())); + connect(trayPausePlay, SIGNAL(play()), player, SLOT(play())); + connect(trayNext, SIGNAL(next()), this, SLOT(nextFile())); + connect(trayPrev, SIGNAL(prev()), this, SLOT(prevFile())); + connect(trayStop, SIGNAL(stop()), this, SLOT(stopPlayer())); + connect(trayOpen, SIGNAL(open()), this, SLOT(openDialog())); + connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason))); connect(pausePlay, SIGNAL(pause()), player, SLOT(pause())); connect(pausePlay, SIGNAL(play()), player, SLOT(play())); + connect(next, SIGNAL(next()), this, SLOT(nextFile())); + connect(prev, SIGNAL(prev()), this, SLOT(prevFile())); + connect(stop, SIGNAL(stop()), this, SLOT(stopPlayer())); connect(open, SIGNAL(open()), this, SLOT(openDialog())); connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(error(QMediaPlayer::Error))); connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), pausePlay, SLOT(stateChanged(QMediaPlayer::State))); - connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(posChanged(qint64))); - connect(player, SIGNAL(durationChanged(qint64)), this, SLOT(durChanged(qint64))); + connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), trayPausePlay, SLOT(stateChanged(QMediaPlayer::State))); + connect(ioDev, SIGNAL(posChanged(qint64)), this, SLOT(posChanged(qint64))); + connect(ioDev, SIGNAL(endOfPlayback()), this, SLOT(nextFile())); connect(slider, SIGNAL(sliderPressed()), this, SLOT(sliderPressed())); connect(slider, SIGNAL(sliderReleased()), this, SLOT(sliderReleased())); connect(conf, SIGNAL(volume(int)), player, SLOT(setVolume(int))); @@ -57,9 +89,7 @@ Ui::Ui(const QStringList &args, QWidget *parent) : QWidget(parent) void Ui::play(const QString &path) { - player->blockSignals(true); - player->stop(); - pausePlay->stateChanged(QMediaPlayer::StoppedState); + stopPlayer(); if (ioDev->openFile(path)) { @@ -68,9 +98,8 @@ void Ui::play(const QString &path) conf->setLastPath(info.path()); fileName->setText(info.fileName()); player->setMedia(0, ioDev); - slider->setValue(0); - slider->setMinimum(0); - pausePlay->stateChanged(QMediaPlayer::PlayingState); + slider->setMinimum(ioDev->getOffset()); + slider->setMaximum(ioDev->size()); player->play(); adjustSize(); @@ -79,8 +108,14 @@ void Ui::play(const QString &path) { error(QMediaPlayer::ResourceError); } +} - player->blockSignals(false); +void Ui::stopPlayer() +{ + ioDev->blockSignals(true); + player->stop(); + ioDev->blockSignals(false); + slider->setValue(ioDev->getOffset()); } void Ui::openDialog() @@ -139,25 +174,29 @@ void Ui::sliderReleased() { pressed = false; - player->setPosition(slider->value()); + float pos = (float) slider->value() - ioDev->getOffset(); + float max = (float) slider->maximum() - ioDev->getOffset(); + float mul = pos / max; + + player->setPosition(mul * player->duration()); } void Ui::posChanged(qint64 pos) { if (!pressed) slider->setSliderPosition(pos); - - if ((slider->sliderPosition() == slider->maximum()) && conf->nextFile()) - { - QTimer::singleShot(1000, this, SLOT(nextFile())); - } -} - -void Ui::durChanged(qint64 len) -{ - slider->setMaximum(len); } void Ui::nextFile() +{ + fileDir('+'); +} + +void Ui::prevFile() +{ + fileDir('-'); +} + +void Ui::fileDir(char direction) { QDir dir(conf->getLastPath()); @@ -173,7 +212,8 @@ void Ui::nextFile() if (pos != -1) { - pos++; + if (direction == '+') pos++; + else if (direction == '-') pos--; if (pos < list.size()) { @@ -181,3 +221,28 @@ void Ui::nextFile() } } } + +void Ui::trayActivated(QSystemTrayIcon::ActivationReason reason) +{ + Q_UNUSED(reason); + + trayMenu->popup(trayIcon->geometry().center()); +} + +void Ui::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::WindowStateChange) + { + if (windowState() & Qt::WindowMinimized) + { + hide(); + } + } +} + +void Ui::closeEvent(QCloseEvent *event) +{ + Q_UNUSED(event); + + QCoreApplication::exit(); +} diff --git a/gui/ui.h b/gui/ui.h index e3b5b95..fcfb4ef 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -20,6 +20,10 @@ #include #include #include +#include +#include +#include +#include #include "icon.h" #include "../io/aud_file.h" @@ -39,20 +43,30 @@ private: QSystemTrayIcon *trayIcon; Conf *conf; QMenu *menu; + QMenu *trayMenu; Icon *pausePlay; Icon *open; + Icon *next; + Icon *prev; + Icon *stop; bool pressed; + void fileDir(char direction); + void changeEvent(QEvent *event); + void closeEvent(QCloseEvent *event); + private slots: void error(QMediaPlayer::Error error); void sliderPressed(); void sliderReleased(); void posChanged(qint64 pos); - void durChanged(qint64 len); void openDialog(); void nextFile(); + void prevFile(); + void stopPlayer(); void play(const QString &path); + void trayActivated(QSystemTrayIcon::ActivationReason reason); public: diff --git a/icon_files.qrc b/icon_files.qrc index df5f091..c91a966 100644 --- a/icon_files.qrc +++ b/icon_files.qrc @@ -1,9 +1,29 @@ + app_logo.ico + + svg/open.svg svg/pause.svg svg/play.svg svg/menu.svg - app_logo.ico + svg/next.svg + svg/prev.svg + svg/stop.svg + svg/volume_up.svg + svg/volume_down.svg + svg/restore.svg + + + png/open.png + png/pause.png + png/play.png + png/menu.png + png/next.png + png/prev.png + png/stop.png + png/volume_up.png + png/volume_down.png + png/restore.png diff --git a/io/aud_file.cpp b/io/aud_file.cpp index 50fa46b..3d335fd 100644 --- a/io/aud_file.cpp +++ b/io/aud_file.cpp @@ -2,7 +2,9 @@ AudFile::AudFile(QObject *parent) : QFile(parent) { - offset = 0; + offset = 0; + buffRate = 0; + init = true; } AudFile::~AudFile() @@ -14,6 +16,9 @@ bool AudFile::openFile(const QString &path) { close(); + init = true; + buffRate = 0; + setFileName(path); bool ret = open(QFile::ReadOnly); @@ -57,10 +62,46 @@ bool AudFile::openFile(const QString &path) bool AudFile::seek(qint64 off) { - return QFile::seek(offset + off); + qint64 newPos = offset + off; + + if (init) + { + if ((off) && (!buffRate)) + { + buffRate = off; + + emit duration(getDuration()); + } + + if (newPos >= size()) + { + init = false; + } + } + else + { + emit posChanged(pos()); + + if (newPos >= size()) + { + QTimer::singleShot(2000, this, SLOT(delayFinished())); + } + } + + return QFile::seek(newPos); } -qint64 AudFile::size() const +qint64 AudFile::getOffset() { - return QFile::size() - offset; + return offset; +} + +qint64 AudFile::getDuration() +{ + return ((size() - offset) / buffRate) * 1000; +} + +void AudFile::delayFinished() +{ + emit endOfPlayback(); } diff --git a/io/aud_file.h b/io/aud_file.h index 5ea927a..75e18dd 100644 --- a/io/aud_file.h +++ b/io/aud_file.h @@ -5,7 +5,8 @@ #include #include #include -#include +#include +#include class AudFile : public QFile { @@ -13,7 +14,13 @@ class AudFile : public QFile private: + qint64 buffRate; qint64 offset; + bool init; + +private slots: + + void delayFinished(); public: @@ -21,9 +28,16 @@ public: bool openFile(const QString &path); bool seek(qint64 off); - qint64 size() const; + qint64 getOffset(); + qint64 getDuration(); ~AudFile(); + +signals: + + void posChanged(qint64 off); + void endOfPlayback(); + void duration(qint64 msec); }; #endif // AUD_FILE_H diff --git a/io/conf.cpp b/io/conf.cpp index fe62c99..4b588fa 100644 --- a/io/conf.cpp +++ b/io/conf.cpp @@ -8,14 +8,23 @@ MenuItem::MenuItem(const QString &label, QWidget *widget, QObject *parent) : QWi QWidget *MenuItem::createWidget(QWidget *parent) { - QWidget *widget = new QWidget(parent); - QHBoxLayout *layout = new QHBoxLayout(widget); + if (str.isEmpty()) + { + wid->setParent(parent); - layout->addWidget(new QLabel(str, parent)); - layout->addStretch(); - layout->addWidget(wid, 0, Qt::AlignRight); + return wid; + } + else + { + QWidget *widget = new QWidget(parent); + QHBoxLayout *layout = new QHBoxLayout(widget); - return widget; + layout->addWidget(wid); + layout->addWidget(new QLabel(str, parent)); + + return widget; + + } } Conf::Conf(QObject *parent) : QObject(parent) @@ -70,23 +79,27 @@ void Conf::populateOptionsMenu(QMenu *menu, QWidget *parent) QHBoxLayout *volLayout = new QHBoxLayout(volWidget); QSlider *volSlider = new QSlider(parent); QCheckBox *nextBox = new QCheckBox(parent); + Icon *volUp = new Icon(Icon::VOL_UP, parent); + Icon *volDown = new Icon(Icon::VOL_DOWN, parent); + volUp->setSlider(volSlider); + volDown->setSlider(volSlider); volSlider->setMinimum(0); volSlider->setMaximum(100); volSlider->setValue(getVolume()); volSlider->setOrientation(Qt::Horizontal); - volLayout->addWidget(new QLabel("-")); + volLayout->addWidget(volDown); volLayout->addWidget(volSlider); - volLayout->addWidget(new QLabel("+")); - nextBox->setText(""); + volLayout->addWidget(volUp); + nextBox->setText(tr("Auto play next file in directory")); nextBox->setChecked(nextFile()); connect(volSlider, SIGNAL(valueChanged(int)), this, SLOT(setVolume(int))); connect(volSlider, SIGNAL(valueChanged(int)), this, SIGNAL(volume(int))); connect(nextBox, SIGNAL(clicked(bool)), this, SLOT(setNextFile(bool))); - menu->addAction(new MenuItem(tr("Volume"), volWidget, this)); - menu->addAction(new MenuItem(tr("Auto play next file in directory"), nextBox, this)); + menu->addAction(new MenuItem("", volWidget, this)); + menu->addAction(new MenuItem("", nextBox, this)); } void Conf::setLastPath(const QString &path) diff --git a/io/conf.h b/io/conf.h index 97e6ba9..1d57833 100644 --- a/io/conf.h +++ b/io/conf.h @@ -14,6 +14,7 @@ #include #include "idm.h" +#include "../gui/icon.h" class MenuItem : public QWidgetAction { diff --git a/main.cpp b/main.cpp index a8df9ea..77ceec9 100644 --- a/main.cpp +++ b/main.cpp @@ -8,6 +8,7 @@ int main(int argc, char *argv[]) QApplication app(argc, argv); Ui win(app.arguments()); + app.setQuitOnLastWindowClosed(false); win.show(); return app.exec(); diff --git a/png/menu.png b/png/menu.png new file mode 100644 index 0000000..25d3bac Binary files /dev/null and b/png/menu.png differ diff --git a/png/next.png b/png/next.png new file mode 100644 index 0000000..d78a45d Binary files /dev/null and b/png/next.png differ diff --git a/png/open.png b/png/open.png new file mode 100644 index 0000000..4aa449b Binary files /dev/null and b/png/open.png differ diff --git a/png/pause.png b/png/pause.png new file mode 100644 index 0000000..403bf06 Binary files /dev/null and b/png/pause.png differ diff --git a/png/play.png b/png/play.png new file mode 100644 index 0000000..1a9b4e2 Binary files /dev/null and b/png/play.png differ diff --git a/png/prev.png b/png/prev.png new file mode 100644 index 0000000..f6247d1 Binary files /dev/null and b/png/prev.png differ diff --git a/png/restore.png b/png/restore.png new file mode 100644 index 0000000..912154b Binary files /dev/null and b/png/restore.png differ diff --git a/png/stop.png b/png/stop.png new file mode 100644 index 0000000..39e1498 Binary files /dev/null and b/png/stop.png differ diff --git a/png/volume_down.png b/png/volume_down.png new file mode 100644 index 0000000..27b8b41 Binary files /dev/null and b/png/volume_down.png differ diff --git a/png/volume_up.png b/png/volume_up.png new file mode 100644 index 0000000..e74cb61 Binary files /dev/null and b/png/volume_up.png differ diff --git a/svg/menu.svg b/svg/menu.svg index f435b85..cd161c4 100644 --- a/svg/menu.svg +++ b/svg/menu.svg @@ -1,12 +1,12 @@ - - - - + + + + - - + + \ No newline at end of file diff --git a/svg/next.svg b/svg/next.svg new file mode 100644 index 0000000..d898ca7 --- /dev/null +++ b/svg/next.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/svg/open.svg b/svg/open.svg index 9406a3a..d1d445a 100644 --- a/svg/open.svg +++ b/svg/open.svg @@ -1,10 +1,11 @@ - - - + + + - - + + + \ No newline at end of file diff --git a/svg/pause.svg b/svg/pause.svg index e7b21b1..354d21f 100644 --- a/svg/pause.svg +++ b/svg/pause.svg @@ -1,11 +1,13 @@ - - - - + + + + - - + + + + \ No newline at end of file diff --git a/svg/play.svg b/svg/play.svg index bbdf169..4c4c1c0 100644 --- a/svg/play.svg +++ b/svg/play.svg @@ -1,10 +1,11 @@ - - - + + + - - + + + \ No newline at end of file diff --git a/svg/prev.svg b/svg/prev.svg new file mode 100644 index 0000000..98433bd --- /dev/null +++ b/svg/prev.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/svg/restore.svg b/svg/restore.svg new file mode 100644 index 0000000..952425f --- /dev/null +++ b/svg/restore.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/svg/stop.svg b/svg/stop.svg new file mode 100644 index 0000000..9c1db42 --- /dev/null +++ b/svg/stop.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/svg/volume_down.svg b/svg/volume_down.svg new file mode 100644 index 0000000..a5bd99c --- /dev/null +++ b/svg/volume_down.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/svg/volume_up.svg b/svg/volume_up.svg new file mode 100644 index 0000000..ebc934f --- /dev/null +++ b/svg/volume_up.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file