PlayerPlaylistBar.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:35k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 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, 50))
  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(CList<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, CList<CString>* subs)
  89. {
  90. CList<CString> sl;
  91. sl.AddTail(fn);
  92. AddItem(sl, subs);
  93. }
  94. void CPlayerPlaylistBar::AddItem(CList<CString>& fns, CList<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. CStringArray paths;
  150. paths.Add(_T("."));
  151. paths.Add(_T(".\subtitles"));
  152. paths.Add(_T("c:\subtitles"));
  153. SubFiles 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, CList<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, CList<CString>* subs)
  204. {
  205. CList<CString> sl;
  206. sl.AddTail(fn);
  207. ParsePlayList(sl, subs);
  208. }
  209. void CPlayerPlaylistBar::ParsePlayList(CList<CString>& fns, CList<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. CList<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. CList<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. CMap<int, int, CPlaylistItem, CPlaylistItem&> pli;
  266. CArray<int> idx;
  267. CWebTextFile f;
  268. if(!f.Open(fn) || !f.ReadString(str) || str != _T("MPCPLAYLIST"))
  269. return false;
  270. CPath base(fn);
  271. base.RemoveFileSpec();
  272. while(f.ReadString(str))
  273. {
  274. CList<CString> sl;
  275. Explode(str, sl, ',', 3);
  276. if(sl.GetCount() != 3) continue;
  277. if(int i = _ttoi(sl.RemoveHead()))
  278. {
  279. CString key = sl.RemoveHead();
  280. CString value = sl.RemoveHead();
  281. if(key == _T("type")) {pli[i].m_type = (CPlaylistItem::type_t)_ttol(value); idx.Add(i);}
  282. else if(key == _T("label")) pli[i].m_label = value;
  283. else if(key == _T("filename")) {value = CombinePath(base, value); pli[i].m_fns.AddTail(value);}
  284. else if(key == _T("subtitle")) {value = CombinePath(base, value); pli[i].m_subs.AddTail(value);}
  285. else if(key == _T("video")) {while(pli[i].m_fns.GetCount() < 2) pli[i].m_fns.AddTail(_T("")); pli[i].m_fns.GetHead() = value;}
  286. else if(key == _T("audio")) {while(pli[i].m_fns.GetCount() < 2) pli[i].m_fns.AddTail(_T("")); pli[i].m_fns.GetTail() = value;}
  287. else if(key == _T("vinput")) pli[i].m_vinput = _ttol(value);
  288. else if(key == _T("vchannel")) pli[i].m_vchannel = _ttol(value);
  289. else if(key == _T("ainput")) pli[i].m_ainput = _ttol(value);
  290. else if(key == _T("country")) pli[i].m_country = _ttol(value);
  291. }
  292. }
  293. qsort(idx.GetData(), idx.GetCount(), sizeof(int), s_int_comp);
  294. for(int i = 0; i < idx.GetCount(); i++)
  295. m_pl.AddTail(pli[idx[i]]);
  296. return pli.GetCount() > 0;
  297. }
  298. bool CPlayerPlaylistBar::SaveMPCPlayList(CString fn, CTextFile::enc e, bool fRemovePath)
  299. {
  300. CTextFile f;
  301. if(!f.Save(fn, e))
  302. return false;
  303. f.WriteString(_T("MPCPLAYLISTn"));
  304. POSITION pos = m_pl.GetHeadPosition(), pos2;
  305. for(int i = 1; pos; i++)
  306. {
  307. CPlaylistItem& pli = m_pl.GetNext(pos);
  308. CString idx;
  309. idx.Format(_T("%d"), i);
  310. CString str;
  311. str.Format(_T("%d,type,%d"), i, pli.m_type);
  312. f.WriteString(str + _T("n"));
  313. if(!pli.m_label.IsEmpty()) 
  314. f.WriteString(idx + _T(",label,") + pli.m_label + _T("n"));
  315. if(pli.m_type == CPlaylistItem::file)
  316. {
  317. pos2 = pli.m_fns.GetHeadPosition();
  318. while(pos2)
  319. {
  320. CString fn = pli.m_fns.GetNext(pos2);
  321. if(fRemovePath) {CPath p(fn); p.StripPath(); fn = (LPCTSTR)p;}
  322. f.WriteString(idx + _T(",filename,") + fn + _T("n"));
  323. }
  324. pos2 = pli.m_subs.GetHeadPosition();
  325. while(pos2)
  326. {
  327. CString fn = pli.m_subs.GetNext(pos2);
  328. if(fRemovePath) {CPath p(fn); p.StripPath(); fn = (LPCTSTR)p;}
  329. f.WriteString(idx + _T(",subtitle,") + fn + _T("n"));
  330. }
  331. }
  332. else if(pli.m_type == CPlaylistItem::device && pli.m_fns.GetCount() == 2)
  333. {
  334. f.WriteString(idx + _T(",video,") + pli.m_fns.GetHead() + _T("n"));
  335. f.WriteString(idx + _T(",audio,") + pli.m_fns.GetTail() + _T("n"));
  336. str.Format(_T("%d,vinput,%d"), i, pli.m_vinput);
  337. f.WriteString(str + _T("n"));
  338. str.Format(_T("%d,vchannel,%d"), i, pli.m_vchannel);
  339. f.WriteString(str + _T("n"));
  340. str.Format(_T("%d,ainput,%d"), i, pli.m_ainput);
  341. f.WriteString(str + _T("n"));
  342. str.Format(_T("%d,country,%d"), i, pli.m_country);
  343. f.WriteString(str + _T("n"));
  344. }
  345. }
  346. return true;
  347. }
  348. void CPlayerPlaylistBar::Refresh()
  349. {
  350. SetupList();
  351. ResizeListColumn();
  352. }
  353. void CPlayerPlaylistBar::Empty()
  354. {
  355. m_pl.RemoveAll();
  356. m_list.DeleteAllItems();
  357. SavePlaylist();
  358. }
  359. void CPlayerPlaylistBar::Open(CList<CString>& fns, bool fMulti, CList<CString>* subs)
  360. {
  361. Empty();
  362. Append(fns, fMulti, subs);
  363. }
  364. void CPlayerPlaylistBar::Append(CList<CString>& fns, bool fMulti, CList<CString>* subs)
  365. {
  366. if(fMulti)
  367. {
  368. ASSERT(subs == NULL || subs->GetCount() == 0);
  369. POSITION pos = fns.GetHeadPosition();
  370. while(pos) ParsePlayList(fns.GetNext(pos), NULL);
  371. }
  372. else
  373. {
  374. ParsePlayList(fns, subs);
  375. }
  376. Refresh();
  377. SavePlaylist();
  378. }
  379. void CPlayerPlaylistBar::Open(CStringW vdn, CStringW adn, int vinput, int vchannel, int ainput)
  380. {
  381. Empty();
  382. Append(vdn, adn, vinput, vchannel, ainput);
  383. }
  384. void CPlayerPlaylistBar::Append(CStringW vdn, CStringW adn, int vinput, int vchannel, int ainput)
  385. {
  386. CPlaylistItem pli;
  387. pli.m_type = CPlaylistItem::device;
  388. pli.m_fns.AddTail(CString(vdn));
  389. pli.m_fns.AddTail(CString(adn));
  390. pli.m_vinput = vinput;
  391. pli.m_vchannel = vchannel;
  392. pli.m_ainput = ainput;
  393. CList<CStringW> sl;
  394. CStringW vfn = GetFriendlyName(vdn);
  395. CStringW afn = GetFriendlyName(adn);
  396. if(!vfn.IsEmpty()) sl.AddTail(vfn);
  397. if(!afn.IsEmpty()) sl.AddTail(afn);
  398. CStringW label = Implode(sl, '|');
  399. label.Replace(L"|", L" - ");
  400. pli.m_label = CString(label);
  401. m_pl.AddTail(pli);
  402. Refresh();
  403. SavePlaylist();
  404. }
  405. void CPlayerPlaylistBar::SetupList()
  406. {
  407. m_list.DeleteAllItems();
  408. POSITION pos = m_pl.GetHeadPosition();
  409. for(int i = 0; pos; i++)
  410. {
  411. CPlaylistItem& pli = m_pl.GetAt(pos);
  412. m_list.SetItemData(m_list.InsertItem(i, pli.GetLabel()), (DWORD_PTR)pos);
  413. m_list.SetItemText(i, COL_TIME, pli.GetLabel(1));
  414. m_pl.GetNext(pos);
  415. }
  416. }
  417. void CPlayerPlaylistBar::UpdateList()
  418. {
  419. POSITION pos = m_pl.GetHeadPosition();
  420. for(int i = 0, j = m_list.GetItemCount(); pos && i < j; i++)
  421. {
  422. CPlaylistItem& pli = m_pl.GetAt(pos);
  423. m_list.SetItemData(i, (DWORD_PTR)pos);
  424. m_list.SetItemText(i, COL_NAME, pli.GetLabel(0));
  425. m_list.SetItemText(i, COL_TIME, pli.GetLabel(1));
  426. m_pl.GetNext(pos);
  427. }
  428. }
  429. void CPlayerPlaylistBar::EnsureVisible(POSITION pos)
  430. {
  431. int i = FindItem(m_pl.GetPos());
  432. if(i < 0) return;
  433. m_list.EnsureVisible(i, TRUE);
  434. m_list.Invalidate();
  435. }
  436. int CPlayerPlaylistBar::FindItem(POSITION pos)
  437. {
  438. for(int i = 0; i < m_list.GetItemCount(); i++)
  439. if((POSITION)m_list.GetItemData(i) == pos)
  440. return(i);
  441. return(-1);
  442. }
  443. POSITION CPlayerPlaylistBar::FindPos(int i)
  444. {
  445. if(i < 0) return(NULL);
  446. return((POSITION)m_list.GetItemData(i));
  447. }
  448. int CPlayerPlaylistBar::GetCount()
  449. {
  450. return(m_pl.GetCount()); // TODO: n - .fInvalid
  451. }
  452. int CPlayerPlaylistBar::GetSelIdx()
  453. {
  454. return(FindItem(m_pl.GetPos()));
  455. }
  456. void CPlayerPlaylistBar::SetSelIdx(int i)
  457. {
  458. m_pl.SetPos(FindPos(i));
  459. }
  460. bool CPlayerPlaylistBar::IsAtEnd()
  461. {
  462. return(m_pl.GetPos() && m_pl.GetPos() == m_pl.GetTailPosition());
  463. }
  464. bool CPlayerPlaylistBar::GetCur(CPlaylistItem& pli)
  465. {
  466. if(!m_pl.GetPos()) return(false);
  467. pli = m_pl.GetAt(m_pl.GetPos());
  468. return(true);
  469. }
  470. CString CPlayerPlaylistBar::GetCur()
  471. {
  472. CString fn;
  473. CPlaylistItem pli;
  474. if(GetCur(pli) && !pli.m_fns.IsEmpty()) fn = pli.m_fns.GetHead();
  475. return(fn);
  476. }
  477. void CPlayerPlaylistBar::SetNext()
  478. {
  479. POSITION pos = m_pl.GetPos(), org = pos;
  480. while(m_pl.GetNextWrap(pos).m_fInvalid && pos != org);
  481. UpdateList();
  482. m_pl.SetPos(pos);
  483. EnsureVisible(pos);
  484. }
  485. void CPlayerPlaylistBar::SetPrev()
  486. {
  487. POSITION pos = m_pl.GetPos(), org = pos;
  488. while(m_pl.GetPrevWrap(pos).m_fInvalid && pos != org);
  489. m_pl.SetPos(pos);
  490. EnsureVisible(pos);
  491. }
  492. void CPlayerPlaylistBar::SetFirst()
  493. {
  494. POSITION pos = m_pl.GetTailPosition(), org = pos;
  495. while(m_pl.GetNextWrap(pos).m_fInvalid && pos != org);
  496. UpdateList();
  497. m_pl.SetPos(pos);
  498. EnsureVisible(pos);
  499. }
  500. void CPlayerPlaylistBar::SetLast()
  501. {
  502. POSITION pos = m_pl.GetHeadPosition(), org = pos;
  503. while(m_pl.GetPrevWrap(pos).m_fInvalid && pos != org);
  504. m_pl.SetPos(pos);
  505. EnsureVisible(pos);
  506. }
  507. void CPlayerPlaylistBar::SetCurValid(bool fValid)
  508. {
  509. if(POSITION pos = m_pl.GetPos())
  510. {
  511. if(m_pl.GetAt(pos).m_fInvalid = !fValid)
  512. {
  513. int i = FindItem(pos);
  514. m_list.RedrawItems(i, i);
  515. }
  516. }
  517. }
  518. void CPlayerPlaylistBar::SetCurTime(REFERENCE_TIME rt)
  519. {
  520. if(POSITION pos = m_pl.GetPos())
  521. {
  522. CPlaylistItem& pli = m_pl.GetAt(pos);
  523. pli.m_duration = rt;
  524. m_list.SetItemText(FindItem(pos), COL_TIME, pli.GetLabel(1));
  525. }
  526. }
  527. OpenMediaData* CPlayerPlaylistBar::GetCurOMD(REFERENCE_TIME rtStart)
  528. {
  529. CPlaylistItem pli;
  530. if(!GetCur(pli)) return NULL;
  531. CString fn = CString(pli.m_fns.GetHead()).MakeLower();
  532. if(fn.Find(_T("video_ts.ifo")) >= 0
  533. || fn.Find(_T(".ratdvd")) >= 0)
  534. {
  535. if(OpenDVDData* p = new OpenDVDData())
  536. {
  537. p->path = pli.m_fns.GetHead(); 
  538. p->subs.AddTail(&pli.m_subs);
  539. return p;
  540. }
  541. }
  542. if(pli.m_type == CPlaylistItem::device)
  543. {
  544. if(OpenDeviceData* p = new OpenDeviceData())
  545. {
  546. POSITION pos = pli.m_fns.GetHeadPosition();
  547. for(int i = 0; i < countof(p->DisplayName) && pos; i++)
  548. p->DisplayName[i] = pli.m_fns.GetNext(pos);
  549. p->vinput = pli.m_vinput;
  550. p->vchannel = pli.m_vchannel;
  551. p->ainput = pli.m_ainput;
  552. return p;
  553. }
  554. }
  555. else
  556. {
  557. if(OpenFileData* p = new OpenFileData())
  558. {
  559. p->fns.AddTail((CList<CString>*)&pli.m_fns);
  560. p->subs.AddTail((CList<CString>*)&pli.m_subs);
  561. p->rtStart = rtStart;
  562. return p;
  563. }
  564. }
  565. return NULL;
  566. }
  567. void CPlayerPlaylistBar::LoadPlaylist()
  568. {
  569. CString base;
  570. if(AfxGetMyApp()->GetAppDataPath(base))
  571. {
  572. CPath p;
  573. p.Combine(base, _T("default.mpcpl"));
  574. if(!AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), TRUE))
  575. {
  576. DeleteFile(p);
  577. }
  578. else
  579. {
  580. ParseMPCPlayList(p);
  581. Refresh();
  582. }
  583. }
  584. }
  585. void CPlayerPlaylistBar::SavePlaylist()
  586. {
  587. CString base;
  588. if(AfxGetMyApp()->GetAppDataPath(base))
  589. {
  590. CPath p;
  591. p.Combine(base, _T("default.mpcpl"));
  592. if(!AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), TRUE))
  593. {
  594. DeleteFile(p);
  595. }
  596. else
  597. {
  598. SaveMPCPlayList(p, CTextFile::UTF8, false);
  599. }
  600. }
  601. }
  602. BEGIN_MESSAGE_MAP(CPlayerPlaylistBar, CSizingControlBarG)
  603. ON_WM_SIZE()
  604. ON_NOTIFY(LVN_KEYDOWN, IDC_PLAYLIST, OnLvnKeyDown)
  605. ON_NOTIFY(NM_DBLCLK, IDC_PLAYLIST, OnNMDblclkList)
  606. // ON_NOTIFY(NM_CUSTOMDRAW, IDC_PLAYLIST, OnCustomdrawList)
  607. ON_WM_DRAWITEM()
  608. ON_COMMAND_EX(ID_FILE_CLOSEPLAYLIST, OnFileClosePlaylist)
  609. ON_COMMAND_EX(ID_PLAY_PLAY, OnPlayPlay)
  610. ON_WM_DROPFILES()
  611. ON_NOTIFY(LVN_BEGINDRAG, IDC_PLAYLIST, OnBeginDrag)
  612. ON_WM_MOUSEMOVE()
  613. ON_WM_LBUTTONUP()
  614. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
  615. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
  616. ON_WM_TIMER()
  617. ON_WM_CONTEXTMENU()
  618. ON_NOTIFY(LVN_ENDLABELEDIT, IDC_PLAYLIST, OnLvnEndlabeleditList)
  619. END_MESSAGE_MAP()
  620. // CPlayerPlaylistBar message handlers
  621. void CPlayerPlaylistBar::ResizeListColumn()
  622. {
  623. if(::IsWindow(m_list.m_hWnd))
  624. {
  625. CRect r;
  626. GetClientRect(r);
  627. r.DeflateRect(2, 2);
  628. m_list.SetRedraw(FALSE);
  629. m_list.MoveWindow(r);
  630. m_list.GetClientRect(r);
  631. m_list.SetColumnWidth(COL_NAME, r.Width()-m_nTimeColWidth); //LVSCW_AUTOSIZE_USEHEADER
  632. m_list.SetRedraw(TRUE);
  633. }
  634. }
  635. void CPlayerPlaylistBar::OnSize(UINT nType, int cx, int cy)
  636. {
  637. CSizingControlBarG::OnSize(nType, cx, cy);
  638. ResizeListColumn();
  639. }
  640. void CPlayerPlaylistBar::OnLvnKeyDown(NMHDR* pNMHDR, LRESULT* pResult) 
  641. {
  642. LPNMLVKEYDOWN pLVKeyDown = reinterpret_cast<LPNMLVKEYDOWN>(pNMHDR);
  643. *pResult = FALSE;
  644. CList<int> items;
  645. POSITION pos = m_list.GetFirstSelectedItemPosition();
  646. while(pos) items.AddHead(m_list.GetNextSelectedItem(pos));
  647. if(pLVKeyDown->wVKey == VK_DELETE && items.GetCount() > 0) 
  648. {
  649. pos = items.GetHeadPosition();
  650. while(pos) 
  651. {
  652. int i = items.GetNext(pos);
  653. if(m_pl.RemoveAt(FindPos(i))) ((CMainFrame*)AfxGetMainWnd())->CloseMedia();
  654. m_list.DeleteItem(i);
  655. }
  656. m_list.SetItemState(-1, 0, LVIS_SELECTED);
  657. m_list.SetItemState(
  658. max(min(items.GetTail(), m_list.GetItemCount()-1), 0), 
  659. LVIS_SELECTED, LVIS_SELECTED);
  660. ResizeListColumn();
  661. *pResult = TRUE;
  662. }
  663. else if(pLVKeyDown->wVKey == VK_SPACE && items.GetCount() == 1) 
  664. {
  665. m_pl.SetPos(FindPos(items.GetHead()));
  666. ((CMainFrame*)AfxGetMainWnd())->OpenCurPlaylistItem();
  667. *pResult = TRUE;
  668. }
  669. }
  670. void CPlayerPlaylistBar::OnNMDblclkList(NMHDR* pNMHDR, LRESULT* pResult)
  671. {
  672. LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)pNMHDR;
  673. if(lpnmlv->iItem >= 0 && lpnmlv->iSubItem >= 0)
  674. {
  675. m_pl.SetPos(FindPos(lpnmlv->iItem));
  676. m_list.Invalidate();
  677. ((CMainFrame*)AfxGetMainWnd())->OpenCurPlaylistItem();
  678. }
  679. *pResult = 0;
  680. }
  681. /*
  682. void CPlayerPlaylistBar::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
  683. {
  684. NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
  685. *pResult = CDRF_DODEFAULT;
  686. if(CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage)
  687. {
  688. *pResult = CDRF_NOTIFYPOSTPAINT|CDRF_NOTIFYITEMDRAW;
  689. }
  690. else if(CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage)
  691. {
  692. pLVCD->nmcd.uItemState &= ~CDIS_SELECTED;
  693. pLVCD->nmcd.uItemState &= ~CDIS_FOCUS;
  694. pLVCD->clrText = (pLVCD->nmcd.dwItemSpec == m_playList.m_idx) ? 0x0000ff : CLR_DEFAULT;
  695. pLVCD->clrTextBk = m_list.GetItemState(pLVCD->nmcd.dwItemSpec, LVIS_SELECTED) ? 0xf1dacc : CLR_DEFAULT;
  696. *pResult = CDRF_NOTIFYPOSTPAINT;
  697. }
  698. else if(CDDS_ITEMPOSTPAINT == pLVCD->nmcd.dwDrawStage)
  699. {
  700.         int nItem = static_cast<int>(pLVCD->nmcd.dwItemSpec);
  701. if(m_list.GetItemState(pLVCD->nmcd.dwItemSpec, LVIS_SELECTED))
  702. {
  703. CRect r, r2;
  704. m_list.GetItemRect(nItem, &r, LVIR_BOUNDS);
  705. m_list.GetItemRect(nItem, &r2, LVIR_LABEL);
  706. r.left = r2.left;
  707. FrameRect(pLVCD->nmcd.hdc, &r, CBrush(0xc56a31));
  708. }
  709. *pResult = CDRF_SKIPDEFAULT;
  710. }
  711. else if(CDDS_POSTPAINT == pLVCD->nmcd.dwDrawStage)
  712. {
  713. }
  714. }
  715. */
  716. void CPlayerPlaylistBar::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
  717. {
  718. if(nIDCtl != IDC_PLAYLIST) return;
  719. int nItem = lpDrawItemStruct->itemID;
  720. CRect rcItem = lpDrawItemStruct->rcItem;
  721. POSITION pos = FindPos(nItem);
  722. bool fSelected = pos == m_pl.GetPos();
  723. CPlaylistItem& pli = m_pl.GetAt(pos);
  724. CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  725. if(!!m_list.GetItemState(nItem, LVIS_SELECTED))
  726. {
  727. FillRect(pDC->m_hDC, rcItem, CBrush(0xf1dacc));
  728. FrameRect(pDC->m_hDC, rcItem, CBrush(0xc56a31));
  729. }
  730. else
  731. {
  732. FillRect(pDC->m_hDC, rcItem, CBrush(GetSysColor(COLOR_WINDOW)));
  733. }
  734. COLORREF textcolor = fSelected?0xff:0;
  735. if(pli.m_fInvalid) textcolor |= 0xA0A0A0;
  736. CString time = !pli.m_fInvalid ? m_list.GetItemText(nItem, COL_TIME) : _T("Invalid");
  737. CSize timesize(0, 0);
  738. CPoint timept(rcItem.right, 0);
  739. if(time.GetLength() > 0)
  740. {
  741. timesize = pDC->GetTextExtent(time);
  742. if((3+timesize.cx+3) < rcItem.Width()/2)
  743. {
  744. timept = CPoint(rcItem.right-(3+timesize.cx+3), (rcItem.top+rcItem.bottom-timesize.cy)/2);
  745. pDC->SetTextColor(textcolor);
  746. pDC->TextOut(timept.x, timept.y, time);
  747. }
  748. }
  749. CString fmt, file;
  750. fmt.Format(_T("%%0%dd. %%s"), (int)log10(0.1+m_pl.GetCount())+1);
  751. file.Format(fmt, nItem+1, m_list.GetItemText(nItem, COL_NAME));
  752. CSize filesize = pDC->GetTextExtent(file);
  753. while(3+filesize.cx+6 > timept.x && file.GetLength() > 3)
  754. {
  755. file = file.Left(file.GetLength()-4) + _T("...");
  756. filesize = pDC->GetTextExtent(file);
  757. }
  758. if(file.GetLength() > 3)
  759. {
  760. pDC->SetTextColor(textcolor);
  761. pDC->TextOut(rcItem.left+3, (rcItem.top+rcItem.bottom-filesize.cy)/2, file);
  762. }
  763. }
  764. BOOL CPlayerPlaylistBar::OnFileClosePlaylist(UINT nID)
  765. {
  766. Empty();
  767. return FALSE;
  768. }
  769. BOOL CPlayerPlaylistBar::OnPlayPlay(UINT nID)
  770. {
  771. m_list.Invalidate();
  772. return FALSE;
  773. }
  774. void CPlayerPlaylistBar::OnDropFiles(HDROP hDropInfo)
  775. {
  776. SetActiveWindow();
  777. CList<CString> sl;
  778. UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
  779. for(UINT iFile = 0; iFile < nFiles; iFile++)
  780. {
  781. TCHAR szFileName[_MAX_PATH];
  782. ::DragQueryFile(hDropInfo, iFile, szFileName, _MAX_PATH);
  783. sl.AddTail(szFileName);
  784. }
  785. ::DragFinish(hDropInfo);
  786. Append(sl, true);
  787. }
  788. void CPlayerPlaylistBar::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult)
  789. {
  790. ModifyStyle(WS_EX_ACCEPTFILES, 0);
  791. m_nDragIndex = ((LPNMLISTVIEW)pNMHDR)->iItem;
  792. CPoint p(0, 0);
  793. m_pDragImage = m_list.CreateDragImageEx(&p);
  794. CPoint p2 = ((LPNMLISTVIEW)pNMHDR)->ptAction;
  795. m_pDragImage->BeginDrag(0, p2 - p);
  796. m_pDragImage->DragEnter(GetDesktopWindow(), ((LPNMLISTVIEW)pNMHDR)->ptAction);
  797. m_bDragging = TRUE;
  798. m_nDropIndex = -1;
  799. SetCapture();
  800. }
  801. void CPlayerPlaylistBar::OnMouseMove(UINT nFlags, CPoint point)
  802. {
  803. if(m_bDragging)
  804. {
  805. m_ptDropPoint = point;
  806. ClientToScreen(&m_ptDropPoint);
  807. m_pDragImage->DragMove(m_ptDropPoint);
  808. m_pDragImage->DragShowNolock(FALSE);
  809. WindowFromPoint(m_ptDropPoint)->ScreenToClient(&m_ptDropPoint);
  810. m_pDragImage->DragShowNolock(TRUE);
  811. {
  812. int iOverItem = m_list.HitTest(m_ptDropPoint);
  813. int iTopItem = m_list.GetTopIndex();
  814. int iBottomItem = m_list.GetBottomIndex();
  815. if(iOverItem == iTopItem && iTopItem != 0) // top of list
  816. SetTimer(1, 100, NULL); 
  817. else
  818. KillTimer(1); 
  819. if(iOverItem >= iBottomItem && iBottomItem != (m_list.GetItemCount() - 1)) // bottom of list
  820. SetTimer(2, 100, NULL); 
  821. else 
  822. KillTimer(2); 
  823. }
  824. }
  825. __super::OnMouseMove(nFlags, point);
  826. }
  827. void CPlayerPlaylistBar::OnTimer(UINT nIDEvent)
  828. {
  829. int iTopItem = m_list.GetTopIndex();
  830. int iBottomItem = iTopItem + m_list.GetCountPerPage() - 1;
  831. if(m_bDragging)
  832. {
  833. m_pDragImage->DragShowNolock(FALSE);
  834. if(nIDEvent == 1)
  835. {
  836. m_list.EnsureVisible(iTopItem - 1, false);
  837. m_list.UpdateWindow();
  838. if(m_list.GetTopIndex() == 0) KillTimer(1); 
  839. }
  840. else if(nIDEvent == 2)
  841. {
  842. m_list.EnsureVisible(iBottomItem + 1, false);
  843. m_list.UpdateWindow();
  844. if(m_list.GetBottomIndex() == (m_list.GetItemCount() - 1)) KillTimer(2); 
  845. m_pDragImage->DragShowNolock(TRUE);
  846. }
  847. __super::OnTimer(nIDEvent);
  848. }
  849. void CPlayerPlaylistBar::OnLButtonUp(UINT nFlags, CPoint point)
  850. {
  851. if(m_bDragging)
  852. {
  853. ::ReleaseCapture();
  854. m_bDragging = FALSE;
  855. m_pDragImage->DragLeave(GetDesktopWindow());
  856. m_pDragImage->EndDrag();
  857. delete m_pDragImage;
  858. m_pDragImage = NULL;
  859. KillTimer(1);
  860. KillTimer(2);
  861. CPoint pt(point);
  862. ClientToScreen(&pt);
  863. if(WindowFromPoint(pt) == &m_list)
  864. DropItemOnList();
  865. }
  866. ModifyStyle(0, WS_EX_ACCEPTFILES); 
  867. __super::OnLButtonUp(nFlags, point);
  868. }
  869. void CPlayerPlaylistBar::DropItemOnList()
  870. {
  871. m_ptDropPoint.y += 10; //
  872. m_nDropIndex = m_list.HitTest(CPoint(10, m_ptDropPoint.y));
  873. TCHAR szLabel[MAX_PATH];
  874. LV_ITEM lvi;
  875. ZeroMemory(&lvi, sizeof(LV_ITEM));
  876. lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
  877. lvi.stateMask = LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED;
  878. lvi.pszText = szLabel;
  879. lvi.iItem = m_nDragIndex;
  880. lvi.cchTextMax = MAX_PATH;
  881. m_list.GetItem(&lvi);
  882. if(m_nDropIndex < 0) m_nDropIndex = m_list.GetItemCount();
  883. lvi.iItem = m_nDropIndex;
  884. m_list.InsertItem(&lvi);
  885. CHeaderCtrl* pHeader = (CHeaderCtrl*)m_list.GetDlgItem(0);
  886. int nColumnCount = pHeader->GetItemCount();
  887. lvi.mask = LVIF_TEXT;
  888. lvi.iItem = m_nDropIndex;
  889. //INDEX OF DRAGGED ITEM WILL CHANGE IF ITEM IS DROPPED ABOVE ITSELF
  890. if(m_nDropIndex < m_nDragIndex) m_nDragIndex++;
  891. for(int col=1; col < nColumnCount; col++)
  892. {
  893. _tcscpy(lvi.pszText, (LPCTSTR)(m_list.GetItemText(m_nDragIndex, col)));
  894. lvi.iSubItem = col;
  895. m_list.SetItem(&lvi);
  896. }
  897. m_list.DeleteItem(m_nDragIndex);
  898. CList<CPlaylistItem> tmp;
  899. UINT id = -1;
  900. for(int i = 0; i < m_list.GetItemCount(); i++)
  901. {
  902. POSITION pos = (POSITION)m_list.GetItemData(i);
  903. CPlaylistItem& pli = m_pl.GetAt(pos);
  904. tmp.AddTail(pli);
  905. if(pos == m_pl.GetPos()) id = pli.m_id;
  906. }
  907. m_pl.RemoveAll();
  908. POSITION pos = tmp.GetHeadPosition();
  909. for(int i = 0; pos; i++)
  910. {
  911. CPlaylistItem& pli = tmp.GetNext(pos);
  912. m_pl.AddTail(pli);
  913. if(pli.m_id == id) m_pl.SetPos(m_pl.GetTailPosition());
  914. m_list.SetItemData(i, (DWORD_PTR)m_pl.GetTailPosition());
  915. }
  916. ResizeListColumn();
  917. }
  918. BOOL CPlayerPlaylistBar::OnToolTipNotify(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
  919. {
  920. TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
  921. TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
  922. if((pNMHDR->code == TTN_NEEDTEXTA && (HWND)pTTTA->lParam != m_list.m_hWnd)
  923. || (pNMHDR->code == TTN_NEEDTEXTW && (HWND)pTTTW->lParam != m_list.m_hWnd))
  924. return FALSE;
  925. int row = ((pNMHDR->idFrom-1) >> 10) & 0x3fffff;
  926. int col = (pNMHDR->idFrom-1) & 0x3ff;
  927. if(row < 0 || row >= m_pl.GetCount())
  928. return FALSE;
  929. CPlaylistItem& pli = m_pl.GetAt(FindPos(row));
  930. CString strTipText;
  931. if(col == COL_NAME)
  932. {
  933. POSITION pos = pli.m_fns.GetHeadPosition();
  934. while(pos) strTipText += _T("n") + pli.m_fns.GetNext(pos);
  935. strTipText.Trim();
  936. if(pli.m_type == CPlaylistItem::device)
  937. {
  938. CString str;
  939. str.Format(_T("Video Input %d"), pli.m_vinput);
  940. if(pli.m_vinput >= 0) strTipText += _T("n") + str;
  941. str.Format(_T("Video Channel %d"), pli.m_vchannel);
  942. if(pli.m_vchannel >= 0) strTipText += _T("n") + str;
  943. str.Format(_T("Audio Input %d"), pli.m_ainput);
  944. if(pli.m_ainput >= 0) strTipText += _T("n") + str;
  945. }
  946. ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, (LPARAM)(INT)1000);
  947. }
  948. else if(col == COL_TIME)
  949. {
  950. return FALSE;
  951. }
  952. static CStringA m_strTipTextA;
  953. static CStringW m_strTipTextW;
  954. if(pNMHDR->code == TTN_NEEDTEXTA)
  955. {
  956. m_strTipTextA = strTipText;
  957. pTTTA->lpszText = (LPSTR)(LPCSTR)m_strTipTextA;
  958. }
  959. else
  960. {
  961. m_strTipTextW = strTipText;
  962. pTTTW->lpszText = (LPWSTR)(LPCWSTR)m_strTipTextW;
  963. }
  964. *pResult = 0;
  965. return TRUE;    // message was handled
  966. }
  967. void CPlayerPlaylistBar::OnContextMenu(CWnd* /*pWnd*/, CPoint p)
  968. {
  969. LVHITTESTINFO lvhti;
  970. lvhti.pt = p;
  971. m_list.ScreenToClient(&lvhti.pt);
  972. m_list.SubItemHitTest(&lvhti);
  973. POSITION pos = FindPos(lvhti.iItem);
  974. // bool fSelected = (pos == m_pl.GetPos());
  975. bool fOnItem = !!(lvhti.flags&LVHT_ONITEM);
  976. CMenu m;
  977. m.CreatePopupMenu();
  978. enum 
  979. {
  980. M_OPEN=1, M_ADD, M_REMOVE, M_CLIPBOARD, M_SAVEAS, 
  981. M_SORTBYNAME, M_SORTBYPATH, M_RANDOMIZE, M_SORTBYID,
  982. M_REMEMBERPLAYLIST, M_SHUFFLE
  983. };
  984. m.AppendMenu(MF_STRING|(!fOnItem?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_OPEN, ResStr(IDS_PLAYLIST_OPEN));
  985. if(((CMainFrame*)AfxGetMainWnd())->m_iPlaybackMode == PM_CAPTURE) m.AppendMenu(MF_STRING|MF_ENABLED, M_ADD, ResStr(IDS_PLAYLIST_ADD));
  986. m.AppendMenu(MF_STRING|(/*fSelected||*/!fOnItem?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_REMOVE, ResStr(IDS_PLAYLIST_REMOVE));
  987. m.AppendMenu(MF_SEPARATOR);
  988. m.AppendMenu(MF_STRING|(!fOnItem?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_CLIPBOARD, ResStr(IDS_PLAYLIST_COPYTOCLIPBOARD));
  989. m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_SAVEAS, ResStr(IDS_PLAYLIST_SAVEAS));
  990. m.AppendMenu(MF_SEPARATOR);
  991. m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_SORTBYNAME, ResStr(IDS_PLAYLIST_SORTBYLABEL));
  992. m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_SORTBYPATH, ResStr(IDS_PLAYLIST_SORTBYPATH));
  993. m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_RANDOMIZE, ResStr(IDS_PLAYLIST_RANDOMIZE));
  994. m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_SORTBYID, ResStr(IDS_PLAYLIST_RESTORE));
  995. m.AppendMenu(MF_SEPARATOR);
  996. m.AppendMenu(MF_STRING|MF_ENABLED|(AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("ShufflePlaylistItems"), FALSE)?MF_CHECKED:0), M_SHUFFLE, _T("Shuffle"));
  997. m.AppendMenu(MF_STRING|MF_ENABLED|(AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), TRUE)?MF_CHECKED:0), M_REMEMBERPLAYLIST, _T("Remember items"));
  998. CMainFrame* pMainFrm = (CMainFrame*)AfxGetMainWnd();
  999. int nID = (int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this);
  1000. switch(nID)
  1001. {
  1002. case M_OPEN:
  1003. m_pl.SetPos(pos);
  1004. m_list.Invalidate();
  1005. pMainFrm->OpenCurPlaylistItem();
  1006. break;
  1007. case M_ADD:
  1008. pMainFrm->AddCurDevToPlaylist();
  1009. m_pl.SetPos(m_pl.GetTailPosition());
  1010. break;
  1011. case M_REMOVE:
  1012. if(m_pl.RemoveAt(pos)) pMainFrm->CloseMedia();
  1013. m_list.DeleteItem(lvhti.iItem);
  1014. SavePlaylist();
  1015. break;
  1016. case M_SORTBYID:
  1017. m_pl.SortById();
  1018. SetupList();
  1019. SavePlaylist();
  1020. break;
  1021. case M_SORTBYNAME:
  1022. m_pl.SortByName();
  1023. SetupList();
  1024. SavePlaylist();
  1025. break;
  1026. case M_SORTBYPATH:
  1027. m_pl.SortByPath();
  1028. SetupList();
  1029. SavePlaylist();
  1030. break;
  1031. case M_RANDOMIZE:
  1032. m_pl.Randomize();
  1033. SetupList();
  1034. SavePlaylist();
  1035. break;
  1036. case M_CLIPBOARD:
  1037. if(OpenClipboard() && EmptyClipboard())
  1038. {
  1039. CString str;
  1040. CPlaylistItem& pli = m_pl.GetAt(pos);
  1041. POSITION pos = pli.m_fns.GetHeadPosition();
  1042. while(pos) str += _T("rn") + pli.m_fns.GetNext(pos);
  1043. str.Trim();
  1044. if(HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, (str.GetLength()+1)*sizeof(TCHAR)))
  1045. {
  1046. if(TCHAR* s = (TCHAR*)GlobalLock(h))
  1047. {
  1048. _tcscpy(s, str);
  1049. GlobalUnlock(h);
  1050. #ifdef UNICODE
  1051. SetClipboardData(CF_UNICODETEXT, h);
  1052. #else
  1053. SetClipboardData(CF_TEXT, h);
  1054. #endif
  1055. }
  1056. }
  1057. CloseClipboard(); 
  1058. }
  1059. break;
  1060. case M_SAVEAS:
  1061. {
  1062. CSaveTextFileDialog fd(
  1063. CTextFile::ASCII, NULL, NULL,
  1064. _T("Media Player Classic playlist (*.mpcpl)|*.mpcpl|Playlist (*.pls)|*.pls|WinAmp playlist (*.m3u)|*.m3u|Windows Media Playlist (*.asx)|*.asx||"), 
  1065. this);
  1066. if(fd.DoModal() != IDOK)
  1067. break;
  1068. int idx = fd.m_pOFN->nFilterIndex;
  1069. CPath path(fd.GetPathName());
  1070. switch(idx)
  1071. {
  1072. case 1: path.AddExtension(_T(".mpcpl")); break;
  1073. case 2: path.AddExtension(_T(".pls")); break;
  1074. case 3: path.AddExtension(_T(".m3u")); break;
  1075. case 4: path.AddExtension(_T(".asx")); break;
  1076. default: break;
  1077. }
  1078. bool fRemovePath = true;
  1079. CPath p(path);
  1080. p.RemoveFileSpec();
  1081. CString base = (LPCTSTR)p;
  1082. pos = m_pl.GetHeadPosition();
  1083. while(pos && fRemovePath)
  1084. {
  1085. CPlaylistItem& pli = m_pl.GetNext(pos);
  1086. if(pli.m_type != CPlaylistItem::file) fRemovePath = false;
  1087. else
  1088. {
  1089. POSITION pos;
  1090. pos = pli.m_fns.GetHeadPosition();
  1091. while(pos && fRemovePath)
  1092. {
  1093. CString fn = pli.m_fns.GetNext(pos);
  1094. CPath p(fn);
  1095. p.RemoveFileSpec();
  1096. if(base != (LPCTSTR)p) fRemovePath = false;
  1097. }
  1098. pos = pli.m_subs.GetHeadPosition();
  1099. while(pos && fRemovePath)
  1100. {
  1101. CString fn = pli.m_subs.GetNext(pos);
  1102. CPath p(fn);
  1103. p.RemoveFileSpec();
  1104. if(base != (LPCTSTR)p) fRemovePath = false;
  1105. }
  1106. }
  1107. }
  1108. if(idx == 1)
  1109. {
  1110. SaveMPCPlayList(path, fd.GetEncoding(), fRemovePath);
  1111. break;
  1112. }
  1113. CTextFile f;
  1114. if(!f.Save(path, fd.GetEncoding()))
  1115. break;
  1116. if(idx == 4)
  1117. {
  1118. f.WriteString(_T("<ASX version = "3.0">n"));
  1119. }
  1120. pos = m_pl.GetHeadPosition();
  1121. for(int i = 0; pos; i++)
  1122. {
  1123. CPlaylistItem& pli = m_pl.GetNext(pos);
  1124. if(pli.m_type != CPlaylistItem::file) 
  1125. continue;
  1126. CString fn = pli.m_fns.GetHead();
  1127. /*
  1128. if(fRemovePath)
  1129. {
  1130. CPath p(path);
  1131. p.StripPath();
  1132. fn = (LPCTSTR)p;
  1133. }
  1134. */
  1135. CString str;
  1136. switch(idx)
  1137. {
  1138. case 2: str.Format(_T("File%d=%sn"), i+1, fn); break;
  1139. case 3: str.Format(_T("%sn"), fn); break;
  1140. case 4: str.Format(_T("<Entry><Ref href = "%s"/></Entry>n"), fn); break;
  1141. default: break;
  1142. }
  1143. f.WriteString(str);
  1144. }
  1145. if(idx == 4)
  1146. {
  1147. f.WriteString(_T("</ASX>n"));
  1148. }
  1149. }
  1150. break;
  1151. case M_REMEMBERPLAYLIST:
  1152. AfxGetApp()->WriteProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), 
  1153. !AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), TRUE));
  1154. break;
  1155. case M_SHUFFLE:
  1156. AfxGetApp()->WriteProfileInt(ResStr(IDS_R_SETTINGS), _T("ShufflePlaylistItems"), 
  1157. !AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("ShufflePlaylistItems"), FALSE));
  1158. break;
  1159. default:
  1160. break;
  1161. }
  1162. }
  1163. void CPlayerPlaylistBar::OnLvnEndlabeleditList(NMHDR* pNMHDR, LRESULT* pResult)
  1164. {
  1165. NMLVDISPINFO* pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
  1166. if(pDispInfo->item.iItem >= 0 && pDispInfo->item.pszText)
  1167. {
  1168. CPlaylistItem& pli = m_pl.GetAt((POSITION)m_list.GetItemData(pDispInfo->item.iItem));
  1169. pli.m_label = pDispInfo->item.pszText;
  1170. m_list.SetItemText(pDispInfo->item.iItem, 0, pDispInfo->item.pszText);
  1171. }
  1172. *pResult = 0;
  1173. }