PlayerPlaylistBar.cpp
上传用户:tangyu_668
上传日期:2014-02-27
资源大小:678k
文件大小:34k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2006 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "stdafx.h"
  22. #include <math.h>
  23. #include <afxinet.h>
  24. #include <atlrx.h>
  25. #include <atlutil.h>
  26. #include "mplayerc.h"
  27. #include "mainfrm.h"
  28. #include "....DSUtilDSUtil.h"
  29. #include "SaveTextFileDialog.h"
  30. #include ".playerplaylistbar.h"
  31. IMPLEMENT_DYNAMIC(CPlayerPlaylistBar, CSizingControlBarG)
  32. CPlayerPlaylistBar::CPlayerPlaylistBar()
  33. : m_list(0)
  34. , m_nTimeColWidth(0)
  35. {
  36. m_bDragging = FALSE;
  37. }
  38. CPlayerPlaylistBar::~CPlayerPlaylistBar()
  39. {
  40. }
  41. BOOL CPlayerPlaylistBar::Create(CWnd* pParentWnd)
  42. {
  43. if(!CSizingControlBarG::Create(_T("Playlist"), pParentWnd, 0))
  44. return FALSE;
  45. m_list.CreateEx(
  46. WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE, 
  47. WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_TABSTOP
  48. |LVS_OWNERDRAWFIXED
  49. |LVS_NOCOLUMNHEADER
  50. |LVS_EDITLABELS
  51. |LVS_REPORT|LVS_SINGLESEL|LVS_AUTOARRANGE|LVS_NOSORTHEADER, // TODO: remove LVS_SINGLESEL and implement multiple item repositioning (dragging is ready)
  52. CRect(0,0,100,100), this, IDC_PLAYLIST);
  53. m_list.SetExtendedStyle(m_list.GetExtendedStyle()|LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER);
  54. m_list.InsertColumn(COL_NAME, _T("Name"), LVCFMT_LEFT, 380);
  55. CDC* pDC = m_list.GetDC();
  56. CFont* old = pDC->SelectObject(GetFont());
  57. m_nTimeColWidth = pDC->GetTextExtent(_T("000:00:00")).cx + 5;
  58. pDC->SelectObject(old);
  59. m_list.ReleaseDC(pDC);
  60. m_list.InsertColumn(COL_TIME, _T("Time"), LVCFMT_RIGHT, m_nTimeColWidth);
  61.     m_fakeImageList.Create(1, 16, ILC_COLOR4, 10, 10);
  62. m_list.SetImageList(&m_fakeImageList, LVSIL_SMALL);
  63. return TRUE;
  64. }
  65. BOOL CPlayerPlaylistBar::PreCreateWindow(CREATESTRUCT& cs)
  66. {
  67. if(!CSizingControlBarG::PreCreateWindow(cs))
  68. return FALSE;
  69. cs.dwExStyle |= WS_EX_ACCEPTFILES;
  70. return TRUE;
  71. }
  72. BOOL CPlayerPlaylistBar::PreTranslateMessage(MSG* pMsg)
  73. {
  74. if(IsWindow(pMsg->hwnd) && IsVisible() && pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
  75. {
  76. if(IsDialogMessage(pMsg))
  77. return TRUE;
  78. }
  79. return CSizingControlBarG::PreTranslateMessage(pMsg);
  80. }
  81. bool FindFileInList(CAtlList<CString>& sl, CString fn)
  82. {
  83. bool fFound = false;
  84. POSITION pos = sl.GetHeadPosition();
  85. while(pos && !fFound) {if(!sl.GetNext(pos).CompareNoCase(fn)) fFound = true;}
  86. return(fFound);
  87. }
  88. void CPlayerPlaylistBar::AddItem(CString fn, CAtlList<CString>* subs)
  89. {
  90. CAtlList<CString> sl;
  91. sl.AddTail(fn);
  92. AddItem(sl, subs);
  93. }
  94. void CPlayerPlaylistBar::AddItem(CAtlList<CString>& fns, CAtlList<CString>* subs)
  95. {
  96. CPlaylistItem pli;
  97. POSITION pos = fns.GetHeadPosition();
  98. while(pos)
  99. {
  100. CString fn = fns.GetNext(pos);
  101. if(!fn.Trim().IsEmpty()) pli.m_fns.AddTail(fn);
  102. }
  103. if(subs)
  104. {
  105. POSITION pos = subs->GetHeadPosition();
  106. while(pos)
  107. {
  108. CString fn = subs->GetNext(pos);
  109. if(!fn.Trim().IsEmpty()) pli.m_subs.AddTail(fn);
  110. }
  111. }
  112. if(pli.m_fns.IsEmpty()) return;
  113. CString fn = pli.m_fns.GetHead();
  114. if(AfxGetAppSettings().fAutoloadAudio && fn.Find(_T("://")) < 0)
  115. {
  116. int i = fn.ReverseFind('.');
  117. if(i > 0)
  118. {
  119. CMediaFormats& mf = AfxGetAppSettings().Formats;
  120. CString ext = fn.Mid(i+1).MakeLower();
  121. if(!mf.FindExt(ext, true))
  122. {
  123. CString path = fn;
  124. path.Replace('/', '\');
  125. path = path.Left(path.ReverseFind('\')+1);
  126. WIN32_FIND_DATA fd = {0};
  127. HANDLE hFind = FindFirstFile(fn.Left(i) + _T("*.*"), &fd);
  128. if(hFind != INVALID_HANDLE_VALUE)
  129. {
  130. do
  131. {
  132. if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
  133. CString fullpath = path + fd.cFileName;
  134. CString ext2 = fullpath.Mid(fullpath.ReverseFind('.')+1).MakeLower();
  135. if(!FindFileInList(pli.m_fns, fullpath) && ext != ext2 
  136. && mf.FindExt(ext2, true) && mf.IsUsingEngine(fullpath, DirectShow))
  137. {
  138. pli.m_fns.AddTail(fullpath);
  139. }
  140. }
  141. while(FindNextFile(hFind, &fd));
  142. FindClose(hFind);
  143. }
  144. }
  145. }
  146. }
  147. if(AfxGetAppSettings().fAutoloadSubtitles)
  148. {
  149. CAtlArray<CString> paths;
  150. paths.Add(_T("."));
  151. paths.Add(_T(".\subtitles"));
  152. paths.Add(_T("c:\subtitles"));
  153. CAtlArray<SubFile> ret;
  154. GetSubFileNames(fn, paths, ret);
  155. for(int i = 0; i < ret.GetCount(); i++)
  156. {
  157. if(!FindFileInList(pli.m_subs, ret[i].fn))
  158. pli.m_subs.AddTail(ret[i].fn);
  159. }
  160. }
  161. m_pl.AddTail(pli);
  162. }
  163. static bool SearchFiles(CString mask, CAtlList<CString>& sl)
  164. {
  165. if(mask.Find(_T("://")) >= 0)
  166. return(false);
  167. mask.Trim();
  168. sl.RemoveAll();
  169. CMediaFormats& mf = AfxGetAppSettings().Formats;
  170. bool fFilterKnownExts;
  171. WIN32_FILE_ATTRIBUTE_DATA fad;
  172. mask = (fFilterKnownExts = (GetFileAttributesEx(mask, GetFileExInfoStandard, &fad) 
  173. && (fad.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)))
  174. ? CString(mask).TrimRight(_T("\/")) + _T("\*.*")
  175. : mask;
  176. {
  177. CString dir = mask.Left(max(mask.ReverseFind('\'), mask.ReverseFind('/'))+1);
  178. WIN32_FIND_DATA fd;
  179. HANDLE h = FindFirstFile(mask, &fd);
  180. if(h != INVALID_HANDLE_VALUE)
  181. {
  182. do
  183. {
  184. if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
  185. CString fn = fd.cFileName;
  186. CString ext = fn.Mid(fn.ReverseFind('.')+1).MakeLower();
  187. CString path = dir + fd.cFileName;
  188. if(!fFilterKnownExts || mf.FindExt(ext))
  189. sl.AddTail(path);
  190. }
  191. while(FindNextFile(h, &fd));
  192. FindClose(h);
  193. if(sl.GetCount() == 0 && mask.Find(_T(":\")) == 1)
  194. {
  195. GetCDROMType(mask[0], sl);
  196. }
  197. }
  198. }
  199. return(sl.GetCount() > 1
  200. || sl.GetCount() == 1 && sl.GetHead().CompareNoCase(mask)
  201. || sl.GetCount() == 0 && mask.FindOneOf(_T("?*")) >= 0);
  202. }
  203. void CPlayerPlaylistBar::ParsePlayList(CString fn, CAtlList<CString>* subs)
  204. {
  205. CAtlList<CString> sl;
  206. sl.AddTail(fn);
  207. ParsePlayList(sl, subs);
  208. }
  209. void CPlayerPlaylistBar::ParsePlayList(CAtlList<CString>& fns, CAtlList<CString>* subs)
  210. {
  211. if(fns.IsEmpty()) return;
  212. // resolve .lnk files
  213. CComPtr<IShellLink> pSL;
  214. pSL.CoCreateInstance(CLSID_ShellLink);
  215. CComQIPtr<IPersistFile> pPF = pSL;
  216. POSITION pos = fns.GetHeadPosition();
  217. while(pSL && pPF && pos)
  218. {
  219. CString& fn = fns.GetNext(pos);
  220. TCHAR buff[MAX_PATH];
  221. if(CPath(fn).GetExtension().MakeLower() != _T(".lnk")
  222. || FAILED(pPF->Load(CStringW(fn), STGM_READ))
  223. || FAILED(pSL->Resolve(NULL, SLR_ANY_MATCH|SLR_NO_UI))
  224. || FAILED(pSL->GetPath(buff, countof(buff), NULL, 0)))
  225. continue;
  226. fn = buff;
  227. }
  228. //
  229. CAtlList<CString> sl;
  230. if(SearchFiles(fns.GetHead(), sl))
  231. {
  232. if(sl.GetCount() > 1) subs = NULL;
  233. POSITION pos = sl.GetHeadPosition();
  234. while(pos) ParsePlayList(sl.GetNext(pos), subs);
  235. return;
  236. }
  237. CAtlList<CString> redir;
  238. CStringA ct = GetContentType(fns.GetHead(), &redir);
  239. if(!redir.IsEmpty())
  240. {
  241. POSITION pos = redir.GetHeadPosition();
  242. while(pos) ParsePlayList(sl.GetNext(pos), subs);
  243. return;
  244. }
  245. if(ct == "application/x-mpc-playlist")
  246. {
  247. ParseMPCPlayList(fns.GetHead());
  248. return;
  249. }
  250. AddItem(fns, subs);
  251. }
  252. static int s_int_comp(const void* i1, const void* i2)
  253. {
  254. return (int)i1 - (int)i2;
  255. }
  256. static CString CombinePath(CPath p, CString fn)
  257. {
  258. if(fn.Find(':') >= 0 || fn.Find(_T("\")) == 0) return fn;
  259. p.Append(CPath(fn));
  260. return (LPCTSTR)p;
  261. }
  262. bool CPlayerPlaylistBar::ParseMPCPlayList(CString fn)
  263. {
  264. CString str;
  265. CAtlMap<int, CPlaylistItem> pli;
  266. CAtlArray<int> idx;
  267. CWebTextFile f;
  268. if(!f.Open(fn) || !f.ReadString(str) || str != _T("MPCPLAYLIST"))
  269. return false;
  270. if(f.GetEncoding() == CTextFile::ASCII) 
  271. f.SetEncoding(CTextFile::ANSI);
  272. CPath base(fn);
  273. base.RemoveFileSpec();
  274. while(f.ReadString(str))
  275. {
  276. CAtlList<CString> sl;
  277. Explode(str, sl, ',', 3);
  278. if(sl.GetCount() != 3) continue;
  279. if(int i = _ttoi(sl.RemoveHead()))
  280. {
  281. CString key = sl.RemoveHead();
  282. CString value = sl.RemoveHead();
  283. if(key == _T("type")) {pli[i].m_type = (CPlaylistItem::type_t)_ttol(value); idx.Add(i);}
  284. else if(key == _T("label")) pli[i].m_label = value;
  285. else if(key == _T("filename")) {value = CombinePath(base, value); pli[i].m_fns.AddTail(value);}
  286. else if(key == _T("subtitle")) {value = CombinePath(base, value); pli[i].m_subs.AddTail(value);}
  287. else if(key == _T("video")) {while(pli[i].m_fns.GetCount() < 2) pli[i].m_fns.AddTail(_T("")); pli[i].m_fns.GetHead() = value;}
  288. else if(key == _T("audio")) {while(pli[i].m_fns.GetCount() < 2) pli[i].m_fns.AddTail(_T("")); pli[i].m_fns.GetTail() = value;}
  289. else if(key == _T("vinput")) pli[i].m_vinput = _ttol(value);
  290. else if(key == _T("vchannel")) pli[i].m_vchannel = _ttol(value);
  291. else if(key == _T("ainput")) pli[i].m_ainput = _ttol(value);
  292. else if(key == _T("country")) pli[i].m_country = _ttol(value);
  293. }
  294. }
  295. qsort(idx.GetData(), idx.GetCount(), sizeof(int), s_int_comp);
  296. for(int i = 0; i < idx.GetCount(); i++)
  297. m_pl.AddTail(pli[idx[i]]);
  298. return pli.GetCount() > 0;
  299. }
  300. bool CPlayerPlaylistBar::SaveMPCPlayList(CString fn, CTextFile::enc e, bool fRemovePath)
  301. {
  302. CTextFile f;
  303. if(!f.Save(fn, e))
  304. return false;
  305. f.WriteString(_T("MPCPLAYLISTn"));
  306. POSITION pos = m_pl.GetHeadPosition(), pos2;
  307. for(int i = 1; pos; i++)
  308. {
  309. CPlaylistItem& pli = m_pl.GetNext(pos);
  310. CString idx;
  311. idx.Format(_T("%d"), i);
  312. CString str;
  313. str.Format(_T("%d,type,%d"), i, pli.m_type);
  314. f.WriteString(str + _T("n"));
  315. if(!pli.m_label.IsEmpty()) 
  316. f.WriteString(idx + _T(",label,") + pli.m_label + _T("n"));
  317. if(pli.m_type == CPlaylistItem::file)
  318. {
  319. pos2 = pli.m_fns.GetHeadPosition();
  320. while(pos2)
  321. {
  322. CString fn = pli.m_fns.GetNext(pos2);
  323. if(fRemovePath) {CPath p(fn); p.StripPath(); fn = (LPCTSTR)p;}
  324. f.WriteString(idx + _T(",filename,") + fn + _T("n"));
  325. }
  326. pos2 = pli.m_subs.GetHeadPosition();
  327. while(pos2)
  328. {
  329. CString fn = pli.m_subs.GetNext(pos2);
  330. if(fRemovePath) {CPath p(fn); p.StripPath(); fn = (LPCTSTR)p;}
  331. f.WriteString(idx + _T(",subtitle,") + fn + _T("n"));
  332. }
  333. }
  334. else if(pli.m_type == CPlaylistItem::device && pli.m_fns.GetCount() == 2)
  335. {
  336. f.WriteString(idx + _T(",video,") + pli.m_fns.GetHead() + _T("n"));
  337. f.WriteString(idx + _T(",audio,") + pli.m_fns.GetTail() + _T("n"));
  338. str.Format(_T("%d,vinput,%d"), i, pli.m_vinput);
  339. f.WriteString(str + _T("n"));
  340. str.Format(_T("%d,vchannel,%d"), i, pli.m_vchannel);
  341. f.WriteString(str + _T("n"));
  342. str.Format(_T("%d,ainput,%d"), i, pli.m_ainput);
  343. f.WriteString(str + _T("n"));
  344. str.Format(_T("%d,country,%d"), i, pli.m_country);
  345. f.WriteString(str + _T("n"));
  346. }
  347. }
  348. return true;
  349. }
  350. void CPlayerPlaylistBar::Refresh()
  351. {
  352. SetupList();
  353. ResizeListColumn();
  354. }
  355. void CPlayerPlaylistBar::Empty()
  356. {
  357. m_pl.RemoveAll();
  358. m_list.DeleteAllItems();
  359. SavePlaylist();
  360. }
  361. void CPlayerPlaylistBar::Open(CAtlList<CString>& fns, bool fMulti, CAtlList<CString>* subs)
  362. {
  363. Empty();
  364. Append(fns, fMulti, subs);
  365. }
  366. void CPlayerPlaylistBar::Append(CAtlList<CString>& fns, bool fMulti, CAtlList<CString>* subs)
  367. {
  368. if(fMulti)
  369. {
  370. ASSERT(subs == NULL || subs->GetCount() == 0);
  371. POSITION pos = fns.GetHeadPosition();
  372. while(pos) ParsePlayList(fns.GetNext(pos), NULL);
  373. }
  374. else
  375. {
  376. ParsePlayList(fns, subs);
  377. }
  378. Refresh();
  379. SavePlaylist();
  380. }
  381. void CPlayerPlaylistBar::Open(CStringW vdn, CStringW adn, int vinput, int vchannel, int ainput)
  382. {
  383. Empty();
  384. Append(vdn, adn, vinput, vchannel, ainput);
  385. }
  386. void CPlayerPlaylistBar::Append(CStringW vdn, CStringW adn, int vinput, int vchannel, int ainput)
  387. {
  388. CPlaylistItem pli;
  389. pli.m_type = CPlaylistItem::device;
  390. pli.m_fns.AddTail(CString(vdn));
  391. pli.m_fns.AddTail(CString(adn));
  392. pli.m_vinput = vinput;
  393. pli.m_vchannel = vchannel;
  394. pli.m_ainput = ainput;
  395. CAtlList<CStringW> sl;
  396. CStringW vfn = GetFriendlyName(vdn);
  397. CStringW afn = GetFriendlyName(adn);
  398. if(!vfn.IsEmpty()) sl.AddTail(vfn);
  399. if(!afn.IsEmpty()) sl.AddTail(afn);
  400. CStringW label = Implode(sl, '|');
  401. label.Replace(L"|", L" - ");
  402. pli.m_label = CString(label);
  403. m_pl.AddTail(pli);
  404. Refresh();
  405. SavePlaylist();
  406. }
  407. void CPlayerPlaylistBar::SetupList()
  408. {
  409. m_list.DeleteAllItems();
  410. POSITION pos = m_pl.GetHeadPosition();
  411. for(int i = 0; pos; i++)
  412. {
  413. CPlaylistItem& pli = m_pl.GetAt(pos);
  414. m_list.SetItemData(m_list.InsertItem(i, pli.GetLabel()), (DWORD_PTR)pos);
  415. m_list.SetItemText(i, COL_TIME, pli.GetLabel(1));
  416. m_pl.GetNext(pos);
  417. }
  418. }
  419. void CPlayerPlaylistBar::UpdateList()
  420. {
  421. POSITION pos = m_pl.GetHeadPosition();
  422. for(int i = 0, j = m_list.GetItemCount(); pos && i < j; i++)
  423. {
  424. CPlaylistItem& pli = m_pl.GetAt(pos);
  425. m_list.SetItemData(i, (DWORD_PTR)pos);
  426. m_list.SetItemText(i, COL_NAME, pli.GetLabel(0));
  427. m_list.SetItemText(i, COL_TIME, pli.GetLabel(1));
  428. m_pl.GetNext(pos);
  429. }
  430. }
  431. void CPlayerPlaylistBar::EnsureVisible(POSITION pos)
  432. {
  433. int i = FindItem(m_pl.GetPos());
  434. if(i < 0) return;
  435. m_list.EnsureVisible(i, TRUE);
  436. m_list.Invalidate();
  437. }
  438. int CPlayerPlaylistBar::FindItem(POSITION pos)
  439. {
  440. for(int i = 0; i < m_list.GetItemCount(); i++)
  441. if((POSITION)m_list.GetItemData(i) == pos)
  442. return(i);
  443. return(-1);
  444. }
  445. POSITION CPlayerPlaylistBar::FindPos(int i)
  446. {
  447. if(i < 0) return(NULL);
  448. return((POSITION)m_list.GetItemData(i));
  449. }
  450. int CPlayerPlaylistBar::GetCount()
  451. {
  452. return(m_pl.GetCount()); // TODO: n - .fInvalid
  453. }
  454. int CPlayerPlaylistBar::GetSelIdx()
  455. {
  456. return(FindItem(m_pl.GetPos()));
  457. }
  458. void CPlayerPlaylistBar::SetSelIdx(int i)
  459. {
  460. m_pl.SetPos(FindPos(i));
  461. }
  462. bool CPlayerPlaylistBar::IsAtEnd()
  463. {
  464. return(m_pl.GetPos() && m_pl.GetPos() == m_pl.GetTailPosition());
  465. }
  466. bool CPlayerPlaylistBar::GetCur(CPlaylistItem& pli)
  467. {
  468. if(!m_pl.GetPos()) return(false);
  469. pli = m_pl.GetAt(m_pl.GetPos());
  470. return(true);
  471. }
  472. CString CPlayerPlaylistBar::GetCur()
  473. {
  474. CString fn;
  475. CPlaylistItem pli;
  476. if(GetCur(pli) && !pli.m_fns.IsEmpty()) fn = pli.m_fns.GetHead();
  477. return(fn);
  478. }
  479. void CPlayerPlaylistBar::SetNext()
  480. {
  481. POSITION pos = m_pl.GetPos(), org = pos;
  482. while(m_pl.GetNextWrap(pos).m_fInvalid && pos != org);
  483. UpdateList();
  484. m_pl.SetPos(pos);
  485. EnsureVisible(pos);
  486. }
  487. void CPlayerPlaylistBar::SetPrev()
  488. {
  489. POSITION pos = m_pl.GetPos(), org = pos;
  490. while(m_pl.GetPrevWrap(pos).m_fInvalid && pos != org);
  491. m_pl.SetPos(pos);
  492. EnsureVisible(pos);
  493. }
  494. void CPlayerPlaylistBar::SetFirst()
  495. {
  496. POSITION pos = m_pl.GetTailPosition(), org = pos;
  497. while(m_pl.GetNextWrap(pos).m_fInvalid && pos != org);
  498. UpdateList();
  499. m_pl.SetPos(pos);
  500. EnsureVisible(pos);
  501. }
  502. void CPlayerPlaylistBar::SetLast()
  503. {
  504. POSITION pos = m_pl.GetHeadPosition(), org = pos;
  505. while(m_pl.GetPrevWrap(pos).m_fInvalid && pos != org);
  506. m_pl.SetPos(pos);
  507. EnsureVisible(pos);
  508. }
  509. void CPlayerPlaylistBar::SetCurValid(bool fValid)
  510. {
  511. if(POSITION pos = m_pl.GetPos())
  512. {
  513. if(m_pl.GetAt(pos).m_fInvalid = !fValid)
  514. {
  515. int i = FindItem(pos);
  516. m_list.RedrawItems(i, i);
  517. }
  518. }
  519. }
  520. void CPlayerPlaylistBar::SetCurTime(REFERENCE_TIME rt)
  521. {
  522. if(POSITION pos = m_pl.GetPos())
  523. {
  524. CPlaylistItem& pli = m_pl.GetAt(pos);
  525. pli.m_duration = rt;
  526. m_list.SetItemText(FindItem(pos), COL_TIME, pli.GetLabel(1));
  527. }
  528. }
  529. OpenMediaData* CPlayerPlaylistBar::GetCurOMD(REFERENCE_TIME rtStart)
  530. {
  531. CPlaylistItem pli;
  532. if(!GetCur(pli)) return NULL;
  533. CString fn = CString(pli.m_fns.GetHead()).MakeLower();
  534. if(fn.Find(_T("video_ts.ifo")) >= 0
  535. || fn.Find(_T(".ratdvd")) >= 0)
  536. {
  537. if(OpenDVDData* p = new OpenDVDData())
  538. {
  539. p->path = pli.m_fns.GetHead(); 
  540. p->subs.AddTailList(&pli.m_subs);
  541. return p;
  542. }
  543. }
  544. if(pli.m_type == CPlaylistItem::device)
  545. {
  546. if(OpenDeviceData* p = new OpenDeviceData())
  547. {
  548. POSITION pos = pli.m_fns.GetHeadPosition();
  549. for(int i = 0; i < countof(p->DisplayName) && pos; i++)
  550. p->DisplayName[i] = pli.m_fns.GetNext(pos);
  551. p->vinput = pli.m_vinput;
  552. p->vchannel = pli.m_vchannel;
  553. p->ainput = pli.m_ainput;
  554. return p;
  555. }
  556. }
  557. else
  558. {
  559. if(OpenFileData* p = new OpenFileData())
  560. {
  561. p->fns.AddTailList(&pli.m_fns);
  562. p->subs.AddTailList(&pli.m_subs);
  563. p->rtStart = rtStart;
  564. return p;
  565. }
  566. }
  567. return NULL;
  568. }
  569. void CPlayerPlaylistBar::LoadPlaylist()
  570. {
  571. CString base;
  572. if(AfxGetMyApp()->GetAppDataPath(base))
  573. {
  574. CPath p;
  575. p.Combine(base, _T("default.mpcpl"));
  576. if(!AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), TRUE))
  577. {
  578. DeleteFile(p);
  579. }
  580. else
  581. {
  582. ParseMPCPlayList(p);
  583. Refresh();
  584. }
  585. }
  586. }
  587. void CPlayerPlaylistBar::SavePlaylist()
  588. {
  589. CString base;
  590. if(AfxGetMyApp()->GetAppDataPath(base))
  591. {
  592. CPath p;
  593. p.Combine(base, _T("default.mpcpl"));
  594. if(!AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), TRUE))
  595. {
  596. DeleteFile(p);
  597. }
  598. else
  599. {
  600. SaveMPCPlayList(p, CTextFile::UTF8, false);
  601. }
  602. }
  603. }
  604. BEGIN_MESSAGE_MAP(CPlayerPlaylistBar, CSizingControlBarG)
  605. ON_WM_SIZE()
  606. ON_NOTIFY(LVN_KEYDOWN, IDC_PLAYLIST, OnLvnKeyDown)
  607. ON_NOTIFY(NM_DBLCLK, IDC_PLAYLIST, OnNMDblclkList)
  608. // ON_NOTIFY(NM_CUSTOMDRAW, IDC_PLAYLIST, OnCustomdrawList)
  609. ON_WM_DRAWITEM()
  610. ON_COMMAND_EX(ID_FILE_CLOSEPLAYLIST, OnFileClosePlaylist)
  611. ON_COMMAND_EX(ID_PLAY_PLAY, OnPlayPlay)
  612. ON_WM_DROPFILES()
  613. ON_NOTIFY(LVN_BEGINDRAG, IDC_PLAYLIST, OnBeginDrag)
  614. ON_WM_MOUSEMOVE()
  615. ON_WM_LBUTTONUP()
  616. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
  617. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
  618. ON_WM_TIMER()
  619. ON_WM_CONTEXTMENU()
  620. ON_NOTIFY(LVN_ENDLABELEDIT, IDC_PLAYLIST, OnLvnEndlabeleditList)
  621. END_MESSAGE_MAP()
  622. // CPlayerPlaylistBar message handlers
  623. void CPlayerPlaylistBar::ResizeListColumn()
  624. {
  625. if(::IsWindow(m_list.m_hWnd))
  626. {
  627. CRect r;
  628. GetClientRect(r);
  629. r.DeflateRect(2, 2);
  630. m_list.SetRedraw(FALSE);
  631. m_list.MoveWindow(r);
  632. m_list.GetClientRect(r);
  633. m_list.SetColumnWidth(COL_NAME, r.Width()-m_nTimeColWidth); //LVSCW_AUTOSIZE_USEHEADER
  634. m_list.SetRedraw(TRUE);
  635. }
  636. }
  637. void CPlayerPlaylistBar::OnSize(UINT nType, int cx, int cy)
  638. {
  639. CSizingControlBarG::OnSize(nType, cx, cy);
  640. ResizeListColumn();
  641. }
  642. void CPlayerPlaylistBar::OnLvnKeyDown(NMHDR* pNMHDR, LRESULT* pResult) 
  643. {
  644. LPNMLVKEYDOWN pLVKeyDown = reinterpret_cast<LPNMLVKEYDOWN>(pNMHDR);
  645. *pResult = FALSE;
  646. CList<int> items;
  647. POSITION pos = m_list.GetFirstSelectedItemPosition();
  648. while(pos) items.AddHead(m_list.GetNextSelectedItem(pos));
  649. if(pLVKeyDown->wVKey == VK_DELETE && items.GetCount() > 0) 
  650. {
  651. pos = items.GetHeadPosition();
  652. while(pos) 
  653. {
  654. int i = items.GetNext(pos);
  655. if(m_pl.RemoveAt(FindPos(i))) ((CMainFrame*)AfxGetMainWnd())->CloseMedia();
  656. m_list.DeleteItem(i);
  657. }
  658. m_list.SetItemState(-1, 0, LVIS_SELECTED);
  659. m_list.SetItemState(
  660. max(min(items.GetTail(), m_list.GetItemCount()-1), 0), 
  661. LVIS_SELECTED, LVIS_SELECTED);
  662. ResizeListColumn();
  663. *pResult = TRUE;
  664. }
  665. else if(pLVKeyDown->wVKey == VK_SPACE && items.GetCount() == 1) 
  666. {
  667. m_pl.SetPos(FindPos(items.GetHead()));
  668. ((CMainFrame*)AfxGetMainWnd())->OpenCurPlaylistItem();
  669. *pResult = TRUE;
  670. }
  671. }
  672. void CPlayerPlaylistBar::OnNMDblclkList(NMHDR* pNMHDR, LRESULT* pResult)
  673. {
  674. LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)pNMHDR;
  675. if(lpnmlv->iItem >= 0 && lpnmlv->iSubItem >= 0)
  676. {
  677. m_pl.SetPos(FindPos(lpnmlv->iItem));
  678. m_list.Invalidate();
  679. ((CMainFrame*)AfxGetMainWnd())->OpenCurPlaylistItem();
  680. }
  681. *pResult = 0;
  682. }
  683. /*
  684. void CPlayerPlaylistBar::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
  685. {
  686. NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
  687. *pResult = CDRF_DODEFAULT;
  688. if(CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage)
  689. {
  690. *pResult = CDRF_NOTIFYPOSTPAINT|CDRF_NOTIFYITEMDRAW;
  691. }
  692. else if(CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage)
  693. {
  694. pLVCD->nmcd.uItemState &= ~CDIS_SELECTED;
  695. pLVCD->nmcd.uItemState &= ~CDIS_FOCUS;
  696. pLVCD->clrText = (pLVCD->nmcd.dwItemSpec == m_playList.m_idx) ? 0x0000ff : CLR_DEFAULT;
  697. pLVCD->clrTextBk = m_list.GetItemState(pLVCD->nmcd.dwItemSpec, LVIS_SELECTED) ? 0xf1dacc : CLR_DEFAULT;
  698. *pResult = CDRF_NOTIFYPOSTPAINT;
  699. }
  700. else if(CDDS_ITEMPOSTPAINT == pLVCD->nmcd.dwDrawStage)
  701. {
  702.         int nItem = static_cast<int>(pLVCD->nmcd.dwItemSpec);
  703. if(m_list.GetItemState(pLVCD->nmcd.dwItemSpec, LVIS_SELECTED))
  704. {
  705. CRect r, r2;
  706. m_list.GetItemRect(nItem, &r, LVIR_BOUNDS);
  707. m_list.GetItemRect(nItem, &r2, LVIR_LABEL);
  708. r.left = r2.left;
  709. FrameRect(pLVCD->nmcd.hdc, &r, CBrush(0xc56a31));
  710. }
  711. *pResult = CDRF_SKIPDEFAULT;
  712. }
  713. else if(CDDS_POSTPAINT == pLVCD->nmcd.dwDrawStage)
  714. {
  715. }
  716. }
  717. */
  718. void CPlayerPlaylistBar::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
  719. {
  720. if(nIDCtl != IDC_PLAYLIST) return;
  721. int nItem = lpDrawItemStruct->itemID;
  722. CRect rcItem = lpDrawItemStruct->rcItem;
  723. POSITION pos = FindPos(nItem);
  724. bool fSelected = pos == m_pl.GetPos();
  725. CPlaylistItem& pli = m_pl.GetAt(pos);
  726. CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  727. if(!!m_list.GetItemState(nItem, LVIS_SELECTED))
  728. {
  729. FillRect(pDC->m_hDC, rcItem, CBrush(0xf1dacc));
  730. FrameRect(pDC->m_hDC, rcItem, CBrush(0xc56a31));
  731. }
  732. else
  733. {
  734. FillRect(pDC->m_hDC, rcItem, CBrush(GetSysColor(COLOR_WINDOW)));
  735. }
  736. COLORREF textcolor = fSelected?0xff:0;
  737. if(pli.m_fInvalid) textcolor |= 0xA0A0A0;
  738. CString time = !pli.m_fInvalid ? m_list.GetItemText(nItem, COL_TIME) : _T("Invalid");
  739. CSize timesize(0, 0);
  740. CPoint timept(rcItem.right, 0);
  741. if(time.GetLength() > 0)
  742. {
  743. timesize = pDC->GetTextExtent(time);
  744. if((3+timesize.cx+3) < rcItem.Width()/2)
  745. {
  746. timept = CPoint(rcItem.right-(3+timesize.cx+3), (rcItem.top+rcItem.bottom-timesize.cy)/2);
  747. pDC->SetTextColor(textcolor);
  748. pDC->TextOut(timept.x, timept.y, time);
  749. }
  750. }
  751. CString fmt, file;
  752. fmt.Format(_T("%%0%dd. %%s"), (int)log10(0.1+m_pl.GetCount())+1);
  753. file.Format(fmt, nItem+1, m_list.GetItemText(nItem, COL_NAME));
  754. CSize filesize = pDC->GetTextExtent(file);
  755. while(3+filesize.cx+6 > timept.x && file.GetLength() > 3)
  756. {
  757. file = file.Left(file.GetLength()-4) + _T("...");
  758. filesize = pDC->GetTextExtent(file);
  759. }
  760. if(file.GetLength() > 3)
  761. {
  762. pDC->SetTextColor(textcolor);
  763. pDC->TextOut(rcItem.left+3, (rcItem.top+rcItem.bottom-filesize.cy)/2, file);
  764. }
  765. }
  766. BOOL CPlayerPlaylistBar::OnFileClosePlaylist(UINT nID)
  767. {
  768. Empty();
  769. return FALSE;
  770. }
  771. BOOL CPlayerPlaylistBar::OnPlayPlay(UINT nID)
  772. {
  773. m_list.Invalidate();
  774. return FALSE;
  775. }
  776. void CPlayerPlaylistBar::OnDropFiles(HDROP hDropInfo)
  777. {
  778. SetActiveWindow();
  779. CAtlList<CString> sl;
  780. UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
  781. for(UINT iFile = 0; iFile < nFiles; iFile++)
  782. {
  783. TCHAR szFileName[_MAX_PATH];
  784. ::DragQueryFile(hDropInfo, iFile, szFileName, _MAX_PATH);
  785. sl.AddTail(szFileName);
  786. }
  787. ::DragFinish(hDropInfo);
  788. Append(sl, true);
  789. }
  790. void CPlayerPlaylistBar::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult)
  791. {
  792. ModifyStyle(WS_EX_ACCEPTFILES, 0);
  793. m_nDragIndex = ((LPNMLISTVIEW)pNMHDR)->iItem;
  794. CPoint p(0, 0);
  795. m_pDragImage = m_list.CreateDragImageEx(&p);
  796. CPoint p2 = ((LPNMLISTVIEW)pNMHDR)->ptAction;
  797. m_pDragImage->BeginDrag(0, p2 - p);
  798. m_pDragImage->DragEnter(GetDesktopWindow(), ((LPNMLISTVIEW)pNMHDR)->ptAction);
  799. m_bDragging = TRUE;
  800. m_nDropIndex = -1;
  801. SetCapture();
  802. }
  803. void CPlayerPlaylistBar::OnMouseMove(UINT nFlags, CPoint point)
  804. {
  805. if(m_bDragging)
  806. {
  807. m_ptDropPoint = point;
  808. ClientToScreen(&m_ptDropPoint);
  809. m_pDragImage->DragMove(m_ptDropPoint);
  810. m_pDragImage->DragShowNolock(FALSE);
  811. WindowFromPoint(m_ptDropPoint)->ScreenToClient(&m_ptDropPoint);
  812. m_pDragImage->DragShowNolock(TRUE);
  813. {
  814. int iOverItem = m_list.HitTest(m_ptDropPoint);
  815. int iTopItem = m_list.GetTopIndex();
  816. int iBottomItem = m_list.GetBottomIndex();
  817. if(iOverItem == iTopItem && iTopItem != 0) // top of list
  818. SetTimer(1, 100, NULL); 
  819. else
  820. KillTimer(1); 
  821. if(iOverItem >= iBottomItem && iBottomItem != (m_list.GetItemCount() - 1)) // bottom of list
  822. SetTimer(2, 100, NULL); 
  823. else 
  824. KillTimer(2); 
  825. }
  826. }
  827. __super::OnMouseMove(nFlags, point);
  828. }
  829. void CPlayerPlaylistBar::OnTimer(UINT nIDEvent)
  830. {
  831. int iTopItem = m_list.GetTopIndex();
  832. int iBottomItem = iTopItem + m_list.GetCountPerPage() - 1;
  833. if(m_bDragging)
  834. {
  835. m_pDragImage->DragShowNolock(FALSE);
  836. if(nIDEvent == 1)
  837. {
  838. m_list.EnsureVisible(iTopItem - 1, false);
  839. m_list.UpdateWindow();
  840. if(m_list.GetTopIndex() == 0) KillTimer(1); 
  841. }
  842. else if(nIDEvent == 2)
  843. {
  844. m_list.EnsureVisible(iBottomItem + 1, false);
  845. m_list.UpdateWindow();
  846. if(m_list.GetBottomIndex() == (m_list.GetItemCount() - 1)) KillTimer(2); 
  847. m_pDragImage->DragShowNolock(TRUE);
  848. }
  849. __super::OnTimer(nIDEvent);
  850. }
  851. void CPlayerPlaylistBar::OnLButtonUp(UINT nFlags, CPoint point)
  852. {
  853. if(m_bDragging)
  854. {
  855. ::ReleaseCapture();
  856. m_bDragging = FALSE;
  857. m_pDragImage->DragLeave(GetDesktopWindow());
  858. m_pDragImage->EndDrag();
  859. delete m_pDragImage;
  860. m_pDragImage = NULL;
  861. KillTimer(1);
  862. KillTimer(2);
  863. CPoint pt(point);
  864. ClientToScreen(&pt);
  865. if(WindowFromPoint(pt) == &m_list)
  866. DropItemOnList();
  867. }
  868. ModifyStyle(0, WS_EX_ACCEPTFILES); 
  869. __super::OnLButtonUp(nFlags, point);
  870. }
  871. void CPlayerPlaylistBar::DropItemOnList()
  872. {
  873. m_ptDropPoint.y += 10; //
  874. m_nDropIndex = m_list.HitTest(CPoint(10, m_ptDropPoint.y));
  875. TCHAR szLabel[MAX_PATH];
  876. LV_ITEM lvi;
  877. ZeroMemory(&lvi, sizeof(LV_ITEM));
  878. lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
  879. lvi.stateMask = LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED;
  880. lvi.pszText = szLabel;
  881. lvi.iItem = m_nDragIndex;
  882. lvi.cchTextMax = MAX_PATH;
  883. m_list.GetItem(&lvi);
  884. if(m_nDropIndex < 0) m_nDropIndex = m_list.GetItemCount();
  885. lvi.iItem = m_nDropIndex;
  886. m_list.InsertItem(&lvi);
  887. CHeaderCtrl* pHeader = (CHeaderCtrl*)m_list.GetDlgItem(0);
  888. int nColumnCount = pHeader->GetItemCount();
  889. lvi.mask = LVIF_TEXT;
  890. lvi.iItem = m_nDropIndex;
  891. //INDEX OF DRAGGED ITEM WILL CHANGE IF ITEM IS DROPPED ABOVE ITSELF
  892. if(m_nDropIndex < m_nDragIndex) m_nDragIndex++;
  893. for(int col=1; col < nColumnCount; col++)
  894. {
  895. _tcscpy(lvi.pszText, (LPCTSTR)(m_list.GetItemText(m_nDragIndex, col)));
  896. lvi.iSubItem = col;
  897. m_list.SetItem(&lvi);
  898. }
  899. m_list.DeleteItem(m_nDragIndex);
  900. CList<CPlaylistItem> tmp;
  901. UINT id = -1;
  902. for(int i = 0; i < m_list.GetItemCount(); i++)
  903. {
  904. POSITION pos = (POSITION)m_list.GetItemData(i);
  905. CPlaylistItem& pli = m_pl.GetAt(pos);
  906. tmp.AddTail(pli);
  907. if(pos == m_pl.GetPos()) id = pli.m_id;
  908. }
  909. m_pl.RemoveAll();
  910. POSITION pos = tmp.GetHeadPosition();
  911. for(int i = 0; pos; i++)
  912. {
  913. CPlaylistItem& pli = tmp.GetNext(pos);
  914. m_pl.AddTail(pli);
  915. if(pli.m_id == id) m_pl.SetPos(m_pl.GetTailPosition());
  916. m_list.SetItemData(i, (DWORD_PTR)m_pl.GetTailPosition());
  917. }
  918. ResizeListColumn();
  919. }
  920. BOOL CPlayerPlaylistBar::OnToolTipNotify(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
  921. {
  922. TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
  923. TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
  924. if((pNMHDR->code == TTN_NEEDTEXTA && (HWND)pTTTA->lParam != m_list.m_hWnd)
  925. || (pNMHDR->code == TTN_NEEDTEXTW && (HWND)pTTTW->lParam != m_list.m_hWnd))
  926. return FALSE;
  927. int row = ((pNMHDR->idFrom-1) >> 10) & 0x3fffff;
  928. int col = (pNMHDR->idFrom-1) & 0x3ff;
  929. if(row < 0 || row >= m_pl.GetCount())
  930. return FALSE;
  931. CPlaylistItem& pli = m_pl.GetAt(FindPos(row));
  932. CString strTipText;
  933. if(col == COL_NAME)
  934. {
  935. POSITION pos = pli.m_fns.GetHeadPosition();
  936. while(pos) strTipText += _T("n") + pli.m_fns.GetNext(pos);
  937. strTipText.Trim();
  938. if(pli.m_type == CPlaylistItem::device)
  939. {
  940. CString str;
  941. str.Format(_T("Video Input %d"), pli.m_vinput);
  942. if(pli.m_vinput >= 0) strTipText += _T("n") + str;
  943. str.Format(_T("Video Channel %d"), pli.m_vchannel);
  944. if(pli.m_vchannel >= 0) strTipText += _T("n") + str;
  945. str.Format(_T("Audio Input %d"), pli.m_ainput);
  946. if(pli.m_ainput >= 0) strTipText += _T("n") + str;
  947. }
  948. ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, (LPARAM)(INT)1000);
  949. }
  950. else if(col == COL_TIME)
  951. {
  952. return FALSE;
  953. }
  954. static CStringA m_strTipTextA;
  955. static CStringW m_strTipTextW;
  956. if(pNMHDR->code == TTN_NEEDTEXTA)
  957. {
  958. m_strTipTextA = strTipText;
  959. pTTTA->lpszText = (LPSTR)(LPCSTR)m_strTipTextA;
  960. }
  961. else
  962. {
  963. m_strTipTextW = strTipText;
  964. pTTTW->lpszText = (LPWSTR)(LPCWSTR)m_strTipTextW;
  965. }
  966. *pResult = 0;
  967. return TRUE;    // message was handled
  968. }
  969. void CPlayerPlaylistBar::OnContextMenu(CWnd* /*pWnd*/, CPoint p)
  970. {
  971. LVHITTESTINFO lvhti;
  972. lvhti.pt = p;
  973. m_list.ScreenToClient(&lvhti.pt);
  974. m_list.SubItemHitTest(&lvhti);
  975. POSITION pos = FindPos(lvhti.iItem);
  976. // bool fSelected = (pos == m_pl.GetPos());
  977. bool fOnItem = !!(lvhti.flags&LVHT_ONITEM);
  978. CMenu m;
  979. m.CreatePopupMenu();
  980. enum 
  981. {
  982. M_OPEN=1, M_ADD, M_REMOVE, M_CLIPBOARD, M_SAVEAS, 
  983. M_SORTBYNAME, M_SORTBYPATH, M_RANDOMIZE, M_SORTBYID,
  984. M_REMEMBERPLAYLIST, M_SHUFFLE
  985. };
  986. m.AppendMenu(MF_STRING|(!fOnItem?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_OPEN, ResStr(IDS_PLAYLIST_OPEN));
  987. if(((CMainFrame*)AfxGetMainWnd())->m_iPlaybackMode == PM_CAPTURE) m.AppendMenu(MF_STRING|MF_ENABLED, M_ADD, ResStr(IDS_PLAYLIST_ADD));
  988. m.AppendMenu(MF_STRING|(/*fSelected||*/!fOnItem?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_REMOVE, ResStr(IDS_PLAYLIST_REMOVE));
  989. m.AppendMenu(MF_SEPARATOR);
  990. m.AppendMenu(MF_STRING|(!fOnItem?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_CLIPBOARD, ResStr(IDS_PLAYLIST_COPYTOCLIPBOARD));
  991. m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_SAVEAS, ResStr(IDS_PLAYLIST_SAVEAS));
  992. m.AppendMenu(MF_SEPARATOR);
  993. m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_SORTBYNAME, ResStr(IDS_PLAYLIST_SORTBYLABEL));
  994. m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_SORTBYPATH, ResStr(IDS_PLAYLIST_SORTBYPATH));
  995. m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_RANDOMIZE, ResStr(IDS_PLAYLIST_RANDOMIZE));
  996. m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_SORTBYID, ResStr(IDS_PLAYLIST_RESTORE));
  997. m.AppendMenu(MF_SEPARATOR);
  998. m.AppendMenu(MF_STRING|MF_ENABLED|(AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("ShufflePlaylistItems"), FALSE)?MF_CHECKED:0), M_SHUFFLE, ResStr(IDS_PLAYLIST_SHUFFLE));
  999. m.AppendMenu(MF_STRING|MF_ENABLED|(AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), TRUE)?MF_CHECKED:0), M_REMEMBERPLAYLIST, ResStr(IDS_PLAYLIST_REMEBERITEMS));
  1000. CMainFrame* pMainFrm = (CMainFrame*)AfxGetMainWnd();
  1001. int nID = (int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this);
  1002. switch(nID)
  1003. {
  1004. case M_OPEN:
  1005. m_pl.SetPos(pos);
  1006. m_list.Invalidate();
  1007. pMainFrm->OpenCurPlaylistItem();
  1008. break;
  1009. case M_ADD:
  1010. pMainFrm->AddCurDevToPlaylist();
  1011. m_pl.SetPos(m_pl.GetTailPosition());
  1012. break;
  1013. case M_REMOVE:
  1014. if(m_pl.RemoveAt(pos)) pMainFrm->CloseMedia();
  1015. m_list.DeleteItem(lvhti.iItem);
  1016. SavePlaylist();
  1017. break;
  1018. case M_SORTBYID:
  1019. m_pl.SortById();
  1020. SetupList();
  1021. SavePlaylist();
  1022. break;
  1023. case M_SORTBYNAME:
  1024. m_pl.SortByName();
  1025. SetupList();
  1026. SavePlaylist();
  1027. break;
  1028. case M_SORTBYPATH:
  1029. m_pl.SortByPath();
  1030. SetupList();
  1031. SavePlaylist();
  1032. break;
  1033. case M_RANDOMIZE:
  1034. m_pl.Randomize();
  1035. SetupList();
  1036. SavePlaylist();
  1037. break;
  1038. case M_CLIPBOARD:
  1039. if(OpenClipboard() && EmptyClipboard())
  1040. {
  1041. CString str;
  1042. CPlaylistItem& pli = m_pl.GetAt(pos);
  1043. POSITION pos = pli.m_fns.GetHeadPosition();
  1044. while(pos) str += _T("rn") + pli.m_fns.GetNext(pos);
  1045. str.Trim();
  1046. if(HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, (str.GetLength()+1)*sizeof(TCHAR)))
  1047. {
  1048. if(TCHAR* s = (TCHAR*)GlobalLock(h))
  1049. {
  1050. _tcscpy(s, str);
  1051. GlobalUnlock(h);
  1052. #ifdef UNICODE
  1053. SetClipboardData(CF_UNICODETEXT, h);
  1054. #else
  1055. SetClipboardData(CF_TEXT, h);
  1056. #endif
  1057. }
  1058. }
  1059. CloseClipboard(); 
  1060. }
  1061. break;
  1062. case M_SAVEAS:
  1063. {
  1064. CSaveTextFileDialog fd(
  1065. CTextFile::ASCII, NULL, NULL,
  1066. _T("Media Player Classic playlist (*.mpcpl)|*.mpcpl|Playlist (*.pls)|*.pls|WinAmp playlist (*.m3u)|*.m3u|Windows Media Playlist (*.asx)|*.asx||"), 
  1067. this);
  1068. if(fd.DoModal() != IDOK)
  1069. break;
  1070. CTextFile::enc encoding = (CTextFile::enc)fd.GetEncoding();
  1071. if(encoding == CTextFile::ASCII) encoding = CTextFile::ANSI;
  1072. int idx = fd.m_pOFN->nFilterIndex;
  1073. CPath path(fd.GetPathName());
  1074. switch(idx)
  1075. {
  1076. case 1: path.AddExtension(_T(".mpcpl")); break;
  1077. case 2: path.AddExtension(_T(".pls")); break;
  1078. case 3: path.AddExtension(_T(".m3u")); break;
  1079. case 4: path.AddExtension(_T(".asx")); break;
  1080. default: break;
  1081. }
  1082. bool fRemovePath = true;
  1083. CPath p(path);
  1084. p.RemoveFileSpec();
  1085. CString base = (LPCTSTR)p;
  1086. pos = m_pl.GetHeadPosition();
  1087. while(pos && fRemovePath)
  1088. {
  1089. CPlaylistItem& pli = m_pl.GetNext(pos);
  1090. if(pli.m_type != CPlaylistItem::file) fRemovePath = false;
  1091. else
  1092. {
  1093. POSITION pos;
  1094. pos = pli.m_fns.GetHeadPosition();
  1095. while(pos && fRemovePath)
  1096. {
  1097. CString fn = pli.m_fns.GetNext(pos);
  1098. CPath p(fn);
  1099. p.RemoveFileSpec();
  1100. if(base != (LPCTSTR)p) fRemovePath = false;
  1101. }
  1102. pos = pli.m_subs.GetHeadPosition();
  1103. while(pos && fRemovePath)
  1104. {
  1105. CString fn = pli.m_subs.GetNext(pos);
  1106. CPath p(fn);
  1107. p.RemoveFileSpec();
  1108. if(base != (LPCTSTR)p) fRemovePath = false;
  1109. }
  1110. }
  1111. }
  1112. if(idx == 1)
  1113. {
  1114. SaveMPCPlayList(path, encoding, fRemovePath);
  1115. break;
  1116. }
  1117. CTextFile f;
  1118. if(!f.Save(path, encoding))
  1119. break;
  1120. if(idx == 4)
  1121. {
  1122. f.WriteString(_T("<ASX version = "3.0">n"));
  1123. }
  1124. pos = m_pl.GetHeadPosition();
  1125. for(int i = 0; pos; i++)
  1126. {
  1127. CPlaylistItem& pli = m_pl.GetNext(pos);
  1128. if(pli.m_type != CPlaylistItem::file) 
  1129. continue;
  1130. CString fn = pli.m_fns.GetHead();
  1131. /*
  1132. if(fRemovePath)
  1133. {
  1134. CPath p(path);
  1135. p.StripPath();
  1136. fn = (LPCTSTR)p;
  1137. }
  1138. */
  1139. CString str;
  1140. switch(idx)
  1141. {
  1142. case 2: str.Format(_T("File%d=%sn"), i+1, fn); break;
  1143. case 3: str.Format(_T("%sn"), fn); break;
  1144. case 4: str.Format(_T("<Entry><Ref href = "%s"/></Entry>n"), fn); break;
  1145. default: break;
  1146. }
  1147. f.WriteString(str);
  1148. }
  1149. if(idx == 4)
  1150. {
  1151. f.WriteString(_T("</ASX>n"));
  1152. }
  1153. }
  1154. break;
  1155. case M_REMEMBERPLAYLIST:
  1156. AfxGetApp()->WriteProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), 
  1157. !AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), TRUE));
  1158. break;
  1159. case M_SHUFFLE:
  1160. AfxGetApp()->WriteProfileInt(ResStr(IDS_R_SETTINGS), _T("ShufflePlaylistItems"), 
  1161. !AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("ShufflePlaylistItems"), FALSE));
  1162. break;
  1163. default:
  1164. break;
  1165. }
  1166. }
  1167. void CPlayerPlaylistBar::OnLvnEndlabeleditList(NMHDR* pNMHDR, LRESULT* pResult)
  1168. {
  1169. NMLVDISPINFO* pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
  1170. if(pDispInfo->item.iItem >= 0 && pDispInfo->item.pszText)
  1171. {
  1172. CPlaylistItem& pli = m_pl.GetAt((POSITION)m_list.GetItemData(pDispInfo->item.iItem));
  1173. pli.m_label = pDispInfo->item.pszText;
  1174. m_list.SetItemText(pDispInfo->item.iItem, 0, pDispInfo->item.pszText);
  1175. }
  1176. *pResult = 0;
  1177. }