📄 playlist.cpp
字号:
/*****************************************************************
|
| PlayList Management
|
|
| (c) 1996-1998 MpegTV, LLC
| Author: Gilles Boccon-Gibod (gilles@mpegtv.com)
|
****************************************************************/
/*----------------------------------------------------------------------
| includes
+---------------------------------------------------------------------*/
#include "playlist.h"
/*----------------------------------------------------------------------
| constants
+---------------------------------------------------------------------*/
#ifndef NULL
#define NULL 0
#endif
/*----------------------------------------------------------------------
| PlayList::PlayList
+---------------------------------------------------------------------*/
PlayList::PlayList() :
m_CallbackClient(NULL),
m_CallbackFunction(NULL),
m_Root(NULL),
m_Current(NULL),
m_Mode(0),
m_DefaultAction(PLAYLIST_ACTION_NONE)
{
// TODO
}
/*----------------------------------------------------------------------
| PlayList::~PlayList
+---------------------------------------------------------------------*/
PlayList::~PlayList()
{
if (m_Root) delete m_Root;
}
/*----------------------------------------------------------------------
| PlayList::RegisterCallback
+---------------------------------------------------------------------*/
void
PlayList::RegisterCallback(PlayListCallback callback, void *client)
{
m_CallbackFunction = callback;
m_CallbackClient = client;
}
/*----------------------------------------------------------------------
| PlayList::Clear
+---------------------------------------------------------------------*/
void
PlayList::Clear()
{
if (m_Root) delete m_Root;
}
/*----------------------------------------------------------------------
| PlayList::AddTrack
+---------------------------------------------------------------------*/
int
PlayList::AddTrack(const char *name)
{
// we must have a root
if (m_Root == NULL) {
m_Root = new PlayListItem(this, "root");
}
return AddTrack(m_Root, name);
}
/*----------------------------------------------------------------------
| PlayList::AddTrack
+---------------------------------------------------------------------*/
int
PlayList::AddTrack(PlayListItem *parent, const char *name)
{
PlayListItem *item;
// create a new item
item = new PlayListItem(parent, name);
// add the item to the parent's children
parent->AddChild(item);
// notify the client
if (m_CallbackFunction) {
m_CallbackFunction(m_CallbackClient,
this,
PLAYLIST_EVENT_ITEM_CREATED,
(void *)item);
}
// if we had no current track, make this one current
if (m_Current == NULL) {
SetCurrent(item);
}
return PLAYLIST_SUCCESS;
}
/*----------------------------------------------------------------------
| PlayList::SetMode
+---------------------------------------------------------------------*/
void
PlayList::SetMode(unsigned int mask, unsigned int mode)
{
m_Mode = (m_Mode ^ mask) | mode;
if (m_Mode & PLAYLIST_MODE_PLAYING) {
m_DefaultAction = PLAYLIST_ACTION_PLAY;
} else {
m_DefaultAction = PLAYLIST_ACTION_NONE;
}
}
/*----------------------------------------------------------------------
| PlayList::SetCurrent
+---------------------------------------------------------------------*/
int
PlayList::SetCurrent(PlayListItem *item, PlayListAction action)
{
PlayListCurrentChangedEvent event;
// notify if the current item has changed
if (m_CallbackFunction) {
// setup event info
event.current = item;
event.previous = m_Current;
event.action = action;
// change current
m_Current = item;
// notify
m_CallbackFunction(m_CallbackClient,
this,
PLAYLIST_EVENT_CURRENT_CHANGED,
(void *)&event);
}
// mark the new current item played
if (action == PLAYLIST_ACTION_PLAY) {
item->m_Status |= PLAYLIST_STATUS_PLAYED;
}
return PLAYLIST_SUCCESS;
}
/*----------------------------------------------------------------------
| PlayList::Play
+---------------------------------------------------------------------*/
int
PlayList::Play()
{
if (m_Current) return m_Current->Play();
if (m_Root) {
return m_Root->Play();
}
return PLAYLIST_FAILURE;
}
/*----------------------------------------------------------------------
| PlayList::Stop
+---------------------------------------------------------------------*/
int
PlayList::Stop()
{
if (m_CallbackFunction) {
m_CallbackFunction(m_CallbackClient,
this,
PLAYLIST_EVENT_STOP_PLAYING,
NULL);
}
return PLAYLIST_SUCCESS;
}
/*----------------------------------------------------------------------
| PlayList::Next
+---------------------------------------------------------------------*/
int
PlayList::Next()
{
if (m_Current) {
return m_Current->Next();
} else {
if (m_Root) {
return m_Root->DoAction(m_DefaultAction);
}
}
return PLAYLIST_FAILURE;
}
/*----------------------------------------------------------------------
| PlayList::Prev
+---------------------------------------------------------------------*/
int
PlayList::Prev()
{
if (m_Current) {
return m_Current->Prev();
}
return PLAYLIST_FAILURE;
}
/*----------------------------------------------------------------------
| PlayListItem::PlayListItem
+---------------------------------------------------------------------*/
PlayListItem::PlayListItem(PlayList *owner, const char *name)
{
Init();
m_PlayList = owner;
SetName(name);
}
/*----------------------------------------------------------------------
| PlayListItem::PlayListItem
+---------------------------------------------------------------------*/
PlayListItem::PlayListItem(PlayListItem *parent, const char *name)
{
Init();
m_PlayList = parent->m_PlayList;
SetName(name);
}
/*----------------------------------------------------------------------
| PlayListItem::~PlayListItem
+---------------------------------------------------------------------*/
PlayListItem::~PlayListItem()
{
// first, delete the children
PlayListItem *item = m_FirstChild;
while (item) {
PlayListItem *next = item->m_RightSibling;
delete item;
item = next;
}
if (m_LeftSibling) {
// we are not first child
m_LeftSibling->m_RightSibling = m_RightSibling;
} else {
// we are fist child
if (m_Parent) {
m_Parent->m_FirstChild = m_RightSibling;
}
}
if (m_RightSibling) {
m_RightSibling->m_LeftSibling = m_LeftSibling;
}
// if we were the curren item, change current
if (m_PlayList->m_Current == this) {
m_PlayList->m_Current = m_LeftSibling;
}
// if we are the root, set the root to NULL
if (m_PlayList->m_Root == this) {
m_PlayList->m_Root = NULL;
}
// notify the client
if (m_PlayList &&
m_PlayList->m_CallbackFunction) {
m_PlayList->m_CallbackFunction(m_PlayList->m_CallbackClient,
m_PlayList,
PLAYLIST_EVENT_ITEM_DELETED,
(void *)this);
}
// free the strings
if (m_FullName) delete[] m_FullName;
if (m_ShortName) delete[] m_FullName;
if (m_GroupName) delete[] m_GroupName;
}
/*----------------------------------------------------------------------
| PlayListItem::Init
+---------------------------------------------------------------------*/
void
PlayListItem::Init()
{
m_PlayList = NULL;
m_Parent = NULL;
m_FirstChild = NULL;
m_RightSibling = NULL;
m_LeftSibling = NULL;
m_Status = 0;
m_ClientData = 0;
}
/*----------------------------------------------------------------------
| PlayListItem::SetName
+---------------------------------------------------------------------*/
void
PlayListItem::SetName(const char *name)
{
const char *ptr = name;
// go to the end of the string
int full_name_size = 0;
while (*ptr) {
ptr++;
full_name_size++;
}
// copy the full name
m_FullName = new char[full_name_size+1];
for (int i=0; i<=full_name_size; i++) {
m_FullName[i] = name[i];
}
// rewind until we find a / or \ or reach the start
int short_name_size = 0;
while (ptr != name &&
ptr[-1] != '/' &&
ptr[-1] != '\\') {
ptr--;
short_name_size++;
}
// copy the short name
m_ShortName = new char[short_name_size+1];
for (i=0; i<=short_name_size; i++) {
m_ShortName[i] = ptr[i];
}
}
/*----------------------------------------------------------------------
| PlayListItem::AddChild
+---------------------------------------------------------------------*/
void
PlayListItem::AddChild(PlayListItem *item)
{
// set the parent
item->m_Parent = this;
// add to the list of children
if (m_FirstChild) {
PlayListItem *child = m_FirstChild;
while (child->m_RightSibling) child = child->m_RightSibling;
child->m_RightSibling = item;
item->m_LeftSibling = child;
} else {
m_FirstChild = item;
}
}
/*----------------------------------------------------------------------
| PlayListItem::DoAction
+---------------------------------------------------------------------*/
int
PlayListItem::DoAction(PlayListAction action)
{
PlayListItem *target;
if (m_FirstChild) {
target = m_FirstChild;
} else {
target = this;
}
m_PlayList->SetCurrent(target, action);
return PLAYLIST_SUCCESS;
}
/*----------------------------------------------------------------------
| PlayListItem::Play
+---------------------------------------------------------------------*/
int
PlayListItem::Play()
{
return DoAction(PLAYLIST_ACTION_PLAY);
}
/*----------------------------------------------------------------------
| PlayListItem::Next
+---------------------------------------------------------------------*/
int
PlayListItem::Next()
{
if (m_RightSibling) {
return m_RightSibling->DoAction(m_PlayList->m_DefaultAction);
} else {
if (m_PlayList->m_Mode & PLAYLIST_MODE_LOOP) {
m_PlayList->m_Root->DoAction(m_PlayList->m_DefaultAction);
} else {
if (m_PlayList->m_Mode & PLAYLIST_MODE_PLAYING) {
m_PlayList->Stop();
}
m_PlayList->m_Root->DoAction(PLAYLIST_ACTION_NONE);
}
}
return PLAYLIST_FAILURE;
}
/*----------------------------------------------------------------------
| PlayListItem::Prev
+---------------------------------------------------------------------*/
int
PlayListItem::Prev()
{
if (m_LeftSibling) {
return m_LeftSibling->DoAction(m_PlayList->m_DefaultAction);
}
return PLAYLIST_FAILURE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -