]> git.saurik.com Git - wxWidgets.git/blame - src/msw/mediactrl.cpp
more wxPostEvent MT fixes
[wxWidgets.git] / src / msw / mediactrl.cpp
CommitLineData
1a680109
RN
1/////////////////////////////////////////////////////////////////////////////
2// Name: msw/mediactrl.cpp
3// Purpose: wxMediaCtrl MSW
4// Author: Ryan Norton <wxprojects@comcast.net>
72259e00 5// Modified by:
1a680109
RN
6// Created: 11/07/04
7// RCS-ID: $Id$
8// Copyright: (c) Ryan Norton
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12//---------------------------------------------------------------------------
13// Pre-wx includes
14//---------------------------------------------------------------------------
15
16//#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
17//#pragma implementation "moviectrl.h"
18//#endif
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24#pragma hdrstop
25#endif
26
27#include "wx/mediactrl.h"
28
29#if wxUSE_MEDIACTRL
30
31//###########################################################################
32// DECLARATIONS
33//###########################################################################
34
35IMPLEMENT_CLASS(wxMediaCtrl, wxControl);
72259e00
RL
36IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent);
37DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED);
1a680109
RN
38
39//---------------------------------------------------------------------------
40// wxMediaCtrlImpl
41//---------------------------------------------------------------------------
42
43class wxMediaCtrlImpl
44{
45public:
46 wxMediaCtrlImpl() : m_bLoaded(false)
47 { }
48
72259e00 49 virtual ~wxMediaCtrlImpl()
1a680109
RN
50 { }
51
72259e00 52 virtual bool Create(wxMediaCtrl* WXUNUSED(ctrl))
1a680109
RN
53 { return false; }
54
55 virtual bool Play() { return false; }
56 virtual bool Pause() { return false; }
57 virtual bool Stop() { return false; }
58
59 virtual bool Load(const wxString&) { return false; }
60 virtual bool Load(const wxURI&) { return false; }
61
62 virtual wxMediaState GetState() { return wxMEDIASTATE_STOPPED; }
63
64 virtual bool SetPosition(long) { return 0; }
65 virtual long GetPosition() { return 0; }
66 virtual long GetDuration() { return 0; }
67
68 virtual void DoMoveWindow(int, int, int, int) { }
69 virtual wxSize DoGetBestSize() const { return wxSize(0,0); }
70
71 virtual double GetPlaybackRate() { return 0; }
72 virtual bool SetPlaybackRate(double) { return false; }
72259e00 73
1a680109
RN
74 virtual bool MSWWindowProc(WXUINT, WXWPARAM, WXLPARAM) { return false; }
75
76 bool IsLoaded()
77 { return m_bLoaded; }
78
79 bool m_bLoaded;
80};
81
82//---------------------------------------------------------------------------
83// wxDXMediaCtrlImpl
84//---------------------------------------------------------------------------
85
86#if wxUSE_DIRECTSHOW
87
88#include <dshow.h>
89
90#define WM_GRAPHNOTIFY WM_USER+13
91
92#ifdef __WXDEBUG__
93#define wxDSVERIFY(x) wxASSERT( SUCCEEDED ((x)) )
94#else
95#define wxDSVERIFY(x) (x)
96#endif
97
98class wxDXMediaCtrlImpl : public wxMediaCtrlImpl
99{
100public:
101 wxDXMediaCtrlImpl();
102
103 virtual ~wxDXMediaCtrlImpl();
104
105 virtual bool Create(wxMediaCtrl* ctrl);
106
107 virtual bool Play();
108 virtual bool Pause();
109 virtual bool Stop();
110
111 virtual bool Load(const wxString& fileName);
112 virtual bool Load(const wxURI& location);
113
114 virtual wxMediaState GetState();
115
116 virtual bool SetPosition(long where);
117 virtual long GetPosition();
118 virtual long GetDuration();
119
120 virtual void DoMoveWindow(int x, int y, int w, int h);
121 wxSize DoGetBestSize() const;
122
123 virtual double GetPlaybackRate();
124 virtual bool SetPlaybackRate(double);
125
126 void Cleanup();
127
128 bool m_bVideo;
129
130 bool MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
131
132 wxMediaCtrl* m_ctrl;
133
134 IGraphBuilder* m_pGB;
135 IMediaControl* m_pMC;
136 IMediaEventEx* m_pME;
137 IVideoWindow* m_pVW;
138 IBasicAudio* m_pBA;
139 IBasicVideo* m_pBV;
140 IMediaSeeking* m_pMS;
141
142 wxSize m_bestSize;
143};
144
145#endif //wxUSE_DIRECTSHOW
146
147//---------------------------------------------------------------------------
148// wxWMMEMediaCtrlImpl
149//---------------------------------------------------------------------------
150
151#include <mmsystem.h>
1a680109
RN
152
153class wxWMMEMediaCtrlImpl : public wxMediaCtrlImpl
154{
155public:
3f9a3bf9 156
1a680109
RN
157 wxWMMEMediaCtrlImpl();
158 ~wxWMMEMediaCtrlImpl();
159
1a680109
RN
160 virtual bool Create(wxMediaCtrl* ctrl);
161
162 virtual bool Play();
163 virtual bool Pause();
164 virtual bool Stop();
165
166 virtual bool Load(const wxString& fileName);
167 virtual bool Load(const wxURI& location);
168
169 virtual wxMediaState GetState();
170
171 virtual bool SetPosition(long where);
172 virtual long GetPosition();
173 virtual long GetDuration();
174
175 virtual void DoMoveWindow(int x, int y, int w, int h);
176 wxSize DoGetBestSize() const;
177
178 virtual double GetPlaybackRate();
179 virtual bool SetPlaybackRate(double);
3f9a3bf9 180
5987f174
RN
181 bool MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
182
1a680109 183 MCIDEVICEID m_hDev;
3f9a3bf9
RN
184 wxMediaCtrl* m_ctrl;
185 bool m_bVideo;
1a680109
RN
186};
187
1a680109
RN
188//###########################################################################
189//
190// IMPLEMENTATION
191//
192//###########################################################################
193
194//---------------------------------------------------------------------------
195//
196// wxMediaCtrl
197//
198//---------------------------------------------------------------------------
199
72259e00
RL
200bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxString& fileName,
201 const wxPoint& pos, const wxSize& size,
1a680109
RN
202 long style, long WXUNUSED(driver), const wxString& name)
203{
204 //base create
72259e00 205 if ( !wxControl::Create(parent, id, pos, size, (style | wxNO_BORDER) | wxCLIP_CHILDREN,
1a680109
RN
206 wxDefaultValidator, name) )
207 return false;
208
209 //Set our background color to black by default
210 SetBackgroundColour(*wxBLACK);
211
212#if wxUSE_DIRECTSHOW
213 m_imp = new wxDXMediaCtrlImpl;
214 if(!m_imp->Create(this))
215 {
216 delete m_imp;
217#endif
5987f174
RN
218 m_imp = new wxWMMEMediaCtrlImpl;
219 if(!m_imp->Create(this))
1a680109 220 {
5987f174 221 delete m_imp;
1a680109
RN
222 m_imp = NULL;
223 return false;
224 }
225#if wxUSE_DIRECTSHOW
226 }
227#endif
228
229 if(!fileName.empty())
230 {
231 if (!Load(fileName))
232 return false;
233 }
234
235 return true;
236}
237
72259e00
RL
238bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxURI& location,
239 const wxPoint& pos, const wxSize& size,
1a680109
RN
240 long style, long WXUNUSED(driver), const wxString& name)
241{
242 //base create
72259e00 243 if ( !wxControl::Create(parent, id, pos, size, (style | wxNO_BORDER) | wxCLIP_CHILDREN,
1a680109
RN
244 wxDefaultValidator, name) )
245 return false;
246
247 //Set our background color to black by default
248 SetBackgroundColour(*wxBLACK);
249
250#if wxUSE_DIRECTSHOW
251 m_imp = new wxDXMediaCtrlImpl;
252 if(!m_imp->Create(this))
253 {
254 delete m_imp;
255#endif
5987f174
RN
256 m_imp = new wxWMMEMediaCtrlImpl;
257 if(!m_imp->Create(this))
1a680109 258 {
5987f174 259 delete m_imp;
1a680109
RN
260 m_imp = NULL;
261 return false;
262 }
263#if wxUSE_DIRECTSHOW
264 }
265#endif
266
267 if (!Load(location))
268 return false;
269
270 return true;
271}
272
273bool wxMediaCtrl::Load(const wxString& fileName)
274{
275 if(m_imp)
276 return m_imp->Load(fileName);
277 return false;
278}
279
280bool wxMediaCtrl::Load(const wxURI& location)
281{
282 if(m_imp)
283 return m_imp->Load(location);
284 return false;
285}
286
287bool wxMediaCtrl::Play()
288{
289 if(m_imp && m_imp->IsLoaded())
290 return m_imp->Play();
291 return false;
292}
293
294bool wxMediaCtrl::Pause()
295{
296 if(m_imp && m_imp->IsLoaded())
297 return m_imp->Pause();
298 return false;
299}
300
301bool wxMediaCtrl::Stop()
302{
303 if(m_imp && m_imp->IsLoaded())
304 return m_imp->Stop();
305 return false;
306}
307
308double wxMediaCtrl::GetPlaybackRate()
309{
310 if(m_imp && m_imp->IsLoaded())
311 return m_imp->GetPlaybackRate();
312 return 0;
313}
314
315bool wxMediaCtrl::SetPlaybackRate(double dRate)
316{
317 if(m_imp && m_imp->IsLoaded())
318 return m_imp->SetPlaybackRate(dRate);
319 return false;
320}
321
322bool wxMediaCtrl::SetPosition(long where)
323{
324 if(m_imp && m_imp->IsLoaded())
325 return m_imp->SetPosition(where);
326 return false;
327}
328
329long wxMediaCtrl::GetPosition()
330{
331 if(m_imp && m_imp->IsLoaded())
332 return m_imp->GetPosition();
333 return 0;
334}
335
336long wxMediaCtrl::GetDuration()
337{
338 if(m_imp && m_imp->IsLoaded())
339 return m_imp->GetDuration();
340 return 0;
341}
342
343wxMediaState wxMediaCtrl::GetState()
344{
345 if(m_imp && m_imp->IsLoaded())
346 return m_imp->GetState();
347 return wxMEDIASTATE_STOPPED;
348}
349
350WXLRESULT wxMediaCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
351{
352 if(m_imp && m_imp->IsLoaded() && m_imp->MSWWindowProc(nMsg, wParam, lParam) )
353 return wxControl::MSWDefWindowProc(nMsg, wParam, lParam);
354 //pass the event to our parent
355 return wxControl::MSWWindowProc(nMsg, wParam, lParam);
356}
357
358wxSize wxMediaCtrl::DoGetBestSize() const
359{
360 if(m_imp && m_imp->IsLoaded())
361 return m_imp->DoGetBestSize();
362 return wxSize(0,0);
363}
364
365void wxMediaCtrl::DoMoveWindow(int x, int y, int w, int h)
366{
367 wxControl::DoMoveWindow(x,y,w,h);
368
369 if(m_imp && m_imp->IsLoaded())
370 m_imp->DoMoveWindow(x, y, w, h);
371}
372
373wxMediaCtrl::~wxMediaCtrl()
374{
375 if (m_imp)
376 delete m_imp;
377}
378
379
380//---------------------------------------------------------------------------
381//
382// wxDXMediaCtrlImpl
383//
384//---------------------------------------------------------------------------
385
72259e00 386#if wxUSE_DIRECTSHOW
1a680109
RN
387
388wxDXMediaCtrlImpl::wxDXMediaCtrlImpl() : m_pGB(NULL)
389{
390}
391
392bool wxDXMediaCtrlImpl::Create(wxMediaCtrl* ctrl)
393{
394 //create our filter graph
395 HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
396 IID_IGraphBuilder, (void**)&m_pGB);
397
398 //directshow not installed?
399 if ( FAILED(hr) )
400 return false;
401
402 m_ctrl = ctrl;
403
404 return true;
405}
406
407#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
408
409bool wxDXMediaCtrlImpl::Load(const wxString& fileName)
410{
411 if(m_bLoaded)
72259e00
RL
412 Cleanup();
413
1a680109
RN
414 SAFE_RELEASE(m_pGB);
415
416 CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
417 IID_IGraphBuilder, (void**)&m_pGB);
418
72259e00 419 //load the graph & render
1a680109
RN
420 if( FAILED(m_pGB->RenderFile(fileName.wc_str(wxConvLocal), NULL)) )
421 return false;
422
423 //get the interfaces, all of them
424 wxDSVERIFY( m_pGB->QueryInterface(IID_IMediaControl, (void**)&m_pMC) );
425 wxDSVERIFY( m_pGB->QueryInterface(IID_IMediaEventEx, (void**)&m_pME) );
426 wxDSVERIFY( m_pGB->QueryInterface(IID_IMediaSeeking, (void**)&m_pMS) );
427 wxDSVERIFY( m_pGB->QueryInterface(IID_IVideoWindow, (void**)&m_pVW) );
428 wxDSVERIFY( m_pGB->QueryInterface(IID_IBasicAudio, (void**)&m_pBA) );
429 wxDSVERIFY( m_pGB->QueryInterface(IID_IBasicVideo, (void**)&m_pBV) );
430
431 //long lVolume;
432 //pBA->get_Volume(&lVolume);
433 //E_NOTIMPL
434
435 //get the _actual_ size of the movie & remember it
436 long nX, nY, nSX, nSY;
437 if (FAILED(m_pVW->GetWindowPosition(&nX,&nY,&nSX,&nSY)))
438 {
439 m_bVideo = false;
440
441 nSX = nSY = 0;
442 }
72259e00 443 else
1a680109
RN
444 {
445 m_bVideo = true;
446 }
447
448 m_bestSize.x = nSX;
449 m_bestSize.y = nSY;
450
451 if (m_bVideo)
452 {
453 wxDSVERIFY( m_pVW->put_Owner((OAHWND)m_ctrl->GetHandle()) );
454 wxDSVERIFY( m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS) );
455 wxDSVERIFY( m_pVW->put_Visible(OATRUE) ); //OATRUE == -1
456 }
457
458 //make it so that wxEVT_MOVIE_FINISHED works
459 wxDSVERIFY( m_pME->SetNotifyWindow((OAHWND)m_ctrl->GetHandle(), WM_GRAPHNOTIFY, 0) );
460
461 //set the time format
462 wxDSVERIFY( m_pMS->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME) );
463
3f9a3bf9
RN
464 //so that DoGetBestSize will work :)
465 m_bLoaded = true;
466
1a680109 467 //work around refresh issues
3f9a3bf9
RN
468 m_ctrl->InvalidateBestSize();
469 m_ctrl->GetParent()->Layout();
1a680109
RN
470 m_ctrl->GetParent()->Refresh();
471 m_ctrl->GetParent()->Update();
472
1a680109
RN
473 return true;
474}
475
476bool wxDXMediaCtrlImpl::Load(const wxURI& location)
477{
478 return Load(location.BuildUnescapedURI());
479}
480
481bool wxDXMediaCtrlImpl::Play()
482{
483 return SUCCEEDED( m_pMC->Run() );
484}
485
486bool wxDXMediaCtrlImpl::Pause()
487{
488 return SUCCEEDED( m_pMC->Pause() );
489}
490
491bool wxDXMediaCtrlImpl::Stop()
492{
e4b12a53
RN
493 bool bOK = SUCCEEDED( m_pMC->Stop() );
494
495 //We don't care if it can't get to the beginning in directshow -
496 //it could be a non-seeking filter (wince midi) in which case playing
497 //starts all over again
498 SetPosition(0);
499 return bOK;
1a680109
RN
500}
501
502bool wxDXMediaCtrlImpl::SetPosition(long where)
503{
504 //DS uses 100 nanos - so we need a 10 mult
505 LONGLONG pos = ((LONGLONG)where) * 10000;
506
507 return SUCCEEDED( m_pMS->SetPositions(
72259e00 508 &pos,
1a680109 509 AM_SEEKING_AbsolutePositioning,
72259e00 510 NULL,
1a680109
RN
511 AM_SEEKING_NoPositioning
512 ) );
513}
514
515long wxDXMediaCtrlImpl::GetPosition()
516{
517 LONGLONG outCur, outStop;
518 wxDSVERIFY( m_pMS->GetPositions(&outCur, &outStop) );
519
520 //h,m,s,milli - outdur is in 100 nanos
521 return outCur/10000;
522}
523
524long wxDXMediaCtrlImpl::GetDuration()
525{
526 LONGLONG outDuration;
527 wxDSVERIFY( m_pMS->GetDuration(&outDuration) );
528
529 //h,m,s,milli - outdur is in 100 nanos
530 return outDuration/10000;
531}
532
533wxMediaState wxDXMediaCtrlImpl::GetState()
534{
535 //TODO: MS recommends against INFINITE here - do it in stages
536 HRESULT hr;
537 OAFilterState theState;
538 hr = m_pMC->GetState(INFINITE, &theState);
72259e00 539
1a680109
RN
540 wxASSERT( SUCCEEDED(hr) );
541
542 //MSW state is the same as ours
543 //State_Stopped = 0,
544 //State_Paused = State_Stopped + 1,
545 //State_Running = State_Paused + 1
546
547 return (wxMediaState) theState;
548}
549
550double wxDXMediaCtrlImpl::GetPlaybackRate()
551{
552 double dRate;
553 wxDSVERIFY( m_pMS->GetRate(&dRate) );
554 return dRate;
555}
556
557bool wxDXMediaCtrlImpl::SetPlaybackRate(double dRate)
558{
559 return SUCCEEDED( m_pMS->SetRate(dRate) );
560}
561
562bool wxDXMediaCtrlImpl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
563{
564 if (nMsg == WM_GRAPHNOTIFY)
565 {
566 LONG evCode, evParam1, evParam2;
567 HRESULT hr=S_OK;
568
569 // Process all queued events
570 while(SUCCEEDED(m_pME->GetEvent(&evCode, (LONG_PTR *) &evParam1,
72259e00
RL
571 (LONG_PTR *) &evParam2, 0)
572 )
1a680109
RN
573 )
574 {
575 // Free memory associated with callback, since we're not using it
576 hr = m_pME->FreeEventParams(evCode, evParam1, evParam2);
577
578 // If this is the end of the clip, notify handler
579 if(EC_COMPLETE == evCode)
580 {
e4b12a53
RN
581 //Interestingly enough, DirectShow does not actually stop
582 //the filters - even when it reaches the end!
1a680109
RN
583#ifdef __WXDEBUG__
584 wxASSERT( Stop() );
585#else
586 Stop();
587#endif
e4b12a53 588
1a680109
RN
589 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED, m_ctrl->GetId());
590 m_ctrl->GetParent()->ProcessEvent(theEvent);
591 }
72259e00 592 }
1a680109
RN
593 return true;
594 }
595 return false;
596}
597
598void wxDXMediaCtrlImpl::Cleanup()
599{
600 // Hide then disown the window
601 if(m_pVW)
602 {
603 m_pVW->put_Visible(OAFALSE); //OSFALSE == 0
604 m_pVW->put_Owner(NULL);
605 }
606
607 // Release and zero DirectShow interfaces
608 SAFE_RELEASE(m_pME);
609 SAFE_RELEASE(m_pMS);
610 SAFE_RELEASE(m_pMC);
611 SAFE_RELEASE(m_pBA);
612 SAFE_RELEASE(m_pBV);
613 SAFE_RELEASE(m_pVW);
614}
615
616wxDXMediaCtrlImpl::~wxDXMediaCtrlImpl()
617{
618 if (m_bLoaded)
619 Cleanup();
620
621 SAFE_RELEASE(m_pGB);
622}
623
624wxSize wxDXMediaCtrlImpl::DoGetBestSize() const
625{
626 return m_bestSize;
627}
628
629void wxDXMediaCtrlImpl::DoMoveWindow(int x, int y, int w, int h)
630{
631 if(m_bLoaded && m_bVideo)
632 {
633 wxDSVERIFY( m_pVW->SetWindowPosition(0, 0, w, h) );
634 }
635}
636
637#endif //wxUSE_DIRECTSHOW
638
639//---------------------------------------------------------------------------
640//
641// wxWMMEMediaCtrlImpl
642//
643//---------------------------------------------------------------------------
644
33d8e2fc
RN
645//
646// Cruft to simulate digitalv.h
647//
648
649typedef struct {
650 DWORD_PTR dwCallback;
651#ifdef MCI_USE_OFFEXT
652 POINT ptOffset;
653 POINT ptExtent;
654#else
655 RECT rc;
656#endif
657} MCI_DGV_RECT_PARMS;
658
659typedef struct {
660 DWORD_PTR dwCallback;
661 HWND hWnd;
662#ifndef _WIN32
663 WORD wReserved1;
664#endif
665 UINT nCmdShow;
666#ifndef _WIN32
667 WORD wReserved2;
668#endif
669 LPSTR lpstrText;
670} MCI_DGV_WINDOW_PARMSA;
671
672typedef struct {
673 DWORD_PTR dwCallback;
674 HWND hWnd;
675#ifndef _WIN32
676 WORD wReserved1;
677#endif
678 UINT nCmdShow;
679#ifndef _WIN32
680 WORD wReserved2;
681#endif
682 LPWSTR lpstrText;
683} MCI_DGV_WINDOW_PARMSW;
684#ifdef UNICODE
685typedef MCI_DGV_WINDOW_PARMSW MCI_DGV_WINDOW_PARMS;
686#else
687typedef MCI_DGV_WINDOW_PARMSA MCI_DGV_WINDOW_PARMS;
688#endif // UNICODE
689
3f9a3bf9
RN
690wxWMMEMediaCtrlImpl::wxWMMEMediaCtrlImpl() : m_bVideo(false)
691{
5987f174
RN
692/* TCHAR sz[5000];
693 mciGetErrorString(nError, sz, 5000);
694 wxMessageBox(wxString::Format(_T("Error:%s"), sz));
72259e00 695 */
3f9a3bf9
RN
696}
697
698wxWMMEMediaCtrlImpl::~wxWMMEMediaCtrlImpl()
699{
700 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
701}
702
703bool wxWMMEMediaCtrlImpl::Create(wxMediaCtrl* ctrl)
72259e00 704{
3f9a3bf9
RN
705 m_ctrl = ctrl;
706 return true;
707}
708
3f9a3bf9
RN
709bool wxWMMEMediaCtrlImpl::Load(const wxString& fileName)
710{
711 if(m_bLoaded)
712 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
713
714 MCI_OPEN_PARMS openParms;
715 MCI_SET_PARMS setParms;
716
3f9a3bf9
RN
717 openParms.lpstrElementName = (wxChar*) fileName.c_str();
718
5987f174
RN
719 //Here's where the trick lies - if you don't specify MCI_OPEN_TYPE,
720 //then it actually automagically finds the device for you!
721 if ( mciSendCommand(0, MCI_OPEN,
722 MCI_OPEN_ELEMENT,
72259e00 723 (DWORD)(LPVOID)&openParms) != 0)
5987f174 724 return false;
3f9a3bf9
RN
725
726 m_hDev = openParms.wDeviceID;
727
3f9a3bf9
RN
728 setParms.dwCallback = 0;
729 setParms.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
730
731 if (mciSendCommand(m_hDev, MCI_SET, MCI_SET_TIME_FORMAT,
732 (DWORD)(LPVOID)&setParms) != 0)
733 return false;
734
3f9a3bf9
RN
735 MCI_DGV_WINDOW_PARMS windowParms;
736
5987f174 737 windowParms.hWnd = (HWND)m_ctrl->GetHandle();
3f9a3bf9 738 m_bVideo = (mciSendCommand(m_hDev, MCI_WINDOW,
33d8e2fc 739 0x00010000L //MCI_DGV_WINDOW_HWND
72259e00 740 ,
33d8e2fc 741 (DWORD)(LPVOID)&windowParms) == 0);
3f9a3bf9
RN
742 m_bLoaded = true;
743
5987f174
RN
744 //work around refresh issues
745 m_ctrl->InvalidateBestSize();
746 m_ctrl->GetParent()->Layout();
747 m_ctrl->GetParent()->Refresh();
748 m_ctrl->GetParent()->Update();
72259e00 749
3f9a3bf9
RN
750 return true;
751}
752
753bool wxWMMEMediaCtrlImpl::Load(const wxURI& WXUNUSED(location))
754{
755 return false;
756}
757
5987f174
RN
758bool wxWMMEMediaCtrlImpl::Play()
759{
760 //the directshow driver ("mpegvideo") will crash if we don't do a playParms here
761 MCI_PLAY_PARMS playParms;
cf237250 762 playParms.dwCallback = (DWORD)(HWND)m_ctrl->GetHWND();
5987f174
RN
763 bool bOK = mciSendCommand(m_hDev, MCI_PLAY, MCI_NOTIFY, (DWORD)(LPVOID)&playParms) == 0;
764 return (bOK) ;/*||
765 (mciSendCommand(m_hDev, MCI_RESUME, 0, 0) == 0);*/
766}
767
768bool wxWMMEMediaCtrlImpl::Pause()
769{
770 return (mciSendCommand(m_hDev, MCI_PAUSE, MCI_WAIT, 0) == 0);
771}
772
773bool wxWMMEMediaCtrlImpl::Stop()
774{
775 return (mciSendCommand(m_hDev, MCI_STOP, MCI_WAIT, 0) == 0) &&
776 (mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0) == 0);
777}
778
779
3f9a3bf9
RN
780wxMediaState wxWMMEMediaCtrlImpl::GetState()
781{
782 MCI_STATUS_PARMS statusParms;
783 statusParms.dwItem = MCI_STATUS_MODE;
784 mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
785 (DWORD)(LPVOID)&statusParms);
786
787 if(statusParms.dwReturn == MCI_MODE_PAUSE)
788 return wxMEDIASTATE_PAUSED;
789 else if(statusParms.dwReturn == MCI_MODE_PLAY)
790 return wxMEDIASTATE_PLAYING;
791 else
792 return wxMEDIASTATE_STOPPED;
793}
794
795bool wxWMMEMediaCtrlImpl::SetPosition(long where)
796{
797 MCI_SEEK_PARMS seekParms;
798 seekParms.dwCallback = 0;
799 seekParms.dwTo = where;
800
801 bool bReplay = GetState() == wxMEDIASTATE_PLAYING;
802
803 if( mciSendCommand(m_hDev, MCI_SEEK, MCI_TO, (DWORD)(LPVOID)&seekParms) != 0)
804 return false;
3f9a3bf9
RN
805
806 if (bReplay)
807 return Play();
808 else
809 return true;
810}
811
812long wxWMMEMediaCtrlImpl::GetPosition()
813{
814 MCI_STATUS_PARMS statusParms;
72259e00
RL
815
816 statusParms.dwItem = MCI_STATUS_POSITION;
817 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
3f9a3bf9
RN
818 (DWORD)(LPSTR)&statusParms) != 0)
819 return 0;
820
821 return statusParms.dwReturn;
822}
823
824long wxWMMEMediaCtrlImpl::GetDuration()
825{
826 MCI_STATUS_PARMS statusParms;
72259e00
RL
827
828 statusParms.dwItem = MCI_STATUS_LENGTH;
829 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
3f9a3bf9
RN
830 (DWORD)(LPSTR)&statusParms) != 0)
831 return 0;
832
833 return statusParms.dwReturn;
834}
835
836void wxWMMEMediaCtrlImpl::DoMoveWindow(int, int, int, int)
837{
838}
839
840wxSize wxWMMEMediaCtrlImpl::DoGetBestSize() const
841{
842 if(m_bVideo)
843 {
72259e00 844 MCI_DGV_RECT_PARMS rect;
3f9a3bf9 845
33d8e2fc 846 mciSendCommand(m_hDev, MCI_WHERE, 0x00020000L//MCI_DGV_WHERE_SOURCE
72259e00 847 ,
33d8e2fc 848 (DWORD)(LPSTR)&rect);
3f9a3bf9 849 return wxSize(rect.rc.right, rect.rc.bottom);
3f9a3bf9
RN
850 }
851 return wxSize(0,0);
852}
853
854double wxWMMEMediaCtrlImpl::GetPlaybackRate()
855{
856 return 1.0;
857}
858
859bool wxWMMEMediaCtrlImpl::SetPlaybackRate(double)
860{
861 return false;
862}
863
5987f174 864bool wxWMMEMediaCtrlImpl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
3f9a3bf9 865{
5987f174
RN
866 if(nMsg == MM_MCINOTIFY)
867 {
868 wxASSERT(lParam == (WXLPARAM) m_hDev);
869 if(wParam == (WXWPARAM) MCI_NOTIFY_SUCCESSFUL && lParam == (WXLPARAM) m_hDev)
870 {
871#ifdef __WXDEBUG__
872 wxASSERT(mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0) == 0);
873#else
874 mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0);
875#endif
3f9a3bf9 876
5987f174
RN
877 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED, m_ctrl->GetId());
878 m_ctrl->GetParent()->ProcessEvent(theEvent);
879 }
880 return true;
881 }
3f9a3bf9
RN
882 return false;
883}
884
72259e00
RL
885#endif //wxUSE_MEDIACTRL
886