Add remaining files
[juce-lv2.git] / juce / source / src / native / windows / juce_win32_DirectShowComponent.cpp
blob21e8e2d8c614175b30ac8afad12ca06d3e80eea8
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #if JUCE_INCLUDED_FILE && JUCE_DIRECTSHOW
29 //======================================================================
30 namespace DirectShowHelpers
32 bool checkDShowAvailability()
34 ComSmartPtr <IGraphBuilder> graph;
35 return SUCCEEDED (graph.CoCreateInstance (CLSID_FilterGraph));
38 //======================================================================
39 class VideoRenderer
41 public:
42 VideoRenderer() {}
43 virtual ~VideoRenderer() {}
45 virtual HRESULT create (ComSmartPtr <IGraphBuilder>& graphBuilder,
46 ComSmartPtr <IBaseFilter>& baseFilter, HWND hwnd) = 0;
48 virtual void setVideoWindow (HWND hwnd) = 0;
49 virtual void setVideoPosition (HWND hwnd, long videoWidth, long videoHeight) = 0;
50 virtual void repaintVideo (HWND hwnd, HDC hdc) = 0;
51 virtual void displayModeChanged() = 0;
52 virtual HRESULT getVideoSize (long& videoWidth, long& videoHeight) = 0;
55 //======================================================================
56 class VMR7 : public VideoRenderer
58 public:
59 VMR7() {}
61 HRESULT create (ComSmartPtr <IGraphBuilder>& graphBuilder,
62 ComSmartPtr <IBaseFilter>& baseFilter, HWND hwnd)
64 ComSmartPtr <IVMRFilterConfig> filterConfig;
66 HRESULT hr = baseFilter.CoCreateInstance (CLSID_VideoMixingRenderer);
68 if (SUCCEEDED (hr))
69 hr = graphBuilder->AddFilter (baseFilter, L"VMR-7");
71 if (SUCCEEDED (hr))
72 hr = baseFilter.QueryInterface (filterConfig);
74 if (SUCCEEDED (hr))
75 hr = filterConfig->SetRenderingMode (VMRMode_Windowless);
77 if (SUCCEEDED (hr))
78 hr = baseFilter.QueryInterface (windowlessControl);
80 if (SUCCEEDED (hr))
81 hr = windowlessControl->SetVideoClippingWindow (hwnd);
83 if (SUCCEEDED (hr))
84 hr = windowlessControl->SetAspectRatioMode (VMR_ARMODE_LETTER_BOX);
86 return hr;
89 void setVideoWindow (HWND hwnd)
91 windowlessControl->SetVideoClippingWindow (hwnd);
94 void setVideoPosition (HWND hwnd, long videoWidth, long videoHeight)
96 RECT src, dest;
98 SetRect (&src, 0, 0, videoWidth, videoHeight);
99 GetClientRect (hwnd, &dest);
101 windowlessControl->SetVideoPosition (&src, &dest);
104 void repaintVideo (HWND hwnd, HDC hdc)
106 windowlessControl->RepaintVideo (hwnd, hdc);
109 void displayModeChanged()
111 windowlessControl->DisplayModeChanged();
114 HRESULT getVideoSize (long& videoWidth, long& videoHeight)
116 return windowlessControl->GetNativeVideoSize (&videoWidth, &videoHeight, nullptr, nullptr);
119 private:
120 ComSmartPtr <IVMRWindowlessControl> windowlessControl;
122 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VMR7);
126 //======================================================================
127 #if JUCE_MEDIAFOUNDATION
128 class EVR : public VideoRenderer
130 public:
131 EVR() {}
133 HRESULT create (ComSmartPtr <IGraphBuilder>& graphBuilder,
134 ComSmartPtr <IBaseFilter>& baseFilter, HWND hwnd)
136 ComSmartPtr <IMFGetService> getService;
138 HRESULT hr = baseFilter.CoCreateInstance (CLSID_EnhancedVideoRenderer);
140 if (SUCCEEDED (hr))
141 hr = graphBuilder->AddFilter (baseFilter, L"EVR");
143 if (SUCCEEDED (hr))
144 hr = baseFilter.QueryInterface (getService);
146 if (SUCCEEDED (hr))
147 hr = getService->GetService (MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl,
148 (LPVOID*) videoDisplayControl.resetAndGetPointerAddress());
150 if (SUCCEEDED (hr))
151 hr = videoDisplayControl->SetVideoWindow (hwnd);
153 if (SUCCEEDED (hr))
154 hr = videoDisplayControl->SetAspectRatioMode (MFVideoARMode_PreservePicture);
156 return hr;
159 void setVideoWindow (HWND hwnd)
161 videoDisplayControl->SetVideoWindow (hwnd);
164 void setVideoPosition (HWND hwnd, long /*videoWidth*/, long /*videoHeight*/)
166 const MFVideoNormalizedRect src = { 0.0f, 0.0f, 1.0f, 1.0f };
168 RECT dest;
169 GetClientRect (hwnd, &dest);
171 videoDisplayControl->SetVideoPosition (&src, &dest);
174 void repaintVideo (HWND /*hwnd*/, HDC /*hdc*/)
176 videoDisplayControl->RepaintVideo();
179 void displayModeChanged() {}
181 HRESULT getVideoSize (long& videoWidth, long& videoHeight)
183 SIZE sz;
184 HRESULT hr = videoDisplayControl->GetNativeVideoSize (&sz, nullptr);
185 videoWidth = sz.cx;
186 videoHeight = sz.cy;
187 return hr;
190 private:
191 ComSmartPtr <IMFVideoDisplayControl> videoDisplayControl;
193 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EVR);
195 #endif
199 //======================================================================
200 class DirectShowComponent::DirectShowContext
202 public:
203 DirectShowContext (DirectShowComponent& component_, VideoRendererType type_)
204 : component (component_),
205 hwnd (0),
206 hdc (0),
207 state (uninitializedState),
208 hasVideo (false),
209 videoWidth (0),
210 videoHeight (0),
211 type (type_)
213 CoInitialize (0);
215 if (type == dshowDefault)
217 type = dshowVMR7;
219 #if JUCE_MEDIAFOUNDATION
220 if (SystemStats::getOperatingSystemType() >= SystemStats::WinVista)
221 type = dshowEVR;
222 #endif
226 ~DirectShowContext()
228 release();
229 CoUninitialize();
232 //======================================================================
233 HWND getNativeWindowHandle() const
235 return nativeWindow != nullptr ? nativeWindow->getHandle() : 0;
238 //======================================================================
239 void updateWindowPosition (const Rectangle<int>& newBounds)
241 nativeWindow->setWindowPosition (newBounds);
244 void showWindow (bool shouldBeVisible)
246 nativeWindow->showWindow (shouldBeVisible);
249 //======================================================================
250 void repaint()
252 if (hasVideo)
253 videoRenderer->repaintVideo (nativeWindow->getHandle(), nativeWindow->getContext());
256 void updateVideoPosition()
258 if (hasVideo)
259 videoRenderer->setVideoPosition (nativeWindow->getHandle(), videoWidth, videoHeight);
262 void displayResolutionChanged()
264 if (hasVideo)
265 videoRenderer->displayModeChanged();
268 //======================================================================
269 void peerChanged()
271 deleteNativeWindow();
273 mediaEvent->SetNotifyWindow (0, 0, 0);
274 if (videoRenderer != nullptr)
275 videoRenderer->setVideoWindow (nullptr);
277 createNativeWindow();
279 mediaEvent->SetNotifyWindow ((OAHWND) hwnd, graphEventID, 0);
280 if (videoRenderer != nullptr)
281 videoRenderer->setVideoWindow (hwnd);
284 //======================================================================
285 bool loadFile (const String& fileOrURLPath)
287 jassert (state == uninitializedState);
289 if (! createNativeWindow())
290 return false;
292 HRESULT hr = graphBuilder.CoCreateInstance (CLSID_FilterGraph);
294 // basic playback interfaces
295 if (SUCCEEDED (hr)) hr = graphBuilder.QueryInterface (mediaControl);
296 if (SUCCEEDED (hr)) hr = graphBuilder.QueryInterface (mediaPosition);
297 if (SUCCEEDED (hr)) hr = graphBuilder.QueryInterface (mediaEvent);
298 if (SUCCEEDED (hr)) hr = graphBuilder.QueryInterface (basicAudio);
300 // video renderer interface
301 if (SUCCEEDED (hr))
303 #if JUCE_MEDIAFOUNDATION
304 if (type == dshowEVR)
305 videoRenderer = new DirectShowHelpers::EVR();
306 else
307 #endif
308 videoRenderer = new DirectShowHelpers::VMR7();
310 hr = videoRenderer->create (graphBuilder, baseFilter, hwnd);
313 // build filter graph
314 if (SUCCEEDED (hr))
315 hr = graphBuilder->RenderFile (fileOrURLPath.toWideCharPointer(), nullptr);
317 // remove video renderer if not connected (no video)
318 if (SUCCEEDED (hr))
320 if (isRendererConnected())
322 hasVideo = true;
323 hr = videoRenderer->getVideoSize (videoWidth, videoHeight);
325 else
327 hasVideo = false;
328 graphBuilder->RemoveFilter (baseFilter);
329 videoRenderer = nullptr;
330 baseFilter = nullptr;
334 // set window to receive events
335 if (SUCCEEDED (hr))
336 hr = mediaEvent->SetNotifyWindow ((OAHWND) hwnd, graphEventID, 0);
338 if (SUCCEEDED (hr))
340 state = stoppedState;
341 return true;
344 release();
345 return false;
348 void release()
350 if (mediaControl != nullptr)
351 mediaControl->Stop();
353 if (mediaEvent != nullptr)
354 mediaEvent->SetNotifyWindow (0, 0, 0);
356 if (videoRenderer != nullptr)
357 videoRenderer->setVideoWindow (0);
359 hasVideo = false;
360 videoRenderer = nullptr;
362 baseFilter = nullptr;
363 basicAudio = nullptr;
364 mediaEvent = nullptr;
365 mediaPosition = nullptr;
366 mediaControl = nullptr;
367 graphBuilder = nullptr;
369 state = uninitializedState;
371 videoWidth = 0;
372 videoHeight = 0;
374 if (nativeWindow != nullptr)
375 deleteNativeWindow();
378 void graphEventProc()
380 LONG ec;
381 LONG_PTR p1, p2;
383 jassert (mediaEvent != nullptr);
385 while (SUCCEEDED (mediaEvent->GetEvent (&ec, &p1, &p2, 0)))
387 switch (ec)
389 case EC_REPAINT:
390 component.repaint();
391 break;
393 case EC_COMPLETE:
394 if (component.isLooping())
395 component.goToStart();
396 else
397 component.stop();
398 break;
400 case EC_USERABORT:
401 case EC_ERRORABORT:
402 case EC_ERRORABORTEX:
403 component.closeMovie();
404 break;
406 default:
407 break;
410 mediaEvent->FreeEventParams (ec, p1, p2);
414 //======================================================================
415 void run()
417 mediaControl->Run();
418 state = runningState;
421 void stop()
423 mediaControl->Stop();
424 state = stoppedState;
427 void pause()
429 mediaControl->Pause();
430 state = pausedState;
433 //======================================================================
434 bool isInitialised() const noexcept { return state != uninitializedState; }
435 bool isRunning() const noexcept { return state == runningState; }
436 bool isPaused() const noexcept { return state == pausedState; }
437 bool isStopped() const noexcept { return state == stoppedState; }
438 bool containsVideo() const noexcept { return hasVideo; }
439 int getVideoWidth() const noexcept { return (int) videoWidth; }
440 int getVideoHeight() const noexcept { return (int) videoHeight; }
442 //======================================================================
443 double getDuration() const
445 REFTIME duration;
446 mediaPosition->get_Duration (&duration);
447 return duration;
450 double getPosition() const
452 REFTIME seconds;
453 mediaPosition->get_CurrentPosition (&seconds);
454 return seconds;
457 //======================================================================
458 void setSpeed (const float newSpeed) { mediaPosition->put_Rate (newSpeed); }
459 void setPosition (const double seconds) { mediaPosition->put_CurrentPosition (seconds); }
460 void setVolume (const float newVolume) { basicAudio->put_Volume (convertToDShowVolume (newVolume)); }
462 // in DirectShow, full volume is 0, silence is -10000
463 static long convertToDShowVolume (const float vol) noexcept
465 if (vol >= 1.0f) return 0;
466 if (vol <= 0.0f) return -10000;
468 return roundToInt ((vol * 10000.0f) - 10000.0f);
471 float getVolume() const
473 long volume;
474 basicAudio->get_Volume (&volume);
475 return (volume + 10000) / 10000.0f;
478 private:
479 //======================================================================
480 enum { graphEventID = WM_APP + 0x43f0 };
482 DirectShowComponent& component;
483 HWND hwnd;
484 HDC hdc;
486 enum State { uninitializedState, runningState, pausedState, stoppedState };
487 State state;
489 bool hasVideo;
490 long videoWidth, videoHeight;
492 VideoRendererType type;
494 ComSmartPtr <IGraphBuilder> graphBuilder;
495 ComSmartPtr <IMediaControl> mediaControl;
496 ComSmartPtr <IMediaPosition> mediaPosition;
497 ComSmartPtr <IMediaEventEx> mediaEvent;
498 ComSmartPtr <IBasicAudio> basicAudio;
499 ComSmartPtr <IBaseFilter> baseFilter;
501 ScopedPointer <DirectShowHelpers::VideoRenderer> videoRenderer;
503 //======================================================================
504 class NativeWindowClass : public DeletedAtShutdown
506 private:
507 NativeWindowClass()
508 : atom (0)
510 String windowClassName ("JUCE_DIRECTSHOW_");
511 windowClassName << (int) (Time::currentTimeMillis() & 0x7fffffff);
513 HINSTANCE moduleHandle = (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle();
515 TCHAR moduleFile [1024] = { 0 };
516 GetModuleFileName (moduleHandle, moduleFile, 1024);
518 WNDCLASSEX wcex = { 0 };
519 wcex.cbSize = sizeof (wcex);
520 wcex.style = CS_OWNDC;
521 wcex.lpfnWndProc = (WNDPROC) wndProc;
522 wcex.lpszClassName = windowClassName.toWideCharPointer();
523 wcex.hInstance = moduleHandle;
525 atom = RegisterClassEx (&wcex);
526 jassert (atom != 0);
529 ~NativeWindowClass()
531 if (atom != 0)
532 UnregisterClass (getWindowClassName(), (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle());
534 clearSingletonInstance();
537 static LRESULT CALLBACK wndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
539 DirectShowContext* c = (DirectShowContext*) GetWindowLongPtr (hwnd, GWLP_USERDATA);
541 if (c != nullptr)
543 jassert (c->getNativeWindowHandle() == hwnd);
545 switch (msg)
547 case WM_ERASEBKGND: return 1;
548 case WM_DISPLAYCHANGE: c->displayResolutionChanged(); break;
549 case graphEventID: c->graphEventProc(); return 0;
550 default: break;
554 return DefWindowProc (hwnd, msg, wParam, lParam);
557 public:
558 bool isRegistered() const noexcept { return atom != 0; }
559 LPCTSTR getWindowClassName() const noexcept { return (LPCTSTR) MAKELONG (atom, 0); }
561 juce_DeclareSingleton_SingleThreaded_Minimal (NativeWindowClass);
563 private:
564 ATOM atom;
566 JUCE_DECLARE_NON_COPYABLE (NativeWindowClass);
569 //======================================================================
570 class NativeWindow
572 public:
573 NativeWindow (HWND parentToAddTo, void* const userData)
574 : hwnd (0), hdc (0)
576 NativeWindowClass* const wc = NativeWindowClass::getInstance();
578 if (wc->isRegistered())
580 DWORD exstyle = 0;
581 DWORD type = WS_CHILD;
583 hwnd = CreateWindowEx (exstyle, wc->getWindowClassName(),
584 L"", type, 0, 0, 0, 0, parentToAddTo, 0,
585 (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(), 0);
587 if (hwnd != 0)
589 hdc = GetDC (hwnd);
590 SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) userData);
594 jassert (hwnd != 0);
597 ~NativeWindow()
599 if (hwnd != 0)
601 SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) 0);
602 DestroyWindow (hwnd);
606 HWND getHandle() const noexcept { return hwnd; }
607 HDC getContext() const noexcept { return hdc; }
609 void setWindowPosition (const Rectangle<int>& newBounds)
611 SetWindowPos (hwnd, 0, newBounds.getX(), newBounds.getY(),
612 newBounds.getWidth(), newBounds.getHeight(),
613 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER);
616 void showWindow (const bool shouldBeVisible)
618 ShowWindow (hwnd, shouldBeVisible ? SW_SHOWNA : SW_HIDE);
621 private:
622 HWND hwnd;
623 HDC hdc;
625 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeWindow);
628 ScopedPointer<NativeWindow> nativeWindow;
630 //======================================================================
631 bool createNativeWindow()
633 jassert (nativeWindow == nullptr);
635 ComponentPeer* topLevelPeer = component.getTopLevelComponent()->getPeer();
637 jassert (topLevelPeer != nullptr);
639 if (topLevelPeer != nullptr)
641 nativeWindow = new NativeWindow ((HWND) topLevelPeer->getNativeHandle(), this);
643 hwnd = nativeWindow->getHandle();
645 if (hwnd != 0)
647 hdc = GetDC (hwnd);
648 component.updateContextPosition();
649 component.showContext (component.isShowing());
650 return true;
652 else
654 nativeWindow = nullptr;
658 return false;
661 void deleteNativeWindow()
663 jassert (nativeWindow != nullptr);
664 ReleaseDC (hwnd, hdc);
665 hwnd = 0;
666 hdc = 0;
667 nativeWindow = nullptr;
670 bool isRendererConnected()
672 ComSmartPtr <IEnumPins> enumPins;
674 HRESULT hr = baseFilter->EnumPins (enumPins.resetAndGetPointerAddress());
676 if (SUCCEEDED (hr))
677 hr = enumPins->Reset();
679 ComSmartPtr<IPin> pin;
681 while (SUCCEEDED (hr)
682 && enumPins->Next (1, pin.resetAndGetPointerAddress(), nullptr) == S_OK)
684 ComSmartPtr<IPin> otherPin;
686 hr = pin->ConnectedTo (otherPin.resetAndGetPointerAddress());
688 if (SUCCEEDED (hr))
690 PIN_DIRECTION direction;
691 hr = pin->QueryDirection (&direction);
693 if (SUCCEEDED (hr) && direction == PINDIR_INPUT)
694 return true;
696 else if (hr == VFW_E_NOT_CONNECTED)
698 hr = S_OK;
702 return false;
705 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DirectShowContext);
708 juce_ImplementSingleton_SingleThreaded (DirectShowComponent::DirectShowContext::NativeWindowClass);
711 //======================================================================
712 class DirectShowComponent::DirectShowComponentWatcher : public ComponentMovementWatcher
714 public:
715 DirectShowComponentWatcher (DirectShowComponent* const owner_)
716 : ComponentMovementWatcher (owner_),
717 owner (owner_)
721 void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
723 if (owner->videoLoaded)
724 owner->updateContextPosition();
727 void componentPeerChanged()
729 if (owner->videoLoaded)
730 owner->recreateNativeWindowAsync();
733 void componentVisibilityChanged()
735 if (owner->videoLoaded)
736 owner->showContext (owner->isShowing());
739 //======================================================================
740 private:
741 DirectShowComponent* const owner;
743 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DirectShowComponentWatcher);
747 //======================================================================
748 DirectShowComponent::DirectShowComponent (VideoRendererType type)
749 : videoLoaded (false),
750 looping (false),
751 needToUpdateViewport (true),
752 needToRecreateNativeWindow (false)
754 setOpaque (true);
755 context = new DirectShowContext (*this, type);
756 componentWatcher = new DirectShowComponentWatcher (this);
759 DirectShowComponent::~DirectShowComponent()
761 componentWatcher = nullptr;
764 bool DirectShowComponent::isDirectShowAvailable()
766 static bool isDSAvailable = DirectShowHelpers::checkDShowAvailability();
767 return isDSAvailable;
770 void DirectShowComponent::recreateNativeWindowAsync()
772 needToRecreateNativeWindow = true;
773 repaint();
776 void DirectShowComponent::updateContextPosition()
778 needToUpdateViewport = true;
780 if (getWidth() > 0 && getHeight() > 0)
782 Component* const topComp = getTopLevelComponent();
784 if (topComp->getPeer() != nullptr)
785 context->updateWindowPosition (topComp->getLocalArea (this, getLocalBounds()));
789 void DirectShowComponent::showContext (const bool shouldBeVisible)
791 context->showWindow (shouldBeVisible);
794 void DirectShowComponent::paint (Graphics& g)
796 if (videoLoaded)
798 if (needToRecreateNativeWindow)
800 context->peerChanged();
801 needToRecreateNativeWindow = false;
804 if (needToUpdateViewport)
806 context->updateVideoPosition();
807 needToUpdateViewport = false;
810 context->repaint();
812 ComponentPeer* const peer = getPeer();
814 if (peer != nullptr)
816 const Point<int> topLeft (getScreenPosition() - peer->getScreenPosition());
817 peer->addMaskedRegion (topLeft.getX(), topLeft.getY(), getWidth(), getHeight());
820 else
822 g.fillAll (Colours::grey);
826 //======================================================================
827 bool DirectShowComponent::loadMovie (const String& fileOrURLPath)
829 closeMovie();
831 videoLoaded = context->loadFile (fileOrURLPath);
833 if (videoLoaded)
835 videoPath = fileOrURLPath;
836 context->updateVideoPosition();
839 return videoLoaded;
842 bool DirectShowComponent::loadMovie (const File& videoFile)
844 return loadMovie (videoFile.getFullPathName());
847 bool DirectShowComponent::loadMovie (const URL& videoURL)
849 return loadMovie (videoURL.toString (false));
852 void DirectShowComponent::closeMovie()
854 if (videoLoaded)
855 context->release();
857 videoLoaded = false;
858 videoPath = String::empty;
861 //======================================================================
862 File DirectShowComponent::getCurrentMoviePath() const { return videoPath; }
863 bool DirectShowComponent::isMovieOpen() const { return videoLoaded; }
864 double DirectShowComponent::getMovieDuration() const { return videoLoaded ? context->getDuration() : 0.0; }
865 void DirectShowComponent::setLooping (const bool shouldLoop) { looping = shouldLoop; }
866 bool DirectShowComponent::isLooping() const { return looping; }
868 void DirectShowComponent::getMovieNormalSize (int &width, int &height) const
870 width = context->getVideoWidth();
871 height = context->getVideoHeight();
874 //======================================================================
875 void DirectShowComponent::setBoundsWithCorrectAspectRatio (const Rectangle<int>& spaceToFitWithin,
876 const RectanglePlacement& placement)
878 int normalWidth, normalHeight;
879 getMovieNormalSize (normalWidth, normalHeight);
881 const Rectangle<int> normalSize (0, 0, normalWidth, normalHeight);
883 if (! (spaceToFitWithin.isEmpty() || normalSize.isEmpty()))
884 setBounds (placement.appliedTo (normalSize, spaceToFitWithin));
885 else
886 setBounds (spaceToFitWithin);
889 //======================================================================
890 void DirectShowComponent::play()
892 if (videoLoaded)
893 context->run();
896 void DirectShowComponent::stop()
898 if (videoLoaded)
899 context->pause();
902 bool DirectShowComponent::isPlaying() const
904 return context->isRunning();
907 void DirectShowComponent::goToStart()
909 setPosition (0.0);
912 void DirectShowComponent::setPosition (const double seconds)
914 if (videoLoaded)
915 context->setPosition (seconds);
918 double DirectShowComponent::getPosition() const
920 return videoLoaded ? context->getPosition() : 0.0;
923 void DirectShowComponent::setSpeed (const float newSpeed)
925 if (videoLoaded)
926 context->setSpeed (newSpeed);
929 void DirectShowComponent::setMovieVolume (const float newVolume)
931 if (videoLoaded)
932 context->setVolume (newVolume);
935 float DirectShowComponent::getMovieVolume() const
937 return videoLoaded ? context->getVolume() : 0.0f;
941 #endif