Skip to content

Commit

Permalink
Merge branch 'development' into development
Browse files Browse the repository at this point in the history
  • Loading branch information
jmckisson authored Apr 29, 2024
2 parents ab4edd4 + f56291b commit e69f714
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 15 deletions.
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ set(mudlet_SRCS
TMap.cpp
TMapLabel.cpp
TMedia.cpp
TMediaPlaylist.cpp
TMxpElementDefinitionHandler.cpp
TMxpElementRegistry.cpp
TMxpFormattingTagsHandler.cpp
Expand Down Expand Up @@ -303,6 +304,7 @@ set(mudlet_HDRS
TMapLabel.h
TMatchState.h
TMedia.h
TMediaPlaylist.h
TMxpBRTagHandler.h
TMxpClient.h
TMxpColorTagHandler.h
Expand Down
78 changes: 63 additions & 15 deletions src/TMedia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@
#include <QFileInfo>
#include <QJsonDocument>
#include <QJsonObject>
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <QMediaPlaylist>
#endif
#include <QNetworkDiskCache>
#include <QRandomGenerator>
#include <QStandardPaths>
Expand Down Expand Up @@ -834,6 +831,33 @@ QList<TMediaPlayer> TMedia::getMediaPlayerList(TMediaData& mediaData)

void TMedia::connectMediaPlayer(TMediaPlayer& player)
{
disconnect(player.getMediaPlayer(), &QMediaPlayer::mediaStatusChanged, nullptr, nullptr);
connect(player.getMediaPlayer(), &QMediaPlayer::mediaStatusChanged, this, [=](QMediaPlayer::MediaStatus mediaStatus) {
if (mediaStatus == QMediaPlayer::EndOfMedia) {
if (player.playlist() && !player.playlist()->isEmpty()) {
QUrl nextMedia = player.playlist()->next();

if (!nextMedia.isEmpty()) {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
player.getMediaPlayer()->setMedia(nextMedia);
#else
player.getMediaPlayer()->setSource(nextMedia);
#endif
player.getMediaPlayer()->play();
} else if (player.playlist()->playbackMode() == TMediaPlaylist::Loop) {
// Start from the beginning if the playlist is set to loop
player.playlist()->setCurrentIndex(0);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
player.getMediaPlayer()->setMedia(player.playlist()->currentMedia());
#else
player.getMediaPlayer()->setSource(player.playlist()->currentMedia());
#endif
player.getMediaPlayer()->play();
}
}
}
});

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
disconnect(player.getMediaPlayer(), &QMediaPlayer::stateChanged, nullptr, nullptr);
connect(player.getMediaPlayer(), &QMediaPlayer::stateChanged, this,
Expand Down Expand Up @@ -1113,7 +1137,6 @@ void TMedia::matchMediaKeyAndStopMediaVariants(TMediaData& mediaData, const QStr

void TMedia::play(TMediaData& mediaData)
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (mediaData.getMediaProtocol() == TMediaData::MediaProtocolMSP && !mpHost->mEnableMSP) {
return;
}
Expand Down Expand Up @@ -1149,11 +1172,17 @@ void TMedia::play(TMediaData& mediaData)
return;
}

auto playlist = !sameMusicIsPlaying ? new QMediaPlaylist : (pPlayer.getMediaPlayer()->playlist() != nullptr ? pPlayer.getMediaPlayer()->playlist() : new QMediaPlaylist);
TMediaPlaylist* playlist = pPlayer.playlist();

if (!sameMusicIsPlaying) {
playlist->clear();
playlist->setPlaybackMode(TMediaPlaylist::Sequential);
}

QString absolutePathFileName;

if (mediaData.getMediaLoops() == TMediaData::MediaLoopsDefault) { // Play once
playlist->setPlaybackMode(QMediaPlaylist::Sequential);
playlist->setPlaybackMode(TMediaPlaylist::Sequential);

if (sameMusicIsPlaying) {
if (mediaData.getMediaContinue() == TMediaData::MediaContinueRestart) {
Expand Down Expand Up @@ -1186,10 +1215,14 @@ void TMedia::play(TMediaData& mediaData)
}

const QUrl mediaSource = QUrl::fromLocalFile(absolutePathFileName);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
pPlayer.getMediaPlayer()->setMedia(mediaSource);
#else
pPlayer.getMediaPlayer()->setSource(mediaSource);
#endif
} else {
if (mediaData.getMediaLoops() == TMediaData::MediaLoopsRepeat) { // Repeat indefinitely
playlist->setPlaybackMode(QMediaPlaylist::Loop);
playlist->setPlaybackMode(TMediaPlaylist::Loop);

if (sameMusicIsPlaying) {
if (mediaData.getMediaContinue() == TMediaData::MediaContinueRestart) {
Expand Down Expand Up @@ -1219,7 +1252,7 @@ void TMedia::play(TMediaData& mediaData)

playlist->addMedia(QUrl::fromLocalFile(absolutePathFileName));
} else {
playlist->setPlaybackMode(QMediaPlaylist::Sequential);
playlist->setPlaybackMode(TMediaPlaylist::Sequential);

if (sameMusicIsPlaying) {
if (mediaData.getMediaContinue() == TMediaData::MediaContinueRestart) {
Expand Down Expand Up @@ -1262,38 +1295,53 @@ void TMedia::play(TMediaData& mediaData)
return;
}

playlist->setCurrentIndex(1);
pPlayer.getMediaPlayer()->setPlaylist(playlist);
playlist->setCurrentIndex(0);
pPlayer.setPlaylist(playlist);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
pPlayer.getMediaPlayer()->setMedia(playlist->currentMedia());
#else
pPlayer.getMediaPlayer()->setSource(playlist->currentMedia());
#endif
}

// Set volume, start and play media
pPlayer.getMediaPlayer()->setVolume(mediaData.getMediaFadeIn() != TMediaData::MediaFadeNotSet ? 1 : mediaData.getMediaVolume());
pPlayer.setVolume(mediaData.getMediaFadeIn() != TMediaData::MediaFadeNotSet ? 1 : mediaData.getMediaVolume());
pPlayer.getMediaPlayer()->setPosition(mediaData.getMediaStart());

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (mediaData.getMediaFadeIn() != TMediaData::MediaFadeNotSet || mediaData.getMediaFadeOut() != TMediaData::MediaFadeNotSet) {
pPlayer.getMediaPlayer()->setNotifyInterval(50); // Smoother volume changes with the tighter interval (default = 1000).
}
#endif

// Set whether or not we should be muted
switch (mediaData.getMediaProtocol()) {
case TMediaData::MediaProtocolAPI:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
pPlayer.getMediaPlayer()->setMuted(mudlet::self()->muteAPI());
#else
pPlayer.getMediaPlayer()->audioOutput()->setMuted(mudlet::self()->muteAPI());
#endif
break;
case TMediaData::MediaProtocolGMCP:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
pPlayer.getMediaPlayer()->setMuted(mudlet::self()->muteMCMP());
#else
pPlayer.getMediaPlayer()->audioOutput()->setMuted(mudlet::self()->muteMCMP());
#endif
break;
case TMediaData::MediaProtocolMSP:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
pPlayer.getMediaPlayer()->setMuted(mudlet::self()->muteMSP());
#else
pPlayer.getMediaPlayer()->audioOutput()->setMuted(mudlet::self()->muteMSP());
#endif
break;
}

pPlayer.getMediaPlayer()->play();

updateMediaPlayerList(pPlayer);
#else
Q_UNUSED(mediaData)
#warning QMediaPlaylist was removed in Qt6 - it has not been reimplemented yet!
#endif
}

// Documentation: https://wiki.mudlet.org/w/Manual:Scripting#type:_sound
Expand Down
12 changes: 12 additions & 0 deletions src/TMedia.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "TEvent.h"
#include "mudlet.h"
#include "TMediaData.h"
#include "TMediaPlaylist.h"

#include "pre_guard.h"
#include <QAudioOutput>
Expand All @@ -50,6 +51,7 @@ class TMediaPlayer
TMediaPlayer(Host* pHost, TMediaData& mediaData)
: mpHost(pHost)
, mMediaData(mediaData)
, mPlaylist(new TMediaPlaylist())
, mMediaPlayer(new QMediaPlayer(pHost))
, initialized(true)
{
Expand Down Expand Up @@ -77,11 +79,21 @@ class TMediaPlayer
return mMediaPlayer->audioOutput()->setVolume(volume / 100.0f);
#endif
}
TMediaPlaylist* playlist() const {
return mPlaylist;
}
void setPlaylist(TMediaPlaylist* playlist) {
if (mPlaylist != playlist) {
delete mPlaylist;
mPlaylist = playlist;
}
}

private:
QPointer<Host> mpHost;
TMediaData mMediaData;
QMediaPlayer* mMediaPlayer = nullptr;
TMediaPlaylist* mPlaylist;
bool initialized = false;
};

Expand Down
125 changes: 125 additions & 0 deletions src/TMediaPlaylist.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/***************************************************************************
* Copyright (C) 2024 by Mike Conley - [email protected] *
* *
* 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. *
* *
* This program 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 this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#include "TMediaPlaylist.h"

#include "pre_guard.h"
#include <QRandomGenerator>
#include "post_guard.h"

TMediaPlaylist::TMediaPlaylist()
: mCurrentIndex(0), mPlaybackMode(Sequential) {}

TMediaPlaylist::~TMediaPlaylist() {}

void TMediaPlaylist::addMedia(const QUrl &url) {
mMediaList.append(url);
}

void TMediaPlaylist::removeMedia(int startIndex, int endIndex) {
if (endIndex >= startIndex && startIndex >= 0 && endIndex < mMediaList.size()) {
for (int i = endIndex; i >= startIndex; --i) {
mMediaList.removeAt(i);
}
}
}

void TMediaPlaylist::clear() {
mMediaList.clear();
}

int TMediaPlaylist::mediaCount() const {
return mMediaList.count();
}

bool TMediaPlaylist::isEmpty() const {
return mMediaList.isEmpty();
}

void TMediaPlaylist::setPlaybackMode(PlaybackMode mode) {
mPlaybackMode = mode;
}

TMediaPlaylist::PlaybackMode TMediaPlaylist::playbackMode() const {
return mPlaybackMode;
}

QUrl TMediaPlaylist::currentMedia() const {
if (!mMediaList.isEmpty() && mCurrentIndex >= 0 && mCurrentIndex < mMediaList.size()) {
return mMediaList.at(mCurrentIndex);
}
return QUrl();
}

bool TMediaPlaylist::setCurrentIndex(int index) {
if (index >= 0 && index < mMediaList.size()) {
mCurrentIndex = index;
return true;
}
return false;
}

int TMediaPlaylist::currentIndex() const {
return mCurrentIndex;
}

int TMediaPlaylist::nextIndex() const {
if (mPlaybackMode == Loop && (mCurrentIndex + 1 == mMediaList.size())) {
return 0;
} else if (mPlaybackMode == Random) {
return QRandomGenerator::global()->bounded(mMediaList.size());
} else if (mCurrentIndex + 1 < mMediaList.size()) {
return mCurrentIndex + 1;
}
return -1; // No valid next index if out of range
}

QUrl TMediaPlaylist::next() {
if (mMediaList.isEmpty()) {
return QUrl();
}

if (mPlaybackMode == Loop && (mCurrentIndex + 1 == mMediaList.size())) {
mCurrentIndex = 0;
} else if (mPlaybackMode == Random) {
mCurrentIndex = QRandomGenerator::global()->bounded(mMediaList.size());
} else {
mCurrentIndex++;
}

if (mCurrentIndex < mMediaList.size()) {
return mMediaList.at(mCurrentIndex);
}

return QUrl();
}

QUrl TMediaPlaylist::previous() {
if (mPlaybackMode == Loop && mCurrentIndex == 0) {
mCurrentIndex = mMediaList.size() - 1;
} else {
mCurrentIndex--;
}

if (mCurrentIndex >= 0) {
return mMediaList.at(mCurrentIndex);
}

return QUrl();
}
61 changes: 61 additions & 0 deletions src/TMediaPlaylist.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#ifndef TMEDIAPLAYLIST_H
#define TMEDIAPLAYLIST_H

/***************************************************************************
* Copyright (C) 2024 by Mike Conley - [email protected] *
* *
* 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. *
* *
* This program 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 this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#include "pre_guard.h"
#include <QList>
#include <QUrl>
#include "post_guard.h"

class TMediaPlaylist
{
public:
enum PlaybackMode {
Sequential,
Loop,
Random
};

TMediaPlaylist();
~TMediaPlaylist();

void addMedia(const QUrl &url);
void removeMedia(int startIndex, int endIndex);
void clear();
int mediaCount() const;
bool isEmpty() const;
void setPlaybackMode(PlaybackMode mode);
PlaybackMode playbackMode() const;

QUrl currentMedia() const;
bool setCurrentIndex(int index);
int currentIndex() const;
int nextIndex() const;
QUrl next();
QUrl previous();

private:
QList<QUrl> mMediaList;
int mCurrentIndex;
PlaybackMode mPlaybackMode;
};

#endif // TMEDIAPLAYLIST_H
Loading

0 comments on commit e69f714

Please sign in to comment.