- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# PlayerPlaylistBar.cpp

    00001 /*
    00002  *      Copyright (C) 2003-2005 Gabest
    00003  *      http://www.gabest.org
    00004  *
    00005  *  This Program is free software; you can redistribute it and/or modify
    00006  *  it under the terms of the GNU General Public License as published by
    00007  *  the Free Software Foundation; either version 2, or (at your option)
    00008  *  any later version.
    00009  *
    00010  *  This Program is distributed in the hope that it will be useful,
    00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00013  *  GNU General Public License for more details.
    00014  *
    00015  *  You should have received a copy of the GNU General Public License
    00016  *  along with GNU Make; see the file COPYING.  If not, write to
    00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00018  *  http://www.gnu.org/copyleft/gpl.html
    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, // TODO: remove LVS_SINGLESEL and implement multiple item repositioning (dragging is ready)
    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         // resolve .lnk files
    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()); // TODO: n - .fInvalid
    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 //      ON_NOTIFY(NM_CUSTOMDRAW, IDC_PLAYLIST, OnCustomdrawList)
    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 // CPlayerPlaylistBar message handlers
    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); //LVSCW_AUTOSIZE_USEHEADER
    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 void CPlayerPlaylistBar::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
    00809 {
    00810         NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
    00811
    00812         *pResult = CDRF_DODEFAULT;
    00813
    00814         if(CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage)
    00815         {
    00816                 *pResult = CDRF_NOTIFYPOSTPAINT|CDRF_NOTIFYITEMDRAW;
    00817         }
    00818         else if(CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage)
    00819         {
    00820                 pLVCD->nmcd.uItemState &= ~CDIS_SELECTED;
    00821                 pLVCD->nmcd.uItemState &= ~CDIS_FOCUS;
    00822
    00823                 pLVCD->clrText = (pLVCD->nmcd.dwItemSpec == m_playList.m_idx) ? 0x0000ff : CLR_DEFAULT;
    00824                 pLVCD->clrTextBk = m_list.GetItemState(pLVCD->nmcd.dwItemSpec, LVIS_SELECTED) ? 0xf1dacc : CLR_DEFAULT;
    00825
    00826                 *pResult = CDRF_NOTIFYPOSTPAINT;
    00827         }
    00828         else if(CDDS_ITEMPOSTPAINT == pLVCD->nmcd.dwDrawStage)
    00829         {
    00830         int nItem = static_cast<int>(pLVCD->nmcd.dwItemSpec);
    00831
    00832                 if(m_list.GetItemState(pLVCD->nmcd.dwItemSpec, LVIS_SELECTED))
    00833                 {
    00834                         CRect r, r2;
    00835                         m_list.GetItemRect(nItem, &r, LVIR_BOUNDS);
    00836                         m_list.GetItemRect(nItem, &r2, LVIR_LABEL);
    00837                         r.left = r2.left;
    00838                         FrameRect(pLVCD->nmcd.hdc, &r, CBrush(0xc56a31));
    00839                 }
    00840
    00841                 *pResult = CDRF_SKIPDEFAULT;
    00842         }
    00843         else if(CDDS_POSTPAINT == pLVCD->nmcd.dwDrawStage)
    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) // top of list
    00976                                 SetTimer(1, 100, NULL);
    00977                         else
    00978                                 KillTimer(1);
    00979
    00980                         if(iOverItem >= iBottomItem && iBottomItem != (m_list.GetItemCount() - 1)) // bottom of list
    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         //INDEX OF DRAGGED ITEM WILL CHANGE IF ITEM IS DROPPED ABOVE ITSELF
    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;    // message was handled
    01162 }
    01163
    01164 void CPlayerPlaylistBar::OnContextMenu(CWnd* /*pWnd*/, 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 //      bool fSelected = (pos == m_pl.GetPos());
    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|(/*fSelected||*/!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                                 if(fRemovePath)
    01353                                 {
    01354                                         CPath p(path);
    01355                                         p.StripPath();
    01356                                         fn = (LPCTSTR)p;
    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 }