00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "stdafx.h"
00023 #include <math.h>
00024 #include <afxinet.h>
00025 #include <atlrx.h>
00026 #include <atlutil.h>
00027 #include "mplayerc.h"
00028 #include "mainfrm.h"
00029 #include "..\..\DSUtil\DSUtil.h"
00030 #include "SaveTextFileDialog.h"
00031 #include ".\playerplaylistbar.h"
00032
00033 IMPLEMENT_DYNAMIC(CPlayerPlaylistBar, CSizingControlBarG)
00034 CPlayerPlaylistBar::CPlayerPlaylistBar()
00035 : m_list(0)
00036 , m_nTimeColWidth(0)
00037 {
00038 m_bDragging = FALSE;
00039 }
00040
00041 CPlayerPlaylistBar::~CPlayerPlaylistBar()
00042 {
00043 }
00044
00045 BOOL CPlayerPlaylistBar::Create(CWnd* pParentWnd)
00046 {
00047 if(!CSizingControlBarG::Create(_T("Playlist"), pParentWnd, 50))
00048 return FALSE;
00049
00050 m_list.CreateEx(
00051 WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE,
00052 WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_TABSTOP
00053 |LVS_OWNERDRAWFIXED
00054 |LVS_NOCOLUMNHEADER
00055 |LVS_EDITLABELS
00056 |LVS_REPORT|LVS_SINGLESEL|LVS_AUTOARRANGE|LVS_NOSORTHEADER,
00057 CRect(0,0,100,100), this, IDC_PLAYLIST);
00058
00059 m_list.SetExtendedStyle(m_list.GetExtendedStyle()|LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER);
00060
00061 m_list.InsertColumn(COL_NAME, _T("Name"), LVCFMT_LEFT, 380);
00062
00063 CDC* pDC = m_list.GetDC();
00064 CFont* old = pDC->SelectObject(GetFont());
00065 m_nTimeColWidth = pDC->GetTextExtent(_T("000:00:00")).cx + 5;
00066 pDC->SelectObject(old);
00067 m_list.ReleaseDC(pDC);
00068 m_list.InsertColumn(COL_TIME, _T("Time"), LVCFMT_RIGHT, m_nTimeColWidth);
00069
00070 m_fakeImageList.Create(1, 16, ILC_COLOR4, 10, 10);
00071 m_list.SetImageList(&m_fakeImageList, LVSIL_SMALL);
00072
00073 return TRUE;
00074 }
00075
00076 BOOL CPlayerPlaylistBar::PreCreateWindow(CREATESTRUCT& cs)
00077 {
00078 if(!CSizingControlBarG::PreCreateWindow(cs))
00079 return FALSE;
00080
00081 cs.dwExStyle |= WS_EX_ACCEPTFILES;
00082
00083 return TRUE;
00084 }
00085
00086 BOOL CPlayerPlaylistBar::PreTranslateMessage(MSG* pMsg)
00087 {
00088 if(IsWindow(pMsg->hwnd) && IsVisible() && pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
00089 {
00090 if(IsDialogMessage(pMsg))
00091 return TRUE;
00092 }
00093
00094 return CSizingControlBarG::PreTranslateMessage(pMsg);
00095 }
00096
00097 bool FindFileInList(CList<CString>& sl, CString fn)
00098 {
00099 bool fFound = false;
00100 POSITION pos = sl.GetHeadPosition();
00101 while(pos && !fFound) {if(!sl.GetNext(pos).CompareNoCase(fn)) fFound = true;}
00102 return(fFound);
00103 }
00104
00105 void CPlayerPlaylistBar::AddItem(CString fn, CList<CString>* subs)
00106 {
00107 CList<CString> sl;
00108 sl.AddTail(fn);
00109 AddItem(sl, subs);
00110 }
00111
00112 void CPlayerPlaylistBar::AddItem(CList<CString>& fns, CList<CString>* subs)
00113 {
00114 CPlaylistItem pli;
00115
00116 POSITION pos = fns.GetHeadPosition();
00117 while(pos)
00118 {
00119 CString fn = fns.GetNext(pos);
00120 if(!fn.Trim().IsEmpty()) pli.m_fns.AddTail(fn);
00121 }
00122
00123 if(subs)
00124 {
00125 POSITION pos = subs->GetHeadPosition();
00126 while(pos)
00127 {
00128 CString fn = subs->GetNext(pos);
00129 if(!fn.Trim().IsEmpty()) pli.m_subs.AddTail(fn);
00130 }
00131 }
00132
00133 if(pli.m_fns.IsEmpty()) return;
00134
00135 CString fn = pli.m_fns.GetHead();
00136
00137 if(AfxGetAppSettings().fAutoloadAudio && fn.Find(_T("://")) < 0)
00138 {
00139 int i = fn.ReverseFind('.');
00140 if(i > 0)
00141 {
00142 CMediaFormats& mf = AfxGetAppSettings().Formats;
00143
00144 CString ext = fn.Mid(i+1).MakeLower();
00145
00146 if(!mf.FindExt(ext, true))
00147 {
00148 CString path = fn;
00149 path.Replace('/', '\\');
00150 path = path.Left(path.ReverseFind('\\')+1);
00151
00152 WIN32_FIND_DATA fd = {0};
00153 HANDLE hFind = FindFirstFile(fn.Left(i) + _T("*.*"), &fd);
00154 if(hFind != INVALID_HANDLE_VALUE)
00155 {
00156 do
00157 {
00158 if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
00159
00160 CString fullpath = path + fd.cFileName;
00161 CString ext2 = fullpath.Mid(fullpath.ReverseFind('.')+1).MakeLower();
00162 if(!FindFileInList(pli.m_fns, fullpath) && ext != ext2
00163 && mf.FindExt(ext2, true) && mf.IsUsingEngine(fullpath, DirectShow))
00164 {
00165 pli.m_fns.AddTail(fullpath);
00166 }
00167 }
00168 while(FindNextFile(hFind, &fd));
00169
00170 FindClose(hFind);
00171 }
00172 }
00173 }
00174 }
00175
00176 if(AfxGetAppSettings().fAutoloadSubtitles)
00177 {
00178 CStringArray paths;
00179 paths.Add(_T("."));
00180 paths.Add(_T(".\\subtitles"));
00181 paths.Add(_T("c:\\subtitles"));
00182
00183 SubFiles ret;
00184 GetSubFileNames(fn, paths, ret);
00185
00186 for(int i = 0; i < ret.GetCount(); i++)
00187 {
00188 if(!FindFileInList(pli.m_subs, ret[i].fn))
00189 pli.m_subs.AddTail(ret[i].fn);
00190 }
00191 }
00192
00193 m_pl.AddTail(pli);
00194 }
00195
00196 static bool SearchFiles(CString mask, CList<CString>& sl)
00197 {
00198 if(mask.Find(_T("://")) >= 0)
00199 return(false);
00200
00201 mask.Trim();
00202 sl.RemoveAll();
00203
00204 CMediaFormats& mf = AfxGetAppSettings().Formats;
00205
00206 bool fFilterKnownExts;
00207 WIN32_FILE_ATTRIBUTE_DATA fad;
00208 mask = (fFilterKnownExts = (GetFileAttributesEx(mask, GetFileExInfoStandard, &fad)
00209 && (fad.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)))
00210 ? CString(mask).TrimRight(_T("\\/")) + _T("\\*.*")
00211 : mask;
00212
00213 {
00214 CString dir = mask.Left(max(mask.ReverseFind('\\'), mask.ReverseFind('/'))+1);
00215
00216 WIN32_FIND_DATA fd;
00217 HANDLE h = FindFirstFile(mask, &fd);
00218 if(h != INVALID_HANDLE_VALUE)
00219 {
00220 do
00221 {
00222 if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) continue;
00223
00224 CString fn = fd.cFileName;
00225 CString ext = fn.Mid(fn.ReverseFind('.')+1).MakeLower();
00226 CString path = dir + fd.cFileName;
00227
00228 if(!fFilterKnownExts || mf.FindExt(ext))
00229 sl.AddTail(path);
00230 }
00231 while(FindNextFile(h, &fd));
00232
00233 FindClose(h);
00234
00235 if(sl.GetCount() == 0 && mask.Find(_T(":\\")) == 1)
00236 {
00237 GetCDROMType(mask[0], sl);
00238 }
00239 }
00240 }
00241
00242 return(sl.GetCount() > 1
00243 || sl.GetCount() == 1 && sl.GetHead().CompareNoCase(mask)
00244 || sl.GetCount() == 0 && mask.FindOneOf(_T("?*")) >= 0);
00245 }
00246
00247 void CPlayerPlaylistBar::ParsePlayList(CString fn, CList<CString>* subs)
00248 {
00249 CList<CString> sl;
00250 sl.AddTail(fn);
00251 ParsePlayList(sl, subs);
00252 }
00253
00254 void CPlayerPlaylistBar::ParsePlayList(CList<CString>& fns, CList<CString>* subs)
00255 {
00256 if(fns.IsEmpty()) return;
00257
00258
00259
00260 CComPtr<IShellLink> pSL;
00261 pSL.CoCreateInstance(CLSID_ShellLink);
00262 CComQIPtr<IPersistFile> pPF = pSL;
00263
00264 POSITION pos = fns.GetHeadPosition();
00265 while(pSL && pPF && pos)
00266 {
00267 CString& fn = fns.GetNext(pos);
00268 TCHAR buff[MAX_PATH];
00269 if(CPath(fn).GetExtension().MakeLower() != _T(".lnk")
00270 || FAILED(pPF->Load(CStringW(fn), STGM_READ))
00271 || FAILED(pSL->Resolve(NULL, SLR_ANY_MATCH|SLR_NO_UI))
00272 || FAILED(pSL->GetPath(buff, countof(buff), NULL, 0)))
00273 continue;
00274
00275 fn = buff;
00276 }
00277
00278
00279
00280 CList<CString> sl;
00281 if(SearchFiles(fns.GetHead(), sl))
00282 {
00283 if(sl.GetCount() > 1) subs = NULL;
00284 POSITION pos = sl.GetHeadPosition();
00285 while(pos) ParsePlayList(sl.GetNext(pos), subs);
00286 return;
00287 }
00288
00289 CList<CString> redir;
00290 CStringA ct = GetContentType(fns.GetHead(), &redir);
00291 if(!redir.IsEmpty())
00292 {
00293 POSITION pos = redir.GetHeadPosition();
00294 while(pos) ParsePlayList(sl.GetNext(pos), subs);
00295 return;
00296 }
00297
00298 if(ct == "application/x-mpc-playlist")
00299 {
00300 ParseMPCPlayList(fns.GetHead());
00301 return;
00302 }
00303
00304 AddItem(fns, subs);
00305 }
00306
00307 static int s_int_comp(const void* i1, const void* i2)
00308 {
00309 return (int)i1 - (int)i2;
00310 }
00311
00312 static CString CombinePath(CPath p, CString fn)
00313 {
00314 if(fn.Find(':') >= 0 || fn.Find(_T("\\")) == 0) return fn;
00315 p.Append(CPath(fn));
00316 return (LPCTSTR)p;
00317 }
00318
00319 bool CPlayerPlaylistBar::ParseMPCPlayList(CString fn)
00320 {
00321 CString str;
00322 CMap<int, int, CPlaylistItem, CPlaylistItem&> pli;
00323 CArray<int> idx;
00324
00325 CWebTextFile f;
00326 if(!f.Open(fn) || !f.ReadString(str) || str != _T("MPCPLAYLIST"))
00327 return false;
00328
00329 CPath base(fn);
00330 base.RemoveFileSpec();
00331
00332 while(f.ReadString(str))
00333 {
00334 CList<CString> sl;
00335 Explode(str, sl, ',', 3);
00336 if(sl.GetCount() != 3) continue;
00337
00338 if(int i = _ttoi(sl.RemoveHead()))
00339 {
00340 CString key = sl.RemoveHead();
00341 CString value = sl.RemoveHead();
00342
00343 if(key == _T("type")) {pli[i].m_type = (CPlaylistItem::type_t)_ttol(value); idx.Add(i);}
00344 else if(key == _T("label")) pli[i].m_label = value;
00345 else if(key == _T("filename")) {value = CombinePath(base, value); pli[i].m_fns.AddTail(value);}
00346 else if(key == _T("subtitle")) {value = CombinePath(base, value); pli[i].m_subs.AddTail(value);}
00347 else if(key == _T("video")) {while(pli[i].m_fns.GetCount() < 2) pli[i].m_fns.AddTail(_T("")); pli[i].m_fns.GetHead() = value;}
00348 else if(key == _T("audio")) {while(pli[i].m_fns.GetCount() < 2) pli[i].m_fns.AddTail(_T("")); pli[i].m_fns.GetTail() = value;}
00349 else if(key == _T("vinput")) pli[i].m_vinput = _ttol(value);
00350 else if(key == _T("vchannel")) pli[i].m_vchannel = _ttol(value);
00351 else if(key == _T("ainput")) pli[i].m_ainput = _ttol(value);
00352 else if(key == _T("country")) pli[i].m_country = _ttol(value);
00353 }
00354 }
00355
00356 qsort(idx.GetData(), idx.GetCount(), sizeof(int), s_int_comp);
00357 for(int i = 0; i < idx.GetCount(); i++)
00358 m_pl.AddTail(pli[idx[i]]);
00359
00360 return pli.GetCount() > 0;
00361 }
00362
00363 bool CPlayerPlaylistBar::SaveMPCPlayList(CString fn, CTextFile::enc e, bool fRemovePath)
00364 {
00365 CTextFile f;
00366 if(!f.Save(fn, e))
00367 return false;
00368
00369 f.WriteString(_T("MPCPLAYLIST\n"));
00370
00371 POSITION pos = m_pl.GetHeadPosition(), pos2;
00372 for(int i = 1; pos; i++)
00373 {
00374 CPlaylistItem& pli = m_pl.GetNext(pos);
00375
00376 CString idx;
00377 idx.Format(_T("%d"), i);
00378
00379 CString str;
00380 str.Format(_T("%d,type,%d"), i, pli.m_type);
00381 f.WriteString(str + _T("\n"));
00382
00383 if(!pli.m_label.IsEmpty())
00384 f.WriteString(idx + _T(",label,") + pli.m_label + _T("\n"));
00385
00386 if(pli.m_type == CPlaylistItem::file)
00387 {
00388 pos2 = pli.m_fns.GetHeadPosition();
00389 while(pos2)
00390 {
00391 CString fn = pli.m_fns.GetNext(pos2);
00392 if(fRemovePath) {CPath p(fn); p.StripPath(); fn = (LPCTSTR)p;}
00393 f.WriteString(idx + _T(",filename,") + fn + _T("\n"));
00394 }
00395
00396 pos2 = pli.m_subs.GetHeadPosition();
00397 while(pos2)
00398 {
00399 CString fn = pli.m_subs.GetNext(pos2);
00400 if(fRemovePath) {CPath p(fn); p.StripPath(); fn = (LPCTSTR)p;}
00401 f.WriteString(idx + _T(",subtitle,") + fn + _T("\n"));
00402 }
00403 }
00404 else if(pli.m_type == CPlaylistItem::device && pli.m_fns.GetCount() == 2)
00405 {
00406 f.WriteString(idx + _T(",video,") + pli.m_fns.GetHead() + _T("\n"));
00407 f.WriteString(idx + _T(",audio,") + pli.m_fns.GetTail() + _T("\n"));
00408 str.Format(_T("%d,vinput,%d"), i, pli.m_vinput);
00409 f.WriteString(str + _T("\n"));
00410 str.Format(_T("%d,vchannel,%d"), i, pli.m_vchannel);
00411 f.WriteString(str + _T("\n"));
00412 str.Format(_T("%d,ainput,%d"), i, pli.m_ainput);
00413 f.WriteString(str + _T("\n"));
00414 str.Format(_T("%d,country,%d"), i, pli.m_country);
00415 f.WriteString(str + _T("\n"));
00416 }
00417 }
00418
00419 return true;
00420 }
00421
00422 void CPlayerPlaylistBar::Refresh()
00423 {
00424 SetupList();
00425 ResizeListColumn();
00426 }
00427
00428 void CPlayerPlaylistBar::Empty()
00429 {
00430 m_pl.RemoveAll();
00431 m_list.DeleteAllItems();
00432 SavePlaylist();
00433 }
00434
00435 void CPlayerPlaylistBar::Open(CList<CString>& fns, bool fMulti, CList<CString>* subs)
00436 {
00437 Empty();
00438 Append(fns, fMulti, subs);
00439 }
00440
00441 void CPlayerPlaylistBar::Append(CList<CString>& fns, bool fMulti, CList<CString>* subs)
00442 {
00443 if(fMulti)
00444 {
00445 ASSERT(subs == NULL || subs->GetCount() == 0);
00446 POSITION pos = fns.GetHeadPosition();
00447 while(pos) ParsePlayList(fns.GetNext(pos), NULL);
00448 }
00449 else
00450 {
00451 ParsePlayList(fns, subs);
00452 }
00453
00454 Refresh();
00455 SavePlaylist();
00456 }
00457
00458 void CPlayerPlaylistBar::Open(CStringW vdn, CStringW adn, int vinput, int vchannel, int ainput)
00459 {
00460 Empty();
00461 Append(vdn, adn, vinput, vchannel, ainput);
00462 }
00463
00464 void CPlayerPlaylistBar::Append(CStringW vdn, CStringW adn, int vinput, int vchannel, int ainput)
00465 {
00466 CPlaylistItem pli;
00467 pli.m_type = CPlaylistItem::device;
00468 pli.m_fns.AddTail(CString(vdn));
00469 pli.m_fns.AddTail(CString(adn));
00470 pli.m_vinput = vinput;
00471 pli.m_vchannel = vchannel;
00472 pli.m_ainput = ainput;
00473 CList<CStringW> sl;
00474 CStringW vfn = GetFriendlyName(vdn);
00475 CStringW afn = GetFriendlyName(adn);
00476 if(!vfn.IsEmpty()) sl.AddTail(vfn);
00477 if(!afn.IsEmpty()) sl.AddTail(afn);
00478 CStringW label = Implode(sl, '|');
00479 label.Replace(L"|", L" - ");
00480 pli.m_label = CString(label);
00481 m_pl.AddTail(pli);
00482
00483 Refresh();
00484 SavePlaylist();
00485 }
00486
00487 void CPlayerPlaylistBar::SetupList()
00488 {
00489 m_list.DeleteAllItems();
00490
00491 POSITION pos = m_pl.GetHeadPosition();
00492 for(int i = 0; pos; i++)
00493 {
00494 CPlaylistItem& pli = m_pl.GetAt(pos);
00495 m_list.SetItemData(m_list.InsertItem(i, pli.GetLabel()), (DWORD_PTR)pos);
00496 m_list.SetItemText(i, COL_TIME, pli.GetLabel(1));
00497 m_pl.GetNext(pos);
00498 }
00499 }
00500
00501 void CPlayerPlaylistBar::UpdateList()
00502 {
00503 POSITION pos = m_pl.GetHeadPosition();
00504 for(int i = 0, j = m_list.GetItemCount(); pos && i < j; i++)
00505 {
00506 CPlaylistItem& pli = m_pl.GetAt(pos);
00507 m_list.SetItemData(i, (DWORD_PTR)pos);
00508 m_list.SetItemText(i, COL_NAME, pli.GetLabel(0));
00509 m_list.SetItemText(i, COL_TIME, pli.GetLabel(1));
00510 m_pl.GetNext(pos);
00511 }
00512 }
00513
00514 void CPlayerPlaylistBar::EnsureVisible(POSITION pos)
00515 {
00516 int i = FindItem(m_pl.GetPos());
00517 if(i < 0) return;
00518 m_list.EnsureVisible(i, TRUE);
00519 m_list.Invalidate();
00520 }
00521
00522 int CPlayerPlaylistBar::FindItem(POSITION pos)
00523 {
00524 for(int i = 0; i < m_list.GetItemCount(); i++)
00525 if((POSITION)m_list.GetItemData(i) == pos)
00526 return(i);
00527 return(-1);
00528 }
00529
00530 POSITION CPlayerPlaylistBar::FindPos(int i)
00531 {
00532 if(i < 0) return(NULL);
00533 return((POSITION)m_list.GetItemData(i));
00534 }
00535
00536 int CPlayerPlaylistBar::GetCount()
00537 {
00538 return(m_pl.GetCount());
00539 }
00540
00541 int CPlayerPlaylistBar::GetSelIdx()
00542 {
00543 return(FindItem(m_pl.GetPos()));
00544 }
00545
00546 void CPlayerPlaylistBar::SetSelIdx(int i)
00547 {
00548 m_pl.SetPos(FindPos(i));
00549 }
00550
00551 bool CPlayerPlaylistBar::IsAtEnd()
00552 {
00553 return(m_pl.GetPos() && m_pl.GetPos() == m_pl.GetTailPosition());
00554 }
00555
00556 bool CPlayerPlaylistBar::GetCur(CPlaylistItem& pli)
00557 {
00558 if(!m_pl.GetPos()) return(false);
00559 pli = m_pl.GetAt(m_pl.GetPos());
00560 return(true);
00561 }
00562
00563 CString CPlayerPlaylistBar::GetCur()
00564 {
00565 CString fn;
00566 CPlaylistItem pli;
00567 if(GetCur(pli) && !pli.m_fns.IsEmpty()) fn = pli.m_fns.GetHead();
00568 return(fn);
00569 }
00570
00571 void CPlayerPlaylistBar::SetNext()
00572 {
00573 POSITION pos = m_pl.GetPos(), org = pos;
00574 while(m_pl.GetNextWrap(pos).m_fInvalid && pos != org);
00575 UpdateList();
00576 m_pl.SetPos(pos);
00577 EnsureVisible(pos);
00578 }
00579
00580 void CPlayerPlaylistBar::SetPrev()
00581 {
00582 POSITION pos = m_pl.GetPos(), org = pos;
00583 while(m_pl.GetPrevWrap(pos).m_fInvalid && pos != org);
00584 m_pl.SetPos(pos);
00585 EnsureVisible(pos);
00586 }
00587
00588 void CPlayerPlaylistBar::SetFirst()
00589 {
00590 POSITION pos = m_pl.GetTailPosition(), org = pos;
00591 while(m_pl.GetNextWrap(pos).m_fInvalid && pos != org);
00592 UpdateList();
00593 m_pl.SetPos(pos);
00594 EnsureVisible(pos);
00595 }
00596
00597 void CPlayerPlaylistBar::SetLast()
00598 {
00599 POSITION pos = m_pl.GetHeadPosition(), org = pos;
00600 while(m_pl.GetPrevWrap(pos).m_fInvalid && pos != org);
00601 m_pl.SetPos(pos);
00602 EnsureVisible(pos);
00603 }
00604
00605 void CPlayerPlaylistBar::SetCurValid(bool fValid)
00606 {
00607 if(POSITION pos = m_pl.GetPos())
00608 {
00609 if(m_pl.GetAt(pos).m_fInvalid = !fValid)
00610 {
00611 int i = FindItem(pos);
00612 m_list.RedrawItems(i, i);
00613 }
00614 }
00615 }
00616
00617 void CPlayerPlaylistBar::SetCurTime(REFERENCE_TIME rt)
00618 {
00619 if(POSITION pos = m_pl.GetPos())
00620 {
00621 CPlaylistItem& pli = m_pl.GetAt(pos);
00622 pli.m_duration = rt;
00623 m_list.SetItemText(FindItem(pos), COL_TIME, pli.GetLabel(1));
00624 }
00625 }
00626
00627 OpenMediaData* CPlayerPlaylistBar::GetCurOMD(REFERENCE_TIME rtStart)
00628 {
00629 CPlaylistItem pli;
00630 if(!GetCur(pli)) return NULL;
00631
00632 CString fn = CString(pli.m_fns.GetHead()).MakeLower();
00633
00634 if(fn.Find(_T("video_ts.ifo")) >= 0
00635 || fn.Find(_T(".ratdvd")) >= 0)
00636 {
00637 if(OpenDVDData* p = new OpenDVDData())
00638 {
00639 p->path = pli.m_fns.GetHead();
00640 p->subs.AddTail(&pli.m_subs);
00641 return p;
00642 }
00643 }
00644
00645 if(pli.m_type == CPlaylistItem::device)
00646 {
00647 if(OpenDeviceData* p = new OpenDeviceData())
00648 {
00649 POSITION pos = pli.m_fns.GetHeadPosition();
00650 for(int i = 0; i < countof(p->DisplayName) && pos; i++)
00651 p->DisplayName[i] = pli.m_fns.GetNext(pos);
00652 p->vinput = pli.m_vinput;
00653 p->vchannel = pli.m_vchannel;
00654 p->ainput = pli.m_ainput;
00655 return p;
00656 }
00657 }
00658 else
00659 {
00660 if(OpenFileData* p = new OpenFileData())
00661 {
00662 p->fns.AddTail((CList<CString>*)&pli.m_fns);
00663 p->subs.AddTail((CList<CString>*)&pli.m_subs);
00664 p->rtStart = rtStart;
00665 return p;
00666 }
00667 }
00668
00669 return NULL;
00670 }
00671
00672 void CPlayerPlaylistBar::LoadPlaylist()
00673 {
00674 CString base;
00675 if(AfxGetMyApp()->GetAppDataPath(base))
00676 {
00677 CPath p;
00678 p.Combine(base, _T("default.mpcpl"));
00679
00680 if(!AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), TRUE))
00681 {
00682 DeleteFile(p);
00683 }
00684 else
00685 {
00686 ParseMPCPlayList(p);
00687 Refresh();
00688 }
00689 }
00690 }
00691
00692 void CPlayerPlaylistBar::SavePlaylist()
00693 {
00694 CString base;
00695 if(AfxGetMyApp()->GetAppDataPath(base))
00696 {
00697 CPath p;
00698 p.Combine(base, _T("default.mpcpl"));
00699
00700 if(!AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), TRUE))
00701 {
00702 DeleteFile(p);
00703 }
00704 else
00705 {
00706 SaveMPCPlayList(p, CTextFile::UTF8, false);
00707 }
00708 }
00709 }
00710
00711 BEGIN_MESSAGE_MAP(CPlayerPlaylistBar, CSizingControlBarG)
00712 ON_WM_SIZE()
00713 ON_NOTIFY(LVN_KEYDOWN, IDC_PLAYLIST, OnLvnKeyDown)
00714 ON_NOTIFY(NM_DBLCLK, IDC_PLAYLIST, OnNMDblclkList)
00715
00716 ON_WM_DRAWITEM()
00717 ON_COMMAND_EX(ID_FILE_CLOSEPLAYLIST, OnFileClosePlaylist)
00718 ON_COMMAND_EX(ID_PLAY_PLAY, OnPlayPlay)
00719 ON_WM_DROPFILES()
00720 ON_NOTIFY(LVN_BEGINDRAG, IDC_PLAYLIST, OnBeginDrag)
00721 ON_WM_MOUSEMOVE()
00722 ON_WM_LBUTTONUP()
00723 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
00724 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
00725 ON_WM_TIMER()
00726 ON_WM_CONTEXTMENU()
00727 ON_NOTIFY(LVN_ENDLABELEDIT, IDC_PLAYLIST, OnLvnEndlabeleditList)
00728 END_MESSAGE_MAP()
00729
00730
00731
00732
00733 void CPlayerPlaylistBar::ResizeListColumn()
00734 {
00735 if(::IsWindow(m_list.m_hWnd))
00736 {
00737 CRect r;
00738 GetClientRect(r);
00739 r.DeflateRect(2, 2);
00740 m_list.SetRedraw(FALSE);
00741 m_list.MoveWindow(r);
00742 m_list.GetClientRect(r);
00743 m_list.SetColumnWidth(COL_NAME, r.Width()-m_nTimeColWidth);
00744 m_list.SetRedraw(TRUE);
00745 }
00746 }
00747
00748 void CPlayerPlaylistBar::OnSize(UINT nType, int cx, int cy)
00749 {
00750 CSizingControlBarG::OnSize(nType, cx, cy);
00751
00752 ResizeListColumn();
00753 }
00754
00755 void CPlayerPlaylistBar::OnLvnKeyDown(NMHDR* pNMHDR, LRESULT* pResult)
00756 {
00757 LPNMLVKEYDOWN pLVKeyDown = reinterpret_cast<LPNMLVKEYDOWN>(pNMHDR);
00758
00759 *pResult = FALSE;
00760
00761 CList<int> items;
00762 POSITION pos = m_list.GetFirstSelectedItemPosition();
00763 while(pos) items.AddHead(m_list.GetNextSelectedItem(pos));
00764
00765 if(pLVKeyDown->wVKey == VK_DELETE && items.GetCount() > 0)
00766 {
00767 pos = items.GetHeadPosition();
00768 while(pos)
00769 {
00770 int i = items.GetNext(pos);
00771 if(m_pl.RemoveAt(FindPos(i))) ((CMainFrame*)AfxGetMainWnd())->CloseMedia();
00772 m_list.DeleteItem(i);
00773 }
00774
00775 m_list.SetItemState(-1, 0, LVIS_SELECTED);
00776 m_list.SetItemState(
00777 max(min(items.GetTail(), m_list.GetItemCount()-1), 0),
00778 LVIS_SELECTED, LVIS_SELECTED);
00779
00780 ResizeListColumn();
00781
00782 *pResult = TRUE;
00783 }
00784 else if(pLVKeyDown->wVKey == VK_SPACE && items.GetCount() == 1)
00785 {
00786 m_pl.SetPos(FindPos(items.GetHead()));
00787
00788 ((CMainFrame*)AfxGetMainWnd())->OpenCurPlaylistItem();
00789
00790 *pResult = TRUE;
00791 }
00792 }
00793
00794 void CPlayerPlaylistBar::OnNMDblclkList(NMHDR* pNMHDR, LRESULT* pResult)
00795 {
00796 LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)pNMHDR;
00797
00798 if(lpnmlv->iItem >= 0 && lpnmlv->iSubItem >= 0)
00799 {
00800 m_pl.SetPos(FindPos(lpnmlv->iItem));
00801 m_list.Invalidate();
00802 ((CMainFrame*)AfxGetMainWnd())->OpenCurPlaylistItem();
00803 }
00804
00805 *pResult = 0;
00806 }
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 void CPlayerPlaylistBar::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
00850 {
00851 if(nIDCtl != IDC_PLAYLIST) return;
00852
00853 int nItem = lpDrawItemStruct->itemID;
00854 CRect rcItem = lpDrawItemStruct->rcItem;
00855 POSITION pos = FindPos(nItem);
00856 bool fSelected = pos == m_pl.GetPos();
00857 CPlaylistItem& pli = m_pl.GetAt(pos);
00858
00859 CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
00860
00861 if(!!m_list.GetItemState(nItem, LVIS_SELECTED))
00862 {
00863 FillRect(pDC->m_hDC, rcItem, CBrush(0xf1dacc));
00864 FrameRect(pDC->m_hDC, rcItem, CBrush(0xc56a31));
00865 }
00866 else
00867 {
00868 FillRect(pDC->m_hDC, rcItem, CBrush(GetSysColor(COLOR_WINDOW)));
00869 }
00870
00871 COLORREF textcolor = fSelected?0xff:0;
00872 if(pli.m_fInvalid) textcolor |= 0xA0A0A0;
00873
00874 CString time = !pli.m_fInvalid ? m_list.GetItemText(nItem, COL_TIME) : _T("Invalid");
00875 CSize timesize(0, 0);
00876 CPoint timept(rcItem.right, 0);
00877 if(time.GetLength() > 0)
00878 {
00879 timesize = pDC->GetTextExtent(time);
00880 if((3+timesize.cx+3) < rcItem.Width()/2)
00881 {
00882 timept = CPoint(rcItem.right-(3+timesize.cx+3), (rcItem.top+rcItem.bottom-timesize.cy)/2);
00883
00884 pDC->SetTextColor(textcolor);
00885 pDC->TextOut(timept.x, timept.y, time);
00886 }
00887 }
00888
00889 CString fmt, file;
00890 fmt.Format(_T("%%0%dd. %%s"), (int)log10(0.1+m_pl.GetCount())+1);
00891 file.Format(fmt, nItem+1, m_list.GetItemText(nItem, COL_NAME));
00892 CSize filesize = pDC->GetTextExtent(file);
00893 while(3+filesize.cx+6 > timept.x && file.GetLength() > 3)
00894 {
00895 file = file.Left(file.GetLength()-4) + _T("...");
00896 filesize = pDC->GetTextExtent(file);
00897 }
00898
00899 if(file.GetLength() > 3)
00900 {
00901 pDC->SetTextColor(textcolor);
00902 pDC->TextOut(rcItem.left+3, (rcItem.top+rcItem.bottom-filesize.cy)/2, file);
00903 }
00904 }
00905
00906 BOOL CPlayerPlaylistBar::OnFileClosePlaylist(UINT nID)
00907 {
00908 Empty();
00909 return FALSE;
00910 }
00911
00912 BOOL CPlayerPlaylistBar::OnPlayPlay(UINT nID)
00913 {
00914 m_list.Invalidate();
00915 return FALSE;
00916 }
00917
00918 void CPlayerPlaylistBar::OnDropFiles(HDROP hDropInfo)
00919 {
00920 SetActiveWindow();
00921
00922 CList<CString> sl;
00923
00924 UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
00925 for(UINT iFile = 0; iFile < nFiles; iFile++)
00926 {
00927 TCHAR szFileName[_MAX_PATH];
00928 ::DragQueryFile(hDropInfo, iFile, szFileName, _MAX_PATH);
00929 sl.AddTail(szFileName);
00930 }
00931 ::DragFinish(hDropInfo);
00932
00933 Append(sl, true);
00934 }
00935
00936 void CPlayerPlaylistBar::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult)
00937 {
00938 ModifyStyle(WS_EX_ACCEPTFILES, 0);
00939
00940 m_nDragIndex = ((LPNMLISTVIEW)pNMHDR)->iItem;
00941
00942 CPoint p(0, 0);
00943 m_pDragImage = m_list.CreateDragImageEx(&p);
00944
00945 CPoint p2 = ((LPNMLISTVIEW)pNMHDR)->ptAction;
00946
00947 m_pDragImage->BeginDrag(0, p2 - p);
00948 m_pDragImage->DragEnter(GetDesktopWindow(), ((LPNMLISTVIEW)pNMHDR)->ptAction);
00949
00950 m_bDragging = TRUE;
00951 m_nDropIndex = -1;
00952
00953 SetCapture();
00954 }
00955
00956 void CPlayerPlaylistBar::OnMouseMove(UINT nFlags, CPoint point)
00957 {
00958 if(m_bDragging)
00959 {
00960 m_ptDropPoint = point;
00961 ClientToScreen(&m_ptDropPoint);
00962
00963 m_pDragImage->DragMove(m_ptDropPoint);
00964 m_pDragImage->DragShowNolock(FALSE);
00965
00966 WindowFromPoint(m_ptDropPoint)->ScreenToClient(&m_ptDropPoint);
00967
00968 m_pDragImage->DragShowNolock(TRUE);
00969
00970 {
00971 int iOverItem = m_list.HitTest(m_ptDropPoint);
00972 int iTopItem = m_list.GetTopIndex();
00973 int iBottomItem = m_list.GetBottomIndex();
00974
00975 if(iOverItem == iTopItem && iTopItem != 0)
00976 SetTimer(1, 100, NULL);
00977 else
00978 KillTimer(1);
00979
00980 if(iOverItem >= iBottomItem && iBottomItem != (m_list.GetItemCount() - 1))
00981 SetTimer(2, 100, NULL);
00982 else
00983 KillTimer(2);
00984 }
00985 }
00986
00987 __super::OnMouseMove(nFlags, point);
00988 }
00989
00990 void CPlayerPlaylistBar::OnTimer(UINT nIDEvent)
00991 {
00992 int iTopItem = m_list.GetTopIndex();
00993 int iBottomItem = iTopItem + m_list.GetCountPerPage() - 1;
00994
00995 if(m_bDragging)
00996 {
00997 m_pDragImage->DragShowNolock(FALSE);
00998
00999 if(nIDEvent == 1)
01000 {
01001 m_list.EnsureVisible(iTopItem - 1, false);
01002 m_list.UpdateWindow();
01003 if(m_list.GetTopIndex() == 0) KillTimer(1);
01004 }
01005 else if(nIDEvent == 2)
01006 {
01007 m_list.EnsureVisible(iBottomItem + 1, false);
01008 m_list.UpdateWindow();
01009 if(m_list.GetBottomIndex() == (m_list.GetItemCount() - 1)) KillTimer(2);
01010 }
01011
01012 m_pDragImage->DragShowNolock(TRUE);
01013 }
01014
01015 __super::OnTimer(nIDEvent);
01016 }
01017
01018 void CPlayerPlaylistBar::OnLButtonUp(UINT nFlags, CPoint point)
01019 {
01020 if(m_bDragging)
01021 {
01022 ::ReleaseCapture();
01023
01024 m_bDragging = FALSE;
01025 m_pDragImage->DragLeave(GetDesktopWindow());
01026 m_pDragImage->EndDrag();
01027
01028 delete m_pDragImage;
01029 m_pDragImage = NULL;
01030
01031 KillTimer(1);
01032 KillTimer(2);
01033
01034 CPoint pt(point);
01035 ClientToScreen(&pt);
01036
01037 if(WindowFromPoint(pt) == &m_list)
01038 DropItemOnList();
01039 }
01040
01041 ModifyStyle(0, WS_EX_ACCEPTFILES);
01042
01043 __super::OnLButtonUp(nFlags, point);
01044 }
01045
01046 void CPlayerPlaylistBar::DropItemOnList()
01047 {
01048 m_ptDropPoint.y += 10;
01049 m_nDropIndex = m_list.HitTest(CPoint(10, m_ptDropPoint.y));
01050
01051 TCHAR szLabel[MAX_PATH];
01052 LV_ITEM lvi;
01053 ZeroMemory(&lvi, sizeof(LV_ITEM));
01054 lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
01055 lvi.stateMask = LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED;
01056 lvi.pszText = szLabel;
01057 lvi.iItem = m_nDragIndex;
01058 lvi.cchTextMax = MAX_PATH;
01059 m_list.GetItem(&lvi);
01060
01061 if(m_nDropIndex < 0) m_nDropIndex = m_list.GetItemCount();
01062 lvi.iItem = m_nDropIndex;
01063 m_list.InsertItem(&lvi);
01064
01065 CHeaderCtrl* pHeader = (CHeaderCtrl*)m_list.GetDlgItem(0);
01066 int nColumnCount = pHeader->GetItemCount();
01067 lvi.mask = LVIF_TEXT;
01068 lvi.iItem = m_nDropIndex;
01069
01070 if(m_nDropIndex < m_nDragIndex) m_nDragIndex++;
01071 for(int col=1; col < nColumnCount; col++)
01072 {
01073 _tcscpy(lvi.pszText, (LPCTSTR)(m_list.GetItemText(m_nDragIndex, col)));
01074 lvi.iSubItem = col;
01075 m_list.SetItem(&lvi);
01076 }
01077
01078 m_list.DeleteItem(m_nDragIndex);
01079
01080 CList<CPlaylistItem> tmp;
01081 UINT id = -1;
01082 for(int i = 0; i < m_list.GetItemCount(); i++)
01083 {
01084 POSITION pos = (POSITION)m_list.GetItemData(i);
01085 CPlaylistItem& pli = m_pl.GetAt(pos);
01086 tmp.AddTail(pli);
01087 if(pos == m_pl.GetPos()) id = pli.m_id;
01088 }
01089 m_pl.RemoveAll();
01090 POSITION pos = tmp.GetHeadPosition();
01091 for(int i = 0; pos; i++)
01092 {
01093 CPlaylistItem& pli = tmp.GetNext(pos);
01094 m_pl.AddTail(pli);
01095 if(pli.m_id == id) m_pl.SetPos(m_pl.GetTailPosition());
01096 m_list.SetItemData(i, (DWORD_PTR)m_pl.GetTailPosition());
01097 }
01098
01099 ResizeListColumn();
01100 }
01101
01102 BOOL CPlayerPlaylistBar::OnToolTipNotify(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
01103 {
01104 TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
01105 TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
01106
01107 if((pNMHDR->code == TTN_NEEDTEXTA && (HWND)pTTTA->lParam != m_list.m_hWnd)
01108 || (pNMHDR->code == TTN_NEEDTEXTW && (HWND)pTTTW->lParam != m_list.m_hWnd))
01109 return FALSE;
01110
01111 int row = ((pNMHDR->idFrom-1) >> 10) & 0x3fffff;
01112 int col = (pNMHDR->idFrom-1) & 0x3ff;
01113
01114 if(row < 0 || row >= m_pl.GetCount())
01115 return FALSE;
01116
01117 CPlaylistItem& pli = m_pl.GetAt(FindPos(row));
01118
01119 CString strTipText;
01120
01121 if(col == COL_NAME)
01122 {
01123 POSITION pos = pli.m_fns.GetHeadPosition();
01124 while(pos) strTipText += _T("\n") + pli.m_fns.GetNext(pos);
01125 strTipText.Trim();
01126
01127 if(pli.m_type == CPlaylistItem::device)
01128 {
01129 CString str;
01130 str.Format(_T("Video Input %d"), pli.m_vinput);
01131 if(pli.m_vinput >= 0) strTipText += _T("\n") + str;
01132 str.Format(_T("Video Channel %d"), pli.m_vchannel);
01133 if(pli.m_vchannel >= 0) strTipText += _T("\n") + str;
01134 str.Format(_T("Audio Input %d"), pli.m_ainput);
01135 if(pli.m_ainput >= 0) strTipText += _T("\n") + str;
01136 }
01137
01138 ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, (LPARAM)(INT)1000);
01139 }
01140 else if(col == COL_TIME)
01141 {
01142 return FALSE;
01143 }
01144
01145 static CStringA m_strTipTextA;
01146 static CStringW m_strTipTextW;
01147
01148 if(pNMHDR->code == TTN_NEEDTEXTA)
01149 {
01150 m_strTipTextA = strTipText;
01151 pTTTA->lpszText = (LPSTR)(LPCSTR)m_strTipTextA;
01152 }
01153 else
01154 {
01155 m_strTipTextW = strTipText;
01156 pTTTW->lpszText = (LPWSTR)(LPCWSTR)m_strTipTextW;
01157 }
01158
01159 *pResult = 0;
01160
01161 return TRUE;
01162 }
01163
01164 void CPlayerPlaylistBar::OnContextMenu(CWnd* , CPoint p)
01165 {
01166 LVHITTESTINFO lvhti;
01167 lvhti.pt = p;
01168 m_list.ScreenToClient(&lvhti.pt);
01169 m_list.SubItemHitTest(&lvhti);
01170
01171 POSITION pos = FindPos(lvhti.iItem);
01172
01173 bool fOnItem = !!(lvhti.flags&LVHT_ONITEM);
01174
01175 CMenu m;
01176 m.CreatePopupMenu();
01177
01178 enum
01179 {
01180 M_OPEN=1, M_ADD, M_REMOVE, M_CLIPBOARD, M_SAVEAS,
01181 M_SORTBYNAME, M_SORTBYPATH, M_RANDOMIZE, M_SORTBYID,
01182 M_REMEMBERPLAYLIST, M_SHUFFLE
01183 };
01184
01185 m.AppendMenu(MF_STRING|(!fOnItem?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_OPEN, ResStr(IDS_PLAYLIST_OPEN));
01186 if(((CMainFrame*)AfxGetMainWnd())->m_iPlaybackMode == PM_CAPTURE) m.AppendMenu(MF_STRING|MF_ENABLED, M_ADD, ResStr(IDS_PLAYLIST_ADD));
01187 m.AppendMenu(MF_STRING|(!fOnItem?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_REMOVE, ResStr(IDS_PLAYLIST_REMOVE));
01188 m.AppendMenu(MF_SEPARATOR);
01189 m.AppendMenu(MF_STRING|(!fOnItem?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_CLIPBOARD, ResStr(IDS_PLAYLIST_COPYTOCLIPBOARD));
01190 m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_SAVEAS, ResStr(IDS_PLAYLIST_SAVEAS));
01191 m.AppendMenu(MF_SEPARATOR);
01192 m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_SORTBYNAME, ResStr(IDS_PLAYLIST_SORTBYLABEL));
01193 m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_SORTBYPATH, ResStr(IDS_PLAYLIST_SORTBYPATH));
01194 m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_RANDOMIZE, ResStr(IDS_PLAYLIST_RANDOMIZE));
01195 m.AppendMenu(MF_STRING|(!m_pl.GetCount()?(MF_DISABLED|MF_GRAYED):MF_ENABLED), M_SORTBYID, ResStr(IDS_PLAYLIST_RESTORE));
01196 m.AppendMenu(MF_SEPARATOR);
01197 m.AppendMenu(MF_STRING|MF_ENABLED|(AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("ShufflePlaylistItems"), FALSE)?MF_CHECKED:0), M_SHUFFLE, _T("Shuffle"));
01198 m.AppendMenu(MF_STRING|MF_ENABLED|(AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), TRUE)?MF_CHECKED:0), M_REMEMBERPLAYLIST, _T("Remember items"));
01199
01200 CMainFrame* pMainFrm = (CMainFrame*)AfxGetMainWnd();
01201
01202 int nID = (int)m.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, this);
01203 switch(nID)
01204 {
01205 case M_OPEN:
01206 m_pl.SetPos(pos);
01207 m_list.Invalidate();
01208 pMainFrm->OpenCurPlaylistItem();
01209 break;
01210 case M_ADD:
01211 pMainFrm->AddCurDevToPlaylist();
01212 m_pl.SetPos(m_pl.GetTailPosition());
01213 break;
01214 case M_REMOVE:
01215 if(m_pl.RemoveAt(pos)) pMainFrm->CloseMedia();
01216 m_list.DeleteItem(lvhti.iItem);
01217 SavePlaylist();
01218 break;
01219 case M_SORTBYID:
01220 m_pl.SortById();
01221 SetupList();
01222 SavePlaylist();
01223 break;
01224 case M_SORTBYNAME:
01225 m_pl.SortByName();
01226 SetupList();
01227 SavePlaylist();
01228 break;
01229 case M_SORTBYPATH:
01230 m_pl.SortByPath();
01231 SetupList();
01232 SavePlaylist();
01233 break;
01234 case M_RANDOMIZE:
01235 m_pl.Randomize();
01236 SetupList();
01237 SavePlaylist();
01238 break;
01239 case M_CLIPBOARD:
01240 if(OpenClipboard() && EmptyClipboard())
01241 {
01242 CString str;
01243
01244 CPlaylistItem& pli = m_pl.GetAt(pos);
01245 POSITION pos = pli.m_fns.GetHeadPosition();
01246 while(pos) str += _T("\r\n") + pli.m_fns.GetNext(pos);
01247 str.Trim();
01248
01249 if(HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, (str.GetLength()+1)*sizeof(TCHAR)))
01250 {
01251 if(TCHAR* s = (TCHAR*)GlobalLock(h))
01252 {
01253 _tcscpy(s, str);
01254 GlobalUnlock(h);
01255 #ifdef UNICODE
01256 SetClipboardData(CF_UNICODETEXT, h);
01257 #else
01258 SetClipboardData(CF_TEXT, h);
01259 #endif
01260 }
01261 }
01262 CloseClipboard();
01263 }
01264 break;
01265 case M_SAVEAS:
01266 {
01267 CSaveTextFileDialog fd(
01268 CTextFile::ASCII, NULL, NULL,
01269 _T("Media Player Classic playlist (*.mpcpl)|*.mpcpl|Playlist (*.pls)|*.pls|WinAmp playlist (*.m3u)|*.m3u|Windows Media Playlist (*.asx)|*.asx||"),
01270 this);
01271
01272 if(fd.DoModal() != IDOK)
01273 break;
01274
01275 int idx = fd.m_pOFN->nFilterIndex;
01276
01277 CPath path(fd.GetPathName());
01278
01279 switch(idx)
01280 {
01281 case 1: path.AddExtension(_T(".mpcpl")); break;
01282 case 2: path.AddExtension(_T(".pls")); break;
01283 case 3: path.AddExtension(_T(".m3u")); break;
01284 case 4: path.AddExtension(_T(".asx")); break;
01285 default: break;
01286 }
01287
01288 bool fRemovePath = true;
01289
01290 CPath p(path);
01291 p.RemoveFileSpec();
01292 CString base = (LPCTSTR)p;
01293
01294 pos = m_pl.GetHeadPosition();
01295 while(pos && fRemovePath)
01296 {
01297 CPlaylistItem& pli = m_pl.GetNext(pos);
01298
01299 if(pli.m_type != CPlaylistItem::file) fRemovePath = false;
01300 else
01301 {
01302 POSITION pos;
01303
01304 pos = pli.m_fns.GetHeadPosition();
01305 while(pos && fRemovePath)
01306 {
01307 CString fn = pli.m_fns.GetNext(pos);
01308
01309 CPath p(fn);
01310 p.RemoveFileSpec();
01311 if(base != (LPCTSTR)p) fRemovePath = false;
01312 }
01313
01314 pos = pli.m_subs.GetHeadPosition();
01315 while(pos && fRemovePath)
01316 {
01317 CString fn = pli.m_subs.GetNext(pos);
01318
01319 CPath p(fn);
01320 p.RemoveFileSpec();
01321 if(base != (LPCTSTR)p) fRemovePath = false;
01322 }
01323 }
01324 }
01325
01326 if(idx == 1)
01327 {
01328 SaveMPCPlayList(path, fd.GetEncoding(), fRemovePath);
01329 break;
01330 }
01331
01332 CTextFile f;
01333 if(!f.Save(path, fd.GetEncoding()))
01334 break;
01335
01336 if(idx == 4)
01337 {
01338 f.WriteString(_T("<ASX version = \"3.0\">\n"));
01339 }
01340
01341 pos = m_pl.GetHeadPosition();
01342 for(int i = 0; pos; i++)
01343 {
01344 CPlaylistItem& pli = m_pl.GetNext(pos);
01345
01346 if(pli.m_type != CPlaylistItem::file)
01347 continue;
01348
01349 CString fn = pli.m_fns.GetHead();
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360 CString str;
01361 switch(idx)
01362 {
01363 case 2: str.Format(_T("File%d=%s\n"), i+1, fn); break;
01364 case 3: str.Format(_T("%s\n"), fn); break;
01365 case 4: str.Format(_T("<Entry><Ref href = \"%s\"/></Entry>\n"), fn); break;
01366 default: break;
01367 }
01368 f.WriteString(str);
01369 }
01370
01371 if(idx == 4)
01372 {
01373 f.WriteString(_T("</ASX>\n"));
01374 }
01375 }
01376 break;
01377 case M_REMEMBERPLAYLIST:
01378 AfxGetApp()->WriteProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"),
01379 !AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("RememberPlaylistItems"), TRUE));
01380 break;
01381 case M_SHUFFLE:
01382 AfxGetApp()->WriteProfileInt(ResStr(IDS_R_SETTINGS), _T("ShufflePlaylistItems"),
01383 !AfxGetApp()->GetProfileInt(ResStr(IDS_R_SETTINGS), _T("ShufflePlaylistItems"), FALSE));
01384 break;
01385 default:
01386 break;
01387 }
01388 }
01389
01390 void CPlayerPlaylistBar::OnLvnEndlabeleditList(NMHDR* pNMHDR, LRESULT* pResult)
01391 {
01392 NMLVDISPINFO* pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
01393
01394 if(pDispInfo->item.iItem >= 0 && pDispInfo->item.pszText)
01395 {
01396 CPlaylistItem& pli = m_pl.GetAt((POSITION)m_list.GetItemData(pDispInfo->item.iItem));
01397 pli.m_label = pDispInfo->item.pszText;
01398 m_list.SetItemText(pDispInfo->item.iItem, 0, pDispInfo->item.pszText);
01399 }
01400
01401 *pResult = 0;
01402 }