#include "SimplePlayerWindow.h" #include #include #include #include SimplePlayerWindow::SimplePlayerWindow(QWidget *parent) : QMainWindow(parent) , m_openGLVideoRenderer(nullptr) { qDebug() << "Initializing SimplePlayerWindow..."; try { // 创建播放器适配器 m_playerAdapter = PlayerAdapterFactory::create(this); if (!m_playerAdapter) { throw std::runtime_error("Failed to create PlayerAdapter"); } qDebug() << "PlayerAdapter created successfully"; setupUI(); connectSignals(); updateUI(); // 设置OpenGL渲染器 if (m_openGLVideoRenderer && m_playerAdapter) { qDebug() << "Setting OpenGL video renderer..."; m_playerAdapter->setOpenGLVideoRenderer(m_openGLVideoRenderer); } else { qWarning() << "No video renderer available"; } setWindowTitle("Simple Media Player (OpenGL)"); resize(800, 600); qDebug() << "SimplePlayerWindow initialized successfully"; } catch (const std::exception& e) { qCritical() << "Exception during SimplePlayerWindow initialization:" << e.what(); QMessageBox::critical(this, "Initialization Error", QString("Failed to initialize player window: %1").arg(e.what())); throw; } catch (...) { qCritical() << "Unknown exception during SimplePlayerWindow initialization"; QMessageBox::critical(this, "Initialization Error", "Unknown error during player window initialization"); throw; } } SimplePlayerWindow::~SimplePlayerWindow() { if (m_playerAdapter) { m_playerAdapter->stop(); } } void SimplePlayerWindow::openFile() { qDebug() << "Opening file dialog..."; QString filename = QFileDialog::getOpenFileName( this, "Open Media File", "", "Media Files (*.mp4 *.avi *.mkv *.mov *.wmv *.flv *.webm *.mp3 *.wav *.aac *.flac *.ogg);;All Files (*.*)" ); if (!filename.isEmpty()) { qDebug() << "Selected file:" << filename; // 检查文件是否存在 QFileInfo fileInfo(filename); if (!fileInfo.exists()) { QMessageBox::critical(this, "Error", "File does not exist: " + filename); return; } if (!fileInfo.isReadable()) { QMessageBox::critical(this, "Error", "File is not readable: " + filename); return; } // 显示加载状态 m_stateLabel->setText("State: Loading..."); m_fileLabel->setText("Loading: " + fileInfo.fileName()); // 尝试打开文件 av::ErrorCode result = m_playerAdapter->openFile(filename); if (result != av::ErrorCode::SUCCESS) { QString errorMsg = "Failed to open file: " + filename; // 根据错误代码提供更具体的错误信息 switch (result) { case av::ErrorCode::FILE_OPEN_FAILED: errorMsg = "Could not open file. Please check if the file is corrupted or in an unsupported format."; break; case av::ErrorCode::CODEC_OPEN_FAILED: errorMsg = "Could not initialize codecs. The file format may not be supported."; break; case av::ErrorCode::NOT_INITIALIZED: errorMsg = "Player not properly initialized. Please restart the application."; break; case av::ErrorCode::INVALID_STATE: errorMsg = "Player is in an invalid state. Please try again."; break; default: errorMsg = "Unknown error occurred while opening the file."; break; } QMessageBox::critical(this, "Error", errorMsg); qCritical() << "Failed to open file:" << filename << "Error code:" << static_cast(result); // 重置状态 m_stateLabel->setText("State: Idle"); m_fileLabel->setText("No file loaded"); } else { m_fileLabel->setText("File: " + fileInfo.fileName()); qDebug() << "File opened successfully:" << filename; } } else { qDebug() << "No file selected"; } } void SimplePlayerWindow::playPause() { if (!m_playerAdapter) { qWarning() << "PlayerAdapter is null"; return; } PlayerState state = m_playerAdapter->getState(); qDebug() << "Current player state:" << static_cast(state); if (state == PlayerState::Playing) { qDebug() << "Pausing playback..."; av::ErrorCode result = m_playerAdapter->pause(); if (result != av::ErrorCode::SUCCESS) { qWarning() << "Failed to pause playback, error code:" << static_cast(result); } } else if (state == PlayerState::Paused || state == PlayerState::Stopped) { qDebug() << "Starting playback..."; av::ErrorCode result = m_playerAdapter->play(); if (result != av::ErrorCode::SUCCESS) { qWarning() << "Failed to start playback, error code:" << static_cast(result); QMessageBox::warning(this, "Playback Error", "Failed to start playback. Please check if a file is loaded."); } } else if (state == PlayerState::Idle) { QMessageBox::information(this, "Information", "Please open a media file first."); } else { qDebug() << "Player is in state:" << static_cast(state) << "- cannot play/pause"; } } void SimplePlayerWindow::stop() { m_playerAdapter->stop(); } void SimplePlayerWindow::seek() { if (m_seeking) { qint64 duration = m_playerAdapter->getDuration(); qint64 position = (duration * m_positionSlider->value()) / 1000; m_playerAdapter->seek(position); } } void SimplePlayerWindow::setVolume() { double volume = m_volumeSlider->value() / 100.0; m_playerAdapter->setVolume(volume); m_volumeLabel->setText(QString("Volume: %1%").arg(m_volumeSlider->value())); } void SimplePlayerWindow::toggleMute() { bool muted = m_playerAdapter->isMuted(); m_playerAdapter->setMuted(!muted); } void SimplePlayerWindow::setPlaybackSpeed() { double speed = m_speedSlider->value() / 100.0; m_playerAdapter->setPlaybackSpeed(speed); m_speedLabel->setText(QString("Speed: %1x").arg(speed, 0, 'f', 2)); } void SimplePlayerWindow::onStateChanged(PlayerState state) { QString stateText; switch (state) { case PlayerState::Idle: stateText = "Idle"; break; // case PlayerState::Loading: // stateText = "Loading"; // break; case PlayerState::Playing: stateText = "Playing"; break; case PlayerState::Paused: stateText = "Paused"; break; case PlayerState::Stopped: stateText = "Stopped"; break; case PlayerState::Error: stateText = "Error"; break; } m_stateLabel->setText("State: " + stateText); updateUI(); } void SimplePlayerWindow::onMediaInfoChanged(const MediaInfo& info) { QString infoText = QString("Duration: %1 | Video: %2x%3 | Audio: %4 Hz") .arg(formatTime(info.duration)) .arg(info.width) .arg(info.height) .arg(info.audioSampleRate); m_infoLabel->setText(infoText); } void SimplePlayerWindow::onPositionChanged(qint64 position) { if (!m_seeking) { qint64 duration = m_playerAdapter->getDuration(); if (duration > 0) { int sliderValue = (position * 1000) / duration; m_positionSlider->setValue(sliderValue); } QString timeText = QString("%1 / %2") .arg(formatTime(position)) .arg(formatTime(duration)); m_timeLabel->setText(timeText); } } void SimplePlayerWindow::onVolumeChanged(double volume) { int volumePercent = static_cast(volume * 100); m_volumeSlider->setValue(volumePercent); m_volumeLabel->setText(QString("Volume: %1%").arg(volumePercent)); } void SimplePlayerWindow::onMutedChanged(bool muted) { m_muteButton->setText(muted ? "Unmute" : "Mute"); } void SimplePlayerWindow::onPlaybackSpeedChanged(double speed) { int speedPercent = static_cast(speed * 100); m_speedSlider->setValue(speedPercent); m_speedLabel->setText(QString("Speed: %1x").arg(speed, 0, 'f', 2)); } void SimplePlayerWindow::onErrorOccurred(const QString& error) { QMessageBox::critical(this, "Player Error", error); qDebug() << "Player error:" << error; } void SimplePlayerWindow::onStatsUpdated(const PlaybackStats& stats) { QString statsText = QString("Packets: %1 | Video Frames: %2 | Audio Frames: %3") .arg(stats.queuedPackets) .arg(stats.queuedVideoFrames) .arg(stats.queuedAudioFrames); m_statsLabel->setText(statsText); } void SimplePlayerWindow::setupUI() { auto* centralWidget = new QWidget(this); setCentralWidget(centralWidget); auto* mainLayout = new QVBoxLayout(centralWidget); // 文件信息 m_fileLabel = new QLabel("No file loaded"); m_stateLabel = new QLabel("State: Idle"); m_infoLabel = new QLabel("Media info will appear here"); mainLayout->addWidget(m_fileLabel); mainLayout->addWidget(m_stateLabel); mainLayout->addWidget(m_infoLabel); // 视频渲染器 - 使用OpenGL渲染器 m_openGLVideoRenderer = new OpenGLVideoRenderer(this); m_openGLVideoRenderer->setMinimumSize(640, 480); m_openGLVideoRenderer->setStyleSheet("border: 1px solid gray;"); mainLayout->addWidget(m_openGLVideoRenderer); // 控制按钮 auto* buttonLayout = new QHBoxLayout(); m_openButton = new QPushButton("Open File"); m_playPauseButton = new QPushButton("Play"); m_stopButton = new QPushButton("Stop"); buttonLayout->addWidget(m_openButton); buttonLayout->addWidget(m_playPauseButton); buttonLayout->addWidget(m_stopButton); buttonLayout->addStretch(); mainLayout->addLayout(buttonLayout); // 进度控制 auto* progressLayout = new QHBoxLayout(); m_timeLabel = new QLabel("00:00 / 00:00"); m_positionSlider = new QSlider(Qt::Horizontal); m_positionSlider->setRange(0, 1000); progressLayout->addWidget(m_timeLabel); progressLayout->addWidget(m_positionSlider); mainLayout->addLayout(progressLayout); // 音量控制 auto* volumeLayout = new QHBoxLayout(); m_volumeLabel = new QLabel("Volume: 100%"); m_volumeSlider = new QSlider(Qt::Horizontal); m_volumeSlider->setRange(0, 100); m_volumeSlider->setValue(100); m_muteButton = new QPushButton("Mute"); volumeLayout->addWidget(m_volumeLabel); volumeLayout->addWidget(m_volumeSlider); volumeLayout->addWidget(m_muteButton); mainLayout->addLayout(volumeLayout); // 播放速度控制 auto* speedLayout = new QHBoxLayout(); m_speedLabel = new QLabel("Speed: 1.00x"); m_speedSlider = new QSlider(Qt::Horizontal); m_speedSlider->setRange(25, 400); // 0.25x to 4.0x m_speedSlider->setValue(100); speedLayout->addWidget(m_speedLabel); speedLayout->addWidget(m_speedSlider); mainLayout->addLayout(speedLayout); // 统计信息 m_statsLabel = new QLabel("Statistics will appear here"); mainLayout->addWidget(m_statsLabel); mainLayout->addStretch(); } void SimplePlayerWindow::connectSignals() { // UI信号 connect(m_openButton, &QPushButton::clicked, this, &SimplePlayerWindow::openFile); connect(m_playPauseButton, &QPushButton::clicked, this, &SimplePlayerWindow::playPause); connect(m_stopButton, &QPushButton::clicked, this, &SimplePlayerWindow::stop); connect(m_positionSlider, &QSlider::sliderPressed, [this]() { m_seeking = true; }); connect(m_positionSlider, &QSlider::sliderReleased, [this]() { seek(); m_seeking = false; }); connect(m_volumeSlider, &QSlider::valueChanged, this, &SimplePlayerWindow::setVolume); connect(m_muteButton, &QPushButton::clicked, this, &SimplePlayerWindow::toggleMute); connect(m_speedSlider, &QSlider::valueChanged, this, &SimplePlayerWindow::setPlaybackSpeed); // 播放器信号 connect(m_playerAdapter.get(), &PlayerAdapter::stateChanged, this, &SimplePlayerWindow::onStateChanged); connect(m_playerAdapter.get(), &PlayerAdapter::mediaInfoChanged, this, &SimplePlayerWindow::onMediaInfoChanged); connect(m_playerAdapter.get(), &PlayerAdapter::positionChanged, this, &SimplePlayerWindow::onPositionChanged); connect(m_playerAdapter.get(), &PlayerAdapter::volumeChanged, this, &SimplePlayerWindow::onVolumeChanged); connect(m_playerAdapter.get(), &PlayerAdapter::mutedChanged, this, &SimplePlayerWindow::onMutedChanged); connect(m_playerAdapter.get(), &PlayerAdapter::playbackSpeedChanged, this, &SimplePlayerWindow::onPlaybackSpeedChanged); connect(m_playerAdapter.get(), &PlayerAdapter::errorOccurred, this, &SimplePlayerWindow::onErrorOccurred); connect(m_playerAdapter.get(), &PlayerAdapter::statsUpdated, this, &SimplePlayerWindow::onStatsUpdated); // 渲染器相关信号 connect(m_playerAdapter.get(), &PlayerAdapter::rendererTypeChanged, this, &SimplePlayerWindow::onRendererTypeChanged); connect(m_playerAdapter.get(), &PlayerAdapter::openGLRendererInitialized, this, &SimplePlayerWindow::onOpenGLRendererInitialized); } void SimplePlayerWindow::updateUI() { PlayerState state = m_playerAdapter->getState(); // 更新播放/暂停按钮 if (state == PlayerState::Playing) { m_playPauseButton->setText("Pause"); } else { m_playPauseButton->setText("Play"); } // 更新按钮可用状态 bool hasMedia = (state != PlayerState::Idle); m_playPauseButton->setEnabled(hasMedia); m_stopButton->setEnabled(hasMedia); m_positionSlider->setEnabled(hasMedia); } void SimplePlayerWindow::onRendererTypeChanged(const QString& type) { qDebug() << "Renderer type changed to:" << type; // 更新窗口标题显示当前渲染器类型 QString title = QString("Simple Media Player (%1)").arg(type); setWindowTitle(title); } void SimplePlayerWindow::onOpenGLRendererInitialized() { qDebug() << "OpenGL renderer initialized successfully"; // 可以在这里添加OpenGL渲染器初始化完成后的逻辑 // 比如显示一些OpenGL特定的信息 } QString SimplePlayerWindow::formatTime(qint64 microseconds) { qint64 seconds = microseconds / 1000000; qint64 minutes = seconds / 60; seconds %= 60; return QString("%1:%2").arg(minutes, 2, 10, QChar('0')).arg(seconds, 2, 10, QChar('0')); }