操作系统接口函数:
mciSendString
例子:
Win32Mci mci("C:\\晨光劍舞_豪情九州.mp3");
mci.Play();
头文件:
cpp
#pragma once
#include <iostream>
#include <string>
namespace ppp
{
namespace win32
{
class Win32Mci final
{
public:
enum class PlayState
{
Closed,
Stopped,
Paused,
Playing,
NotReady,
Open,
Recording,
Parked,
Seeking,
};
public:
explicit Win32Mci(const std::string& path);
~Win32Mci() noexcept;
public:
void Play();
void Stop();
void Pause();
void Resume();
void Seek(int64_t offset, uint32_t loc);
void SetVolume(int volume);
int64_t Position() const;
int64_t Length() const;
PlayState State() const;
void SetRepeat(bool repeat);
void Dispose() noexcept;
private:
std::string Command(const std::string& command) const;
bool PlayCommand(const std::string& command) const;
void Close() noexcept;
private:
std::string path_;
std::string alias_;
bool Repeat_;
};
}
}
源文件:
cpp
#include <windows/ppp/win32/Win32Mci.h>
#include <ppp/stdafx.h>
#include <Windows.h>
#include <mmsystem.h>
#include <string>
#include <stdexcept>
namespace ppp
{
namespace win32
{
Win32Mci::Win32Mci(const std::string& path)
: Repeat_(false)
{
alias_ = "mci-" + std::to_string(ppp::GetTickCount()) + "-" + std::to_string(ppp::RandomNext());
if (!path.empty())
{
path_ = path;
}
else
{
throw std::invalid_argument("Path is empty.");
}
if (!PlayCommand("open \"" + path_ + "\" type mpegvideo alias " + alias_))
{
throw std::runtime_error("Failed to open audio file.");
}
}
Win32Mci::~Win32Mci() noexcept
{
Close();
}
void Win32Mci::Play()
{
if (Repeat_)
{
PlayCommand("play " + alias_ + " repeat");
}
else
{
PlayCommand("play " + alias_);
}
}
void Win32Mci::Stop()
{
PlayCommand("stop " + alias_);
}
void Win32Mci::Pause()
{
PlayCommand("pause " + alias_);
}
void Win32Mci::Resume()
{
PlayCommand("resume " + alias_);
}
void Win32Mci::Seek(int64_t offset, uint32_t loc)
{
int64_t position = 0;
switch (loc)
{
case SEEK_SET:
position = offset;
break;
case SEEK_CUR:
position = Position() + offset;
break;
case SEEK_END:
position = Length() + offset;
break;
default:
throw std::invalid_argument("Invalid seek origin.");
}
PlayCommand("seek " + alias_ + " to " + std::to_string(position));
}
void Win32Mci::SetVolume(int volume)
{
int vol = std::min(volume, 1000);
if (vol < 0)
{
vol = 0;
}
PlayCommand("setaudio " + alias_ + " volume to " + std::to_string(vol));
}
int64_t Win32Mci::Position() const
{
std::string result = Command("status " + alias_ + " position");
return std::stoll(result);
}
int64_t Win32Mci::Length() const
{
std::string result = Command("status " + alias_ + " length");
return std::stoll(result);
}
Win32Mci::PlayState Win32Mci::State() const
{
std::string result = Command("status " + alias_ + " mode");
std::string mode = result.empty() ? "" : result.substr(0, result.find_first_of("\r\n"));
if (mode == "stopped")
{
return PlayState::Stopped;
}
else if (mode == "paused")
{
return PlayState::Paused;
}
else if (mode == "playing")
{
return PlayState::Playing;
}
else if (mode == "not ready")
{
return PlayState::NotReady;
}
else if (mode == "open")
{
return PlayState::Open;
}
else if (mode == "recording")
{
return PlayState::Recording;
}
else if (mode == "parked")
{
return PlayState::Parked;
}
else if (mode == "seeking")
{
return PlayState::Seeking;
}
return PlayState::Closed;
}
void Win32Mci::SetRepeat(bool repeat)
{
Repeat_ = repeat;
if (State() == PlayState::Playing || State() == PlayState::Paused)
{
Seek(0, SEEK_SET);
Play();
if (State() == PlayState::Paused)
{
Pause();
}
}
}
std::string Win32Mci::Command(const std::string& command) const
{
const DWORD bufferSize = 1000;
char buffer[bufferSize] = { 0 };
if (mciSendStringA(command.c_str(), buffer, bufferSize, nullptr) != MMSYSERR_NOERROR)
{
throw std::runtime_error("MCI command failed.");
}
return buffer;
}
bool Win32Mci::PlayCommand(const std::string& command) const
{
return mciSendStringA(command.c_str(), nullptr, 0, nullptr) == MMSYSERR_NOERROR;
}
void Win32Mci::Close() noexcept
{
PlayCommand("close " + alias_);
}
void Win32Mci::Dispose() noexcept
{
Close();
}
}
}