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 }

Generated on Tue Dec 13 14:46:59 2005 for guliverkli by  doxygen 1.4.5