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