mediaplayer.cpp 66 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: mediaplayer.cpp
  3. // Purpose: wxMediaCtrl sample
  4. // Author: Ryan Norton
  5. // Modified by:
  6. // Created: 11/10/04
  7. // Copyright: (c) Ryan Norton
  8. // Licence: wxWindows licence
  9. ///////////////////////////////////////////////////////////////////////////////
  10. // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  11. // MediaPlayer
  12. //
  13. // This is a somewhat comprehensive example of how to use all the funtionality
  14. // of the wxMediaCtrl class in wxWidgets.
  15. //
  16. // To use this sample, simply select Open File from the file menu,
  17. // select the file you want to play - and MediaPlayer will play the file in a
  18. // the current notebook page, showing video if necessary.
  19. //
  20. // You can select one of the menu options, or move the slider around
  21. // to manipulate what is playing.
  22. // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  23. // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  24. // Known bugs with wxMediaCtrl:
  25. //
  26. // 1) Certain backends can't play the same media file at the same time (MCI,
  27. // Cocoa NSMovieView-Quicktime).
  28. // 2) Positioning on Mac Carbon is messed up if put in a sub-control like a
  29. // Notebook (like this sample does).
  30. // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  31. // ============================================================================
  32. // Definitions
  33. // ============================================================================
  34. // ----------------------------------------------------------------------------
  35. // Pre-compiled header stuff
  36. // ----------------------------------------------------------------------------
  37. #include "wx/wxprec.h"
  38. #ifdef __BORLANDC__
  39. #pragma hdrstop
  40. #endif
  41. #ifndef WX_PRECOMP
  42. #include "wx/wx.h"
  43. #endif
  44. // ----------------------------------------------------------------------------
  45. // Headers
  46. // ----------------------------------------------------------------------------
  47. #include "wx/mediactrl.h" // for wxMediaCtrl
  48. #include "wx/filedlg.h" // for opening files from OpenFile
  49. #include "wx/slider.h" // for a slider for seeking within media
  50. #include "wx/sizer.h" // for positioning controls/wxBoxSizer
  51. #include "wx/timer.h" // timer for updating status bar
  52. #include "wx/textdlg.h" // for getting user text from OpenURL/Debug
  53. #include "wx/notebook.h" // for wxNotebook and putting movies in pages
  54. #include "wx/cmdline.h" // for wxCmdLineParser (optional)
  55. #include "wx/listctrl.h" // for wxListCtrl
  56. #include "wx/dnd.h" // drag and drop for the playlist
  57. #include "wx/filename.h" // For wxFileName::GetName()
  58. #include "wx/config.h" // for native wxConfig
  59. #include "wx/vector.h"
  60. // Under MSW we have several different backends but when linking statically
  61. // they may be discarded by the linker (this definitely happens with MSVC) so
  62. // force linking them. You don't have to do this in your code if you don't plan
  63. // to use them, of course.
  64. #if defined(__WXMSW__) && !defined(WXUSINGDLL)
  65. #include "wx/link.h"
  66. wxFORCE_LINK_MODULE(wxmediabackend_am)
  67. wxFORCE_LINK_MODULE(wxmediabackend_qt)
  68. wxFORCE_LINK_MODULE(wxmediabackend_wmp10)
  69. #endif // static wxMSW build
  70. #ifndef wxHAS_IMAGES_IN_RESOURCES
  71. #include "../sample.xpm"
  72. #endif
  73. // ----------------------------------------------------------------------------
  74. // Bail out if the user doesn't want one of the
  75. // things we need
  76. // ----------------------------------------------------------------------------
  77. #if !wxUSE_MEDIACTRL || !wxUSE_MENUS || !wxUSE_SLIDER || !wxUSE_TIMER || \
  78. !wxUSE_NOTEBOOK || !wxUSE_LISTCTRL
  79. #error "Not all required elements are enabled. Please modify setup.h!"
  80. #endif
  81. // ============================================================================
  82. // Declarations
  83. // ============================================================================
  84. // ----------------------------------------------------------------------------
  85. // Enumurations
  86. // ----------------------------------------------------------------------------
  87. // IDs for the controls and the menu commands
  88. enum
  89. {
  90. // Menu event IDs
  91. wxID_LOOP = 1,
  92. wxID_OPENFILESAMEPAGE,
  93. wxID_OPENFILENEWPAGE,
  94. wxID_OPENURLSAMEPAGE,
  95. wxID_OPENURLNEWPAGE,
  96. wxID_CLOSECURRENTPAGE,
  97. wxID_PLAY,
  98. wxID_PAUSE,
  99. wxID_NEXT,
  100. wxID_PREV,
  101. wxID_SELECTBACKEND,
  102. wxID_SHOWINTERFACE,
  103. // wxID_STOP, [built-in to wxWidgets]
  104. // wxID_ABOUT, [built-in to wxWidgets]
  105. // wxID_EXIT, [built-in to wxWidgets]
  106. // Control event IDs
  107. wxID_SLIDER,
  108. wxID_PBSLIDER,
  109. wxID_VOLSLIDER,
  110. wxID_NOTEBOOK,
  111. wxID_MEDIACTRL,
  112. wxID_BUTTONNEXT,
  113. wxID_BUTTONPREV,
  114. wxID_BUTTONSTOP,
  115. wxID_BUTTONPLAY,
  116. wxID_BUTTONVD,
  117. wxID_BUTTONVU,
  118. wxID_LISTCTRL,
  119. wxID_GAUGE
  120. };
  121. // ----------------------------------------------------------------------------
  122. // wxMediaPlayerApp
  123. // ----------------------------------------------------------------------------
  124. class wxMediaPlayerApp : public wxApp
  125. {
  126. public:
  127. #ifdef __WXMAC__
  128. virtual void MacOpenFiles(const wxArrayString & fileNames );
  129. #endif
  130. #if wxUSE_CMDLINE_PARSER
  131. virtual void OnInitCmdLine(wxCmdLineParser& parser);
  132. virtual bool OnCmdLineParsed(wxCmdLineParser& parser);
  133. // Files specified on the command line, if any.
  134. wxVector<wxString> m_params;
  135. #endif // wxUSE_CMDLINE_PARSER
  136. virtual bool OnInit();
  137. protected:
  138. class wxMediaPlayerFrame* m_frame;
  139. };
  140. // ----------------------------------------------------------------------------
  141. // wxMediaPlayerFrame
  142. // ----------------------------------------------------------------------------
  143. class wxMediaPlayerFrame : public wxFrame
  144. {
  145. public:
  146. // Ctor/Dtor
  147. wxMediaPlayerFrame(const wxString& title);
  148. ~wxMediaPlayerFrame();
  149. // Menu event handlers
  150. void OnQuit(wxCommandEvent& event);
  151. void OnAbout(wxCommandEvent& event);
  152. void OnOpenFileSamePage(wxCommandEvent& event);
  153. void OnOpenFileNewPage(wxCommandEvent& event);
  154. void OnOpenURLSamePage(wxCommandEvent& event);
  155. void OnOpenURLNewPage(wxCommandEvent& event);
  156. void OnCloseCurrentPage(wxCommandEvent& event);
  157. void OnPlay(wxCommandEvent& event);
  158. void OnPause(wxCommandEvent& event);
  159. void OnStop(wxCommandEvent& event);
  160. void OnNext(wxCommandEvent& event);
  161. void OnPrev(wxCommandEvent& event);
  162. void OnVolumeDown(wxCommandEvent& event);
  163. void OnVolumeUp(wxCommandEvent& event);
  164. void OnLoop(wxCommandEvent& event);
  165. void OnShowInterface(wxCommandEvent& event);
  166. void OnSelectBackend(wxCommandEvent& event);
  167. // Key event handlers
  168. void OnKeyDown(wxKeyEvent& event);
  169. // Quickie for playing from command line
  170. void AddToPlayList(const wxString& szString);
  171. // ListCtrl event handlers
  172. void OnChangeSong(wxListEvent& event);
  173. // Media event handlers
  174. void OnMediaLoaded(wxMediaEvent& event);
  175. // Close event handlers
  176. void OnClose(wxCloseEvent& event);
  177. private:
  178. // Common open file code
  179. void OpenFile(bool bNewPage);
  180. void OpenURL(bool bNewPage);
  181. void DoOpenFile(const wxString& path, bool bNewPage);
  182. void DoPlayFile(const wxString& path);
  183. class wxMediaPlayerTimer* m_timer; // Timer to write info to status bar
  184. wxNotebook* m_notebook; // Notebook containing our pages
  185. // Maybe I should use more accessors, but for simplicity
  186. // I'll allow the other classes access to our members
  187. friend class wxMediaPlayerApp;
  188. friend class wxMediaPlayerNotebookPage;
  189. friend class wxMediaPlayerTimer;
  190. };
  191. // ----------------------------------------------------------------------------
  192. // wxMediaPlayerNotebookPage
  193. // ----------------------------------------------------------------------------
  194. class wxMediaPlayerNotebookPage : public wxPanel
  195. {
  196. wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentFrame,
  197. wxNotebook* book, const wxString& be = wxEmptyString);
  198. // Slider event handlers
  199. void OnBeginSeek(wxScrollEvent& event);
  200. void OnEndSeek(wxScrollEvent& event);
  201. void OnPBChange(wxScrollEvent& event);
  202. void OnVolChange(wxScrollEvent& event);
  203. // Media event handlers
  204. void OnMediaPlay(wxMediaEvent& event);
  205. void OnMediaPause(wxMediaEvent& event);
  206. void OnMediaStop(wxMediaEvent& event);
  207. void OnMediaFinished(wxMediaEvent& event);
  208. public:
  209. bool IsBeingDragged(); // accessor for m_bIsBeingDragged
  210. // make wxMediaPlayerFrame able to access the private members
  211. friend class wxMediaPlayerFrame;
  212. int m_nLastFileId; // List ID of played file in listctrl
  213. wxString m_szFile; // Name of currently playing file/location
  214. wxMediaCtrl* m_mediactrl; // Our media control
  215. class wxMediaPlayerListCtrl* m_playlist; // Our playlist
  216. wxSlider* m_slider; // The slider below our media control
  217. wxSlider* m_pbSlider; // Lower-left slider for adjusting speed
  218. wxSlider* m_volSlider; // Lower-right slider for adjusting volume
  219. int m_nLoops; // Number of times media has looped
  220. bool m_bLoop; // Whether we are looping or not
  221. bool m_bIsBeingDragged; // Whether the user is dragging the scroll bar
  222. wxMediaPlayerFrame* m_parentFrame; // Main wxFrame of our sample
  223. wxButton* m_prevButton; // Go to previous file button
  224. wxButton* m_playButton; // Play/pause file button
  225. wxButton* m_stopButton; // Stop playing file button
  226. wxButton* m_nextButton; // Next file button
  227. wxButton* m_vdButton; // Volume down button
  228. wxButton* m_vuButton; // Volume up button
  229. wxGauge* m_gauge; // Gauge to keep in line with slider
  230. };
  231. // ----------------------------------------------------------------------------
  232. // wxMediaPlayerTimer
  233. // ----------------------------------------------------------------------------
  234. class wxMediaPlayerTimer : public wxTimer
  235. {
  236. public:
  237. // Ctor
  238. wxMediaPlayerTimer(wxMediaPlayerFrame* frame) {m_frame = frame;}
  239. // Called each time the timer's timeout expires
  240. void Notify();
  241. wxMediaPlayerFrame* m_frame; // The wxMediaPlayerFrame
  242. };
  243. // ----------------------------------------------------------------------------
  244. // wxMediaPlayerListCtrl
  245. // ----------------------------------------------------------------------------
  246. class wxMediaPlayerListCtrl : public wxListCtrl
  247. {
  248. public:
  249. void AddToPlayList(const wxString& szString)
  250. {
  251. wxListItem kNewItem;
  252. kNewItem.SetAlign(wxLIST_FORMAT_LEFT);
  253. int nID = this->GetItemCount();
  254. kNewItem.SetId(nID);
  255. kNewItem.SetMask(wxLIST_MASK_DATA);
  256. kNewItem.SetData(new wxString(szString));
  257. this->InsertItem(kNewItem);
  258. this->SetItem(nID, 0, wxT("*"));
  259. this->SetItem(nID, 1, wxFileName(szString).GetName());
  260. if (nID % 2)
  261. {
  262. kNewItem.SetBackgroundColour(wxColour(192,192,192));
  263. this->SetItem(kNewItem);
  264. }
  265. }
  266. void GetSelectedItem(wxListItem& listitem)
  267. {
  268. listitem.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_DATA);
  269. int nLast = -1, nLastSelected = -1;
  270. while ((nLast = this->GetNextItem(nLast,
  271. wxLIST_NEXT_ALL,
  272. wxLIST_STATE_SELECTED)) != -1)
  273. {
  274. listitem.SetId(nLast);
  275. this->GetItem(listitem);
  276. if ((listitem.GetState() & wxLIST_STATE_FOCUSED) )
  277. break;
  278. nLastSelected = nLast;
  279. }
  280. if (nLast == -1 && nLastSelected == -1)
  281. return;
  282. listitem.SetId(nLastSelected == -1 ? nLast : nLastSelected);
  283. this->GetItem(listitem);
  284. }
  285. };
  286. // ----------------------------------------------------------------------------
  287. // wxPlayListDropTarget
  288. //
  289. // Drop target for playlist (i.e. allows users to drag a file from explorer into
  290. // the playlist to add that file)
  291. // ----------------------------------------------------------------------------
  292. #if wxUSE_DRAG_AND_DROP
  293. class wxPlayListDropTarget : public wxFileDropTarget
  294. {
  295. public:
  296. wxPlayListDropTarget(wxMediaPlayerListCtrl& list) : m_list(list) {}
  297. ~wxPlayListDropTarget(){}
  298. virtual bool OnDropFiles(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
  299. const wxArrayString& files)
  300. {
  301. for (size_t i = 0; i < files.GetCount(); ++i)
  302. {
  303. m_list.AddToPlayList(files[i]);
  304. }
  305. return true;
  306. }
  307. wxMediaPlayerListCtrl& m_list;
  308. };
  309. #endif
  310. // ============================================================================
  311. //
  312. // Implementation
  313. //
  314. // ============================================================================
  315. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  316. //
  317. // [Functions]
  318. //
  319. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  320. // ----------------------------------------------------------------------------
  321. // wxGetMediaStateText
  322. //
  323. // Converts a wxMediaCtrl state into something useful that we can display
  324. // to the user
  325. // ----------------------------------------------------------------------------
  326. const wxChar* wxGetMediaStateText(int nState)
  327. {
  328. switch(nState)
  329. {
  330. case wxMEDIASTATE_PLAYING:
  331. return wxT("Playing");
  332. case wxMEDIASTATE_STOPPED:
  333. return wxT("Stopped");
  334. ///case wxMEDIASTATE_PAUSED:
  335. default:
  336. return wxT("Paused");
  337. }
  338. }
  339. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  340. //
  341. // wxMediaPlayerApp
  342. //
  343. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  344. // ----------------------------------------------------------------------------
  345. // This sets up this wxApp as the global wxApp that gui calls in wxWidgets
  346. // use. For example, if you were to be in windows and use a file dialog,
  347. // wxWidgets would use wxTheApp->GetHInstance() which would get the instance
  348. // handle of the application. These routines in wx _DO NOT_ check to see if
  349. // the wxApp exists, and thus will crash the application if you try it.
  350. //
  351. // IMPLEMENT_APP does this, and also implements the platform-specific entry
  352. // routine, such as main or WinMain(). Use IMPLEMENT_APP_NO_MAIN if you do
  353. // not desire this behaviour.
  354. // ----------------------------------------------------------------------------
  355. IMPLEMENT_APP(wxMediaPlayerApp)
  356. // ----------------------------------------------------------------------------
  357. // wxMediaPlayerApp command line parsing
  358. // ----------------------------------------------------------------------------
  359. #if wxUSE_CMDLINE_PARSER
  360. void wxMediaPlayerApp::OnInitCmdLine(wxCmdLineParser& parser)
  361. {
  362. wxApp::OnInitCmdLine(parser);
  363. parser.AddParam("input files",
  364. wxCMD_LINE_VAL_STRING,
  365. wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE);
  366. }
  367. bool wxMediaPlayerApp::OnCmdLineParsed(wxCmdLineParser& parser)
  368. {
  369. if ( !wxApp::OnCmdLineParsed(parser) )
  370. return false;
  371. for (size_t paramNr=0; paramNr < parser.GetParamCount(); ++paramNr)
  372. m_params.push_back(parser.GetParam(paramNr));
  373. return true;
  374. }
  375. #endif // wxUSE_CMDLINE_PARSER
  376. // ----------------------------------------------------------------------------
  377. // wxMediaPlayerApp::OnInit
  378. //
  379. // Where execution starts - akin to a main or WinMain.
  380. // 1) Create the frame and show it to the user
  381. // 2) Process filenames from the commandline
  382. // 3) return true specifying that we want execution to continue past OnInit
  383. // ----------------------------------------------------------------------------
  384. bool wxMediaPlayerApp::OnInit()
  385. {
  386. if ( !wxApp::OnInit() )
  387. return false;
  388. // SetAppName() lets wxConfig and others know where to write
  389. SetAppName(wxT("wxMediaPlayer"));
  390. wxMediaPlayerFrame *frame =
  391. new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
  392. frame->Show(true);
  393. #if wxUSE_CMDLINE_PARSER
  394. if ( !m_params.empty() )
  395. {
  396. for ( size_t n = 0; n < m_params.size(); n++ )
  397. frame->AddToPlayList(m_params[n]);
  398. wxCommandEvent theEvent(wxEVT_MENU, wxID_NEXT);
  399. frame->AddPendingEvent(theEvent);
  400. }
  401. #endif // wxUSE_CMDLINE_PARSER
  402. return true;
  403. }
  404. #ifdef __WXMAC__
  405. void wxMediaPlayerApp::MacOpenFiles(const wxArrayString & fileNames )
  406. {
  407. // Called when a user drags files over our app
  408. m_frame->DoOpenFile(fileNames[0], true /* new page */);
  409. }
  410. #endif // __WXMAC__
  411. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  412. //
  413. // wxMediaPlayerFrame
  414. //
  415. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  416. // ----------------------------------------------------------------------------
  417. // wxMediaPlayerFrame Constructor
  418. //
  419. // 1) Create our menus
  420. // 2) Create our notebook control and add it to the frame
  421. // 3) Create our status bar
  422. // 4) Connect our events
  423. // 5) Start our timer
  424. // ----------------------------------------------------------------------------
  425. wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString& title)
  426. : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(600,600))
  427. {
  428. SetIcon(wxICON(sample));
  429. //
  430. // Create Menus
  431. //
  432. wxMenu *fileMenu = new wxMenu;
  433. wxMenu *controlsMenu = new wxMenu;
  434. wxMenu *optionsMenu = new wxMenu;
  435. wxMenu *helpMenu = new wxMenu;
  436. wxMenu *debugMenu = new wxMenu;
  437. fileMenu->Append(wxID_OPENFILESAMEPAGE, wxT("&Open File\tCtrl-Shift-O"),
  438. wxT("Open a File in the current notebook page"));
  439. fileMenu->Append(wxID_OPENFILENEWPAGE, wxT("&Open File in a new page"),
  440. wxT("Open a File in a new notebook page"));
  441. fileMenu->Append(wxID_OPENURLSAMEPAGE, wxT("&Open URL"),
  442. wxT("Open a URL in the current notebook page"));
  443. fileMenu->Append(wxID_OPENURLNEWPAGE, wxT("&Open URL in a new page"),
  444. wxT("Open a URL in a new notebook page"));
  445. fileMenu->AppendSeparator();
  446. fileMenu->Append(wxID_CLOSECURRENTPAGE, wxT("&Close Current Page\tCtrl-C"),
  447. wxT("Close current notebook page"));
  448. fileMenu->AppendSeparator();
  449. fileMenu->Append(wxID_EXIT,
  450. wxT("E&xit\tAlt-X"),
  451. wxT("Quit this program"));
  452. controlsMenu->Append(wxID_PLAY, wxT("&Play/Pause\tCtrl-P"), wxT("Resume/Pause playback"));
  453. controlsMenu->Append(wxID_STOP, wxT("&Stop\tCtrl-S"), wxT("Stop playback"));
  454. controlsMenu->AppendSeparator();
  455. controlsMenu->Append(wxID_PREV, wxT("&Previous\tCtrl-B"), wxT("Go to previous track"));
  456. controlsMenu->Append(wxID_NEXT, wxT("&Next\tCtrl-N"), wxT("Skip to next track"));
  457. optionsMenu->AppendCheckItem(wxID_LOOP,
  458. wxT("&Loop\tCtrl-L"),
  459. wxT("Loop Selected Media"));
  460. optionsMenu->AppendCheckItem(wxID_SHOWINTERFACE,
  461. wxT("&Show Interface\tCtrl-I"),
  462. wxT("Show wxMediaCtrl native controls"));
  463. debugMenu->Append(wxID_SELECTBACKEND,
  464. wxT("&Select Backend...\tCtrl-D"),
  465. wxT("Select a backend manually"));
  466. helpMenu->Append(wxID_ABOUT,
  467. wxT("&About\tF1"),
  468. wxT("Show about dialog"));
  469. wxMenuBar *menuBar = new wxMenuBar();
  470. menuBar->Append(fileMenu, wxT("&File"));
  471. menuBar->Append(controlsMenu, wxT("&Controls"));
  472. menuBar->Append(optionsMenu, wxT("&Options"));
  473. menuBar->Append(debugMenu, wxT("&Debug"));
  474. menuBar->Append(helpMenu, wxT("&Help"));
  475. SetMenuBar(menuBar);
  476. //
  477. // Create our notebook - using wxNotebook is luckily pretty
  478. // simple and self-explanatory in most cases
  479. //
  480. m_notebook = new wxNotebook(this, wxID_NOTEBOOK);
  481. //
  482. // Create our status bar
  483. //
  484. #if wxUSE_STATUSBAR
  485. // create a status bar just for fun (by default with 1 pane only)
  486. CreateStatusBar(1);
  487. #endif // wxUSE_STATUSBAR
  488. //
  489. // Connect events.
  490. //
  491. // There are two ways in wxWidgets to use events -
  492. // Message Maps and Connections.
  493. //
  494. // Message Maps are implemented by putting
  495. // DECLARE_MESSAGE_MAP in your wxEvtHandler-derived
  496. // class you want to use for events, such as wxMediaPlayerFrame.
  497. //
  498. // Then after your class declaration you put
  499. // wxBEGIN_EVENT_TABLE(wxMediaPlayerFrame, wxFrame)
  500. // EVT_XXX(XXX)...
  501. // wxEND_EVENT_TABLE()
  502. //
  503. // Where wxMediaPlayerFrame is the class with the DECLARE_MESSAGE_MAP
  504. // in it. EVT_XXX(XXX) are each of your handlers, such
  505. // as EVT_MENU for menu events and the XXX inside
  506. // is the parameters to the event macro - in the case
  507. // of EVT_MENU the menu id and then the function to call.
  508. //
  509. // However, with wxEvtHandler::Connect you can avoid a
  510. // global message map for your class and those annoying
  511. // macros. You can also change the context in which
  512. // the call the handler (more later).
  513. //
  514. // The downside is that due to the limitation that
  515. // wxWidgets doesn't use templates in certain areas,
  516. // You have to triple-cast the event function.
  517. //
  518. // There are five parameters to wxEvtHandler::Connect -
  519. //
  520. // The first is the id of the instance whose events
  521. // you want to handle - i.e. a menu id for menus,
  522. // a control id for controls (wxControl::GetId())
  523. // and so on.
  524. //
  525. // The second is the event id. This is the same
  526. // as the message maps (EVT_MENU) except prefixed
  527. // with "wx" (wxEVT_MENU).
  528. //
  529. // The third is the function handler for the event -
  530. // You need to cast it to the specific event handler
  531. // type, then to a wxEventFunction, then to a
  532. // wxObjectEventFunction - I.E.
  533. // (wxObjectEventFunction)(wxEventFunction)
  534. // (wxCommandEventFunction) &wxMediaPlayerFrame::MyHandler
  535. //
  536. // Or, you can use the new (2.5.5+) event handler
  537. // conversion macros - for instance the above could
  538. // be done as
  539. // wxCommandEventHandler(wxMediaPlayerFrame::MyHandler)
  540. // pretty simple, eh?
  541. //
  542. // The fourth is an optional userdata param -
  543. // this is of historical relevance only and is
  544. // there only for backwards compatibility.
  545. //
  546. // The fifth is the context in which to call the
  547. // handler - by default (this param is optional)
  548. // this. For example in your event handler
  549. // if you were to call "this->MyFunc()"
  550. // it would literally do this->MyFunc. However,
  551. // if you were to pass myHandler as the fifth
  552. // parameter, for instance, you would _really_
  553. // be calling myHandler->MyFunc, even though
  554. // the compiler doesn't really know it.
  555. //
  556. //
  557. // Menu events
  558. //
  559. this->Connect(wxID_EXIT, wxEVT_MENU,
  560. wxCommandEventHandler(wxMediaPlayerFrame::OnQuit));
  561. this->Connect(wxID_ABOUT, wxEVT_MENU,
  562. wxCommandEventHandler(wxMediaPlayerFrame::OnAbout));
  563. this->Connect(wxID_LOOP, wxEVT_MENU,
  564. wxCommandEventHandler(wxMediaPlayerFrame::OnLoop));
  565. this->Connect(wxID_SHOWINTERFACE, wxEVT_MENU,
  566. wxCommandEventHandler(wxMediaPlayerFrame::OnShowInterface));
  567. this->Connect(wxID_OPENFILENEWPAGE, wxEVT_MENU,
  568. wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileNewPage));
  569. this->Connect(wxID_OPENFILESAMEPAGE, wxEVT_MENU,
  570. wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileSamePage));
  571. this->Connect(wxID_OPENURLNEWPAGE, wxEVT_MENU,
  572. wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLNewPage));
  573. this->Connect(wxID_OPENURLSAMEPAGE, wxEVT_MENU,
  574. wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLSamePage));
  575. this->Connect(wxID_CLOSECURRENTPAGE, wxEVT_MENU,
  576. wxCommandEventHandler(wxMediaPlayerFrame::OnCloseCurrentPage));
  577. this->Connect(wxID_PLAY, wxEVT_MENU,
  578. wxCommandEventHandler(wxMediaPlayerFrame::OnPlay));
  579. this->Connect(wxID_STOP, wxEVT_MENU,
  580. wxCommandEventHandler(wxMediaPlayerFrame::OnStop));
  581. this->Connect(wxID_NEXT, wxEVT_MENU,
  582. wxCommandEventHandler(wxMediaPlayerFrame::OnNext));
  583. this->Connect(wxID_PREV, wxEVT_MENU,
  584. wxCommandEventHandler(wxMediaPlayerFrame::OnPrev));
  585. this->Connect(wxID_SELECTBACKEND, wxEVT_MENU,
  586. wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend));
  587. //
  588. // Key events
  589. //
  590. wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN,
  591. wxKeyEventHandler(wxMediaPlayerFrame::OnKeyDown),
  592. (wxObject*)0, this);
  593. //
  594. // Close events
  595. //
  596. this->Connect(wxID_ANY, wxEVT_CLOSE_WINDOW,
  597. wxCloseEventHandler(wxMediaPlayerFrame::OnClose));
  598. //
  599. // End of Events
  600. //
  601. //
  602. // Create an initial notebook page so the user has something
  603. // to work with without having to go file->open every time :).
  604. //
  605. wxMediaPlayerNotebookPage* page =
  606. new wxMediaPlayerNotebookPage(this, m_notebook);
  607. m_notebook->AddPage(page,
  608. wxT(""),
  609. true);
  610. // Don't load previous files if we have some specified on the command line,
  611. // we wouldn't play them otherwise (they'd have to be inserted into the
  612. // play list at the beginning instead of being appended but we don't
  613. // support this).
  614. #if wxUSE_CMDLINE_PARSER
  615. if ( wxGetApp().m_params.empty() )
  616. #endif // wxUSE_CMDLINE_PARSER
  617. {
  618. //
  619. // Here we load the our configuration -
  620. // in our case we load all the files that were left in
  621. // the playlist the last time the user closed our application
  622. //
  623. // As an exercise to the reader try modifying it so that
  624. // it properly loads the playlist for each page without
  625. // conflicting (loading the same data) with the other ones.
  626. //
  627. wxConfig conf;
  628. wxString key, outstring;
  629. for(int i = 0; ; ++i)
  630. {
  631. key.clear();
  632. key << i;
  633. if(!conf.Read(key, &outstring))
  634. break;
  635. page->m_playlist->AddToPlayList(outstring);
  636. }
  637. }
  638. //
  639. // Create a timer to update our status bar
  640. //
  641. m_timer = new wxMediaPlayerTimer(this);
  642. m_timer->Start(500);
  643. }
  644. // ----------------------------------------------------------------------------
  645. // wxMediaPlayerFrame Destructor
  646. //
  647. // 1) Deletes child objects implicitly
  648. // 2) Delete our timer explicitly
  649. // ----------------------------------------------------------------------------
  650. wxMediaPlayerFrame::~wxMediaPlayerFrame()
  651. {
  652. // Shut down our timer
  653. delete m_timer;
  654. //
  655. // Here we save our info to the registry or whatever
  656. // mechanism the OS uses.
  657. //
  658. // This makes it so that when mediaplayer loads up again
  659. // it restores the same files that were in the playlist
  660. // this time, rather than the user manually re-adding them.
  661. //
  662. // We need to do conf->DeleteAll() here because by default
  663. // the config still contains the same files as last time
  664. // so we need to clear it before writing our new ones.
  665. //
  666. // TODO: Maybe you could add a menu option to the
  667. // options menu to delete the configuration on exit -
  668. // all you'd need to do is just remove everything after
  669. // conf->DeleteAll() here
  670. //
  671. // As an exercise to the reader, try modifying this so
  672. // that it saves the data for each notebook page
  673. //
  674. wxMediaPlayerListCtrl* playlist =
  675. ((wxMediaPlayerNotebookPage*)m_notebook->GetPage(0))->m_playlist;
  676. wxConfig conf;
  677. conf.DeleteAll();
  678. for(int i = 0; i < playlist->GetItemCount(); ++i)
  679. {
  680. wxString* pData = (wxString*) playlist->GetItemData(i);
  681. wxString s;
  682. s << i;
  683. conf.Write(s, *(pData));
  684. delete pData;
  685. }
  686. }
  687. // ----------------------------------------------------------------------------
  688. // wxMediaPlayerFrame::OnClose
  689. // ----------------------------------------------------------------------------
  690. void wxMediaPlayerFrame::OnClose(wxCloseEvent& event)
  691. {
  692. event.Skip(); // really close the frame
  693. }
  694. // ----------------------------------------------------------------------------
  695. // wxMediaPlayerFrame::AddToPlayList
  696. // ----------------------------------------------------------------------------
  697. void wxMediaPlayerFrame::AddToPlayList(const wxString& szString)
  698. {
  699. wxMediaPlayerNotebookPage* currentpage =
  700. ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage());
  701. currentpage->m_playlist->AddToPlayList(szString);
  702. }
  703. // ----------------------------------------------------------------------------
  704. // wxMediaPlayerFrame::OnQuit
  705. //
  706. // Called from file->quit.
  707. // Closes this application.
  708. // ----------------------------------------------------------------------------
  709. void wxMediaPlayerFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
  710. {
  711. // true is to force the frame to close
  712. Close(true);
  713. }
  714. // ----------------------------------------------------------------------------
  715. // wxMediaPlayerFrame::OnAbout
  716. //
  717. // Called from help->about.
  718. // Gets some info about this application.
  719. // ----------------------------------------------------------------------------
  720. void wxMediaPlayerFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
  721. {
  722. wxString msg;
  723. msg.Printf( wxT("This is a test of wxMediaCtrl.\n\n")
  724. wxT("Instructions:\n")
  725. wxT("The top slider shows the current the current position, ")
  726. wxT("which you can change by dragging and releasing it.\n")
  727. wxT("The gauge (progress bar) shows the progress in ")
  728. wxT("downloading data of the current file - it may always be ")
  729. wxT("empty due to lack of support from the current backend.\n")
  730. wxT("The lower-left slider controls the volume and the lower-")
  731. wxT("right slider controls the playback rate/speed of the ")
  732. wxT("media\n\n")
  733. wxT("Currently using: %s"), wxVERSION_STRING);
  734. wxMessageBox(msg, wxT("About wxMediaCtrl test"),
  735. wxOK | wxICON_INFORMATION, this);
  736. }
  737. // ----------------------------------------------------------------------------
  738. // wxMediaPlayerFrame::OnLoop
  739. //
  740. // Called from file->loop.
  741. // Changes the state of whether we want to loop or not.
  742. // ----------------------------------------------------------------------------
  743. void wxMediaPlayerFrame::OnLoop(wxCommandEvent& WXUNUSED(event))
  744. {
  745. wxMediaPlayerNotebookPage* currentpage =
  746. ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage());
  747. currentpage->m_bLoop = !currentpage->m_bLoop;
  748. }
  749. // ----------------------------------------------------------------------------
  750. // wxMediaPlayerFrame::OnLoop
  751. //
  752. // Called from file->loop.
  753. // Changes the state of whether we want to loop or not.
  754. // ----------------------------------------------------------------------------
  755. void wxMediaPlayerFrame::OnShowInterface(wxCommandEvent& event)
  756. {
  757. wxMediaPlayerNotebookPage* currentpage =
  758. ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage());
  759. if( !currentpage->m_mediactrl->ShowPlayerControls(event.IsChecked() ?
  760. wxMEDIACTRLPLAYERCONTROLS_DEFAULT :
  761. wxMEDIACTRLPLAYERCONTROLS_NONE) )
  762. {
  763. // error - uncheck and warn user
  764. wxMenuItem* pSIItem = GetMenuBar()->FindItem(wxID_SHOWINTERFACE);
  765. wxASSERT(pSIItem);
  766. pSIItem->Check(!event.IsChecked());
  767. if(event.IsChecked())
  768. wxMessageBox(wxT("Could not show player controls"));
  769. else
  770. wxMessageBox(wxT("Could not hide player controls"));
  771. }
  772. }
  773. // ----------------------------------------------------------------------------
  774. // wxMediaPlayerFrame::OnOpenFileSamePage
  775. //
  776. // Called from file->openfile.
  777. // Opens and plays a media file in the current notebook page
  778. // ----------------------------------------------------------------------------
  779. void wxMediaPlayerFrame::OnOpenFileSamePage(wxCommandEvent& WXUNUSED(event))
  780. {
  781. OpenFile(false);
  782. }
  783. // ----------------------------------------------------------------------------
  784. // wxMediaPlayerFrame::OnOpenFileNewPage
  785. //
  786. // Called from file->openfileinnewpage.
  787. // Opens and plays a media file in a new notebook page
  788. // ----------------------------------------------------------------------------
  789. void wxMediaPlayerFrame::OnOpenFileNewPage(wxCommandEvent& WXUNUSED(event))
  790. {
  791. OpenFile(true);
  792. }
  793. // ----------------------------------------------------------------------------
  794. // wxMediaPlayerFrame::OpenFile
  795. //
  796. // Opens a file dialog asking the user for a filename, then
  797. // calls DoOpenFile which will add the file to the playlist and play it
  798. // ----------------------------------------------------------------------------
  799. void wxMediaPlayerFrame::OpenFile(bool bNewPage)
  800. {
  801. wxFileDialog fd(this);
  802. if(fd.ShowModal() == wxID_OK)
  803. {
  804. DoOpenFile(fd.GetPath(), bNewPage);
  805. }
  806. }
  807. // ----------------------------------------------------------------------------
  808. // wxMediaPlayerFrame::DoOpenFile
  809. //
  810. // Adds the file to our playlist, selects it in the playlist,
  811. // and then calls DoPlayFile to play it
  812. // ----------------------------------------------------------------------------
  813. void wxMediaPlayerFrame::DoOpenFile(const wxString& path, bool bNewPage)
  814. {
  815. if(bNewPage)
  816. {
  817. m_notebook->AddPage(
  818. new wxMediaPlayerNotebookPage(this, m_notebook),
  819. path,
  820. true);
  821. }
  822. wxMediaPlayerNotebookPage* currentpage =
  823. (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
  824. if(currentpage->m_nLastFileId != -1)
  825. currentpage->m_playlist->SetItemState(currentpage->m_nLastFileId,
  826. 0, wxLIST_STATE_SELECTED);
  827. wxListItem newlistitem;
  828. newlistitem.SetAlign(wxLIST_FORMAT_LEFT);
  829. int nID;
  830. newlistitem.SetId(nID = currentpage->m_playlist->GetItemCount());
  831. newlistitem.SetMask(wxLIST_MASK_DATA | wxLIST_MASK_STATE);
  832. newlistitem.SetState(wxLIST_STATE_SELECTED);
  833. newlistitem.SetData(new wxString(path));
  834. currentpage->m_playlist->InsertItem(newlistitem);
  835. currentpage->m_playlist->SetItem(nID, 0, wxT("*"));
  836. currentpage->m_playlist->SetItem(nID, 1, wxFileName(path).GetName());
  837. if (nID % 2)
  838. {
  839. newlistitem.SetBackgroundColour(wxColour(192,192,192));
  840. currentpage->m_playlist->SetItem(newlistitem);
  841. }
  842. DoPlayFile(path);
  843. }
  844. // ----------------------------------------------------------------------------
  845. // wxMediaPlayerFrame::DoPlayFile
  846. //
  847. // Pauses the file if its the currently playing file,
  848. // otherwise it plays the file
  849. // ----------------------------------------------------------------------------
  850. void wxMediaPlayerFrame::DoPlayFile(const wxString& path)
  851. {
  852. wxMediaPlayerNotebookPage* currentpage =
  853. (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
  854. wxListItem listitem;
  855. currentpage->m_playlist->GetSelectedItem(listitem);
  856. if( ( listitem.GetData() &&
  857. currentpage->m_nLastFileId == listitem.GetId() &&
  858. currentpage->m_szFile.compare(path) == 0 ) ||
  859. ( !listitem.GetData() &&
  860. currentpage->m_nLastFileId != -1 &&
  861. currentpage->m_szFile.compare(path) == 0)
  862. )
  863. {
  864. if(currentpage->m_mediactrl->GetState() == wxMEDIASTATE_PLAYING)
  865. {
  866. if( !currentpage->m_mediactrl->Pause() )
  867. wxMessageBox(wxT("Couldn't pause movie!"));
  868. }
  869. else
  870. {
  871. if( !currentpage->m_mediactrl->Play() )
  872. wxMessageBox(wxT("Couldn't play movie!"));
  873. }
  874. }
  875. else
  876. {
  877. int nNewId = listitem.GetData() ? listitem.GetId() :
  878. currentpage->m_playlist->GetItemCount()-1;
  879. m_notebook->SetPageText(m_notebook->GetSelection(),
  880. wxFileName(path).GetName());
  881. if(currentpage->m_nLastFileId != -1)
  882. currentpage->m_playlist->SetItem(
  883. currentpage->m_nLastFileId, 0, wxT("*"));
  884. wxURI uripath(path);
  885. if( uripath.IsReference() )
  886. {
  887. if( !currentpage->m_mediactrl->Load(path) )
  888. {
  889. wxMessageBox(wxT("Couldn't load file!"));
  890. currentpage->m_playlist->SetItem(nNewId, 0, wxT("E"));
  891. }
  892. else
  893. {
  894. currentpage->m_playlist->SetItem(nNewId, 0, wxT("O"));
  895. }
  896. }
  897. else
  898. {
  899. if( !currentpage->m_mediactrl->Load(uripath) )
  900. {
  901. wxMessageBox(wxT("Couldn't load URL!"));
  902. currentpage->m_playlist->SetItem(nNewId, 0, wxT("E"));
  903. }
  904. else
  905. {
  906. currentpage->m_playlist->SetItem(nNewId, 0, wxT("O"));
  907. }
  908. }
  909. currentpage->m_nLastFileId = nNewId;
  910. currentpage->m_szFile = path;
  911. currentpage->m_playlist->SetItem(currentpage->m_nLastFileId,
  912. 1, wxFileName(path).GetName());
  913. currentpage->m_playlist->SetItem(currentpage->m_nLastFileId,
  914. 2, wxT(""));
  915. }
  916. }
  917. // ----------------------------------------------------------------------------
  918. // wxMediaPlayerFrame::OnMediaLoaded
  919. //
  920. // Called when the media is ready to be played - and does
  921. // so, also gets the length of media and shows that in the list control
  922. // ----------------------------------------------------------------------------
  923. void wxMediaPlayerFrame::OnMediaLoaded(wxMediaEvent& WXUNUSED(evt))
  924. {
  925. wxMediaPlayerNotebookPage* currentpage =
  926. (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
  927. if( !currentpage->m_mediactrl->Play() )
  928. {
  929. wxMessageBox(wxT("Couldn't play movie!"));
  930. currentpage->m_playlist->SetItem(currentpage->m_nLastFileId, 0, wxT("E"));
  931. }
  932. else
  933. {
  934. currentpage->m_playlist->SetItem(currentpage->m_nLastFileId, 0, wxT(">"));
  935. }
  936. }
  937. // ----------------------------------------------------------------------------
  938. // wxMediaPlayerFrame::OnSelectBackend
  939. //
  940. // Little debugging routine - enter the class name of a backend and it
  941. // will use that instead of letting wxMediaCtrl search the wxMediaBackend
  942. // RTTI class list.
  943. // ----------------------------------------------------------------------------
  944. void wxMediaPlayerFrame::OnSelectBackend(wxCommandEvent& WXUNUSED(evt))
  945. {
  946. wxString sBackend = wxGetTextFromUser(wxT("Enter backend to use"));
  947. if(sBackend.empty() == false) // could have been cancelled by the user
  948. {
  949. int sel = m_notebook->GetSelection();
  950. if (sel != wxNOT_FOUND)
  951. {
  952. m_notebook->DeletePage(sel);
  953. }
  954. m_notebook->AddPage(new wxMediaPlayerNotebookPage(this, m_notebook,
  955. sBackend
  956. ), wxT(""), true);
  957. DoOpenFile(
  958. ((wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage())->m_szFile,
  959. false);
  960. }
  961. }
  962. // ----------------------------------------------------------------------------
  963. // wxMediaPlayerFrame::OnOpenURLSamePage
  964. //
  965. // Called from file->openurl.
  966. // Opens and plays a media file from a URL in the current notebook page
  967. // ----------------------------------------------------------------------------
  968. void wxMediaPlayerFrame::OnOpenURLSamePage(wxCommandEvent& WXUNUSED(event))
  969. {
  970. OpenURL(false);
  971. }
  972. // ----------------------------------------------------------------------------
  973. // wxMediaPlayerFrame::OnOpenURLNewPage
  974. //
  975. // Called from file->openurlinnewpage.
  976. // Opens and plays a media file from a URL in a new notebook page
  977. // ----------------------------------------------------------------------------
  978. void wxMediaPlayerFrame::OnOpenURLNewPage(wxCommandEvent& WXUNUSED(event))
  979. {
  980. OpenURL(true);
  981. }
  982. // ----------------------------------------------------------------------------
  983. // wxMediaPlayerFrame::OpenURL
  984. //
  985. // Just calls DoOpenFile with the url path - which calls DoPlayFile
  986. // which handles the real dirty work
  987. // ----------------------------------------------------------------------------
  988. void wxMediaPlayerFrame::OpenURL(bool bNewPage)
  989. {
  990. wxString sUrl = wxGetTextFromUser(
  991. wxT("Enter the URL that has the movie to play")
  992. );
  993. if(sUrl.empty() == false) // could have been cancelled by user
  994. {
  995. DoOpenFile(sUrl, bNewPage);
  996. }
  997. }
  998. // ----------------------------------------------------------------------------
  999. // wxMediaPlayerFrame::OnCloseCurrentPage
  1000. //
  1001. // Called when the user wants to close the current notebook page
  1002. //
  1003. // 1) Get the current page number (wxControl::GetSelection)
  1004. // 2) If there is no current page, break out
  1005. // 3) Delete the current page
  1006. // ----------------------------------------------------------------------------
  1007. void wxMediaPlayerFrame::OnCloseCurrentPage(wxCommandEvent& WXUNUSED(event))
  1008. {
  1009. if( m_notebook->GetPageCount() > 1 )
  1010. {
  1011. int sel = m_notebook->GetSelection();
  1012. if (sel != wxNOT_FOUND)
  1013. {
  1014. m_notebook->DeletePage(sel);
  1015. }
  1016. }
  1017. else
  1018. {
  1019. wxMessageBox(wxT("Cannot close main page"));
  1020. }
  1021. }
  1022. // ----------------------------------------------------------------------------
  1023. // wxMediaPlayerFrame::OnPlay
  1024. //
  1025. // Called from file->play.
  1026. // Resumes the media if it is paused or stopped.
  1027. // ----------------------------------------------------------------------------
  1028. void wxMediaPlayerFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
  1029. {
  1030. wxMediaPlayerNotebookPage* currentpage =
  1031. (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
  1032. wxListItem listitem;
  1033. currentpage->m_playlist->GetSelectedItem(listitem);
  1034. if ( !listitem.GetData() )
  1035. {
  1036. int nLast = -1;
  1037. if ((nLast = currentpage->m_playlist->GetNextItem(nLast,
  1038. wxLIST_NEXT_ALL,
  1039. wxLIST_STATE_DONTCARE)) == -1)
  1040. {
  1041. // no items in list
  1042. wxMessageBox(wxT("No items in playlist!"));
  1043. }
  1044. else
  1045. {
  1046. listitem.SetId(nLast);
  1047. currentpage->m_playlist->GetItem(listitem);
  1048. listitem.SetMask(listitem.GetMask() | wxLIST_MASK_STATE);
  1049. listitem.SetState(listitem.GetState() | wxLIST_STATE_SELECTED);
  1050. currentpage->m_playlist->SetItem(listitem);
  1051. wxASSERT(listitem.GetData());
  1052. DoPlayFile((*((wxString*) listitem.GetData())));
  1053. }
  1054. }
  1055. else
  1056. {
  1057. wxASSERT(listitem.GetData());
  1058. DoPlayFile((*((wxString*) listitem.GetData())));
  1059. }
  1060. }
  1061. // ----------------------------------------------------------------------------
  1062. // wxMediaPlayerFrame::OnKeyDown
  1063. //
  1064. // Deletes all selected files from the playlist if the backspace key is pressed
  1065. // ----------------------------------------------------------------------------
  1066. void wxMediaPlayerFrame::OnKeyDown(wxKeyEvent& event)
  1067. {
  1068. if(event.GetKeyCode() == WXK_BACK/*DELETE*/)
  1069. {
  1070. wxMediaPlayerNotebookPage* currentpage =
  1071. (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
  1072. // delete all selected items
  1073. while(true)
  1074. {
  1075. wxInt32 nSelectedItem = currentpage->m_playlist->GetNextItem(
  1076. -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
  1077. if (nSelectedItem == -1)
  1078. break;
  1079. wxListItem listitem;
  1080. listitem.SetId(nSelectedItem);
  1081. currentpage->m_playlist->GetItem(listitem);
  1082. delete (wxString*) listitem.GetData();
  1083. currentpage->m_playlist->DeleteItem(nSelectedItem);
  1084. }
  1085. }
  1086. // Could be wxGetTextFromUser or something else important
  1087. if(event.GetEventObject() != this)
  1088. event.Skip();
  1089. }
  1090. // ----------------------------------------------------------------------------
  1091. // wxMediaPlayerFrame::OnStop
  1092. //
  1093. // Called from file->stop.
  1094. // Where it stops depends on whether you can seek in the
  1095. // media control or not - if you can it stops and seeks to the beginning,
  1096. // otherwise it will appear to be at the end - but it will start over again
  1097. // when Play() is called
  1098. // ----------------------------------------------------------------------------
  1099. void wxMediaPlayerFrame::OnStop(wxCommandEvent& WXUNUSED(evt))
  1100. {
  1101. wxMediaPlayerNotebookPage* currentpage =
  1102. (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
  1103. if( !currentpage->m_mediactrl->Stop() )
  1104. wxMessageBox(wxT("Couldn't stop movie!"));
  1105. else
  1106. currentpage->m_playlist->SetItem(
  1107. currentpage->m_nLastFileId, 0, wxT("[]"));
  1108. }
  1109. // ----------------------------------------------------------------------------
  1110. // wxMediaPlayerFrame::OnChangeSong
  1111. //
  1112. // Routine that plays the currently selected file in the playlist.
  1113. // Called when the user actives the song from the playlist,
  1114. // and from other various places in the sample
  1115. // ----------------------------------------------------------------------------
  1116. void wxMediaPlayerFrame::OnChangeSong(wxListEvent& WXUNUSED(evt))
  1117. {
  1118. wxMediaPlayerNotebookPage* currentpage =
  1119. (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
  1120. wxListItem listitem;
  1121. currentpage->m_playlist->GetSelectedItem(listitem);
  1122. if(listitem.GetData())
  1123. DoPlayFile((*((wxString*) listitem.GetData())));
  1124. else
  1125. wxMessageBox(wxT("No selected item!"));
  1126. }
  1127. // ----------------------------------------------------------------------------
  1128. // wxMediaPlayerFrame::OnPrev
  1129. //
  1130. // Tedious wxListCtrl stuff. Goes to prevous song in list, or if at the
  1131. // beginning goes to the last in the list.
  1132. // ----------------------------------------------------------------------------
  1133. void wxMediaPlayerFrame::OnPrev(wxCommandEvent& WXUNUSED(event))
  1134. {
  1135. wxMediaPlayerNotebookPage* currentpage =
  1136. (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
  1137. if (currentpage->m_playlist->GetItemCount() == 0)
  1138. return;
  1139. wxInt32 nLastSelectedItem = -1;
  1140. while(true)
  1141. {
  1142. wxInt32 nSelectedItem = currentpage->m_playlist->GetNextItem(nLastSelectedItem,
  1143. wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
  1144. if (nSelectedItem == -1)
  1145. break;
  1146. nLastSelectedItem = nSelectedItem;
  1147. currentpage->m_playlist->SetItemState(nSelectedItem, 0, wxLIST_STATE_SELECTED);
  1148. }
  1149. if (nLastSelectedItem == -1)
  1150. {
  1151. // nothing selected, default to the file before the currently playing one
  1152. if(currentpage->m_nLastFileId == 0)
  1153. nLastSelectedItem = currentpage->m_playlist->GetItemCount() - 1;
  1154. else
  1155. nLastSelectedItem = currentpage->m_nLastFileId - 1;
  1156. }
  1157. else if (nLastSelectedItem == 0)
  1158. nLastSelectedItem = currentpage->m_playlist->GetItemCount() - 1;
  1159. else
  1160. nLastSelectedItem -= 1;
  1161. if(nLastSelectedItem == currentpage->m_nLastFileId)
  1162. return; // already playing... nothing to do
  1163. wxListItem listitem;
  1164. listitem.SetId(nLastSelectedItem);
  1165. listitem.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_DATA);
  1166. currentpage->m_playlist->GetItem(listitem);
  1167. listitem.SetMask(listitem.GetMask() | wxLIST_MASK_STATE);
  1168. listitem.SetState(listitem.GetState() | wxLIST_STATE_SELECTED);
  1169. currentpage->m_playlist->SetItem(listitem);
  1170. wxASSERT(listitem.GetData());
  1171. DoPlayFile((*((wxString*) listitem.GetData())));
  1172. }
  1173. // ----------------------------------------------------------------------------
  1174. // wxMediaPlayerFrame::OnNext
  1175. //
  1176. // Tedious wxListCtrl stuff. Goes to next song in list, or if at the
  1177. // end goes to the first in the list.
  1178. // ----------------------------------------------------------------------------
  1179. void wxMediaPlayerFrame::OnNext(wxCommandEvent& WXUNUSED(event))
  1180. {
  1181. wxMediaPlayerNotebookPage* currentpage =
  1182. (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
  1183. if (currentpage->m_playlist->GetItemCount() == 0)
  1184. return;
  1185. wxInt32 nLastSelectedItem = -1;
  1186. while(true)
  1187. {
  1188. wxInt32 nSelectedItem = currentpage->m_playlist->GetNextItem(nLastSelectedItem,
  1189. wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
  1190. if (nSelectedItem == -1)
  1191. break;
  1192. nLastSelectedItem = nSelectedItem;
  1193. currentpage->m_playlist->SetItemState(nSelectedItem, 0, wxLIST_STATE_SELECTED);
  1194. }
  1195. if (nLastSelectedItem == -1)
  1196. {
  1197. if(currentpage->m_nLastFileId == currentpage->m_playlist->GetItemCount() - 1)
  1198. nLastSelectedItem = 0;
  1199. else
  1200. nLastSelectedItem = currentpage->m_nLastFileId + 1;
  1201. }
  1202. else if (nLastSelectedItem == currentpage->m_playlist->GetItemCount() - 1)
  1203. nLastSelectedItem = 0;
  1204. else
  1205. nLastSelectedItem += 1;
  1206. if(nLastSelectedItem == currentpage->m_nLastFileId)
  1207. return; // already playing... nothing to do
  1208. wxListItem listitem;
  1209. listitem.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_DATA);
  1210. listitem.SetId(nLastSelectedItem);
  1211. currentpage->m_playlist->GetItem(listitem);
  1212. listitem.SetMask(listitem.GetMask() | wxLIST_MASK_STATE);
  1213. listitem.SetState(listitem.GetState() | wxLIST_STATE_SELECTED);
  1214. currentpage->m_playlist->SetItem(listitem);
  1215. wxASSERT(listitem.GetData());
  1216. DoPlayFile((*((wxString*) listitem.GetData())));
  1217. }
  1218. // ----------------------------------------------------------------------------
  1219. // wxMediaPlayerFrame::OnVolumeDown
  1220. //
  1221. // Lowers the volume of the media control by 5%
  1222. // ----------------------------------------------------------------------------
  1223. void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent& WXUNUSED(event))
  1224. {
  1225. wxMediaPlayerNotebookPage* currentpage =
  1226. (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
  1227. double dVolume = currentpage->m_mediactrl->GetVolume();
  1228. currentpage->m_mediactrl->SetVolume(dVolume < 0.05 ? 0.0 : dVolume - .05);
  1229. }
  1230. // ----------------------------------------------------------------------------
  1231. // wxMediaPlayerFrame::OnVolumeUp
  1232. //
  1233. // Increases the volume of the media control by 5%
  1234. // ----------------------------------------------------------------------------
  1235. void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent& WXUNUSED(event))
  1236. {
  1237. wxMediaPlayerNotebookPage* currentpage =
  1238. (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
  1239. double dVolume = currentpage->m_mediactrl->GetVolume();
  1240. currentpage->m_mediactrl->SetVolume(dVolume > 0.95 ? 1.0 : dVolume + .05);
  1241. }
  1242. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1243. //
  1244. // wxMediaPlayerTimer
  1245. //
  1246. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1247. // ----------------------------------------------------------------------------
  1248. // wxMediaPlayerTimer::Notify
  1249. //
  1250. // 1) Updates media information on the status bar
  1251. // 2) Sets the max/min length of the slider and guage
  1252. //
  1253. // Note that the reason we continually do this and don't cache it is because
  1254. // some backends such as GStreamer are dynamic change values all the time
  1255. // and often don't have things like duration or video size available
  1256. // until the media is actually being played
  1257. // ----------------------------------------------------------------------------
  1258. void wxMediaPlayerTimer::Notify()
  1259. {
  1260. wxMediaPlayerNotebookPage* currentpage =
  1261. (wxMediaPlayerNotebookPage*) m_frame->m_notebook->GetCurrentPage();
  1262. wxMediaCtrl* currentMediaCtrl = currentpage->m_mediactrl;
  1263. // Number of minutes/seconds total
  1264. wxLongLong llLength = currentpage->m_mediactrl->Length();
  1265. int nMinutes = (int) (llLength / 60000).GetValue();
  1266. int nSeconds = (int) ((llLength % 60000)/1000).GetValue();
  1267. // Duration string (i.e. MM:SS)
  1268. wxString sDuration;
  1269. sDuration.Printf(wxT("%2i:%02i"), nMinutes, nSeconds);
  1270. // Number of minutes/seconds total
  1271. wxLongLong llTell = currentpage->m_mediactrl->Tell();
  1272. nMinutes = (int) (llTell / 60000).GetValue();
  1273. nSeconds = (int) ((llTell % 60000)/1000).GetValue();
  1274. // Position string (i.e. MM:SS)
  1275. wxString sPosition;
  1276. sPosition.Printf(wxT("%2i:%02i"), nMinutes, nSeconds);
  1277. // Set the third item in the listctrl entry to the duration string
  1278. if(currentpage->m_nLastFileId >= 0)
  1279. currentpage->m_playlist->SetItem(
  1280. currentpage->m_nLastFileId, 2, sDuration);
  1281. // Setup the slider and gauge min/max values
  1282. currentpage->m_slider->SetRange(0, (int)(llLength / 1000).GetValue());
  1283. currentpage->m_gauge->SetRange(100);
  1284. // if the slider is not being dragged then update it with the song position
  1285. if(currentpage->IsBeingDragged() == false)
  1286. currentpage->m_slider->SetValue((long)(llTell / 1000).GetValue());
  1287. // Update the gauge with the download progress
  1288. wxLongLong llDownloadProgress =
  1289. currentpage->m_mediactrl->GetDownloadProgress();
  1290. wxLongLong llDownloadTotal =
  1291. currentpage->m_mediactrl->GetDownloadTotal();
  1292. if(llDownloadTotal.GetValue() != 0)
  1293. {
  1294. currentpage->m_gauge->SetValue(
  1295. (int) ((llDownloadProgress * 100) / llDownloadTotal).GetValue()
  1296. );
  1297. }
  1298. // GetBestSize holds the original video size
  1299. wxSize videoSize = currentMediaCtrl->GetBestSize();
  1300. // Now the big part - set the status bar text to
  1301. // hold various metadata about the media
  1302. #if wxUSE_STATUSBAR
  1303. m_frame->SetStatusText(wxString::Format(
  1304. wxT("Size(x,y):%i,%i ")
  1305. wxT("Position:%s/%s Speed:%1.1fx ")
  1306. wxT("State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"),
  1307. videoSize.x,
  1308. videoSize.y,
  1309. sPosition.c_str(),
  1310. sDuration.c_str(),
  1311. currentMediaCtrl->GetPlaybackRate(),
  1312. wxGetMediaStateText(currentpage->m_mediactrl->GetState()),
  1313. currentpage->m_nLoops,
  1314. (int)llDownloadProgress.GetValue(),
  1315. (int)llDownloadTotal.GetValue(),
  1316. (int)(currentpage->m_mediactrl->GetVolume() * 100)));
  1317. #endif // wxUSE_STATUSBAR
  1318. }
  1319. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1320. //
  1321. // wxMediaPlayerNotebookPage
  1322. //
  1323. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1324. // ----------------------------------------------------------------------------
  1325. // wxMediaPlayerNotebookPage Constructor
  1326. //
  1327. // Creates a media control and slider and adds it to this panel,
  1328. // along with some sizers for positioning
  1329. // ----------------------------------------------------------------------------
  1330. wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentFrame,
  1331. wxNotebook* theBook,
  1332. const wxString& szBackend)
  1333. : wxPanel(theBook, wxID_ANY),
  1334. m_nLastFileId(-1),
  1335. m_nLoops(0),
  1336. m_bLoop(false),
  1337. m_bIsBeingDragged(false),
  1338. m_parentFrame(parentFrame)
  1339. {
  1340. //
  1341. // Layout
  1342. //
  1343. // [wxMediaCtrl]
  1344. // [playlist]
  1345. // [5 control buttons]
  1346. // [slider]
  1347. // [gauge]
  1348. //
  1349. //
  1350. // Create and attach a 2-column grid sizer
  1351. //
  1352. wxFlexGridSizer* sizer = new wxFlexGridSizer(2);
  1353. sizer->AddGrowableCol(0);
  1354. this->SetSizer(sizer);
  1355. //
  1356. // Create our media control
  1357. //
  1358. m_mediactrl = new wxMediaCtrl();
  1359. // Make sure creation was successful
  1360. bool bOK = m_mediactrl->Create(this, wxID_MEDIACTRL, wxEmptyString,
  1361. wxDefaultPosition, wxDefaultSize, 0,
  1362. // you could specify a macro backend here like
  1363. // wxMEDIABACKEND_WMP10);
  1364. // wxT("wxPDFMediaBackend"));
  1365. szBackend);
  1366. // you could change the cursor here like
  1367. // m_mediactrl->SetCursor(wxCURSOR_BLANK);
  1368. // note that this may not effect it if SetPlayerControls
  1369. // is set to something else than wxMEDIACTRLPLAYERCONTROLS_NONE
  1370. wxASSERT_MSG(bOK, wxT("Could not create media control!"));
  1371. wxUnusedVar(bOK);
  1372. sizer->Add(m_mediactrl, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 5);
  1373. //
  1374. // Create the playlist/listctrl
  1375. //
  1376. m_playlist = new wxMediaPlayerListCtrl();
  1377. m_playlist->Create(this, wxID_LISTCTRL, wxDefaultPosition,
  1378. wxDefaultSize,
  1379. wxLC_REPORT // wxLC_LIST
  1380. | wxSUNKEN_BORDER);
  1381. // Set the background of our listctrl to white
  1382. m_playlist->SetBackgroundColour(*wxWHITE);
  1383. // The layout of the headers of the listctrl are like
  1384. // | | File | Length
  1385. //
  1386. // Where Column one is a character representing the state the file is in:
  1387. // * - not the current file
  1388. // E - Error has occured
  1389. // > - Currently Playing
  1390. // [] - Stopped
  1391. // || - Paused
  1392. // (( - Volume Down 5%
  1393. // )) - Volume Up 5%
  1394. //
  1395. // Column two is the name of the file
  1396. //
  1397. // Column three is the length in seconds of the file
  1398. m_playlist->AppendColumn(_(""), wxLIST_FORMAT_CENTER, 20);
  1399. m_playlist->AppendColumn(_("File"), wxLIST_FORMAT_LEFT, /*wxLIST_AUTOSIZE_USEHEADER*/305);
  1400. m_playlist->AppendColumn(_("Length"), wxLIST_FORMAT_CENTER, 75);
  1401. #if wxUSE_DRAG_AND_DROP
  1402. m_playlist->SetDropTarget(new wxPlayListDropTarget(*m_playlist));
  1403. #endif
  1404. sizer->Add(m_playlist, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 5);
  1405. //
  1406. // Create the control buttons
  1407. // TODO/FIXME/HACK: This part about sizers is really a nice hack
  1408. // and probably isn't proper
  1409. //
  1410. wxBoxSizer* horsizer1 = new wxBoxSizer(wxHORIZONTAL);
  1411. wxBoxSizer* vertsizer = new wxBoxSizer(wxHORIZONTAL);
  1412. m_prevButton = new wxButton();
  1413. m_playButton = new wxButton();
  1414. m_stopButton = new wxButton();
  1415. m_nextButton = new wxButton();
  1416. m_vdButton = new wxButton();
  1417. m_vuButton = new wxButton();
  1418. m_prevButton->Create(this, wxID_BUTTONPREV, wxT("|<"));
  1419. m_prevButton->SetToolTip("Previous");
  1420. m_playButton->Create(this, wxID_BUTTONPLAY, wxT(">"));
  1421. m_playButton->SetToolTip("Play");
  1422. m_stopButton->Create(this, wxID_BUTTONSTOP, wxT("[]"));
  1423. m_stopButton->SetToolTip("Stop");
  1424. m_nextButton->Create(this, wxID_BUTTONNEXT, wxT(">|"));
  1425. m_nextButton->SetToolTip("Next");
  1426. m_vdButton->Create(this, wxID_BUTTONVD, wxT("(("));
  1427. m_vdButton->SetToolTip("Volume down");
  1428. m_vuButton->Create(this, wxID_BUTTONVU, wxT("))"));
  1429. m_vuButton->SetToolTip("Volume up");
  1430. vertsizer->Add(m_prevButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
  1431. vertsizer->Add(m_playButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
  1432. vertsizer->Add(m_stopButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
  1433. vertsizer->Add(m_nextButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
  1434. vertsizer->Add(m_vdButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
  1435. vertsizer->Add(m_vuButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
  1436. horsizer1->Add(vertsizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
  1437. sizer->Add(horsizer1, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
  1438. //
  1439. // Create our slider
  1440. //
  1441. m_slider = new wxSlider(this, wxID_SLIDER, 0, // init
  1442. 0, // start
  1443. 1, // end, dummy but must be greater than start
  1444. wxDefaultPosition, wxDefaultSize,
  1445. wxSL_HORIZONTAL );
  1446. sizer->Add(m_slider, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
  1447. //
  1448. // Create the gauge
  1449. //
  1450. m_gauge = new wxGauge();
  1451. m_gauge->Create(this, wxID_GAUGE, 0, wxDefaultPosition, wxDefaultSize,
  1452. wxGA_HORIZONTAL | wxGA_SMOOTH);
  1453. sizer->Add(m_gauge, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
  1454. //
  1455. // Create the speed/volume sliders
  1456. //
  1457. wxBoxSizer* horsizer3 = new wxBoxSizer(wxHORIZONTAL);
  1458. m_volSlider = new wxSlider(this, wxID_VOLSLIDER, 100, // init
  1459. 0, // start
  1460. 100, // end
  1461. wxDefaultPosition, wxSize(250,20),
  1462. wxSL_HORIZONTAL );
  1463. horsizer3->Add(m_volSlider, 1, wxALL, 5);
  1464. m_pbSlider = new wxSlider(this, wxID_PBSLIDER, 4, // init
  1465. 1, // start
  1466. 16, // end
  1467. wxDefaultPosition, wxSize(250,20),
  1468. wxSL_HORIZONTAL );
  1469. horsizer3->Add(m_pbSlider, 1, wxALL, 5);
  1470. sizer->Add(horsizer3, 1, wxCENTRE | wxALL, 5);
  1471. // Now that we have all our rows make some of them growable
  1472. sizer->AddGrowableRow(0);
  1473. //
  1474. // ListCtrl events
  1475. //
  1476. this->Connect( wxID_LISTCTRL, wxEVT_LIST_ITEM_ACTIVATED,
  1477. wxListEventHandler(wxMediaPlayerFrame::OnChangeSong),
  1478. (wxObject*)0, parentFrame);
  1479. //
  1480. // Slider events
  1481. //
  1482. this->Connect(wxID_SLIDER, wxEVT_SCROLL_THUMBTRACK,
  1483. wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek));
  1484. this->Connect(wxID_SLIDER, wxEVT_SCROLL_THUMBRELEASE,
  1485. wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek));
  1486. this->Connect(wxID_PBSLIDER, wxEVT_SCROLL_THUMBRELEASE,
  1487. wxScrollEventHandler(wxMediaPlayerNotebookPage::OnPBChange));
  1488. this->Connect(wxID_VOLSLIDER, wxEVT_SCROLL_THUMBRELEASE,
  1489. wxScrollEventHandler(wxMediaPlayerNotebookPage::OnVolChange));
  1490. //
  1491. // Media Control events
  1492. //
  1493. this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_PLAY,
  1494. wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPlay));
  1495. this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_PAUSE,
  1496. wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPause));
  1497. this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_STOP,
  1498. wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaStop));
  1499. this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_FINISHED,
  1500. wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished));
  1501. this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_LOADED,
  1502. wxMediaEventHandler(wxMediaPlayerFrame::OnMediaLoaded),
  1503. (wxObject*)0, parentFrame);
  1504. //
  1505. // Button events
  1506. //
  1507. this->Connect( wxID_BUTTONPREV, wxEVT_BUTTON,
  1508. wxCommandEventHandler(wxMediaPlayerFrame::OnPrev),
  1509. (wxObject*)0, parentFrame);
  1510. this->Connect( wxID_BUTTONPLAY, wxEVT_BUTTON,
  1511. wxCommandEventHandler(wxMediaPlayerFrame::OnPlay),
  1512. (wxObject*)0, parentFrame);
  1513. this->Connect( wxID_BUTTONSTOP, wxEVT_BUTTON,
  1514. wxCommandEventHandler(wxMediaPlayerFrame::OnStop),
  1515. (wxObject*)0, parentFrame);
  1516. this->Connect( wxID_BUTTONNEXT, wxEVT_BUTTON,
  1517. wxCommandEventHandler(wxMediaPlayerFrame::OnNext),
  1518. (wxObject*)0, parentFrame);
  1519. this->Connect( wxID_BUTTONVD, wxEVT_BUTTON,
  1520. wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeDown),
  1521. (wxObject*)0, parentFrame);
  1522. this->Connect( wxID_BUTTONVU, wxEVT_BUTTON,
  1523. wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeUp),
  1524. (wxObject*)0, parentFrame);
  1525. }
  1526. // ----------------------------------------------------------------------------
  1527. // MyNotebook::OnBeginSeek
  1528. //
  1529. // Sets m_bIsBeingDragged to true to stop the timer from changing the position
  1530. // of our slider
  1531. // ----------------------------------------------------------------------------
  1532. void wxMediaPlayerNotebookPage::OnBeginSeek(wxScrollEvent& WXUNUSED(event))
  1533. {
  1534. m_bIsBeingDragged = true;
  1535. }
  1536. // ----------------------------------------------------------------------------
  1537. // MyNotebook::OnEndSeek
  1538. //
  1539. // Called from file->seek.
  1540. // Called when the user moves the slider -
  1541. // seeks to a position within the media
  1542. // then sets m_bIsBeingDragged to false to ok the timer to change the position
  1543. // ----------------------------------------------------------------------------
  1544. void wxMediaPlayerNotebookPage::OnEndSeek(wxScrollEvent& WXUNUSED(event))
  1545. {
  1546. if( m_mediactrl->Seek(
  1547. m_slider->GetValue() * 1000
  1548. ) == wxInvalidOffset )
  1549. wxMessageBox(wxT("Couldn't seek in movie!"));
  1550. m_bIsBeingDragged = false;
  1551. }
  1552. // ----------------------------------------------------------------------------
  1553. // wxMediaPlayerNotebookPage::IsBeingDragged
  1554. //
  1555. // Returns true if the user is dragging the slider
  1556. // ----------------------------------------------------------------------------
  1557. bool wxMediaPlayerNotebookPage::IsBeingDragged()
  1558. {
  1559. return m_bIsBeingDragged;
  1560. }
  1561. // ----------------------------------------------------------------------------
  1562. // wxMediaPlayerNotebookPage::OnVolChange
  1563. //
  1564. // Called when the user is done dragging the volume-changing slider
  1565. // ----------------------------------------------------------------------------
  1566. void wxMediaPlayerNotebookPage::OnVolChange(wxScrollEvent& WXUNUSED(event))
  1567. {
  1568. if( m_mediactrl->SetVolume(
  1569. m_volSlider->GetValue() / 100.0
  1570. ) == false )
  1571. wxMessageBox(wxT("Couldn't set volume!"));
  1572. }
  1573. // ----------------------------------------------------------------------------
  1574. // wxMediaPlayerNotebookPage::OnPBChange
  1575. //
  1576. // Called when the user is done dragging the speed-changing slider
  1577. // ----------------------------------------------------------------------------
  1578. void wxMediaPlayerNotebookPage::OnPBChange(wxScrollEvent& WXUNUSED(event))
  1579. {
  1580. if( m_mediactrl->SetPlaybackRate(
  1581. m_pbSlider->GetValue() * .25
  1582. ) == false )
  1583. wxMessageBox(wxT("Couldn't set playbackrate!"));
  1584. }
  1585. // ----------------------------------------------------------------------------
  1586. // wxMediaPlayerNotebookPage::OnMediaPlay
  1587. //
  1588. // Called when the media plays.
  1589. // ----------------------------------------------------------------------------
  1590. void wxMediaPlayerNotebookPage::OnMediaPlay(wxMediaEvent& WXUNUSED(event))
  1591. {
  1592. m_playlist->SetItem(m_nLastFileId, 0, wxT(">"));
  1593. }
  1594. // ----------------------------------------------------------------------------
  1595. // wxMediaPlayerNotebookPage::OnMediaPause
  1596. //
  1597. // Called when the media is paused.
  1598. // ----------------------------------------------------------------------------
  1599. void wxMediaPlayerNotebookPage::OnMediaPause(wxMediaEvent& WXUNUSED(event))
  1600. {
  1601. m_playlist->SetItem(m_nLastFileId, 0, wxT("||"));
  1602. }
  1603. // ----------------------------------------------------------------------------
  1604. // wxMediaPlayerNotebookPage::OnMediaStop
  1605. //
  1606. // Called when the media stops.
  1607. // ----------------------------------------------------------------------------
  1608. void wxMediaPlayerNotebookPage::OnMediaStop(wxMediaEvent& WXUNUSED(event))
  1609. {
  1610. m_playlist->SetItem(m_nLastFileId, 0, wxT("[]"));
  1611. }
  1612. // ----------------------------------------------------------------------------
  1613. // wxMediaPlayerNotebookPage::OnMediaFinished
  1614. //
  1615. // Called when the media finishes playing.
  1616. // Here we loop it if the user wants to (has been selected from file menu)
  1617. // ----------------------------------------------------------------------------
  1618. void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent& WXUNUSED(event))
  1619. {
  1620. if(m_bLoop)
  1621. {
  1622. if ( !m_mediactrl->Play() )
  1623. {
  1624. wxMessageBox(wxT("Couldn't loop movie!"));
  1625. m_playlist->SetItem(m_nLastFileId, 0, wxT("E"));
  1626. }
  1627. else
  1628. ++m_nLoops;
  1629. }
  1630. else
  1631. {
  1632. m_playlist->SetItem(m_nLastFileId, 0, wxT("[]"));
  1633. }
  1634. }
  1635. //
  1636. // End of MediaPlayer sample
  1637. //