/*
# define _CRT_SECURE_NO_WARNINGS
# include <stdio.h>
//输入输出
# include <conio.h>
//输入输出
# include <io.h>
//浏览文件夹文件名
# include <stdlib.h>
// 动态空间分配
# include <string.h>
// 字符串操作
# include <windows.h>
// Windows系统的各种API函数
# pragma comment (lib , "WINMM.LIB") //音乐播放必须要用到
# include <pthread.h>
//多线程编程
# include <process.h>
typedef struct filename
{
int Filenumber;
char Filename[260];
struct filename * next , *previous;
}Fn , *PFn;
int status = 0;
pthread_mutex_t mutt;
# define PAUSE_OR_RESUME
1//停止或播放
# define PREVIOUS
2//上一首
# define NEXT
3//下一首
# define QUIT
4//退出
PFn ListHead (Fn variable)
{
PFn head = (PFn) malloc (sizeof (Fn));
if (!head)
return 0;
head->next = head->previous = NULL;
head->Filenumber = variable.Filenumber;
strcpy (head->Filename , variable.Filename);
return head;
}
PFn CreateList (PFn head ,char *FilePathAndExtension)
{
PFn p , t;
p = t = NULL;
Fn var;
int i = 0;
_finddata_t Info;
//这是文件信息的结构体
long hfind;
hfind = _findfirst (FilePathAndExtension , &Info);//浏览文件夹内文件的函数,找到第一个文件,返回一个句柄。
if (hfind == -1)
return 0;
strcpy (var.Filename , Info.name);
var.Filenumber = ++i;
p = ListHead (var);
head->next = p;
p->previous = head;
t = p;
while (!_findnext (hfind , &Info))//浏览文件。
{
i++;
var.Filenumber = i;
strcpy (var.Filename , Info.name);
p = ListHead (var);
t->next = p;
p->previous = t;
t = p;
}
_findclose (hfind);//
return head;
}
void OutputList (PFn head)
{
PFn p = head->next;
while (p)
{
printf ("\t%d:%s\n" , p->Filenumber , p->Filename);
p = p->next;
}
}
void DestroyList (PFn head)
{
PFn p , t;
p = head->next;
while (p)
{
t = p;
p = p->next;
free (t);
}
}
PFn SearchFile (PFn head , Fn variable)
{
PFn p;
p = head->next;
while (p)
{
if (variable.Filenumber == p->Filenumber ||
strcmp (p->Filename , variable.Filename) == 0
|| (variable.Filenumber == p->Filenumber &&
strcmp (p->Filename , variable.Filename) == 0))
{
return p;
}
p = p->next;
}
return 0;
}
//////////////////////////////////以上是链表的操作//////////////////////////////////
void * SetKey (void*);
void CreateThreads (void)
{
pthread_t thid;
pthread_mutex_init (&mutt , NULL);
pthread_create (&thid , NULL , SetKey , NULL);
pthread_detach (thid);
}
void * SetKey (void*)
{
pthread_mutex_lock (&mutt);
while (1)
{
status = 0;
getch ();//等待按键
if (GetAsyncKeyState (VK_SPACE))//GetAsyncKeyState (VK_SPACE)参数是一个虚拟键,如果按了键盘上对应
//的虚拟键,它的返回值不为0 。MSDN 上则解释,按下对应键返回负值,否则
{
//返回 大于等于0 的值。//好像是这样……
status = PAUSE_OR_RESUME;
//
printf ("%d\n" , status);
}
if (GetAsyncKeyState (0x68))
{
status = PREVIOUS;
//
printf ("%d\n" , status);
}
if (GetAsyncKeyState (0x62))
{
status = NEXT;
//
printf ("%d\n" , status);
}
if (GetAsyncKeyState (VK_ESCAPE))
{
status = QUIT;
//
printf ("%d\n" , status);
break;
}
Sleep (100);//这个必须要有,因为电脑执行太快,没有这个,按一下键就会执行好多遍了。
}
pthread_mutex_unlock (&mutt);
return 0;
}
/////////////////////////////////上面是关于线程的创建///////////////////////
void ErrorReason (MCIERROR err)///////检查MCI操作出错原因/////////
{
char errorBuff[260];
mciGetErrorStringA (err , errorBuff , sizeof (errorBuff));
printf ("\t%d:\t%s\n" , err , errorBuff);
}
void PlayAMusic (char * filename , char * filepath)
{
MCIERROR err;
MCIDEVICEID dev;
char cmd[260];
sprintf (cmd , "%s%s" , filepath , filename);
puts (filename);
/////////////////////////////////////////////////打开设备//////////
MCI_OPEN_PARMSA open;
open.lpstrElementName = cmd;
open.lpstrDeviceType = 0;
err = mciSendCommandA (NULL , MCI_OPEN , MCI_OPEN_ELEMENT , (DWORD)(PVOID)&open);
if (err)
{
ErrorReason (err);
return ;
}
/////////////////////////////////
dev = open.wDeviceID ; //打开成功后得到设备ID
////////////////////////////获取设备的总长度//////////
MCI_STATUS_PARMS state;
state.dwCallback = NULL;
state.dwItem = MCI_STATUS_LENGTH;
mciSendCommandA (dev , MCI_STATUS , MCI_STATUS_ITEM , (DWORD)(PVOID)&state);
DWORD len = state.dwReturn;
///////////////////////////////////////////////////播放///////
MCI_PLAY_PARMS play;
play.dwCallback = NULL;
play.dwFrom = 0;
//表示从开始处播放。
err = mciSendCommandA (dev , MCI_PLAY , MCI_FROM , (DWORD)(PVOID)&play);
if (err)
{
ErrorReason (err);
return ;
}
//
getch ();//////////////通过正在播放的位置与总长度比较,来确定播放时间//////////////
DWORD position = 0;
while (1)
{
while (position < len)
{
if ((status == PAUSE_OR_RESUME) || (status == NEXT )//通过status的值来判断循环是否进行
|| (status == PREVIOUS) || (status == QUIT))
//status是全局变量,它的值通过同步线程按键获得
break;
else
{
state.dwItem = MCI_STATUS_POSITION;//获取此时播放到的位置
mciSendCommandA (dev , MCI_STATUS , MCI_STATUS_ITEM , (DWORD)(PVOID)&state);
position = state.dwReturn;
//
printf ("%ld" , status);
}
}
/////////////////////// 暂停/////////
MCI_GENERIC_PARMS pause;
pause.dwCallback = NULL;
mciSendCommandA (dev , MCI_PAUSE , 0 , (DWORD)(PVOID)&pause);
if (status == PAUSE_OR_RESUME)
{
//
printf ("%ld" , status);
//经过测试发现上下两个值是不一样的
Sleep (200);
//这里一点要暂停一点时间,用来确保同步线程中有足够的时间给status重新赋值。
//
printf ("%ld" , status);//
while (status != PAUSE_OR_RESUME)
//如果没有暂停,由于电脑运行太快,同步线程还没有来得及给status赋值,
//这里的程序就执行完了,所以status的值是一样的。
{
//这里的while循环相当于Sleep一样,只是这里可以通过输入数据来终止。
if (status == PAUSE_OR_RESUME || status == QUIT
|| status == NEXT || status == PREVIOUS)
break;
}
}
//////////////////////从暂停处播放///////////
mciSendCommandA (dev , MCI_RESUME , 0 , (DWORD)(PVOID)&play);
//
getch ();//下面的一些程序实现的相当getch 的功效。
//////////
这个if……esle语句是为了确保按上或下键时退出循环,这样写容易理解一些。/////////
//
if ((status == NEXT) || status == PREVIOUS )
//
{;
//
printf ("%ld\n" , status);
//
Sleep (200);
//
printf ("%ld\n" , status);
///
}//暂停之后,status的值会在同步线程中重新赋值为0.
//
else
//
Sleep (200);
////////////////////////////////////////
if (status != NEXT && status != PREVIOUS )
Sleep (200);
while (position < len)
{
if ((status == PAUSE_OR_RESUME) || (status == NEXT )
|| (status == PREVIOUS) || (status == QUIT))
break;
else
{
state.dwItem = MCI_STATUS_POSITION;
mciSendCommandA (dev , MCI_STATUS , MCI_STATUS_ITEM , (DWORD)(PVOID)&state);
position = state.dwReturn;
//
printf ("%ld" , status);
}
}
if (!(len > position)||status == QUIT || status == NEXT || status == PREVIOUS)
break;
}
////////////////关闭设备///////////////
MCI_GENERIC_PARMS close;
close.dwCallback = NULL;
mciSendCommandA (dev , MCI_CLOSE , 0 , (DWORD)(PVOID)&close);
}
void PlayAllTheMusic (PFn head , char *Filepath)
{
PFn p = head->next;
Fn var;
while (p)
{
//
printf ("%d\n" ,status);
PlayAMusic (p->Filename , Filepath);
if (status == QUIT)
break;
else if (status == PREVIOUS)
{
if (p->previous != head)
{
p = p->previous;
//
strcpy (var.Filename , p->Filename);//这部分似乎没必要。
//
var.Filenumber = p->Filenumber;
//
if (SearchFile(head , var))
//
{
//
PlayAMusic (p->Filename , Filepath);
//
}
}
else
printf ("已经是第一首歌曲了!\n");
}
else
p = p->next;
}
}
int main (void)
{
Fn var = {0 , "\0"};
PFn head = ListHead (var);
char *Filepath = "C:\\Users\\yutang\\Desktop\\music\\";
char *FilePathAndExtension = "C:\\Users\\yutang\\Desktop\\music\\*.mp3";
CreateThreads ();
CreateList (head , FilePathAndExtension);
OutputList (head);
PlayAllTheMusic (head , Filepath);
DestroyList (head);
return 0;
}*/
我写的,分享一下。