当前位置: 首页 > news >正文

QT6引入QMediaPlaylist类

前言

##### 大家都找到实习了吗,我boss投了470份,目前还是0面😭####

1.QMediaPlaylist是做什么的

在QT5中QMediaPlayer和QMediaPlaylist都被用来管理音频模块,QMediaPlayer负责音频解析,播放暂停,音量调节等功能,而QMediaPlaylist负责多个音频的播放管理,如单曲循环,随机播放,顺序播放,播放相关的槽函数处理

2.QT6的音频模块

QT6中对音频模块进行了大调整,QMediaPlayer解析歌曲改为信号槽式,本身功能也被拆分为QMediaPlayer,QAudioOutput两部分;并将QMediaPlaylist删除,如果仍要使用这个模块,则需要自己搓一个,于是也就有了本文

3.MediaPlaylist

这是我和ai仿照QMediaPlaylist制作的类,用以实现其常用功能,其接口与QT5的QMediaPlaylist保持一致,并在我的项目中引入了这个模块,成功完成任务

// MediaPlaylist.h
#ifndef MEDIAPLAYLIST_H
#define MEDIAPLAYLIST_H#include <QObject>
#include <QList>
#include <QUrl>
#include <QMediaPlayer>class MediaPlaylist : public QObject
{Q_OBJECT
public:enum PlaybackMode {CurrentItemOnce,CurrentItemInLoop,Sequential,Loop,Random};Q_ENUM(PlaybackMode)void bindToPlayer(QMediaPlayer *player);void unbindPlayer();bool isBoundToPlayer() const;explicit MediaPlaylist(QObject *parent = nullptr);int currentIndex() const;QUrl currentMedia() const;int nextIndex(int steps = 1) const;int previousIndex(int steps = 1) const;void addMedia(const QUrl &content);void addMedia(const QList<QUrl> &items);void insertMedia(int index, const QUrl &content);void insertMedia(int index, const QList<QUrl> &items);bool removeMedia(int pos);bool removeMedia(int start, int end);void clear();bool isEmpty() const;int mediaCount() const;QUrl media(int index) const;PlaybackMode playbackMode() const;void setPlaybackMode(PlaybackMode mode);void shuffle();void setCurrentIndex(int index);void next();void previous();void connectToPlayer(QMediaPlayer *player);signals:void currentIndexChanged(int index);void currentMediaChanged(const QUrl &content);void playbackModeChanged(PlaybackMode mode);void mediaAboutToBeInserted(int start, int end);void mediaInserted(int start, int end);void mediaAboutToBeRemoved(int start, int end);void mediaRemoved(int start, int end);void mediaChanged(int start, int end);
private slots:void handlePlayerStateChanged(QMediaPlayer::PlaybackState state);void handleMediaFinished();private:QList<QUrl> m_mediaList;int m_currentIndex = -1;PlaybackMode m_playbackMode = Sequential;QMediaPlayer *m_player = nullptr;int randomIndex() const;void updatePlayerSource();QMediaPlayer *m_boundPlayer = nullptr;bool m_autoPlayOnBind = true; bool m_autoPlayNext = false; 
};#endif // MEDIAPLAYLIST_H
// MediaPlaylist.cpp
#include "MediaPlaylist.h"
#include <QRandomGenerator>MediaPlaylist::MediaPlaylist(QObject *parent) : QObject(parent)
{
}int MediaPlaylist::currentIndex() const
{return m_currentIndex;
}QUrl MediaPlaylist::currentMedia() const
{if (m_currentIndex >= 0 && m_currentIndex < m_mediaList.size()) {return m_mediaList.at(m_currentIndex);}return QUrl();
}int MediaPlaylist::nextIndex(int steps) const
{if (m_mediaList.isEmpty()) {return -1;}switch (m_playbackMode) {case CurrentItemOnce:case CurrentItemInLoop:return m_currentIndex;case Sequential:return (m_currentIndex + steps) % m_mediaList.size();case Loop:return (m_currentIndex + steps) % m_mediaList.size();case Random:return randomIndex();}return -1;
}int MediaPlaylist::previousIndex(int steps) const
{if (m_mediaList.isEmpty()) {return -1;}switch (m_playbackMode) {case CurrentItemOnce:case CurrentItemInLoop:return m_currentIndex;case Sequential:case Loop: {int index = m_currentIndex - steps;while (index < 0) {index += m_mediaList.size();}return index;}case Random:return randomIndex();}return -1;
}void MediaPlaylist::addMedia(const QUrl &content)
{insertMedia(m_mediaList.size(), content);
}void MediaPlaylist::addMedia(const QList<QUrl> &items)
{insertMedia(m_mediaList.size(), items);
}void MediaPlaylist::insertMedia(int index, const QUrl &content)
{insertMedia(index, QList<QUrl>() << content);
}void MediaPlaylist::insertMedia(int index, const QList<QUrl> &items)
{if (items.isEmpty()) {return;}int start = qBound(0, index, m_mediaList.size());int end = start + items.size() - 1;emit mediaAboutToBeInserted(start, end);for (int i = 0; i < items.size(); ++i) {m_mediaList.insert(start + i, items.at(i));}emit mediaInserted(start, end);if (m_currentIndex >= start) {m_currentIndex += items.size();}if (m_mediaList.size() == items.size()) {setCurrentIndex(0);}
}bool MediaPlaylist::removeMedia(int pos)
{return removeMedia(pos, pos);
}bool MediaPlaylist::removeMedia(int start, int end)
{if (start < 0 || end >= m_mediaList.size() || start > end) {return false;}emit mediaAboutToBeRemoved(start, end);for (int i = end; i >= start; --i) {m_mediaList.removeAt(i);}emit mediaRemoved(start, end);if (m_currentIndex >= start && m_currentIndex <= end) {if (m_mediaList.isEmpty()) {setCurrentIndex(-1);} else {setCurrentIndex(qMin(start, m_mediaList.size() - 1));}} else if (m_currentIndex > end) {m_currentIndex -= (end - start + 1);}return true;
}void MediaPlaylist::clear()
{if (m_mediaList.isEmpty()) {return;}removeMedia(0, m_mediaList.size() - 1);
}bool MediaPlaylist::isEmpty() const
{return m_mediaList.isEmpty();
}int MediaPlaylist::mediaCount() const
{return m_mediaList.size();
}QUrl MediaPlaylist::media(int index) const
{if (index >= 0 && index < m_mediaList.size()) {return m_mediaList.at(index);}return QUrl();
}MediaPlaylist::PlaybackMode MediaPlaylist::playbackMode() const
{return m_playbackMode;
}void MediaPlaylist::setPlaybackMode(PlaybackMode mode)
{if (m_playbackMode != mode) {m_playbackMode = mode;emit playbackModeChanged(mode);}
}void MediaPlaylist::shuffle()
{if (m_mediaList.size() < 2) {return;}int current = m_currentIndex;QList<QUrl> shuffled;while (!m_mediaList.isEmpty()) {int index = QRandomGenerator::global()->bounded(m_mediaList.size());shuffled.append(m_mediaList.takeAt(index));}m_mediaList = shuffled;m_currentIndex = m_mediaList.indexOf(currentMedia());emit mediaChanged(0, m_mediaList.size() - 1);
}void MediaPlaylist::setCurrentIndex(int index)
{if (index == m_currentIndex) {return;}if (index >= m_mediaList.size()) {index = -1;}int oldIndex = m_currentIndex;m_currentIndex = index;if (oldIndex != m_currentIndex) {emit currentIndexChanged(m_currentIndex);emit currentMediaChanged(currentMedia());updatePlayerSource();}
}void MediaPlaylist::next()
{if (m_mediaList.isEmpty()) {return;}setCurrentIndex(nextIndex());m_boundPlayer->play();
}void MediaPlaylist::previous()
{if (m_mediaList.isEmpty()) {return;}setCurrentIndex(previousIndex());m_boundPlayer->play();
}void MediaPlaylist::connectToPlayer(QMediaPlayer *player)
{bindToPlayer(player);//if (m_player) {disconnect(m_player, &QMediaPlayer::playbackStateChanged,this, &MediaPlaylist::handlePlayerStateChanged);}m_player = player;if (m_player) {connect(m_player, &QMediaPlayer::playbackStateChanged,this, &MediaPlaylist::handlePlayerStateChanged);}//
}void MediaPlaylist::handlePlayerStateChanged(QMediaPlayer::PlaybackState state)
{if (!m_boundPlayer || m_mediaList.isEmpty()) {return;}// 仅在播放停止且不是用户主动停止时处理if (state == QMediaPlayer::StoppedState &&m_boundPlayer->mediaStatus() == QMediaPlayer::EndOfMedia) {switch (m_playbackMode) {case CurrentItemOnce:// 单曲播放一次,不自动继续break;case CurrentItemInLoop:// 单曲循环m_boundPlayer->setPosition(0);if (m_autoPlayNext) {m_boundPlayer->play();}break;case Sequential:case Loop:// 顺序播放或列表循环if (m_autoPlayNext) {next();}break;case Random:// 随机播放if (m_autoPlayNext) {setCurrentIndex(randomIndex());}break;}}// 处理播放错误情况else if (state == QMediaPlayer::StoppedState &&m_boundPlayer->error() != QMediaPlayer::NoError) {qWarning() << "Playback error:" << m_boundPlayer->errorString();// emit playbackErrorOccurred(m_boundPlayer->error(), m_boundPlayer->errorString());}
}int MediaPlaylist::randomIndex() const
{if (m_mediaList.isEmpty()) {return -1;}if (m_mediaList.size() == 1) {return 0;}int index;do {index = QRandomGenerator::global()->bounded(m_mediaList.size());} while (index == m_currentIndex && m_mediaList.size() > 1);return index;
}void MediaPlaylist::updatePlayerSource()
{if (!m_boundPlayer || m_currentIndex < 0 || m_currentIndex >= m_mediaList.size()) {return;}m_boundPlayer->setSource(m_mediaList.at(m_currentIndex));
}
void MediaPlaylist::bindToPlayer(QMediaPlayer *player)
{if (m_boundPlayer == player) {return;}unbindPlayer(); // 先解绑现有的if (player) {m_boundPlayer = player;// 连接播放器状态信号connect(player, &QMediaPlayer::playbackStateChanged,this, &MediaPlaylist::handlePlayerStateChanged);// 连接媒体状态信号(用于检测播放结束)connect(player, &QMediaPlayer::mediaStatusChanged,this, [this](QMediaPlayer::MediaStatus status) {if (status == QMediaPlayer::EndOfMedia) {this->handleMediaFinished();}});// 连接错误信号connect(player, &QMediaPlayer::errorOccurred,this, [this]() {qWarning() << "Player error:" << m_boundPlayer->errorString();});// 自动设置第一个媒体并播放(如果列表不为空)if (!m_mediaList.isEmpty() && m_currentIndex < 0) {setCurrentIndex(0);}// 如果已经有当前选中的媒体,更新播放器源if (m_currentIndex >= 0 && m_currentIndex < m_mediaList.size()) {updatePlayerSource();// 如果设置了自动播放且播放器当前是停止状态,则开始播放if (m_autoPlayOnBind && m_boundPlayer->playbackState() == QMediaPlayer::StoppedState) {m_boundPlayer->play();}}}
}void MediaPlaylist::unbindPlayer()
{if (m_boundPlayer) {disconnect(m_boundPlayer, nullptr, this, nullptr);m_boundPlayer = nullptr;}
}
bool MediaPlaylist::isBoundToPlayer() const
{return m_boundPlayer != nullptr;
}void MediaPlaylist::handleMediaFinished()
{if (!m_boundPlayer) return;switch (m_playbackMode) {case CurrentItemInLoop:m_boundPlayer->setPosition(0);m_boundPlayer->play();break;case CurrentItemOnce:// 不做任何操作,保持停止状态break;default:// 其他模式自动播放下一个next();break;}
}

相关文章:

  • redis核心知识点
  • LeetCode Hot100 (贪心)
  • C# 面向对象特性
  • linux nm/objdump/readelf/addr2line命令详解
  • 【优比】基于STM32的紧急求助定位导盲仪系统
  • 【深度学习-Day 20】PyTorch入门:核心数据结构张量(Tensor)详解与操作
  • 【教学类-36-10】20250531蝴蝶图案描边,最适合大小(一页1图1图、2图图案不同、2图图案相同对称)
  • 【计算机CPU架构】ARM架构简介
  • YOLOv10改进|爆改模型|涨点|在颈部网络添加结合部分卷积PConv和SDI融合方法的PSDI特征融合层(附代码+修改教程)
  • 如何打包conda环境从一台电脑到另外一台电脑
  • C语言 — 动态内存管理
  • 鸿蒙HarmonyOS (React Native)的实战教程
  • 【NLP 78、手搓Transformer模型结构】
  • leetcode刷题日记——二叉树的右视图
  • 使用Python绘制节日祝福——以端午节和儿童节为例
  • 嵌入式编译工具链熟悉与游戏移植
  • Fragment事务commit与commitNow区别
  • atapi!IdeReadWrite函数分析中.txt
  • LeeCode 98. 验证二叉搜索树
  • LearnOpenGL-笔记-其十二
  • 做数学题目在哪个网站好/seo的推广技巧
  • 电子商务网站制作步骤/百度seo优化方法
  • 深圳网站建设10强/新浪体育最新消息
  • 域名备案网站服务内容/seo网站优化排名
  • 深圳外贸网站建设企业/sem扫描电镜是测什么的
  • 网站开发的工作需要什么材料/seo是干什么的