📄 playlist.cpp
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / Osmo4 wxWidgets GUI * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */#include "wxOsmo4.h"#include "Playlist.h"#include "playlist.xpm"PLEntry::PLEntry(wxString url){ m_url = strdup(url.mb_str(wxConvUTF8)); Bool is_remote = 0;; wxCharBuffer the_url = (const char *) url.mb_str(wxConvUTF8); const char *_url = strstr(the_url, "://"); if (_url) {_url += 3; is_remote = 1; } else _url = (const char *) the_url; char *str = strrchr(_url, '\\'); if (!str) str = strrchr(_url, '/'); if (str && strlen(str+1)) { m_disp_name = strdup(str+1); str = strrchr(m_disp_name, '.'); if (str) str[0] = 0; } else { m_disp_name = strdup(_url); if (!is_remote) { m_disp_name = strdup(_url); str = strrchr(m_disp_name, '.'); if (str) str[0] = 0; } } m_duration = 0; m_bIsDead = 0; m_bIsPlaying = 0; m_bIsSelected = 0;}PLEntry::~PLEntry(){ if (m_url) free(m_url); if (m_disp_name) free(m_disp_name);}wxPlaylist::wxPlaylist(wxWindow *parent) : wxFrame(parent, -1, wxString(_T("Osmo4 Playlist")), wxDefaultPosition, wxDefaultSize, wxCLOSE_BOX | wxSYSTEM_MENU | wxCAPTION | wxRESIZE_BORDER){ m_pApp = (wxOsmo4Frame *)parent; m_pOpen = new wxBitmap(pl_open); m_pSave = new wxBitmap(pl_save); m_pAdd = new wxBitmap(pl_add); m_pRem = new wxBitmap(pl_rem); m_pUp = new wxBitmap(pl_up); m_pDown = new wxBitmap(pl_down); m_pSort = new wxBitmap(pl_sort); m_pToolBar = CreateToolBar(wxTB_HORIZONTAL); m_pAddBut = new wxMenuButton(m_pToolBar, ID_PL_ADD_FILE, *m_pAdd); wxMenu *menu = new wxMenu(); menu->Append(ID_PL_ADD_URL, wxT("&Url")); menu->Append(ID_PL_ADD_DIR, wxT("&Directory")); menu->Append(ID_PL_ADD_DIR_REC, wxT("&Directory and subfolders")); m_pAddBut->AssignMenu(menu); m_pAddBut->SetToolTip(wxString(wxT("Add Files"))); m_pRemBut = new wxMenuButton(m_pToolBar, ID_PL_REM_FILE, *m_pRem); menu = new wxMenu(); menu->Append(ID_PL_REM_ALL, wxT("&Clear")); menu->Append(ID_PL_REM_DEAD, wxT("&Remove dead entries")); m_pRemBut->AssignMenu(menu); m_pRemBut->SetToolTip(wxString(wxT("Remove Selected Files"))); m_pSortBut = new wxMenuButton(m_pToolBar, ID_PL_SORT_FILE, *m_pSort); menu = new wxMenu(); menu->Append(ID_PL_SORT_TITLE, wxT("&Sort by Title")); menu->Append(ID_PL_SORT_FILE, wxT("&Sort by file name")); menu->Append(ID_PL_SORT_DUR, wxT("&Sort by Duration")); menu->AppendSeparator(); menu->Append(ID_PL_REVERSE, wxT("&Reverse")); menu->Append(ID_PL_RANDOMIZE, wxT("&Randomize")); m_pSortBut->AssignMenu(menu); m_pSortBut->SetToolTip(wxString(wxT("Sort Playlist by filename"))); m_pToolBar->AddTool(ID_PL_OPEN, wxT(""), *m_pOpen, wxT("Open Playlist")); m_pToolBar->AddTool(ID_PL_SAVE, wxT(""), *m_pSave, wxT("Save Playlist")); m_pToolBar->AddSeparator(); m_pToolBar->AddControl(m_pAddBut); m_pToolBar->AddControl(m_pRemBut); m_pToolBar->AddSeparator(); m_pToolBar->AddTool(ID_PL_UP, wxT(""), *m_pUp, wxT("Moves Selected Files Up")); m_pToolBar->AddTool(ID_PL_DOWN, wxT(""), *m_pDown, wxT("Moves Selected Files Down")); m_pToolBar->AddSeparator(); m_pToolBar->AddControl(m_pSortBut); m_pToolBar->Realize(); m_FileList = new wxListCtrl(this, ID_FILE_LIST, wxDefaultPosition, wxDefaultSize, wxLC_REPORT); m_FileList->InsertColumn(0, wxT(""), wxLIST_FORMAT_LEFT, 1); m_FileList->InsertColumn(1, wxT("Title"), wxLIST_FORMAT_LEFT, 1); m_FileList->InsertColumn(2, wxT("Duration"), wxLIST_FORMAT_LEFT, 1); m_entries = gf_list_new(); m_cur_entry = -1; m_all_dead_entries = -1; SetSize(220, 380); Centre();}wxPlaylist::~wxPlaylist(){ Clear(); gf_list_del(m_entries); delete m_pAddBut; delete m_pRemBut; delete m_pSortBut; delete m_pOpen; delete m_pSave; delete m_pAdd; delete m_pRem; delete m_pUp; delete m_pDown; delete m_pSort;}BEGIN_EVENT_TABLE(wxPlaylist, wxWindow) EVT_CLOSE(wxPlaylist::OnClose) EVT_SIZE(wxPlaylist::OnSize) EVT_TOOL(ID_PL_ADD_FILE, wxPlaylist::OnAddFile) EVT_TOOL(ID_PL_ADD_URL, wxPlaylist::OnAddURL) EVT_TOOL(ID_PL_ADD_DIR, wxPlaylist::OnAddDir) EVT_TOOL(ID_PL_ADD_DIR_REC, wxPlaylist::OnAddDirRec) EVT_TOOL(ID_PL_REM_FILE, wxPlaylist::OnRemFile) EVT_TOOL(ID_PL_REM_ALL, wxPlaylist::OnRemAll) EVT_TOOL(ID_PL_REM_DEAD, wxPlaylist::OnRemDead) EVT_TOOL(ID_PL_UP, wxPlaylist::OnSelUp) EVT_TOOL(ID_PL_DOWN, wxPlaylist::OnSelDown) EVT_TOOL(ID_PL_SAVE, wxPlaylist::OnSave) EVT_TOOL(ID_PL_OPEN, wxPlaylist::OnOpen) EVT_MENU(ID_PL_PLAY, wxPlaylist::OnPlay) EVT_MENU(ID_PL_RANDOMIZE, wxPlaylist::OnRandomize) EVT_MENU(ID_PL_REVERSE, wxPlaylist::OnReverseList) EVT_MENU(ID_PL_SEL_REV, wxPlaylist::OnReverseSelection) EVT_MENU(ID_PL_SORT_TITLE, wxPlaylist::OnSortTitle) EVT_MENU(ID_PL_SORT_FILE, wxPlaylist::OnSortFile) EVT_MENU(ID_PL_SORT_DUR, wxPlaylist::OnSortDuration) EVT_LIST_ITEM_ACTIVATED(ID_FILE_LIST, wxPlaylist::OnItemActivate) EVT_LIST_ITEM_RIGHT_CLICK(ID_FILE_LIST, wxPlaylist::OnRightClick)END_EVENT_TABLE()void wxPlaylist::OnClose(wxCloseEvent &event){ if (event.CanVeto()) { event.Veto(); Hide(); }}void wxPlaylist::OnSize(wxSizeEvent &event){ wxSize s = event.GetSize(); m_FileList->SetSize(0, 0, s.GetWidth()-2, s.GetHeight()); m_FileList->SetColumnWidth(0, 30); m_FileList->SetColumnWidth(2, 60); m_FileList->SetColumnWidth(1, s.GetWidth()-96);}void wxPlaylist::Clear(){ m_FileList->DeleteAllItems(); while (gf_list_count(m_entries)) { PLEntry *ple = (PLEntry *) gf_list_get(m_entries, 0); gf_list_rem(m_entries, 0); delete ple; } m_cur_entry = -1;}void wxPlaylist::ClearButPlaying(){ PLEntry *p = NULL; if (m_cur_entry >= 0) { p = (PLEntry *) gf_list_get(m_entries, m_cur_entry); gf_list_rem(m_entries, m_cur_entry); } Clear(); if (p) { gf_list_add(m_entries, p); m_cur_entry = 0; } RefreshList();}void wxPlaylist::UpdateEntry(u32 idx){ char szText[20]; PLEntry *ple = (PLEntry *) gf_list_get(m_entries, idx); if (idx+1<10) sprintf(szText, "00%d", idx+1); else if (idx+1<100) sprintf(szText, "0%d", idx+1); else sprintf(szText, "%d", idx+1); m_FileList->SetItem(idx, 0, wxString(szText, wxConvUTF8)); wxString str; if (ple->m_bIsDead) str = wxT("!! ") + wxString(ple->m_disp_name, wxConvUTF8) + wxT(" (DEAD)!!)"); else if (ple->m_bIsPlaying) str = wxT(">> ") + wxString(ple->m_disp_name, wxConvUTF8) + wxT(" >>"); else str = wxString(ple->m_disp_name, wxConvUTF8); m_FileList->SetItem(idx, 1, str); if (ple->m_duration) { u32 h = (u32) (ple->m_duration / 3600); u32 m = (u32) (ple->m_duration / 60) - h*60; u32 s = (u32) (ple->m_duration) - h*3600 - m*60; m_FileList->SetItem(idx, 2, wxString::Format(wxT("%02d:%02d:%02d"), h, m, s) ); } else { m_FileList->SetItem(idx, 2, wxT("Unknown")); }}void wxPlaylist::RefreshList(){ u32 i, top_idx; char szPath[GF_MAX_PATH]; Bool first_sel; top_idx = m_FileList->GetTopItem(); m_FileList->DeleteAllItems(); first_sel = 0; for (i=0; i<gf_list_count(m_entries); i++) { PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i); m_FileList->InsertItem(i, wxT("")); /*cast for 64-bit compilation*/ m_FileList->SetItemData(i, (unsigned long) ple); UpdateEntry(i); if (ple->m_bIsPlaying) m_cur_entry = i; if (ple->m_bIsSelected) { m_FileList->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED | wxLIST_MASK_STATE); ple->m_bIsSelected = 0; /*ensure first item of selection is visible*/ if (!first_sel) { first_sel = 1; top_idx = i; } } } if (m_cur_entry >= (s32) gf_list_count(m_entries)-1) m_cur_entry = gf_list_count(m_entries)-1; else { s32 last_idx = top_idx + m_FileList->GetCountPerPage(); m_FileList->EnsureVisible(top_idx); if (gf_list_count(m_entries)<1+ (u32) last_idx) last_idx = gf_list_count(m_entries)-1; m_FileList->EnsureVisible(last_idx); } strcpy((char *) szPath, m_pApp->szAppPath);#ifdef WIN32 strcat(szPath, "gpac_pl.m3u");#else strcat(szPath, ".gpac_pl.m3u");#endif Save(szPath, 1);}void wxPlaylist::OnAddFile(wxCommandEvent &WXUNUSED(event)) { wxFileDialog dlg(this, wxT("Select file(s)"), wxT(""), wxT(""), m_pApp->GetFileFilter(), wxOPEN | wxCHANGE_DIR | /*wxHIDE_READONLY |*/ wxMULTIPLE); if (dlg.ShowModal() == wxID_OK) { wxArrayString stra; dlg.GetPaths(stra); for (u32 i=0; i<stra.GetCount(); i++) { PLEntry *ple = new PLEntry(stra[i]); gf_list_add(m_entries, ple); } m_all_dead_entries = -1; RefreshList(); }}static Bool pl_enum_dir_item(void *cbck, char *item_name, char *item_path){ wxPlaylist *_this = (wxPlaylist *)cbck; if (gf_term_is_supported_url(_this->m_pApp->m_term, item_name, 0, 1)) { PLEntry *ple = new PLEntry(wxString(item_path, wxConvUTF8) ); gf_list_add(_this->m_entries, ple); } return 0;}static Bool pl_enum_dir_dirs(void *cbck, char *item_name, char *item_path){ gf_enum_directory(item_path, 0, pl_enum_dir_item, cbck, NULL); gf_enum_directory(item_path, 1, pl_enum_dir_dirs, cbck, NULL); return 0;}void wxPlaylist::AddDir(Bool do_recurse) { wxDirDialog dlg(this); dlg.SetPath(wxString(szCacheDir, wxConvUTF8) ); if (dlg.ShowModal() != wxID_OK) return; strcpy(szCacheDir, dlg.GetPath().mb_str(wxConvUTF8)); gf_enum_directory(szCacheDir, 0, pl_enum_dir_item, this, NULL); if (do_recurse) gf_enum_directory(szCacheDir, 1, pl_enum_dir_dirs, this, NULL); m_all_dead_entries = -1; RefreshList();}void wxPlaylist::OnAddDir(wxCommandEvent &WXUNUSED(event)) { AddDir(0);}void wxPlaylist::OnAddDirRec(wxCommandEvent &WXUNUSED(event)) { AddDir(1);}void wxPlaylist::OnAddURL(wxCommandEvent &WXUNUSED(event)) { OpenURLDlg dlg(this, m_pApp->m_user.config); if (dlg.ShowModal() != wxID_OK) return; PLEntry *ple = new PLEntry(dlg.m_urlVal); gf_list_add(m_entries, ple); m_all_dead_entries = -1; RefreshList();}void wxPlaylist::OnRemFile(wxCommandEvent &WXUNUSED(event)) { if (!m_FileList->GetSelectedItemCount()) return; long item = -1; for (;;) { item = m_FileList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); if (item == -1) break; PLEntry *ple = (PLEntry *) m_FileList->GetItemData(item); gf_list_del_item(m_entries, ple); delete ple; } RefreshList();}void wxPlaylist::OnRemAll(wxCommandEvent &WXUNUSED(event)) { Clear(); RefreshList(); m_cur_entry = -1; m_all_dead_entries = 1;}void wxPlaylist::OnRemDead(wxCommandEvent &WXUNUSED(event)) { for (u32 i=0; i<gf_list_count(m_entries); i++) { PLEntry *ple = (PLEntry *) gf_list_get(m_entries, i); if (!ple->m_bIsDead) continue; gf_list_rem(m_entries, i); i--; delete ple; } m_all_dead_entries = gf_list_count(m_entries) ? 0 : 1; RefreshList();}void wxPlaylist::OnSelUp(wxCommandEvent &WXUNUSED(event)) { s32 i; if (!m_FileList->GetSelectedItemCount()) return; long item = -1; item = m_FileList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); if (item <= 0) return; item = -1; for (;;) { item = m_FileList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); if (item == -1) break; PLEntry *ple = (PLEntry *) m_FileList->GetItemData(item); i = gf_list_del_item(m_entries, ple); assert(i>=1); gf_list_insert(m_entries, ple, i-1); ple->m_bIsSelected = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -