文本版|topic 高级搜索
   名人堂 帮助 论坛制度 意见反馈 | 首页 博客 周新贴 招聘 专题 新闻
RSS 底部
 
社区导航: 专家门诊   网络技术   操作系统   数据库   程序设计   系统应用   考试认证   CIO及信息化   站长交流   综合交流   下载基地  51CTO产品服务 设为首页 | 收藏本站
51CTO技术论坛» C/C++ » 一个支持所有媒体类型和循环播放的类       [ 打印]  [ 订阅]  [ 收藏]  [ 推荐给朋友]   [ 本帖文本页]

论坛跳转:
     
标题: [转载] 一个支持所有媒体类型和循环播放的类  ( 查看:251  回复:0 )   
 
dada00000
技术员  点击可查看详细



帖子 83
精华 0
无忧币 709
积分 423
阅读权限 30
注册日期 2007-8-16
最后登录 2007-8-24 离线

[查看资料]  [发短消息]  [Blog
       
发表于:2007-8-20 14:33   标题:一个支持所有媒体类型和循环播放的类
上一帖 |
这篇文章是我第一次在VC在线发表,我应该是只VC的菜鸟。为了找个能循环播放mp3的VC源程序,我搜遍了网上的资源(差点气得要砸电脑),好不容易找到一个,却只有程序中的调用,关键的类的生成文件却没有,有什么用?(主要是自己没有MCI函数的具体的参数资料,不知道怎么调用,如果你有,请发一份给我,字符串的我已经有了,命令方式的没有。)
        后来找到一个,非常感谢他,作者叫:黄利龙。但他没有单独把类分离出来,且没有保存列表到文件。
        我把他的程序打印出来,仔细分析了程序语句,然后进行了修改和优化。
大家可以从下面的程序看出来,我们菜鸟的人基础不够,很希望了解每一句的确切意思,有些地方我带有猜测的,如果有错的地方,请大家指出,也欢迎大家来信和我交流,我向您学习。我的Email:lyj2008@lajy.com
        我修改的程序特点如下:
        1、把它分离出来单独构成一个类,便于以后所有程序的使用。
        2、提供了接口函数。
        3、支持所有的媒体类型
        4、能循环播放音乐
        5、能保存上次打开的文件。
        难免会有错,请大家可以不断完善它,然后把它贴出来,这样,以后有类似遭遇的不用这么辛苦了!
   
        CMidi类的使用方法:
          1、直接把MIDI.h和MIDI.cpp文件复制到你程序目录下,工程中加入这两个文件。
          2、单击“工程->设置->Link”,在“对象/库模块”中连接库winmm.lib
          3、在你工程的头文件中包含头文件,#include "MIDI.H"
          4、在工程中定义一个CMidi类的对象,如:CMidi m_Music;
          5、在工程的初始化文件中,初始化歌曲列表路径,m_Music.InitPath(),
          再打开列表,m_Misic.OpenList();下面就可以在各个对应的消息函数中处理它了
  如:
           播放:m_Misic.Play();
           停止:m_Misic.Stop();
           上一首:m_Misic.Per();
           下一首:m_Misic.Next();
           打开:m_Misic.OpenFiles();
           保存歌曲列表:m_Misic.SaveList();
        保存列表我没有放在打开函数中,如果打开的文件比较多,
那样会在打开过一会儿才能播放音乐,不舒服,你自己到工程的OnDestroy()中保存吧
        循环播放:m_Misic.OnTimer();
        它需要在主程序中打开一个定时器,SetTimer(0,500,NULL);然后在主
程序中重载OnTimer()函数,在该函数体内,先判断是否正在播放,
  m_Misic.PlayingFalg是否为真,真,则调用循环播放函数。如下:
  {
       if(m_Misic.PlayingFalg)
          m_Misic.OnTimer();
  }

/ /Midi.h
/////////////////////////////////////////////////////////////////////////////
#ifndef __MIDI_H__
#define __MIDI_H__

#include

class CMidi
{

public:
bool Play();//播放初始化函数(打开设备并初始化)
CMidi();
~CMidi();
public:
void OnTimer();//循环播放函数
bool InitPath();//初始化路径,取得播放曲目列表文件的全路径
bool OpenFiles();//打开文件对话框,获取歌曲列表
bool OpenList();//读取文件中的歌曲列表
bool SaveList();//保存列表
void Per();//上一首
void Next();//下一首
void Stop();//停止函数,在播放以前先停止
DWORD getinfo(DWORD item);//获取歌曲长度信息
DWORD m_count;
DWORD cdlen,cdfrom,cdto;
int m_totalFiles;//保存歌曲的首数
int fr;//当前已播放的歌曲数
CString m_FileList[256];//歌曲路径列表数组
CString m_MusicFilePath;//保存歌曲列表文件的路径
bool PlayingFalg;//正在播放标志,以便定时器判断
};

#endif


//////////////////////////////////////////////////////////////////
//以下为MIDI.cpp文件
/////////////////////////////////////////////////////////////////
// Midi.cpp

#include "stdafx.h"
#include "Midi.h"

CMidi::CMidi()
{
m_totalFiles=0;
fr=0;
cdfrom=0;
m_MusicFilePath="";
PlayingFalg=false;

}

CMidi::~CMidi()
{

}

//------------播放---------------------
bool CMidi:lay()
{
if(m_FileList[fr]=="")
{//如果读取路径为空,则弹出打开对话框
  OpenFiles();
}
else
{
  PlayingFalg=true;//标志为正在播放
  MCI_OPEN_PARMS mciopenparms;//打开
  MCI_PLAY_PARMS mciplayparms;//播放
  //以下用fr做下标,能在停止再播放时恢复上次的位置
  mciopenparms.lpstrElementName=m_FileList[fr];//播放路径
  mciopenparms.lpstrDeviceType=NULL;//文件类型为NULL,就可以支持全部类型
  mciSendCommand(0,MCI_OPEN,MCI_DEVTYPE_WAVEFORM_AUDIO,
   (DWORD)(LPVOID)&mciopenparms);//向MCI设备发送命令消息

  m_count=mciopenparms.wDeviceID;
  mciplayparms.dwCallback=NULL;//窗口拥有者句柄
  cdlen=getinfo(MCI_STATUS_LENGTH);//得到曲目长度                                                                                                                                                                                                                                          
  cdto=MCI_MAKE_HMS(MCI_HMS_HOUR(cdlen),MCI_HMS_MINUTE(cdlen),
   MCI_HMS_SECOND(cdlen));//根据长度计算出时、分、秒
  mciplayparms.dwFrom=MCI_MAKE_HMS(0,0,0);//表示从哪儿开始播放吧
  mciplayparms.dwTo=cdto;//表示放到哪儿为止
  mciSendCommand(m_count,MCI_PLAY,MCI_TO|MCI_FROM,
   (DWORD)(LPVOID)& mciplayparms); //发送播放消息
}

return true;
}

//---------------获取歌曲信息(长度,已播放长度)------
DWORD CMidi::getinfo(DWORD item)
{
MCI_STATUS_PARMS mcistatusparms;
mcistatusparms.dwCallback=NULL;
/* //接受传入的命令参数,这是关键。命令参数如下:
   获取歌曲长度: MCI_STATUS_LENGTH
   获取当前已播放的长度:MCI_STATUS_POSITION
*/
mcistatusparms.dwItem=item;//接受命令参数的地方
mcistatusparms.dwReturn=0;//返回值
mciSendCommand(m_count,MCI_STATUS,MCI_STATUS_ITEM,(DWORD)&mcistatusparms);
return mcistatusparms.dwReturn;
}

//-------------------停止-------------------
void CMidi::Stop()
{
PlayingFalg=false;//关闭正在播放标志
cdfrom=MCI_MAKE_HMS(0,0,0);//播放位置归文件开头
mciSendCommand(m_count,MCI_CLOSE,0,NULL);//发出关闭消息
m_count=0;
}

//-------------------下一首----------------
void CMidi::Next()
{
fr++;
if(fr>=m_totalFiles)
{
  //让fr指向下一个音乐文件,fr是从0下标开始
  //m_totalFiles为总文件数
  fr=fr%m_totalFiles;
}
Stop();
Play();
}

//----------上一首------------------
void CMidi:er()
{
fr--;
if(fr==-1)
{//指向最后一首歌,但fr是从0下标开始的,而m_totalFiles是从1开始
  fr=m_totalFiles-1;
}
Stop();
Play();//播放fr指向的位置

}

//----------保存曲目列表-----------------
bool CMidi::SaveList()
{
CFile fileList;//文件对象
if(!fileList.Open(m_MusicFilePath,CFile::modeCreate|CFile::modeWrite))
  return FALSE;//打开文件,不存在则创建,写文件
char fileName[256];
for(int i=0;i {//m_totalFiles为打开对话框中获取的歌曲总数
  strcpy(fileName,m_FileList[i]);//取出一条曲目路径
  fileList.Write(fileName,strlen(fileName));//写入文件
  fileList.Write("\r\n",2);//写入一行结束和换行符
}
fileList.Write("----",4);//写入文件最后标志
fileList.Close();//关闭文件
return TRUE;

}

//----------读取曲目路径列表-----------------
bool CMidi::OpenList()
{
CFile fileList;
if(!fileList.Open(m_MusicFilePath,CFile::modeNoTruncate|CFile::modeRead))
  return FALSE;//以只读模式打开,不覆盖原有文件,m_MusicFilePath为列表文件的路径
char ch;
while(1)
{
  CString fileName;
  fileList.Read(&ch,1);//读入一个字符
  if(ch==@#-@#) break;  //如文件是最后返回,-是文件最后的标志
  fileName+=ch;//否则存入
  while(1)
  {//读入一行
   fileList.Read(&ch,1);
   if(ch==@#\r@#)
   {//这儿可以判断是一行了
    m_totalFiles++;//曲目首数计数
    fileList.Read(&ch,1);
    break;
   }
   fileName+=ch;
  }
        //下面这句把路径加入列表中,用字符串数组代替
  //m_totalFiles前面已经加一了,所以这儿要少一个
  m_FileList[m_totalFiles-1]=fileName;
}
fileList.Close();
return TRUE;
}

//----------打开对话框,获取曲目列表-----------------
bool CMidi::OpenFiles()
{
CFileDialog f(true);//打开对话框对象
f.m_ofn.Flags |=512;//OFN_ALLOWMULTISELECT;目录列表方式
f.m_ofn.lpstrFilter="所有媒体类型\0*.*\0\0";
    if(f.DoModal()!=IDOK)
  return FALSE;//用户单击了“取消”
POSITION pos=f.GetStartPosition();//获取第一个文件位置
int i=0;
while(pos)
{
  m_FileList[i]=f.GetNextPathName(pos);//读取文件到曲目路径列表
  i++;
}
m_totalFiles=i;//保存曲目总数
Stop();
Play();//播放打开的文件
return TRUE;
}

//-------------------获得播放列表文件的路径------------
bool CMidi::InitPath()
{//初始化路径,取得播放曲目列表文件的全路径
TCHAR path[256];//保存文件路径
GetModuleFileName(NULL,path,sizeof(path)) ;//获取当前程序路径
TCHAR * p = _tcsrchr(path,_T(@#\\@#)) ;//查找最后一个@#\\@#字符
if(p) lstrcpy(p,_T("\\MPlayer.mdr"));//替换成要查找的完整路径
m_MusicFilePath=path;//保存到路径变量中,以便用它来打开列表文件
return true;
}

//----------------------循环播放------------------
void CMidi::OnTimer()
{//循环播放
if(getinfo(MCI_STATUS_POSITION)==cdlen)
    {//如当前播放的长度等于歌曲的长度,说明已经播放完毕
  Next();//指向下一首
}
}



网络工程师到底该不该去考CCIE认证?
2007-8-20 14:331楼
[ 顶部 ]
     
论坛跳转:  

| | |

标记已读 · 删除论坛Cookies · 文本版 · WAP
 
| 诚征版主 | 版主堂 | 意见建议 | 大史记 | 论坛地图
Copyright©2005-2008 51CTO.COM  Powered by Discuz!
本论坛言论纯属发布者个人意见,不代表51CTO网站立场!如有疑义,请与管理员联系。
京ICP备05051492号