diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile index ff04a9469b..3ccc60f94c 100644 --- a/Builds/Linux/Makefile +++ b/Builds/Linux/Makefile @@ -318,6 +318,7 @@ OBJECTS := \ $(OBJDIR)/juce_win32_AudioCDReader_66c7252.o \ $(OBJDIR)/juce_win32_CameraDevice_ea35306d.o \ $(OBJDIR)/juce_win32_Direct2DGraphicsContext_9f1b6be1.o \ + $(OBJDIR)/juce_win32_DirectShowComponent_e4030c4f.o \ $(OBJDIR)/juce_win32_DirectSound_3462415e.o \ $(OBJDIR)/juce_win32_FileChooser_18a257.o \ $(OBJDIR)/juce_win32_Files_f3e9a2ef.o \ @@ -1782,6 +1783,11 @@ $(OBJDIR)/juce_win32_Direct2DGraphicsContext_9f1b6be1.o: ../../src/native/window @echo "Compiling juce_win32_Direct2DGraphicsContext.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/juce_win32_DirectShowComponent_e4030c4f.o: ../../src/native/windows/juce_win32_DirectShowComponent.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling juce_win32_DirectShowComponent.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/juce_win32_DirectSound_3462415e.o: ../../src/native/windows/juce_win32_DirectSound.cpp -@mkdir -p $(OBJDIR) @echo "Compiling juce_win32_DirectSound.cpp" diff --git a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj index ded6dda5a0..d030e10356 100644 --- a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj @@ -313,6 +313,7 @@ 9686F29C29D1C26E353DE68A = { isa = PBXBuildFile; fileRef = F3B50EE3939E9F16D13C3C7C; }; 79B4C2F1C0CF592ACE8093C0 = { isa = PBXBuildFile; fileRef = 3A37CD82212075940421CE4F; }; 88A87D28B3809665F28DC16E = { isa = PBXBuildFile; fileRef = 7F3EF672D07ECE3E13AAF267; }; + 6BDBEFD97E643E5BB27637FF = { isa = PBXBuildFile; fileRef = 249959E338D7750E56A9F2F8; }; BC3C22F5350ED7433D303A04 = { isa = PBXBuildFile; fileRef = 58B70C726D186B4E770300BC; }; 0B41EC4D7839F8CBCB8F9A0D = { isa = PBXBuildFile; fileRef = DCD09B6EF4A4A109DE01F152; }; B420CD4B589C08EAFA6E3DA4 = { isa = PBXBuildFile; fileRef = 7527A5E8F4F39581159D3E5B; }; @@ -785,6 +786,7 @@ C25DFA2F2B673EB0146412BB = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_BubbleMessageComponent.h; path = ../../src/gui/components/special/juce_BubbleMessageComponent.h; sourceTree = SOURCE_ROOT; }; 0A20E7E561633610A76A34AB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ColourSelector.cpp; path = ../../src/gui/components/special/juce_ColourSelector.cpp; sourceTree = SOURCE_ROOT; }; CD9F817B7EF0DA080668A3A8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ColourSelector.h; path = ../../src/gui/components/special/juce_ColourSelector.h; sourceTree = SOURCE_ROOT; }; + 4BF7A01BCE61A5068CA13D8F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_DirectShowComponent.h; path = ../../src/gui/components/special/juce_DirectShowComponent.h; sourceTree = SOURCE_ROOT; }; 9C1D5CDA61FB51F657DA8B22 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_DropShadower.cpp; path = ../../src/gui/components/special/juce_DropShadower.cpp; sourceTree = SOURCE_ROOT; }; 7DB8CFB77EA690ACF54C63B4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_DropShadower.h; path = ../../src/gui/components/special/juce_DropShadower.h; sourceTree = SOURCE_ROOT; }; 3C8C1AAF32DFECB89EB83271 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_MidiKeyboardComponent.cpp; path = ../../src/gui/components/special/juce_MidiKeyboardComponent.cpp; sourceTree = SOURCE_ROOT; }; @@ -1015,6 +1017,7 @@ 9C4D1018ECC0BA07346453EF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_win32_AutoLinkLibraries.h; path = ../../src/native/windows/juce_win32_AutoLinkLibraries.h; sourceTree = SOURCE_ROOT; }; 3A37CD82212075940421CE4F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_win32_CameraDevice.cpp; path = ../../src/native/windows/juce_win32_CameraDevice.cpp; sourceTree = SOURCE_ROOT; }; 7F3EF672D07ECE3E13AAF267 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_win32_Direct2DGraphicsContext.cpp; path = ../../src/native/windows/juce_win32_Direct2DGraphicsContext.cpp; sourceTree = SOURCE_ROOT; }; + 249959E338D7750E56A9F2F8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_win32_DirectShowComponent.cpp; path = ../../src/native/windows/juce_win32_DirectShowComponent.cpp; sourceTree = SOURCE_ROOT; }; 58B70C726D186B4E770300BC = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_win32_DirectSound.cpp; path = ../../src/native/windows/juce_win32_DirectSound.cpp; sourceTree = SOURCE_ROOT; }; BA66E265749F75DBA86EC3F1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_win32_DynamicLibraryLoader.h; path = ../../src/native/windows/juce_win32_DynamicLibraryLoader.h; sourceTree = SOURCE_ROOT; }; DCD09B6EF4A4A109DE01F152 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_win32_FileChooser.cpp; path = ../../src/native/windows/juce_win32_FileChooser.cpp; sourceTree = SOURCE_ROOT; }; @@ -1565,6 +1568,7 @@ C25DFA2F2B673EB0146412BB, 0A20E7E561633610A76A34AB, CD9F817B7EF0DA080668A3A8, + 4BF7A01BCE61A5068CA13D8F, 9C1D5CDA61FB51F657DA8B22, 7DB8CFB77EA690ACF54C63B4, 3C8C1AAF32DFECB89EB83271, @@ -1851,6 +1855,7 @@ 9C4D1018ECC0BA07346453EF, 3A37CD82212075940421CE4F, 7F3EF672D07ECE3E13AAF267, + 249959E338D7750E56A9F2F8, 58B70C726D186B4E770300BC, BA66E265749F75DBA86EC3F1, DCD09B6EF4A4A109DE01F152, @@ -2361,6 +2366,7 @@ 9686F29C29D1C26E353DE68A, 79B4C2F1C0CF592ACE8093C0, 88A87D28B3809665F28DC16E, + 6BDBEFD97E643E5BB27637FF, BC3C22F5350ED7433D303A04, 0B41EC4D7839F8CBCB8F9A0D, B420CD4B589C08EAFA6E3DA4, diff --git a/Builds/VisualStudio2005/Juce.vcproj b/Builds/VisualStudio2005/Juce.vcproj index e1e0c0e6cc..a37a9211f1 100644 --- a/Builds/VisualStudio2005/Juce.vcproj +++ b/Builds/VisualStudio2005/Juce.vcproj @@ -646,6 +646,7 @@ + @@ -919,6 +920,7 @@ + diff --git a/Builds/VisualStudio2008/Juce.vcproj b/Builds/VisualStudio2008/Juce.vcproj index cd0c98a40b..f789ed2030 100644 --- a/Builds/VisualStudio2008/Juce.vcproj +++ b/Builds/VisualStudio2008/Juce.vcproj @@ -646,6 +646,7 @@ + @@ -919,6 +920,7 @@ + diff --git a/Builds/VisualStudio2008_DLL/Juce.vcproj b/Builds/VisualStudio2008_DLL/Juce.vcproj index eb8810c17b..071c104db2 100644 --- a/Builds/VisualStudio2008_DLL/Juce.vcproj +++ b/Builds/VisualStudio2008_DLL/Juce.vcproj @@ -648,6 +648,7 @@ + @@ -921,6 +922,7 @@ + diff --git a/Builds/VisualStudio2010/Juce.vcxproj b/Builds/VisualStudio2010/Juce.vcxproj index 0a97ed77a1..68d92ebf05 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj +++ b/Builds/VisualStudio2010/Juce.vcxproj @@ -401,6 +401,7 @@ + @@ -683,6 +684,7 @@ + diff --git a/Builds/VisualStudio2010/Juce.vcxproj.filters b/Builds/VisualStudio2010/Juce.vcxproj.filters index 14a733545d..a46857739c 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj.filters +++ b/Builds/VisualStudio2010/Juce.vcxproj.filters @@ -1138,6 +1138,9 @@ Juce\Source\native\windows + + Juce\Source\native\windows + Juce\Source\native\windows @@ -1980,6 +1983,9 @@ Juce\Source\gui\components\special + + Juce\Source\gui\components\special + Juce\Source\gui\components\special diff --git a/Builds/iOS/Juce.xcodeproj/project.pbxproj b/Builds/iOS/Juce.xcodeproj/project.pbxproj index 964e6feeba..9a9a9b0825 100644 --- a/Builds/iOS/Juce.xcodeproj/project.pbxproj +++ b/Builds/iOS/Juce.xcodeproj/project.pbxproj @@ -313,6 +313,7 @@ 9686F29C29D1C26E353DE68A = { isa = PBXBuildFile; fileRef = F3B50EE3939E9F16D13C3C7C; }; 79B4C2F1C0CF592ACE8093C0 = { isa = PBXBuildFile; fileRef = 3A37CD82212075940421CE4F; }; 88A87D28B3809665F28DC16E = { isa = PBXBuildFile; fileRef = 7F3EF672D07ECE3E13AAF267; }; + 6BDBEFD97E643E5BB27637FF = { isa = PBXBuildFile; fileRef = 249959E338D7750E56A9F2F8; }; BC3C22F5350ED7433D303A04 = { isa = PBXBuildFile; fileRef = 58B70C726D186B4E770300BC; }; 0B41EC4D7839F8CBCB8F9A0D = { isa = PBXBuildFile; fileRef = DCD09B6EF4A4A109DE01F152; }; B420CD4B589C08EAFA6E3DA4 = { isa = PBXBuildFile; fileRef = 7527A5E8F4F39581159D3E5B; }; @@ -785,6 +786,7 @@ C25DFA2F2B673EB0146412BB = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_BubbleMessageComponent.h; path = ../../src/gui/components/special/juce_BubbleMessageComponent.h; sourceTree = SOURCE_ROOT; }; 0A20E7E561633610A76A34AB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ColourSelector.cpp; path = ../../src/gui/components/special/juce_ColourSelector.cpp; sourceTree = SOURCE_ROOT; }; CD9F817B7EF0DA080668A3A8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ColourSelector.h; path = ../../src/gui/components/special/juce_ColourSelector.h; sourceTree = SOURCE_ROOT; }; + 4BF7A01BCE61A5068CA13D8F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_DirectShowComponent.h; path = ../../src/gui/components/special/juce_DirectShowComponent.h; sourceTree = SOURCE_ROOT; }; 9C1D5CDA61FB51F657DA8B22 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_DropShadower.cpp; path = ../../src/gui/components/special/juce_DropShadower.cpp; sourceTree = SOURCE_ROOT; }; 7DB8CFB77EA690ACF54C63B4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_DropShadower.h; path = ../../src/gui/components/special/juce_DropShadower.h; sourceTree = SOURCE_ROOT; }; 3C8C1AAF32DFECB89EB83271 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_MidiKeyboardComponent.cpp; path = ../../src/gui/components/special/juce_MidiKeyboardComponent.cpp; sourceTree = SOURCE_ROOT; }; @@ -1015,6 +1017,7 @@ 9C4D1018ECC0BA07346453EF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_win32_AutoLinkLibraries.h; path = ../../src/native/windows/juce_win32_AutoLinkLibraries.h; sourceTree = SOURCE_ROOT; }; 3A37CD82212075940421CE4F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_win32_CameraDevice.cpp; path = ../../src/native/windows/juce_win32_CameraDevice.cpp; sourceTree = SOURCE_ROOT; }; 7F3EF672D07ECE3E13AAF267 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_win32_Direct2DGraphicsContext.cpp; path = ../../src/native/windows/juce_win32_Direct2DGraphicsContext.cpp; sourceTree = SOURCE_ROOT; }; + 249959E338D7750E56A9F2F8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_win32_DirectShowComponent.cpp; path = ../../src/native/windows/juce_win32_DirectShowComponent.cpp; sourceTree = SOURCE_ROOT; }; 58B70C726D186B4E770300BC = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_win32_DirectSound.cpp; path = ../../src/native/windows/juce_win32_DirectSound.cpp; sourceTree = SOURCE_ROOT; }; BA66E265749F75DBA86EC3F1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_win32_DynamicLibraryLoader.h; path = ../../src/native/windows/juce_win32_DynamicLibraryLoader.h; sourceTree = SOURCE_ROOT; }; DCD09B6EF4A4A109DE01F152 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_win32_FileChooser.cpp; path = ../../src/native/windows/juce_win32_FileChooser.cpp; sourceTree = SOURCE_ROOT; }; @@ -1565,6 +1568,7 @@ C25DFA2F2B673EB0146412BB, 0A20E7E561633610A76A34AB, CD9F817B7EF0DA080668A3A8, + 4BF7A01BCE61A5068CA13D8F, 9C1D5CDA61FB51F657DA8B22, 7DB8CFB77EA690ACF54C63B4, 3C8C1AAF32DFECB89EB83271, @@ -1851,6 +1855,7 @@ 9C4D1018ECC0BA07346453EF, 3A37CD82212075940421CE4F, 7F3EF672D07ECE3E13AAF267, + 249959E338D7750E56A9F2F8, 58B70C726D186B4E770300BC, BA66E265749F75DBA86EC3F1, DCD09B6EF4A4A109DE01F152, @@ -2365,6 +2370,7 @@ 9686F29C29D1C26E353DE68A, 79B4C2F1C0CF592ACE8093C0, 88A87D28B3809665F28DC16E, + 6BDBEFD97E643E5BB27637FF, BC3C22F5350ED7433D303A04, 0B41EC4D7839F8CBCB8F9A0D, B420CD4B589C08EAFA6E3DA4, diff --git a/Juce.jucer b/Juce.jucer index ca75a7d61b..ad3bcfb40c 100644 --- a/Juce.jucer +++ b/Juce.jucer @@ -926,6 +926,8 @@ file="src/gui/components/special/juce_ColourSelector.cpp"/> + + + JUCE_DIRECT2D="default" JUCE_MEDIAFOUNDATION="default" JUCE_DIRECTSHOW="default"/> diff --git a/extras/Introjucer/Introjucer.jucer b/extras/Introjucer/Introjucer.jucer index 7cb449f08d..41178e556d 100644 --- a/extras/Introjucer/Introjucer.jucer +++ b/extras/Introjucer/Introjucer.jucer @@ -186,5 +186,6 @@ JUCE_USE_XINERAMA="default" JUCE_USE_XSHM="default" JUCE_ONLY_BUILD_CORE_LIBRARY="default" JUCE_WEB_BROWSER="default" JUCE_SUPPORT_CARBON="default" JUCE_CHECK_MEMORY_LEAKS="default" JUCE_CATCH_UNHANDLED_EXCEPTIONS="default" JUCE_STRINGS_ARE_UNICODE="default" - JUCE_USE_XRENDER="default" JUCE_USE_XCURSOR="default" JUCE_DIRECT2D="default"/> + JUCE_USE_XRENDER="default" JUCE_USE_XCURSOR="default" JUCE_DIRECT2D="default" + JUCE_DIRECTSHOW="default" JUCE_MEDIAFOUNDATION="default"/> diff --git a/extras/Introjucer/JuceLibraryCode/AppConfig.h b/extras/Introjucer/JuceLibraryCode/AppConfig.h index 0dc80c4954..e66cbe123d 100644 --- a/extras/Introjucer/JuceLibraryCode/AppConfig.h +++ b/extras/Introjucer/JuceLibraryCode/AppConfig.h @@ -16,6 +16,8 @@ #define JUCE_ASIO 0 #define JUCE_WASAPI 0 #define JUCE_DIRECTSOUND 0 +//#define JUCE_DIRECTSHOW +//#define JUCE_MEDIAFOUNDATION #define JUCE_ALSA 0 #define JUCE_QUICKTIME 0 #define JUCE_OPENGL 0 diff --git a/extras/JuceDemo/Builds/Android/jni/Android.mk b/extras/JuceDemo/Builds/Android/jni/Android.mk index bda2d33078..930c7f3c30 100644 --- a/extras/JuceDemo/Builds/Android/jni/Android.mk +++ b/extras/JuceDemo/Builds/Android/jni/Android.mk @@ -18,6 +18,7 @@ LOCAL_SRC_FILES := \ ../../../Source/demos/AudioDemoTabComponent.cpp\ ../../../Source/demos/CameraDemo.cpp\ ../../../Source/demos/CodeEditorDemo.cpp\ + ../../../Source/demos/DirectShowDemo.cpp\ ../../../Source/demos/DragAndDropDemo.cpp\ ../../../Source/demos/FontsAndTextDemo.cpp\ ../../../Source/demos/InterprocessCommsDemo.cpp\ diff --git a/extras/JuceDemo/Builds/Linux/Makefile b/extras/JuceDemo/Builds/Linux/Makefile index 67658c58c4..31decfca9c 100644 --- a/extras/JuceDemo/Builds/Linux/Makefile +++ b/extras/JuceDemo/Builds/Linux/Makefile @@ -53,6 +53,7 @@ OBJECTS := \ $(OBJDIR)/AudioDemoTabComponent_81185e3.o \ $(OBJDIR)/CameraDemo_954a4a30.o \ $(OBJDIR)/CodeEditorDemo_55f35645.o \ + $(OBJDIR)/DirectShowDemo_2e0bc311.o \ $(OBJDIR)/DragAndDropDemo_f8c9e5d7.o \ $(OBJDIR)/FontsAndTextDemo_2cefcecb.o \ $(OBJDIR)/InterprocessCommsDemo_aa1c1119.o \ @@ -135,6 +136,11 @@ $(OBJDIR)/CodeEditorDemo_55f35645.o: ../../Source/demos/CodeEditorDemo.cpp @echo "Compiling CodeEditorDemo.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/DirectShowDemo_2e0bc311.o: ../../Source/demos/DirectShowDemo.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling DirectShowDemo.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/DragAndDropDemo_f8c9e5d7.o: ../../Source/demos/DragAndDropDemo.cpp -@mkdir -p $(OBJDIR) @echo "Compiling DragAndDropDemo.cpp" diff --git a/extras/JuceDemo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj b/extras/JuceDemo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj index 5f835b6dd6..ef48b77bd6 100644 --- a/extras/JuceDemo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj +++ b/extras/JuceDemo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ 7EFB4E7D738BFFF90F49E0C0 = { isa = PBXBuildFile; fileRef = 048CEE4CC06227D8A57E47F2; }; B69F5957B1729915BFB18735 = { isa = PBXBuildFile; fileRef = 7D65727C8F72F2BCC9A17D34; }; F920A5AB6D0FF01022575079 = { isa = PBXBuildFile; fileRef = 268D7AFE2F3822C2C8E9A612; }; + 940BE0338CC1FEB65B4B82E2 = { isa = PBXBuildFile; fileRef = E072353A8A1F26CFB7090905; }; A3AF0F559DD97F1B908AC1CA = { isa = PBXBuildFile; fileRef = F23738E4EFD2323063F82F1C; }; 2C0AB902CB01E38D87A2A6A5 = { isa = PBXBuildFile; fileRef = B7F4DAFA5F8F1FC976C8B55D; }; ACD2210FDE1137548F995F85 = { isa = PBXBuildFile; fileRef = F7620D8D567CCE463ADDE0A6; }; @@ -76,6 +77,7 @@ 8BEA0B754661F3038DBAF558 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioDemoTabComponent.h; path = ../../Source/demos/AudioDemoTabComponent.h; sourceTree = SOURCE_ROOT; }; 7D65727C8F72F2BCC9A17D34 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CameraDemo.cpp; path = ../../Source/demos/CameraDemo.cpp; sourceTree = SOURCE_ROOT; }; 268D7AFE2F3822C2C8E9A612 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CodeEditorDemo.cpp; path = ../../Source/demos/CodeEditorDemo.cpp; sourceTree = SOURCE_ROOT; }; + E072353A8A1F26CFB7090905 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DirectShowDemo.cpp; path = ../../Source/demos/DirectShowDemo.cpp; sourceTree = SOURCE_ROOT; }; F23738E4EFD2323063F82F1C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DragAndDropDemo.cpp; path = ../../Source/demos/DragAndDropDemo.cpp; sourceTree = SOURCE_ROOT; }; B7F4DAFA5F8F1FC976C8B55D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FontsAndTextDemo.cpp; path = ../../Source/demos/FontsAndTextDemo.cpp; sourceTree = SOURCE_ROOT; }; F7620D8D567CCE463ADDE0A6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InterprocessCommsDemo.cpp; path = ../../Source/demos/InterprocessCommsDemo.cpp; sourceTree = SOURCE_ROOT; }; @@ -117,6 +119,7 @@ 8BEA0B754661F3038DBAF558, 7D65727C8F72F2BCC9A17D34, 268D7AFE2F3822C2C8E9A612, + E072353A8A1F26CFB7090905, F23738E4EFD2323063F82F1C, B7F4DAFA5F8F1FC976C8B55D, F7620D8D567CCE463ADDE0A6, @@ -258,6 +261,7 @@ 7EFB4E7D738BFFF90F49E0C0, B69F5957B1729915BFB18735, F920A5AB6D0FF01022575079, + 940BE0338CC1FEB65B4B82E2, A3AF0F559DD97F1B908AC1CA, 2C0AB902CB01E38D87A2A6A5, ACD2210FDE1137548F995F85, diff --git a/extras/JuceDemo/Builds/VisualStudio2005/Juce Demo.vcproj b/extras/JuceDemo/Builds/VisualStudio2005/Juce Demo.vcproj index 559037762e..e0a519bb3c 100644 --- a/extras/JuceDemo/Builds/VisualStudio2005/Juce Demo.vcproj +++ b/extras/JuceDemo/Builds/VisualStudio2005/Juce Demo.vcproj @@ -148,6 +148,7 @@ + diff --git a/extras/JuceDemo/Builds/VisualStudio2008/Juce Demo.vcproj b/extras/JuceDemo/Builds/VisualStudio2008/Juce Demo.vcproj index 4a0a7a49e9..63dd1025ff 100644 --- a/extras/JuceDemo/Builds/VisualStudio2008/Juce Demo.vcproj +++ b/extras/JuceDemo/Builds/VisualStudio2008/Juce Demo.vcproj @@ -148,6 +148,7 @@ + diff --git a/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj b/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj index 7835779251..fd1ba5c5c4 100644 --- a/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj +++ b/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj @@ -132,6 +132,7 @@ + diff --git a/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters b/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters index 17106637a0..2eb22b293e 100644 --- a/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters +++ b/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters @@ -49,6 +49,9 @@ Juce Demo\Source\Demos + + Juce Demo\Source\Demos + Juce Demo\Source\Demos diff --git a/extras/JuceDemo/Builds/iOS/Juce Demo.xcodeproj/project.pbxproj b/extras/JuceDemo/Builds/iOS/Juce Demo.xcodeproj/project.pbxproj index 384ecb815e..006fddff51 100644 --- a/extras/JuceDemo/Builds/iOS/Juce Demo.xcodeproj/project.pbxproj +++ b/extras/JuceDemo/Builds/iOS/Juce Demo.xcodeproj/project.pbxproj @@ -24,6 +24,7 @@ 7EFB4E7D738BFFF90F49E0C0 = { isa = PBXBuildFile; fileRef = 048CEE4CC06227D8A57E47F2; }; B69F5957B1729915BFB18735 = { isa = PBXBuildFile; fileRef = 7D65727C8F72F2BCC9A17D34; }; F920A5AB6D0FF01022575079 = { isa = PBXBuildFile; fileRef = 268D7AFE2F3822C2C8E9A612; }; + 940BE0338CC1FEB65B4B82E2 = { isa = PBXBuildFile; fileRef = E072353A8A1F26CFB7090905; }; A3AF0F559DD97F1B908AC1CA = { isa = PBXBuildFile; fileRef = F23738E4EFD2323063F82F1C; }; 2C0AB902CB01E38D87A2A6A5 = { isa = PBXBuildFile; fileRef = B7F4DAFA5F8F1FC976C8B55D; }; ACD2210FDE1137548F995F85 = { isa = PBXBuildFile; fileRef = F7620D8D567CCE463ADDE0A6; }; @@ -68,6 +69,7 @@ 8BEA0B754661F3038DBAF558 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioDemoTabComponent.h; path = ../../Source/demos/AudioDemoTabComponent.h; sourceTree = SOURCE_ROOT; }; 7D65727C8F72F2BCC9A17D34 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CameraDemo.cpp; path = ../../Source/demos/CameraDemo.cpp; sourceTree = SOURCE_ROOT; }; 268D7AFE2F3822C2C8E9A612 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CodeEditorDemo.cpp; path = ../../Source/demos/CodeEditorDemo.cpp; sourceTree = SOURCE_ROOT; }; + E072353A8A1F26CFB7090905 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DirectShowDemo.cpp; path = ../../Source/demos/DirectShowDemo.cpp; sourceTree = SOURCE_ROOT; }; F23738E4EFD2323063F82F1C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DragAndDropDemo.cpp; path = ../../Source/demos/DragAndDropDemo.cpp; sourceTree = SOURCE_ROOT; }; B7F4DAFA5F8F1FC976C8B55D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FontsAndTextDemo.cpp; path = ../../Source/demos/FontsAndTextDemo.cpp; sourceTree = SOURCE_ROOT; }; F7620D8D567CCE463ADDE0A6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InterprocessCommsDemo.cpp; path = ../../Source/demos/InterprocessCommsDemo.cpp; sourceTree = SOURCE_ROOT; }; @@ -109,6 +111,7 @@ 8BEA0B754661F3038DBAF558, 7D65727C8F72F2BCC9A17D34, 268D7AFE2F3822C2C8E9A612, + E072353A8A1F26CFB7090905, F23738E4EFD2323063F82F1C, B7F4DAFA5F8F1FC976C8B55D, F7620D8D567CCE463ADDE0A6, @@ -249,6 +252,7 @@ 7EFB4E7D738BFFF90F49E0C0, B69F5957B1729915BFB18735, F920A5AB6D0FF01022575079, + 940BE0338CC1FEB65B4B82E2, A3AF0F559DD97F1B908AC1CA, 2C0AB902CB01E38D87A2A6A5, ACD2210FDE1137548F995F85, diff --git a/extras/JuceDemo/Juce Demo.jucer b/extras/JuceDemo/Juce Demo.jucer index c05c6eae9d..08a6892b45 100644 --- a/extras/JuceDemo/Juce Demo.jucer +++ b/extras/JuceDemo/Juce Demo.jucer @@ -72,6 +72,8 @@ file="Source/demos/CameraDemo.cpp"/> + + JUCE_USE_XRENDER="default" JUCE_USE_XCURSOR="default" JUCE_DIRECT2D="default" + JUCE_MEDIAFOUNDATION="default" JUCE_DIRECTSHOW="default"/> diff --git a/extras/JuceDemo/JuceLibraryCode/AppConfig.h b/extras/JuceDemo/JuceLibraryCode/AppConfig.h index d878651b93..122c4df422 100644 --- a/extras/JuceDemo/JuceLibraryCode/AppConfig.h +++ b/extras/JuceDemo/JuceLibraryCode/AppConfig.h @@ -16,6 +16,8 @@ //#define JUCE_ASIO //#define JUCE_WASAPI //#define JUCE_DIRECTSOUND +//#define JUCE_DIRECTSHOW +//#define JUCE_MEDIAFOUNDATION //#define JUCE_ALSA //#define JUCE_QUICKTIME //#define JUCE_OPENGL diff --git a/extras/JuceDemo/Source/MainDemoWindow.cpp b/extras/JuceDemo/Source/MainDemoWindow.cpp index 9207b01364..a2bad8e515 100644 --- a/extras/JuceDemo/Source/MainDemoWindow.cpp +++ b/extras/JuceDemo/Source/MainDemoWindow.cpp @@ -86,6 +86,7 @@ public: menu.addCommandItem (commandManager, showDragAndDrop); menu.addCommandItem (commandManager, showOpenGL); menu.addCommandItem (commandManager, showQuicktime); + menu.addCommandItem (commandManager, showDirectShow); menu.addCommandItem (commandManager, showInterprocessComms); menu.addCommandItem (commandManager, showCamera); menu.addCommandItem (commandManager, showWebBrowser); @@ -157,6 +158,7 @@ public: showDragAndDrop, showOpenGL, showQuicktime, + showDirectShow, showCamera, showWebBrowser, showCodeEditor, @@ -251,6 +253,15 @@ public: #endif break; + case showDirectShow: + result.setInfo ("DirectShow", "Shows the DirectShow demo", demosCategory, 0); + result.addDefaultKeypress ('b', ModifierKeys::commandModifier); + result.setTicked (currentDemoId == showDirectShow); +#if ! JUCE_DIRECTSHOW + result.setActive (false); +#endif + break; + case showCamera: result.setInfo ("Camera Capture", "Shows the camera demo", demosCategory, 0); result.addDefaultKeypress ('c', ModifierKeys::commandModifier); @@ -374,6 +385,13 @@ public: #endif break; + case showDirectShow: +#if JUCE_DIRECTSHOW + showDemo (createDirectShowDemo()); + currentDemoId = showDirectShow; +#endif + break; + case showCamera: #if JUCE_USE_CAMERA showDemo (createCameraDemo()); @@ -474,6 +492,7 @@ private: showCamera = 0x2011, showWebBrowser = 0x2012, showCodeEditor = 0x2013, + showDirectShow = 0x2014, setDefaultLookAndFeel = 0x200b, setOldSchoolLookAndFeel = 0x200c, diff --git a/extras/JuceDemo/Source/demos/DirectShowDemo.cpp b/extras/JuceDemo/Source/demos/DirectShowDemo.cpp new file mode 100644 index 0000000000..a7de04f553 --- /dev/null +++ b/extras/JuceDemo/Source/demos/DirectShowDemo.cpp @@ -0,0 +1,155 @@ + +#include "../jucedemo_headers.h" + +#if JUCE_DIRECTSHOW + +//============================================================================== +class DirectShowWindowWithFileBrowser : public Component, + public FilenameComponentListener +{ +public: + DirectShowWindowWithFileBrowser (DirectShowComponent::VideoRendererType type) + : fileChooser ("movie", File::nonexistent, true, false, false, + "*", String::empty, "(choose a video file to play)"), + dshowComp (type) + { + addAndMakeVisible (&dshowComp); + addAndMakeVisible (&fileChooser); + fileChooser.addListener (this); + fileChooser.setBrowseButtonText ("browse"); + } + + void resized() + { + dshowComp.setBounds (0, 0, getWidth(), getHeight() - 60); + + if (transportControl != 0) + transportControl->setBounds (0, dshowComp.getBottom() + 4, getWidth(), 26); + + fileChooser.setBounds (0, getHeight() - 24, getWidth(), 24); + } + + void filenameComponentChanged (FilenameComponent*) + { + // this is called when the user changes the filename in the file chooser box + if (dshowComp.loadMovie (fileChooser.getCurrentFile())) + { + addAndMakeVisible (transportControl = new TransportControl (dshowComp)); + resized(); + + dshowComp.play(); + } + else + { + AlertWindow::showMessageBox (AlertWindow::WarningIcon, + "Couldn't load the file!", + "Sorry, DirectShow didn't manage to load that file!"); + } + } + +private: + DirectShowComponent dshowComp; + FilenameComponent fileChooser; + + //============================================================================== + // A quick-and-dirty transport control, containing a play button and a position slider.. + class TransportControl : public Component, + public ButtonListener, + public SliderListener, + public Timer + { + public: + TransportControl (DirectShowComponent& dshowComp_) + : playButton ("Play/Pause"), + position (String::empty), + dshowComp (dshowComp_) + { + addAndMakeVisible (&playButton); + playButton.addListener (this); + + addAndMakeVisible (&position); + position.setRange (0, dshowComp.getMovieDuration(), 0); + position.setSliderStyle (Slider::LinearHorizontal); + position.setTextBoxStyle (Slider::NoTextBox, false, 80, 20); + position.addListener (this); + + startTimer (1000 / 50); + } + + void buttonClicked (Button* buttonThatWasClicked) + { + if (dshowComp.isPlaying()) + dshowComp.stop(); + else + dshowComp.play(); + } + + void sliderValueChanged (Slider* sliderThatWasMoved) + { + dshowComp.setPosition (position.getValue()); + } + + void resized() + { + const int playButtonWidth = 90; + playButton.setBounds (0, 0, playButtonWidth, getHeight()); + position.setBounds (playButtonWidth, 0, getWidth() - playButtonWidth, getHeight()); + } + + void timerCallback() + { + if (! position.isMouseButtonDown()) + position.setValue (dshowComp.getPosition(), false); + } + + private: + TextButton playButton; + Slider position; + DirectShowComponent& dshowComp; + }; + + ScopedPointer transportControl; +}; + + +//============================================================================== +class DirectShowDemo : public Component +{ +public: + //============================================================================== + DirectShowDemo() + : dsComp1 (DirectShowComponent::dshowVMR7), + dsComp2 (DirectShowComponent::dshowEVR) + { + setName ("DirectShow"); + + // add a movie component.. + addAndMakeVisible (&dsComp1); + addAndMakeVisible (&dsComp2); + } + + ~DirectShowDemo() + { + dsComp1.setVisible (false); + dsComp2.setVisible (false); + } + + void resized() + { + dsComp1.setBoundsRelative (0.05f, 0.05f, 0.425f, 0.9f); + dsComp2.setBoundsRelative (0.525f, 0.05f, 0.425f, 0.9f); + } + +private: + //============================================================================== + DirectShowWindowWithFileBrowser dsComp1, dsComp2; +}; + + +//============================================================================== +Component* createDirectShowDemo() +{ + return new DirectShowDemo(); +} + +#endif diff --git a/extras/JuceDemo/Source/jucedemo_headers.h b/extras/JuceDemo/Source/jucedemo_headers.h index 36a5e27c73..cafaf8dbf2 100644 --- a/extras/JuceDemo/Source/jucedemo_headers.h +++ b/extras/JuceDemo/Source/jucedemo_headers.h @@ -61,5 +61,8 @@ Component* createCodeEditorDemo(); Component* createCameraDemo(); #endif +#if JUCE_DIRECTSHOW + Component* createDirectShowDemo(); +#endif #endif // __JUCEDEMO_HEADERS_JUCEHEADER__ diff --git a/extras/amalgamator/Amalgamator.jucer b/extras/amalgamator/Amalgamator.jucer index fb070464db..44037ce364 100644 --- a/extras/amalgamator/Amalgamator.jucer +++ b/extras/amalgamator/Amalgamator.jucer @@ -37,5 +37,6 @@ JUCE_PLUGINHOST_AU="default" JUCE_ONLY_BUILD_CORE_LIBRARY="enabled" JUCE_WEB_BROWSER="default" JUCE_SUPPORT_CARBON="default" JUCE_CHECK_MEMORY_LEAKS="default" JUCE_CATCH_UNHANDLED_EXCEPTIONS="default" JUCE_STRINGS_ARE_UNICODE="default" - JUCE_USE_XRENDER="default" JUCE_USE_XCURSOR="default" JUCE_DIRECT2D="default"/> + JUCE_USE_XRENDER="default" JUCE_USE_XCURSOR="default" JUCE_DIRECT2D="default" + JUCE_DIRECTSHOW="default" JUCE_MEDIAFOUNDATION="default"/> diff --git a/extras/amalgamator/JuceLibraryCode/AppConfig.h b/extras/amalgamator/JuceLibraryCode/AppConfig.h index 654892fe15..139a284556 100644 --- a/extras/amalgamator/JuceLibraryCode/AppConfig.h +++ b/extras/amalgamator/JuceLibraryCode/AppConfig.h @@ -16,6 +16,8 @@ //#define JUCE_ASIO //#define JUCE_WASAPI //#define JUCE_DIRECTSOUND +//#define JUCE_DIRECTSHOW +//#define JUCE_MEDIAFOUNDATION //#define JUCE_ALSA //#define JUCE_QUICKTIME //#define JUCE_OPENGL diff --git a/extras/audio plugin host/JuceLibraryCode/AppConfig.h b/extras/audio plugin host/JuceLibraryCode/AppConfig.h index 13a0dc7f9e..3fc04623c6 100644 --- a/extras/audio plugin host/JuceLibraryCode/AppConfig.h +++ b/extras/audio plugin host/JuceLibraryCode/AppConfig.h @@ -16,6 +16,8 @@ //#define JUCE_ASIO #define JUCE_WASAPI 1 #define JUCE_DIRECTSOUND 1 +//#define JUCE_DIRECTSHOW +//#define JUCE_MEDIAFOUNDATION #define JUCE_ALSA 1 //#define JUCE_QUICKTIME //#define JUCE_OPENGL diff --git a/extras/audio plugin host/Plugin Host.jucer b/extras/audio plugin host/Plugin Host.jucer index 973841362d..609c598f9d 100644 --- a/extras/audio plugin host/Plugin Host.jucer +++ b/extras/audio plugin host/Plugin Host.jucer @@ -57,5 +57,6 @@ JUCE_PLUGINHOST_AU="enabled" JUCE_ONLY_BUILD_CORE_LIBRARY="default" JUCE_WEB_BROWSER="default" JUCE_SUPPORT_CARBON="default" JUCE_CHECK_MEMORY_LEAKS="default" JUCE_CATCH_UNHANDLED_EXCEPTIONS="default" JUCE_STRINGS_ARE_UNICODE="default" - JUCE_USE_XRENDER="default" JUCE_USE_XCURSOR="default" JUCE_DIRECT2D="default"/> + JUCE_USE_XRENDER="default" JUCE_USE_XCURSOR="default" JUCE_DIRECT2D="default" + JUCE_DIRECTSHOW="default" JUCE_MEDIAFOUNDATION="default"/> diff --git a/extras/audio plugins/demo/JuceDemoPlugin.jucer b/extras/audio plugins/demo/JuceDemoPlugin.jucer index 7c5823b250..d22020447c 100644 --- a/extras/audio plugins/demo/JuceDemoPlugin.jucer +++ b/extras/audio plugins/demo/JuceDemoPlugin.jucer @@ -45,5 +45,5 @@ JUCE_PLUGINHOST_VST="default" JUCE_PLUGINHOST_AU="default" JUCE_ONLY_BUILD_CORE_LIBRARY="default" JUCE_WEB_BROWSER="default" JUCE_SUPPORT_CARBON="default" JUCE_CHECK_MEMORY_LEAKS="default" JUCE_CATCH_UNHANDLED_EXCEPTIONS="default" JUCE_USE_XCURSOR="default" - JUCE_DIRECT2D="default"/> + JUCE_DIRECT2D="default" JUCE_DIRECTSHOW="default" JUCE_MEDIAFOUNDATION="default"/> diff --git a/extras/audio plugins/demo/JuceLibraryCode/AppConfig.h b/extras/audio plugins/demo/JuceLibraryCode/AppConfig.h index e16565bdf8..6d8293c3d5 100644 --- a/extras/audio plugins/demo/JuceLibraryCode/AppConfig.h +++ b/extras/audio plugins/demo/JuceLibraryCode/AppConfig.h @@ -16,6 +16,8 @@ //#define JUCE_ASIO //#define JUCE_WASAPI //#define JUCE_DIRECTSOUND +//#define JUCE_DIRECTSHOW +//#define JUCE_MEDIAFOUNDATION //#define JUCE_ALSA #define JUCE_QUICKTIME 0 //#define JUCE_OPENGL diff --git a/extras/binarybuilder/BinaryBuilder.jucer b/extras/binarybuilder/BinaryBuilder.jucer index 772fd76846..b025dd7d80 100644 --- a/extras/binarybuilder/BinaryBuilder.jucer +++ b/extras/binarybuilder/BinaryBuilder.jucer @@ -38,5 +38,6 @@ JUCE_PLUGINHOST_AU="default" JUCE_ONLY_BUILD_CORE_LIBRARY="enabled" JUCE_WEB_BROWSER="default" JUCE_SUPPORT_CARBON="default" JUCE_CHECK_MEMORY_LEAKS="default" JUCE_CATCH_UNHANDLED_EXCEPTIONS="default" JUCE_STRINGS_ARE_UNICODE="default" - JUCE_USE_XRENDER="default" JUCE_USE_XCURSOR="default" JUCE_DIRECT2D="default"/> + JUCE_USE_XRENDER="default" JUCE_USE_XCURSOR="default" JUCE_DIRECT2D="default" + JUCE_DIRECTSHOW="default" JUCE_MEDIAFOUNDATION="default"/> diff --git a/extras/binarybuilder/JuceLibraryCode/AppConfig.h b/extras/binarybuilder/JuceLibraryCode/AppConfig.h index 654892fe15..139a284556 100644 --- a/extras/binarybuilder/JuceLibraryCode/AppConfig.h +++ b/extras/binarybuilder/JuceLibraryCode/AppConfig.h @@ -16,6 +16,8 @@ //#define JUCE_ASIO //#define JUCE_WASAPI //#define JUCE_DIRECTSOUND +//#define JUCE_DIRECTSHOW +//#define JUCE_MEDIAFOUNDATION //#define JUCE_ALSA //#define JUCE_QUICKTIME //#define JUCE_OPENGL diff --git a/extras/example projects/HelloWorld.jucer b/extras/example projects/HelloWorld.jucer index 5b78c3f465..ab81767438 100644 --- a/extras/example projects/HelloWorld.jucer +++ b/extras/example projects/HelloWorld.jucer @@ -45,5 +45,6 @@ JUCE_PLUGINHOST_AU="default" JUCE_ONLY_BUILD_CORE_LIBRARY="default" JUCE_WEB_BROWSER="default" JUCE_SUPPORT_CARBON="default" JUCE_CHECK_MEMORY_LEAKS="default" JUCE_CATCH_UNHANDLED_EXCEPTIONS="default" JUCE_STRINGS_ARE_UNICODE="default" - JUCE_USE_XRENDER="default" JUCE_USE_XCURSOR="default" JUCE_DIRECT2D="default"/> + JUCE_USE_XRENDER="default" JUCE_USE_XCURSOR="default" JUCE_DIRECT2D="default" + JUCE_DIRECTSHOW="default" JUCE_MEDIAFOUNDATION="default"/> diff --git a/extras/example projects/JuceLibraryCode/AppConfig.h b/extras/example projects/JuceLibraryCode/AppConfig.h index 23094fe3f3..8489a36b4d 100644 --- a/extras/example projects/JuceLibraryCode/AppConfig.h +++ b/extras/example projects/JuceLibraryCode/AppConfig.h @@ -16,6 +16,8 @@ //#define JUCE_ASIO //#define JUCE_WASAPI //#define JUCE_DIRECTSOUND +//#define JUCE_DIRECTSHOW +//#define JUCE_MEDIAFOUNDATION //#define JUCE_ALSA //#define JUCE_QUICKTIME //#define JUCE_OPENGL diff --git a/juce_Config.h b/juce_Config.h index eb96130714..2397a93b9d 100644 --- a/juce_Config.h +++ b/juce_Config.h @@ -86,6 +86,25 @@ #define JUCE_DIRECTSOUND 1 #endif +/** JUCE_DIRECTSHOW: Enables DirectShow media-streaming architecture + (MS Windows only). +*/ +#ifndef JUCE_DIRECTSHOW + #define JUCE_DIRECTSHOW 1 +#endif + +/** JUCE_MEDIAFOUNDATION: Enables Media Foundation multimedia platform + (Windows Vista and above). +*/ +#ifndef JUCE_MEDIAFOUNDATION + #define JUCE_MEDIAFOUNDATION 1 +#endif + +#if ! JUCE_WINDOWS + #undef JUCE_DIRECTSHOW + #undef JUCE_MEDIAFOUNDATION +#endif + /** JUCE_ALSA: Enables ALSA audio devices (Linux only). */ #ifndef JUCE_ALSA #define JUCE_ALSA 1 diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 00f6d02b4f..beb6cfc446 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -257,6 +257,25 @@ #define JUCE_DIRECTSOUND 1 #endif +/** JUCE_DIRECTSHOW: Enables DirectShow media-streaming architecture + (MS Windows only). +*/ +#ifndef JUCE_DIRECTSHOW + #define JUCE_DIRECTSHOW 1 +#endif + +/** JUCE_MEDIAFOUNDATION: Enables Media Foundation multimedia platform + (Windows Vista and above). +*/ +#ifndef JUCE_MEDIAFOUNDATION + #define JUCE_MEDIAFOUNDATION 1 +#endif + +#if ! JUCE_WINDOWS + #undef JUCE_DIRECTSHOW + #undef JUCE_MEDIAFOUNDATION +#endif + /** JUCE_ALSA: Enables ALSA audio devices (Linux only). */ #ifndef JUCE_ALSA #define JUCE_ALSA 1 @@ -645,6 +664,14 @@ #import #endif +#if JUCE_DIRECTSHOW && JUCE_BUILD_NATIVE + #include +#endif + +#if JUCE_MEDIAFOUNDATION && JUCE_BUILD_NATIVE + #include +#endif + #if JUCE_MSVC #pragma warning (pop) #endif @@ -78179,11 +78206,7 @@ void OpenGLComponent::updateContextPosition() const ScopedLock sl (contextLock); if (context != nullptr) - context->updateWindowPosition (getScreenX() - topComp->getScreenX(), - getScreenY() - topComp->getScreenY(), - getWidth(), - getHeight(), - topComp->getHeight()); + context->updateWindowPosition (topComp->getLocalArea (this, getLocalBounds())); } } } @@ -245592,7 +245615,7 @@ MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMo { jassert (mode == readOnly || mode == readWrite); - DWORD accessMode = GENERIC_READ, shareMode = FILE_SHARE_READ, createType = OPEN_EXISTING; + DWORD accessMode = GENERIC_READ, createType = OPEN_EXISTING; DWORD protect = PAGE_READONLY, access = FILE_MAP_READ; if (mode == readWrite) @@ -252841,6 +252864,897 @@ void QuickTimeMovieComponent::setBoundsWithCorrectAspectRatio (const Rectangle graph; + return SUCCEEDED (graph.CoCreateInstance (CLSID_FilterGraph)); + } + + class VideoRenderer + { + public: + VideoRenderer() {} + virtual ~VideoRenderer() {} + + virtual HRESULT create (ComSmartPtr & graphBuilder, + ComSmartPtr & baseFilter, HWND hwnd) = 0; + + virtual void setVideoWindow (HWND hwnd) = 0; + virtual void setVideoPosition (HWND hwnd, long videoWidth, long videoHeight) = 0; + virtual void repaintVideo (HWND hwnd, HDC hdc) = 0; + virtual void displayModeChanged() = 0; + virtual HRESULT getVideoSize (long& videoWidth, long& videoHeight) = 0; + }; + + class VMR7 : public VideoRenderer + { + public: + VMR7() {} + + HRESULT create (ComSmartPtr & graphBuilder, + ComSmartPtr & baseFilter, HWND hwnd) + { + ComSmartPtr filterConfig; + + HRESULT hr = baseFilter.CoCreateInstance (CLSID_VideoMixingRenderer); + + if (SUCCEEDED (hr)) + hr = graphBuilder->AddFilter (baseFilter, L"VMR-7"); + + if (SUCCEEDED (hr)) + hr = baseFilter.QueryInterface (IID_IVMRFilterConfig, filterConfig); + + if (SUCCEEDED (hr)) + hr = filterConfig->SetRenderingMode (VMRMode_Windowless); + + if (SUCCEEDED (hr)) + hr = baseFilter.QueryInterface (IID_IVMRWindowlessControl, windowlessControl); + + if (SUCCEEDED (hr)) + hr = windowlessControl->SetVideoClippingWindow (hwnd); + + if (SUCCEEDED (hr)) + hr = windowlessControl->SetAspectRatioMode (VMR_ARMODE_LETTER_BOX); + + return hr; + } + + void setVideoWindow (HWND hwnd) + { + windowlessControl->SetVideoClippingWindow (hwnd); + } + + void setVideoPosition (HWND hwnd, long videoWidth, long videoHeight) + { + RECT src, dest; + + SetRect (&src, 0, 0, videoWidth, videoHeight); + GetClientRect (hwnd, &dest); + + windowlessControl->SetVideoPosition (&src, &dest); + } + + void repaintVideo (HWND hwnd, HDC hdc) + { + windowlessControl->RepaintVideo (hwnd, hdc); + } + + void displayModeChanged() + { + windowlessControl->DisplayModeChanged(); + } + + HRESULT getVideoSize (long& videoWidth, long& videoHeight) + { + return windowlessControl->GetNativeVideoSize (&videoWidth, &videoHeight, nullptr, nullptr); + } + + private: + ComSmartPtr windowlessControl; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VMR7); + }; + +#if JUCE_MEDIAFOUNDATION + class EVR : public VideoRenderer + { + public: + EVR() {} + + HRESULT create (ComSmartPtr & graphBuilder, + ComSmartPtr & baseFilter, HWND hwnd) + { + ComSmartPtr getService; + + HRESULT hr = baseFilter.CoCreateInstance (CLSID_EnhancedVideoRenderer); + + if (SUCCEEDED (hr)) + hr = graphBuilder->AddFilter (baseFilter, L"EVR"); + + if (SUCCEEDED (hr)) + hr = baseFilter.QueryInterface (IID_IMFGetService, getService); + + if (SUCCEEDED (hr)) + hr = getService->GetService (MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl, + (LPVOID*) videoDisplayControl.resetAndGetPointerAddress()); + + if (SUCCEEDED (hr)) + hr = videoDisplayControl->SetVideoWindow (hwnd); + + if (SUCCEEDED (hr)) + hr = videoDisplayControl->SetAspectRatioMode (MFVideoARMode_PreservePicture); + + return hr; + } + + void setVideoWindow (HWND hwnd) + { + videoDisplayControl->SetVideoWindow (hwnd); + } + + void setVideoPosition (HWND hwnd, long /*videoWidth*/, long /*videoHeight*/) + { + const MFVideoNormalizedRect src = { 0.0f, 0.0f, 1.0f, 1.0f }; + + RECT dest; + GetClientRect (hwnd, &dest); + + videoDisplayControl->SetVideoPosition (&src, &dest); + } + + void repaintVideo (HWND /*hwnd*/, HDC /*hdc*/) + { + videoDisplayControl->RepaintVideo(); + } + + void displayModeChanged() {} + + HRESULT getVideoSize (long& videoWidth, long& videoHeight) + { + SIZE sz; + HRESULT hr = videoDisplayControl->GetNativeVideoSize (&sz, nullptr); + videoWidth = sz.cx; + videoHeight = sz.cy; + return hr; + } + + private: + ComSmartPtr videoDisplayControl; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EVR); + }; +#endif +} + +class DirectShowComponent::DirectShowContext +{ +public: + DirectShowContext (DirectShowComponent& component_, VideoRendererType type_) + : component (component_), + hwnd (0), + hdc (0), + state (uninitializedState), + hasVideo (false), + videoWidth (0), + videoHeight (0), + type (type_) + { + CoInitialize (0); + + if (type == dshowDefault) + { + type = dshowVMR7; + + #if JUCE_MEDIAFOUNDATION + if (SystemStats::getOperatingSystemType() >= SystemStats::WinVista) + type = dshowEVR; + #endif + } + } + + ~DirectShowContext() + { + release(); + CoUninitialize(); + } + + HWND getNativeWindowHandle() const + { + return nativeWindow != nullptr ? nativeWindow->getHandle() : 0; + } + + void updateWindowPosition (const Rectangle& newBounds) + { + nativeWindow->setWindowPosition (newBounds); + } + + void showWindow (bool shouldBeVisible) + { + nativeWindow->showWindow (shouldBeVisible); + } + + void repaint() + { + if (hasVideo) + videoRenderer->repaintVideo (nativeWindow->getHandle(), nativeWindow->getContext()); + } + + void updateVideoPosition() + { + if (hasVideo) + videoRenderer->setVideoPosition (nativeWindow->getHandle(), videoWidth, videoHeight); + } + + void displayResolutionChanged() + { + if (hasVideo) + videoRenderer->displayModeChanged(); + } + + void peerChanged() + { + deleteNativeWindow(); + + mediaEvent->SetNotifyWindow (0, 0, 0); + if (videoRenderer != nullptr) + videoRenderer->setVideoWindow (nullptr); + + createNativeWindow(); + + mediaEvent->SetNotifyWindow ((OAHWND) hwnd, graphEventID, 0); + if (videoRenderer != nullptr) + videoRenderer->setVideoWindow (hwnd); + } + + bool loadFile (const String& fileOrURLPath) + { + jassert (state == uninitializedState); + + if (! createNativeWindow()) + return false; + + HRESULT hr = graphBuilder.CoCreateInstance (CLSID_FilterGraph); + + // basic playback interfaces + if (SUCCEEDED (hr)) hr = graphBuilder.QueryInterface (IID_IMediaControl, mediaControl); + if (SUCCEEDED (hr)) hr = graphBuilder.QueryInterface (IID_IMediaPosition, mediaPosition); + if (SUCCEEDED (hr)) hr = graphBuilder.QueryInterface (IID_IMediaEventEx, mediaEvent); + if (SUCCEEDED (hr)) hr = graphBuilder.QueryInterface (IID_IBasicAudio, basicAudio); + + // video renderer interface + if (SUCCEEDED (hr)) + { + #if JUCE_MEDIAFOUNDATION + if (type == dshowEVR) + videoRenderer = new DirectShowHelpers::EVR(); + else + #endif + videoRenderer = new DirectShowHelpers::VMR7(); + + hr = videoRenderer->create (graphBuilder, baseFilter, hwnd); + } + + // build filter graph + if (SUCCEEDED (hr)) + hr = graphBuilder->RenderFile (fileOrURLPath.toWideCharPointer(), nullptr); + + // remove video renderer if not connected (no video) + if (SUCCEEDED (hr)) + { + if (isRendererConnected()) + { + hasVideo = true; + hr = videoRenderer->getVideoSize (videoWidth, videoHeight); + } + else + { + hasVideo = false; + graphBuilder->RemoveFilter (baseFilter); + videoRenderer = nullptr; + baseFilter = nullptr; + } + } + + // set window to receive events + if (SUCCEEDED (hr)) + hr = mediaEvent->SetNotifyWindow ((OAHWND) hwnd, graphEventID, 0); + + if (SUCCEEDED (hr)) + { + state = stoppedState; + return true; + } + + release(); + return false; + } + + void release() + { + if (mediaControl != nullptr) + mediaControl->Stop(); + + if (mediaEvent != nullptr) + mediaEvent->SetNotifyWindow (0, 0, 0); + + if (videoRenderer != nullptr) + videoRenderer->setVideoWindow (0); + + hasVideo = false; + videoRenderer = nullptr; + + baseFilter = nullptr; + basicAudio = nullptr; + mediaEvent = nullptr; + mediaPosition = nullptr; + mediaControl = nullptr; + graphBuilder = nullptr; + + state = uninitializedState; + + videoWidth = 0; + videoHeight = 0; + + if (nativeWindow != nullptr) + deleteNativeWindow(); + } + + void graphEventProc() + { + LONG ec; + LONG_PTR p1, p2; + + jassert (mediaEvent != nullptr); + + while (SUCCEEDED (mediaEvent->GetEvent (&ec, &p1, &p2, 0))) + { + switch (ec) + { + case EC_REPAINT: + component.repaint(); + break; + + case EC_COMPLETE: + if (component.isLooping()) + component.goToStart(); + else + component.stop(); + break; + + case EC_USERABORT: + case EC_ERRORABORT: + case EC_ERRORABORTEX: + component.closeMovie(); + break; + + default: + break; + } + + mediaEvent->FreeEventParams (ec, p1, p2); + } + } + + void run() + { + mediaControl->Run(); + state = runningState; + } + + void stop() + { + mediaControl->Stop(); + state = stoppedState; + } + + void pause() + { + mediaControl->Pause(); + state = pausedState; + } + + bool isInitialised() const noexcept { return state != uninitializedState; } + bool isRunning() const noexcept { return state == runningState; } + bool isPaused() const noexcept { return state == pausedState; } + bool isStopped() const noexcept { return state == stoppedState; } + bool containsVideo() const noexcept { return hasVideo; } + int getVideoWidth() const noexcept { return (int) videoWidth; } + int getVideoHeight() const noexcept { return (int) videoHeight; } + + double getDuration() const + { + REFTIME duration; + mediaPosition->get_Duration (&duration); + return duration; + } + + double getPosition() const + { + REFTIME seconds; + mediaPosition->get_CurrentPosition (&seconds); + return seconds; + } + + void setSpeed (const float newSpeed) { mediaPosition->put_Rate (newSpeed); } + void setPosition (const double seconds) { mediaPosition->put_CurrentPosition (seconds); } + void setVolume (const float newVolume) { basicAudio->put_Volume (convertToDShowVolume (newVolume)); } + + // in DirectShow, full volume is 0, silence is -10000 + static long convertToDShowVolume (const float vol) noexcept + { + if (vol >= 1.0f) return 0; + if (vol <= 0.0f) return -10000; + + return roundToInt ((vol * 10000.0f) - 10000.0f); + } + + float getVolume() const + { + long volume; + basicAudio->get_Volume (&volume); + return (volume + 10000) / 10000.0f; + } + +private: + + enum { graphEventID = WM_APP + 0x43f0 }; + + DirectShowComponent& component; + HWND hwnd; + HDC hdc; + + enum State { uninitializedState, runningState, pausedState, stoppedState }; + State state; + + bool hasVideo; + long videoWidth, videoHeight; + + VideoRendererType type; + + ComSmartPtr graphBuilder; + ComSmartPtr mediaControl; + ComSmartPtr mediaPosition; + ComSmartPtr mediaEvent; + ComSmartPtr basicAudio; + ComSmartPtr baseFilter; + + ScopedPointer videoRenderer; + + class NativeWindowClass : public DeletedAtShutdown + { + private: + NativeWindowClass() + : atom (0) + { + String windowClassName ("JUCE_DIRECTSHOW_"); + windowClassName << (int) (Time::currentTimeMillis() & 0x7fffffff); + + HINSTANCE moduleHandle = (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(); + + TCHAR moduleFile [1024] = { 0 }; + GetModuleFileName (moduleHandle, moduleFile, 1024); + + WNDCLASSEX wcex = { 0 }; + wcex.cbSize = sizeof (wcex); + wcex.style = CS_OWNDC; + wcex.lpfnWndProc = (WNDPROC) wndProc; + wcex.lpszClassName = windowClassName.toWideCharPointer(); + wcex.hInstance = moduleHandle; + + atom = RegisterClassEx (&wcex); + jassert (atom != 0); + } + + ~NativeWindowClass() + { + if (atom != 0) + UnregisterClass (getWindowClassName(), (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle()); + + clearSingletonInstance(); + } + + static LRESULT CALLBACK wndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + DirectShowContext* c = (DirectShowContext*) GetWindowLongPtr (hwnd, GWLP_USERDATA); + + if (c != nullptr) + { + jassert (c->getNativeWindowHandle() == hwnd); + + switch (msg) + { + case WM_ERASEBKGND: return 1; + case WM_DISPLAYCHANGE: c->displayResolutionChanged(); break; + case graphEventID: c->graphEventProc(); return 0; + default: break; + } + } + + return DefWindowProc (hwnd, msg, wParam, lParam); + } + + public: + bool isRegistered() const noexcept { return atom != 0; } + LPCTSTR getWindowClassName() const noexcept { return (LPCTSTR) MAKELONG (atom, 0); } + + juce_DeclareSingleton_SingleThreaded_Minimal (NativeWindowClass); + + private: + ATOM atom; + + JUCE_DECLARE_NON_COPYABLE (NativeWindowClass); + }; + + class NativeWindow + { + public: + NativeWindow (HWND parentToAddTo, void* const userData) + : hwnd (0), hdc (0) + { + NativeWindowClass* const wc = NativeWindowClass::getInstance(); + + if (wc->isRegistered()) + { + DWORD exstyle = 0; + DWORD type = WS_CHILD; + + hwnd = CreateWindowEx (exstyle, wc->getWindowClassName(), + L"", type, 0, 0, 0, 0, parentToAddTo, 0, + (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(), 0); + + if (hwnd != 0) + { + hdc = GetDC (hwnd); + SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) userData); + } + } + + jassert (hwnd != 0); + } + + ~NativeWindow() + { + if (hwnd != 0) + { + SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) 0); + DestroyWindow (hwnd); + } + } + + HWND getHandle() const noexcept { return hwnd; } + HDC getContext() const noexcept { return hdc; } + + void setWindowPosition (const Rectangle& newBounds) + { + SetWindowPos (hwnd, 0, newBounds.getX(), newBounds.getY(), + newBounds.getWidth(), newBounds.getHeight(), + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); + } + + void showWindow (const bool shouldBeVisible) + { + ShowWindow (hwnd, shouldBeVisible ? SW_SHOWNA : SW_HIDE); + } + + private: + HWND hwnd; + HDC hdc; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeWindow); + }; + + ScopedPointer nativeWindow; + + bool createNativeWindow() + { + jassert (nativeWindow == nullptr); + + ComponentPeer* topLevelPeer = component.getTopLevelComponent()->getPeer(); + + jassert (topLevelPeer != nullptr); + + if (topLevelPeer != nullptr) + { + nativeWindow = new NativeWindow ((HWND) topLevelPeer->getNativeHandle(), this); + + hwnd = nativeWindow->getHandle(); + + if (hwnd != 0) + { + hdc = GetDC (hwnd); + component.updateContextPosition(); + component.showContext (component.isShowing()); + return true; + } + else + { + nativeWindow = nullptr; + } + } + + return false; + } + + void deleteNativeWindow() + { + jassert (nativeWindow != nullptr); + ReleaseDC (hwnd, hdc); + hwnd = 0; + hdc = 0; + nativeWindow = nullptr; + } + + bool isRendererConnected() + { + ComSmartPtr enumPins; + + HRESULT hr = baseFilter->EnumPins (enumPins.resetAndGetPointerAddress()); + + if (SUCCEEDED (hr)) + hr = enumPins->Reset(); + + ComSmartPtr pin; + + while (SUCCEEDED (hr) + && enumPins->Next (1, pin.resetAndGetPointerAddress(), nullptr) == S_OK) + { + ComSmartPtr otherPin; + + hr = pin->ConnectedTo (otherPin.resetAndGetPointerAddress()); + + if (SUCCEEDED (hr)) + { + PIN_DIRECTION direction; + hr = pin->QueryDirection (&direction); + + if (SUCCEEDED (hr) && direction == PINDIR_INPUT) + return true; + } + else if (hr == VFW_E_NOT_CONNECTED) + { + hr = S_OK; + } + } + + return false; + } + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DirectShowContext); +}; + +juce_ImplementSingleton_SingleThreaded (DirectShowComponent::DirectShowContext::NativeWindowClass); + +class DirectShowComponent::DirectShowComponentWatcher : public ComponentMovementWatcher +{ +public: + DirectShowComponentWatcher (DirectShowComponent* const owner_) + : ComponentMovementWatcher (owner_), + owner (owner_) + { + } + + void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) + { + if (owner->videoLoaded) + owner->updateContextPosition(); + } + + void componentPeerChanged() + { + if (owner->videoLoaded) + owner->recreateNativeWindowAsync(); + } + + void componentVisibilityChanged() + { + if (owner->videoLoaded) + owner->showContext (owner->isShowing()); + } + +private: + DirectShowComponent* const owner; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DirectShowComponentWatcher); +}; + +DirectShowComponent::DirectShowComponent (VideoRendererType type) + : videoLoaded (false), + looping (false), + needToUpdateViewport (true), + needToRecreateNativeWindow (false) +{ + setOpaque (true); + context = new DirectShowContext (*this, type); + componentWatcher = new DirectShowComponentWatcher (this); +} + +DirectShowComponent::~DirectShowComponent() +{ + componentWatcher = nullptr; +} + +bool DirectShowComponent::isDirectShowAvailable() +{ + static bool isDSAvailable = DirectShowHelpers::checkDShowAvailability(); + return isDSAvailable; +} + +void DirectShowComponent::recreateNativeWindowAsync() +{ + needToRecreateNativeWindow = true; + repaint(); +} + +void DirectShowComponent::updateContextPosition() +{ + needToUpdateViewport = true; + + if (getWidth() > 0 && getHeight() > 0) + { + Component* const topComp = getTopLevelComponent(); + + if (topComp->getPeer() != nullptr) + context->updateWindowPosition (topComp->getLocalArea (this, getLocalBounds())); + } +} + +void DirectShowComponent::showContext (const bool shouldBeVisible) +{ + context->showWindow (shouldBeVisible); +} + +void DirectShowComponent::paint (Graphics& g) +{ + if (videoLoaded) + { + if (needToRecreateNativeWindow) + { + context->peerChanged(); + needToRecreateNativeWindow = false; + } + + if (needToUpdateViewport) + { + context->updateVideoPosition(); + needToUpdateViewport = false; + } + + context->repaint(); + + ComponentPeer* const peer = getPeer(); + + if (peer != nullptr) + { + const Point topLeft (getScreenPosition() - peer->getScreenPosition()); + peer->addMaskedRegion (topLeft.getX(), topLeft.getY(), getWidth(), getHeight()); + } + } + else + { + g.fillAll (Colours::grey); + } +} + +bool DirectShowComponent::loadMovie (const String& fileOrURLPath) +{ + closeMovie(); + + videoLoaded = context->loadFile (fileOrURLPath); + + if (videoLoaded) + { + videoPath = fileOrURLPath; + context->updateVideoPosition(); + } + + return videoLoaded; +} + +bool DirectShowComponent::loadMovie (const File& videoFile) +{ + return loadMovie (videoFile.getFullPathName()); +} + +bool DirectShowComponent::loadMovie (const URL& videoURL) +{ + return loadMovie (videoURL.toString (false)); +} + +void DirectShowComponent::closeMovie() +{ + if (videoLoaded) + context->release(); + + videoLoaded = false; + videoPath = String::empty; +} + +const File DirectShowComponent::getCurrentMoviePath() const { return videoPath; } +bool DirectShowComponent::isMovieOpen() const { return videoLoaded; } +double DirectShowComponent::getMovieDuration() const { return videoLoaded ? context->getDuration() : 0.0; } +void DirectShowComponent::setLooping (const bool shouldLoop) { looping = shouldLoop; } +bool DirectShowComponent::isLooping() const { return looping; } + +void DirectShowComponent::getMovieNormalSize (int &width, int &height) const +{ + width = context->getVideoWidth(); + height = context->getVideoHeight(); +} + +void DirectShowComponent::setBoundsWithCorrectAspectRatio (const Rectangle& spaceToFitWithin, + const RectanglePlacement& placement) +{ + int normalWidth, normalHeight; + getMovieNormalSize (normalWidth, normalHeight); + + const Rectangle normalSize (0, 0, normalWidth, normalHeight); + + if (! (spaceToFitWithin.isEmpty() || normalSize.isEmpty())) + setBounds (placement.appliedTo (normalSize, spaceToFitWithin)); + else + setBounds (spaceToFitWithin); +} + +void DirectShowComponent::play() +{ + if (videoLoaded) + context->run(); +} + +void DirectShowComponent::stop() +{ + if (videoLoaded) + context->stop(); +} + +bool DirectShowComponent::isPlaying() const +{ + return context->isRunning(); +} + +void DirectShowComponent::goToStart() +{ + setPosition (0.0); +} + +void DirectShowComponent::setPosition (const double seconds) +{ + if (videoLoaded) + context->setPosition (seconds); +} + +double DirectShowComponent::getPosition() const +{ + return videoLoaded ? context->getPosition() : 0.0; +} + +void DirectShowComponent::setSpeed (const float newSpeed) +{ + if (videoLoaded) + context->setSpeed (newSpeed); +} + +void DirectShowComponent::setMovieVolume (const float newVolume) +{ + if (videoLoaded) + context->setVolume (newVolume); +} + +float DirectShowComponent::getMovieVolume() const +{ + return videoLoaded ? context->getVolume() : 0.0f; +} + +#endif + +/*** End of inlined file: juce_win32_DirectShowComponent.cpp ***/ + + /*** Start of inlined file: juce_win32_WebBrowserComponent.cpp ***/ // (This file gets included by juce_win32_NativeCode.cpp, rather than being // compiled on its own). @@ -253397,10 +254311,10 @@ public: return false; } - void updateWindowPosition (int x, int y, int w, int h, int) + void updateWindowPosition (const Rectangle& bounds) { SetWindowPos ((HWND) nativeWindow->getNativeHandle(), 0, - x, y, w, h, + bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); } @@ -260934,6 +261848,14 @@ CameraDevice* CameraDevice::openDevice (int index, #pragma comment (lib, "D2d1.lib") #endif +#if JUCE_DIRECTSHOW + #pragma comment (lib, "strmiids.lib") +#endif + +#if JUCE_MEDIAFOUNDATION + #pragma comment (lib, "mfuuid.lib") +#endif + /*** End of inlined file: juce_win32_AutoLinkLibraries.h ***/ @@ -267409,11 +268331,11 @@ public: return renderContext; } - void updateWindowPosition (int x, int y, int w, int h, int) + void updateWindowPosition (const Rectangle& bounds) { ScopedXLock xlock; XMoveResizeWindow (display, embeddedWindow, - x, y, jmax (1, w), jmax (1, h)); + bounds.getX(), bounds.getY(), jmax (1, bounds.getWidth()), jmax (1, bounds.getHeight())); } void swapBuffers() @@ -276123,9 +277045,7 @@ public: const OpenGLPixelFormat getPixelFormat() const { return pixelFormat; } void* getRawContext() const noexcept { return renderContext; } - void updateWindowPosition (int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*outerWindowHeight*/) - { - } + void updateWindowPosition (const Rectangle&) {} void swapBuffers() { @@ -276327,9 +277247,10 @@ public: const OpenGLPixelFormat getPixelFormat() const { return pixelFormat; } void* getRawContext() const noexcept { return glLayer; } - void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight) + void updateWindowPosition (const Rectangle& bounds) { - view.frame = CGRectMake ((CGFloat) x, (CGFloat) y, (CGFloat) w, (CGFloat) h); + view.frame = CGRectMake ((CGFloat) bounds.getX(), (CGFloat) bounds.getY(), + (CGFloat) bounds.getWidth(), (CGFloat) bounds.getHeight()); if (lastWidth != w || lastHeight != h) { @@ -282037,9 +282958,7 @@ public: const OpenGLPixelFormat getPixelFormat() const { return pixelFormat; } void* getRawContext() const noexcept { return renderContext; } - void updateWindowPosition (int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*outerWindowHeight*/) - { - } + void updateWindowPosition (const Rectangle&) {} void swapBuffers() { @@ -282241,9 +283160,10 @@ public: const OpenGLPixelFormat getPixelFormat() const { return pixelFormat; } void* getRawContext() const noexcept { return glLayer; } - void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight) + void updateWindowPosition (const Rectangle& bounds) { - view.frame = CGRectMake ((CGFloat) x, (CGFloat) y, (CGFloat) w, (CGFloat) h); + view.frame = CGRectMake ((CGFloat) bounds.getX(), (CGFloat) bounds.getY(), + (CGFloat) bounds.getWidth(), (CGFloat) bounds.getHeight()); if (lastWidth != w || lastHeight != h) { diff --git a/juce_amalgamated.h b/juce_amalgamated.h index b30c2a3083..7093485eca 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 99 +#define JUCE_BUILDNUMBER 100 /** Current Juce version number. @@ -305,6 +305,25 @@ namespace JuceDummyNamespace {} #define JUCE_DIRECTSOUND 1 #endif +/** JUCE_DIRECTSHOW: Enables DirectShow media-streaming architecture + (MS Windows only). +*/ +#ifndef JUCE_DIRECTSHOW + #define JUCE_DIRECTSHOW 1 +#endif + +/** JUCE_MEDIAFOUNDATION: Enables Media Foundation multimedia platform + (Windows Vista and above). +*/ +#ifndef JUCE_MEDIAFOUNDATION + #define JUCE_MEDIAFOUNDATION 1 +#endif + +#if ! JUCE_WINDOWS + #undef JUCE_DIRECTSHOW + #undef JUCE_MEDIAFOUNDATION +#endif + /** JUCE_ALSA: Enables ALSA audio devices (Linux only). */ #ifndef JUCE_ALSA #define JUCE_ALSA 1 @@ -64223,6 +64242,202 @@ private: /*** End of inlined file: juce_ColourSelector.h ***/ +#endif +#ifndef __JUCE_DIRECTSHOWCOMPONENT_JUCEHEADER__ + +/*** Start of inlined file: juce_DirectShowComponent.h ***/ +#ifndef __JUCE_DIRECTSHOWCOMPONENT_JUCEHEADER__ +#define __JUCE_DIRECTSHOWCOMPONENT_JUCEHEADER__ + +#if JUCE_DIRECTSHOW || DOXYGEN + +/** + A window that can play back a DirectShow video. + + @note Controller is not implemented +*/ +class JUCE_API DirectShowComponent : public Component +{ +public: + + /** DirectShow video renderer type. + + See MSDN for adivce about choosing the right renderer. + */ + enum VideoRendererType + { + dshowDefault, /**< VMR7 for Windows XP, EVR for Windows Vista and later */ + dshowVMR7, /**< Video Mixing Renderer 7 */ + dshowEVR /**< Enhanced Video Renderer */ + }; + + /** Creates a DirectShowComponent, initially blank. + + Use the loadMovie() method to load a video once you've added the + component to a window, (or put it on the desktop as a heavyweight window). + Loading a video when the component isn't visible can cause problems, as + DirectShow needs a window handle to initialise properly. + + @see VideoRendererType + */ + DirectShowComponent (VideoRendererType type = dshowDefault); + + /** Destructor. */ + ~DirectShowComponent(); + + /** Returns true if DirectShow is installed and working on this machine. */ + static bool isDirectShowAvailable(); + + /** Tries to load a DirectShow video from a file or URL into the player. + + It's best to call this function once you've added the component to a window, + (or put it on the desktop as a heavyweight window). Loading a video when the + component isn't visible can cause problems, because DirectShow needs a window + handle to do its stuff. + + @param fileOrURLPath the file or URL path to open + @returns true if the video opens successfully + */ + bool loadMovie (const String& fileOrURLPath); + + /** Tries to load a DirectShow video from a file into the player. + + It's best to call this function once you've added the component to a window, + (or put it on the desktop as a heavyweight window). Loading a video when the + component isn't visible can cause problems, because DirectShow needs a window + handle to do its stuff. + + @param videoFile the video file to open + @returns true if the video opens successfully + */ + bool loadMovie (const File& videoFile); + + /** Tries to load a DirectShow video from a URL into the player. + + It's best to call this function once you've added the component to a window, + (or put it on the desktop as a heavyweight window). Loading a video when the + component isn't visible can cause problems, because DirectShow needs a window + handle to do its stuff. + + @param videoURL the video URL to open + @returns true if the video opens successfully + */ + bool loadMovie (const URL& videoURL); + + /** Closes the video, if one is open. */ + void closeMovie(); + + /** Returns the file path or URL from which the video file was loaded. + If there isn't one, this returns an empty string. + */ + const File getCurrentMoviePath() const; + + /** Returns true if there's currently a video open. */ + bool isMovieOpen() const; + + /** Returns the length of the video, in seconds. */ + double getMovieDuration() const; + + /** Returns the video's natural size, in pixels. + + You can use this to resize the component to show the video at its preferred + scale. + + If no video is loaded, the size returned will be 0 x 0. + */ + void getMovieNormalSize (int& width, int& height) const; + + /** This will position the component within a given area, keeping its aspect + ratio correct according to the video's normal size. + + The component will be made as large as it can go within the space, and will + be aligned according to the justification value if this means there are gaps at + the top or sides. + + @note Not implemented + */ + void setBoundsWithCorrectAspectRatio (const Rectangle& spaceToFitWithin, + const RectanglePlacement& placement); + + /** Starts the video playing. */ + void play(); + + /** Stops the video playing. */ + void stop(); + + /** Returns true if the video is currently playing. */ + bool isPlaying() const; + + /** Moves the video's position back to the start. */ + void goToStart(); + + /** Sets the video's position to a given time. */ + void setPosition (double seconds); + + /** Returns the current play position of the video. */ + double getPosition() const; + + /** Changes the video playback rate. + + A value of 1 is normal speed, greater values play it proportionately faster, + smaller values play it slower. + */ + void setSpeed (float newSpeed); + + /** Changes the video's playback volume. + + @param newVolume the volume in the range 0 (silent) to 1.0 (full) + */ + void setMovieVolume (float newVolume); + + /** Returns the video's playback volume. + + @returns the volume in the range 0 (silent) to 1.0 (full) + */ + float getMovieVolume() const; + + /** Tells the video whether it should loop. */ + void setLooping (bool shouldLoop); + + /** Returns true if the video is currently looping. + + @see setLooping + */ + bool isLooping() const; + + /** @internal */ + void paint (Graphics& g); + +private: + + String videoPath; + bool videoLoaded, looping; + + class DirectShowContext; + friend class DirectShowContext; + friend class ScopedPointer ; + ScopedPointer context; + + class DirectShowComponentWatcher; + friend class DirectShowComponentWatcher; + friend class ScopedPointer ; + ScopedPointer componentWatcher; + + bool needToUpdateViewport, needToRecreateNativeWindow; + + void updateContextPosition(); + void showContext (bool shouldBeVisible); + void recreateNativeWindowAsync(); + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DirectShowComponent); +}; + +#endif +#endif // __JUCE_DIRECTSHOWCOMPONENT_JUCEHEADER__ + +/*** End of inlined file: juce_DirectShowComponent.h ***/ + + #endif #ifndef __JUCE_DROPSHADOWER_JUCEHEADER__ @@ -64786,7 +65001,7 @@ public: /** For windowed contexts, this moves the context within the bounds of its parent window. */ - virtual void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight) = 0; + virtual void updateWindowPosition (const Rectangle& bounds) = 0; /** For windowed contexts, this triggers a repaint of the window. @@ -69544,6 +69759,14 @@ END_JUCE_NAMESPACE #pragma comment (lib, "D2d1.lib") #endif +#if JUCE_DIRECTSHOW + #pragma comment (lib, "strmiids.lib") +#endif + +#if JUCE_MEDIAFOUNDATION + #pragma comment (lib, "mfuuid.lib") +#endif + /*** End of inlined file: juce_win32_AutoLinkLibraries.h ***/ diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 83fdf0d9da..88557a4285 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 99 +#define JUCE_BUILDNUMBER 100 /** Current Juce version number. diff --git a/src/gui/components/special/juce_DirectShowComponent.h b/src/gui/components/special/juce_DirectShowComponent.h new file mode 100644 index 0000000000..3fcf7249b1 --- /dev/null +++ b/src/gui/components/special/juce_DirectShowComponent.h @@ -0,0 +1,221 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-11 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#ifndef __JUCE_DIRECTSHOWCOMPONENT_JUCEHEADER__ +#define __JUCE_DIRECTSHOWCOMPONENT_JUCEHEADER__ + +#include "../juce_Component.h" + +#if JUCE_DIRECTSHOW || DOXYGEN + +//============================================================================== +/** + A window that can play back a DirectShow video. + + @note Controller is not implemented +*/ +class JUCE_API DirectShowComponent : public Component +{ +public: + //============================================================================== + /** DirectShow video renderer type. + + See MSDN for adivce about choosing the right renderer. + */ + enum VideoRendererType + { + dshowDefault, /**< VMR7 for Windows XP, EVR for Windows Vista and later */ + dshowVMR7, /**< Video Mixing Renderer 7 */ + dshowEVR /**< Enhanced Video Renderer */ + }; + + /** Creates a DirectShowComponent, initially blank. + + Use the loadMovie() method to load a video once you've added the + component to a window, (or put it on the desktop as a heavyweight window). + Loading a video when the component isn't visible can cause problems, as + DirectShow needs a window handle to initialise properly. + + @see VideoRendererType + */ + DirectShowComponent (VideoRendererType type = dshowDefault); + + /** Destructor. */ + ~DirectShowComponent(); + + /** Returns true if DirectShow is installed and working on this machine. */ + static bool isDirectShowAvailable(); + + //============================================================================== + /** Tries to load a DirectShow video from a file or URL into the player. + + It's best to call this function once you've added the component to a window, + (or put it on the desktop as a heavyweight window). Loading a video when the + component isn't visible can cause problems, because DirectShow needs a window + handle to do its stuff. + + @param fileOrURLPath the file or URL path to open + @returns true if the video opens successfully + */ + bool loadMovie (const String& fileOrURLPath); + + /** Tries to load a DirectShow video from a file into the player. + + It's best to call this function once you've added the component to a window, + (or put it on the desktop as a heavyweight window). Loading a video when the + component isn't visible can cause problems, because DirectShow needs a window + handle to do its stuff. + + @param videoFile the video file to open + @returns true if the video opens successfully + */ + bool loadMovie (const File& videoFile); + + /** Tries to load a DirectShow video from a URL into the player. + + It's best to call this function once you've added the component to a window, + (or put it on the desktop as a heavyweight window). Loading a video when the + component isn't visible can cause problems, because DirectShow needs a window + handle to do its stuff. + + @param videoURL the video URL to open + @returns true if the video opens successfully + */ + bool loadMovie (const URL& videoURL); + + /** Closes the video, if one is open. */ + void closeMovie(); + + /** Returns the file path or URL from which the video file was loaded. + If there isn't one, this returns an empty string. + */ + const File getCurrentMoviePath() const; + + /** Returns true if there's currently a video open. */ + bool isMovieOpen() const; + + /** Returns the length of the video, in seconds. */ + double getMovieDuration() const; + + /** Returns the video's natural size, in pixels. + + You can use this to resize the component to show the video at its preferred + scale. + + If no video is loaded, the size returned will be 0 x 0. + */ + void getMovieNormalSize (int& width, int& height) const; + + /** This will position the component within a given area, keeping its aspect + ratio correct according to the video's normal size. + + The component will be made as large as it can go within the space, and will + be aligned according to the justification value if this means there are gaps at + the top or sides. + + @note Not implemented + */ + void setBoundsWithCorrectAspectRatio (const Rectangle& spaceToFitWithin, + const RectanglePlacement& placement); + + /** Starts the video playing. */ + void play(); + + /** Stops the video playing. */ + void stop(); + + /** Returns true if the video is currently playing. */ + bool isPlaying() const; + + /** Moves the video's position back to the start. */ + void goToStart(); + + /** Sets the video's position to a given time. */ + void setPosition (double seconds); + + /** Returns the current play position of the video. */ + double getPosition() const; + + /** Changes the video playback rate. + + A value of 1 is normal speed, greater values play it proportionately faster, + smaller values play it slower. + */ + void setSpeed (float newSpeed); + + /** Changes the video's playback volume. + + @param newVolume the volume in the range 0 (silent) to 1.0 (full) + */ + void setMovieVolume (float newVolume); + + /** Returns the video's playback volume. + + @returns the volume in the range 0 (silent) to 1.0 (full) + */ + float getMovieVolume() const; + + /** Tells the video whether it should loop. */ + void setLooping (bool shouldLoop); + + /** Returns true if the video is currently looping. + + @see setLooping + */ + bool isLooping() const; + + + //============================================================================== + /** @internal */ + void paint (Graphics& g); + +private: + //============================================================================== + String videoPath; + bool videoLoaded, looping; + + class DirectShowContext; + friend class DirectShowContext; + friend class ScopedPointer ; + ScopedPointer context; + + class DirectShowComponentWatcher; + friend class DirectShowComponentWatcher; + friend class ScopedPointer ; + ScopedPointer componentWatcher; + + bool needToUpdateViewport, needToRecreateNativeWindow; + + //============================================================================== + void updateContextPosition(); + void showContext (bool shouldBeVisible); + void recreateNativeWindowAsync(); + + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DirectShowComponent); +}; + +#endif +#endif // __JUCE_DIRECTSHOWCOMPONENT_JUCEHEADER__ diff --git a/src/gui/components/special/juce_OpenGLComponent.cpp b/src/gui/components/special/juce_OpenGLComponent.cpp index 02dfa413a3..7afbdcd281 100644 --- a/src/gui/components/special/juce_OpenGLComponent.cpp +++ b/src/gui/components/special/juce_OpenGLComponent.cpp @@ -359,11 +359,7 @@ void OpenGLComponent::updateContextPosition() const ScopedLock sl (contextLock); if (context != nullptr) - context->updateWindowPosition (getScreenX() - topComp->getScreenX(), - getScreenY() - topComp->getScreenY(), - getWidth(), - getHeight(), - topComp->getHeight()); + context->updateWindowPosition (topComp->getLocalArea (this, getLocalBounds())); } } } diff --git a/src/gui/components/special/juce_OpenGLComponent.h b/src/gui/components/special/juce_OpenGLComponent.h index c3c051f381..673b430cef 100644 --- a/src/gui/components/special/juce_OpenGLComponent.h +++ b/src/gui/components/special/juce_OpenGLComponent.h @@ -132,7 +132,7 @@ public: /** For windowed contexts, this moves the context within the bounds of its parent window. */ - virtual void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight) = 0; + virtual void updateWindowPosition (const Rectangle& bounds) = 0; /** For windowed contexts, this triggers a repaint of the window. diff --git a/src/juce_app_includes.h b/src/juce_app_includes.h index 45d44478e9..5407cf8759 100644 --- a/src/juce_app_includes.h +++ b/src/juce_app_includes.h @@ -587,6 +587,9 @@ #ifndef __JUCE_COLOURSELECTOR_JUCEHEADER__ #include "gui/components/special/juce_ColourSelector.h" #endif +#ifndef __JUCE_DIRECTSHOWCOMPONENT_JUCEHEADER__ + #include "gui/components/special/juce_DirectShowComponent.h" +#endif #ifndef __JUCE_DROPSHADOWER_JUCEHEADER__ #include "gui/components/special/juce_DropShadower.h" #endif diff --git a/src/native/linux/juce_linux_Windowing.cpp b/src/native/linux/juce_linux_Windowing.cpp index 6c4dd90eeb..a22a917002 100644 --- a/src/native/linux/juce_linux_Windowing.cpp +++ b/src/native/linux/juce_linux_Windowing.cpp @@ -3213,11 +3213,11 @@ public: return renderContext; } - void updateWindowPosition (int x, int y, int w, int h, int) + void updateWindowPosition (const Rectangle& bounds) { ScopedXLock xlock; XMoveResizeWindow (display, embeddedWindow, - x, y, jmax (1, w), jmax (1, h)); + bounds.getX(), bounds.getY(), jmax (1, bounds.getWidth()), jmax (1, bounds.getHeight())); } void swapBuffers() diff --git a/src/native/mac/juce_mac_OpenGLComponent.mm b/src/native/mac/juce_mac_OpenGLComponent.mm index afcd096d94..18acd5b8bc 100644 --- a/src/native/mac/juce_mac_OpenGLComponent.mm +++ b/src/native/mac/juce_mac_OpenGLComponent.mm @@ -215,9 +215,7 @@ public: const OpenGLPixelFormat getPixelFormat() const { return pixelFormat; } void* getRawContext() const noexcept { return renderContext; } - void updateWindowPosition (int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*outerWindowHeight*/) - { - } + void updateWindowPosition (const Rectangle&) {} void swapBuffers() { @@ -424,9 +422,10 @@ public: const OpenGLPixelFormat getPixelFormat() const { return pixelFormat; } void* getRawContext() const noexcept { return glLayer; } - void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight) + void updateWindowPosition (const Rectangle& bounds) { - view.frame = CGRectMake ((CGFloat) x, (CGFloat) y, (CGFloat) w, (CGFloat) h); + view.frame = CGRectMake ((CGFloat) bounds.getX(), (CGFloat) bounds.getY(), + (CGFloat) bounds.getWidth(), (CGFloat) bounds.getHeight()); if (lastWidth != w || lastHeight != h) { diff --git a/src/native/windows/juce_win32_AutoLinkLibraries.h b/src/native/windows/juce_win32_AutoLinkLibraries.h index a3b4ebb632..18bb4fca64 100644 --- a/src/native/windows/juce_win32_AutoLinkLibraries.h +++ b/src/native/windows/juce_win32_AutoLinkLibraries.h @@ -48,3 +48,11 @@ #pragma comment (lib, "Dwrite.lib") #pragma comment (lib, "D2d1.lib") #endif + +#if JUCE_DIRECTSHOW + #pragma comment (lib, "strmiids.lib") +#endif + +#if JUCE_MEDIAFOUNDATION + #pragma comment (lib, "mfuuid.lib") +#endif diff --git a/src/native/windows/juce_win32_DirectShowComponent.cpp b/src/native/windows/juce_win32_DirectShowComponent.cpp new file mode 100644 index 0000000000..7c98a2c511 --- /dev/null +++ b/src/native/windows/juce_win32_DirectShowComponent.cpp @@ -0,0 +1,941 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-11 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#if JUCE_INCLUDED_FILE + + +//====================================================================== +namespace DirectShowHelpers +{ + bool checkDShowAvailability() + { + ComSmartPtr graph; + return SUCCEEDED (graph.CoCreateInstance (CLSID_FilterGraph)); + } + + //====================================================================== + class VideoRenderer + { + public: + VideoRenderer() {} + virtual ~VideoRenderer() {} + + virtual HRESULT create (ComSmartPtr & graphBuilder, + ComSmartPtr & baseFilter, HWND hwnd) = 0; + + virtual void setVideoWindow (HWND hwnd) = 0; + virtual void setVideoPosition (HWND hwnd, long videoWidth, long videoHeight) = 0; + virtual void repaintVideo (HWND hwnd, HDC hdc) = 0; + virtual void displayModeChanged() = 0; + virtual HRESULT getVideoSize (long& videoWidth, long& videoHeight) = 0; + }; + + //====================================================================== + class VMR7 : public VideoRenderer + { + public: + VMR7() {} + + HRESULT create (ComSmartPtr & graphBuilder, + ComSmartPtr & baseFilter, HWND hwnd) + { + ComSmartPtr filterConfig; + + HRESULT hr = baseFilter.CoCreateInstance (CLSID_VideoMixingRenderer); + + if (SUCCEEDED (hr)) + hr = graphBuilder->AddFilter (baseFilter, L"VMR-7"); + + if (SUCCEEDED (hr)) + hr = baseFilter.QueryInterface (IID_IVMRFilterConfig, filterConfig); + + if (SUCCEEDED (hr)) + hr = filterConfig->SetRenderingMode (VMRMode_Windowless); + + if (SUCCEEDED (hr)) + hr = baseFilter.QueryInterface (IID_IVMRWindowlessControl, windowlessControl); + + if (SUCCEEDED (hr)) + hr = windowlessControl->SetVideoClippingWindow (hwnd); + + if (SUCCEEDED (hr)) + hr = windowlessControl->SetAspectRatioMode (VMR_ARMODE_LETTER_BOX); + + return hr; + } + + void setVideoWindow (HWND hwnd) + { + windowlessControl->SetVideoClippingWindow (hwnd); + } + + void setVideoPosition (HWND hwnd, long videoWidth, long videoHeight) + { + RECT src, dest; + + SetRect (&src, 0, 0, videoWidth, videoHeight); + GetClientRect (hwnd, &dest); + + windowlessControl->SetVideoPosition (&src, &dest); + } + + void repaintVideo (HWND hwnd, HDC hdc) + { + windowlessControl->RepaintVideo (hwnd, hdc); + } + + void displayModeChanged() + { + windowlessControl->DisplayModeChanged(); + } + + HRESULT getVideoSize (long& videoWidth, long& videoHeight) + { + return windowlessControl->GetNativeVideoSize (&videoWidth, &videoHeight, nullptr, nullptr); + } + + private: + ComSmartPtr windowlessControl; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VMR7); + }; + + + //====================================================================== +#if JUCE_MEDIAFOUNDATION + class EVR : public VideoRenderer + { + public: + EVR() {} + + HRESULT create (ComSmartPtr & graphBuilder, + ComSmartPtr & baseFilter, HWND hwnd) + { + ComSmartPtr getService; + + HRESULT hr = baseFilter.CoCreateInstance (CLSID_EnhancedVideoRenderer); + + if (SUCCEEDED (hr)) + hr = graphBuilder->AddFilter (baseFilter, L"EVR"); + + if (SUCCEEDED (hr)) + hr = baseFilter.QueryInterface (IID_IMFGetService, getService); + + if (SUCCEEDED (hr)) + hr = getService->GetService (MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl, + (LPVOID*) videoDisplayControl.resetAndGetPointerAddress()); + + if (SUCCEEDED (hr)) + hr = videoDisplayControl->SetVideoWindow (hwnd); + + if (SUCCEEDED (hr)) + hr = videoDisplayControl->SetAspectRatioMode (MFVideoARMode_PreservePicture); + + return hr; + } + + void setVideoWindow (HWND hwnd) + { + videoDisplayControl->SetVideoWindow (hwnd); + } + + void setVideoPosition (HWND hwnd, long /*videoWidth*/, long /*videoHeight*/) + { + const MFVideoNormalizedRect src = { 0.0f, 0.0f, 1.0f, 1.0f }; + + RECT dest; + GetClientRect (hwnd, &dest); + + videoDisplayControl->SetVideoPosition (&src, &dest); + } + + void repaintVideo (HWND /*hwnd*/, HDC /*hdc*/) + { + videoDisplayControl->RepaintVideo(); + } + + void displayModeChanged() {} + + HRESULT getVideoSize (long& videoWidth, long& videoHeight) + { + SIZE sz; + HRESULT hr = videoDisplayControl->GetNativeVideoSize (&sz, nullptr); + videoWidth = sz.cx; + videoHeight = sz.cy; + return hr; + } + + private: + ComSmartPtr videoDisplayControl; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EVR); + }; +#endif +} + + +//====================================================================== +class DirectShowComponent::DirectShowContext +{ +public: + DirectShowContext (DirectShowComponent& component_, VideoRendererType type_) + : component (component_), + hwnd (0), + hdc (0), + state (uninitializedState), + hasVideo (false), + videoWidth (0), + videoHeight (0), + type (type_) + { + CoInitialize (0); + + if (type == dshowDefault) + { + type = dshowVMR7; + + #if JUCE_MEDIAFOUNDATION + if (SystemStats::getOperatingSystemType() >= SystemStats::WinVista) + type = dshowEVR; + #endif + } + } + + ~DirectShowContext() + { + release(); + CoUninitialize(); + } + + //====================================================================== + HWND getNativeWindowHandle() const + { + return nativeWindow != nullptr ? nativeWindow->getHandle() : 0; + } + + //====================================================================== + void updateWindowPosition (const Rectangle& newBounds) + { + nativeWindow->setWindowPosition (newBounds); + } + + void showWindow (bool shouldBeVisible) + { + nativeWindow->showWindow (shouldBeVisible); + } + + //====================================================================== + void repaint() + { + if (hasVideo) + videoRenderer->repaintVideo (nativeWindow->getHandle(), nativeWindow->getContext()); + } + + void updateVideoPosition() + { + if (hasVideo) + videoRenderer->setVideoPosition (nativeWindow->getHandle(), videoWidth, videoHeight); + } + + void displayResolutionChanged() + { + if (hasVideo) + videoRenderer->displayModeChanged(); + } + + //====================================================================== + void peerChanged() + { + deleteNativeWindow(); + + mediaEvent->SetNotifyWindow (0, 0, 0); + if (videoRenderer != nullptr) + videoRenderer->setVideoWindow (nullptr); + + createNativeWindow(); + + mediaEvent->SetNotifyWindow ((OAHWND) hwnd, graphEventID, 0); + if (videoRenderer != nullptr) + videoRenderer->setVideoWindow (hwnd); + } + + //====================================================================== + bool loadFile (const String& fileOrURLPath) + { + jassert (state == uninitializedState); + + if (! createNativeWindow()) + return false; + + HRESULT hr = graphBuilder.CoCreateInstance (CLSID_FilterGraph); + + // basic playback interfaces + if (SUCCEEDED (hr)) hr = graphBuilder.QueryInterface (IID_IMediaControl, mediaControl); + if (SUCCEEDED (hr)) hr = graphBuilder.QueryInterface (IID_IMediaPosition, mediaPosition); + if (SUCCEEDED (hr)) hr = graphBuilder.QueryInterface (IID_IMediaEventEx, mediaEvent); + if (SUCCEEDED (hr)) hr = graphBuilder.QueryInterface (IID_IBasicAudio, basicAudio); + + // video renderer interface + if (SUCCEEDED (hr)) + { + #if JUCE_MEDIAFOUNDATION + if (type == dshowEVR) + videoRenderer = new DirectShowHelpers::EVR(); + else + #endif + videoRenderer = new DirectShowHelpers::VMR7(); + + hr = videoRenderer->create (graphBuilder, baseFilter, hwnd); + } + + // build filter graph + if (SUCCEEDED (hr)) + hr = graphBuilder->RenderFile (fileOrURLPath.toWideCharPointer(), nullptr); + + // remove video renderer if not connected (no video) + if (SUCCEEDED (hr)) + { + if (isRendererConnected()) + { + hasVideo = true; + hr = videoRenderer->getVideoSize (videoWidth, videoHeight); + } + else + { + hasVideo = false; + graphBuilder->RemoveFilter (baseFilter); + videoRenderer = nullptr; + baseFilter = nullptr; + } + } + + // set window to receive events + if (SUCCEEDED (hr)) + hr = mediaEvent->SetNotifyWindow ((OAHWND) hwnd, graphEventID, 0); + + if (SUCCEEDED (hr)) + { + state = stoppedState; + return true; + } + + release(); + return false; + } + + void release() + { + if (mediaControl != nullptr) + mediaControl->Stop(); + + if (mediaEvent != nullptr) + mediaEvent->SetNotifyWindow (0, 0, 0); + + if (videoRenderer != nullptr) + videoRenderer->setVideoWindow (0); + + hasVideo = false; + videoRenderer = nullptr; + + baseFilter = nullptr; + basicAudio = nullptr; + mediaEvent = nullptr; + mediaPosition = nullptr; + mediaControl = nullptr; + graphBuilder = nullptr; + + state = uninitializedState; + + videoWidth = 0; + videoHeight = 0; + + if (nativeWindow != nullptr) + deleteNativeWindow(); + } + + void graphEventProc() + { + LONG ec; + LONG_PTR p1, p2; + + jassert (mediaEvent != nullptr); + + while (SUCCEEDED (mediaEvent->GetEvent (&ec, &p1, &p2, 0))) + { + switch (ec) + { + case EC_REPAINT: + component.repaint(); + break; + + case EC_COMPLETE: + if (component.isLooping()) + component.goToStart(); + else + component.stop(); + break; + + case EC_USERABORT: + case EC_ERRORABORT: + case EC_ERRORABORTEX: + component.closeMovie(); + break; + + default: + break; + } + + mediaEvent->FreeEventParams (ec, p1, p2); + } + } + + //====================================================================== + void run() + { + mediaControl->Run(); + state = runningState; + } + + void stop() + { + mediaControl->Stop(); + state = stoppedState; + } + + void pause() + { + mediaControl->Pause(); + state = pausedState; + } + + //====================================================================== + bool isInitialised() const noexcept { return state != uninitializedState; } + bool isRunning() const noexcept { return state == runningState; } + bool isPaused() const noexcept { return state == pausedState; } + bool isStopped() const noexcept { return state == stoppedState; } + bool containsVideo() const noexcept { return hasVideo; } + int getVideoWidth() const noexcept { return (int) videoWidth; } + int getVideoHeight() const noexcept { return (int) videoHeight; } + + //====================================================================== + double getDuration() const + { + REFTIME duration; + mediaPosition->get_Duration (&duration); + return duration; + } + + double getPosition() const + { + REFTIME seconds; + mediaPosition->get_CurrentPosition (&seconds); + return seconds; + } + + //====================================================================== + void setSpeed (const float newSpeed) { mediaPosition->put_Rate (newSpeed); } + void setPosition (const double seconds) { mediaPosition->put_CurrentPosition (seconds); } + void setVolume (const float newVolume) { basicAudio->put_Volume (convertToDShowVolume (newVolume)); } + + // in DirectShow, full volume is 0, silence is -10000 + static long convertToDShowVolume (const float vol) noexcept + { + if (vol >= 1.0f) return 0; + if (vol <= 0.0f) return -10000; + + return roundToInt ((vol * 10000.0f) - 10000.0f); + } + + float getVolume() const + { + long volume; + basicAudio->get_Volume (&volume); + return (volume + 10000) / 10000.0f; + } + +private: + //====================================================================== + enum { graphEventID = WM_APP + 0x43f0 }; + + DirectShowComponent& component; + HWND hwnd; + HDC hdc; + + enum State { uninitializedState, runningState, pausedState, stoppedState }; + State state; + + bool hasVideo; + long videoWidth, videoHeight; + + VideoRendererType type; + + ComSmartPtr graphBuilder; + ComSmartPtr mediaControl; + ComSmartPtr mediaPosition; + ComSmartPtr mediaEvent; + ComSmartPtr basicAudio; + ComSmartPtr baseFilter; + + ScopedPointer videoRenderer; + + //====================================================================== + class NativeWindowClass : public DeletedAtShutdown + { + private: + NativeWindowClass() + : atom (0) + { + String windowClassName ("JUCE_DIRECTSHOW_"); + windowClassName << (int) (Time::currentTimeMillis() & 0x7fffffff); + + HINSTANCE moduleHandle = (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(); + + TCHAR moduleFile [1024] = { 0 }; + GetModuleFileName (moduleHandle, moduleFile, 1024); + + WNDCLASSEX wcex = { 0 }; + wcex.cbSize = sizeof (wcex); + wcex.style = CS_OWNDC; + wcex.lpfnWndProc = (WNDPROC) wndProc; + wcex.lpszClassName = windowClassName.toWideCharPointer(); + wcex.hInstance = moduleHandle; + + atom = RegisterClassEx (&wcex); + jassert (atom != 0); + } + + ~NativeWindowClass() + { + if (atom != 0) + UnregisterClass (getWindowClassName(), (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle()); + + clearSingletonInstance(); + } + + static LRESULT CALLBACK wndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + DirectShowContext* c = (DirectShowContext*) GetWindowLongPtr (hwnd, GWLP_USERDATA); + + if (c != nullptr) + { + jassert (c->getNativeWindowHandle() == hwnd); + + switch (msg) + { + case WM_ERASEBKGND: return 1; + case WM_DISPLAYCHANGE: c->displayResolutionChanged(); break; + case graphEventID: c->graphEventProc(); return 0; + default: break; + } + } + + return DefWindowProc (hwnd, msg, wParam, lParam); + } + + public: + bool isRegistered() const noexcept { return atom != 0; } + LPCTSTR getWindowClassName() const noexcept { return (LPCTSTR) MAKELONG (atom, 0); } + + juce_DeclareSingleton_SingleThreaded_Minimal (NativeWindowClass); + + private: + ATOM atom; + + JUCE_DECLARE_NON_COPYABLE (NativeWindowClass); + }; + + //====================================================================== + class NativeWindow + { + public: + NativeWindow (HWND parentToAddTo, void* const userData) + : hwnd (0), hdc (0) + { + NativeWindowClass* const wc = NativeWindowClass::getInstance(); + + if (wc->isRegistered()) + { + DWORD exstyle = 0; + DWORD type = WS_CHILD; + + hwnd = CreateWindowEx (exstyle, wc->getWindowClassName(), + L"", type, 0, 0, 0, 0, parentToAddTo, 0, + (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(), 0); + + if (hwnd != 0) + { + hdc = GetDC (hwnd); + SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) userData); + } + } + + jassert (hwnd != 0); + } + + ~NativeWindow() + { + if (hwnd != 0) + { + SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) 0); + DestroyWindow (hwnd); + } + } + + HWND getHandle() const noexcept { return hwnd; } + HDC getContext() const noexcept { return hdc; } + + void setWindowPosition (const Rectangle& newBounds) + { + SetWindowPos (hwnd, 0, newBounds.getX(), newBounds.getY(), + newBounds.getWidth(), newBounds.getHeight(), + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); + } + + void showWindow (const bool shouldBeVisible) + { + ShowWindow (hwnd, shouldBeVisible ? SW_SHOWNA : SW_HIDE); + } + + private: + HWND hwnd; + HDC hdc; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeWindow); + }; + + ScopedPointer nativeWindow; + + //====================================================================== + bool createNativeWindow() + { + jassert (nativeWindow == nullptr); + + ComponentPeer* topLevelPeer = component.getTopLevelComponent()->getPeer(); + + jassert (topLevelPeer != nullptr); + + if (topLevelPeer != nullptr) + { + nativeWindow = new NativeWindow ((HWND) topLevelPeer->getNativeHandle(), this); + + hwnd = nativeWindow->getHandle(); + + if (hwnd != 0) + { + hdc = GetDC (hwnd); + component.updateContextPosition(); + component.showContext (component.isShowing()); + return true; + } + else + { + nativeWindow = nullptr; + } + } + + return false; + } + + void deleteNativeWindow() + { + jassert (nativeWindow != nullptr); + ReleaseDC (hwnd, hdc); + hwnd = 0; + hdc = 0; + nativeWindow = nullptr; + } + + bool isRendererConnected() + { + ComSmartPtr enumPins; + + HRESULT hr = baseFilter->EnumPins (enumPins.resetAndGetPointerAddress()); + + if (SUCCEEDED (hr)) + hr = enumPins->Reset(); + + ComSmartPtr pin; + + while (SUCCEEDED (hr) + && enumPins->Next (1, pin.resetAndGetPointerAddress(), nullptr) == S_OK) + { + ComSmartPtr otherPin; + + hr = pin->ConnectedTo (otherPin.resetAndGetPointerAddress()); + + if (SUCCEEDED (hr)) + { + PIN_DIRECTION direction; + hr = pin->QueryDirection (&direction); + + if (SUCCEEDED (hr) && direction == PINDIR_INPUT) + return true; + } + else if (hr == VFW_E_NOT_CONNECTED) + { + hr = S_OK; + } + } + + return false; + } + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DirectShowContext); +}; + +juce_ImplementSingleton_SingleThreaded (DirectShowComponent::DirectShowContext::NativeWindowClass); + + +//====================================================================== +class DirectShowComponent::DirectShowComponentWatcher : public ComponentMovementWatcher +{ +public: + DirectShowComponentWatcher (DirectShowComponent* const owner_) + : ComponentMovementWatcher (owner_), + owner (owner_) + { + } + + void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) + { + if (owner->videoLoaded) + owner->updateContextPosition(); + } + + void componentPeerChanged() + { + if (owner->videoLoaded) + owner->recreateNativeWindowAsync(); + } + + void componentVisibilityChanged() + { + if (owner->videoLoaded) + owner->showContext (owner->isShowing()); + } + + //====================================================================== +private: + DirectShowComponent* const owner; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DirectShowComponentWatcher); +}; + + +//====================================================================== +DirectShowComponent::DirectShowComponent (VideoRendererType type) + : videoLoaded (false), + looping (false), + needToUpdateViewport (true), + needToRecreateNativeWindow (false) +{ + setOpaque (true); + context = new DirectShowContext (*this, type); + componentWatcher = new DirectShowComponentWatcher (this); +} + +DirectShowComponent::~DirectShowComponent() +{ + componentWatcher = nullptr; +} + +bool DirectShowComponent::isDirectShowAvailable() +{ + static bool isDSAvailable = DirectShowHelpers::checkDShowAvailability(); + return isDSAvailable; +} + +void DirectShowComponent::recreateNativeWindowAsync() +{ + needToRecreateNativeWindow = true; + repaint(); +} + +void DirectShowComponent::updateContextPosition() +{ + needToUpdateViewport = true; + + if (getWidth() > 0 && getHeight() > 0) + { + Component* const topComp = getTopLevelComponent(); + + if (topComp->getPeer() != nullptr) + context->updateWindowPosition (topComp->getLocalArea (this, getLocalBounds())); + } +} + +void DirectShowComponent::showContext (const bool shouldBeVisible) +{ + context->showWindow (shouldBeVisible); +} + +void DirectShowComponent::paint (Graphics& g) +{ + if (videoLoaded) + { + if (needToRecreateNativeWindow) + { + context->peerChanged(); + needToRecreateNativeWindow = false; + } + + if (needToUpdateViewport) + { + context->updateVideoPosition(); + needToUpdateViewport = false; + } + + context->repaint(); + + ComponentPeer* const peer = getPeer(); + + if (peer != nullptr) + { + const Point topLeft (getScreenPosition() - peer->getScreenPosition()); + peer->addMaskedRegion (topLeft.getX(), topLeft.getY(), getWidth(), getHeight()); + } + } + else + { + g.fillAll (Colours::grey); + } +} + +//====================================================================== +bool DirectShowComponent::loadMovie (const String& fileOrURLPath) +{ + closeMovie(); + + videoLoaded = context->loadFile (fileOrURLPath); + + if (videoLoaded) + { + videoPath = fileOrURLPath; + context->updateVideoPosition(); + } + + return videoLoaded; +} + +bool DirectShowComponent::loadMovie (const File& videoFile) +{ + return loadMovie (videoFile.getFullPathName()); +} + +bool DirectShowComponent::loadMovie (const URL& videoURL) +{ + return loadMovie (videoURL.toString (false)); +} + +void DirectShowComponent::closeMovie() +{ + if (videoLoaded) + context->release(); + + videoLoaded = false; + videoPath = String::empty; +} + +//====================================================================== +const File DirectShowComponent::getCurrentMoviePath() const { return videoPath; } +bool DirectShowComponent::isMovieOpen() const { return videoLoaded; } +double DirectShowComponent::getMovieDuration() const { return videoLoaded ? context->getDuration() : 0.0; } +void DirectShowComponent::setLooping (const bool shouldLoop) { looping = shouldLoop; } +bool DirectShowComponent::isLooping() const { return looping; } + +void DirectShowComponent::getMovieNormalSize (int &width, int &height) const +{ + width = context->getVideoWidth(); + height = context->getVideoHeight(); +} + +//====================================================================== +void DirectShowComponent::setBoundsWithCorrectAspectRatio (const Rectangle& spaceToFitWithin, + const RectanglePlacement& placement) +{ + int normalWidth, normalHeight; + getMovieNormalSize (normalWidth, normalHeight); + + const Rectangle normalSize (0, 0, normalWidth, normalHeight); + + if (! (spaceToFitWithin.isEmpty() || normalSize.isEmpty())) + setBounds (placement.appliedTo (normalSize, spaceToFitWithin)); + else + setBounds (spaceToFitWithin); +} + +//====================================================================== +void DirectShowComponent::play() +{ + if (videoLoaded) + context->run(); +} + +void DirectShowComponent::stop() +{ + if (videoLoaded) + context->stop(); +} + +bool DirectShowComponent::isPlaying() const +{ + return context->isRunning(); +} + +void DirectShowComponent::goToStart() +{ + setPosition (0.0); +} + +void DirectShowComponent::setPosition (const double seconds) +{ + if (videoLoaded) + context->setPosition (seconds); +} + +double DirectShowComponent::getPosition() const +{ + return videoLoaded ? context->getPosition() : 0.0; +} + +void DirectShowComponent::setSpeed (const float newSpeed) +{ + if (videoLoaded) + context->setSpeed (newSpeed); +} + +void DirectShowComponent::setMovieVolume (const float newVolume) +{ + if (videoLoaded) + context->setVolume (newVolume); +} + +float DirectShowComponent::getMovieVolume() const +{ + return videoLoaded ? context->getVolume() : 0.0f; +} + + +#endif diff --git a/src/native/windows/juce_win32_Files.cpp b/src/native/windows/juce_win32_Files.cpp index 572e51055c..84247764cc 100644 --- a/src/native/windows/juce_win32_Files.cpp +++ b/src/native/windows/juce_win32_Files.cpp @@ -307,7 +307,7 @@ MemoryMappedFile::MemoryMappedFile (const File& file, MemoryMappedFile::AccessMo { jassert (mode == readOnly || mode == readWrite); - DWORD accessMode = GENERIC_READ, shareMode = FILE_SHARE_READ, createType = OPEN_EXISTING; + DWORD accessMode = GENERIC_READ, createType = OPEN_EXISTING; DWORD protect = PAGE_READONLY, access = FILE_MAP_READ; if (mode == readWrite) diff --git a/src/native/windows/juce_win32_NativeCode.cpp b/src/native/windows/juce_win32_NativeCode.cpp index 5b57974fe5..e6c4627c75 100644 --- a/src/native/windows/juce_win32_NativeCode.cpp +++ b/src/native/windows/juce_win32_NativeCode.cpp @@ -74,6 +74,7 @@ BEGIN_JUCE_NAMESPACE #include "../../gui/components/menus/juce_MenuBarModel.h" #include "../../gui/components/special/juce_OpenGLComponent.h" #include "../../gui/components/special/juce_QuickTimeMovieComponent.h" +#include "../../gui/components/special/juce_DirectShowComponent.h" #include "../../gui/components/mouse/juce_DragAndDropContainer.h" #include "../../gui/components/mouse/juce_MouseInputSource.h" #include "../../gui/components/keyboard/juce_KeyPressMappingSet.h" @@ -114,6 +115,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_win32_Misc.cpp" #include "juce_win32_ActiveXComponent.cpp" #include "juce_win32_QuickTimeMovieComponent.cpp" + #include "juce_win32_DirectShowComponent.cpp" #include "juce_win32_WebBrowserComponent.cpp" #include "juce_win32_OpenGLComponent.cpp" #include "juce_win32_AudioCDReader.cpp" diff --git a/src/native/windows/juce_win32_NativeIncludes.h b/src/native/windows/juce_win32_NativeIncludes.h index 520c4823f7..30fe9ea2ac 100644 --- a/src/native/windows/juce_win32_NativeIncludes.h +++ b/src/native/windows/juce_win32_NativeIncludes.h @@ -183,6 +183,14 @@ #import #endif +#if JUCE_DIRECTSHOW && JUCE_BUILD_NATIVE + #include +#endif + +#if JUCE_MEDIAFOUNDATION && JUCE_BUILD_NATIVE + #include +#endif + //============================================================================== #if JUCE_MSVC #pragma warning (pop) diff --git a/src/native/windows/juce_win32_OpenGLComponent.cpp b/src/native/windows/juce_win32_OpenGLComponent.cpp index bee75c7d01..9ac80d944d 100644 --- a/src/native/windows/juce_win32_OpenGLComponent.cpp +++ b/src/native/windows/juce_win32_OpenGLComponent.cpp @@ -287,10 +287,10 @@ public: return false; } - void updateWindowPosition (int x, int y, int w, int h, int) + void updateWindowPosition (const Rectangle& bounds) { SetWindowPos ((HWND) nativeWindow->getNativeHandle(), 0, - x, y, w, h, + bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); }