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