This source file includes following definitions.
- DoDataExchange
- BEGIN_MESSAGE_MAP
- OnSize
- OnDropFiles
- OnNotify
- Clear
- ClearButPlaying
- UpdateEntry
- RefreshList
- OnPlAddFile
- OnClose
- OnPlRemFile
- OnSelUp
- OnSelDown
- OnPlRemAll
- OnPlRemDead
- LocCbck
- pl_enum_dir_item
- pl_enum_dir_dirs
- AddDir
- OnPlAddDir
- OnPlAddDirRec
- OnPlAddUrl
- OnPlSave
- Save
- OnPlOpen
- OpenPlayList
- OnRclickFilelist
- OnReverseSelection
- OnReverseList
- OnRandomize
- Sort
- OnSortFile
- OnSortTitle
- OnSortDuration
- HasValidEntries
- RefreshCurrent
- OnDblclkFilelist
- OnPlPlay
- Truncate
- QueueURL
- PlayNext
- PlayPrev
- SetDead
- SetDuration
- GetDisplayName
- GetURL
#include "stdafx.h"
#include "osmo4.h"
#include "MainFrm.h"
#include "OpenURL.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
PLEntry::PLEntry(CString url, char *path)
{
if (!path || strrchr(url, '\\') || strstr(url, "://")) {
m_url = gf_strdup(url);
} else {
char szPath[MAX_PATH];
strcpy(szPath, path);
strcat(szPath, url);
m_url = gf_strdup(szPath);
}
char *str = (char *) strrchr(url, '\\');
if (!str) str = (char *) strrchr(url, '/');
if (str && strlen(str+1)) {
m_disp_name = gf_strdup(str+1);
str = strrchr(m_disp_name, '.');
if (str) str[0] = 0;
} else {
str = (char *) strstr(url, "://");
if (str) {
str += 3;
m_disp_name = gf_strdup(str);
} else {
m_disp_name = gf_strdup(url);
str = strrchr(m_disp_name, '.');
if (str) str[0] = 0;
}
}
m_duration = 0;
m_bIsDead = GF_FALSE;
m_bIsPlaying = GF_FALSE;
m_bIsSelected = GF_FALSE;
}
PLEntry::~PLEntry()
{
if (m_url) gf_free(m_url);
if (m_disp_name) gf_free(m_disp_name);
}
static char szCacheDir[MAX_PATH];
Playlist::Playlist()
: CDialog(Playlist::IDD, NULL)
{
m_entries = gf_list_new();
m_cur_entry = -1;
m_all_dead_entries=-1;
GetCurrentDirectory(MAX_PATH, szCacheDir);
}
Playlist::~Playlist()
{
Clear();
gf_list_del(m_entries);
}
void Playlist::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_FILELIST, m_FileList);
}
BEGIN_MESSAGE_MAP(Playlist, CDialog)
ON_WM_SIZE()
ON_COMMAND(ID_PL_ADD_FILE, OnPlAddFile)
ON_COMMAND(ID_PL_REM_FILE, OnPlRemFile)
ON_COMMAND(ID_PL_UP, OnSelUp)
ON_COMMAND(ID_PL_DOWN, OnSelDown)
ON_COMMAND(ID_PL_SAVE, OnPlSave)
ON_WM_DROPFILES()
ON_WM_CLOSE()
ON_WM_DESTROY()
ON_COMMAND(ID_PL_REM_DEAD, OnPlRemDead)
ON_COMMAND(ID_PL_REM_ALL, OnPlRemAll)
ON_COMMAND(ID_PL_ADD_DIR, OnPlAddDir)
ON_COMMAND(ID_PL_ADD_DIR_REC, OnPlAddDirRec)
ON_COMMAND(ID_PL_ADD_URL, OnPlAddUrl)
ON_COMMAND(ID_PL_OPEN, OnPlOpen)
ON_COMMAND(ID_PL_PLAY, OnPlPlay)
ON_COMMAND(ID_PL_SEL_REV, OnReverseSelection)
ON_COMMAND(ID_PL_SORT_REV, OnReverseList)
ON_COMMAND(ID_PL_RANDOM, OnRandomize)
ON_COMMAND(ID_PL_SORT_TITLE, OnSortTitle)
ON_COMMAND(ID_PL_SORT_FILE, OnSortFile)
ON_COMMAND(ID_PL_SORT_DUR, OnSortDuration)
ON_NOTIFY(NM_RCLICK, IDC_FILELIST, OnRclickFilelist)
ON_NOTIFY(NM_DBLCLK, IDC_FILELIST, OnDblclkFilelist)
END_MESSAGE_MAP()
BOOL Playlist::OnInitDialog()
{
UINT buttonArray[50];
TBBUTTONINFO bi;
u32 *ba;
CDialog::OnInitDialog();
SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), TRUE);
SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), FALSE);
if (!m_toolBar.CreateEx(this, WS_CHILD | CBRS_TOP | CBRS_FLYBY) ||
!m_toolBar.LoadBitmap(IDR_PLAYLIST))
{
TRACE0("Failed to create toolbar\n");
return 0;
}
ba = &buttonArray[0];
*ba = ID_PL_OPEN;
ba++;
*ba = ID_PL_SAVE;
ba++;
*ba = ID_SEPARATOR;
ba++;
*ba = ID_PL_ADD_FILE;
ba++;
*ba = ID_PL_REM_FILE;
ba++;
*ba = ID_SEPARATOR;
ba++;
*ba = ID_PL_UP;
ba++;
*ba = ID_PL_DOWN;
ba++;
*ba = ID_SEPARATOR;
ba++;
*ba = ID_PL_SORT_FILE;
ba++;
m_toolBar.SetButtons(buttonArray, 9);
m_toolBar.SetButtonInfo(0, ID_PL_OPEN, TBBS_BUTTON, 0);
m_toolBar.SetButtonInfo(1, ID_PL_SAVE, TBBS_BUTTON, 1);
m_toolBar.SetButtonInfo(2, ID_SEPARATOR, TBBS_SEPARATOR, 0);
m_toolBar.SetButtonInfo(3, ID_PL_ADD_FILE, TBBS_DROPDOWN | TBBS_BUTTON, 2);
m_toolBar.SetButtonInfo(4, ID_PL_REM_FILE, TBBS_DROPDOWN | TBBS_BUTTON, 3);
m_toolBar.SetButtonInfo(5, ID_SEPARATOR, TBBS_SEPARATOR, 0);
m_toolBar.SetButtonInfo(6, ID_PL_UP, TBBS_BUTTON, 4);
m_toolBar.SetButtonInfo(7, ID_PL_DOWN, TBBS_BUTTON, 5);
m_toolBar.SetButtonInfo(8, ID_PL_SORT_FILE, TBBS_DROPDOWN | TBBS_BUTTON, 6);
CToolBarCtrl &ctrl = m_toolBar.GetToolBarCtrl();
ctrl.SetStyle(TBSTYLE_FLAT | TBSTYLE_DROPDOWN);
ctrl.SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS);
memset(&bi, 0, sizeof(bi));
bi.cbSize = sizeof(bi);
ctrl.GetButtonInfo(3, &bi);
bi.fsStyle |= TBSTYLE_DROPDOWN;
ctrl.SetButtonInfo(ID_PL_ADD_FILE, &bi);
memset(&bi, 0, sizeof(bi));
bi.cbSize = sizeof(bi);
ctrl.GetButtonInfo(4, &bi);
bi.fsStyle |= TBBS_DROPDOWN | TBSTYLE_DROPDOWN;
ctrl.SetButtonInfo(ID_PL_REM_FILE, &bi);
memset(&bi, 0, sizeof(bi));
bi.cbSize = sizeof(bi);
ctrl.GetButtonInfo(9, &bi);
bi.fsStyle |= TBSTYLE_DROPDOWN;
ctrl.SetButtonInfo(ID_PL_SORT_FILE, &bi);
m_FileList.InsertColumn(0, "", LVCFMT_LEFT, 30, 0);
m_FileList.InsertColumn(1, "Title", LVCFMT_LEFT, 200, 1);
m_FileList.InsertColumn(2, "Duration", LVCFMT_LEFT, 200, 2);
m_toolBar.UpdateWindow();
m_toolBar.ShowWindow(SW_SHOW);
SetWindowPos(NULL, 0, 0, 400, 600, SWP_NOZORDER | SWP_NOMOVE);
PostMessage(WM_NULL);
DragAcceptFiles();
return TRUE;
}
void Playlist::OnSize(UINT nType, int cx, int cy)
{
u32 tool_h;
CDialog::OnSize(nType, cx, cy);
RECT rc;
if (!m_toolBar.m_hWnd) return;
if (!m_FileList.m_hWnd) return;
m_toolBar.GetClientRect(&rc);
tool_h = rc.bottom - rc.top;
m_toolBar.SetWindowPos(this, 0, 0, cx, tool_h, SWP_NOZORDER);
m_FileList.SetWindowPos(this, 0, tool_h, cx, cy-tool_h, SWP_NOZORDER);
m_FileList.SetExtendedStyle(m_FileList.GetExtendedStyle() | LVS_EX_FULLROWSELECT);
m_FileList.SetColumnWidth(0, 30);
m_FileList.SetColumnWidth(2, 60);
m_FileList.SetColumnWidth(1, cx-95);
}
void Playlist::OnDropFiles(HDROP hDropInfo)
{
u32 i, count;
Osmo4 *app = GetApp();
char fileName[MAX_PATH];
count = ::DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0);
if (!count) return;
for (i=0; i<count; i++) {
::DragQueryFile (hDropInfo, i, fileName, MAX_PATH);
QueueURL(fileName);
}
RefreshList();
}
BOOL Playlist::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
if (((LPNMHDR)lParam)->code == TBN_DROPDOWN) {
RECT rc;
POINT pt;
CMenu *pPopup = new CMenu();
pPopup->CreatePopupMenu();
m_toolBar.GetWindowRect(&rc);
pt.y = rc.bottom;
pt.x = rc.left;
if ( ((LPNMTOOLBAR)lParam)->iItem == ID_PL_ADD_FILE) {
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_ADD_DIR, "Directory...");
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_ADD_DIR_REC, "Directory and subfolders...");
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_ADD_URL, "URL...");
m_toolBar.GetToolBarCtrl().GetItemRect(3, &rc);
pt.x += rc.left;
} else if ( ((LPNMTOOLBAR)lParam)->iItem == ID_PL_REM_FILE) {
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_REM_ALL, "Clear");
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_REM_DEAD, "Remove dead entries");
m_toolBar.GetToolBarCtrl().GetItemRect(4, &rc);
pt.x += rc.left;
} else if ( ((LPNMTOOLBAR)lParam)->iItem == ID_PL_SORT_FILE) {
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_SORT_TITLE, "Sort Files by title");
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_SORT_FILE, "Sort Files by filename");
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_SORT_DUR, "Sort Files by duration");
pPopup->AppendMenu(MF_SEPARATOR,0);
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_SORT_REV, "Reverse Playlist");
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_RANDOM, "Shuffle Playlist");
m_toolBar.GetToolBarCtrl().GetItemRect(8, &rc);
pt.x += rc.left;
}
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);
delete pPopup;
return FALSE;
}
return CDialog::OnNotify(wParam, lParam, pResult);
}
void Playlist::Clear()
{
m_FileList.DeleteAllItems();
while (gf_list_count(m_entries)) {
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, 0);
gf_list_rem(m_entries, 0);
delete ple;
}
m_cur_entry = -1;
}
void Playlist::ClearButPlaying()
{
PLEntry *p=NULL;
if (m_cur_entry>=0) p = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
if (p) gf_list_rem(m_entries, m_cur_entry);
Clear();
if (p) {
gf_list_add(m_entries, p);
m_cur_entry = 0;
}
RefreshList();
}
void Playlist::UpdateEntry(u32 i)
{
char szText[20];
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i);
if (i+1<10) sprintf(szText, "00%d", i+1);
else if (i+1<100) sprintf(szText, "0%d", i+1);
else sprintf(szText, "%d", i+1);
m_FileList.SetItem(i, 0, LVIF_TEXT, szText, 0, 0, 0, 0);
CString str;
if (ple->m_bIsDead) {
str = "!! DEAD !! ";
str += ple->m_disp_name;
}
else if (ple->m_bIsPlaying) {
str = ">> ";
str += ple->m_disp_name;
str += " >>";
}
else str = ple->m_disp_name;
m_FileList.SetItem(i, 1, LVIF_TEXT, str, 0, 0, 0, 0);
if (ple->m_duration) {
u32 h = (u32) (ple->m_duration / 3600);
u32 m = (u32) (ple->m_duration / 60) - h*60;
u32 s = (u32) (ple->m_duration) - h*3600 - m*60;
sprintf(szText, "%02d:%02d:%02d", h, m, s);
m_FileList.SetItem(i, 2, LVIF_TEXT, szText, 0, 0, 0, 0);
} else {
m_FileList.SetItem(i, 2, LVIF_TEXT, "Unknown", 0, 0, 0, 0);
}
}
void Playlist::RefreshList()
{
u32 i, top_idx;
char szPath[GF_MAX_PATH];
top_idx = m_FileList.GetTopIndex();
m_FileList.DeleteAllItems();
for (i=0; i<gf_list_count(m_entries); i++) {
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i);
m_FileList.InsertItem(i, "");
m_FileList.SetItemData(i, (u32) ple);
UpdateEntry(i);
if (ple->m_bIsPlaying) m_cur_entry = i;
if (ple->m_bIsSelected) {
m_FileList.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);
ple->m_bIsSelected = GF_FALSE;
}
}
if (m_cur_entry >= (s32)gf_list_count(m_entries)) m_cur_entry = gf_list_count(m_entries);
else {
s32 last_idx = top_idx + m_FileList.GetCountPerPage();
m_FileList.EnsureVisible(top_idx, 0);
if (gf_list_count(m_entries)<(u32) last_idx) last_idx = gf_list_count(m_entries);
m_FileList.EnsureVisible(last_idx, 1);
}
strcpy((char *) szPath, GetApp()->szUserPath);
strcat(szPath, "gpac_pl.m3u");
Save(szPath, GF_TRUE);
}
void Playlist::OnPlAddFile()
{
Osmo4 *app = GetApp();
CString sFiles = app->GetFileFilter();
CFileDialog fd(TRUE,NULL,NULL, OFN_ALLOWMULTISELECT | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST , sFiles);
fd.m_ofn.nMaxFile = 25000;
fd.m_ofn.lpstrFile = (char *) gf_malloc(sizeof(char) * fd.m_ofn.nMaxFile);
fd.m_ofn.lpstrFile[0] = 0;
if (fd.DoModal() == IDOK) {
s32 cur = m_FileList.GetItemCount();
POSITION pos = fd.GetStartPosition();
while (pos) {
QueueURL(fd.GetNextPathName(pos));
}
}
gf_free(fd.m_ofn.lpstrFile);
m_all_dead_entries=-1;
RefreshList();
}
void Playlist::OnClose()
{
ShowWindow(SW_HIDE);
}
void Playlist::OnPlRemFile()
{
if (!m_FileList.GetSelectedCount()) return;
POSITION pos = m_FileList.GetFirstSelectedItemPosition();
while (pos != NULL) {
int nItem = m_FileList.GetNextSelectedItem(pos);
PLEntry *ple = (PLEntry *) m_FileList.GetItemData(nItem);
gf_list_del_item(m_entries, ple);
delete ple;
}
m_all_dead_entries=-1;
RefreshList();
}
void Playlist::OnSelUp()
{
s32 i;
if (!m_FileList.GetSelectedCount()) return;
POSITION pos = m_FileList.GetFirstSelectedItemPosition();
int nItem = m_FileList.GetNextSelectedItem(pos);
if (nItem==0) return;
pos = m_FileList.GetFirstSelectedItemPosition();
while (pos != NULL) {
nItem = m_FileList.GetNextSelectedItem(pos);
PLEntry *ple = (PLEntry *) m_FileList.GetItemData(nItem);
i = gf_list_del_item(m_entries, ple);
assert(i>=1);
gf_list_insert(m_entries, ple, i-1);
ple->m_bIsSelected = GF_TRUE;
}
RefreshList();
}
void Playlist::OnSelDown()
{
s32 i, nItem;
if (!m_FileList.GetSelectedCount()) return;
POSITION pos = m_FileList.GetFirstSelectedItemPosition();
while (pos != NULL) nItem = m_FileList.GetNextSelectedItem(pos);
if ((u32) nItem + 1 == gf_list_count(m_entries)) return;
pos = m_FileList.GetFirstSelectedItemPosition();
while (pos != NULL) {
nItem = m_FileList.GetNextSelectedItem(pos);
PLEntry *ple = (PLEntry *) m_FileList.GetItemData(nItem);
i = gf_list_del_item(m_entries, ple);
gf_list_insert(m_entries, ple, i+1);
ple->m_bIsSelected = GF_TRUE;
}
RefreshList();
}
void Playlist::OnPlRemAll()
{
Clear();
RefreshList();
m_cur_entry = -1;
}
void Playlist::OnPlRemDead()
{
for (u32 i=0; i<gf_list_count(m_entries); i++) {
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i);
if (!ple->m_bIsDead) continue;
gf_list_rem(m_entries, i);
i--;
delete ple;
}
m_all_dead_entries=-1;
RefreshList();
}
static int CALLBACK LocCbck(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
{
char dir[MAX_PATH];
if (uMsg == BFFM_INITIALIZED) {
strcpy(dir, szCacheDir);
SendMessage(hwnd, BFFM_SETSELECTION, TRUE,(LPARAM) dir);
}
return 0;
}
static Bool pl_enum_dir_item(void *cbck, char *item_name, char *item_path, GF_FileEnumInfo *file_info)
{
Osmo4 *gpac = GetApp();
Playlist *_this = (Playlist *)cbck;
if (gf_term_is_supported_url(gpac->m_term, item_name, GF_FALSE, GF_TRUE)) {
_this->QueueURL(item_path);
}
return GF_FALSE;
}
static Bool pl_enum_dir_dirs(void *cbck, char *item_name, char *item_path, GF_FileEnumInfo *file_info)
{
gf_enum_directory(item_path, GF_FALSE, pl_enum_dir_item, cbck, NULL);
gf_enum_directory(item_path, GF_TRUE, pl_enum_dir_dirs, cbck, NULL);
return GF_FALSE;
}
void Playlist::AddDir(Bool do_recurse)
{
BROWSEINFO brw;
LPMALLOC pMalloc;
LPITEMIDLIST ret;
char dir[MAX_PATH];
Bool res = GF_FALSE;
if (NOERROR == ::SHGetMalloc(&pMalloc) ) {
memset(&brw, 0, sizeof(BROWSEINFO));
brw.hwndOwner = this->GetSafeHwnd();
brw.pszDisplayName = dir;
brw.lpszTitle = "Select Directory...";
brw.ulFlags = 0L;
brw.lpfn = LocCbck;
ret = SHBrowseForFolder(&brw);
if (ret != NULL) {
if (::SHGetPathFromIDList(ret, dir)) res = GF_TRUE;
pMalloc->Free(ret);
}
pMalloc->Release();
}
if (!res) return;
strcpy(szCacheDir, dir);
gf_enum_directory(dir, GF_FALSE, pl_enum_dir_item, this, NULL);
if (do_recurse) gf_enum_directory(dir, GF_FALSE, pl_enum_dir_dirs, this, NULL);
m_all_dead_entries=-1;
RefreshList();
}
void Playlist::OnPlAddDir()
{
AddDir(GF_FALSE);
}
void Playlist::OnPlAddDirRec()
{
AddDir(GF_TRUE);
}
void Playlist::OnPlAddUrl()
{
COpenUrl url;
if (url.DoModal() != IDOK) return;
PLEntry *ple = new PLEntry(url.m_url);
gf_list_add(m_entries, ple);
m_all_dead_entries=-1;
RefreshList();
}
void Playlist::OnPlSave()
{
Bool save_m3u;
char szPath[GF_MAX_PATH];
if (!gf_list_count(m_entries)) return;
CFileDialog fd(FALSE,NULL,NULL, OFN_OVERWRITEPROMPT, "M3U Playlists|*.m3u|ShoutCast Playlists|*.pls|");
if (fd.DoModal() != IDOK) return;
strcpy(szPath, fd.GetPathName());
strlwr(szPath);
save_m3u = (fd.m_ofn.nFilterIndex==1) ? GF_TRUE : GF_FALSE;
if (save_m3u) {
if (!strstr(szPath, ".m3u")) {
strcpy(szPath, fd.GetPathName());
strcat(szPath, ".m3u");
} else {
strcpy(szPath, fd.GetPathName());
}
} else {
if (!strstr(szPath, ".pls")) {
strcpy(szPath, fd.GetPathName());
strcat(szPath, ".pls");
} else {
strcpy(szPath, fd.GetPathName());
}
}
Save(szPath, save_m3u);
}
void Playlist::Save(char *szPath, Bool save_m3u)
{
FILE *out = gf_fopen(szPath, "wt");
if (!save_m3u)
fprintf(out, "[playlist]\nNumberOfEntries=%d\n", gf_list_count(m_entries));
for (u32 i=0; i<gf_list_count(m_entries); i++) {
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i);
if (save_m3u) {
fprintf(out, "%s\n", ple->m_url);
} else {
fprintf(out, "File%d=%s\n", i+1, ple->m_url);
fprintf(out, "Title%d=%s\n", i+1, ple->m_disp_name);
fprintf(out, "Length%d=%d\n", i+1, ple->m_duration ? ple->m_duration : -1);
}
}
if (!save_m3u) fprintf(out, "Version=2\n");
fprintf(out, "\n");
gf_fclose(out);
}
void Playlist::OnPlOpen()
{
CFileDialog fd(TRUE,NULL,NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, "M3U & PLS Playlists|*.m3u;*.pls|M3U Playlists|*.m3u|ShoutCast Playlists|*.pls|");
if (fd.DoModal() != IDOK) return;
Clear();
OpenPlayList(fd.GetPathName());
m_cur_entry = 0;
Play();
}
void Playlist::OpenPlayList(CString fileName)
{
FILE *pl;
PLEntry *ple;
Bool load_m3u, go;
char szLine[GF_MAX_PATH], *sep;
char szPath[GF_MAX_PATH];
strcpy(szPath, fileName);
sep = strrchr(szPath, '\\');
if (sep) sep[1] = 0;
else szPath[0] = 0;
pl = gf_fopen(fileName, "rt");
if (!pl) return;
ple = NULL;
load_m3u = GF_TRUE;
while (!feof(pl)) {
fgets(szLine, GF_MAX_PATH, pl);
go = GF_TRUE;
while (go) {
switch (szLine[strlen(szLine)-1]) {
case '\n':
case '\r':
case ' ':
szLine[strlen(szLine)-1] = 0;
break;
default:
go = GF_FALSE;
break;
}
}
if (!strlen(szLine)) continue;
if (!stricmp(szLine, "[playlist]")) {
load_m3u = GF_FALSE;
} else if (load_m3u) {
ple = new PLEntry(szLine, szPath);
gf_list_add(m_entries, ple);
} else if (!strnicmp(szLine, "file", 4)) {
char *st = strchr(szLine, '=');
if (!st) ple = NULL;
else {
ple = new PLEntry(st + 1, szPath);
gf_list_add(m_entries, ple);
}
} else if (ple && !strnicmp(szLine, "Length", 6)) {
char *st = strchr(szLine, '=');
s32 d = atoi(st + 1);
if (d>0) ple->m_duration = d;
} else if (ple && !strnicmp(szLine, "Title", 5)) {
char *st = strchr(szLine, '=');
gf_free(ple->m_disp_name);
ple->m_disp_name = gf_strdup(st + 6);
}
}
gf_fclose(pl);
m_all_dead_entries=-1;
m_cur_entry = -1;
RefreshList();
}
void Playlist::OnRclickFilelist(NMHDR* pNMHDR, LRESULT* pResult)
{
if (!m_FileList.GetItemCount()) return;
CMenu *pPopup = new CMenu();
pPopup->CreatePopupMenu();
if (m_FileList.GetSelectedCount()==1) {
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_PLAY, "Play");
pPopup->AppendMenu(MF_SEPARATOR, 0, "");
}
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_SEL_REV, "Inverse Selection");
if (m_FileList.GetSelectedCount()) pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_REM_FILE, "Remove File(s)");
if (m_FileList.GetItemCount()>1) {
pPopup->AppendMenu(MF_SEPARATOR, 0, "");
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_SORT_TITLE, "Sort By Title");
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_SORT_FILE, "Sort By File Name");
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_SORT_DUR, "Sort By Duration");
pPopup->AppendMenu(MF_SEPARATOR, 0, "");
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_SORT_REV, "Reverse List");
pPopup->AppendMenu(MF_STRING | MF_ENABLED, ID_PL_RANDOM, "Randomize");
}
POINT pt;
GetCursorPos(&pt);
pPopup->TrackPopupMenu(TPM_RIGHTBUTTON, pt.x, pt.y, this);
delete pPopup;
*pResult = 0;
}
void Playlist::OnReverseSelection()
{
u32 i;
POSITION pos = m_FileList.GetFirstSelectedItemPosition();
while (pos != NULL) {
int nItem = m_FileList.GetNextSelectedItem(pos);
PLEntry *ple = (PLEntry *) m_FileList.GetItemData(nItem);
ple->m_bIsSelected = GF_TRUE;
}
for (i=0; i<gf_list_count(m_entries); i++) {
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i);
ple->m_bIsSelected = (Bool) !ple->m_bIsSelected;
}
RefreshList();
}
void Playlist::OnReverseList()
{
u32 count = gf_list_count(m_entries);
u32 hcount = count / 2;
count--;
for (u32 i=0; i<hcount; i++) {
PLEntry *ple1 = (PLEntry *) gf_list_get(m_entries, i);
PLEntry *ple2 = (PLEntry *) gf_list_get(m_entries, count-i);
gf_list_rem(m_entries, i);
gf_list_insert(m_entries, ple2, i);
gf_list_rem(m_entries, count-i);
gf_list_insert(m_entries, ple1, count-i);
}
RefreshList();
}
void Playlist::OnRandomize()
{
GF_List *new_entries = gf_list_new();
gf_rand_init(GF_FALSE);
while (gf_list_count(m_entries)>1) {
u32 pos = gf_rand() % (gf_list_count(m_entries)-1);
PLEntry *ple = (PLEntry *)gf_list_get(m_entries, pos);
gf_list_rem(m_entries, pos);
gf_list_add(new_entries, ple);
}
PLEntry *ple = (PLEntry *)gf_list_get(m_entries, 0);
gf_list_rem(m_entries, 0);
gf_list_add(new_entries, ple);
gf_list_del(m_entries);
m_entries = new_entries;
m_cur_entry = -1;
RefreshList();
}
void Playlist::Sort(u32 type)
{
u32 i, j, smallest;
if (gf_list_count(m_entries)<=1) return;
for (i=0; i<gf_list_count(m_entries)-1; i++) {
smallest = i;
for (j=i+1; j<gf_list_count(m_entries); j++) {
PLEntry *ple2 = (PLEntry *) gf_list_get(m_entries, smallest);
PLEntry *ple1 = (PLEntry *) gf_list_get(m_entries, j);
s32 test = 0;
switch (type) {
case 0:
test = stricmp(ple1->m_url, ple2->m_url);
break;
case 1:
test = stricmp(ple1->m_disp_name, ple2->m_disp_name);
break;
case 2:
test = ple1->m_duration - ple2->m_duration;
break;
}
if (test<0) smallest = j;
}
PLEntry *ple = (PLEntry *)gf_list_get(m_entries, smallest);
gf_list_rem(m_entries, smallest);
gf_list_insert(m_entries, ple, i);
}
m_cur_entry = -1;
RefreshList();
}
void Playlist::OnSortFile() {
Sort(0);
}
void Playlist::OnSortTitle() {
Sort(1);
}
void Playlist::OnSortDuration() {
Sort(2);
}
Bool Playlist::HasValidEntries()
{
u32 nb_dead = 0;
if (m_all_dead_entries==-1) {
for (u32 i=0; i<gf_list_count(m_entries); i++) {
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i);
ple->m_bIsPlaying = GF_FALSE;
if (ple->m_bIsDead) nb_dead ++;
}
m_all_dead_entries = (nb_dead==gf_list_count(m_entries)) ? 1 : 0;
}
if (m_all_dead_entries==1) return GF_FALSE;
return GF_TRUE;
}
void Playlist::RefreshCurrent()
{
if (m_cur_entry==-1) return;
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
if (ple && ple->m_bIsPlaying) {
ple->m_bIsPlaying = GF_FALSE;
UpdateEntry(m_cur_entry);
}
}
void Playlist::Play()
{
PLEntry *ple;
if (!HasValidEntries()) return;
RefreshCurrent();
if (m_cur_entry==-1) m_cur_entry = 0;
if (m_cur_entry >= (s32)gf_list_count(m_entries)) {
if (!GetApp()->m_Loop) return;
m_cur_entry = 0;
}
ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
assert(ple);
if (ple->m_bIsDead) {
m_cur_entry++;
Play();
} else {
char szPLE[20];
ple->m_bIsPlaying = GF_TRUE;
UpdateEntry(m_cur_entry);
sprintf(szPLE, "%d", m_cur_entry);
gf_cfg_set_key(GetApp()->m_user.config, "General", "PLEntry", szPLE);
GetApp()->m_pMainWnd->PostMessage(WM_OPENURL);
}
}
void Playlist::OnDblclkFilelist(NMHDR* pNMHDR, LRESULT* pResult)
{
POSITION pos = m_FileList.GetFirstSelectedItemPosition();
RefreshCurrent();
m_cur_entry = m_FileList.GetNextSelectedItem(pos);
Play();
*pResult = 0;
}
void Playlist::OnPlPlay()
{
POSITION pos = m_FileList.GetFirstSelectedItemPosition();
RefreshCurrent();
m_cur_entry = m_FileList.GetNextSelectedItem(pos);
Play();
}
void Playlist::Truncate()
{
while (m_cur_entry+1 < (s32)gf_list_count(m_entries)) {
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry+1);
gf_list_rem(m_entries, m_cur_entry+1);
delete ple;
}
RefreshList();
}
void Playlist::QueueURL(CString filename)
{
char *ext = (char *) strrchr(filename, '.');
if (ext && (!stricmp(ext, ".m3u") || !stricmp(ext, ".pls")) ) {
OpenPlayList(filename);
} else {
PLEntry *ple = new PLEntry(filename);
gf_list_add(m_entries, ple);
}
m_all_dead_entries=-1;
}
void Playlist::PlayNext()
{
s32 count = (s32)gf_list_count(m_entries);
RefreshCurrent();
if (1+m_cur_entry < count) {
m_cur_entry++;
Play();
} else if ((1+m_cur_entry == count) && GetApp()->m_Loop) {
m_cur_entry=0;
Play();
}
}
void Playlist::PlayPrev()
{
RefreshCurrent();
if (m_cur_entry>0) {
m_cur_entry--;
Play();
}
}
void Playlist::SetDead()
{
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
if (ple) {
ple->m_bIsDead = GF_TRUE;
UpdateEntry(m_cur_entry);
m_all_dead_entries=-1;
if (ple->m_bIsPlaying) PlayNext();
}
}
void Playlist::SetDuration(u32 duration)
{
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
if (ple) {
ple->m_duration = duration;
UpdateEntry(m_cur_entry);
}
}
CString Playlist::GetDisplayName()
{
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
if (ple) return CString(ple->m_disp_name);
return CString("");
}
CString Playlist::GetURL()
{
PLEntry *ple = (PLEntry *) gf_list_get(m_entries, m_cur_entry);
if (ple) return CString(ple->m_url);
return CString("");
}