diff options
865 files changed, 39943 insertions, 4304 deletions
diff --git a/.gitignore b/.gitignore index ee878bb385..c80d0e2bf8 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ config.log *.rej *.orig *.bak +*.apk # Windows specific generated files *.exp @@ -113,6 +114,11 @@ config.log /addons/visualization.itunes/iTunes.mvis /addons/script.module.pil/ +# /xbmc/android +/xbmc/android/Makefile +/xbmc/android/activity/Makefile +/xbmc/android/loader/Makefile + # /xbmc/guilib/ /xbmc/guilib/Makefile /xbmc/guilib/*.obj @@ -497,6 +503,7 @@ lib/cmyth/Makefile # /xbmc/ /xbmc/DllPaths_generated.h +/xbmc/DllPaths_generated_android.h /xbmc/Makefile # /xbmc/addons/ @@ -522,12 +529,14 @@ lib/cmyth/Makefile /xbmc/cores/DllLoader/exports/build_wrapper.sh /xbmc/cores/DllLoader/exports/wrapper.def /xbmc/cores/DllLoader/Makefile +/xbmc/cores/DllLoader/exports/Makefile /xbmc/cores/Makefile /xbmc/cores/VideoRenderers/Makefile /xbmc/cores/dvdplayer/Makefile +/xbmc/cores/amlplayer/Makefile # /lib/ffmpeg/ /lib/ffmpeg/config.h @@ -1191,6 +1200,8 @@ lib/cmyth/Makefile /xbmc/visualizations/DirectXSpectrum/Debug (DirectX) /xbmc/visualizations/DirectXSpectrum/Release (DirectX) +xbmc/visualizations/EGLHelpers/Makefile + /xbmc/visualizations/Goom/Makefile /xbmc/visualizations/Goom/goom2k4-0/aclocal.m4 /xbmc/visualizations/Goom/goom2k4-0/configure diff --git a/Makefile.in b/Makefile.in index 9ffae7e047..3af486ca9d 100755..100644 --- a/Makefile.in +++ b/Makefile.in @@ -97,6 +97,7 @@ endif ifeq (@USE_OPENGLES@,1) DIRECTORY_ARCHIVES += xbmc/rendering/gles/rendering_gles.a DIRECTORY_ARCHIVES += xbmc/windowing/egl/windowing_egl.a +DIRECTORY_ARCHIVES += xbmc/visualizations/EGLHelpers/eglhelpers.a endif ifeq ($(findstring osx,@ARCH@),osx) @@ -107,12 +108,20 @@ DIRECTORY_ARCHIVES += xbmc/powermanagement/osx/powermanagement.a DIRECTORY_ARCHIVES += xbmc/storage/osx/storage.a DIRECTORY_ARCHIVES += xbmc/windowing/osx/windowing_osx.a else +ifeq (@USE_ANDROID@,1) +DIRECTORY_ARCHIVES += xbmc/input/linux/input_linux.a +DIRECTORY_ARCHIVES += xbmc/network/linux/network_linux.a +DIRECTORY_ARCHIVES += xbmc/powermanagement/android/powermanagement_android.a +DIRECTORY_ARCHIVES += xbmc/storage/android/storage_android.a +DIRECTORY_ARCHIVES += xbmc/windowing/X11/windowing_X11.a +else DIRECTORY_ARCHIVES += xbmc/input/linux/input_linux.a DIRECTORY_ARCHIVES += xbmc/network/linux/network_linux.a DIRECTORY_ARCHIVES += xbmc/powermanagement/linux/powermanagement_linux.a DIRECTORY_ARCHIVES += xbmc/storage/linux/storage_linux.a DIRECTORY_ARCHIVES += xbmc/windowing/X11/windowing_X11.a endif +endif ifeq ($(findstring freebsd,@ARCH@),freebsd) DIRECTORY_ARCHIVES += xbmc/freebsd/freebsd.a @@ -124,6 +133,16 @@ endif BIN_DIRS = $(dir $(DIRECTORY_ARCHIVES)) $(dir $(NWAOBJSXBMC)) +ifeq (@USE_ANDROID@,1) +DIRECTORY_ARCHIVES += xbmc/android/loader/AndroidDyload.a +DIRECTORY_ARCHIVES += xbmc/windowing/android/windowing_android.a +DIRECTORY_ARCHIVES += xbmc/android/activity/activity.a +endif + +ifeq (@USE_AMLPLAYER@,1) +DIRECTORY_ARCHIVES += xbmc/cores/amlplayer/amlplayer.a +endif + PAPCODECS_DIRS= \ lib/xbadpcm \ lib/nosefart \ @@ -149,6 +168,7 @@ LIB_DIRS=\ ifeq (@USE_MYSQL@,1) LIB_DIRS += lib/cmyth +CMYTH=cmyth endif SS_DIRS= @@ -196,6 +216,9 @@ DISTCLEAN_FILES=config.h config.log config.status tools/Linux/xbmc.sh \ ifeq (@USE_LIBXBMC@,1) FINAL_TARGETS+=libxbmc.so +ifeq (@USE_ANDROID@,1) +FINAL_TARGETS+=skins +endif else FINAL_TARGETS=xbmc.bin skins xbmc-xrandr endif @@ -254,7 +277,7 @@ lib/libapetag/.libs/libapetag.a: force $(MAKE) -C lib/libapetag lib/cpluff/libcpluff/.libs/libcpluff.a: force $(MAKE) -C lib/cpluff/libcpluff -system/libcpluff-@ARCH@.so: lib/cpluff/libcpluff/.libs/libcpluff.a +system/libcpluff-@ARCH@.so: lib/cpluff/libcpluff/.libs/libcpluff.a exports ifeq ($(findstring osx,@ARCH@), osx) ifeq (@ARCH@, arm-osx) $(CXX) $(LDFLAGS) -all_load -bundle -flat_namespace -undefined dynamic_lookup -read_only_relocs suppress -o $@ $< @@ -262,14 +285,23 @@ ifeq ($(findstring osx,@ARCH@), osx) $(CXX) $(LDFLAGS) -all_load -bundle -flat_namespace -undefined dynamic_lookup -lexpat $(BUNDLE1_O) -o $@ $< endif else - cp lib/cpluff/libcpluff/.libs/libcpluff.so $@ + $(CXX) $(LDFLAGS) -shared -o $@ -Wl,--whole-archive $< \ + -Wl,--no-whole-archive \ + `cat xbmc/cores/DllLoader/exports/wrapper.def` xbmc/cores/DllLoader/exports/wrapper.o -lexpat endif exports: xbmc/cores/DllLoader/exports/exports.a xbmc/cores/DllLoader/exports/util/exports_utils.a $(MAKE) -C xbmc/cores/DllLoader/exports wrapper.def dllloader: exports xbmc/cores/DllLoader/dllloader.a -$(VIS_DIRS) $(SS_DIRS): force exports +ifeq (@USE_OPENGLES@,1) +EGLHELPERS=xbmc/visualizations/EGLHelpers/eglhelpers.a +endif + +$(VIS_DIRS): force exports $(EGLHELPERS) + $(MAKE) -C $@ + +$(SS_DIRS): force exports $(MAKE) -C $@ visualizations: $(VIS_DIRS) @@ -280,7 +312,7 @@ libpython: dllloader $(MAKE) -C xbmc/interfaces/python $(MAKE) -C xbmc/interfaces/python/xbmcmodule dvdpcodecs: dllloader - $(MAKE) -C lib + $(MAKE) -C lib $(MAKE) -C lib/libdvd eventclients: ifeq ($(findstring osx,@ARCH@), osx) @@ -303,16 +335,16 @@ papcodecs: dllloader dvdpcodecs $(MAKE) -C lib/xbadpcm $(MAKE) -C lib/vgmstream $(MAKE) -C lib/timidity - $(MAKE) -C lib/nosefart + $(MAKE) -C lib/nosefart ifneq ($(findstring arm-osx,@ARCH@), arm-osx) - $(MAKE) -C lib/libsidplay2 + $(MAKE) -C lib/libsidplay2 endif ifeq (@USE_ASAP_CODEC@,1) ifneq ($(findstring osx,@ARCH@), osx) $(MAKE) -C lib/asap asap-xbmc endif endif - $(MAKE) -C lib/stsound/StSoundLibrary + $(MAKE) -C lib/stsound/StSoundLibrary ifeq ($(or $(findstring powerpc,@ARCH@),$(findstring x86_64-linux,@ARCH@),$(findstring arm, @ARCH@),$(findstring freebsd,@ARCH@)),) $(MAKE) -C lib/snesapu/SNES/SNESAPU endif @@ -321,10 +353,7 @@ imagelib: dllloader codecs: papcodecs dvdpcodecs -libs: libhdhomerun libid3tag imagelib libexif system/libcpluff-@ARCH@.so -ifeq (@USE_MYSQL@,1) -libs += cmyth -endif +libs: libhdhomerun libid3tag imagelib libexif system/libcpluff-@ARCH@.so $(CMYTH) externals: codecs libs visualizations screensavers @@ -356,13 +385,11 @@ endif OBJSXBMC:=$(filter-out $(DYNOBJSXBMC), $(OBJSXBMC)) -LIBS += @PYTHON_LDFLAGS@ - libxbmc.so: $(OBJSXBMC) $(DYNOBJSXBMC) $(NWAOBJSXBMC) ifeq ($(findstring osx,@ARCH@), osx) $(SILENT_LD) $(CXX) $(LDFLAGS) -bundle -o $@ -Wl,-all_load,-ObjC $(DYNOBJSXBMC) $(NWAOBJSXBMC) $(OBJSXBMC) $(LIBS) else - $(SILENT_LD) $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $@ -Wl,--whole-archive $(DYNOBJSXBMC) $(OBJSXBMC) -Wl,--no-whole-archive $(NWAOBJSXBMC) $(LIBS) + $(SILENT_LD) $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $@ -Wl,--whole-archive $(DYNOBJSXBMC) $(OBJSXBMC) -Wl,--no-whole-archive -Wl,--no-undefined $(NWAOBJSXBMC) $(LIBS) endif xbmc.bin: $(OBJSXBMC) $(DYNOBJSXBMC) $(NWAOBJSXBMC) @@ -402,16 +429,19 @@ ifeq ($(findstring osx,@ARCH@), osx) else install: install-binaries install-arch install-datas +apk: install + make -C tools/android/packaging + install-binaries: install-scripts - @echo "Copying XBMC binary to $(DESTDIR)$(libdir)/xbmc/xbmc.bin" + @echo "Copying XBMC binary to $(DESTDIR)$(libdir)/xbmc/" @install -d $(DESTDIR)$(libdir)/xbmc - @install xbmc.bin $(DESTDIR)$(libdir)/xbmc/xbmc.bin ifeq (1,@USE_XRANDR@) @install xbmc-xrandr $(DESTDIR)$(libdir)/xbmc/xbmc-xrandr endif ifeq (@USE_LIBXBMC@,1) @install libxbmc.so $(DESTDIR)$(libdir)/xbmc/libxbmc.so else + @install xbmc.bin $(DESTDIR)$(libdir)/xbmc/xbmc.bin @echo "You can run XBMC with the command 'xbmc'" endif endif @@ -426,7 +456,16 @@ ifeq ($(findstring freebsd,@ARCH@), freebsd) -exec install "{}" $(DESTDIR)$(libdir)/xbmc/"{}" \; \ -exec printf " -- %-75.75s\r" "{}" \; else - @find system addons -regextype posix-extended -type f -not -iregex ".*svn.*" -iregex ".*@ARCH@.*|.*\.vis|.*\.xbs" -exec install -D "{}" $(DESTDIR)$(libdir)/xbmc/"{}" \; -printf " -- %-75.75f\r" +ifeq ($(findstring Darwin,$(shell uname -s)),Darwin) + @find -E system addons -type f -not -iregex ".*svn.*" \ + -iregex ".*@ARCH@.*|.*\.vis|.*\.xbs" \ + -exec sh -c "install -d \"$(DESTDIR)$(libdir)/xbmc/\`dirname '{}'\`\"" \; \ + -and \ + -exec install "{}" $(DESTDIR)$(libdir)/xbmc/"{}" \; \ + -exec printf " -- %-75.75s\r" "{}" \; +else + @find system addons -regextype posix-extended -type f -not -iregex ".*svn.*" -iregex ".*\.so|.*\.vis|.*\.xbs" -exec install -D "{}" $(DESTDIR)$(libdir)/xbmc/"{}" \; -printf " -- %-75.75f\r" +endif endif install-scripts: @@ -456,8 +495,17 @@ ifeq ($(findstring bsd,@ARCH@), bsd) -exec install -m 0644 "{}" $(DESTDIR)$(datarootdir)/xbmc/"{}" \; \ -exec printf " -- %-75.75s\r" "{}" \; else +ifeq ($(findstring Darwin,$(shell uname -s)),Darwin) + @find -E addons language media sounds userdata system -type f \ + -not -iregex ".*@ARCH@.*|.*\.vis|.*\.xbs|.*svn.*|.*\.so|.*\.dll" \ + -exec sh -c "install -d \"$(DESTDIR)$(datarootdir)/xbmc/\`dirname '{}'\`\"" \; \ + -and \ + -exec install -m 0644 "{}" $(DESTDIR)$(datarootdir)/xbmc/"{}" \; \ + -exec printf " -- %-75.75s\r" "{}" \; +else @find addons language media sounds userdata system -regextype posix-extended -type f -not -iregex ".*@ARCH@.*|.*\.vis|.*\.xbs|.*svn.*|.*\.so|.*\.dll" -exec install -D -m 0644 "{}" $(DESTDIR)$(datarootdir)/xbmc/"{}" \; -printf " -- %-75.75f\r" endif +endif @# Icons and links @install -d $(DESTDIR)$(datarootdir)/applications @install tools/Linux/xbmc.desktop $(DESTDIR)$(datarootdir)/applications/xbmc.desktop @@ -482,13 +530,13 @@ clean-eventclients: for d in $(EC_DIRS); do if test -f $$d/Makefile; then $(MAKE) -C $$d clean; fi; done clean-xbmctex: for d in $(XBMCTEX_DIRS); do if test -f $$d/Makefile; then $(MAKE) -C $$d clean; fi; done -clean-dvdpcodecs: +clean-dvdpcodecs: for d in $(DVDPCODECS_DIRS); do if test -f $$d/Makefile; then $(MAKE) -C $$d clean; fi; done clean-papcodecs: for d in $(PAPCODECS_DIRS); do if test -f $$d/Makefile; then $(MAKE) -C $$d clean; fi; done -clean-libs: +clean-libs: for d in $(LIB_DIRS); do if test -f $$d/Makefile; then $(MAKE) -C $$d clean; fi; done -clean-screensavers: +clean-screensavers: for d in $(SS_DIRS); do if test -f $$d/Makefile; then $(MAKE) -C $$d clean; fi; done clean-visualisations: for d in $(VIS_DIRS); do if test -f $$d/Makefile; then $(MAKE) -C $$d clean; fi; done diff --git a/Makefile.include.in b/Makefile.include.in index 2ef3a640a7..a517dd269e 100644 --- a/Makefile.include.in +++ b/Makefile.include.in @@ -1,4 +1,4 @@ -AR=ar +AR=@AR@ ARFLAGS=crus RM=rm -rf SHELL=@SHELL@ diff --git a/XBMC-ATV2.xcodeproj/project.pbxproj b/XBMC-ATV2.xcodeproj/project.pbxproj index 54760b5d1a..92959215be 100644 --- a/XBMC-ATV2.xcodeproj/project.pbxproj +++ b/XBMC-ATV2.xcodeproj/project.pbxproj @@ -22,6 +22,10 @@ 36A9445915821F8300727135 /* DatabaseUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9445715821F8300727135 /* DatabaseUtils.cpp */; }; 36A9445D15821FAC00727135 /* SortUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9445B15821FAB00727135 /* SortUtils.cpp */; }; 36A9465315AA269B00727135 /* DirectoryNodeTags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9465115AA269B00727135 /* DirectoryNodeTags.cpp */; }; + 36A9468415CF213000727135 /* DbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9468215CF213000727135 /* DbUrl.cpp */; }; + 36A9468815CF214300727135 /* VideoDbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9468615CF214300727135 /* VideoDbUrl.cpp */; }; + 36A9468B15CF215300727135 /* UrlOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9468915CF215300727135 /* UrlOptions.cpp */; }; + 36A9468E15CF217400727135 /* MusicDbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9468C15CF217400727135 /* MusicDbUrl.cpp */; }; 4D5D2E131301753F006ABC13 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D5D2E121301753F006ABC13 /* CFNetwork.framework */; }; 7C0A7ECD13A5DBF900AFC2BD /* AppParamParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7ECB13A5DBF900AFC2BD /* AppParamParser.cpp */; }; 7C0A7FC813A9E75400AFC2BD /* DirtyRegionSolvers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7FC413A9E75400AFC2BD /* DirtyRegionSolvers.cpp */; }; @@ -56,6 +60,8 @@ DF527783151BAFD600B5B63B /* WebSocketV8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF52777D151BAFD600B5B63B /* WebSocketV8.cpp */; }; DF527788151BAFEE00B5B63B /* Base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF527784151BAFEE00B5B63B /* Base64.cpp */; }; DF527789151BAFEE00B5B63B /* HttpResponse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF527786151BAFEE00B5B63B /* HttpResponse.cpp */; }; + DF830D4815BB2CFC00602BE6 /* GUIKeyboardFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF830D4515BB2CFC00602BE6 /* GUIKeyboardFactory.cpp */; }; + DF830D4B15BB2D2300602BE6 /* GUIDialogKeyboardGeneric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF830D4915BB2D2300602BE6 /* GUIDialogKeyboardGeneric.cpp */; }; DF93D7701444B09C007C6459 /* AFPFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF93D7381444B09C007C6459 /* AFPFile.cpp */; }; DF93D7731444B09C007C6459 /* CDDAFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF93D73E1444B09C007C6459 /* CDDAFile.cpp */; }; DF93D7741444B09C007C6459 /* CurlFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF93D7401444B09C007C6459 /* CurlFile.cpp */; }; @@ -333,7 +339,6 @@ F56C7959131EC154000AD0F6 /* GUIDialogFileBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C736F131EC151000AD0F6 /* GUIDialogFileBrowser.cpp */; }; F56C795A131EC154000AD0F6 /* GUIDialogGamepad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C7371131EC151000AD0F6 /* GUIDialogGamepad.cpp */; }; F56C795B131EC154000AD0F6 /* GUIDialogKaiToast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C7373131EC151000AD0F6 /* GUIDialogKaiToast.cpp */; }; - F56C795C131EC154000AD0F6 /* GUIDialogKeyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C7375131EC151000AD0F6 /* GUIDialogKeyboard.cpp */; }; F56C795D131EC154000AD0F6 /* GUIDialogMediaSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C7377131EC151000AD0F6 /* GUIDialogMediaSource.cpp */; }; F56C795E131EC154000AD0F6 /* GUIDialogMuteBug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C7379131EC151000AD0F6 /* GUIDialogMuteBug.cpp */; }; F56C795F131EC154000AD0F6 /* GUIDialogNumeric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C737B131EC151000AD0F6 /* GUIDialogNumeric.cpp */; }; @@ -1012,6 +1017,14 @@ 36A9445C15821FAB00727135 /* SortUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SortUtils.h; sourceTree = "<group>"; }; 36A9465115AA269B00727135 /* DirectoryNodeTags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectoryNodeTags.cpp; sourceTree = "<group>"; }; 36A9465215AA269B00727135 /* DirectoryNodeTags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryNodeTags.h; sourceTree = "<group>"; }; + 36A9468215CF213000727135 /* DbUrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DbUrl.cpp; sourceTree = "<group>"; }; + 36A9468315CF213000727135 /* DbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DbUrl.h; sourceTree = "<group>"; }; + 36A9468615CF214300727135 /* VideoDbUrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoDbUrl.cpp; sourceTree = "<group>"; }; + 36A9468715CF214300727135 /* VideoDbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoDbUrl.h; sourceTree = "<group>"; }; + 36A9468915CF215300727135 /* UrlOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UrlOptions.cpp; sourceTree = "<group>"; }; + 36A9468A15CF215300727135 /* UrlOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UrlOptions.h; sourceTree = "<group>"; }; + 36A9468C15CF217400727135 /* MusicDbUrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MusicDbUrl.cpp; sourceTree = "<group>"; }; + 36A9468D15CF217400727135 /* MusicDbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MusicDbUrl.h; sourceTree = "<group>"; }; 4D5D2E121301753F006ABC13 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 7C0A7ECB13A5DBF900AFC2BD /* AppParamParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppParamParser.cpp; sourceTree = "<group>"; }; 7C0A7ECC13A5DBF900AFC2BD /* AppParamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppParamParser.h; sourceTree = "<group>"; }; @@ -1024,9 +1037,9 @@ 7C0A7FCB13A9E76E00AFC2BD /* GUIWindowDebugInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIWindowDebugInfo.h; sourceTree = "<group>"; }; 7C0B9908154B80200065A238 /* AEDeviceInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AEDeviceInfo.cpp; sourceTree = "<group>"; }; 7C0B9909154B80200065A238 /* AEDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEDeviceInfo.h; sourceTree = "<group>"; }; - 7C1A494015A968D6004AF4A4 /* SaveFileStateJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveFileStateJob.h; sourceTree = "<group>"; }; 7C1A493B15A968BA004AF4A4 /* SeekHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SeekHandler.cpp; sourceTree = "<group>"; }; 7C1A493C15A968BA004AF4A4 /* SeekHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SeekHandler.h; sourceTree = "<group>"; }; + 7C1A494015A968D6004AF4A4 /* SaveFileStateJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveFileStateJob.h; sourceTree = "<group>"; }; 7C1A89B9152671FB00C63311 /* TextureCacheJob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureCacheJob.cpp; sourceTree = "<group>"; }; 7C1A89BA152671FB00C63311 /* TextureCacheJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCacheJob.h; sourceTree = "<group>"; }; 7C1D698915A8142F00658B65 /* DatabaseManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseManager.cpp; sourceTree = "<group>"; }; @@ -1083,6 +1096,11 @@ DF527785151BAFEE00B5B63B /* Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Base64.h; sourceTree = "<group>"; }; DF527786151BAFEE00B5B63B /* HttpResponse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HttpResponse.cpp; sourceTree = "<group>"; }; DF527787151BAFEE00B5B63B /* HttpResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HttpResponse.h; sourceTree = "<group>"; }; + DF830D4415BB2CFC00602BE6 /* GUIKeyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIKeyboard.h; sourceTree = "<group>"; }; + DF830D4515BB2CFC00602BE6 /* GUIKeyboardFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIKeyboardFactory.cpp; sourceTree = "<group>"; }; + DF830D4615BB2CFC00602BE6 /* GUIKeyboardFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIKeyboardFactory.h; sourceTree = "<group>"; }; + DF830D4915BB2D2300602BE6 /* GUIDialogKeyboardGeneric.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogKeyboardGeneric.cpp; sourceTree = "<group>"; }; + DF830D4A15BB2D2300602BE6 /* GUIDialogKeyboardGeneric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogKeyboardGeneric.h; sourceTree = "<group>"; }; DF93D7381444B09C007C6459 /* AFPFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AFPFile.cpp; sourceTree = "<group>"; }; DF93D7391444B09C007C6459 /* AFPFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFPFile.h; sourceTree = "<group>"; }; DF93D73E1444B09C007C6459 /* CDDAFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDDAFile.cpp; sourceTree = "<group>"; }; @@ -1169,7 +1187,6 @@ DFB662A215376810006B8FF1 /* ICoreAudioSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ICoreAudioSource.h; path = CoreAudio/ICoreAudioSource.h; sourceTree = "<group>"; }; DFB662B015376810006B8FF1 /* AE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AE.h; sourceTree = "<group>"; }; DFB662B115376810006B8FF1 /* AEEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEEncoder.h; sourceTree = "<group>"; }; - DFB662B215376810006B8FF1 /* AEPostProc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEPostProc.h; sourceTree = "<group>"; }; DFB662B315376810006B8FF1 /* AESink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESink.h; sourceTree = "<group>"; }; DFB662B415376810006B8FF1 /* AESound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESound.h; sourceTree = "<group>"; }; DFB662B515376810006B8FF1 /* AEStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEStream.h; sourceTree = "<group>"; }; @@ -1748,8 +1765,6 @@ F56C7372131EC151000AD0F6 /* GUIDialogGamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogGamepad.h; sourceTree = "<group>"; }; F56C7373131EC151000AD0F6 /* GUIDialogKaiToast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogKaiToast.cpp; sourceTree = "<group>"; }; F56C7374131EC151000AD0F6 /* GUIDialogKaiToast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogKaiToast.h; sourceTree = "<group>"; }; - F56C7375131EC151000AD0F6 /* GUIDialogKeyboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogKeyboard.cpp; sourceTree = "<group>"; }; - F56C7376131EC151000AD0F6 /* GUIDialogKeyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogKeyboard.h; sourceTree = "<group>"; }; F56C7377131EC151000AD0F6 /* GUIDialogMediaSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogMediaSource.cpp; sourceTree = "<group>"; }; F56C7378131EC151000AD0F6 /* GUIDialogMediaSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogMediaSource.h; sourceTree = "<group>"; }; F56C7379131EC151000AD0F6 /* GUIDialogMuteBug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogMuteBug.cpp; sourceTree = "<group>"; }; @@ -3208,7 +3223,6 @@ children = ( DFB662B015376810006B8FF1 /* AE.h */, DFB662B115376810006B8FF1 /* AEEncoder.h */, - DFB662B215376810006B8FF1 /* AEPostProc.h */, DFB662B315376810006B8FF1 /* AESink.h */, DFB662B415376810006B8FF1 /* AESound.h */, DFB662B515376810006B8FF1 /* AEStream.h */, @@ -3572,6 +3586,8 @@ F56C77D9131EC154000AD0F6 /* CueDocument.h */, 7C1D698915A8142F00658B65 /* DatabaseManager.cpp */, 7C1D698A15A8142F00658B65 /* DatabaseManager.h */, + 36A9468215CF213000727135 /* DbUrl.cpp */, + 36A9468315CF213000727135 /* DbUrl.h */, F56C77DC131EC154000AD0F6 /* DynamicDll.cpp */, F56C77DD131EC154000AD0F6 /* DynamicDll.h */, F56C77DE131EC154000AD0F6 /* Favourites.cpp */, @@ -4196,8 +4212,8 @@ F56C7372131EC151000AD0F6 /* GUIDialogGamepad.h */, F56C7373131EC151000AD0F6 /* GUIDialogKaiToast.cpp */, F56C7374131EC151000AD0F6 /* GUIDialogKaiToast.h */, - F56C7375131EC151000AD0F6 /* GUIDialogKeyboard.cpp */, - F56C7376131EC151000AD0F6 /* GUIDialogKeyboard.h */, + DF830D4915BB2D2300602BE6 /* GUIDialogKeyboardGeneric.cpp */, + DF830D4A15BB2D2300602BE6 /* GUIDialogKeyboardGeneric.h */, F56C7377131EC151000AD0F6 /* GUIDialogMediaSource.cpp */, F56C7378131EC151000AD0F6 /* GUIDialogMediaSource.h */, F56C7379131EC151000AD0F6 /* GUIDialogMuteBug.cpp */, @@ -4617,6 +4633,9 @@ F56C74C1131EC152000AD0F6 /* GUIIncludes.h */, F56C751C131EC152000AD0F6 /* GUIInfoTypes.cpp */, F56C74C2131EC152000AD0F6 /* GUIInfoTypes.h */, + DF830D4415BB2CFC00602BE6 /* GUIKeyboard.h */, + DF830D4515BB2CFC00602BE6 /* GUIKeyboardFactory.cpp */, + DF830D4615BB2CFC00602BE6 /* GUIKeyboardFactory.h */, F56C751D131EC152000AD0F6 /* GUILabel.cpp */, F56C74C3131EC152000AD0F6 /* GUILabel.h */, F56C751E131EC152000AD0F6 /* GUILabelControl.cpp */, @@ -4901,6 +4920,8 @@ F56C7640131EC153000AD0F6 /* LastFmManager.h */, F56C7641131EC153000AD0F6 /* MusicDatabase.cpp */, F56C7642131EC153000AD0F6 /* MusicDatabase.h */, + 36A9468C15CF217400727135 /* MusicDbUrl.cpp */, + 36A9468D15CF217400727135 /* MusicDbUrl.h */, F56C7643131EC153000AD0F6 /* MusicInfoLoader.cpp */, F56C7644131EC153000AD0F6 /* MusicInfoLoader.h */, F56C7645131EC153000AD0F6 /* Song.cpp */, @@ -5468,6 +5489,8 @@ F56C776D131EC154000AD0F6 /* TuxBoxUtil.h */, F56C7714131EC153000AD0F6 /* URIUtils.cpp */, F56C7715131EC154000AD0F6 /* URIUtils.h */, + 36A9468915CF215300727135 /* UrlOptions.cpp */, + 36A9468A15CF215300727135 /* UrlOptions.h */, F56C776E131EC154000AD0F6 /* Variant.cpp */, F56C776F131EC154000AD0F6 /* Variant.h */, F56C7770131EC154000AD0F6 /* Weather.cpp */, @@ -5495,6 +5518,8 @@ F56C77A0131EC154000AD0F6 /* TeletextDefines.h */, F56C77A1131EC154000AD0F6 /* VideoDatabase.cpp */, F56C77A2131EC154000AD0F6 /* VideoDatabase.h */, + 36A9468615CF214300727135 /* VideoDbUrl.cpp */, + 36A9468715CF214300727135 /* VideoDbUrl.h */, F56C77A3131EC154000AD0F6 /* VideoInfoDownloader.cpp */, F56C77A4131EC154000AD0F6 /* VideoInfoDownloader.h */, F56C77A5131EC154000AD0F6 /* VideoInfoScanner.cpp */, @@ -6238,7 +6263,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ ${XCODE_VERSION_MINOR} -gt 400 ]\nthen\n TARGET_OUTPUT_DIR=\"${PROJECT_DIR}/build/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}\"\n mkdir -p \"${TARGET_OUTPUT_DIR}\"\n\n ln -sf \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\" \"${TARGET_OUTPUT_DIR}/\"\n ln -sf \"${BUILT_PRODUCTS_DIR}/${DWARF_DSYM_FILE_NAME}\" \"${TARGET_OUTPUT_DIR}/\"\nfi"; + shellScript = "if [ ${XCODE_VERSION_MINOR} -gt 400 ]\nthen\n TARGET_OUTPUT_DIR=\"${PROJECT_DIR}/build/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}\"\n mkdir -p \"${TARGET_OUTPUT_DIR}\"\n if [ \"${BUILT_PRODUCTS_DIR}\" != \"${TARGET_OUTPUT_DIR}\" ]\n then\n rm -rf \"${TARGET_OUTPUT_DIR}/${FULL_PRODUCT_NAME}\"\n rm -rf \"${TARGET_OUTPUT_DIR}/${DWARF_DSYM_FILE_NAME}\"\n ln -s \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\" \"${TARGET_OUTPUT_DIR}/\" || true\n ln -s \"${BUILT_PRODUCTS_DIR}/${DWARF_DSYM_FILE_NAME}\" \"${TARGET_OUTPUT_DIR}/\" || true\n fi\nfi"; }; F589B48B128A696700D8079E /* copy root files */ = { isa = PBXShellScriptBuildPhase; @@ -6480,7 +6505,6 @@ F56C7959131EC154000AD0F6 /* GUIDialogFileBrowser.cpp in Sources */, F56C795A131EC154000AD0F6 /* GUIDialogGamepad.cpp in Sources */, F56C795B131EC154000AD0F6 /* GUIDialogKaiToast.cpp in Sources */, - F56C795C131EC154000AD0F6 /* GUIDialogKeyboard.cpp in Sources */, F56C795D131EC154000AD0F6 /* GUIDialogMediaSource.cpp in Sources */, F56C795E131EC154000AD0F6 /* GUIDialogMuteBug.cpp in Sources */, F56C795F131EC154000AD0F6 /* GUIDialogNumeric.cpp in Sources */, @@ -7221,6 +7245,12 @@ 36A9465315AA269B00727135 /* DirectoryNodeTags.cpp in Sources */, 7C1D698B15A8142F00658B65 /* DatabaseManager.cpp in Sources */, 7C1A493D15A968BA004AF4A4 /* SeekHandler.cpp in Sources */, + DF830D4815BB2CFC00602BE6 /* GUIKeyboardFactory.cpp in Sources */, + DF830D4B15BB2D2300602BE6 /* GUIDialogKeyboardGeneric.cpp in Sources */, + 36A9468415CF213000727135 /* DbUrl.cpp in Sources */, + 36A9468815CF214300727135 /* VideoDbUrl.cpp in Sources */, + 36A9468B15CF215300727135 /* UrlOptions.cpp in Sources */, + 36A9468E15CF217400727135 /* MusicDbUrl.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -7310,6 +7340,10 @@ "\"$(SRCROOT)/lib/ffmpeg/libpostproc\"", "\"$(SRCROOT)/lib/ffmpeg/libswscale\"", ); + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-Wreorder", + ); OTHER_LDFLAGS = ( "-Wl,-headerpad_max_install_names", "-Wl,-undefined,dynamic_lookup", @@ -7349,7 +7383,7 @@ PRODUCT_NAME = XBMC; TARGETED_DEVICE_FAMILY = "2,3"; USER_HEADER_SEARCH_PATHS = "$XBMC_DEPENDS/include $XBMC_DEPENDS/include/mysql $XBMC_DEPENDS/include/freetype2 $XBMC_DEPENDS/include/python2.6"; - WARNING_CFLAGS = "-Wreorder"; + WARNING_CFLAGS = ""; WRAPPER_EXTENSION = frappliance; XBMC_DEPENDS = "/Users/Shared/xbmc-depends/$(SDK_NAME)_$(ARCHS)"; }; @@ -7427,6 +7461,10 @@ "\"$(SRCROOT)/lib/ffmpeg/libpostproc\"", "\"$(SRCROOT)/lib/ffmpeg/libswscale\"", ); + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-Wreorder", + ); OTHER_LDFLAGS = ( "-Wl,-headerpad_max_install_names", "-Wl,-undefined,dynamic_lookup", @@ -7466,7 +7504,7 @@ PRODUCT_NAME = XBMC; TARGETED_DEVICE_FAMILY = "2,3"; USER_HEADER_SEARCH_PATHS = "$XBMC_DEPENDS/include $XBMC_DEPENDS/include/mysql $XBMC_DEPENDS/include/freetype2 $XBMC_DEPENDS/include/python2.6"; - WARNING_CFLAGS = "-Wreorder"; + WARNING_CFLAGS = ""; WRAPPER_EXTENSION = frappliance; XBMC_DEPENDS = "/Users/Shared/xbmc-depends/$(SDK_NAME)_$(ARCHS)"; }; diff --git a/XBMC-IOS.xcodeproj/project.pbxproj b/XBMC-IOS.xcodeproj/project.pbxproj index 043412dd7e..cfb63ee130 100644 --- a/XBMC-IOS.xcodeproj/project.pbxproj +++ b/XBMC-IOS.xcodeproj/project.pbxproj @@ -23,6 +23,10 @@ 36A9444E15821F2C00727135 /* DatabaseUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9444C15821F2C00727135 /* DatabaseUtils.cpp */; }; 36A9445215821F5300727135 /* SortUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9445015821F5300727135 /* SortUtils.cpp */; }; 36A9465B15AA26BC00727135 /* DirectoryNodeTags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9465915AA26BC00727135 /* DirectoryNodeTags.cpp */; }; + 36A9467415CF208B00727135 /* MusicDbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9467215CF208B00727135 /* MusicDbUrl.cpp */; }; + 36A9467815CF20A500727135 /* UrlOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9467615CF20A500727135 /* UrlOptions.cpp */; }; + 36A9467B15CF20BD00727135 /* VideoDbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9467915CF20BD00727135 /* VideoDbUrl.cpp */; }; + 36A9467E15CF20E100727135 /* DbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9467C15CF20E100727135 /* DbUrl.cpp */; }; 4D5D2E1E1301758F006ABC13 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D5D2E1D1301758F006ABC13 /* CFNetwork.framework */; }; 7C0A7EDE13A5DC2800AFC2BD /* AppParamParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7EDC13A5DC2800AFC2BD /* AppParamParser.cpp */; }; 7C0A7F9D13A9E70800AFC2BD /* GUIWindowDebugInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7F9B13A9E70800AFC2BD /* GUIWindowDebugInfo.cpp */; }; @@ -43,6 +47,7 @@ C893606F152C870600812418 /* monitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C893606D152C870600812418 /* monitor.cpp */; }; C8936072152C871400812418 /* PythonMonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C8936070152C871400812418 /* PythonMonitor.cpp */; }; C8EC5D26136953E100CCC10D /* XBMC_keytable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C8EC5D24136953E100CCC10D /* XBMC_keytable.cpp */; }; + DF02A888153382A60084754E /* IOSKeyboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = DF02A887153382A60084754E /* IOSKeyboard.mm */; }; DF0DF18013A3AF9F008ED511 /* NFSDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0DF17D13A3AF9F008ED511 /* NFSDirectory.cpp */; }; DF2E329415509B2C000F5772 /* XbmcContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2E329215509B2C000F5772 /* XbmcContext.cpp */; }; DF33C29415509BF50046CDCB /* ilog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF33C29115509BF50046CDCB /* ilog.cpp */; }; @@ -56,6 +61,8 @@ DF52775A151BAF8200B5B63B /* WebSocketV8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF527754151BAF8200B5B63B /* WebSocketV8.cpp */; }; DF527760151BAFA000B5B63B /* Base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF52775C151BAFA000B5B63B /* Base64.cpp */; }; DF527761151BAFA000B5B63B /* HttpResponse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF52775E151BAFA000B5B63B /* HttpResponse.cpp */; }; + DF830C9515BB20FC00602BE6 /* GUIDialogKeyboardGeneric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF830C9315BB20FC00602BE6 /* GUIDialogKeyboardGeneric.cpp */; }; + DF830C9E15BB215500602BE6 /* GUIKeyboardFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF830C9C15BB215500602BE6 /* GUIKeyboardFactory.cpp */; }; DF93D7CF1444B105007C6459 /* AFPFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF93D7971444B105007C6459 /* AFPFile.cpp */; }; DF93D7D21444B105007C6459 /* CDDAFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF93D79D1444B105007C6459 /* CDDAFile.cpp */; }; DF93D7D31444B105007C6459 /* CurlFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF93D79F1444B105007C6459 /* CurlFile.cpp */; }; @@ -121,6 +128,7 @@ DFDB00251516403A005079A4 /* DirectoryCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFDB001E1516403A005079A4 /* DirectoryCache.cpp */; }; DFDB00261516403A005079A4 /* FileCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFDB00201516403A005079A4 /* FileCache.cpp */; }; DFDB00271516403A005079A4 /* MemBufferCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFDB00221516403A005079A4 /* MemBufferCache.cpp */; }; + DFE3505B1532535500F84CAA /* IOSKeyboardView.mm in Sources */ = {isa = PBXBuildFile; fileRef = DFE3505A1532535500F84CAA /* IOSKeyboardView.mm */; }; DFFD59401506B5B10088DE4B /* IOSEAGLView.mm in Sources */ = {isa = PBXBuildFile; fileRef = DFFD593F1506B5B10088DE4B /* IOSEAGLView.mm */; }; DFFEFBEE15160739001294DC /* IOSScreenManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = DFFEFBED15160739001294DC /* IOSScreenManager.mm */; }; DFFEFC0415160808001294DC /* IOSExternalTouchController.mm in Sources */ = {isa = PBXBuildFile; fileRef = DFFEFC0315160808001294DC /* IOSExternalTouchController.mm */; }; @@ -423,7 +431,6 @@ F56C8943131F42ED000AD0F6 /* GUIDialogFileBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C8352131F42E8000AD0F6 /* GUIDialogFileBrowser.cpp */; }; F56C8944131F42ED000AD0F6 /* GUIDialogGamepad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C8354131F42E8000AD0F6 /* GUIDialogGamepad.cpp */; }; F56C8945131F42ED000AD0F6 /* GUIDialogKaiToast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C8356131F42E8000AD0F6 /* GUIDialogKaiToast.cpp */; }; - F56C8946131F42ED000AD0F6 /* GUIDialogKeyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C8358131F42E8000AD0F6 /* GUIDialogKeyboard.cpp */; }; F56C8947131F42ED000AD0F6 /* GUIDialogMediaSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C835A131F42E8000AD0F6 /* GUIDialogMediaSource.cpp */; }; F56C8948131F42ED000AD0F6 /* GUIDialogMuteBug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C835C131F42E8000AD0F6 /* GUIDialogMuteBug.cpp */; }; F56C8949131F42ED000AD0F6 /* GUIDialogNumeric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C835E131F42E8000AD0F6 /* GUIDialogNumeric.cpp */; }; @@ -785,7 +792,6 @@ F56C8ADA131F42ED000AD0F6 /* PowerManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C869F131F42EB000AD0F6 /* PowerManager.cpp */; }; F56C8ADB131F42ED000AD0F6 /* GUIViewStatePrograms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86A2131F42EB000AD0F6 /* GUIViewStatePrograms.cpp */; }; F56C8ADC131F42ED000AD0F6 /* GUIWindowPrograms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86A4131F42EB000AD0F6 /* GUIWindowPrograms.cpp */; }; - F56C8ADE131F42ED000AD0F6 /* Shortcut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86A8131F42EB000AD0F6 /* Shortcut.cpp */; }; F56C8ADF131F42ED000AD0F6 /* RenderSystemGLES.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86AC131F42EB000AD0F6 /* RenderSystemGLES.cpp */; }; F56C8AE0131F42ED000AD0F6 /* RenderSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86AE131F42EB000AD0F6 /* RenderSystem.cpp */; }; F56C8AE1131F42ED000AD0F6 /* GUIDialogContentSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86B2131F42EB000AD0F6 /* GUIDialogContentSettings.cpp */; }; @@ -1013,6 +1019,14 @@ 36A9445115821F5300727135 /* SortUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SortUtils.h; sourceTree = "<group>"; }; 36A9465915AA26BC00727135 /* DirectoryNodeTags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectoryNodeTags.cpp; sourceTree = "<group>"; }; 36A9465A15AA26BC00727135 /* DirectoryNodeTags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryNodeTags.h; sourceTree = "<group>"; }; + 36A9467215CF208B00727135 /* MusicDbUrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MusicDbUrl.cpp; sourceTree = "<group>"; }; + 36A9467315CF208B00727135 /* MusicDbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MusicDbUrl.h; sourceTree = "<group>"; }; + 36A9467615CF20A500727135 /* UrlOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UrlOptions.cpp; sourceTree = "<group>"; }; + 36A9467715CF20A500727135 /* UrlOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UrlOptions.h; sourceTree = "<group>"; }; + 36A9467915CF20BD00727135 /* VideoDbUrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoDbUrl.cpp; sourceTree = "<group>"; }; + 36A9467A15CF20BD00727135 /* VideoDbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoDbUrl.h; sourceTree = "<group>"; }; + 36A9467C15CF20E100727135 /* DbUrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DbUrl.cpp; sourceTree = "<group>"; }; + 36A9467D15CF20E100727135 /* DbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DbUrl.h; sourceTree = "<group>"; }; 4D5D2E1D1301758F006ABC13 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 7C0A7EDC13A5DC2800AFC2BD /* AppParamParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppParamParser.cpp; sourceTree = "<group>"; }; 7C0A7EDD13A5DC2800AFC2BD /* AppParamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppParamParser.h; sourceTree = "<group>"; }; @@ -1025,9 +1039,9 @@ 7C0A7FB113A9E72E00AFC2BD /* DirtyRegionTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirtyRegionTracker.h; sourceTree = "<group>"; }; 7C0B98F7154B7FF30065A238 /* AEDeviceInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AEDeviceInfo.cpp; sourceTree = "<group>"; }; 7C0B98F8154B7FF30065A238 /* AEDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEDeviceInfo.h; sourceTree = "<group>"; }; - 7C1A495415A96908004AF4A4 /* SaveFileStateJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveFileStateJob.h; sourceTree = "<group>"; }; 7C1A495115A968FB004AF4A4 /* SeekHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SeekHandler.cpp; sourceTree = "<group>"; }; 7C1A495215A968FB004AF4A4 /* SeekHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SeekHandler.h; sourceTree = "<group>"; }; + 7C1A495415A96908004AF4A4 /* SaveFileStateJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveFileStateJob.h; sourceTree = "<group>"; }; 7C1A89CC1526722200C63311 /* TextureCacheJob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureCacheJob.cpp; sourceTree = "<group>"; }; 7C1A89CD1526722200C63311 /* TextureCacheJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCacheJob.h; sourceTree = "<group>"; }; 7C1D697615A8141000658B65 /* DatabaseManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseManager.cpp; sourceTree = "<group>"; }; @@ -1056,6 +1070,10 @@ C8936071152C871400812418 /* PythonMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PythonMonitor.h; sourceTree = "<group>"; }; C8EC5D24136953E100CCC10D /* XBMC_keytable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XBMC_keytable.cpp; sourceTree = "<group>"; }; C8EC5D25136953E100CCC10D /* XBMC_keytable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBMC_keytable.h; sourceTree = "<group>"; }; + DF02A831153373EC0084754E /* GUIKeyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIKeyboard.h; sourceTree = "<group>"; }; + DF02A86D153381990084754E /* GUIKeyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIKeyboard.h; sourceTree = "<group>"; }; + DF02A881153382560084754E /* IOSKeyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSKeyboard.h; sourceTree = "<group>"; }; + DF02A887153382A60084754E /* IOSKeyboard.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IOSKeyboard.mm; sourceTree = "<group>"; }; DF0DF17D13A3AF9F008ED511 /* NFSDirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NFSDirectory.cpp; sourceTree = "<group>"; }; DF0DF17E13A3AF9F008ED511 /* NFSDirectory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NFSDirectory.h; sourceTree = "<group>"; }; DF2E329215509B2C000F5772 /* XbmcContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XbmcContext.cpp; sourceTree = "<group>"; }; @@ -1082,6 +1100,10 @@ DF52775D151BAFA000B5B63B /* Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Base64.h; sourceTree = "<group>"; }; DF52775E151BAFA000B5B63B /* HttpResponse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HttpResponse.cpp; sourceTree = "<group>"; }; DF52775F151BAFA000B5B63B /* HttpResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HttpResponse.h; sourceTree = "<group>"; }; + DF830C9315BB20FC00602BE6 /* GUIDialogKeyboardGeneric.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogKeyboardGeneric.cpp; sourceTree = "<group>"; }; + DF830C9415BB20FC00602BE6 /* GUIDialogKeyboardGeneric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogKeyboardGeneric.h; sourceTree = "<group>"; }; + DF830C9C15BB215500602BE6 /* GUIKeyboardFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIKeyboardFactory.cpp; sourceTree = "<group>"; }; + DF830C9D15BB215500602BE6 /* GUIKeyboardFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIKeyboardFactory.h; sourceTree = "<group>"; }; DF93D7971444B105007C6459 /* AFPFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AFPFile.cpp; sourceTree = "<group>"; }; DF93D7981444B105007C6459 /* AFPFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFPFile.h; sourceTree = "<group>"; }; DF93D79D1444B105007C6459 /* CDDAFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDDAFile.cpp; sourceTree = "<group>"; }; @@ -1168,7 +1190,6 @@ DFB6621C15376791006B8FF1 /* ICoreAudioSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ICoreAudioSource.h; path = CoreAudio/ICoreAudioSource.h; sourceTree = "<group>"; }; DFB6622A15376791006B8FF1 /* AE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AE.h; sourceTree = "<group>"; }; DFB6622B15376791006B8FF1 /* AEEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEEncoder.h; sourceTree = "<group>"; }; - DFB6622C15376791006B8FF1 /* AEPostProc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEPostProc.h; sourceTree = "<group>"; }; DFB6622D15376791006B8FF1 /* AESink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESink.h; sourceTree = "<group>"; }; DFB6622E15376791006B8FF1 /* AESound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESound.h; sourceTree = "<group>"; }; DFB6622F15376791006B8FF1 /* AEStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEStream.h; sourceTree = "<group>"; }; @@ -1227,6 +1248,8 @@ DFDB00211516403A005079A4 /* FileCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileCache.h; sourceTree = "<group>"; }; DFDB00221516403A005079A4 /* MemBufferCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemBufferCache.cpp; sourceTree = "<group>"; }; DFDB00231516403A005079A4 /* MemBufferCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemBufferCache.h; sourceTree = "<group>"; }; + DFE350591532535500F84CAA /* IOSKeyboardView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSKeyboardView.h; sourceTree = "<group>"; }; + DFE3505A1532535500F84CAA /* IOSKeyboardView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IOSKeyboardView.mm; sourceTree = "<group>"; }; DFFD593E1506B5B10088DE4B /* IOSEAGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSEAGLView.h; sourceTree = "<group>"; }; DFFD593F1506B5B10088DE4B /* IOSEAGLView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IOSEAGLView.mm; sourceTree = "<group>"; }; DFFEFBEC15160739001294DC /* IOSScreenManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSScreenManager.h; sourceTree = "<group>"; }; @@ -1945,8 +1968,6 @@ F56C8355131F42E8000AD0F6 /* GUIDialogGamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogGamepad.h; sourceTree = "<group>"; }; F56C8356131F42E8000AD0F6 /* GUIDialogKaiToast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogKaiToast.cpp; sourceTree = "<group>"; }; F56C8357131F42E8000AD0F6 /* GUIDialogKaiToast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogKaiToast.h; sourceTree = "<group>"; }; - F56C8358131F42E8000AD0F6 /* GUIDialogKeyboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogKeyboard.cpp; sourceTree = "<group>"; }; - F56C8359131F42E8000AD0F6 /* GUIDialogKeyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogKeyboard.h; sourceTree = "<group>"; }; F56C835A131F42E8000AD0F6 /* GUIDialogMediaSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogMediaSource.cpp; sourceTree = "<group>"; }; F56C835B131F42E8000AD0F6 /* GUIDialogMediaSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogMediaSource.h; sourceTree = "<group>"; }; F56C835C131F42E8000AD0F6 /* GUIDialogMuteBug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogMuteBug.cpp; sourceTree = "<group>"; }; @@ -3206,7 +3227,6 @@ children = ( DFB6622A15376791006B8FF1 /* AE.h */, DFB6622B15376791006B8FF1 /* AEEncoder.h */, - DFB6622C15376791006B8FF1 /* AEPostProc.h */, DFB6622D15376791006B8FF1 /* AESink.h */, DFB6622E15376791006B8FF1 /* AESound.h */, DFB6622F15376791006B8FF1 /* AEStream.h */, @@ -3929,6 +3949,8 @@ F56C87C6131F42ED000AD0F6 /* CueDocument.h */, 7C1D697615A8141000658B65 /* DatabaseManager.cpp */, 7C1D697715A8141000658B65 /* DatabaseManager.h */, + 36A9467C15CF20E100727135 /* DbUrl.cpp */, + 36A9467D15CF20E100727135 /* DbUrl.h */, F56C87C9131F42ED000AD0F6 /* DynamicDll.cpp */, F56C87CA131F42ED000AD0F6 /* DynamicDll.h */, F56C87CB131F42ED000AD0F6 /* Favourites.cpp */, @@ -4553,8 +4575,8 @@ F56C8355131F42E8000AD0F6 /* GUIDialogGamepad.h */, F56C8356131F42E8000AD0F6 /* GUIDialogKaiToast.cpp */, F56C8357131F42E8000AD0F6 /* GUIDialogKaiToast.h */, - F56C8358131F42E8000AD0F6 /* GUIDialogKeyboard.cpp */, - F56C8359131F42E8000AD0F6 /* GUIDialogKeyboard.h */, + DF830C9315BB20FC00602BE6 /* GUIDialogKeyboardGeneric.cpp */, + DF830C9415BB20FC00602BE6 /* GUIDialogKeyboardGeneric.h */, F56C835A131F42E8000AD0F6 /* GUIDialogMediaSource.cpp */, F56C835B131F42E8000AD0F6 /* GUIDialogMediaSource.h */, F56C835C131F42E8000AD0F6 /* GUIDialogMuteBug.cpp */, @@ -4974,6 +4996,9 @@ F56C84A4131F42E9000AD0F6 /* GUIIncludes.h */, F56C84FF131F42E9000AD0F6 /* GUIInfoTypes.cpp */, F56C84A5131F42E9000AD0F6 /* GUIInfoTypes.h */, + DF830C9C15BB215500602BE6 /* GUIKeyboardFactory.cpp */, + DF830C9D15BB215500602BE6 /* GUIKeyboardFactory.h */, + DF02A831153373EC0084754E /* GUIKeyboard.h */, F56C8500131F42E9000AD0F6 /* GUILabel.cpp */, F56C84A6131F42E9000AD0F6 /* GUILabel.h */, F56C8501131F42E9000AD0F6 /* GUILabelControl.cpp */, @@ -5087,6 +5112,7 @@ F56C84DF131F42E9000AD0F6 /* XBTF.h */, F56C8535131F42E9000AD0F6 /* XBTFReader.cpp */, F56C84E0131F42E9000AD0F6 /* XBTFReader.h */, + DF02A86D153381990084754E /* GUIKeyboard.h */, ); path = guilib; sourceTree = "<group>"; @@ -5258,6 +5284,8 @@ F56C8623131F42EA000AD0F6 /* LastFmManager.h */, F56C8624131F42EA000AD0F6 /* MusicDatabase.cpp */, F56C8625131F42EA000AD0F6 /* MusicDatabase.h */, + 36A9467215CF208B00727135 /* MusicDbUrl.cpp */, + 36A9467315CF208B00727135 /* MusicDbUrl.h */, F56C8626131F42EA000AD0F6 /* MusicInfoLoader.cpp */, F56C8627131F42EA000AD0F6 /* MusicInfoLoader.h */, F56C8628131F42EA000AD0F6 /* Song.cpp */, @@ -5834,6 +5862,8 @@ F56C875C131F42EC000AD0F6 /* TuxBoxUtil.h */, F56C8703131F42EB000AD0F6 /* URIUtils.cpp */, F56C8704131F42EB000AD0F6 /* URIUtils.h */, + 36A9467615CF20A500727135 /* UrlOptions.cpp */, + 36A9467715CF20A500727135 /* UrlOptions.h */, F56C875D131F42EC000AD0F6 /* Variant.cpp */, F56C875E131F42EC000AD0F6 /* Variant.h */, F56C875F131F42EC000AD0F6 /* Weather.cpp */, @@ -5861,6 +5891,8 @@ F56C878F131F42EC000AD0F6 /* TeletextDefines.h */, F56C8790131F42EC000AD0F6 /* VideoDatabase.cpp */, F56C8791131F42EC000AD0F6 /* VideoDatabase.h */, + 36A9467915CF20BD00727135 /* VideoDbUrl.cpp */, + 36A9467A15CF20BD00727135 /* VideoDbUrl.h */, F56C8792131F42EC000AD0F6 /* VideoInfoDownloader.cpp */, F56C8793131F42EC000AD0F6 /* VideoInfoDownloader.h */, F56C8794131F42EC000AD0F6 /* VideoInfoScanner.cpp */, @@ -5972,6 +6004,10 @@ isa = PBXGroup; children = ( F56C8BB6131F44AA000AD0F6 /* English.lproj */, + DF02A887153382A60084754E /* IOSKeyboard.mm */, + DF02A881153382560084754E /* IOSKeyboard.h */, + DFE350591532535500F84CAA /* IOSKeyboardView.h */, + DFE3505A1532535500F84CAA /* IOSKeyboardView.mm */, F56C8B9E131F4466000AD0F6 /* XBMC.png */, F56C8B9F131F4466000AD0F6 /* XBMCApplication.h */, F56C8BA0131F4466000AD0F6 /* XBMCApplication.m */, @@ -6236,7 +6272,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ ${XCODE_VERSION_MINOR} -gt 400 ]\nthen\n TARGET_OUTPUT_DIR=\"${PROJECT_DIR}/build/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}\"\n mkdir -p \"${TARGET_OUTPUT_DIR}\"\n\n ln -sf \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\" \"${TARGET_OUTPUT_DIR}/\"\n ln -sf \"${BUILT_PRODUCTS_DIR}/${DWARF_DSYM_FILE_NAME}\" \"${TARGET_OUTPUT_DIR}/\"\nfi"; + shellScript = "if [ ${XCODE_VERSION_MINOR} -gt 400 ]\nthen\n TARGET_OUTPUT_DIR=\"${PROJECT_DIR}/build/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}\"\n mkdir -p \"${TARGET_OUTPUT_DIR}\"\n\n if [ \"${BUILT_PRODUCTS_DIR}\" != \"${TARGET_OUTPUT_DIR}\" ]\n then\n rm -rf \"${TARGET_OUTPUT_DIR}/${FULL_PRODUCT_NAME}\"\n rm -rf \"${TARGET_OUTPUT_DIR}/${DWARF_DSYM_FILE_NAME}\"\n ln -s \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\" \"${TARGET_OUTPUT_DIR}/\" || true\n ln -s \"${BUILT_PRODUCTS_DIR}/${DWARF_DSYM_FILE_NAME}\" \"${TARGET_OUTPUT_DIR}/\" || true\n fi\nfi"; }; 3234980612AF0B3400657FF1 /* codesign */ = { isa = PBXShellScriptBuildPhase; @@ -6583,7 +6619,6 @@ F56C8943131F42ED000AD0F6 /* GUIDialogFileBrowser.cpp in Sources */, F56C8944131F42ED000AD0F6 /* GUIDialogGamepad.cpp in Sources */, F56C8945131F42ED000AD0F6 /* GUIDialogKaiToast.cpp in Sources */, - F56C8946131F42ED000AD0F6 /* GUIDialogKeyboard.cpp in Sources */, F56C8947131F42ED000AD0F6 /* GUIDialogMediaSource.cpp in Sources */, F56C8948131F42ED000AD0F6 /* GUIDialogMuteBug.cpp in Sources */, F56C8949131F42ED000AD0F6 /* GUIDialogNumeric.cpp in Sources */, @@ -6945,7 +6980,6 @@ F56C8ADA131F42ED000AD0F6 /* PowerManager.cpp in Sources */, F56C8ADB131F42ED000AD0F6 /* GUIViewStatePrograms.cpp in Sources */, F56C8ADC131F42ED000AD0F6 /* GUIWindowPrograms.cpp in Sources */, - F56C8ADE131F42ED000AD0F6 /* Shortcut.cpp in Sources */, F56C8ADF131F42ED000AD0F6 /* RenderSystemGLES.cpp in Sources */, F56C8AE0131F42ED000AD0F6 /* RenderSystem.cpp in Sources */, F56C8AE1131F42ED000AD0F6 /* GUIDialogContentSettings.cpp in Sources */, @@ -7234,6 +7268,14 @@ 36A9465B15AA26BC00727135 /* DirectoryNodeTags.cpp in Sources */, 7C1D697815A8141000658B65 /* DatabaseManager.cpp in Sources */, 7C1A495315A968FB004AF4A4 /* SeekHandler.cpp in Sources */, + DFE3505B1532535500F84CAA /* IOSKeyboardView.mm in Sources */, + DF02A888153382A60084754E /* IOSKeyboard.mm in Sources */, + DF830C9515BB20FC00602BE6 /* GUIDialogKeyboardGeneric.cpp in Sources */, + DF830C9E15BB215500602BE6 /* GUIKeyboardFactory.cpp in Sources */, + 36A9467415CF208B00727135 /* MusicDbUrl.cpp in Sources */, + 36A9467815CF20A500727135 /* UrlOptions.cpp in Sources */, + 36A9467B15CF20BD00727135 /* VideoDbUrl.cpp in Sources */, + 36A9467E15CF20E100727135 /* DbUrl.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -7320,6 +7362,10 @@ "\"$(SRCROOT)/lib/ffmpeg/libpostproc\"", "\"$(SRCROOT)/lib/ffmpeg/libswscale\"", ); + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-Wreorder", + ); OTHER_LDFLAGS = ( "-Wl,-headerpad_max_install_names", "-Wl,-all_load", @@ -7359,7 +7405,7 @@ TARGETED_DEVICE_FAMILY = "1,2"; USER_HEADER_SEARCH_PATHS = "$XBMC_DEPENDS/include $XBMC_DEPENDS/include/mysql $XBMC_DEPENDS/include/freetype2 $XBMC_DEPENDS/include/python2.6"; VALIDATE_PRODUCT = NO; - WARNING_CFLAGS = "-Wreorder"; + WARNING_CFLAGS = ""; WRAPPER_EXTENSION = app; XBMC_DEPENDS = "/Users/Shared/xbmc-depends/$(SDK_NAME)_$(ARCHS)"; }; @@ -7436,6 +7482,10 @@ "\"$(SRCROOT)/lib/ffmpeg/libpostproc\"", "\"$(SRCROOT)/lib/ffmpeg/libswscale\"", ); + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-Wreorder", + ); OTHER_LDFLAGS = ( "-Wl,-headerpad_max_install_names", "-Wl,-all_load", @@ -7475,7 +7525,7 @@ TARGETED_DEVICE_FAMILY = "1,2"; USER_HEADER_SEARCH_PATHS = "$XBMC_DEPENDS/include $XBMC_DEPENDS/include/mysql $XBMC_DEPENDS/include/freetype2 $XBMC_DEPENDS/include/python2.6"; VALIDATE_PRODUCT = NO; - WARNING_CFLAGS = "-Wreorder"; + WARNING_CFLAGS = ""; WRAPPER_EXTENSION = app; XBMC_DEPENDS = "/Users/Shared/xbmc-depends/$(SDK_NAME)_$(ARCHS)"; }; diff --git a/XBMC.xcodeproj/project.pbxproj b/XBMC.xcodeproj/project.pbxproj index b9fa7cda8a..611aaa00a2 100644 --- a/XBMC.xcodeproj/project.pbxproj +++ b/XBMC.xcodeproj/project.pbxproj @@ -195,6 +195,10 @@ 36A9443D15821E2800727135 /* DatabaseUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9443B15821E2800727135 /* DatabaseUtils.cpp */; }; 36A9444115821E7C00727135 /* SortUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9443F15821E7C00727135 /* SortUtils.cpp */; }; 36A9464C15AA25FD00727135 /* DirectoryNodeTags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9464A15AA25FD00727135 /* DirectoryNodeTags.cpp */; }; + 36A9466315CF1FA600727135 /* DbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9466115CF1FA600727135 /* DbUrl.cpp */; }; + 36A9466715CF1FD200727135 /* MusicDbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9466515CF1FD200727135 /* MusicDbUrl.cpp */; }; + 36A9466A15CF1FED00727135 /* UrlOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9466815CF1FED00727135 /* UrlOptions.cpp */; }; + 36A9466D15CF201F00727135 /* VideoDbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9466B15CF201F00727135 /* VideoDbUrl.cpp */; }; 3802709A13D5A653009493DD /* SystemClock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3802709813D5A653009493DD /* SystemClock.cpp */; }; 384718D81325BA04000486D6 /* XBDateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 384718D61325BA04000486D6 /* XBDateTime.cpp */; }; 38F4E57013CCCB3B00664821 /* Implementation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 38F4E56C13CCCB3B00664821 /* Implementation.cpp */; }; @@ -342,6 +346,8 @@ DF527736151BAF4C00B5B63B /* WebSocketV13.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF52772F151BAF4C00B5B63B /* WebSocketV13.cpp */; }; DF527737151BAF4C00B5B63B /* WebSocketV8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF527731151BAF4C00B5B63B /* WebSocketV8.cpp */; }; DF673AA51443819600A5A509 /* AddonManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B49FF41152BFA5001AF8A6 /* AddonManager.cpp */; }; + DF830D0C15BB260C00602BE6 /* GUIDialogKeyboardGeneric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF830D0A15BB260C00602BE6 /* GUIDialogKeyboardGeneric.cpp */; }; + DF830D1215BB262700602BE6 /* GUIKeyboardFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF830D0F15BB262700602BE6 /* GUIKeyboardFactory.cpp */; }; DF93D65D1444A7A3007C6459 /* SlingboxDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF93D65C1444A7A3007C6459 /* SlingboxDirectory.cpp */; }; DF93D6991444A8B1007C6459 /* AFPFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF93D6631444A8B0007C6459 /* AFPFile.cpp */; }; DF93D69A1444A8B1007C6459 /* DirectoryCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF93D6651444A8B0007C6459 /* DirectoryCache.cpp */; }; @@ -593,7 +599,6 @@ E38E20810D25F9FD00618676 /* GUIDialogFileBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E17A80D25F9FA00618676 /* GUIDialogFileBrowser.cpp */; }; E38E20820D25F9FD00618676 /* GUIDialogFileStacking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E17AA0D25F9FA00618676 /* GUIDialogFileStacking.cpp */; }; E38E20830D25F9FD00618676 /* GUIDialogGamepad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E17AC0D25F9FA00618676 /* GUIDialogGamepad.cpp */; }; - E38E20870D25F9FD00618676 /* GUIDialogKeyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E17B40D25F9FA00618676 /* GUIDialogKeyboard.cpp */; }; E38E20890D25F9FD00618676 /* GUIDialogMediaSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E17B80D25F9FA00618676 /* GUIDialogMediaSource.cpp */; }; E38E208A0D25F9FD00618676 /* GUIDialogMusicOSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E17BA0D25F9FA00618676 /* GUIDialogMusicOSD.cpp */; }; E38E208B0D25F9FD00618676 /* GUIDialogMusicScan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E17BC0D25F9FA00618676 /* GUIDialogMusicScan.cpp */; }; @@ -753,7 +758,6 @@ E38E22AE0D25F9FE00618676 /* Profile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E1DF10D25F9FD00618676 /* Profile.cpp */; }; E38E22B30D25F9FE00618676 /* SectionLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E1DFE0D25F9FD00618676 /* SectionLoader.cpp */; }; E38E22B40D25F9FE00618676 /* VideoSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E1E010D25F9FD00618676 /* VideoSettings.cpp */; }; - E38E22B70D25F9FE00618676 /* Shortcut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E1E070D25F9FD00618676 /* Shortcut.cpp */; }; E38E22B80D25F9FE00618676 /* SlideShowPicture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E1E090D25F9FD00618676 /* SlideShowPicture.cpp */; }; E38E22BA0D25F9FE00618676 /* Song.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E1E0D0D25F9FD00618676 /* Song.cpp */; }; E38E22BE0D25F9FE00618676 /* Temperature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E1E160D25F9FD00618676 /* Temperature.cpp */; }; @@ -1379,6 +1383,14 @@ 36A9444015821E7C00727135 /* SortUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SortUtils.h; sourceTree = "<group>"; }; 36A9464A15AA25FD00727135 /* DirectoryNodeTags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectoryNodeTags.cpp; sourceTree = "<group>"; }; 36A9464B15AA25FD00727135 /* DirectoryNodeTags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryNodeTags.h; sourceTree = "<group>"; }; + 36A9466115CF1FA600727135 /* DbUrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DbUrl.cpp; sourceTree = "<group>"; }; + 36A9466215CF1FA600727135 /* DbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DbUrl.h; sourceTree = "<group>"; }; + 36A9466515CF1FD200727135 /* MusicDbUrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MusicDbUrl.cpp; sourceTree = "<group>"; }; + 36A9466615CF1FD200727135 /* MusicDbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MusicDbUrl.h; sourceTree = "<group>"; }; + 36A9466815CF1FED00727135 /* UrlOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UrlOptions.cpp; sourceTree = "<group>"; }; + 36A9466915CF1FED00727135 /* UrlOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UrlOptions.h; sourceTree = "<group>"; }; + 36A9466B15CF201F00727135 /* VideoDbUrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoDbUrl.cpp; sourceTree = "<group>"; }; + 36A9466C15CF201F00727135 /* VideoDbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoDbUrl.h; sourceTree = "<group>"; }; 3802709713D5A62D009493DD /* ThreadLocal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadLocal.h; sourceTree = "<group>"; }; 3802709813D5A653009493DD /* SystemClock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SystemClock.cpp; sourceTree = "<group>"; }; 3802709913D5A653009493DD /* SystemClock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SystemClock.h; sourceTree = "<group>"; }; @@ -1531,9 +1543,9 @@ 7C0A7EBF13A5DBCE00AFC2BD /* AppParamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppParamParser.h; sourceTree = "<group>"; }; 7C0B98A1154B79C30065A238 /* AEDeviceInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AEDeviceInfo.cpp; sourceTree = "<group>"; }; 7C0B98A2154B79C30065A238 /* AEDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEDeviceInfo.h; sourceTree = "<group>"; }; - 7C1A495B15A96918004AF4A4 /* SaveFileStateJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveFileStateJob.h; sourceTree = "<group>"; }; 7C1A492115A962EE004AF4A4 /* SeekHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SeekHandler.cpp; sourceTree = "<group>"; }; 7C1A492215A962EE004AF4A4 /* SeekHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SeekHandler.h; sourceTree = "<group>"; }; + 7C1A495B15A96918004AF4A4 /* SaveFileStateJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveFileStateJob.h; sourceTree = "<group>"; }; 7C1A85631520522500C63311 /* TextureCacheJob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureCacheJob.cpp; sourceTree = "<group>"; }; 7C1A85641520522500C63311 /* TextureCacheJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCacheJob.h; sourceTree = "<group>"; }; 7C1D682715A7D2FD00658B65 /* DatabaseManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseManager.cpp; sourceTree = "<group>"; }; @@ -1709,6 +1721,11 @@ DF527730151BAF4C00B5B63B /* WebSocketV13.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketV13.h; sourceTree = "<group>"; }; DF527731151BAF4C00B5B63B /* WebSocketV8.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocketV8.cpp; sourceTree = "<group>"; }; DF527732151BAF4C00B5B63B /* WebSocketV8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketV8.h; sourceTree = "<group>"; }; + DF830D0A15BB260C00602BE6 /* GUIDialogKeyboardGeneric.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogKeyboardGeneric.cpp; sourceTree = "<group>"; }; + DF830D0B15BB260C00602BE6 /* GUIDialogKeyboardGeneric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogKeyboardGeneric.h; sourceTree = "<group>"; }; + DF830D0E15BB262700602BE6 /* GUIKeyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIKeyboard.h; sourceTree = "<group>"; }; + DF830D0F15BB262700602BE6 /* GUIKeyboardFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIKeyboardFactory.cpp; sourceTree = "<group>"; }; + DF830D1015BB262700602BE6 /* GUIKeyboardFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIKeyboardFactory.h; sourceTree = "<group>"; }; DF93D65B1444A7A3007C6459 /* SlingboxDirectory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlingboxDirectory.h; sourceTree = "<group>"; }; DF93D65C1444A7A3007C6459 /* SlingboxDirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SlingboxDirectory.cpp; sourceTree = "<group>"; }; DF93D6631444A8B0007C6459 /* AFPFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AFPFile.cpp; sourceTree = "<group>"; }; @@ -1795,7 +1812,6 @@ DFB65F7B15373AE7006B8FF1 /* ICoreAudioSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ICoreAudioSource.h; path = CoreAudio/ICoreAudioSource.h; sourceTree = "<group>"; }; DFB65F8915373AE7006B8FF1 /* AE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AE.h; sourceTree = "<group>"; }; DFB65F8A15373AE7006B8FF1 /* AEEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEEncoder.h; sourceTree = "<group>"; }; - DFB65F8B15373AE7006B8FF1 /* AEPostProc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEPostProc.h; sourceTree = "<group>"; }; DFB65F8C15373AE7006B8FF1 /* AESink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESink.h; sourceTree = "<group>"; }; DFB65F8D15373AE7006B8FF1 /* AESound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESound.h; sourceTree = "<group>"; }; DFB65F8E15373AE7006B8FF1 /* AEStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEStream.h; sourceTree = "<group>"; }; @@ -2263,8 +2279,6 @@ E38E17AB0D25F9FA00618676 /* GUIDialogFileStacking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogFileStacking.h; sourceTree = "<group>"; }; E38E17AC0D25F9FA00618676 /* GUIDialogGamepad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogGamepad.cpp; sourceTree = "<group>"; }; E38E17AD0D25F9FA00618676 /* GUIDialogGamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogGamepad.h; sourceTree = "<group>"; }; - E38E17B40D25F9FA00618676 /* GUIDialogKeyboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogKeyboard.cpp; sourceTree = "<group>"; }; - E38E17B50D25F9FA00618676 /* GUIDialogKeyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogKeyboard.h; sourceTree = "<group>"; }; E38E17B80D25F9FA00618676 /* GUIDialogMediaSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogMediaSource.cpp; sourceTree = "<group>"; }; E38E17B90D25F9FA00618676 /* GUIDialogMediaSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogMediaSource.h; sourceTree = "<group>"; }; E38E17BA0D25F9FA00618676 /* GUIDialogMusicOSD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogMusicOSD.cpp; sourceTree = "<group>"; }; @@ -3317,6 +3331,9 @@ 18B7C7171294222D009E7A26 /* GUIIncludes.h */, 18B7C7721294222E009E7A26 /* GUIInfoTypes.cpp */, 18B7C7181294222D009E7A26 /* GUIInfoTypes.h */, + DF830D0E15BB262700602BE6 /* GUIKeyboard.h */, + DF830D0F15BB262700602BE6 /* GUIKeyboardFactory.cpp */, + DF830D1015BB262700602BE6 /* GUIKeyboardFactory.h */, 18B7C7731294222E009E7A26 /* GUILabel.cpp */, 18B7C7191294222D009E7A26 /* GUILabel.h */, 18B7C7741294222E009E7A26 /* GUILabelControl.cpp */, @@ -3452,6 +3469,8 @@ E38E185B0D25F9FA00618676 /* LastFmManager.h */, E38E1D8F0D25F9FD00618676 /* MusicDatabase.cpp */, E38E1D900D25F9FD00618676 /* MusicDatabase.h */, + 36A9466515CF1FD200727135 /* MusicDbUrl.cpp */, + 36A9466615CF1FD200727135 /* MusicDbUrl.h */, E38E1D910D25F9FD00618676 /* MusicInfoLoader.cpp */, E38E1D920D25F9FD00618676 /* MusicInfoLoader.h */, E38E1E0D0D25F9FD00618676 /* Song.cpp */, @@ -3768,8 +3787,8 @@ E38E17AD0D25F9FA00618676 /* GUIDialogGamepad.h */, E38A06CC0D95AA5500FF8227 /* GUIDialogKaiToast.cpp */, E38A06CD0D95AA5500FF8227 /* GUIDialogKaiToast.h */, - E38E17B40D25F9FA00618676 /* GUIDialogKeyboard.cpp */, - E38E17B50D25F9FA00618676 /* GUIDialogKeyboard.h */, + DF830D0A15BB260C00602BE6 /* GUIDialogKeyboardGeneric.cpp */, + DF830D0B15BB260C00602BE6 /* GUIDialogKeyboardGeneric.h */, E38E17B80D25F9FA00618676 /* GUIDialogMediaSource.cpp */, E38E17B90D25F9FA00618676 /* GUIDialogMediaSource.h */, E38E17BE0D25F9FA00618676 /* GUIDialogMuteBug.cpp */, @@ -4005,6 +4024,8 @@ F5E55B6F10741340006E788A /* TeletextDefines.h */, E38E1E930D25F9FD00618676 /* VideoDatabase.cpp */, E38E1E940D25F9FD00618676 /* VideoDatabase.h */, + 36A9466B15CF201F00727135 /* VideoDbUrl.cpp */, + 36A9466C15CF201F00727135 /* VideoDbUrl.h */, E38E1E4A0D25F9FD00618676 /* VideoInfoDownloader.cpp */, E38E1E4B0D25F9FD00618676 /* VideoInfoDownloader.h */, E38E1E950D25F9FD00618676 /* VideoInfoScanner.cpp */, @@ -4207,7 +4228,6 @@ children = ( DFB65F8915373AE7006B8FF1 /* AE.h */, DFB65F8A15373AE7006B8FF1 /* AEEncoder.h */, - DFB65F8B15373AE7006B8FF1 /* AEPostProc.h */, DFB65F8C15373AE7006B8FF1 /* AESink.h */, DFB65F8D15373AE7006B8FF1 /* AESound.h */, DFB65F8E15373AE7006B8FF1 /* AEStream.h */, @@ -4332,6 +4352,8 @@ E38E167F0D25F9FA00618676 /* CueDocument.h */, 7C1D682715A7D2FD00658B65 /* DatabaseManager.cpp */, 7C1D682815A7D2FD00658B65 /* DatabaseManager.h */, + 36A9466115CF1FA600727135 /* DbUrl.cpp */, + 36A9466215CF1FA600727135 /* DbUrl.h */, E38E168C0D25F9FA00618676 /* DynamicDll.cpp */, E38E168D0D25F9FA00618676 /* DynamicDll.h */, E38E16900D25F9FA00618676 /* Favourites.cpp */, @@ -5913,6 +5935,8 @@ E38E1E8A0D25F9FD00618676 /* TuxBoxUtil.h */, 18B7C8EC12942613009E7A26 /* URIUtils.cpp */, 18B7C8ED12942613009E7A26 /* URIUtils.h */, + 36A9466815CF1FED00727135 /* UrlOptions.cpp */, + 36A9466915CF1FED00727135 /* UrlOptions.h */, 7CF1FB09123B1AF000B2CBCB /* Variant.cpp */, 7CF1FB0A123B1AF000B2CBCB /* Variant.h */, E38E1E8D0D25F9FD00618676 /* Weather.cpp */, @@ -6293,7 +6317,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ ${XCODE_VERSION_MINOR} -gt 400 ]\nthen\n TARGET_OUTPUT_DIR=\"${PROJECT_DIR}/build/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}\"\n mkdir -p \"${TARGET_OUTPUT_DIR}\"\n\n ln -sf \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\" \"${TARGET_OUTPUT_DIR}/\"\n ln -sf \"${BUILT_PRODUCTS_DIR}/${DWARF_DSYM_FILE_NAME}\" \"${TARGET_OUTPUT_DIR}/\"\nfi"; + shellScript = "if [ ${XCODE_VERSION_MINOR} -gt 400 ]\nthen\n TARGET_OUTPUT_DIR=\"${PROJECT_DIR}/build/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}\"\n mkdir -p \"${TARGET_OUTPUT_DIR}\"\n\n if [ \"${BUILT_PRODUCTS_DIR}\" != \"${TARGET_OUTPUT_DIR}\" ]\n then\n rm -rf \"${TARGET_OUTPUT_DIR}/${FULL_PRODUCT_NAME}\"\n rm -rf \"${TARGET_OUTPUT_DIR}/${DWARF_DSYM_FILE_NAME}\"\n ln -s \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\" \"${TARGET_OUTPUT_DIR}/\" || true\n ln -s \"${BUILT_PRODUCTS_DIR}/${DWARF_DSYM_FILE_NAME}\" \"${TARGET_OUTPUT_DIR}/\" || true\n fi\nfi"; }; 1D64E5FC157BD76F001ACEBE /* genoutputdirlink */ = { isa = PBXShellScriptBuildPhase; @@ -6307,7 +6331,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ ${XCODE_VERSION_MINOR} -gt 400 ]\nthen\n TARGET_OUTPUT_DIR=\"${PROJECT_DIR}/build/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}\"\n mkdir -p \"${TARGET_OUTPUT_DIR}\"\n\n ln -sf \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}\" \"${TARGET_OUTPUT_DIR}/\"\n ln -sf \"${BUILT_PRODUCTS_DIR}/${PROJECT_NAME}${DWARF_DSYM_FILE_NAME}\" \"${TARGET_OUTPUT_DIR}/\"\nfi"; + shellScript = "if [ ${XCODE_VERSION_MINOR} -gt 400 ]\nthen\n TARGET_OUTPUT_DIR=\"${PROJECT_DIR}/build/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}\"\n mkdir -p \"${TARGET_OUTPUT_DIR}\"\n\n if [ \"${BUILT_PRODUCTS_DIR}\" != \"${TARGET_OUTPUT_DIR}\" ]\n then\n rm -rf \"${TARGET_OUTPUT_DIR}/${PRODUCT_NAME}\"\n rm -rf \"${TARGET_OUTPUT_DIR}/${PROJECT_NAME}${DWARF_DSYM_FILE_NAME}\"\n ln -s \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}\" \"${TARGET_OUTPUT_DIR}/\" || true\n ln -s \"${BUILT_PRODUCTS_DIR}/${PROJECT_NAME}${DWARF_DSYM_FILE_NAME}\" \"${TARGET_OUTPUT_DIR}/\" || true\n fi\nfi"; }; 6E2FACC70E26E22400DF79EA /* copy frameworks */ = { isa = PBXShellScriptBuildPhase; @@ -6542,7 +6566,6 @@ E38E20810D25F9FD00618676 /* GUIDialogFileBrowser.cpp in Sources */, E38E20820D25F9FD00618676 /* GUIDialogFileStacking.cpp in Sources */, E38E20830D25F9FD00618676 /* GUIDialogGamepad.cpp in Sources */, - E38E20870D25F9FD00618676 /* GUIDialogKeyboard.cpp in Sources */, E38E20890D25F9FD00618676 /* GUIDialogMediaSource.cpp in Sources */, E38E208A0D25F9FD00618676 /* GUIDialogMusicOSD.cpp in Sources */, E38E208B0D25F9FD00618676 /* GUIDialogMusicScan.cpp in Sources */, @@ -6702,7 +6725,6 @@ E38E22AE0D25F9FE00618676 /* Profile.cpp in Sources */, E38E22B30D25F9FE00618676 /* SectionLoader.cpp in Sources */, E38E22B40D25F9FE00618676 /* VideoSettings.cpp in Sources */, - E38E22B70D25F9FE00618676 /* Shortcut.cpp in Sources */, E38E22B80D25F9FE00618676 /* SlideShowPicture.cpp in Sources */, E38E22BA0D25F9FE00618676 /* Song.cpp in Sources */, E38E22BE0D25F9FE00618676 /* Temperature.cpp in Sources */, @@ -7315,6 +7337,12 @@ 36A9464C15AA25FD00727135 /* DirectoryNodeTags.cpp in Sources */, 7C1D682915A7D2FD00658B65 /* DatabaseManager.cpp in Sources */, 7C1A492315A962EE004AF4A4 /* SeekHandler.cpp in Sources */, + DF830D0C15BB260C00602BE6 /* GUIDialogKeyboardGeneric.cpp in Sources */, + DF830D1215BB262700602BE6 /* GUIKeyboardFactory.cpp in Sources */, + 36A9466315CF1FA600727135 /* DbUrl.cpp in Sources */, + 36A9466715CF1FD200727135 /* MusicDbUrl.cpp in Sources */, + 36A9466A15CF1FED00727135 /* UrlOptions.cpp in Sources */, + 36A9466D15CF201F00727135 /* VideoDbUrl.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -7399,6 +7427,10 @@ "\"$(SRCROOT)/lib/ffmpeg/libswscale\"", ); LINK_WITH_STANDARD_LIBRARIES = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-Wreorder", + ); OTHER_LDFLAGS = ( "-headerpad_max_install_names", "-all_load", @@ -7437,7 +7469,7 @@ ); PRODUCT_NAME = XBMC; USER_HEADER_SEARCH_PATHS = "$XBMC_DEPENDS/include $XBMC_DEPENDS/include/libcec $XBMC_DEPENDS/include/mysql $XBMC_DEPENDS/include/freetype2 $XBMC_DEPENDS/include/python2.6"; - WARNING_CFLAGS = "-Wreorder"; + WARNING_CFLAGS = ""; XBMC_DEPENDS = "/Users/Shared/xbmc-depends/$(SDK_NAME)_$(ARCHS)"; ZERO_LINK = NO; }; @@ -7516,6 +7548,10 @@ "\"$(SRCROOT)/lib/ffmpeg/libswscale\"", ); LINK_WITH_STANDARD_LIBRARIES = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-Wreorder", + ); OTHER_LDFLAGS = ( "-headerpad_max_install_names", "-all_load", @@ -7554,7 +7590,7 @@ ); PRODUCT_NAME = XBMC; USER_HEADER_SEARCH_PATHS = "$XBMC_DEPENDS/include $XBMC_DEPENDS/include/libcec $XBMC_DEPENDS/include/mysql $XBMC_DEPENDS/include/freetype2 $XBMC_DEPENDS/include/python2.6"; - WARNING_CFLAGS = "-Wreorder"; + WARNING_CFLAGS = ""; XBMC_DEPENDS = "/Users/Shared/xbmc-depends/$(SDK_NAME)_$(ARCHS)"; ZERO_LINK = NO; }; diff --git a/addons/skin.confluence/720p/Home.xml b/addons/skin.confluence/720p/Home.xml index dc9ecffca6..0001a3abd3 100644 --- a/addons/skin.confluence/720p/Home.xml +++ b/addons/skin.confluence/720p/Home.xml @@ -644,7 +644,8 @@ </item> <item id="1"> <label>0</label> - <onclick>ActivateWindow(Programs,Addons,return)</onclick> + <onclick condition="!System.Platform.Android">ActivateWindow(Programs,Addons,return)</onclick> + <onclick condition="System.Platform.Android">ActivateWindow(Programs)</onclick> <icon>-</icon> <thumb>-</thumb> <visible>!Skin.HasSetting(HomeMenuNoProgramsButton)</visible> diff --git a/addons/skin.confluence/720p/IncludesBackgroundBuilding.xml b/addons/skin.confluence/720p/IncludesBackgroundBuilding.xml index 025feb4e6a..74b202eb37 100644 --- a/addons/skin.confluence/720p/IncludesBackgroundBuilding.xml +++ b/addons/skin.confluence/720p/IncludesBackgroundBuilding.xml @@ -33,7 +33,7 @@ <fadetime>FanartCrossfadeTime</fadetime> <visible>!Skin.HasSetting(HideBackGroundFanart) + !IsEmpty(ListItem.Property(Fanart_Image))</visible> <include>Window_OpenClose_Animation</include> - <visible>![Player.HasVideo + !Skin.HasSetting(ShowBackgroundVideo)] + ![Player.HasAudio + !Skin.HasSetting(ShowBackgroundVis)]</visible> + <visible>![Player.HasVideo + !Skin.HasSetting(ShowBackgroundVideo)] + ![Player.HasAudio + ![Skin.HasSetting(ShowBackgroundVis) | SubString(Window(videolibrary).Property(TvTunesIsAlive),True)]]</visible> </control> <control type="image"> <posx>0</posx> @@ -64,8 +64,7 @@ <width>1280</width> <height>120</height> <texture flipy="true">HomeNowPlayingBack.png</texture> - <visible>[Player.HasVideo + !Skin.HasSetting(ShowBackgroundVideo)] | [Player.HasAudio + !Skin.HasSetting(ShowBackgroundVis)] | [!Skin.HasSetting(HideBackGroundFanart) + !IsEmpty(ListItem.Property(Fanart_Image))]</visible> - <visible>!SubString(Window(videolibrary).Property(TvTunesIsAlive),True)</visible> + <visible>[Player.HasVideo + !Skin.HasSetting(ShowBackgroundVideo)] | [Player.HasAudio + ![Skin.HasSetting(ShowBackgroundVis) | SubString(Window(videolibrary).Property(TvTunesIsAlive),True)]] | [!Skin.HasSetting(HideBackGroundFanart) + !IsEmpty(ListItem.Property(Fanart_Image))]</visible> </control> </include> <include name="ContentPanelBackgrounds"> diff --git a/addons/skin.confluence/720p/MusicVisualisation.xml b/addons/skin.confluence/720p/MusicVisualisation.xml index 7f0049bef0..e5ae66d3c6 100644 --- a/addons/skin.confluence/720p/MusicVisualisation.xml +++ b/addons/skin.confluence/720p/MusicVisualisation.xml @@ -246,7 +246,7 @@ <posy>40</posy> <label>-</label> <align>left</align> - <label>$INFO[Visualisation.Name] [I][COLOR=orange]($LOCALIZE[20166])[/COLOR][/I] · fps: $INFO[System.FPS]</label> + <label>$INFO[Visualisation.Name,, [I][COLOR=orange]($LOCALIZE[20166])[/COLOR][/I] · ]fps: $INFO[System.FPS]</label> <font>font12</font> <visible>Visualisation.Locked</visible> </control> @@ -256,7 +256,7 @@ <posy>40</posy> <label>-</label> <align>left</align> - <label>$INFO[Visualisation.Name] · fps: $INFO[System.FPS]</label> + <label>$INFO[Visualisation.Name,, · ]fps: $INFO[System.FPS]</label> <font>font12</font> <visible>!Visualisation.Locked</visible> </control> @@ -266,7 +266,7 @@ <posy>70</posy> <label>-</label> <align>left</align> - <label>$LOCALIZE[13388]: $INFO[Visualisation.Preset]</label> + <label>$INFO[Visualisation.Preset,$LOCALIZE[13388]: ]</label> <font>font12</font> </control> </control> diff --git a/addons/skin.confluence/media/Makefile.in b/addons/skin.confluence/media/Makefile.in index 52a040e1b6..3cf7d1bcd3 100644 --- a/addons/skin.confluence/media/Makefile.in +++ b/addons/skin.confluence/media/Makefile.in @@ -10,8 +10,12 @@ all: $(TARGET) .PHONY: force $(TARGET): $(XBMCTEX) $(IMAGES) +ifeq (@USE_ANDROID@,1) + $(XBMCTEX) -use_none -input . -output $(TARGET) +else $(XBMCTEX) -input . -output $(TARGET) +endif $(XBMCTEX): force $(MAKE) -C @abs_top_srcdir@/tools/TexturePacker diff --git a/addons/visualization.glspectrum/addon.xml b/addons/visualization.glspectrum/addon.xml index 856989d498..6f5470b63b 100644 --- a/addons/visualization.glspectrum/addon.xml +++ b/addons/visualization.glspectrum/addon.xml @@ -7,7 +7,8 @@ <extension point="xbmc.player.musicviz" library_linux="opengl_spectrum.vis" - library_osx="opengl_spectrum.vis" /> + library_osx="opengl_spectrum.vis" + library_android="libvisopengl_spectrum.so" /> <extension point="xbmc.addon.metadata"> <summary lang="bg">ВизŃализация предŃтавяща ротиращ Ńе 3D Ńпектрален анализатор</summary> <summary lang="en">Visualisation showing a rotating 3D Spectrum Analyzer</summary> @@ -48,6 +49,6 @@ Det har ocksĂĄ inställningar för att justera spektrumhöjden, hastigheten och <description lang="zh">Opengl Spectrum可视化ć•ćžśćŻOpengl渲染的一个旋转的三维频谱ĺ†ćžĺ›ľĺŹďĽŚé˘‘谱矩éµéšŹçť€éźłäąčŠ‚拍而象波浪起伏。 ä˝ čżĺŹŻä»Ąč®ľç˝®é˘‘谱棒的é«ĺş¦ă€ĺŹćŤ˘é€źĺş¦ă€ä»ĄĺŹŠĺ‘现ć•ćžśďĽĺ›şä˝“ă€ç‚ąă€ćˇ†ćž¶ďĽ‰ă€‚čż™ćŻä¸€ä¸Şä¸Ťé”™çš„轻量级,低CPU使用率的可视化ć•ćžśă€‚</description> <disclaimer></disclaimer> - <platform>linux osx ios</platform> + <platform>linux osx ios android</platform> </extension> </addon> diff --git a/addons/visualization.waveform/addon.xml b/addons/visualization.waveform/addon.xml index 320592372b..203a35949f 100644 --- a/addons/visualization.waveform/addon.xml +++ b/addons/visualization.waveform/addon.xml @@ -8,7 +8,8 @@ point="xbmc.player.musicviz" library_linux="Waveform.vis" library_windx="Waveform_win32.vis" - library_osx="Waveform.vis"/> + library_osx="Waveform.vis" + library_android="libvisWaveform.so"/> <extension point="xbmc.addon.metadata"> <summary lang="bg">ВизŃализация предŃтавяща графика на две ĐľŃцилиращи вълни на екрана</summary> <summary lang="en">Visualization showing 2 Waveform Graphs on the screen</summary> diff --git a/addons/webinterface.default/addon.xml b/addons/webinterface.default/addon.xml index 9076851493..0fa6f40337 100644 --- a/addons/webinterface.default/addon.xml +++ b/addons/webinterface.default/addon.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <addon id="webinterface.default" - version="2.0.0" + version="2.0.1" name="Default" provider-name="Team XBMC"> <requires> diff --git a/addons/webinterface.default/index.html b/addons/webinterface.default/index.html index 9a29eb0d87..4d816d1755 100755 --- a/addons/webinterface.default/index.html +++ b/addons/webinterface.default/index.html @@ -4,15 +4,15 @@ <title>XBMC</title> <meta http-equiv="Content-Language" content="EN" /> <meta http-equiv="Content-Type" content="UTF-8" /> - <!-- <link rel="search" href="/provider.xml" type="application/opensearchdescription+xml" title="XBMC Library" /> --> - <link rel="icon" href="/favicon.ico" type="image/x-icon"> - <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"> + <!-- <link rel="search" href="provider.xml" type="application/opensearchdescription+xml" title="XBMC Library" /> --> + <link rel="icon" href="favicon.ico" type="image/x-icon"> + <link rel="shortcut icon" href="favicon.ico" type="image/x-icon"> <!-- <link href="/images/logo.png" rel="image_src" /> --> <meta name="robots" content="NOINDEX, NOFOLLOW"> - <link href="/css/core.css?1.3.57" rel="stylesheet" type="text/css"> - <link href="/css/ipad.css?1.0.5" rel="stylesheet" media="only screen and (max-device-width: 1024px)" type="text/css"> - <script type="text/javascript" src="/js/jquery-1.5.2.js"></script> - <script type="text/javascript" src="/js/Launcher.js?1.0.0"></script> + <link href="css/core.css?1.3.57" rel="stylesheet" type="text/css"> + <link href="css/ipad.css?1.0.5" rel="stylesheet" media="only screen and (max-device-width: 1024px)" type="text/css"> + <script type="text/javascript" src="js/jquery-1.5.2.js"></script> + <script type="text/javascript" src="js/Launcher.js?1.0.0"></script> </head> <body> <div id="header"> @@ -27,7 +27,7 @@ <!-- <li id="settingsPanel">Settings</li> --> </ul> </div> - <img src="/images/ajax-loader.gif" alt="Loading please wait" id="spinner" style="display: none"> + <img src="images/ajax-loader.gif" alt="Loading please wait" id="spinner" style="display: none"> </div> <div id="body"> <div id="topScrollFade" style="display: none;"></div> diff --git a/addons/webinterface.default/js/Core.js b/addons/webinterface.default/js/Core.js index a01e3ba149..01b6b76e3a 100644 --- a/addons/webinterface.default/js/Core.js +++ b/addons/webinterface.default/js/Core.js @@ -21,7 +21,7 @@ /* Global Paths */ -var JSON_RPC = '/jsonrpc'; +var JSON_RPC = 'jsonrpc'; var DEFAULT_ALBUM_COVER = 'images/DefaultAlbumCover.png'; var DEFAULT_VIDEO_COVER = 'images/DefaultVideo.png'; diff --git a/addons/webinterface.default/js/MediaLibrary.js b/addons/webinterface.default/js/MediaLibrary.js index 64b0a40e2e..01c275643b 100755 --- a/addons/webinterface.default/js/MediaLibrary.js +++ b/addons/webinterface.default/js/MediaLibrary.js @@ -454,7 +454,7 @@ MediaLibrary.prototype = { } }, getThumbnailPath: function(thumbnail) { - return thumbnail ? ('/image/' + encodeURI(thumbnail)) : DEFAULT_ALBUM_COVER; + return thumbnail ? ('image/' + encodeURI(thumbnail)) : DEFAULT_ALBUM_COVER; }, generateThumb: function(type, thumbnail, title, artist) { var floatableAlbum = $('<div>'); @@ -752,7 +752,7 @@ MediaLibrary.prototype = { displayEpisodeDetails: function(event) { var episodeDetails = $('<div>').attr('id', 'episode-' + event.data.episode.episodeid).addClass('episodePopoverContainer'); - episodeDetails.append($('<img>').attr('src', '/images/close-button.png').addClass('closeButton').bind('click', jQuery.proxy(this.hideOverlay, this))); + episodeDetails.append($('<img>').attr('src', 'images/close-button.png').addClass('closeButton').bind('click', jQuery.proxy(this.hideOverlay, this))); episodeDetails.append($('<img>').attr('src', this.getThumbnailPath(event.data.episode.thumbnail)).addClass('episodeCover')); episodeDetails.append($('<div>').addClass('playIcon').bind('click', {episode: event.data.episode}, jQuery.proxy(this.playTVShow, this))); var episodeTitle = $('<p>').addClass('episodeTitle'); @@ -838,7 +838,7 @@ MediaLibrary.prototype = { }, displayMovieDetails: function(event) { var movieDetails = $('<div>').attr('id', 'movie-' + event.data.movie.movieid).addClass('moviePopoverContainer'); - movieDetails.append($('<img>').attr('src', '/images/close-button.png').addClass('closeButton').bind('click', jQuery.proxy(this.hideOverlay, this))); + movieDetails.append($('<img>').attr('src', 'images/close-button.png').addClass('closeButton').bind('click', jQuery.proxy(this.hideOverlay, this))); movieDetails.append($('<img>').attr('src', this.getThumbnailPath(event.data.movie.thumbnail)).addClass('movieCover')); movieDetails.append($('<div>').addClass('playIcon').bind('click', {movie: event.data.movie}, jQuery.proxy(this.playMovie, this))); var movieTitle = $('<p>').addClass('movieTitle'); diff --git a/addons/webinterface.default/js/NowPlayingManager.js b/addons/webinterface.default/js/NowPlayingManager.js index d251168f76..4a9ca81e94 100755 --- a/addons/webinterface.default/js/NowPlayingManager.js +++ b/addons/webinterface.default/js/NowPlayingManager.js @@ -382,7 +382,7 @@ NowPlayingManager.prototype = { this.lastPlaylistItem = this.activePlaylistItem; var imgPath = DEFAULT_ALBUM_COVER; if (this.activePlaylistItem.thumbnail) { - imgPath = '/image/' + encodeURI(this.activePlaylistItem.thumbnail); + imgPath = 'image/' + encodeURI(this.activePlaylistItem.thumbnail); } $('#audioCoverArt').html('<img src="' + imgPath + '" alt="' + this.activePlaylistItem.album + ' cover art">'); $('#audioTrackTitle').html('<span title="' + this.activePlaylistItem.title + '">' + this.activePlaylistItem.title + '</span>'); @@ -430,7 +430,7 @@ NowPlayingManager.prototype = { this.lastPlaylistItem = this.activePlaylistItem; var imgPath = DEFAULT_VIDEO_COVER; if (this.activePlaylistItem.thumbnail) { - imgPath = '/image/' + encodeURI(this.activePlaylistItem.thumbnail); + imgPath = 'image/' + encodeURI(this.activePlaylistItem.thumbnail); } $('#videoCoverArt').html('<img src="' + imgPath + '" alt="' + this.activePlaylistItem.title + ' cover art">'); $('#videoShowTitle').html(this.activePlaylistItem.showtitle||' '); diff --git a/addons/xbmc.addon/addon.xml b/addons/xbmc.addon/addon.xml index 20b9da0fae..feeff690c1 100644 --- a/addons/xbmc.addon/addon.xml +++ b/addons/xbmc.addon/addon.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<addon id="xbmc.addon" version="11.9.4" provider-name="Team XBMC"> +<addon id="xbmc.addon" version="11.9.5" provider-name="Team XBMC"> <requires> <import addon="xbmc.core" version="0.1"/> </requires> diff --git a/addons/xbmc.python/addon.xml b/addons/xbmc.python/addon.xml index b3d1099821..0010c1cae2 100644 --- a/addons/xbmc.python/addon.xml +++ b/addons/xbmc.python/addon.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<addon id="xbmc.python" version="2.0" provider-name="Team XBMC"> +<addon id="xbmc.python" version="2.1" provider-name="Team XBMC"> <backwards-compatibility abi="1.0"/> <requires> <import addon="xbmc.core" version="0.1"/> diff --git a/configure.in b/configure.in index d44825f8ae..a0fd2c56f9 100755..100644 --- a/configure.in +++ b/configure.in @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -AC_INIT([xbmc], [11.9.4], [http://trac.xbmc.org]) +AC_INIT([xbmc], [11.9.5], [http://trac.xbmc.org]) AC_CONFIG_HEADERS([xbmc/config.h]) AH_TOP([#pragma once]) m4_include([m4/ax_python_devel.m4]) @@ -15,6 +15,21 @@ tolower(){ echo "$@" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz } +# check for enabling additional players +AC_DEFUN([XB_ADD_PLAYER], +[ + AC_MSG_CHECKING([for $2]) + case $add_players in + *$2*) + AC_SUBST([USE_$1], 1) + AC_DEFINE([HAS_$1], 1, [using $2]) + AC_MSG_RESULT([enabling $2]) + ;; + *) + AC_MSG_RESULT([$2 is not enabled]) + esac +]) + # check for library basenames AC_DEFUN([XB_FIND_SONAME], [ @@ -27,8 +42,12 @@ AC_DEFUN([XB_FIND_SONAME], elif [[ "$host_vendor" != "apple" ]]; then AC_MSG_CHECKING([for lib$2 soname]) $1_FILENAME=$($CC -nostdlib -o /dev/null $LDFLAGS -l$2 -Wl,-M 2>/dev/null | grep "^LOAD.*$2" | awk '{V=2; print $V}') + if [[ -z $$1_FILENAME ]]; then + #try gold linker syntax + $1_FILENAME=$($CC -nostdlib -o /dev/null $LDFLAGS -l$2 -Wl,-t 3>&1 1>&2 2>&3 | grep "$2") + fi if [[ ! -z $$1_FILENAME ]]; then - $1_SONAME=$(objdump -p $$1_FILENAME | grep "SONAME.*$2" | awk '{V=2; print $V}') + $1_SONAME=$($OBJDUMP -p $$1_FILENAME | grep "SONAME.*$2" | awk '{V=2; print $V}') fi else AC_MSG_CHECKING([for lib$2 dylib]) @@ -454,6 +473,12 @@ AC_ARG_ENABLE([libcap], [use_libcap=$enableval], [use_libcap=auto]) +AC_ARG_ENABLE([player], + [AS_HELP_STRING([--enable-player], + [enable additional players from a list of comma separated names, (default is none, choices are amlplayer)])], + [add_players=$enableval], + [add_players=no]) + ### External libraries options AC_ARG_ENABLE([external-libraries], [AS_HELP_STRING([--enable-external-libraries], @@ -486,9 +511,25 @@ AC_PROG_AWK AC_PROG_LN_S AC_PROG_MAKE_SET MAKE="${MAKE:-make}" +OBJDUMP="${OBJDUMP:-objdump}" + +# ffmpeg needs the output of uname -s (e.x. linux, darwin) for the target_os +# there is no autoconf variable which will give +# the correct output format when doing cross compilation +# so we have to use our own var here +# defaults to the build side target_os +# and should be overridden for cross below (see android) +ffmpeg_target_os=$(tolower $(uname -s)) # host detection and setup case $host in + i*86*-android-linux-gnu*) + target_platform=target_android + ARCH="i486-linux" + use_arch="x86" + use_cpu="i686" + ffmpeg_target_os=linux + ;; i*86*-linux-gnu*) ARCH="i486-linux" AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") @@ -567,11 +608,37 @@ case $host in use_arch="arm" AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") ;; + arm*-*linux-android*) + target_platform=target_android + use_arch="arm" + use_cpu=cortex-a9 + ARCH="arm" + ffmpeg_target_os=linux + ;; *) AC_MSG_ERROR(unsupported host ($host)) esac AC_SUBST([ARCH]) + +check_sdl_arch=[`file $USE_TEXTUREPACKER_NATIVE_ROOT/lib/libSDL_image.dylib | awk '{print $NF}'`] +if test "x$check_sdl_arch" = "xi386" ; then + DARWIN_NATIVE_ARCH=-m32 +elif test "x$check_sdl_arch" = "xx86_64" ; then + DARWIN_NATIVE_ARCH=-m64 +fi +AC_SUBST([DARWIN_NATIVE_ARCH]) + +if test "$target_platform" = "target_android" ; then + USE_ANDROID=1 + use_texturepacker_native=yes + webserver_checkdepends=yes + AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX -DTARGET_ANDROID") + CFLAGS="$CFLAGS -Wno-psabi" + CXXFLAGS="$CXXFLAGS -Wno-psabi" + AC_DEFINE(HAS_EGLGLES, [1], [Define if supporting EGL based GLES Framebuffer]) +fi + if test "$build_shared_lib" = "yes"; then final_message="$final_message\n Shared lib\tYes" AC_SUBST(USE_LIBXBMC,1) @@ -703,6 +770,19 @@ AC_LANG_PUSH([C++]) AC_CHECK_HEADER([boost/shared_ptr.hpp],, AC_MSG_ERROR($missing_library)) AC_LANG_POP([C++]) +# Python +if test -z "$PYTHON_NOVERSIONCHECK"; then + AX_PYTHON_DEVEL([>= 2.4]) + PYTHON_VERSION=$ac_python_version +fi + +if test -z "$PYTHON_VERSION"; then + AC_MSG_ERROR([Can't find a Python version.]) +else + LIBS="$LIBS $PYTHON_LDFLAGS" + AC_MSG_NOTICE([Using Python $PYTHON_VERSION]) +fi + # Checks for platforms libraries. if test "$use_gles" = "yes"; then use_gl="no" @@ -738,11 +818,11 @@ fi # platform common libraries if test "$use_mysql" = "yes"; then - AC_CHECK_PROG(MYSQL_CONFIG, mysql_config, "yes", "no") - if test $MYSQL_CONFIG = "yes"; then + AC_PATH_PROG(MYSQL_CONFIG, mysql_config,"no") + if test "x$MYSQL_CONFIG" != "xno"; then AC_DEFINE([HAVE_MYSQL],[1],["Define to 1 if you have the `mysql' library (-lmysqlclient)."]) - INCLUDES="$INCLUDES `mysql_config --include`" - MYSQL_LIBS=`mysql_config --libs` + INCLUDES="$INCLUDES `$MYSQL_CONFIG --include`" + MYSQL_LIBS=`$MYSQL_CONFIG --libs` LIBS="$LIBS $MYSQL_LIBS" AC_SUBST(MYSQL_LIBS) else @@ -770,6 +850,7 @@ AC_CHECK_HEADER([openssl/crypto.h], AC_DEFINE([HAVE_OPENSSL],[1],[Define if we h AC_CHECK_HEADER([gcrypt.h], gcrypt_headers_available=yes,gcrypt_headers_available=no) if test "$gcrypt_headers_available" = "yes"; then # if we have the headers then we must have the lib + AC_CHECK_LIB([gpg-error],[main],, AC_MSG_ERROR($missing_library)) AC_CHECK_LIB([gcrypt],[gcry_control],, AC_MSG_ERROR($missing_library)) AC_DEFINE([HAVE_GCRYPT],[1],[Define if we have gcrypt]) fi @@ -780,7 +861,9 @@ AC_CHECK_LIB([tiff], [main],, AC_MSG_ERROR($missing_library)) if echo "$ARCH" | grep -q freebsd; then AC_CHECK_LIB([pthread], [main],LIBS="-pthread $LIBS", AC_MSG_ERROR($missing_library)) else -AC_CHECK_LIB([pthread], [main],, AC_MSG_ERROR($missing_library)) +if test "$target_platform" != "target_android" ; then + AC_CHECK_LIB([pthread], [main],, AC_MSG_ERROR($missing_library)) +fi fi AC_CHECK_LIB([lzo2], [main],, AC_MSG_ERROR($missing_library)) AC_CHECK_LIB([z], [main],, AC_MSG_ERROR($missing_library)) @@ -793,10 +876,11 @@ AC_CHECK_LIB([ssh], [sftp_tell64],, AC_MSG_RESULT([Could not find suitab AC_CHECK_LIB([bluetooth], [hci_devid],, AC_MSG_RESULT([Could not find suitable version of libbluetooth])) AC_CHECK_LIB([yajl], [main],, AC_MSG_ERROR($missing_library)) AC_CHECK_LIB([tinyxml], [main],, AC_MSG_ERROR($missing_library)) - -PKG_CHECK_MODULES([FONTCONFIG], [fontconfig], - [INCLUDES="$INCLUDES $FONTCONFIG_CFLAGS"; LIBS="$LIBS $FONTCONFIG_LIBS"], - AC_MSG_ERROR($missing_library)) +if test "$target_platform" = "target_android" ; then + #android hack for static python. Required to maintain correct linking order. + AC_CHECK_LIB([python$PYTHON_VERSION], [main],, AC_MSG_ERROR($missing_library)) + AC_CHECK_LIB([android], [main],, AC_MSG_ERROR($missing_library)) +fi PKG_CHECK_MODULES([FRIBIDI], [fribidi], [INCLUDES="$INCLUDES $FRIBIDI_CFLAGS"; LIBS="$LIBS $FRIBIDI_LIBS"], AC_MSG_ERROR($missing_library)) @@ -806,14 +890,14 @@ PKG_CHECK_MODULES([SQLITE3], [sqlite3], PKG_CHECK_MODULES([PNG], [libpng], [INCLUDES="$INCLUDES $PNG_CFLAGS"; LIBS="$LIBS $PNG_LIBS"], AC_MSG_ERROR($missing_library)) -PKG_CHECK_MODULES([PCRE], [libpcre], - [INCLUDES="$INCLUDES $PCRE_CFLAGS"; LIBS="$LIBS $PCRE_LIBS"]; \ - AC_DEFINE([HAVE_LIBPCRE],[1],["Define to 1 if libpcre is installed"]), - AC_MSG_ERROR($missing_library)) PKG_CHECK_MODULES([PCRECPP], [libpcrecpp], [INCLUDES="$INCLUDES $PCRECPP_CFLAGS"; LIBS="$LIBS $PCRECPP_LIBS"]; \ AC_DEFINE([HAVE_LIBPCRECPP],[1],["Define to 1 if libpcrecpp is installed"]), AC_MSG_ERROR($missing_library)) +PKG_CHECK_MODULES([PCRE], [libpcre], + [INCLUDES="$INCLUDES $PCRE_CFLAGS"; LIBS="$LIBS $PCRE_LIBS"]; \ + AC_DEFINE([HAVE_LIBPCRE],[1],["Define to 1 if libpcre is installed"]), + AC_MSG_ERROR($missing_library)) PKG_CHECK_MODULES([CDIO], [libcdio], [INCLUDES="$INCLUDES $CDIO_CFLAGS"; LIBS="$LIBS $CDIO_LIBS"], AC_MSG_ERROR($missing_library)) @@ -824,6 +908,12 @@ PKG_CHECK_MODULES([FREETYPE2], [freetype2], [INCLUDES="$INCLUDES $FREETYPE2_CFLAGS"; LIBS="$LIBS $FREETYPE2_LIBS"], AC_MSG_ERROR($missing_library)) +if test "$target_platform" = "target_android" ; then +PKG_CHECK_MODULES([ZIP], [libzip], + [INCLUDES="$INCLUDES $ZIP_CFLAGS"; LIBS="$LIBS $ZIP_LIBS"], + AC_MSG_ERROR($missing_library)) +fi + # check for libbluray AS_CASE([x$use_libbluray], [xyes],[ @@ -858,19 +948,25 @@ else esac case $host_os in freebsd*) ;; - *) AC_CHECK_LIB([resolv], [main],, AC_MSG_ERROR($missing_library)) ;; + *) + if test "$target_platform" != "target_android" ; then + AC_CHECK_LIB([resolv], [main],, AC_MSG_ERROR($missing_library)) + fi + ;; esac +if test "$target_platform" != "target_android" ; then AC_CHECK_LIB([jasper], [main],, AC_MSG_ERROR($missing_library)) # check for cximage AC_CHECK_LIB([rt], [clock_gettime],, AC_MSG_ERROR($missing_library)) - +fi +if test "x$use_alsa" != "xno"; then PKG_CHECK_MODULES([ALSA], [alsa], [INCLUDES="$INCLUDES $ALSA_CFLAGS"; LIBS="$LIBS $ALSA_LIBS"; use_alsa=yes], AC_MSG_NOTICE($alsa_not_found); use_alsa=no) +fi PKG_CHECK_MODULES([DBUS], [dbus-1], [INCLUDES="$INCLUDES $DBUS_CFLAGS"; LIBS="$LIBS $DBUS_LIBS"; use_dbus=yes]; \ AC_DEFINE([HAVE_DBUS],[1],["Define to 1 if dbus is installed"]), AC_MSG_NOTICE($missing_library); use_dbus=no) - if test "x$use_sdl" != "xno"; then PKG_CHECK_MODULES([SDL], [sdl], [INCLUDES="$INCLUDES $SDL_CFLAGS"; LIBS="$LIBS $SDL_LIBS"], @@ -1167,7 +1263,7 @@ fi # libplist for airplay feature USE_AIRPLAY=0 if test "$use_airplay" != "no"; then - AC_CHECK_LIB([plist],[main],, + AC_CHECK_HEADER([plist/plist.h],, [if test "$use_airplay" = "yes"; then AC_MSG_ERROR($libplist_not_found) elif test "$use_airplay" != "no"; then @@ -1179,13 +1275,14 @@ if test "$use_airplay" != "no"; then if test "$use_airplay" != "no"; then XB_FIND_SONAME([PLIST], [plist], [use_airplay]) USE_AIRPLAY=1 + AC_DEFINE([HAVE_LIBPLIST],[1],["Define to 1 if you have libplist."]) fi fi # libshairport for AirTunes USE_AIRTUNES=0 if test "x$use_airtunes" != "xno"; then - AC_CHECK_LIB([shairport], [shairport_set_ao],, + AC_CHECK_HEADERS([shairport/shairport.h shairport/ao.h],, [if test "x$use_airtunes" = "xyes"; then AC_MSG_ERROR($libshairport_not_found) elif test "x$use_airtunes" != "xno"; then @@ -1197,6 +1294,9 @@ if test "x$use_airtunes" != "xno"; then if test "x$use_airtunes" != "xno"; then XB_FIND_SONAME([SHAIRPORT], [shairport], [use_airtunes]) USE_AIRTUNES=1 + AC_CHECK_MEMBERS([struct AudioOutput.ao_set_metadata],,, + [[#include <shairport/shairport.h>]]) + AC_DEFINE([HAVE_LIBSHAIRPORT],[1],["Define to 1 if you have libshairport."]) fi fi @@ -1389,18 +1489,6 @@ else AC_DEFINE([PIX_FMT_VDPAU_MPEG4_IN_AVUTIL], [1], [Whether AVUtil defines PIX_FMT_VDPAU_MPEG4.]) fi -# Python -if test -z "$PYTHON_NOVERSIONCHECK"; then - AX_PYTHON_DEVEL([>= 2.4]) - PYTHON_VERSION=$ac_python_version -fi - -if test -z "$PYTHON_VERSION"; then - AC_MSG_ERROR([Can't find a Python version.]) -else - AC_MSG_NOTICE([Using Python $PYTHON_VERSION]) -fi - # VDPAU if test "x$use_vdpau" != "xno"; then if test "$host_vendor" = "apple" ; then @@ -1562,6 +1650,14 @@ AC_CHECK_HEADERS([yajl/yajl_version.h], [], [ AC_DEFINE(YAJL_MAJOR, 1, [yajl version 1]) ], []) +# additional internal players +case $add_players in + *amlplayer*) + AC_CHECK_HEADER([amlplayer/amports/amstream.h],, AC_MSG_ERROR($missing_headers)) + XB_ADD_PLAYER([AMLPLAYER], [amlplayer]) + ;; +esac + # platform specific bin utilities if test "$host_vendor" != "apple" ; then AC_CHECK_PROG(HAVE_GAWK,gawk,"yes","no",) @@ -1981,6 +2077,12 @@ else final_message="$final_message\n libcap support:\tNo" fi +if test "x$add_players" != "xno"; then + final_message="$final_message\n additional players:\tYes" +else + final_message="$final_message\n additional players:\tNo" +fi + ### External libraries messages if test "$use_external_ffmpeg" = "yes"; then @@ -2013,6 +2115,7 @@ OUTPUT_FILES="Makefile \ lib/Makefile \ lib/libdvd/Makefile \ xbmc/cores/DllLoader/Makefile \ + xbmc/cores/DllLoader/exports/Makefile \ xbmc/cores/dvdplayer/DVDCodecs/Makefile \ xbmc/cores/dvdplayer/DVDCodecs/Audio/Makefile \ xbmc/cores/dvdplayer/DVDCodecs/Overlay/Makefile \ @@ -2021,6 +2124,7 @@ OUTPUT_FILES="Makefile \ xbmc/cores/dvdplayer/DVDSubtitles/Makefile \ xbmc/cores/AudioEngine/Makefile \ xbmc/cores/paplayer/Makefile \ + xbmc/cores/amlplayer/Makefile \ lib/timidity/Makefile \ lib/xbadpcm/Makefile \ lib/asap/Makefile \ @@ -2048,6 +2152,7 @@ OUTPUT_FILES="Makefile \ xbmc/interfaces/python/xbmcmodule/Makefile \ lib/libUPnP/Makefile \ xbmc/DllPaths_generated.h \ + xbmc/DllPaths_generated_android.h \ xbmc/freebsd/Makefile \ xbmc/linux/Makefile \ xbmc/filesystem/Makefile \ @@ -2057,12 +2162,15 @@ OUTPUT_FILES="Makefile \ xbmc/visualizations/OpenGLSpectrum/Makefile \ xbmc/visualizations/WaveForm/Makefile \ xbmc/visualizations/iTunes/Makefile \ + xbmc/visualizations/EGLHelpers/Makefile \ tools/Linux/xbmc.sh \ tools/Linux/xbmc-standalone.sh \ tools/TexturePacker/Makefile \ tools/EventClients/Clients/OSXRemote/Makefile \ xbmc/peripherals/bus/Makefile \ - xbmc/peripherals/devices/Makefile" + xbmc/peripherals/devices/Makefile \ + xbmc/android/activity/Makefile \ + xbmc/android/loader/Makefile" if test "$use_skin_touched" = "yes"; then OUTPUT_FILES="$OUTPUT_FILES addons/skin.touched/media/Makefile" @@ -2124,6 +2232,7 @@ AC_SUBST(USE_LIBUSB) AC_SUBST(USE_LIBCEC) AC_SUBST(USE_MYSQL) AC_SUBST(USE_WEB_SERVER) +AC_SUBST(USE_ANDROID) # pushd and popd are not available in other shells besides bash, so implement @@ -2178,7 +2287,7 @@ fi XB_CONFIG_MODULE([lib/ffmpeg], [ if test "$host_vendor" = "apple" ; then - ffmpg_config="--target-os=$(tolower $(uname -s))" + ffmpg_config="--target-os=$ffmpeg_target_os" # handle disables first, we do individual enables later ffmpg_config="$ffmpg_config --disable-muxers --disable-encoders" ffmpg_config="$ffmpg_config --disable-devices --disable-doc" @@ -2250,6 +2359,8 @@ XB_CONFIG_MODULE([lib/ffmpeg], [ sed -ie "s# -D_ISOC99_SOURCE -D_POSIX_C_SOURCE=200112 # #" config.mak else CFLAGS="" \ + CPPFLAGS="" \ + CXXFLAGS="" \ LDFLAGS="$(echo "$LDFLAGS" | sed "s/-Wl,-Bsymbolic-functions//g")" \ ./configure \ --extra-cflags="$PASSED_CFLAGS $FFMPEG_EXTRACFLAGS" \ @@ -2259,7 +2370,7 @@ XB_CONFIG_MODULE([lib/ffmpeg], [ `if test "$use_arch" != "no"; then echo --arch=$use_arch; fi`\ `if test "$use_cpu" != "no"; then echo --cpu=$use_cpu; fi`\ `if test "$use_neon" = "yes"; then echo --enable-neon; else echo --disable-neon; fi`\ - --target-os=$(tolower $(uname -s)) \ + --target-os=$ffmpeg_target_os \ --disable-muxers \ --enable-muxer=spdif \ --enable-muxer=adts \ @@ -2280,10 +2391,13 @@ XB_CONFIG_MODULE([lib/ffmpeg], [ --enable-gpl \ `if test "x$use_vdpau" != "xno"; then echo --enable-vdpau; else echo --disable-vdpau; fi` \ `if test "x$use_vaapi" != "xno"; then echo --enable-vaapi; else echo --disable-vaapi; fi` \ + `if test "$use_optimizations" != "no"; then echo --enable-optimizations; else echo --disable-optimizations; fi` \ --enable-protocol=http \ --enable-pthreads \ --enable-runtime-cpudetect \ - --custom-libname-with-major="\$(FULLNAME)-\$(LIBMAJOR)-${ARCH}\$(SLIBSUF)" \ + `if test "$target_platform" = "target_android" && test "$host_cpu" = "i686"; then echo --disable-mmx; fi #workaround for gcc 4.6 bug` \ + `if test "$target_platform" = "target_android"; then echo "--custom-libname-with-major=\\$(SLIBPREF)\\$(FULLNAME)-\\$(LIBMAJOR)-${ARCH}\\$(SLIBSUF)"; \ + else echo "--custom-libname-with-major=\\$(FULLNAME)-\\$(LIBMAJOR)-${ARCH}\\$(SLIBSUF)"; fi` \ `case $host_cpu in i?86*) echo --disable-pic ;; *) echo --enable-pic ;; esac` \ --cc="$CC" && sed -i -e "s#define HAVE_SYMVER 1#define HAVE_SYMVER 0#" config.h && @@ -2425,7 +2539,7 @@ XB_CONFIG_MODULE([lib/cpluff], [ --prefix="${prefix}" --includedir="${includedir}" --libdir="${libdir}" --datadir="${datadir}" \ --host=$host_alias \ --build=$build_alias \ - --target=$target_alias CFLAGS="$CFLAGS" CC="$CC" CXX="$CXX" LDFLAGS="$LDFLAGS" + --target=$target_alias CFLAGS="$CFLAGS" CC="$CC" CXX="$CXX" LDFLAGS="$LDFLAGS" LIBS="" #LDFLAGS="$LDFLAGS -Wl,-read_only_relocs,suppress" ], [0]) diff --git a/docs/README.android b/docs/README.android new file mode 100644 index 0000000000..feb96ccc9d --- /dev/null +++ b/docs/README.android @@ -0,0 +1,304 @@ +TOC +1. Introduction +2. Installing and setting up the Android environment +3. Getting the source code +4. Installing the required Ubuntu packages +5. How to compile +6. Installing XBMC in an Android system +7. Running and debugging XBMC in an Android system +8. Architecture +9. Useful Commands + +----------------------------------------------------------------------------- +1. Introduction +----------------------------------------------------------------------------- + +We currently recommend Ubuntu Natty (11.04) or later. Current work has been +done here. Additionally, building from OSX Snow Leopard is working. + +NOTE TO NEW USERS: All lines that are prefixed with the '#' +character are commands that need to be typed into a terminal window / +console (similar to the command prompt for Windows). Note that the '#' +character itself should NOT be typed as part of the command. + +----------------------------------------------------------------------------- +2. Installing the required Ubuntu packages +----------------------------------------------------------------------------- +These are the minimum packages necessary for building XBMC. Non-Ubuntu +users will need to get the equivalents. + + # sudo apt-get install build-essential default-jdk git curl autoconf \ + unzip zip zlib1g-dev gawk gperf + +If you run a 64bit operating system you will also need to get ia32-libs + + # sudo apt-get install ia32-libs + + +----------------------------------------------------------------------------- +3. Installing and setting up the Android environment +----------------------------------------------------------------------------- + +To develop XBMC for Android the Android SDK and NDK are required. +Because the Android NDK is lacking support for wide characters (wchar_t) +which XBMC relies on for Unicode implementation, a third-party NDK +from Crystax is being used. + +-------------------------------------------------------------------- +3.1. Getting the Android SDK and NDK +-------------------------------------------------------------------- + +To get the Android SDK, go to http://developer.android.com/sdk and +download the latest version for your operating system. The Crystax NDK +can be downloaded from http://www.crystax.net/en/android/ndk + +[NOTICE] Compiling XBMC for Android requires at least Crystax Android NDK + Revision 7b. Crystax Android NDK Revision 7 and earlier do not work + properly for our cause. The corresponding Crystax NDK version + is android-ndk-r7-crystax-5. Do not use the standard Android NDK. + +After downloading the SDK and NDK extract the files contained in the +archives to your harddisk. + +Make sure you have a recent JRE and JDK installed otherwise the +Android SDK will not work. + +-------------------------------------------------------------------- +3.2. Installing Android SDK packages +-------------------------------------------------------------------- + +After having extracted the Android SDK to <android-sdk> you need to +install some android packages using the Android SDK Manager: + + # cd <android-sdk>/tools + # ./android update sdk -u -t platform,platform-tool + +-------------------------------------------------------------------- +3.3. Setup the Android toolchain +-------------------------------------------------------------------- + +To be able to compile XBMC and the libraries it depends on for the +Android platform you first need to setup an Android toolchain using +the Android NDK which you earlier extracted to <android-ndk>. The +following commands will create a toolchain suitable for the most +common scenario. +The --install-dir option (and therefore the <android-toolchain> value) +specifies where the resulting toolchain should be installed (your choice). + + # cd <android-ndk> + # ls platforms + # cd build/tools + # ./make-standalone-toolchain.sh --ndk-dir=../../ \ + --install-dir=<android-toolchain>/android-9 --platform=android-9 + +ATTENTION FOR X86 BUILDS - THIS DOES NOT APPLY TO 99% OF BUILDS: +If you want to build for the x86 platform there is a flaw in the mentioned +NDK. See http://code.google.com/p/android/issues/detail?id=19851 which results +in linker errors mentioning "sigsetjmp and siglongjmp". +In that case you have to download the libc.tar.bz2 from that google issue +entry: + +http://android.googlecode.com/issues/attachment?aid=198510003000&name=libc.tar.bz2&token=6uNpHc1v8ixmVOTq3y6-ohUfb0o%3A1341156659947 + +And extract it to <android-toolchain>/android-<x>/sysroot/usr/lib/ and overwrite +the libc.so there. (where <android-toolchain>/android-<x>/ is the path you have given on the +--install-dir option above) + +-------------------------------------------------------------------- +3.4. Create a (new) debug key to sign debug APKs +-------------------------------------------------------------------- + + All packages must be signed. The following command will generate a + self-signed debug key. If the result is a cryptic error, it + probably just means a debug key already existed, no cause for alarm. + + # keytool -genkey -keystore ~/.android/debug.keystore -v -alias \ + androiddebugkey -dname "CN=Android Debug,O=Android,C=US" -keypass \ + android -storepass android -keyalg RSA -keysize 2048 -validity 10000 + +----------------------------------------------------------------------------- +4. Getting the source code +----------------------------------------------------------------------------- + + # cd $HOME + # git clone git://github.com/xbmc/xbmc.git xbmc-android + # cd xbmc-android + # git submodule update --init addons/skin.touched + +----------------------------------------------------------------------------- +5. How to compile +----------------------------------------------------------------------------- + +Compiling XBMC for Android consists of compiling the libraries XBMC depends +on with the Android toolchain and creating an Android Application Package +(APK) which can be installed in an Android system. + +-------------------------------------------------------------------- +5.1. Building dependencies +-------------------------------------------------------------------- + + # cd $HOME/xbmc-android/tools/android/depends + # ./bootstrap + # ./configure --help + + Run configure with the correct settings for you local configuration. + + Anyone working on the dependencies themselves will want to set the + environment variables specified in ~/.bashrc or similar, to avoid + having to input these with each configure. + + # make -j <jobs> + + This build was designed to be massively parallel. Don't be afraid to + give it a 'make -j20' or so. + + Verify that all deps built correctly (it will tell you so) before + continuing. You will get crazy build errors otherwise. + +-------------------------------------------------------------------- +5.2. Building XBMC +-------------------------------------------------------------------- + + # cd $HOME/xbmc-android + # make -C tools/android/depends/xbmc + + After the first build (assuming bootstrap and configure are successful), + subsequent builds can be run with a simple 'make' and 'make apk'. + +----------------------------------------------------------------------------- +6. Installing XBMC in an Android system +----------------------------------------------------------------------------- + +To install XBMC through the previously built APK in an Android system you can +either install it on a real device (smartphone/tablet/...) running Android + >= 2.3.x. + +-------------------------------------------------------------------- +6.1. Installing XBMC on the Android device +-------------------------------------------------------------------- + +Make sure your Android device is connected to your computer through +USB. Furthermore you have to enable the following option in your +device's Android settings: + + - Applications + [X] Unknown sources + + # cd $HOME/xbmc-android/tools/android/packaging + # adb devices + # adb -s <device-id> install -r images/xbmcapp-debug.apk + +The <device-id> can be retrieved from the list returned by the +"adb devices" command and is the first value in the row representing +your device. + +----------------------------------------------------------------------------- +7. Running and debugging XBMC in an Android system +----------------------------------------------------------------------------- + +After installing XBMC's APK in an Android system you can start it using its +Launcher icon in Android's Application Launcher. + +-------------------------------------------------------------------- +7.1. Debugging XBMC +-------------------------------------------------------------------- + +To be able to see what is happening while running XBMC you first need +to enable USB debugging in your Android settings (this is already done +when using the emulator): + + - Applications + [X] Unknown sources + - Development + [X] USB debugging + +To access the log output of your Android system run (the -s parameter +and the <device-id> may not be needed when using the Android emulator) + + # adb -s <device-id> logcat + + +-------------------------------------------------------------------- +7.2. GDB +-------------------------------------------------------------------- + +GDB can be used to debug, though the support is rather primitive. Rather than +using gdb directly, you will need to use ndk-gdb which wraps it. Do NOT trust +the -p/--project switches, as of ndk7b they do not work. Instead you will need +to cd to tools/android/packaging/xbmc and execute it from there. + + # ndk-gdb --start --delay=0 + +This will open the installed version of XBMC and break. The warnings can be +ignored as we have setup the appropriate paths already. + +-------------------------------------------------------------------- +8. Architecture +-------------------------------------------------------------------- + +During the early days of the android port, xbmc was launched via a stub lib +that then dlopen'd libxbmc. This was done to get around bionic's poor handling +of shared libs. We now compile everything into libxbmc itself so that it has +no runtime dependencies beyond system libs. Done this way, we're able to launch +into libxbmc directly. + +But we still hit Bionic's loader's deficiencies when we dlopen a lib. There are +two main issues to overcome for loading: + +1. Bionic imports all symbols for a lib as soon as it is loaded, and it will +refuse to open a lib if it has a single unresolved symbol + +2. It does not search recursively during the resolve. So if liba depends on +libb, dlopen'ing liba will _not_ pull in missing symbols from libb. This is +particularly nasty considering #1. + +To work-around these problems we use our own recursive loader in place of +dlopen. This loader mimics expected behavior. Using the example above, loading +libb before liba will mean that everything will resolve correctly. + +Additionally, Android does not use versioned solibs. libfoo.so.1 which is +typical on linux would not be found by the loader. This means that we must +strip the SONAME and NEEDED values out of the libs as well as changing the +filenames themselves. The cleaner solution would be to patch libtool/cmake/etc +to not add versioning in the first place. For now, we use the brute-force +approach of modifying the binary and blanking out the versions. + +See here for more info: +http://www.bernawebdesign.ch/byteblog/2011/11/23/creating-non-versioned-shared-libraries-for-android/ + +As a final gotcha, all libs must be in the form of ^lib.*so$ with no +exceptions (they won't even install otherwise), and the soname must match. +So we have to do some renaming to get some of our self-built libs loaded. + +Development: +Typical android native activities are built with ndk-build which is a wrapper +around Make. It would be a nightmare to port our entire buildsystem over, so +instead we build as usual then package ourselves. It may be beneficial to use +ndk-build to do the actual packaging, but for now its behavior is emulated. + +ABI: +Presently we are targeting armv7a+neon for arm, and i686 for x86. Note that x86 +builds successfully but has not been tested. + +-------------------------------------------------------------------- +9. Useful Commands +-------------------------------------------------------------------- + +Below are a few helpful commands when building/debugging. These assume that pwd +is 'tools/android/packaging' and that the proper sdk/ndk paths are set. + +-Install a new build over the existing one + # adb -e install -r images/xbmcapp-debug.apk + +-Launch XBMC on the emulator without the GUI + # adb shell am start -a android.intent.action.MAIN -n org.xbmc.xbmc/android.app.NativeActivity + +-Kill a misbehaving XBMC + # adb shell ps | grep org.xbmc | awk '{print $2}' | xargs adb shell kill + +-Filter logcat messages by a specific tag (e.g. "XBMC") + # adb logcat -s XBMC:V + +-Enable CheckJNI (BEFORE starting the application) + # adb shell setprop debug.checkjni 1 + diff --git a/docs/README.ios b/docs/README.ios index e4704c5391..d69464b218 100644 --- a/docs/README.ios +++ b/docs/README.ios @@ -80,6 +80,7 @@ from the step 3.1. $ make -C tools/darwin/depends/xbmc $ make clean $ make xcode_depends + $ make -C lib/addons/script.module.pil ----------------------------------------------------------------------------- 4.1 Using Xcode diff --git a/docs/README.linux b/docs/README.linux index b13f956e91..f8f885c52f 100644 --- a/docs/README.linux +++ b/docs/README.linux @@ -98,7 +98,9 @@ Tip: by adding -j<number> to the make command, you describe how many $ make -j2 -.3 $ make install +.3 $ make -C lib/addons/script.module.pil + +.4 $ make install This will install XBMC in the prefix provided in 4.1 as well as a launcher script. diff --git a/docs/README.osx b/docs/README.osx index fa86366487..4221131fb4 100644 --- a/docs/README.osx +++ b/docs/README.osx @@ -48,12 +48,13 @@ Install latest Xcode (4.3.2 or 3.2.6 as of the writing). You can download it fro 1. Apple's site after registration at http://developer.apple.com/tools/download (Xcode 3.2.6) 2. In the MacOSX AppStore (Xcode 4.3.x). -If you are using XCode 4.3.x you also need to install the "Command Line Tools". To do so +If you are using XCode 4.3.x or later you also need to install the "Command Line Tools". To do so after installing Xcode you have to go to "Xcode->Preferences->Downloads" and install the package "Command Line Tools". Xcode 3.2.6 only runs on 10.6.x (Snow Leopard). Xcode 4.3.x only runs on 10.7.x (Lion). +Xcode 4.4 only runs on 10.8.x (Mountain Lion). ----------------------------------------------------------------------------- 3.1 Install XBMC build depends @@ -73,6 +74,12 @@ Xcode 4.3.x only runs on 10.7.x (Lion). $ ./configure --with-darwin=osx --with-arch=x86_64 $ make +IMPORTANT!! for Mountain Lion users. In Xcode 4.4 there is only SDK 10.7 and 10.8 +available. The XBMC buildsystem defaults to 10.6. So for compiling with ML +you have to specify the 10.7 SDK explicitly on configure: + + $ ./configure --with-darwin=osx --with-sdk=10.7 + ----------------------------------------------------------------------------- 4. How to compile @@ -87,6 +94,7 @@ first. This is a simple step and involves the following: $ make -C tools/darwin/depends/xbmc $ make clean $ make xcode_depends + $ make -C lib/addons/script.module.pil 4.b Compilation by using command-line building via make (experimental) @@ -112,7 +120,7 @@ Xcode 3.2.6 add "XBMC_HOME" as an enviroment variable. Set the value to the path to the XBMC root folder. For example, "/Users/bigdog/Documents/XBMC" -Xcode 4.3.x +Xcode 4.3.x and later Menu -> Product -> Edit Sheme -> "Run XBMC"/"Debug" -> Add XBMC_HOME into the List of "Environment Variables".Set the value to the path to thev XBMC root folder. For example, "/Users/bigdog/Documents/XBMC" @@ -124,7 +132,12 @@ OSX application. Set the build target to "XBMC" or "XBMC.app" and be sure to select the same architecture as selected in step 3.1 (either i386 for 32Bit or x86_64 for 64Bit), -then build. The build process will take a long time when building the first time. +then build. + +Mountain Lion users have to ensure to build against 10.7 SDK not 10.8 (which is +selected in Xcode 4.4 by default). + +The build process will take a long time when building the first time. You can see the progress in "Build Results". There are a large number of static and dynamic libaries that will need to be built. Once these are built, subsequent builds will be faster. @@ -163,6 +176,7 @@ developers). $ cd $HOME/XBMC $ export XBMC_HOME=`pwd` $ make xcode_depends + $ make -C lib/addons/script.module.pil $ xcodebuild -sdk macosx10.7 -project XBMC.xcodeproj -target XBMC.app ONLY_ACTIVE_ARCH=YES \ ARCHS=x86_64 VALID_ARCHS=x86_64 -configuration Release build diff --git a/language/English/strings.po b/language/English/strings.po index f0527a2c58..12ad2c7cd3 100644 --- a/language/English/strings.po +++ b/language/English/strings.po @@ -3158,39 +3158,7 @@ msgctxt "#1235" msgid "Programs & pictures & video" msgstr "" -#empty strings from id 1236 to 1249 - -msgctxt "#1250" -msgid "Auto-detection" -msgstr "" - -msgctxt "#1251" -msgid "Auto-detect system" -msgstr "" - -msgctxt "#1252" -msgid "Nickname" -msgstr "" - -#empty string with id 1253 - -msgctxt "#1254" -msgid "Ask to connect" -msgstr "" - -msgctxt "#1255" -msgid "Send FTP user and password" -msgstr "" - -msgctxt "#1256" -msgid "Ping interval" -msgstr "" - -msgctxt "#1257" -msgid "Would you like to connect to the auto-detected system?" -msgstr "" - -#empty string with id 1258 +#empty strings from id 1236 to 1258 msgctxt "#1259" msgid "Zeroconf" @@ -6793,7 +6761,29 @@ msgid "Downloading artist info failed" msgstr "" #string id's 20200 thru 20211 are reserved for speedstrings (LocalizeStrings.cpp) -#empty strings from id 20200 to 20249 +#empty strings from id 20200 to 20239 + +msgctxt "#20240" +msgid "Android music" +msgstr "" + +msgctxt "#20241" +msgid "Android videos" +msgstr "" + +msgctxt "#20242" +msgid "Android pictures" +msgstr "" + +msgctxt "#20243" +msgid "Android photos" +msgstr "" + +msgctxt "#20244" +msgid "Android Apps" +msgstr "" + +#empty strings from id 20245 to 20249 msgctxt "#20250" msgid "Party on! (videos)" @@ -7879,7 +7869,11 @@ msgctxt "#21455" msgid "Cache filled before reaching required amount for continous playback" msgstr "" -#empty strings from id 21456 to 21459 +msgctxt "#21456" +msgid "External storage" +msgstr "" + +#empty strings from id 21457 to 21459 msgctxt "#21460" msgid "Subtitle location" @@ -9499,3 +9493,18 @@ msgctxt "#36032" msgid "The port is busy. Only one program can access the CEC adapter" msgstr "" +msgctxt "#36033" +msgid "Pause playback when switching to another source" +msgstr "" + +#. adjust refreshrate +#: xbmc/settings/GUISettings.cpp +msgctxt "#36035" +msgid "Always" +msgstr "" + +#. adjust refreshrate +#: xbmc/settings/GUISettings.cpp +msgctxt "#36036" +msgid "On start/stop" +msgstr "" diff --git a/lib/DllAvFilter.h b/lib/DllAvFilter.h index 6ae5d15123..de6f4c0c51 100644 --- a/lib/DllAvFilter.h +++ b/lib/DllAvFilter.h @@ -74,10 +74,11 @@ public: virtual void avfilter_inout_free(AVFilterInOut **inout)=0; virtual int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs, void *log_ctx)=0; virtual int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)=0; - virtual int avfilter_poll_frame(AVFilterLink *link)=0; - virtual int avfilter_request_frame(AVFilterLink *link)=0; +#if LIBAVFILTER_VERSION_INT < AV_VERSION_INT(3,0,0) virtual int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, int flags)=0; - virtual AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h)=0; +#else + virtual int av_buffersrc_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, int flags)=0; +#endif virtual void avfilter_unref_buffer(AVFilterBufferRef *ref)=0; virtual int avfilter_link(AVFilterContext *src, unsigned srcpad, AVFilterContext *dst, unsigned dstpad)=0; virtual int av_buffersink_get_buffer_ref(AVFilterContext *buffer_sink, AVFilterBufferRef **bufref, int flags)=0; @@ -133,10 +134,11 @@ public: { return ::avfilter_graph_config(graphctx, log_ctx); } - virtual int avfilter_poll_frame(AVFilterLink *link) { return ::avfilter_poll_frame(link); } - virtual int avfilter_request_frame(AVFilterLink *link) { return ::avfilter_request_frame(link); } +#if LIBAVFILTER_VERSION_INT < AV_VERSION_INT(3,0,0) virtual int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, int flags) { return ::av_vsrc_buffer_add_frame(buffer_filter, frame, flags); } - virtual AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h) { return ::avfilter_get_video_buffer(link, perms, w, h); } +#else + virtual int av_buffersrc_add_frame(AVFilterContext *buffer_filter, AVFrame* frame, int flags) { return ::av_buffersrc_add_frame(buffer_filter, frame, flags); } +#endif virtual void avfilter_unref_buffer(AVFilterBufferRef *ref) { ::avfilter_unref_buffer(ref); } virtual int avfilter_link(AVFilterContext *src, unsigned srcpad, AVFilterContext *dst, unsigned dstpad) { return ::avfilter_link(src, srcpad, dst, dstpad); } virtual int av_buffersink_get_buffer_ref(AVFilterContext *buffer_sink, AVFilterBufferRef **bufref, int flags) { return ::av_buffersink_get_buffer_ref(buffer_sink, bufref, flags); } @@ -168,10 +170,11 @@ class DllAvFilter : public DllDynamic, DllAvFilterInterface DEFINE_METHOD1(void, avfilter_inout_free_dont_call, (AVFilterInOut **p1)) DEFINE_FUNC_ALIGNED5(int, __cdecl, avfilter_graph_parse_dont_call, AVFilterGraph *, const char *, AVFilterInOut **, AVFilterInOut **, void *) DEFINE_FUNC_ALIGNED2(int, __cdecl, avfilter_graph_config_dont_call, AVFilterGraph *, void *) - DEFINE_FUNC_ALIGNED1(int, __cdecl, avfilter_poll_frame, AVFilterLink *) - DEFINE_FUNC_ALIGNED1(int, __cdecl, avfilter_request_frame, AVFilterLink*) +#if LIBAVFILTER_VERSION_INT < AV_VERSION_INT(3,0,0) DEFINE_METHOD3(int, av_vsrc_buffer_add_frame, (AVFilterContext *p1, AVFrame *p2, int p3)) - DEFINE_METHOD4(AVFilterBufferRef*, avfilter_get_video_buffer, (AVFilterLink *p1, int p2, int p3, int p4)) +#else + DEFINE_METHOD3(int, av_buffersrc_add_frame, (AVFilterContext *p1, AVFrame *p2, int p3)) +#endif DEFINE_METHOD1(void, avfilter_unref_buffer, (AVFilterBufferRef *p1)) DEFINE_METHOD4(int, avfilter_link, (AVFilterContext *p1, unsigned p2, AVFilterContext *p3, unsigned p4)) DEFINE_FUNC_ALIGNED3(int , __cdecl, av_buffersink_get_buffer_ref, AVFilterContext *, AVFilterBufferRef **, int); @@ -190,10 +193,11 @@ class DllAvFilter : public DllDynamic, DllAvFilterInterface RESOLVE_METHOD_RENAME(avfilter_inout_free, avfilter_inout_free_dont_call) RESOLVE_METHOD_RENAME(avfilter_graph_parse, avfilter_graph_parse_dont_call) RESOLVE_METHOD_RENAME(avfilter_graph_config, avfilter_graph_config_dont_call) - RESOLVE_METHOD(avfilter_poll_frame) - RESOLVE_METHOD(avfilter_request_frame) +#if LIBAVFILTER_VERSION_INT < AV_VERSION_INT(3,0,0) RESOLVE_METHOD(av_vsrc_buffer_add_frame) - RESOLVE_METHOD(avfilter_get_video_buffer) +#else + RESOLVE_METHOD(av_buffersrc_add_frame) +#endif RESOLVE_METHOD(avfilter_unref_buffer) RESOLVE_METHOD(avfilter_link) RESOLVE_METHOD(av_buffersink_get_buffer_ref) diff --git a/lib/Makefile.in b/lib/Makefile.in index 45ae5df0ce..37e2d2f7e5 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -6,13 +6,19 @@ CC=@CC@ CXX=@CXX@ SYSDIR=@abs_top_srcdir@/system/players/dvdplayer -AVFORMAT_SO=avformat-53-$(ARCH).so -AVCODEC_SO=avcodec-53-$(ARCH).so -AVUTIL_SO=avutil-51-$(ARCH).so -AVFILTER_SO=avfilter-2-$(ARCH).so -SWSCALE_SO=swscale-2-$(ARCH).so -POSTPROC_SO=postproc-52-$(ARCH).so -SWRESAMPLE_SO=swresample-0-$(ARCH).so +ifeq (@USE_ANDROID@,1) +AVPREFIX=lib +else +AVPREFIX= +endif + +AVFORMAT_SO=$(AVPREFIX)avformat-53-$(ARCH).so +AVCODEC_SO=$(AVPREFIX)avcodec-53-$(ARCH).so +AVUTIL_SO=$(AVPREFIX)avutil-51-$(ARCH).so +AVFILTER_SO=$(AVPREFIX)avfilter-2-$(ARCH).so +SWSCALE_SO=$(AVPREFIX)swscale-2-$(ARCH).so +POSTPROC_SO=$(AVPREFIX)postproc-52-$(ARCH).so +SWRESAMPLE_SO=$(AVPREFIX)swresample-0-$(ARCH).so DIRS= ifneq (@USE_EXTERNAL_FFMPEG@,1) diff --git a/lib/UnrarXLib/os.hpp b/lib/UnrarXLib/os.hpp index e48fa0a239..165d01b64c 100644 --- a/lib/UnrarXLib/os.hpp +++ b/lib/UnrarXLib/os.hpp @@ -55,7 +55,7 @@ #include <dir.h> #endif #ifdef _MSC_VER - #define for if (0) ; else for +// #define for if (0) ; else for #ifndef _WIN_CE #include <direct.h> #endif diff --git a/lib/UnrarXLib/rar.cpp b/lib/UnrarXLib/rar.cpp index 7fe29370ba..1b5ad04345 100644 --- a/lib/UnrarXLib/rar.cpp +++ b/lib/UnrarXLib/rar.cpp @@ -203,9 +203,12 @@ int urarlib_get(char *rarfile, char *targetPath, char *fileToExtract, char *libp if (bShowProgress) { pExtract->GetDataIO().m_pDlgProgress = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS); - pExtract->GetDataIO().m_pDlgProgress->SetHeading(fileToExtract); - pExtract->GetDataIO().m_pDlgProgress->SetCanCancel(false); - pExtract->GetDataIO().m_pDlgProgress->StartModal(); + if (pExtract->GetDataIO().m_pDlgProgress) + { + pExtract->GetDataIO().m_pDlgProgress->SetHeading(fileToExtract); + pExtract->GetDataIO().m_pDlgProgress->SetCanCancel(false); + pExtract->GetDataIO().m_pDlgProgress->StartModal(); + } } int64_t iOff=0; @@ -234,7 +237,8 @@ int urarlib_get(char *rarfile, char *targetPath, char *fileToExtract, char *libp if (pExtract->GetDataIO().bQuit) { - pExtract->GetDataIO().m_pDlgProgress->Close(); + if (pExtract->GetDataIO().m_pDlgProgress) + pExtract->GetDataIO().m_pDlgProgress->Close(); bRes = 2; break; } @@ -269,7 +273,8 @@ int urarlib_get(char *rarfile, char *targetPath, char *fileToExtract, char *libp pExtract->GetDataIO().m_pDlgProgress->ShowProgressBar(false); } if (bShowProgress) - pExtract->GetDataIO().m_pDlgProgress->Close(); + if (pExtract->GetDataIO().m_pDlgProgress) + pExtract->GetDataIO().m_pDlgProgress->Close(); } } } diff --git a/lib/cmyth/Makefile.in b/lib/cmyth/Makefile.in index 325106a07d..e91a3d32db 100644 --- a/lib/cmyth/Makefile.in +++ b/lib/cmyth/Makefile.in @@ -16,8 +16,8 @@ $(CMYTH_LIB): libcmyth/libcmyth.a librefmem/librefmem.a -Wl,-all_load libcmyth/libcmyth.a librefmem/librefmem.a else $(CMYTH_LIB): libcmyth/libcmyth.a librefmem/librefmem.a - $(CC) $(LDFLAGS) -shared -fpic -o $@ @MYSQL_LIBS@ \ - -Wl,--whole-archive libcmyth/libcmyth.a librefmem/librefmem.a -Wl,--no-whole-archive + $(CC) $(LDFLAGS) -shared -fpic -o $@ -Wl,--whole-archive \ + libcmyth/libcmyth.a librefmem/librefmem.a -Wl,--no-whole-archive @MYSQL_LIBS@ endif libcmyth/libcmyth.a: compile diff --git a/lib/cmyth/Win32/libcmyth.vcxproj b/lib/cmyth/Win32/libcmyth.vcxproj index f2bd32921a..1494f558d7 100644 --- a/lib/cmyth/Win32/libcmyth.vcxproj +++ b/lib/cmyth/Win32/libcmyth.vcxproj @@ -62,6 +62,7 @@ </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Link> <AdditionalDependencies>ws2_32.lib;mysqlclient.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/lib/cpluff/libcpluff/win32/cpluff.vcxproj b/lib/cpluff/libcpluff/win32/cpluff.vcxproj index 7c4d21cc68..1cecfe0bb5 100644 --- a/lib/cpluff/libcpluff/win32/cpluff.vcxproj +++ b/lib/cpluff/libcpluff/win32/cpluff.vcxproj @@ -60,6 +60,7 @@ </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Link> <AdditionalDependencies>libexpat.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/lib/cximage-6.0/CxImage/ximaraw.cpp b/lib/cximage-6.0/CxImage/ximaraw.cpp index ea7b7023d0..fd86f965db 100644 --- a/lib/cximage-6.0/CxImage/ximaraw.cpp +++ b/lib/cximage-6.0/CxImage/ximaraw.cpp @@ -14,6 +14,23 @@ #if CXIMAGE_SUPPORT_RAW +#if defined(__ANDROID__) +#include <stdint.h> +#include <asm/byteorder.h> + +extern "C" void swab(const void *from, void*to, ssize_t n) +{ + ssize_t i; + + if (n < 0) + return; + + for (i = 0; i < (n/2)*2; i += 2) + *((uint16_t*)to+i) = __arch__swab16(*((uint16_t*)from+i)); +} + +#endif + //////////////////////////////////////////////////////////////////////////////// #if CXIMAGE_SUPPORT_DECODE //////////////////////////////////////////////////////////////////////////////// @@ -191,7 +208,7 @@ bool CxImageRAW::Decode(CxFile *hFile) for (c=0; c < dcr.colors; c++) ppm2[col*dcr.colors+c] = dcr.image[soff][c]; } if (dcr.opt.output_bps == 16 && !dcr.opt.output_tiff && htons(0x55aa) != 0x55aa) -#if defined(_LINUX) || defined(__APPLE__) +#if defined(_LINUX) || defined(__APPLE__) || defined(__ANDROID__) swab ((char*)ppm2, (char*)ppm2, dcr.width*dcr.colors*2); #else _swab ((char*)ppm2, (char*)ppm2, dcr.width*dcr.colors*2); diff --git a/lib/cximage-6.0/ImageLib.vcxproj b/lib/cximage-6.0/ImageLib.vcxproj index 931ac23ee4..f2759cb25f 100644 --- a/lib/cximage-6.0/ImageLib.vcxproj +++ b/lib/cximage-6.0/ImageLib.vcxproj @@ -160,6 +160,7 @@ <WarningLevel>Level3</WarningLevel> <SuppressStartupBanner>true</SuppressStartupBanner> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/lib/cximage-6.0/jasper/jasper.vcxproj b/lib/cximage-6.0/jasper/jasper.vcxproj index d79835914a..267e2f2a78 100644 --- a/lib/cximage-6.0/jasper/jasper.vcxproj +++ b/lib/cximage-6.0/jasper/jasper.vcxproj @@ -86,7 +86,7 @@ <AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions>_DEBUG;WIN32;_LIB;JAS_WIN_MSVC_BUILD;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jasper.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName> @@ -94,6 +94,7 @@ <WarningLevel>Level2</WarningLevel> <SuppressStartupBanner>true</SuppressStartupBanner> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> @@ -111,7 +112,7 @@ <AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions>NDEBUG;WIN32;_LIB;JAS_WIN_MSVC_BUILD;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <StringPooling>true</StringPooling> - <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <FunctionLevelLinking>true</FunctionLevelLinking> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jasper.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> diff --git a/lib/cximage-6.0/jbig/jbig.vcxproj b/lib/cximage-6.0/jbig/jbig.vcxproj index 8a9078c191..c70359d780 100644 --- a/lib/cximage-6.0/jbig/jbig.vcxproj +++ b/lib/cximage-6.0/jbig/jbig.vcxproj @@ -82,7 +82,7 @@ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> <StringPooling>true</StringPooling> - <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <FunctionLevelLinking>true</FunctionLevelLinking> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jbig.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> @@ -131,7 +131,7 @@ <Optimization>Disabled</Optimization> <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jbig.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName> @@ -139,6 +139,7 @@ <WarningLevel>Level3</WarningLevel> <SuppressStartupBanner>true</SuppressStartupBanner> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/lib/cximage-6.0/jpeg/Jpeg.vcxproj b/lib/cximage-6.0/jpeg/Jpeg.vcxproj index d4c8da4f12..b6561befdd 100644 --- a/lib/cximage-6.0/jpeg/Jpeg.vcxproj +++ b/lib/cximage-6.0/jpeg/Jpeg.vcxproj @@ -126,7 +126,7 @@ <ClCompile> <Optimization>Disabled</Optimization> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jpeg.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName> @@ -134,6 +134,7 @@ <WarningLevel>Level3</WarningLevel> <SuppressStartupBanner>true</SuppressStartupBanner> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> @@ -150,7 +151,7 @@ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <StringPooling>true</StringPooling> - <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <FunctionLevelLinking>true</FunctionLevelLinking> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jpeg.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> diff --git a/lib/cximage-6.0/mng/mng.vcxproj b/lib/cximage-6.0/mng/mng.vcxproj index 41fc8c304f..821c1252af 100644 --- a/lib/cximage-6.0/mng/mng.vcxproj +++ b/lib/cximage-6.0/mng/mng.vcxproj @@ -83,7 +83,7 @@ <AdditionalIncludeDirectories>..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;MNG_SUPPORT_DISPLAY;MNG_SUPPORT_READ;MNG_SUPPORT_WRITE;MNG_ACCESS_CHUNKS;MNG_STORE_CHUNKS;_CRT_SECURE_NO_DEPRECATE;MNG_ERROR_TELLTALE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\mng.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName> @@ -91,6 +91,7 @@ <WarningLevel>Level3</WarningLevel> <SuppressStartupBanner>true</SuppressStartupBanner> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> @@ -158,7 +159,7 @@ <AdditionalIncludeDirectories>..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;MNG_SUPPORT_DISPLAY;MNG_SUPPORT_READ;MNG_SUPPORT_WRITE;MNG_ACCESS_CHUNKS;MNG_STORE_CHUNKS;_CRT_SECURE_NO_DEPRECATE;MNG_ERROR_TELLTALE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <StringPooling>true</StringPooling> - <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <FunctionLevelLinking>true</FunctionLevelLinking> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\mng.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> diff --git a/lib/cximage-6.0/png/png.vcxproj b/lib/cximage-6.0/png/png.vcxproj index fefaf43b02..5393c65952 100644 --- a/lib/cximage-6.0/png/png.vcxproj +++ b/lib/cximage-6.0/png/png.vcxproj @@ -82,7 +82,7 @@ <Optimization>Disabled</Optimization> <AdditionalIncludeDirectories>..\zlib;..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\png.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName> @@ -90,6 +90,7 @@ <WarningLevel>Level3</WarningLevel> <SuppressStartupBanner>true</SuppressStartupBanner> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> @@ -132,7 +133,7 @@ <AdditionalIncludeDirectories>..\zlib;..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <StringPooling>true</StringPooling> - <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <FunctionLevelLinking>true</FunctionLevelLinking> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\png.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> diff --git a/lib/cximage-6.0/raw/dcr.c b/lib/cximage-6.0/raw/dcr.c index 1668dd0122..e688d6277e 100644 --- a/lib/cximage-6.0/raw/dcr.c +++ b/lib/cximage-6.0/raw/dcr.c @@ -145,7 +145,7 @@ int DCR_CLASS main (int argc, char **argv) //!!! set return point for error handling if (setjmp (dcr.failure)) { #if !defined(__FreeBSD__) - if (fileno(dcr.obj_) > 2) (*dcr.ops_->close_)(dcr.obj_); + if (fileno((FILE*)dcr.obj_) > 2) (*dcr.ops_->close_)(dcr.obj_); #endif if (fileno(ofp) > 2) fclose(ofp); status = 1; diff --git a/lib/cximage-6.0/raw/libdcr.vcxproj b/lib/cximage-6.0/raw/libdcr.vcxproj index ec0a46577d..281055fb38 100644 --- a/lib/cximage-6.0/raw/libdcr.vcxproj +++ b/lib/cximage-6.0/raw/libdcr.vcxproj @@ -82,7 +82,7 @@ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <StringPooling>true</StringPooling> - <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <FunctionLevelLinking>true</FunctionLevelLinking> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\libdcr.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> @@ -106,7 +106,7 @@ <Optimization>Disabled</Optimization> <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\libdcr.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName> @@ -114,6 +114,7 @@ <WarningLevel>Level3</WarningLevel> <SuppressStartupBanner>true</SuppressStartupBanner> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/lib/cximage-6.0/tiff/Tiff.vcxproj b/lib/cximage-6.0/tiff/Tiff.vcxproj index add003c890..11c91a40f4 100644 --- a/lib/cximage-6.0/tiff/Tiff.vcxproj +++ b/lib/cximage-6.0/tiff/Tiff.vcxproj @@ -83,7 +83,7 @@ <AdditionalIncludeDirectories>..\zlib;..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\Tiff.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName> @@ -92,6 +92,7 @@ <SuppressStartupBanner>true</SuppressStartupBanner> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <CompileAs>Default</CompileAs> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> @@ -109,7 +110,7 @@ <AdditionalIncludeDirectories>..\zlib;..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <StringPooling>true</StringPooling> - <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <FunctionLevelLinking>true</FunctionLevelLinking> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\Tiff.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> diff --git a/lib/cximage-6.0/zlib/zlib.vcxproj b/lib/cximage-6.0/zlib/zlib.vcxproj index 91e99aa325..6675efc845 100644 --- a/lib/cximage-6.0/zlib/zlib.vcxproj +++ b/lib/cximage-6.0/zlib/zlib.vcxproj @@ -130,7 +130,7 @@ <Optimization>Disabled</Optimization> <AdditionalIncludeDirectories>..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\zlib.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName> @@ -138,6 +138,7 @@ <WarningLevel>Level3</WarningLevel> <SuppressStartupBanner>true</SuppressStartupBanner> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> @@ -155,7 +156,7 @@ <AdditionalIncludeDirectories>..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <StringPooling>true</StringPooling> - <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <FunctionLevelLinking>true</FunctionLevelLinking> <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\zlib.pch</PrecompiledHeaderOutputFile> <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation> diff --git a/lib/enca/libenca_win32/libenca_win32.vcxproj b/lib/enca/libenca_win32/libenca_win32.vcxproj index 56702f4503..38ea401199 100644 --- a/lib/enca/libenca_win32/libenca_win32.vcxproj +++ b/lib/enca/libenca_win32/libenca_win32.vcxproj @@ -57,6 +57,7 @@ </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Lib> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> diff --git a/lib/ffmpeg/libavcodec/arm/vp56_arith.h b/lib/ffmpeg/libavcodec/arm/vp56_arith.h index ece9ac2a6c..29a222844a 100644 --- a/lib/ffmpeg/libavcodec/arm/vp56_arith.h +++ b/lib/ffmpeg/libavcodec/arm/vp56_arith.h @@ -29,6 +29,14 @@ # define T(x) #endif +#if CONFIG_THUMB || defined __clang__ +# define L(x) +# define U(x) x +#else +# define L(x) x +# define U(x) +#endif + #if HAVE_ARMV6 && HAVE_INLINE_ASM #define vp56_rac_get_prob vp56_rac_get_prob_armv6 @@ -42,8 +50,8 @@ static inline int vp56_rac_get_prob_armv6(VP56RangeCoder *c, int pr) __asm__ ("adds %3, %3, %0 \n" "itt cs \n" "cmpcs %7, %4 \n" - A("ldrcsh %2, [%4], #2 \n") - T("ldrhcs %2, [%4], #2 \n") + L("ldrcsh %2, [%4], #2 \n") + U("ldrhcs %2, [%4], #2 \n") "rsb %0, %6, #256 \n" "smlabb %0, %5, %6, %0 \n" T("itttt cs \n") @@ -80,8 +88,8 @@ static inline int vp56_rac_get_prob_branchy_armv6(VP56RangeCoder *c, int pr) __asm__ ("adds %3, %3, %0 \n" "itt cs \n" "cmpcs %7, %4 \n" - A("ldrcsh %2, [%4], #2 \n") - T("ldrhcs %2, [%4], #2 \n") + L("ldrcsh %2, [%4], #2 \n") + U("ldrhcs %2, [%4], #2 \n") "rsb %0, %6, #256 \n" "smlabb %0, %5, %6, %0 \n" T("itttt cs \n") diff --git a/lib/ffmpeg/libavformat/rtsp.c b/lib/ffmpeg/libavformat/rtsp.c index c2a0d26e5e..2fccea1bea 100644 --- a/lib/ffmpeg/libavformat/rtsp.c +++ b/lib/ffmpeg/libavformat/rtsp.c @@ -900,9 +900,13 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, char buf[4096], buf1[1024], *q; unsigned char ch; const char *p; - int ret, content_length, line_count = 0; + int ret, content_length, line_count = 0, request = 0; unsigned char *content = NULL; +start: + line_count = 0; + request = 0; + content = NULL; memset(reply, 0, sizeof(*reply)); /* parse reply (XXX: use buffers) */ @@ -938,9 +942,15 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, if (line_count == 0) { /* get reply code */ get_word(buf1, sizeof(buf1), &p); - get_word(buf1, sizeof(buf1), &p); - reply->status_code = atoi(buf1); - av_strlcpy(reply->reason, p, sizeof(reply->reason)); + if (!strncmp(buf1, "RTSP/", 5)) { + get_word(buf1, sizeof(buf1), &p); + reply->status_code = atoi(buf1); + av_strlcpy(reply->reason, p, sizeof(reply->reason)); + } else { + av_strlcpy(reply->reason, buf1, sizeof(reply->reason)); // method + get_word(buf1, sizeof(buf1), &p); // object + request = 1; + } } else { ff_rtsp_parse_line(reply, p, rt, method); av_strlcat(rt->last_reply, p, sizeof(rt->last_reply)); @@ -949,7 +959,7 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, line_count++; } - if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0') + if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0' && !request) av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id)); content_length = reply->content_length; @@ -964,6 +974,44 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, else av_free(content); + if (request) { + char buf[1024]; + char base64buf[AV_BASE64_SIZE(sizeof(buf))]; + const char* ptr = buf; + + if (!strcmp(reply->reason, "OPTIONS")) { + snprintf(buf, sizeof(buf), "RTSP/1.0 200 OK\r\n"); + if (reply->seq) + av_strlcatf(buf, sizeof(buf), "CSeq: %d\r\n", reply->seq); + if (reply->session_id[0]) + av_strlcatf(buf, sizeof(buf), "Session: %s\r\n", + reply->session_id); + } else { + snprintf(buf, sizeof(buf), "RTSP/1.0 501 Not Implemented\r\n"); + } + av_strlcat(buf, "\r\n", sizeof(buf)); + + if (rt->control_transport == RTSP_MODE_TUNNEL) { + av_base64_encode(base64buf, sizeof(base64buf), buf, strlen(buf)); + ptr = base64buf; + } + ffurl_write(rt->rtsp_hd_out, ptr, strlen(ptr)); + + rt->last_cmd_time = av_gettime(); + /* Even if the request from the server had data, it is not the data + * that the caller wants or expects. The memory could also be leaked + * if the actual following reply has content data. */ + if (content_ptr) + av_freep(content_ptr); + /* If method is set, this is called from ff_rtsp_send_cmd, + * where a reply to exactly this request is awaited. For + * callers from within packet reciving, we just want to + * return to the caller and go back to receiving packets. */ + if (method) + goto start; + return 0; + } + if (rt->seq != reply->seq) { av_log(s, AV_LOG_WARNING, "CSeq %d expected, %d received.\n", rt->seq, reply->seq); diff --git a/lib/ffmpeg/libavutil/arm/intmath.h b/lib/ffmpeg/libavutil/arm/intmath.h index 52af66e722..4ebe562632 100644 --- a/lib/ffmpeg/libavutil/arm/intmath.h +++ b/lib/ffmpeg/libavutil/arm/intmath.h @@ -75,6 +75,8 @@ static av_always_inline av_const int16_t av_clip_int16_arm(int a) return x; } +/* Android fix. See: http://patches.libav.org/patch/3525/ */ +#if !defined(ANDROID) #define av_clip_uintp2 av_clip_uintp2_arm static av_always_inline av_const unsigned av_clip_uintp2_arm(int a, int p) { @@ -82,7 +84,7 @@ static av_always_inline av_const unsigned av_clip_uintp2_arm(int a, int p) __asm__ ("usat %0, %2, %1" : "=r"(x) : "r"(a), "i"(p)); return x; } - +#endif #else /* HAVE_ARMV6 */ diff --git a/lib/ffmpeg/patches/0031-ARM-vp56-allow-inline-asm-to-build-with-clang.patch b/lib/ffmpeg/patches/0031-ARM-vp56-allow-inline-asm-to-build-with-clang.patch new file mode 100644 index 0000000000..994be915e2 --- /dev/null +++ b/lib/ffmpeg/patches/0031-ARM-vp56-allow-inline-asm-to-build-with-clang.patch @@ -0,0 +1,56 @@ +#The clang integrated assembler does not support pre-UAL syntax, +#while gcc requires pre-UAL syntax for ARM code. A patch[1] for +#clang to support the old syntax as well has been ignored since +#January. +# +#This patch chooses the syntax appropriate for each compiler, +#allowing both to build the code. Notably, this change allows +#building for iphone with the latest Apple Xcode update. +# +#[1] http://llvm.org/bugs/show_bug.cgi?id=11855 +# +#Signed-off-by: Mans Rullgard <mans at mansr.com> + +diff --git a/libavcodec/arm/vp56_arith.h b/libavcodec/arm/vp56_arith.h +index ef30ffe..d1a8837 100644 +--- a/libavcodec/arm/vp56_arith.h ++++ b/libavcodec/arm/vp56_arith.h +@@ -29,6 +29,14 @@ + # define T(x) + #endif + ++#if CONFIG_THUMB || defined __clang__ ++# define L(x) ++# define U(x) x ++#else ++# define L(x) x ++# define U(x) ++#endif ++ + #if HAVE_ARMV6 && HAVE_INLINE_ASM + + #define vp56_rac_get_prob vp56_rac_get_prob_armv6 +@@ -42,8 +50,8 @@ static inline int vp56_rac_get_prob_armv6(VP56RangeCoder *c, int pr) + __asm__ ("adds %3, %3, %0 \n" + "itt cs \n" + "cmpcs %7, %4 \n" +- A("ldrcsh %2, [%4], #2 \n") +- T("ldrhcs %2, [%4], #2 \n") ++ L("ldrcsh %2, [%4], #2 \n") ++ U("ldrhcs %2, [%4], #2 \n") + "rsb %0, %6, #256 \n" + "smlabb %0, %5, %6, %0 \n" + T("itttt cs \n") +@@ -80,8 +88,8 @@ static inline int vp56_rac_get_prob_branchy_armv6(VP56RangeCoder *c, int pr) + __asm__ ("adds %3, %3, %0 \n" + "itt cs \n" + "cmpcs %7, %4 \n" +- A("ldrcsh %2, [%4], #2 \n") +- T("ldrhcs %2, [%4], #2 \n") ++ L("ldrcsh %2, [%4], #2 \n") ++ U("ldrhcs %2, [%4], #2 \n") + "rsb %0, %6, #256 \n" + "smlabb %0, %5, %6, %0 \n" + T("itttt cs \n") +-- +1.7.11.1 diff --git a/lib/libRTV/GuideParser.cpp b/lib/libRTV/GuideParser.cpp index fa1e70c636..988bde2918 100644 --- a/lib/libRTV/GuideParser.cpp +++ b/lib/libRTV/GuideParser.cpp @@ -855,6 +855,7 @@ int CalculateMinutes( int seconds ) //------------------------------------------------------------------------- //------------------------------------------------------------------------- +#if _MSC_VER < 1700 DWORD64 ntohll(DWORD64 llValue) { DWORD64 retval = 0; @@ -884,7 +885,7 @@ DWORD64 ntohll(DWORD64 llValue) return retval; } - +#endif // _MSC_VER < 1700 //------------------------------------------------------------------------- void ConvertProgramInfoEndian(struct tagProgramInfo * strProgramInfo) { diff --git a/lib/libRTV/crypt.c b/lib/libRTV/crypt.c index 62251331a6..df4d682d6b 100644 --- a/lib/libRTV/crypt.c +++ b/lib/libRTV/crypt.c @@ -50,11 +50,12 @@ static void checksum(unsigned char * dest, unsigned const char * src, u32 len, 0x96,0x43,0x2b,0xcc, 0x0c,0x9d,0x26,0xb9, }}; - md5_context c; - md5_starts(&c); - md5_update(&c, src, len); - md5_update(&c, extradata[checksum_num], sizeof extradata[checksum_num]); - md5_finish(&c, dest); + rtv_md5_context c; + rtv_md5_starts(&c); + rtv_md5_update(&c, src, len); + rtv_md5_update(&c, extradata[checksum_num], sizeof extradata[checksum_num]); + rtv_md5_finish(&c, dest); + } static u32 cryptblock(u32 k, char * buf, u32 size) diff --git a/lib/libRTV/md5.c b/lib/libRTV/md5.c index e0802fe2ac..73dbb1d780 100644 --- a/lib/libRTV/md5.c +++ b/lib/libRTV/md5.c @@ -31,7 +31,7 @@ (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \ } -void md5_starts( md5_context *ctx ) +void rtv_md5_starts( rtv_md5_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -42,7 +42,7 @@ void md5_starts( md5_context *ctx ) ctx->state[3] = 0x10325476; } -void md5_process( md5_context *ctx, const uint8 data[64] ) +void rtv_md5_process( rtv_md5_context *ctx, const uint8 data[64] ) { uint32 X[16], A, B, C, D; @@ -165,7 +165,7 @@ void md5_process( md5_context *ctx, const uint8 data[64] ) ctx->state[3] += D; } -void md5_update( md5_context *ctx, const uint8 *input, uint32 length ) +void rtv_md5_update( rtv_md5_context *ctx, const uint8 *input, uint32 length ) { uint32 left, fill; @@ -184,7 +184,7 @@ void md5_update( md5_context *ctx, const uint8 *input, uint32 length ) { memcpy( (void *) (ctx->buffer + left), (void *) input, fill ); - md5_process( ctx, ctx->buffer ); + rtv_md5_process( ctx, ctx->buffer ); length -= fill; input += fill; left = 0; @@ -192,7 +192,7 @@ void md5_update( md5_context *ctx, const uint8 *input, uint32 length ) while( length >= 64 ) { - md5_process( ctx, input ); + rtv_md5_process( ctx, input ); length -= 64; input += 64; } @@ -204,7 +204,7 @@ void md5_update( md5_context *ctx, const uint8 *input, uint32 length ) } } -static uint8 md5_padding[64] = +static uint8 rtv_md5_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -212,7 +212,7 @@ static uint8 md5_padding[64] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -void md5_finish( md5_context *ctx, uint8 digest[16] ) +void rtv_md5_finish( rtv_md5_context *ctx, uint8 digest[16] ) { uint32 last, padn; uint32 high, low; @@ -228,8 +228,8 @@ void md5_finish( md5_context *ctx, uint8 digest[16] ) last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - md5_update( ctx, md5_padding, padn ); - md5_update( ctx, msglen, 8 ); + rtv_md5_update( ctx, rtv_md5_padding, padn ); + rtv_md5_update( ctx, msglen, 8 ); PUT_UINT32( ctx->state[0], digest, 0 ); PUT_UINT32( ctx->state[1], digest, 4 ); @@ -274,7 +274,7 @@ int main( int argc, char *argv[] ) FILE *f; int i, j; char output[33]; - md5_context ctx; + rtv_md5_context ctx; unsigned char buf[1000]; unsigned char md5sum[16]; @@ -286,9 +286,9 @@ int main( int argc, char *argv[] ) { //printf( " Test %d ", i + 1 ); - md5_starts( &ctx ); - md5_update( &ctx, (uint8 *) msg[i], strlen( msg[i] ) ); - md5_finish( &ctx, md5sum ); + rtv_md5_starts( &ctx ); + rtv_md5_update( &ctx, (uint8 *) msg[i], strlen( msg[i] ) ); + rtv_md5_finish( &ctx, md5sum ); for( j = 0; j < 16; j++ ) { @@ -314,14 +314,14 @@ int main( int argc, char *argv[] ) return( 1 ); } - md5_starts( &ctx ); + rtv_md5_starts( &ctx ); while( ( i = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) { - md5_update( &ctx, buf, i ); + rtv_md5_update( &ctx, buf, i ); } - md5_finish( &ctx, md5sum ); + rtv_md5_finish( &ctx, md5sum ); for( j = 0; j < 16; j++ ) { diff --git a/lib/libRTV/md5.h b/lib/libRTV/md5.h index e382062528..bde04de12b 100644 --- a/lib/libRTV/md5.h +++ b/lib/libRTV/md5.h @@ -15,10 +15,10 @@ typedef struct uint32 state[4]; uint8 buffer[64]; } -md5_context; +rtv_md5_context; -void md5_starts( md5_context *ctx ); -void md5_update( md5_context *ctx, const uint8 *input, uint32 length ); -void md5_finish( md5_context *ctx, uint8 digest[16] ); +void rtv_md5_starts( rtv_md5_context *ctx ); +void rtv_md5_update( rtv_md5_context *ctx, const uint8 *input, uint32 length ); +void rtv_md5_finish( rtv_md5_context *ctx, uint8 digest[16] ); #endif /* md5.h */ diff --git a/lib/libXDAAP/libXDAAP_win32/libXDAAP_win32.vcxproj b/lib/libXDAAP/libXDAAP_win32/libXDAAP_win32.vcxproj index cbbc77a4e8..3aee17c0f0 100644 --- a/lib/libXDAAP/libXDAAP_win32/libXDAAP_win32.vcxproj +++ b/lib/libXDAAP/libXDAAP_win32/libXDAAP_win32.vcxproj @@ -56,6 +56,7 @@ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Lib> <OutputFile>$(OutDir)$(TargetFileName)</OutputFile> diff --git a/lib/libapetag/libapetag.vcxproj b/lib/libapetag/libapetag.vcxproj index 2be4dbcb4d..c790bc15ca 100644 --- a/lib/libapetag/libapetag.vcxproj +++ b/lib/libapetag/libapetag.vcxproj @@ -56,6 +56,7 @@ </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Lib> <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> diff --git a/lib/libass/xbmc/libass_win32/libass_win32_vs2010.vcxproj b/lib/libass/xbmc/libass_win32/libass_win32_vs2010.vcxproj index 4d4e17a115..ca210991b5 100644 --- a/lib/libass/xbmc/libass_win32/libass_win32_vs2010.vcxproj +++ b/lib/libass/xbmc/libass_win32/libass_win32_vs2010.vcxproj @@ -66,6 +66,7 @@ <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <DisableSpecificWarnings>4001;4996;4244;4267;4018;4005;%(DisableSpecificWarnings)</DisableSpecificWarnings> <CompileAs>CompileAsC</CompileAs> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Link> <AdditionalDependencies>fontconfig.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/lib/libdvd/Makefile.in b/lib/libdvd/Makefile.in index 1534f33158..69d2286e1e 100644 --- a/lib/libdvd/Makefile.in +++ b/lib/libdvd/Makefile.in @@ -56,11 +56,11 @@ else $(SYSDIR)/libdvdcss-$(ARCH).so: $(WRAPPER) libdvdcss/src/.libs/libdvdcss.a $(CC) -o $@ $(LDFLAGS) -Wl,--soname,$@ \ - libdvdcss/src/*.o -Wl,--unresolved-symbols=ignore-all \ + libdvdcss/src/*.o -Wl,--unresolved-symbols=ignore-all -lm \ `cat $(WRAPPER:.o=.def)` $(WRAPPER) $(SYSDIR)/libdvdnav-$(ARCH).so: $(WRAPPER) $(DVDCSS_A) libdvdread/obj/libdvdread.a libdvdnav/obj/libdvdnav.a - $(CC) -o $@ $(LDFLAGS) -Wl,--soname,$@ $(DVDCSS_O) libdvdread/obj/*.o libdvdnav/obj/*.o \ + $(CC) -o $@ $(LDFLAGS) -Wl,--soname,$@ $(DVDCSS_O) libdvdread/obj/*.o libdvdnav/obj/*.o -lm \ -Wl,--unresolved-symbols=ignore-all \ `cat $(WRAPPER:.o=.def)` $(WRAPPER) diff --git a/lib/libdvd/libdvdnav/src/remap.c b/lib/libdvd/libdvdnav/src/remap.c index 5601605dba..eb40b9d841 100644 --- a/lib/libdvd/libdvdnav/src/remap.c +++ b/lib/libdvd/libdvdnav/src/remap.c @@ -25,10 +25,10 @@ #include <stdlib.h> #include <string.h> #include <stdio.h> +#include <fcntl.h> #ifndef _MSC_VER #include <sys/param.h> -#include <sys/fcntl.h> #else #ifndef MAXPATHLEN #define MAXPATHLEN 255 diff --git a/lib/libdvd/libdvdread/src/dvd_reader.c b/lib/libdvd/libdvdread/src/dvd_reader.c index 2173cdda1f..8849e848e3 100644 --- a/lib/libdvd/libdvdread/src/dvd_reader.c +++ b/lib/libdvd/libdvdread/src/dvd_reader.c @@ -31,6 +31,9 @@ #include <unistd.h> #include <limits.h> #include <dirent.h> +#ifndef WIN32 +#include <paths.h> +#endif #define WITH_CACHE @@ -492,7 +495,7 @@ dvd_reader_t *DVDOpen( const char *ppath ) fclose( mntfile ); } #elif defined(__linux__) - mntfile = fopen( MOUNTED, "r" ); + mntfile = fopen( _PATH_MOUNTED, "r" ); if( mntfile ) { struct mntent *me; diff --git a/lib/libexif/ExifParse.cpp b/lib/libexif/ExifParse.cpp index 2386fd3dab..4f39a51b51 100644 --- a/lib/libexif/ExifParse.cpp +++ b/lib/libexif/ExifParse.cpp @@ -33,6 +33,7 @@ #include <windows.h> #else #include <memory.h> +#include <cstring> #define min(a,b) (a)>(b)?(b):(a) #define max(a,b) (a)<(b)?(b):(a) #endif diff --git a/lib/libexif/JpegParse.cpp b/lib/libexif/JpegParse.cpp index 87f0d6296b..ded323119a 100644 --- a/lib/libexif/JpegParse.cpp +++ b/lib/libexif/JpegParse.cpp @@ -34,6 +34,7 @@ #include <windows.h> #else #include <memory.h> +#include <cstring> #define min(a,b) (a)>(b)?(b):(a) typedef unsigned char BYTE; #endif diff --git a/lib/libexif/libexif.cpp b/lib/libexif/libexif.cpp index 12e298c304..5f1804d789 100644 --- a/lib/libexif/libexif.cpp +++ b/lib/libexif/libexif.cpp @@ -5,6 +5,7 @@ #include <windows.h> #else #include <memory.h> +#include <cstring> #endif #include "JpegParse.h" #include "libexif.h" diff --git a/lib/libexif/libexif.vcxproj b/lib/libexif/libexif.vcxproj index 22feb4a89a..9ddb6c5a44 100644 --- a/lib/libexif/libexif.vcxproj +++ b/lib/libexif/libexif.vcxproj @@ -82,6 +82,7 @@ </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Link> <OutputFile>$(OutDir)libexif.exe</OutputFile> diff --git a/lib/libhdhomerun/Makefile.in b/lib/libhdhomerun/Makefile.in index 825bbde184..ce909c17ca 100644 --- a/lib/libhdhomerun/Makefile.in +++ b/lib/libhdhomerun/Makefile.in @@ -24,7 +24,7 @@ ifeq ($(findstring osx,$(ARCH)), osx) -bundle -undefined dynamic_lookup -read_only_relocs suppress -o $@ \ @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.o $(OBJS) else - $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -shared -o $@ -Wl,--unresolved-symbols=ignore-all \ + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -shared -o $@ -Wl,--unresolved-symbols=ignore-all -lm \ `cat @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.def` \ @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.o endif diff --git a/lib/libhdhomerun/hdhomerun/hdhomerun.vcxproj b/lib/libhdhomerun/hdhomerun/hdhomerun.vcxproj index dcd2cbc022..eb826e08e9 100644 --- a/lib/libhdhomerun/hdhomerun/hdhomerun.vcxproj +++ b/lib/libhdhomerun/hdhomerun/hdhomerun.vcxproj @@ -69,6 +69,7 @@ <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <CompileAs>CompileAsCpp</CompileAs> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Link> <AdditionalDependencies>ws2_32.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/lib/libhdhomerun/hdhomerun_os_posix.h b/lib/libhdhomerun/hdhomerun_os_posix.h index e47bea17a7..c68ecce53a 100644 --- a/lib/libhdhomerun/hdhomerun_os_posix.h +++ b/lib/libhdhomerun/hdhomerun_os_posix.h @@ -43,7 +43,11 @@ #include <sys/time.h> #include <sys/timeb.h> #include <sys/wait.h> +#if defined(__ANDROID__) +#include <signal.h> +#else #include <sys/signal.h> +#endif #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> diff --git a/lib/libhts/Win32/libhts_2010.vcxproj b/lib/libhts/Win32/libhts_2010.vcxproj index ffc4f86d45..a321e0c780 100644 --- a/lib/libhts/Win32/libhts_2010.vcxproj +++ b/lib/libhts/Win32/libhts_2010.vcxproj @@ -57,6 +57,7 @@ </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Lib> <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> diff --git a/lib/libid3tag/Makefile.in b/lib/libid3tag/Makefile.in index c4c4ba7220..b58f2c9d06 100644 --- a/lib/libid3tag/Makefile.in +++ b/lib/libid3tag/Makefile.in @@ -18,7 +18,7 @@ else $(SLIB): libid3tag/.libs/libid3tag.so $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -fPIC -Wl,--unresolved-symbols=ignore-all -o $@ libid3tag/.libs/*.o \ `cat ../../xbmc/cores/DllLoader/exports/wrapper.def` \ - ../../xbmc/cores/DllLoader/exports/wrapper.o + ../../xbmc/cores/DllLoader/exports/wrapper.o -lz endif ifeq ($(findstring osx,$(ARCH)), osx) diff --git a/lib/libid3tag/libid3tag/msvc++/libid3tag.vcxproj b/lib/libid3tag/libid3tag/msvc++/libid3tag.vcxproj index 2a9a8e0dab..efafd176c3 100644 --- a/lib/libid3tag/libid3tag/msvc++/libid3tag.vcxproj +++ b/lib/libid3tag/libid3tag/msvc++/libid3tag.vcxproj @@ -140,6 +140,7 @@ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <CompileAs>Default</CompileAs> <MinimalRebuild>true</MinimalRebuild> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/lib/liblame/vc_solution/vc10_libmp3lame_dll.vcxproj b/lib/liblame/vc_solution/vc10_libmp3lame_dll.vcxproj index 1d0c799a51..7fa666404e 100644 --- a/lib/liblame/vc_solution/vc10_libmp3lame_dll.vcxproj +++ b/lib/liblame/vc_solution/vc10_libmp3lame_dll.vcxproj @@ -146,6 +146,7 @@ <PreprocessorDefinitions>_DEBUG;_WINDOWS;HAVE_MPGLIB;WIN32;HAVE_CONFIG_H;%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_VC80_UPGRADE=0x0600;_DLL=$(TargetFileName);_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/lib/libmad/msvc++/libmad.vcxproj b/lib/libmad/msvc++/libmad.vcxproj index 426c567765..b29e611453 100644 --- a/lib/libmad/msvc++/libmad.vcxproj +++ b/lib/libmad/msvc++/libmad.vcxproj @@ -68,6 +68,7 @@ <SuppressStartupBanner>true</SuppressStartupBanner> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <MinimalRebuild>true</MinimalRebuild> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/lib/libmodplug/libmodplug_2010.vcxproj b/lib/libmodplug/libmodplug_2010.vcxproj index 00effaf3b1..a6245398d5 100644 --- a/lib/libmodplug/libmodplug_2010.vcxproj +++ b/lib/libmodplug/libmodplug_2010.vcxproj @@ -59,6 +59,7 @@ <RuntimeTypeInfo>false</RuntimeTypeInfo> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Link> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> diff --git a/lib/libsidplay2/libsidplay/win/VC/libsidplay.vcxproj b/lib/libsidplay2/libsidplay/win/VC/libsidplay.vcxproj index 9ba0fb9cc9..4f68e2f898 100644 --- a/lib/libsidplay2/libsidplay/win/VC/libsidplay.vcxproj +++ b/lib/libsidplay2/libsidplay/win/VC/libsidplay.vcxproj @@ -140,6 +140,7 @@ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DisableSpecificWarnings>4231;4355;4910;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings> <MinimalRebuild>true</MinimalRebuild> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/lib/libsquish/Makefile.in b/lib/libsquish/Makefile.in index 2b4a7ac084..f7b3cc1621 100644 --- a/lib/libsquish/Makefile.in +++ b/lib/libsquish/Makefile.in @@ -24,14 +24,14 @@ ifeq (@USE_TEXTUREPACKER_NATIVE@,1) NATIVE_LIB=libsquish-native.so CLEAN_FILES+=$(NATIVE_LIB) -ifeq ($(findstring osx,$(ARCH)),osx) -NATIVE_ARCH=$(shell echo $(CXXFLAGS) | grep x86_64 >/dev/null && echo -m64 || echo -m32) +ifeq ($(findstring Darwin,$(shell uname -s)),Darwin) +NATIVE_ARCH=@DARWIN_NATIVE_ARCH@ endif all: $(LIB) $(NATIVE_LIB) # TexturePacker links to libsquish and needs to run on build system, so make a native flavor. $(NATIVE_LIB): $(SRCS) -ifeq ($(findstring osx,$(ARCH)),osx) +ifeq ($(findstring Darwin,$(shell uname -s)),Darwin) g++ $(NATIVE_ARCH) -DSQUISH_USE_SSE=2 -msse2 -I. $(SRCS) -dynamiclib -install_name `pwd`/libsquish-native.so -o $@ else g++ -DSQUISH_USE_SSE=2 -msse2 -I. $(SRCS) -shared -fPIC -Wl,-soname,`pwd`/libsquish-native.so -o $@ diff --git a/lib/libsquish/vs7/squish/squish_2010.vcxproj b/lib/libsquish/vs7/squish/squish_2010.vcxproj index bf2e4dc345..b1e7481434 100644 --- a/lib/libsquish/vs7/squish/squish_2010.vcxproj +++ b/lib/libsquish/vs7/squish/squish_2010.vcxproj @@ -54,7 +54,7 @@ <MinimalRebuild>true</MinimalRebuild> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> - <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <WarningLevel>Level4</WarningLevel> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> @@ -75,7 +75,7 @@ <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <WarningLevel>Level4</WarningLevel> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> - <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Lib> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> diff --git a/lib/nosefart/Makefile.in b/lib/nosefart/Makefile.in index f8a8397cec..0da88b6a76 100644 --- a/lib/nosefart/Makefile.in +++ b/lib/nosefart/Makefile.in @@ -31,7 +31,7 @@ ifeq ($(findstring osx,$(ARCH)), osx) -bundle -undefined dynamic_lookup -read_only_relocs suppress -o $@ \ @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.o $(OBJS) $(BUNDLE1_O) else - $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $(OBJS) -Wl,--unresolved-symbols=ignore-all \ + $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $(OBJS) -Wl,--unresolved-symbols=ignore-all -lm \ `cat @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.def` @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.o endif diff --git a/lib/nosefart/NoseFartXBMC.vcxproj b/lib/nosefart/NoseFartXBMC.vcxproj index cc642edec5..936deaf908 100644 --- a/lib/nosefart/NoseFartXBMC.vcxproj +++ b/lib/nosefart/NoseFartXBMC.vcxproj @@ -71,6 +71,7 @@ <DisableLanguageExtensions>false</DisableLanguageExtensions> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Link> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> diff --git a/lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj b/lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj index d21b7b6b0a..40b3045bbc 100644 --- a/lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj +++ b/lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj @@ -68,6 +68,7 @@ <SuppressStartupBanner>true</SuppressStartupBanner> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DisableSpecificWarnings>4018;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/lib/vgmstream/win32/win32.vcxproj b/lib/vgmstream/win32/win32.vcxproj index f94f3b592e..497d927470 100644 --- a/lib/vgmstream/win32/win32.vcxproj +++ b/lib/vgmstream/win32/win32.vcxproj @@ -71,6 +71,7 @@ <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DisableSpecificWarnings>4267;4018;4244;4312;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Link> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> diff --git a/lib/win32/pcre/libpcre/libpcre.vcxproj b/lib/win32/pcre/libpcre/libpcre.vcxproj index 09921d85a8..2630e8bac3 100644 --- a/lib/win32/pcre/libpcre/libpcre.vcxproj +++ b/lib/win32/pcre/libpcre/libpcre.vcxproj @@ -57,6 +57,7 @@ <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <CompileAs>CompileAsCpp</CompileAs> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Lib> <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> diff --git a/lib/xbadpcm/Makefile.in b/lib/xbadpcm/Makefile.in index 2a53042781..0a2bc43e44 100644 --- a/lib/xbadpcm/Makefile.in +++ b/lib/xbadpcm/Makefile.in @@ -12,7 +12,7 @@ ifeq ($(findstring osx,$(ARCH)), osx) @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.o *.o $(BUNDLE1_O) chmod +x $@ else - $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ *.o -Wl,--unresolved-symbols=ignore-all \ + $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ *.o -Wl,--unresolved-symbols=ignore-all -lm \ `cat @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.def` @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.o endif diff --git a/lib/xbadpcm/adpcm.vcxproj b/lib/xbadpcm/adpcm.vcxproj index 83b198e43a..84be0b5bdc 100644 --- a/lib/xbadpcm/adpcm.vcxproj +++ b/lib/xbadpcm/adpcm.vcxproj @@ -70,6 +70,7 @@ <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DisableSpecificWarnings>4244;4267;4311;4312;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <ResourceCompile> <ResourceOutputFileName> diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index b51acea87a..45e0513d7d 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -158,6 +158,7 @@ <ForcedIncludeFiles>pch.h;%(ForcedIncludeFiles)</ForcedIncludeFiles> <ShowIncludes>false</ShowIncludes> <MultiProcessorCompilation>true</MultiProcessorCompilation> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Link> <AdditionalOptions>/MACHINE:I386 /IGNORE:4089 /ignore:4254 %(AdditionalOptions)</AdditionalOptions> @@ -321,6 +322,7 @@ <ClCompile Include="..\..\xbmc\cores\VideoRenderers\RenderCapture.cpp" /> <ClCompile Include="..\..\xbmc\cores\VideoRenderers\VideoShaders\WinVideoFilter.cpp" /> <ClCompile Include="..\..\xbmc\CueDocument.cpp" /> + <ClCompile Include="..\..\xbmc\DbUrl.cpp" /> <ClCompile Include="..\..\xbmc\dbwrappers\Database.cpp" /> <ClCompile Include="..\..\xbmc\dbwrappers\dataset.cpp" /> <ClCompile Include="..\..\xbmc\dbwrappers\mysqldataset.cpp" /> @@ -335,7 +337,7 @@ <ClCompile Include="..\..\xbmc\dialogs\GUIDialogFileBrowser.cpp" /> <ClCompile Include="..\..\xbmc\dialogs\GUIDialogGamepad.cpp" /> <ClCompile Include="..\..\xbmc\dialogs\GUIDialogKaiToast.cpp" /> - <ClCompile Include="..\..\xbmc\dialogs\GUIDialogKeyboard.cpp" /> + <ClCompile Include="..\..\xbmc\dialogs\GUIDialogKeyboardGeneric.cpp" /> <ClCompile Include="..\..\xbmc\dialogs\GUIDialogMediaSource.cpp" /> <ClCompile Include="..\..\xbmc\dialogs\GUIDialogMuteBug.cpp" /> <ClCompile Include="..\..\xbmc\dialogs\GUIDialogNumeric.cpp" /> @@ -496,6 +498,7 @@ <ClCompile Include="..\..\xbmc\guilib\GUIImage.cpp" /> <ClCompile Include="..\..\xbmc\guilib\GUIIncludes.cpp" /> <ClCompile Include="..\..\xbmc\guilib\GUIInfoTypes.cpp" /> + <ClCompile Include="..\..\xbmc\guilib\GUIKeyboardFactory.cpp" /> <ClCompile Include="..\..\xbmc\guilib\GUILabel.cpp" /> <ClCompile Include="..\..\xbmc\guilib\GUILabelControl.cpp" /> <ClCompile Include="..\..\xbmc\guilib\GUIListContainer.cpp" /> @@ -745,6 +748,7 @@ <ClCompile Include="..\..\xbmc\music\karaoke\karaokewindowbackground.cpp" /> <ClCompile Include="..\..\xbmc\music\LastFmManager.cpp" /> <ClCompile Include="..\..\xbmc\music\MusicDatabase.cpp" /> + <ClCompile Include="..\..\xbmc\music\MusicDbUrl.cpp" /> <ClCompile Include="..\..\xbmc\music\MusicInfoLoader.cpp" /> <ClCompile Include="..\..\xbmc\music\Song.cpp" /> <ClCompile Include="..\..\xbmc\music\tags\APEv2Tag.cpp" /> @@ -921,12 +925,17 @@ <ClInclude Include="..\..\xbmc\cores\AudioEngine\Utils\AEWAVLoader.h" /> <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDCodecs\Audio\DVDAudioCodecPassthrough.h" /> <ClInclude Include="..\..\xbmc\cores\paplayer\PCMCodec.h" /> + <ClInclude Include="..\..\xbmc\dialogs\GUIDialogKeyboardGeneric.h" /> + <ClInclude Include="..\..\xbmc\DbUrl.h" /> <ClInclude Include="..\..\xbmc\filesystem\ImageFile.h" /> <ClInclude Include="..\..\xbmc\filesystem\VideoDatabaseDirectory\DirectoryNodeTags.h" /> <ClInclude Include="..\..\xbmc\filesystem\windows\WINFileSMB.h" /> <ClInclude Include="..\..\xbmc\filesystem\windows\WINSMBDirectory.h" /> + <ClInclude Include="..\..\xbmc\guilib\GUIKeyboard.h" /> + <ClInclude Include="..\..\xbmc\guilib\GUIKeyboardFactory.h" /> <ClInclude Include="..\..\xbmc\input\windows\WINJoystick.h" /> <ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\pythreadstate.h" /> + <ClInclude Include="..\..\xbmc\music\MusicDbUrl.h" /> <ClInclude Include="..\..\xbmc\network\httprequesthandler\HTTPImageHandler.h" /> <ClInclude Include="..\..\xbmc\network\AirTunesServer.h" /> <ClInclude Include="..\..\xbmc\network\DllLibShairplay.h" /> @@ -1120,6 +1129,7 @@ <ClCompile Include="..\..\xbmc\utils\TimeUtils.cpp" /> <ClCompile Include="..\..\xbmc\utils\TuxBoxUtil.cpp" /> <ClCompile Include="..\..\xbmc\utils\URIUtils.cpp" /> + <ClCompile Include="..\..\xbmc\utils\UrlOptions.cpp" /> <ClCompile Include="..\..\xbmc\utils\Variant.cpp" /> <ClCompile Include="..\..\xbmc\utils\Weather.cpp" /> <ClCompile Include="..\..\xbmc\utils\XBMCTinyXML.cpp" /> @@ -1138,6 +1148,7 @@ <ClCompile Include="..\..\xbmc\video\GUIViewStateVideo.cpp" /> <ClCompile Include="..\..\xbmc\video\Teletext.cpp" /> <ClCompile Include="..\..\xbmc\video\VideoDatabase.cpp" /> + <ClCompile Include="..\..\xbmc\video\VideoDbUrl.cpp" /> <ClCompile Include="..\..\xbmc\video\VideoInfoDownloader.cpp" /> <ClCompile Include="..\..\xbmc\video\VideoInfoScanner.cpp" /> <ClCompile Include="..\..\xbmc\video\VideoInfoTag.cpp" /> @@ -1468,7 +1479,6 @@ <ClInclude Include="..\..\xbmc\dialogs\GUIDialogFileBrowser.h" /> <ClInclude Include="..\..\xbmc\dialogs\GUIDialogGamepad.h" /> <ClInclude Include="..\..\xbmc\dialogs\GUIDialogKaiToast.h" /> - <ClInclude Include="..\..\xbmc\dialogs\GUIDialogKeyboard.h" /> <ClInclude Include="..\..\xbmc\dialogs\GUIDialogMediaSource.h" /> <ClInclude Include="..\..\xbmc\dialogs\GUIDialogMuteBug.h" /> <ClInclude Include="..\..\xbmc\dialogs\GUIDialogNumeric.h" /> @@ -1915,6 +1925,7 @@ <ClInclude Include="..\..\xbmc\utils\TimeUtils.h" /> <ClInclude Include="..\..\xbmc\utils\TuxBoxUtil.h" /> <ClInclude Include="..\..\xbmc\utils\URIUtils.h" /> + <ClInclude Include="..\..\xbmc\utils\UrlOptions.h" /> <ClInclude Include="..\..\xbmc\utils\Variant.h" /> <ClInclude Include="..\..\xbmc\utils\Weather.h" /> <ClInclude Include="..\..\xbmc\utils\XBMCTinyXML.h" /> @@ -1934,6 +1945,7 @@ <ClInclude Include="..\..\xbmc\video\Teletext.h" /> <ClInclude Include="..\..\xbmc\video\TeletextDefines.h" /> <ClInclude Include="..\..\xbmc\video\VideoDatabase.h" /> + <ClInclude Include="..\..\xbmc\video\VideoDbUrl.h" /> <ClInclude Include="..\..\xbmc\video\VideoInfoDownloader.h" /> <ClInclude Include="..\..\xbmc\video\VideoInfoScanner.h" /> <ClInclude Include="..\..\xbmc\video\VideoInfoTag.h" /> @@ -2282,4 +2294,4 @@ </VisualStudio> </ProjectExtensions> <Import Project="$(SolutionDir)\$(ProjectFileName).targets.user" Condition="Exists('$(SolutionDir)\$(ProjectFileName).targets.user')" /> -</Project> +</Project>
\ No newline at end of file diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters index 5db2a078ec..64f1650c2d 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters @@ -897,9 +897,6 @@ <ClCompile Include="..\..\xbmc\dialogs\GUIDialogKaiToast.cpp"> <Filter>dialogs</Filter> </ClCompile> - <ClCompile Include="..\..\xbmc\dialogs\GUIDialogKeyboard.cpp"> - <Filter>dialogs</Filter> - </ClCompile> <ClCompile Include="..\..\xbmc\dialogs\GUIDialogMediaSource.cpp"> <Filter>dialogs</Filter> </ClCompile> @@ -2587,6 +2584,22 @@ <ClCompile Include="..\..\xbmc\utils\EndianSwap.cpp"> <Filter>utils</Filter> </ClCompile> + <ClCompile Include="..\..\xbmc\guilib\GUIKeyboardFactory.cpp"> + <Filter>guilib</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\dialogs\GUIDialogKeyboardGeneric.cpp"> + <Filter>dialogs</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\video\VideoDbUrl.cpp"> + <Filter>video</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\DbUrl.cpp" /> + <ClCompile Include="..\..\xbmc\utils\UrlOptions.cpp"> + <Filter>utils</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\music\MusicDbUrl.cpp"> + <Filter>music</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\xbmc\win32\pch.h"> @@ -3402,9 +3415,6 @@ <ClInclude Include="..\..\xbmc\dialogs\GUIDialogKaiToast.h"> <Filter>dialogs</Filter> </ClInclude> - <ClInclude Include="..\..\xbmc\dialogs\GUIDialogKeyboard.h"> - <Filter>dialogs</Filter> - </ClInclude> <ClInclude Include="..\..\xbmc\dialogs\GUIDialogMediaSource.h"> <Filter>dialogs</Filter> </ClInclude> @@ -5215,6 +5225,25 @@ <ClInclude Include="..\..\xbmc\filesystem\VideoDatabaseDirectory\DirectoryNodeTags.h"> <Filter>filesystem\VideoDatabaseDirectory</Filter> </ClInclude> + <ClInclude Include="..\..\xbmc\guilib\GUIKeyboard.h"> + <Filter>guilib</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\guilib\GUIKeyboardFactory.h"> + <Filter>guilib</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\dialogs\GUIDialogKeyboardGeneric.h"> + <Filter>dialogs</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\video\VideoDbUrl.h"> + <Filter>video</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\DbUrl.h" /> + <ClInclude Include="..\..\xbmc\utils\UrlOptions.h"> + <Filter>utils</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\music\MusicDbUrl.h"> + <Filter>music</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ResourceCompile Include="..\..\xbmc\win32\XBMC_PC.rc"> @@ -5226,4 +5255,4 @@ <Filter>win32</Filter> </CustomBuild> </ItemGroup> -</Project> +</Project>
\ No newline at end of file diff --git a/project/VS2010Express/libPlatinum.vcxproj b/project/VS2010Express/libPlatinum.vcxproj index 1c0aede79d..f392468ffd 100644 --- a/project/VS2010Express/libPlatinum.vcxproj +++ b/project/VS2010Express/libPlatinum.vcxproj @@ -60,6 +60,7 @@ <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Lib> <OutputFile>$(OutDir)libPlatinumd.lib</OutputFile> diff --git a/system/peripherals.xml b/system/peripherals.xml index 9589295c87..cf0c6c442f 100644 --- a/system/peripherals.xml +++ b/system/peripherals.xml @@ -19,10 +19,11 @@ <setting key="standby_tv_on_pc_standby" type="bool" value="1" label="36026" order="7" /> <setting key="send_inactive_source" type="bool" value="1" label="36025" order="8" /> <setting key="use_tv_menu_language" type="bool" value="1" label="36018" order="9" /> - <setting key="physical_address" type="string" label="36021" value="0" order="10" /> - <setting key="cec_hdmi_port" type="int" value="1" min="1" max="15" label="36015" order="11" /> - <setting key="connected_device" type="int" label="36019" value="0" min="0" max="15" step="1" order="12" /> - <setting key="port" type="string" value="" label="36022" order="13" /> + <setting key="pause_playback_on_deactivate" type="bool" value="1" label="36033" order="10" /> + <setting key="physical_address" type="string" label="36021" value="0" order="11" /> + <setting key="cec_hdmi_port" type="int" value="1" min="1" max="15" label="36015" order="12" /> + <setting key="connected_device" type="int" label="36019" value="0" min="0" max="15" step="1" order="13" /> + <setting key="port" type="string" value="" label="36022" order="14" /> <setting key="tv_vendor" type="int" value="0" configurable="0" /> <setting key="device_name" type="string" value="XBMC" configurable="0" /> diff --git a/system/playercorefactory.xml b/system/playercorefactory.xml index 66784de36f..6e475ef0f5 100644 --- a/system/playercorefactory.xml +++ b/system/playercorefactory.xml @@ -24,9 +24,9 @@ </rule> <!-- DVDs --> - <rule name="dvd" dvd="true" player="videodefaultdvdplayer" /> - <rule name="dvdfile" dvdfile="true" player="videodefaultdvdplayer" /> - <rule name="dvdimage" dvdimage="true" player="videodefaultdvdplayer" /> + <rule name="dvd" dvd="true" player="DVDPlayer" /> + <rule name="dvdfile" dvdfile="true" player="DVDPlayer" /> + <rule name="dvdimage" dvdimage="true" player="DVDPlayer" /> <!-- Only dvdplayer can handle these normally --> <rule name="sdp/asf" filetypes="sdp|asf" player="DVDPlayer" /> diff --git a/tools/Linux/xbmc.desktop b/tools/Linux/xbmc.desktop index 46e2f8e4f8..fd3ea1b869 100644 --- a/tools/Linux/xbmc.desktop +++ b/tools/Linux/xbmc.desktop @@ -14,9 +14,9 @@ Actions=Fullscreen;Standalone [Desktop Action Fullscreen] Name=Open in fullscreen Exec=xbmc -fs -OnlyShowIn=Unity +OnlyShowIn=Unity; [Desktop Action Standalone] Name=Open in standalone mode -Exect=xbmc --standalone -OnlyShowIn=Unity +Exec=xbmc --standalone +OnlyShowIn=Unity; diff --git a/tools/TexturePacker/Makefile.in b/tools/TexturePacker/Makefile.in index 482a6af087..951720d817 100644 --- a/tools/TexturePacker/Makefile.in +++ b/tools/TexturePacker/Makefile.in @@ -9,17 +9,25 @@ CXXFLAGS+= \ -I@abs_top_srcdir@/xbmc \ -I@abs_top_srcdir@/xbmc/linux +RPATH=-Wl,-rpath=$(NATIVE_ROOT_PATH)/lib + ifeq (@USE_TEXTUREPACKER_NATIVE@,1) NATIVE_ROOT_PATH=@USE_TEXTUREPACKER_NATIVE_ROOT@ ifdef NATIVE_ROOT_PATH -ifeq ($(findstring osx,@ARCH@),osx) +ifeq ($(findstring Darwin,$(shell uname -s)),Darwin) DEFINES += -DTARGET_DARWIN -NATIVE_ARCH=$(shell echo $(CXXFLAGS) | grep x86_64 >/dev/null && echo -m64 || echo -m32) +NATIVE_ARCH=@DARWIN_NATIVE_ARCH@ +RPATH= endif -CXXFLAGS+= -I$(NATIVE_ROOT_PATH)/include -LIBS += -L$(NATIVE_ROOT_PATH)/lib +NATIVE_CXXFLAGS+= -I. \ + -I$(NATIVE_ROOT_PATH)/include \ + -I@abs_top_srcdir@/lib \ + -I@abs_top_srcdir@/xbmc \ + -I@abs_top_srcdir@/xbmc/linux +NATIVE_LIBS += -L$(NATIVE_ROOT_PATH)/lib endif -LIBS += -L@abs_top_srcdir@/lib/libsquish -lsquish-native +NATIVE_LIBS += -lSDL_image -lSDL -llzo2 +NATIVE_LIBS += -L@abs_top_srcdir@/lib/libsquish -lsquish-native else LIBS += -L@abs_top_srcdir@/lib/libsquish -lsquish endif @@ -42,7 +50,7 @@ all: $(TARGET) ifeq (@USE_TEXTUREPACKER_NATIVE@,1) # TexturePacker run native on build system, build it with native tools $(TARGET): $(SRCS) - g++ $(DEFINES) $(NATIVE_ARCH) $(CXXFLAGS) $(SRCS) $(LIBS) -o $(TARGET) + g++ $(DEFINES) $(NATIVE_ARCH) $(NATIVE_CXXFLAGS) $(SRCS) $(NATIVE_LIBS) $(RPATH) -o $(TARGET) clean: rm -f $(TARGET) else diff --git a/tools/android/depends/.gitignore b/tools/android/depends/.gitignore new file mode 100644 index 0000000000..923edf28fe --- /dev/null +++ b/tools/android/depends/.gitignore @@ -0,0 +1,10 @@ +/Makefile +/configure +/Makefile.include +/autom4te.cache/ +/**/.gitignore +/**/.installed-* +/*/x86/* +/*/x86-native/* +/*/armeabi-v7a/* +/*/armeabi-v7a-native/* diff --git a/tools/android/depends/Makefile.in b/tools/android/depends/Makefile.in new file mode 100644 index 0000000000..4027fb264a --- /dev/null +++ b/tools/android/depends/Makefile.in @@ -0,0 +1,88 @@ +#include Makefile.include + +BUILDTOOLS = help2man gettext-native autoconf automake libtool pkg-config yasm cmake + +SUBDIRS = \ + ncurses pcre expat libiconv gettext readline sqlite3 libgpg-error \ + libgcrypt bzip2 liblzo2 libzip freetype2 fontconfig \ + openssl libssh2 curl \ + libjpeg-turbo tiff jasper libpng \ + libogg libvorbis libflac libid3tag libmad fribidi libmpeg2 \ + libass libsamplerate \ + libmodplug librtmp libxml2 yajl libmicrohttpd mysql libffi \ + python26-native python26 samba alsa-lib libcdio afpfs-ng libshairport \ + libplist libcec libbluray boost tinyxml dummy-libxbmc libsdl \ + liblzo2-native libjpeg-turbo-native libpng-native tiff-native libsdl_image rpl \ + libamplayer libssh + +.PHONY: buildtools $(BUILDTOOLS) subdirs $(SUBDIRS) arm + +all: subdirs + @echo "Dependencies built successfully." + +release: armeabi-v7a x86 + +# Dependency layout for parallel builds +gettext: libiconv ncurses +libgcrypt: libgpg-error +fontconfig: freetype2 expat libiconv +libssh2: libgcrypt openssl rpl +curl: openssl libssh2 rpl +tiff: libjpeg-turbo +jasper: libjpeg-turbo +libvorbis: libogg rpl +libflac: libogg gettext rpl +libass: fontconfig libpng freetype2 expat libiconv rpl +librtmp: openssl rpl +libxml2: libiconv +libmicrohttpd: openssl libgpg-error libgcrypt +python26: python26-native expat gettext libxml2 sqlite3 openssl libffi +libcdio: libiconv +afpfs-ng: libgcrypt readline libiconv rpl +libshairport: openssl rpl +libplist: libxml2 cmake +libbluray: libiconv libxml2 rpl +yajl: cmake +libsdl_image: buildtools libsdl libjpeg-turbo-native libpng-native tiff-native +python26-native: buildtools +libsdl: buildtools +alsa-lib: rpl +libcec: rpl +libid3tag: rpl +libmad: rpl +libmodplug: rpl +libmpeg2: rpl +libogg: rpl +rpl: python26-native +libjpeg-turbo-native: buildtools +libpng-native: buildtools +tiff-native: buildtools libjpeg-turbo-native +liblzo2-native: buildtools +libssh: openssl cmake rpl + + +X86OVERRIDES=XBMC_OVERRIDE_HOST=i686-android-linux XBMC_OVERRIDE_TOOLCHAIN=$(XBMC_X86_TOOLCHAIN) +ARMOVERRIDES=XBMC_OVERRIDE_HOST=arm-linux-androideabi XBMC_OVERRIDE_TOOLCHAIN=$(XBMC_ARM_TOOLCHAIN) + +buildtools: $(BUILDTOOLS) +$(BUILDTOOLS): + $(MAKE) -C $@ + +subdirs: $(SUBDIRS) +$(SUBDIRS): help2man autoconf automake libtool pkg-config yasm + $(MAKE) -C $@ +clean: + for d in $(BUILDTOOLS); do $(MAKE) -C $$d clean; done + for d in $(SUBDIRS); do $(MAKE) -C $$d clean; done + +distclean:: + for d in $(BUILDTOOLS); do $(MAKE) -C $$d distclean; done + for d in $(SUBDIRS); do $(MAKE) -C $$d distclean; done + +arm: armeabi-v7a + +armeabi-v7a: $(XBMC_ARM_TOOLCHAIN) + XBMC_OVERRIDE_PLATFORM=$@ $(ARMOVERRIDES) $(MAKE) all + +x86: $(XBMC_X86_TOOLCHAIN) + XBMC_OVERRIDE_PLATFORM=$@ $(X86OVERRIDES) $(MAKE) all diff --git a/tools/android/depends/Makefile.include.in b/tools/android/depends/Makefile.include.in new file mode 100644 index 0000000000..85b8e798db --- /dev/null +++ b/tools/android/depends/Makefile.include.in @@ -0,0 +1,82 @@ +TOOLCHAIN=@use_toolchain@ +NDKROOT=@use_ndk@ +SDKROOT=@use_sdk@ +XBMCPREFIX=@use_staging@ +TARBALLS_LOCATION=@use_tarballs@ +HOST=@use_host@ +PLATFORM=@use_cpu@ +NATIVEPLATFORM=@use_cpu@-native +SDK_PLATFORM=@use_sdk_platform@ +RETRIEVE_TOOL=@CURL@ +ARCHIVE_TOOL=@TAR@ + +ifneq ($(XBMC_OVERRIDE_TOOLCHAIN),) +TOOLCHAIN=$(XBMC_OVERRIDE_TOOLCHAIN) +endif + +ifneq ($(XBMC_OVERRIDE_PLATFORM),) +PLATFORM=$(XBMC_OVERRIDE_PLATFORM) +NATIVEPLATFORM=$(XBMC_OVERRIDE_PLATFORM)-native +endif + +ifneq ($(XBMC_OVERRIDE_HOST),) +HOST=$(XBMC_OVERRIDE_HOST) +endif + +PREFIX=$(XBMCPREFIX)/$(PLATFORM) +NATIVEPREFIX=$(XBMCPREFIX)/$(NATIVEPLATFORM) + +PLATFORM_FLAGS=-DANDROID -Os +ifeq ($(PLATFORM),armeabi-v7a) + PLATFORM_FLAGS+=-march=armv7-a -mtune=cortex-a9 -mfloat-abi=softfp -mfpu=neon -D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ +endif + +ifeq ($(PLATFORM),x86) + PLATFORM_FLAGS+=-fomit-frame-pointer +endif + +BASE_URL=http://mirrors.xbmc.org/build-deps/sources +RETRIEVE_TOOL_FLAGS=-Ls --create-dirs -f --output $(TARBALLS_LOCATION)/$(ARCHIVE) +ARCHIVE_TOOL_FLAGS=-C $(PLATFORM) --strip-components=1 -xf +CONFIG_SUB=$(NATIVEPREFIX)/share/automake-1.11/config.sub +CONFIG_GUESS=$(NATIVEPREFIX)/share/automake-1.11/config.guess +RPL=$(NATIVEPREFIX)/bin/python $(NATIVEPREFIX)/bin/rpl +YASM=$(NATIVEPREFIX)/bin/yasm + +ifneq ($(NATIVE_BUILD),1) + export SYSROOT=$(TOOLCHAIN)/sysroot + export CROSSTOOLS=$(TOOLCHAIN)/bin/$(HOST)- + export LD=$(CROSSTOOLS)ld + export CC=$(CROSSTOOLS)gcc + export CXX=$(CROSSTOOLS)g++ + export AR=$(CROSSTOOLS)ar + export AS=$(CROSSTOOLS)as + export NM=$(CROSSTOOLS)nm + export STRIP=$(CROSSTOOLS)strip + export RANLIB=$(CROSSTOOLS)ranlib + export OBJDUMP=$(CROSSTOOLS)objdump + export READELF=$(CROSSTOOLS)readelf + export CFLAGS=$(PLATFORM_FLAGS) -I$(PREFIX)/include -I$(PREFIX)/include/$(SDK_PLATFORM) -fexceptions + export LDFLAGS=$(PLATFORM_FLAGS) -L$(PREFIX)/lib -L$(PREFIX)/lib/$(SDK_PLATFORM) + export CPPFLAGS=$(PLATFORM_FLAGS) -I$(PREFIX)/include -I$(PREFIX)/include/$(SDK_PLATFORM) -fexceptions + export CXXFLAGS=$(PLATFORM_FLAGS) -I$(PREFIX)/include -I$(PREFIX)/include/$(SDK_PLATFORM) -fexceptions -frtti + + export PKG_CONFIG_PATH=$(PREFIX)/lib/pkgconfig + export PKG_CONFIG=$(NATIVEPREFIX)/bin/pkg-config + + export AUTOMAKE=$(NATIVEPREFIX)/bin/automake + export AUTOCONF=$(NATIVEPREFIX)/bin/autoconf + export ACLOCAL=$(NATIVEPREFIX)/bin/aclocal + export ACLOCAL_PATH=$(PREFIX)/share/aclocal:$(NATIVEPREFIX)/share/aclocal + export LIBTOOLIZE=$(NATIVEPREFIX)/bin/libtoolize + export AUTORECONF=$(NATIVEPREFIX)/bin/autoreconf +else + PLATFORM=$(NATIVEPLATFORM) + PREFIX=$(NATIVEPREFIX) + + export CFLAGS=-I$(PREFIX)/include + export LDFLAGS=-L$(PREFIX)/lib + export CPPFLAGS=-I$(PREFIX)/include + export CXXFLAGS=-I$(PREFIX)/include +endif + export PATH:=$(NATIVEPREFIX)/bin:$(PATH) diff --git a/tools/android/depends/afpfs-ng/01-gcrypt.patch b/tools/android/depends/afpfs-ng/01-gcrypt.patch new file mode 100644 index 0000000000..7bcace2812 --- /dev/null +++ b/tools/android/depends/afpfs-ng/01-gcrypt.patch @@ -0,0 +1,26 @@ +diff -ru afpfs-ng-0.8.1/configure.ac afpfs-ng-0.8.1+iPhone/configure.ac +--- afpfs-ng-0.8.1/configure.ac 2008-03-08 16:23:12.000000000 +0000 ++++ afpfs-ng-0.8.1+iPhone/configure.ac 2010-10-24 05:26:15.000000000 +0000 +@@ -50,21 +50,6 @@ + case $host in + *-*-darwin*) + AC_MSG_CHECKING([for correct gcrypt version]) +- AC_RUN_IFELSE( +- [AC_LANG_PROGRAM([ +- #include <gcrypt.h> +- #include <stdio.h>],[ +- char*p= GCRYPT_VERSION; +- unsigned int vers; +- vers=atoi(p)*10000; +- p=strchr(p,'.')+1; +- vers+=atoi(p)*100; +- p=strchr(p,'.')+1; +- vers+=atoi(p); +- if (vers<10400) return 1; +- ])], +- [AC_MSG_RESULT([yes])], +- [AC_MSG_ERROR([version is < 1.4.0])]) + AM_CONDITIONAL(HAVE_LIBGCRYPT, true) + AC_DEFINE([HAVE_LIBGCRYPT], [1] ) + ;; + diff --git a/tools/android/depends/afpfs-ng/02-pointer.patch b/tools/android/depends/afpfs-ng/02-pointer.patch new file mode 100644 index 0000000000..80507b5725 --- /dev/null +++ b/tools/android/depends/afpfs-ng/02-pointer.patch @@ -0,0 +1,280 @@ +diff -up afpfs-ng-0.8.1/cmdline/getstatus.c.pointer afpfs-ng-0.8.1/cmdline/getstatus.c +--- afpfs-ng-0.8.1/cmdline/getstatus.c.pointer 2011-06-14 17:06:35.000000000 +0200 ++++ afpfs-ng-0.8.1/cmdline/getstatus.c 2011-06-14 17:07:25.000000000 +0200 +@@ -1,4 +1,5 @@ + #include <stdio.h> ++#include <stdlib.h> + #include <string.h> + #include <pthread.h> + +diff -up afpfs-ng-0.8.1/fuse/client.c.pointer afpfs-ng-0.8.1/fuse/client.c +--- afpfs-ng-0.8.1/fuse/client.c.pointer 2008-03-08 03:44:16.000000000 +0100 ++++ afpfs-ng-0.8.1/fuse/client.c 2011-06-14 17:02:15.000000000 +0200 +@@ -61,8 +61,9 @@ static int start_afpfsd(void) + snprintf(filename, PATH_MAX, + "/usr/local/bin/%s",AFPFSD_FILENAME); + if (access(filename,X_OK)) { +- snprintf(filename, "/usr/bin/%s", ++ snprintf(filename, sizeof(filename), "/usr/bin/%s", + AFPFSD_FILENAME); ++ filename[sizeof(filename) - 1] = 0; + if (access(filename,X_OK)) { + printf("Could not find server (%s)\n", + filename); +diff -up afpfs-ng-0.8.1/fuse/fuse_int.c.pointer afpfs-ng-0.8.1/fuse/fuse_int.c +--- afpfs-ng-0.8.1/fuse/fuse_int.c.pointer 2008-03-02 06:06:24.000000000 +0100 ++++ afpfs-ng-0.8.1/fuse/fuse_int.c 2011-06-14 17:02:15.000000000 +0200 +@@ -197,7 +197,7 @@ static int fuse_open(const char *path, s + ret = ml_open(volume,path,flags,&fp); + + if (ret==0) +- fi->fh=(void *) fp; ++ fi->fh=(unsigned long) fp; + + return ret; + } +diff -up afpfs-ng-0.8.1/include/afpfs-ng/afp.h.pointer afpfs-ng-0.8.1/include/afp.h +--- afpfs-ng-0.8.1/include/afpfs-ng/afp.h.pointer 2008-03-08 17:08:18.000000000 +0100 ++++ afpfs-ng-0.8.1/include/afpfs-ng/afp.h 2011-06-14 17:02:15.000000000 +0200 +@@ -370,7 +370,7 @@ int afp_unmount_all_volumes(struct afp_s + + int afp_opendt(struct afp_volume *volume, unsigned short * refnum); + +-int afp_closedt(struct afp_server * server, unsigned short * refnum); ++int afp_closedt(struct afp_server * server, unsigned short refnum); + + int afp_getcomment(struct afp_volume *volume, unsigned int did, + const char * pathname, struct afp_comment * comment); +diff -up afpfs-ng-0.8.1/include/afpfs-gn/utils.h.pointer afpfs-ng-0.8.1/include/utils.h +--- afpfs-ng-0.8.1/include/afpfs-ng/utils.h.pointer 2008-02-18 04:33:58.000000000 +0100 ++++ afpfs-ng-0.8.1/include/afpfs-ng/utils.h 2011-06-14 17:02:15.000000000 +0200 +@@ -8,8 +8,8 @@ + #define hton64(x) (x) + #define ntoh64(x) (x) + #else /* BYTE_ORDER == BIG_ENDIAN */ +-#define hton64(x) ((u_int64_t) (htonl(((x) >> 32) & 0xffffffffLL)) | \ +- (u_int64_t) ((htonl(x) & 0xffffffffLL) << 32)) ++#define hton64(x) ((u_int64_t) (htonl((((unsigned long long)(x)) >> 32) & 0xffffffffLL)) | \ ++ (u_int64_t) ((htonl((unsigned long long)(x)) & 0xffffffffLL) << 32)) + #define ntoh64(x) (hton64(x)) + #endif /* BYTE_ORDER == BIG_ENDIAN */ + +diff -up afpfs-ng-0.8.1/lib/afp_url.c.pointer afpfs-ng-0.8.1/lib/afp_url.c +--- afpfs-ng-0.8.1/lib/afp_url.c.pointer 2008-03-04 21:16:49.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/afp_url.c 2011-06-14 17:02:15.000000000 +0200 +@@ -33,7 +33,7 @@ static int check_port(char * port) + static int check_uamname(const char * uam) + { + char * p; +- for (p=uam;*p;p++) { ++ for (p=(char *)uam;*p;p++) { + if (*p==' ') continue; + if ((*p<'A') || (*p>'z')) return -1; + } +@@ -188,7 +188,7 @@ int afp_parse_url(struct afp_url * url, + return -1; + + } +- if (p==NULL) p=toparse; ++ if (p==NULL) p=(char *)toparse; + + /* Now split on the first / */ + if (sscanf(p,"%[^/]/%[^$]", +diff -up afpfs-ng-0.8.1/lib/did.c.pointer afpfs-ng-0.8.1/lib/did.c +--- afpfs-ng-0.8.1/lib/did.c.pointer 2008-02-18 04:39:17.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/did.c 2011-06-14 17:02:15.000000000 +0200 +@@ -226,7 +226,7 @@ int get_dirid(struct afp_volume * volume + + + /* Go to the end of last known entry */ +- p=path+(p-copy); ++ p=(char *)path+(p-copy); + p2=p; + + while ((p=strchr(p+1,'/'))) { +diff -up afpfs-ng-0.8.1/lib/dsi.c.pointer afpfs-ng-0.8.1/lib/dsi.c +--- afpfs-ng-0.8.1/lib/dsi.c.pointer 2008-02-18 04:53:03.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/dsi.c 2011-06-14 17:02:15.000000000 +0200 +@@ -474,7 +474,7 @@ void dsi_getstatus_reply(struct afp_serv + } + server->flags=ntohs(reply1->flags); + +- p=(void *)((unsigned int) server->incoming_buffer + sizeof(*reply1)); ++ p=(void *)((unsigned long) server->incoming_buffer + sizeof(*reply1)); + p+=copy_from_pascal(server->server_name,p,AFP_SERVER_NAME_LEN)+1; + + /* Now work our way through the variable bits */ +@@ -757,7 +757,7 @@ gotenough: + printf("<<< read() of rest of AFP, %d bytes\n",amount_to_read); + #endif + ret = read(server->fd, (void *) +- (((unsigned int) server->incoming_buffer)+server->data_read), ++ (((unsigned long) server->incoming_buffer)+server->data_read), + amount_to_read); + if (ret<0) return -1; + if (ret==0) { +diff -up afpfs-ng-0.8.1/lib/loop.c.pointer afpfs-ng-0.8.1/lib/loop.c +--- afpfs-ng-0.8.1/lib/loop.c.pointer 2008-02-18 04:40:11.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/loop.c 2011-06-14 17:02:15.000000000 +0200 +@@ -25,7 +25,7 @@ + static unsigned char exit_program=0; + + static pthread_t ending_thread; +-static pthread_t main_thread = NULL; ++static pthread_t main_thread = (pthread_t)NULL; + + static int loop_started=0; + static pthread_cond_t loop_started_condition; +diff -up afpfs-ng-0.8.1/lib/lowlevel.c.pointer afpfs-ng-0.8.1/lib/lowlevel.c +--- afpfs-ng-0.8.1/lib/lowlevel.c.pointer 2008-02-20 02:33:17.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/lowlevel.c 2011-06-14 17:02:15.000000000 +0200 +@@ -582,7 +582,7 @@ int ll_getattr(struct afp_volume * volum + if (volume->server->using_version->av_number>=30) + stbuf->st_mode |= fp.unixprivs.permissions; + else +- set_nonunix_perms(stbuf,&fp); ++ set_nonunix_perms(&stbuf->st_mode,&fp); + + stbuf->st_uid=fp.unixprivs.uid; + stbuf->st_gid=fp.unixprivs.gid; +diff -up afpfs-ng-0.8.1/lib/midlevel.c.pointer afpfs-ng-0.8.1/lib/midlevel.c +--- afpfs-ng-0.8.1/lib/midlevel.c.pointer 2008-03-08 17:08:18.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/midlevel.c 2011-06-14 17:02:15.000000000 +0200 +@@ -713,7 +713,7 @@ int ml_write(struct afp_volume * volume, + { + + int ret,err=0; +- int totalwritten = 0; ++ size_t totalwritten = 0; + uint64_t sizetowrite, ignored; + unsigned char flags = 0; + unsigned int max_packet_size=volume->server->tx_quantum; +diff -up afpfs-ng-0.8.1/lib/proto_attr.c.pointer afpfs-ng-0.8.1/lib/proto_attr.c +--- afpfs-ng-0.8.1/lib/proto_attr.c.pointer 2008-01-30 05:37:58.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/proto_attr.c 2011-06-14 17:02:15.000000000 +0200 +@@ -166,7 +166,7 @@ int afp_getextattr(struct afp_volume * v + copy_path(server,p,pathname,strlen(pathname)); + unixpath_to_afppath(server,p); + p2=p+sizeof_path_header(server)+strlen(pathname); +- if (((unsigned int ) p2) & 0x1) p2++; ++ if (((unsigned long) p2) & 0x1) p2++; + req2=(void *) p2; + + req2->len=htons(namelen); +diff -up afpfs-ng-0.8.1/lib/proto_desktop.c.pointer afpfs-ng-0.8.1/lib/proto_desktop.c +--- afpfs-ng-0.8.1/lib/proto_desktop.c.pointer 2008-02-18 04:44:11.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/proto_desktop.c 2011-06-14 17:02:15.000000000 +0200 +@@ -168,7 +168,7 @@ int afp_getcomment_reply(struct afp_serv + return 0; + } + +-int afp_closedt(struct afp_server * server, unsigned short * refnum) ++int afp_closedt(struct afp_server * server, unsigned short refnum) + { + struct { + struct dsi_header dsi_header __attribute__((__packed__)); +diff -up afpfs-ng-0.8.1/lib/proto_directory.c.pointer afpfs-ng-0.8.1/lib/proto_directory.c +--- afpfs-ng-0.8.1/lib/proto_directory.c.pointer 2008-02-19 03:39:29.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/proto_directory.c 2011-06-14 17:02:15.000000000 +0200 +@@ -248,6 +248,7 @@ int afp_enumerate_reply(struct afp_serve + + return 0; + } ++ + int afp_enumerateext2_reply(struct afp_server *server, char * buf, unsigned int size, void * other) + { + +@@ -266,8 +267,7 @@ int afp_enumerateext2_reply(struct afp_s + char * p = buf + sizeof(*reply); + int i; + char *max=buf+size; +- struct afp_file_info * filebase = NULL, *filecur=NULL, *new_file=NULL; +- void ** x = other; ++ struct afp_file_info * filebase = NULL, *filecur = NULL, *new_file = NULL, **x = (struct afp_file_info **) other; + + if (reply->dsi_header.return_code.error_code) { + return reply->dsi_header.return_code.error_code; +diff -up afpfs-ng-0.8.1/lib/proto_map.c.pointer afpfs-ng-0.8.1/lib/proto_map.c +--- afpfs-ng-0.8.1/lib/proto_map.c.pointer 2008-01-30 05:37:59.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/proto_map.c 2011-06-14 17:02:15.000000000 +0200 +@@ -122,7 +122,7 @@ int afp_mapid_reply(struct afp_server *s + + if (reply->header.return_code.error_code!=kFPNoErr) return -1; + +- copy_from_pascal_two(name,&reply->name,255); ++ copy_from_pascal_two(name,reply->name,255); + + return 0; + } +diff -up afpfs-ng-0.8.1/lib/proto_session.c.pointer afpfs-ng-0.8.1/lib/proto_session.c +--- afpfs-ng-0.8.1/lib/proto_session.c.pointer 2008-02-18 04:46:19.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/proto_session.c 2011-06-14 17:02:15.000000000 +0200 +@@ -39,7 +39,7 @@ int afp_getsessiontoken(struct afp_serve + switch (type) { + case kLoginWithTimeAndID: + case kReconnWithTimeAndID: { +- uint32_t *p = (void *) (((unsigned int) request)+ ++ uint32_t *p = (void *) (((unsigned long) request)+ + sizeof(*request)); + + offset=sizeof(timestamp); +@@ -63,7 +63,7 @@ int afp_getsessiontoken(struct afp_serve + goto error; + } + +- data=(void *) (((unsigned int) request)+sizeof(*request)+offset); ++ data=(void *) (((unsigned long) request)+sizeof(*request)+offset); + request->idlength=htonl(datalen); + request->pad=0; + request->type=htons(type); +@@ -127,7 +127,7 @@ int afp_disconnectoldsession(struct afp_ + if ((request=malloc(sizeof(*request) + AFP_TOKEN_MAX_LEN))==NULL) + return -1; + +- token_data = request + sizeof(*request); ++ token_data = (char *)request + sizeof(*request); + + request->type=htons(type); + +diff -up afpfs-ng-0.8.1/lib/uams.c.pointer afpfs-ng-0.8.1/lib/uams.c +--- afpfs-ng-0.8.1/lib/uams.c.pointer 2008-01-04 04:52:44.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/uams.c 2011-06-14 17:02:15.000000000 +0200 +@@ -180,7 +180,7 @@ static int cleartxt_login(struct afp_ser + goto cleartxt_fail; + + p += copy_to_pascal(p, username) + 1; +- if ((int)p & 0x1) ++ if ((long)p & 0x1) + len--; + else + p++; +@@ -230,7 +230,7 @@ static int cleartxt_passwd(struct afp_se + goto cleartxt_fail; + + p += copy_to_pascal(p, username) + 1; +- if ((int)p & 0x1) ++ if ((long)p & 0x1) + len--; + else + p++; +@@ -580,7 +580,7 @@ static int dhx_login(struct afp_server * + if (ai == NULL) + goto dhx_noctx_fail; + d += copy_to_pascal(ai, username) + 1; +- if (((int)d) % 2) ++ if (((long)d) % 2) + d++; + else + ai_len--; +diff -up afpfs-ng-0.8.1/lib/utils.c.pointer afpfs-ng-0.8.1/lib/utils.c +--- afpfs-ng-0.8.1/lib/utils.c.pointer 2008-02-18 04:53:37.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/utils.c 2011-06-14 17:02:15.000000000 +0200 +@@ -196,7 +196,7 @@ int invalid_filename(struct afp_server * + maxlen=255; + + +- p=filename+1; ++ p=(char *)filename+1; + while ((q=strchr(p,'/'))) { + if (q>p+maxlen) + return 1; diff --git a/tools/android/depends/afpfs-ng/04-boxee1.patch b/tools/android/depends/afpfs-ng/04-boxee1.patch new file mode 100644 index 0000000000..9f3c20f35e --- /dev/null +++ b/tools/android/depends/afpfs-ng/04-boxee1.patch @@ -0,0 +1,25 @@ +--- afpfs-ng-0.8.1/include/afpfs-ng/dsi.h 2008-02-18 04:33:24.000000000 +0100 ++++ afpfs-ng-0.8.1/include/afpfs-ng/dsi.h 2011-08-26 21:33:33.000000000 +0200 +@@ -6,13 +6,15 @@ + + struct dsi_request + { +- unsigned short requestid; +- unsigned char subcommand; +- void * other; +- unsigned char wait; +- pthread_cond_t condition_cond; +- struct dsi_request * next; +- int return_code; ++ unsigned short requestid; ++ unsigned char subcommand; ++ void * other; ++ int wait; ++ int done_waiting; ++ pthread_cond_t waiting_cond; ++ pthread_mutex_t waiting_mutex; ++ struct dsi_request * next; ++ int return_code; + }; + + int dsi_receive(struct afp_server * server, void * data, int size); diff --git a/tools/android/depends/afpfs-ng/05-boxee2.patch b/tools/android/depends/afpfs-ng/05-boxee2.patch new file mode 100644 index 0000000000..50250bc0af --- /dev/null +++ b/tools/android/depends/afpfs-ng/05-boxee2.patch @@ -0,0 +1,89 @@ +--- afpfs-ng-0.8.1/lib/afp.c 2008-03-08 03:44:16.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/afp.c 2011-08-26 21:33:33.000000000 +0200 +@@ -68,7 +68,7 @@ + afp_getsessiontoken_reply,afp_blank_reply, NULL, NULL, + afp_enumerateext2_reply, NULL, NULL, NULL, /*64 - 71 */ + afp_listextattrs_reply, NULL, NULL, NULL, +- afp_blank_reply, NULL, NULL, NULL, /*72 - 79 */ ++ afp_blank_reply, NULL, afp_blank_reply, afp_blank_reply, /*72 - 79 */ + + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +@@ -320,8 +320,16 @@ + + struct dsi_request * p; + struct afp_server *s2; ++ ++ ++ if (s==NULL) ++ goto out; ++ + for (p=s->command_requests;p;p=p->next) { +- pthread_cond_signal(&p->condition_cond); ++ pthread_mutex_lock(&p->waiting_mutex); ++ p->done_waiting=1; ++ pthread_cond_signal(&p->waiting_cond); ++ pthread_mutex_unlock(&p->waiting_mutex); + } + + if (s==server_base) { +@@ -354,7 +362,7 @@ + s->exit_flag = 0; + s->path_encoding=kFPUTF8Name; /* This is a default */ + s->next=NULL; +- s->bufsize=2048; ++ s->bufsize=4096; + s->incoming_buffer=malloc(s->bufsize); + + s->attention_quantum=AFP_DEFAULT_ATTENTION_QUANTUM; +@@ -524,13 +532,14 @@ + kFPVolCreateDateBit|kFPVolIDBit | + kFPVolNameBit; + char new_encoding; ++ int ret; + + if (server->using_version->av_number>=30) + bitmap|= kFPVolNameBit|kFPVolBlockSizeBit; + +- switch (afp_volopen(volume,bitmap, +- (strlen(volume->volpassword)>0) ? volume->volpassword : NULL)) +- { ++ ret = afp_volopen(volume,bitmap, ++ (strlen(volume->volpassword)>0) ? volume->volpassword : NULL); ++ switch(ret){ + case kFPAccessDenied: + *l+=snprintf(mesg,max-*l, + "Incorrect volume password\n"); +@@ -544,6 +553,10 @@ + *l+=snprintf(mesg,max-*l, + "Could not open volume\n"); + goto error; ++ case ETIMEDOUT: ++ *l+=snprintf(mesg,max-*l, ++ "Timed out waiting to open volume\n"); ++ goto error; + } + + /* It is said that if a volume's encoding will be the same +@@ -641,7 +654,6 @@ + add_server(server); + + add_fd_and_signal(server->fd); +- + if (!full) { + return 0; + } +@@ -649,10 +661,13 @@ + /* Get the status, and calculate the transmit time. We use this to + * calculate our rx quantum. */ + gettimeofday(&t1,NULL); ++ + if ((error=dsi_getstatus(server))!=0) + goto error; + gettimeofday(&t2,NULL); + ++ afp_server_identify(server); ++ + if ((t2.tv_sec - t1.tv_sec) > 0) + server->tx_delay= (t2.tv_sec - t1.tv_sec) * 1000; + else diff --git a/tools/android/depends/afpfs-ng/06-boxee3.patch b/tools/android/depends/afpfs-ng/06-boxee3.patch new file mode 100644 index 0000000000..4b7c916da3 --- /dev/null +++ b/tools/android/depends/afpfs-ng/06-boxee3.patch @@ -0,0 +1,141 @@ +--- afpfs-ng-0.8.1/lib/dsi.c 2011-08-26 17:27:16.000000000 +0200 ++++ afpfs-ng-0.8.1/lib/dsi.c 2011-08-26 21:33:33.000000000 +0200 +@@ -64,7 +64,7 @@ + rx.size=0; + dsi_setup_header(server,&header,DSI_DSIGetStatus); + /* We're intentionally ignoring the results */ +- ret=dsi_send(server,(char *) &header,sizeof(struct dsi_header),20, ++ ret=dsi_send(server,(char *) &header,sizeof(struct dsi_header),60, + 0,(void *) &rx); + + free(rx.data); +@@ -197,6 +197,7 @@ + new_request->other=other; + new_request->wait=wait; + new_request->next=NULL; ++ new_request->done_waiting=0; + + pthread_mutex_lock(&server->request_queue_mutex); + if (server->command_requests==NULL) { +@@ -208,7 +209,8 @@ + server->stats.requests_pending++; + pthread_mutex_unlock(&server->request_queue_mutex); + +- pthread_cond_init(&new_request->condition_cond,NULL); ++ pthread_cond_init(&new_request->waiting_cond,NULL); ++ pthread_mutex_init(&new_request->waiting_mutex,NULL); + + if (server->connect_state==SERVER_STATE_DISCONNECTED) { + char mesg[1024]; +@@ -240,16 +242,12 @@ + server->stats.tx_bytes+=size; + pthread_mutex_unlock(&server->send_mutex); + +- int tmpwait=new_request->wait; + #ifdef DEBUG_DSI + printf("=== Waiting for response for %d %s\n", + new_request->requestid, + afp_get_command_name(new_request->subcommand)); + #endif +- if (tmpwait<0) { +- +- pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +- pthread_mutex_lock(&mutex); ++ if (new_request->wait<0) { + + /* Wait forever */ + #ifdef DEBUG_DSI +@@ -258,14 +256,17 @@ + afp_get_command_name(new_request->subcommand)); + #endif + +- rc=pthread_cond_wait( +- &new_request->condition_cond, +- &mutex ); +- pthread_mutex_unlock(&mutex); +- +- } else if (tmpwait>0) { +- pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +- pthread_mutex_lock(&mutex); ++ pthread_mutex_lock(&new_request->waiting_mutex); ++ ++ if (new_request->done_waiting==0) ++ rc=pthread_cond_wait( ++ &new_request->waiting_cond, ++ &new_request->waiting_mutex ); ++ ++ pthread_mutex_unlock(&new_request->waiting_mutex); ++ ++ } else if (new_request->wait>0) { ++ /* wait for new_request->wait seconds */ + + #ifdef DEBUG_DSI + printf("=== Waiting for %d %s, for %ds\n", +@@ -283,13 +284,15 @@ + printf("=== Changing my mind, no longer waiting for %d\n", + new_request->requestid); + #endif +- pthread_mutex_unlock(&mutex); + goto skip; + } +- rc=pthread_cond_timedwait( +- &new_request->condition_cond, +- &mutex,&ts); +- pthread_mutex_unlock(&mutex); ++ pthread_mutex_lock(&new_request->waiting_mutex); ++ if (new_request->done_waiting==0) ++ rc=pthread_cond_timedwait( ++ &new_request->waiting_cond, ++ &new_request->waiting_mutex,&ts); ++ pthread_mutex_unlock(&new_request->waiting_mutex); ++ + if (rc==ETIMEDOUT) { + /* FIXME: should handle this case properly */ + #ifdef DEBUG_DSI +@@ -299,6 +302,7 @@ + goto out; + } + } else { ++ /* Don't wait */ + #ifdef DEBUG_DSI + printf("=== Skipping wait altogether for %d\n",new_request->requestid); + #endif +@@ -474,7 +478,7 @@ + } + server->flags=ntohs(reply1->flags); + +- p=(void *)((unsigned long) server->incoming_buffer + sizeof(*reply1)); ++ p=(void *)((unsigned int) server->incoming_buffer + sizeof(*reply1)); + p+=copy_from_pascal(server->server_name,p,AFP_SERVER_NAME_LEN)+1; + + /* Now work our way through the variable bits */ +@@ -577,6 +581,7 @@ + unsigned char mins=0; + unsigned char checkmessage=0; + ++ memset(mesg,0,AFP_LOGINMESG_LEN); + + /* The logic here's undocumented. If we get an attention packet and + there's no flag, then go check the message. Also, go check the +@@ -757,7 +762,7 @@ + printf("<<< read() of rest of AFP, %d bytes\n",amount_to_read); + #endif + ret = read(server->fd, (void *) +- (((unsigned long) server->incoming_buffer)+server->data_read), ++ (((unsigned int) server->incoming_buffer)+server->data_read), + amount_to_read); + if (ret<0) return -1; + if (ret==0) { +@@ -862,8 +867,11 @@ + #ifdef DEBUG_DSI + printf("<<< Signalling %d, returning %d or %d\n",request->requestid,request->return_code,rc); + #endif ++ pthread_mutex_lock(&request->waiting_mutex); + request->wait=0; +- pthread_cond_signal(&request->condition_cond); ++ request->done_waiting=1; ++ pthread_cond_signal(&request->waiting_cond); ++ pthread_mutex_unlock(&request->waiting_mutex); + } else { + dsi_remove_from_request_queue(server,request); + } diff --git a/tools/android/depends/afpfs-ng/07-boxee4.patch b/tools/android/depends/afpfs-ng/07-boxee4.patch new file mode 100644 index 0000000000..3e09f40dc5 --- /dev/null +++ b/tools/android/depends/afpfs-ng/07-boxee4.patch @@ -0,0 +1,27 @@ +--- afpfs-ng-0.8.1/lib/identify.c 1970-01-01 01:00:00.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/identify.c 2011-08-26 21:33:33.000000000 +0200 +@@ -0,0 +1,24 @@ ++#include <string.h> ++#include <afpfs-ng/afp.h> ++ ++ ++/* ++ * afp_server_identify() ++ * ++ * Identifies a server ++ * ++ * Right now, this only does identification using the machine_type ++ * given in getsrvrinfo, but this could later use mDNS to get ++ * more details. ++ */ ++void afp_server_identify(struct afp_server * s) ++{ ++ if (strcmp(s->machine_type,"Netatalk")==0) ++ s->server_type=AFPFS_SERVER_TYPE_NETATALK; ++ else if (strcmp(s->machine_type,"AirPort")==0) ++ s->server_type=AFPFS_SERVER_TYPE_AIRPORT; ++ else if (strcmp(s->machine_type,"Macintosh")==0) ++ s->server_type=AFPFS_SERVER_TYPE_MACINTOSH; ++ else ++ s->server_type=AFPFS_SERVER_TYPE_UNKNOWN; ++} diff --git a/tools/android/depends/afpfs-ng/08-boxee5.patch b/tools/android/depends/afpfs-ng/08-boxee5.patch new file mode 100644 index 0000000000..253fb05c97 --- /dev/null +++ b/tools/android/depends/afpfs-ng/08-boxee5.patch @@ -0,0 +1,11 @@ +--- afpfs-ng-0.8.1/lib/Makefile.am 2008-02-18 04:34:32.000000000 +0100 ++++ afpfs-ng-0.8.1/lib/Makefile.am 2011-08-26 21:33:33.000000000 +0200 +@@ -4,7 +4,7 @@ + + lib_LTLIBRARIES = libafpclient.la + +-libafpclient_la_SOURCES = afp.c codepage.c did.c dsi.c map_def.c uams.c uams_def.c unicode.c users.c utils.c resource.c log.c client.c server.c connect.c loop.c midlevel.c proto_attr.c proto_desktop.c proto_directory.c proto_files.c proto_fork.c proto_login.c proto_map.c proto_replyblock.c proto_server.c proto_volume.c proto_session.c afp_url.c status.c forklist.c debug.c lowlevel.c ++libafpclient_la_SOURCES = afp.c codepage.c did.c dsi.c map_def.c uams.c uams_def.c unicode.c users.c utils.c resource.c log.c client.c server.c connect.c loop.c midlevel.c proto_attr.c proto_desktop.c proto_directory.c proto_files.c proto_fork.c proto_login.c proto_map.c proto_replyblock.c proto_server.c proto_volume.c proto_session.c afp_url.c status.c forklist.c debug.c lowlevel.c identify.c + + # libafpclient_la_LDFLAGS = -module -avoid-version + diff --git a/tools/android/depends/afpfs-ng/10-fix-errno.patch b/tools/android/depends/afpfs-ng/10-fix-errno.patch new file mode 100644 index 0000000000..ff7ce44bdb --- /dev/null +++ b/tools/android/depends/afpfs-ng/10-fix-errno.patch @@ -0,0 +1,23 @@ +--- afpfs-ng-0.8.1/lib/afp.c 2011-09-04 19:42:42.000000000 +0200 ++++ afpfs-ng-0.8.1/lib/afp.c 2011-09-04 19:39:44.000000000 +0200 +@@ -19,7 +19,6 @@ + #include <sys/time.h> + #include <sys/types.h> + #include <sys/socket.h> +-#include <errno.h> + + #include <afpfs-ng/afp_protocol.h> + #include <afpfs-ng/libafpclient.h> +--- afpfs-ng-0.8.1/lib/afp_url.c 2011-09-04 19:42:42.000000000 +0200 ++++ afpfs-ng-0.8.1/lib/afp_url.c 2011-09-04 19:40:27.000000000 +0200 +@@ -21,7 +21,9 @@ + + static int check_port(char * port) + { +- long long ret = strtol(port,NULL,10); ++ long long ret = 0; ++ errno = 0; ++ ret = strtol(port,NULL,10); + if ((ret<0) || (ret>32767)) return -1; + if (errno) { + printf("port error\n"); diff --git a/tools/android/depends/afpfs-ng/11-fix-stat.patch b/tools/android/depends/afpfs-ng/11-fix-stat.patch new file mode 100644 index 0000000000..09e9a35231 --- /dev/null +++ b/tools/android/depends/afpfs-ng/11-fix-stat.patch @@ -0,0 +1,11 @@ +--- afpfs-ng-0.8.1/lib/lowlevel.c 2011-10-01 20:36:55.000000000 +0200 ++++ afpfs-ng-0.8.1/lib/lowlevel.c 2011-10-01 20:46:00.000000000 +0200 +@@ -579,7 +579,7 @@ + return -EIO; + } + +- if (volume->server->using_version->av_number>=30) ++ if (volume->server->using_version->av_number>=30 && fp.unixprivs.permissions != 0) + stbuf->st_mode |= fp.unixprivs.permissions; + else + set_nonunix_perms(&stbuf->st_mode,&fp); diff --git a/tools/android/depends/afpfs-ng/Makefile b/tools/android/depends/afpfs-ng/Makefile new file mode 100644 index 0000000000..ea3d54cc03 --- /dev/null +++ b/tools/android/depends/afpfs-ng/Makefile @@ -0,0 +1,60 @@ +include ../Makefile.include +DEPS= ../Makefile.include 01-gcrypt.patch 02-pointer.patch 04-boxee1.patch \ + 05-boxee2.patch 06-boxee3.patch 07-boxee4.patch \ + 08-boxee5.patch 10-fix-errno.patch 11-fix-stat.patch \ + android.patch fix_afpfs-ng_includes.patch Makefile + +# lib name, version +LIBNAME=afpfs-ng +VERSION=0.8.1 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.bz2 + +# configuration settings +export PATH:=$(TOOLCHAIN)/bin:$(PATH) +export LIBS=-liconv +CONFIGURE=./configure --prefix=$(PREFIX) --host=$(HOST) \ + --disable-fuse ac_cv_func_malloc_0_nonnull=yes + +LIBDYLIB=$(PLATFORM)/lib/.libs/libafpclient.so.0.0.0 + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 <../fix_afpfs-ng_includes.patch + cd $(PLATFORM); patch -p1 <../01-gcrypt.patch + cd $(PLATFORM); patch -p1 <../02-pointer.patch + cd $(PLATFORM); patch -p1 <../04-boxee1.patch + cd $(PLATFORM); patch -p1 <../05-boxee2.patch + cd $(PLATFORM); patch -p1 <../06-boxee3.patch + cd $(PLATFORM); patch -p1 <../07-boxee4.patch + cd $(PLATFORM); patch -p1 <../08-boxee5.patch + cd $(PLATFORM); patch -p1 <../10-fix-errno.patch + cd $(PLATFORM); patch -p1 <../11-fix-stat.patch + cd $(PLATFORM); patch -p0 < ../android.patch + cd $(PLATFORM); $(AUTORECONF) -vif + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -j 1 -C $(PLATFORM)/lib + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM)/lib install + $(MAKE) -C $(PLATFORM)/include install + rm -f $(PREFIX)/lib/libafpclient.la $(PREFIX)/lib/libafpclient.so $(PREFIX)/lib/libafpclient.so.0 + mv -f $(PREFIX)/lib/libafpclient.so.0.0.0 $(PREFIX)/lib/libafpclient.so + $(RPL) -e "libafpclient.so.0" "libafpclient.so\x00\x00" $(PREFIX)/lib/libafpclient.so + -$(READELF) --dynamic $(PREFIX)/lib/libafpclient.so | grep ibrary + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/afpfs-ng/android.patch b/tools/android/depends/afpfs-ng/android.patch new file mode 100644 index 0000000000..b8acfeca5f --- /dev/null +++ b/tools/android/depends/afpfs-ng/android.patch @@ -0,0 +1,64 @@ +--- include/afpfs-ng/afp.h 2012-06-03 22:47:49.014348648 -0400 ++++ include/afpfs-ng/afp.h 2012-06-03 22:46:28.924348698 -0400 +@@ -5,7 +5,13 @@ + #include <arpa/inet.h> + #include <pthread.h> + #include <netdb.h> ++#ifndef ANDROID + #include <sys/statvfs.h> ++#else ++#include <sys/vfs.h> ++#define statvfs statfs ++#define fstatvfs fstatfs ++#endif + #include <pwd.h> + #include <afpfs-ng/afp_protocol.h> + #include <afpfs-ng/libafpclient.h> +--- lib/midlevel.c 2012-06-03 22:47:49.014348648 -0400 ++++ lib/midlevel.c 2012-06-03 22:46:28.924348698 -0400 +@@ -1388,10 +1388,12 @@ + stat->f_frsize=0; + stat->f_files=0; + stat->f_ffree=0; ++#ifndef ANDROID + stat->f_favail=0; + stat->f_fsid=0; + stat->f_flag=0; + stat->f_namemax=255; ++#endif + return 0; + + } +--- lib/lowlevel.c 2012-06-03 22:47:49.054348648 -0400 ++++ lib/lowlevel.c 2012-06-03 22:46:28.914348698 -0400 +@@ -612,7 +612,7 @@ + modification_date=fp.modification_date; + } + +-#ifdef __linux__ ++#if defined(__linux__) && !defined(ANDROID) + stbuf->st_ctim.tv_sec=creation_date; + stbuf->st_mtim.tv_sec=modification_date; + #else +--- lib/dsi.c 2012-06-03 23:24:15.454347269 -0400 ++++ lib/dsi.c 2012-06-03 23:25:01.634347240 -0400 +@@ -610,7 +610,7 @@ + afp_getsrvrmsg(server,AFPMESG_SERVER, + ((server->using_version->av_number>=30)?1:0), + DSI_DEFAULT_TIMEOUT,mesg); +- if(bcmp(mesg,"The server is going down for maintenance.",41)==0) ++ if(memcmp(mesg,"The server is going down for maintenance.",41)==0) + shutdown=1; + } + +--- lib/afp.c 2012-06-03 23:24:15.474347269 -0400 ++++ lib/afp.c 2012-06-03 23:25:12.464347233 -0400 +@@ -205,7 +205,7 @@ + { + struct afp_server *s; + for (s=server_base;s;s=s->next) { +- if (bcmp(&s->address,address,sizeof(struct sockaddr_in))==0) ++ if (memcmp(&s->address,address,sizeof(struct sockaddr_in))==0) + return s; + } + return NULL; diff --git a/tools/android/depends/afpfs-ng/fix_afpfs-ng_includes.patch b/tools/android/depends/afpfs-ng/fix_afpfs-ng_includes.patch new file mode 100644 index 0000000000..f507a485ef --- /dev/null +++ b/tools/android/depends/afpfs-ng/fix_afpfs-ng_includes.patch @@ -0,0 +1,3082 @@ +diff -Naur afpfs-ng-0.8.1/cmdline/cmdline_afp.c afpfs-ng-0.8.1.patch/cmdline/cmdline_afp.c +--- afpfs-ng-0.8.1/cmdline/cmdline_afp.c 2008-02-19 02:54:19.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/cmdline/cmdline_afp.c 2011-09-10 12:13:50.102124369 +0200 +@@ -3,9 +3,9 @@ + + */ + +-#include "afp.h" +-#include "midlevel.h" +-#include "map_def.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/midlevel.h" ++#include "afpfs-ng/map_def.h" + + #include <string.h> + #include <stdio.h> +diff -Naur afpfs-ng-0.8.1/cmdline/cmdline_testafp.c afpfs-ng-0.8.1.patch/cmdline/cmdline_testafp.c +--- afpfs-ng-0.8.1/cmdline/cmdline_testafp.c 2008-03-04 21:16:50.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/cmdline/cmdline_testafp.c 2011-09-10 12:13:50.102124369 +0200 +@@ -3,8 +3,8 @@ + + */ + +-#include "afp.h" +-#include "midlevel.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/midlevel.h" + + #include "cmdline_main.h" + +diff -Naur afpfs-ng-0.8.1/cmdline/getstatus.c afpfs-ng-0.8.1.patch/cmdline/getstatus.c +--- afpfs-ng-0.8.1/cmdline/getstatus.c 2008-02-18 04:28:09.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/cmdline/getstatus.c 2011-09-10 12:13:50.109124463 +0200 +@@ -2,7 +2,7 @@ + #include <string.h> + #include <pthread.h> + +-#include "afp.h" ++#include "afpfs-ng/afp.h" + + static int getstatus(char * address_string, unsigned int port) + { +diff -Naur afpfs-ng-0.8.1/configure.ac afpfs-ng-0.8.1.patch/configure.ac +--- afpfs-ng-0.8.1/configure.ac 2008-03-08 17:23:12.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/configure.ac 2011-09-10 12:13:50.109124463 +0200 +@@ -11,6 +11,7 @@ + AC_PROG_CC + AC_PROG_INSTALL + AC_PROG_LIBTOOL ++AM_PROG_CC_C_O + + # Checks for libraries. + # FIXME: Replace `main' with a function in `-lncurses': +@@ -105,7 +106,7 @@ + + + +-AC_CONFIG_FILES([lib/Makefile fuse/Makefile cmdline/Makefile Makefile docs/Makefile]) ++AC_CONFIG_FILES([lib/Makefile fuse/Makefile cmdline/Makefile Makefile include/Makefile include/afpfs-ng/Makefile docs/Makefile]) + + AC_OUTPUT + +diff -Naur afpfs-ng-0.8.1/fuse/client.c afpfs-ng-0.8.1.patch/fuse/client.c +--- afpfs-ng-0.8.1/fuse/client.c 2008-03-08 03:44:16.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/fuse/client.c 2011-09-10 12:13:50.110124477 +0200 +@@ -12,11 +12,11 @@ + #include <grp.h> + + #include "config.h" +-#include <afp.h> ++#include <afpfs-ng/afp.h> + #include "afp_server.h" +-#include "uams_def.h" +-#include "map_def.h" +-#include "libafpclient.h" ++#include "afpfs-ng/uams_def.h" ++#include "afpfs-ng/map_def.h" ++#include "afpfs-ng/libafpclient.h" + + #define default_uam "Cleartxt Passwrd" + +diff -Naur afpfs-ng-0.8.1/fuse/commands.c afpfs-ng-0.8.1.patch/fuse/commands.c +--- afpfs-ng-0.8.1/fuse/commands.c 2008-03-08 17:06:25.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/fuse/commands.c 2011-09-10 12:13:50.110124477 +0200 +@@ -19,15 +19,15 @@ + #include <getopt.h> + #include <signal.h> + +-#include "afp.h" +-#include "dsi.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/dsi.h" + #include "afp_server.h" +-#include "utils.h" ++#include "afpfs-ng/utils.h" + #include "daemon.h" +-#include "uams_def.h" +-#include "codepage.h" +-#include "libafpclient.h" +-#include "map_def.h" ++#include "afpfs-ng/uams_def.h" ++#include "afpfs-ng/codepage.h" ++#include "afpfs-ng/libafpclient.h" ++#include "afpfs-ng/map_def.h" + #include "fuse_int.h" + #include "fuse_error.h" + #include "fuse_internal.h" +diff -Naur afpfs-ng-0.8.1/fuse/daemon.c afpfs-ng-0.8.1.patch/fuse/daemon.c +--- afpfs-ng-0.8.1/fuse/daemon.c 2008-03-04 18:26:05.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/fuse/daemon.c 2011-09-10 12:13:50.110124477 +0200 +@@ -23,11 +23,11 @@ + #include <signal.h> + #include <sys/socket.h> + +-#include "afp.h" ++#include "afpfs-ng/afp.h" + +-#include "dsi.h" ++#include "afpfs-ng/dsi.h" + #include "afp_server.h" +-#include "utils.h" ++#include "afpfs-ng/utils.h" + #include "daemon.h" + #include "commands.h" + +diff -Naur afpfs-ng-0.8.1/fuse/fuse_error.c afpfs-ng-0.8.1.patch/fuse/fuse_error.c +--- afpfs-ng-0.8.1/fuse/fuse_error.c 2008-01-18 05:40:10.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/fuse/fuse_error.c 2011-09-10 12:13:50.111124491 +0200 +@@ -4,7 +4,7 @@ + #include <unistd.h> + #include <string.h> + #include <stdio.h> +-#include "libafpclient.h" ++#include "afpfs-ng/libafpclient.h" + #include "fuse_internal.h" + + #define TMP_FILE "/tmp/fuse_stderr" +diff -Naur afpfs-ng-0.8.1/fuse/fuse_int.c afpfs-ng-0.8.1.patch/fuse/fuse_int.c +--- afpfs-ng-0.8.1/fuse/fuse_int.c 2008-03-02 06:06:24.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/fuse/fuse_int.c 2011-09-10 12:13:50.111124491 +0200 +@@ -18,7 +18,7 @@ + #define FUSE_USE_VERSION 25 + + +-#include "afp.h" ++#include "afpfs-ng/afp.h" + + #include <fuse.h> + #include <stdio.h> +@@ -39,10 +39,10 @@ + #include <pwd.h> + #include <stdarg.h> + +-#include "dsi.h" +-#include "afp_protocol.h" +-#include "codepage.h" +-#include "midlevel.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp_protocol.h" ++#include "afpfs-ng/codepage.h" ++#include "afpfs-ng/midlevel.h" + #include "fuse_error.h" + + /* Uncomment the following line to enable full debugging: */ +diff -Naur afpfs-ng-0.8.1/include/afpfs-ng/afp.h afpfs-ng-0.8.1.patch/include/afpfs-ng/afp.h +--- afpfs-ng-0.8.1/include/afpfs-ng/afp.h 1970-01-01 01:00:00.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/afpfs-ng/afp.h 2011-09-10 12:13:50.112124505 +0200 +@@ -0,0 +1,533 @@ ++ ++#ifndef _AFP_H_ ++#define _AFP_H_ ++ ++#include <arpa/inet.h> ++#include <pthread.h> ++#include <netdb.h> ++#include <sys/statvfs.h> ++#include <pwd.h> ++#include <afpfs-ng/afp_protocol.h> ++#include <afpfs-ng/libafpclient.h> ++#include <sys/types.h> ++#include <sys/stat.h> ++#include <unistd.h> ++#include <netinet/in.h> ++ ++ ++#define AFPFS_VERSION "0.8.1" ++ ++/* This is the maximum AFP version this library supports */ ++#define AFP_MAX_SUPPORTED_VERSION 32 ++ ++/* afp_url is used to pass locations around */ ++struct afp_url { ++ enum {TCPIP,AT} protocol; ++ char username[AFP_MAX_USERNAME_LEN]; ++ char uamname[50]; ++ char password[AFP_MAX_PASSWORD_LEN]; ++ char servername[AFP_SERVER_NAME_UTF8_LEN]; ++ int port; ++ char volumename[AFP_VOLUME_NAME_UTF8_LEN]; ++ char path[AFP_MAX_PATH]; ++ ++ int requested_version; ++ char zone[AFP_ZONE_LEN]; /* Only used for Appletalk */ ++ char volpassword[9];; ++}; ++ ++struct afp_token { ++ unsigned int length; ++ char data[AFP_TOKEN_MAX_LEN]; ++}; ++ ++#define SERVER_MAX_VERSIONS 10 ++#define SERVER_MAX_UAMS 10 ++ ++struct afp_rx_buffer { ++ unsigned int size; ++ unsigned int maxsize; ++ char * data; ++ int errorcode; ++}; ++ ++ ++struct afp_file_info { ++ unsigned short attributes; ++ unsigned int did; ++ unsigned int creation_date; ++ unsigned int modification_date; ++ unsigned int backup_date; ++ unsigned int fileid; ++ unsigned short offspring; ++ char sync; ++ char finderinfo[32]; ++ char name[AFP_MAX_PATH]; ++ char basename[AFP_MAX_PATH]; ++ char translated_name[AFP_MAX_PATH]; ++ struct afp_unixprivs unixprivs; ++ unsigned int accessrights; ++ struct afp_file_info * next; ++ struct afp_file_info * largelist_next; ++ unsigned char isdir; ++ unsigned long long size; ++ unsigned short resourcesize; ++ unsigned int resource; ++ unsigned short forkid; ++ struct afp_icon * icon; ++ int eof; ++}; ++ ++ ++#define VOLUME_EXTRA_FLAGS_VOL_CHMOD_KNOWN 0x1 ++#define VOLUME_EXTRA_FLAGS_VOL_CHMOD_BROKEN 0x2 ++#define VOLUME_EXTRA_FLAGS_SHOW_APPLEDOUBLE 0x4 ++#define VOLUME_EXTRA_FLAGS_VOL_SUPPORTS_UNIX 0x8 ++#define VOLUME_EXTRA_FLAGS_NO_LOCKING 0x10 ++#define VOLUME_EXTRA_FLAGS_IGNORE_UNIXPRIVS 0x20 ++#define VOLUME_EXTRA_FLAGS_READONLY 0x40 ++ ++#define AFP_VOLUME_UNMOUNTED 0 ++#define AFP_VOLUME_MOUNTED 1 ++#define AFP_VOLUME_UNMOUNTING 2 ++ ++struct afp_volume { ++ unsigned short volid; ++ char flags; /* This is from afpGetSrvrParms */ ++ unsigned short attributes; /* This is from VolOpen */ ++ unsigned short signature; /* This is fixed or variable */ ++ unsigned int creation_date; ++ unsigned int modification_date; ++ unsigned int backup_date; ++ struct statvfs stat; ++ unsigned char mounted; ++ char mountpoint[255]; ++ struct afp_server * server; ++ char volume_name[AFP_VOLUME_NAME_LEN]; ++ char volume_name_printable[AFP_VOLUME_NAME_UTF8_LEN]; ++ unsigned short dtrefnum; ++ char volpassword[AFP_VOLPASS_LEN]; ++ unsigned int extra_flags; /* This is an afpfs-ng specific field */ ++ ++ /* Our directory ID cache */ ++ struct did_cache_entry * did_cache_base; ++ pthread_mutex_t did_cache_mutex; ++ ++ /* Our journal of open forks */ ++ struct afp_file_info * open_forks; ++ pthread_mutex_t open_forks_mutex; ++ ++ /* Used to trigger startup */ ++ pthread_cond_t startup_condition_cond; ++ ++ struct { ++ uint64_t hits; ++ uint64_t misses; ++ uint64_t expired; ++ uint64_t force_removed; ++ } did_cache_stats; ++ ++ void * priv; /* This is a private structure for fuse/cmdline, etc */ ++ pthread_t thread; /* This is the per-volume thread */ ++ ++ int mapping; ++ ++}; ++ ++#define SERVER_STATE_CONNECTED 1 ++#define SERVER_STATE_DISCONNECTED 2 ++ ++enum server_type{ ++ AFPFS_SERVER_TYPE_UNKNOWN, ++ AFPFS_SERVER_TYPE_NETATALK, ++ AFPFS_SERVER_TYPE_AIRPORT, ++ AFPFS_SERVER_TYPE_MACINTOSH, ++}; ++ ++#define is_netatalk(x) ( (x)->machine_type == AFPFS_SERVER_TYPE_NETATALK ) ++#define is_airport(x) ( (x)->machine_type == AFPFS_SERVER_TYPE_AIRPORT ) ++#define is_macintosh(x) ( (x)->machine_type == AFPFS_SERVER_TYPE_MACINTOSH ) ++ ++ ++ ++struct afp_versions { ++ char *av_name; ++ int av_number; ++}; ++extern struct afp_versions afp_versions[]; ++ ++struct afp_server { ++ ++ /* Our buffer sizes */ ++ unsigned int tx_quantum; ++ unsigned int rx_quantum; ++ ++ unsigned int tx_delay; ++ ++ /* Connection information */ ++ struct sockaddr_in address; ++ int fd; ++ ++ /* Some stats, for information only */ ++ struct { ++ uint64_t runt_packets; ++ uint64_t incoming_dsi; ++ uint64_t rx_bytes; ++ uint64_t tx_bytes; ++ uint64_t requests_pending; ++ } stats; ++ ++ /* General information */ ++ char server_name[AFP_SERVER_NAME_LEN]; ++ char server_name_utf8[AFP_SERVER_NAME_UTF8_LEN]; ++ char server_name_printable[AFP_SERVER_NAME_UTF8_LEN]; ++ ++ char machine_type[17]; ++ char icon[256]; ++ char signature[16]; ++ unsigned short flags; ++ int connect_state; ++ enum server_type server_type; ++ ++ /* This is the time we connected */ ++ time_t connect_time; ++ ++ /* UAMs */ ++ unsigned int supported_uams; ++ unsigned int using_uam; ++ ++ /* Authentication */ ++ char username[AFP_MAX_USERNAME_LEN]; ++ char password[AFP_MAX_PASSWORD_LEN]; ++ ++ /* Session */ ++ struct afp_token token; ++ char need_resume; ++ ++ /* Versions */ ++ unsigned char requested_version; ++ unsigned char versions[SERVER_MAX_VERSIONS]; ++ struct afp_versions *using_version; ++ ++ /* Volumes */ ++ unsigned char num_volumes; ++ struct afp_volume * volumes; ++ ++ void * dsi; ++ unsigned int exit_flag; ++ ++ /* Our DSI request queue */ ++ pthread_mutex_t requestid_mutex; ++ pthread_mutex_t request_queue_mutex; ++ unsigned short lastrequestid; ++ unsigned short expectedrequestid; ++ struct dsi_request * command_requests; ++ ++ ++ char loginmesg[200]; ++ char servermesg[200]; ++ char path_encoding; ++ ++ /* This is the data for the incoming buffer */ ++ char * incoming_buffer; ++ int data_read; ++ int bufsize; ++ ++ /* And this is for the outgoing queue */ ++ pthread_mutex_t send_mutex; ++ ++ /* This is for user mapping */ ++ struct passwd passwd; ++ unsigned int server_uid, server_gid; ++ int server_gid_valid; ++ ++ struct afp_server *next; ++ ++ /* These are for DSI attention packets */ ++ unsigned int attention_quantum; ++ unsigned int attention_len; ++ char * attention_buffer; ++ ++}; ++ ++struct afp_extattr_info { ++ unsigned int maxsize; ++ unsigned int size; ++ char data[1024]; ++}; ++struct afp_comment { ++ unsigned int maxsize; ++ unsigned int size; ++ char *data; ++}; ++ ++struct afp_icon { ++ unsigned int maxsize; ++ unsigned int size; ++ char *data; ++}; ++ ++#define AFP_DEFAULT_ATTENTION_QUANTUM 1024 ++ ++void afp_unixpriv_to_stat(struct afp_file_info *fp, ++ struct stat *stat); ++ ++int init_uams(void) ; ++ ++unsigned int find_uam_by_name(const char * name); ++char * uam_bitmap_to_string(unsigned int bitmap); ++ ++ ++char * get_uam_names_list(void); ++ ++unsigned int default_uams_mask(void); ++ ++struct afp_volume * find_volume_by_name(struct afp_server * server, ++ const char * volname); ++ ++struct afp_connection_request { ++ unsigned int uam_mask; ++ struct afp_url url; ++}; ++ ++void afp_default_url(struct afp_url *url); ++int afp_parse_url(struct afp_url * url, const char * toparse, int verbose); ++void afp_print_url(struct afp_url * url); ++int afp_url_validate(char * url_string, struct afp_url * valid_url); ++ ++int afp_list_volnames(struct afp_server * server, char * names, int max); ++ ++/* User mapping */ ++int afp_detect_mapping(struct afp_volume * volume); ++ ++/* These are some functions that help with simple status text generation */ ++ ++int afp_status_header(char * text, int * len); ++int afp_status_server(struct afp_server * s,char * text, int * len); ++ ++ ++struct afp_server * afp_server_full_connect(void * priv, struct afp_connection_request * req); ++ ++void * just_end_it_now(void *other); ++void add_fd_and_signal(int fd); ++void loop_disconnect(struct afp_server *s); ++void afp_wait_for_started_loop(void); ++ ++ ++struct afp_versions * pick_version(unsigned char *versions, ++ unsigned char requested) ; ++int pick_uam(unsigned int u1, unsigned int u2); ++ ++int afp_server_login(struct afp_server *server, ++ char * mesg, unsigned int *l, unsigned int max); ++ ++ ++int afp_dologin(struct afp_server *server, ++ unsigned int uam, char * username, char * passwd); ++ ++void afp_free_server(struct afp_server **server); ++ ++struct afp_server * afp_server_init(struct sockaddr_in * address); ++int afp_get_address(void * priv, const char * hostname, unsigned int port, ++ struct sockaddr_in * address); ++ ++ ++int afp_main_loop(int command_fd); ++int afp_main_quick_startup(pthread_t * thread); ++ ++int afp_server_destroy(struct afp_server *s) ; ++int afp_server_reconnect(struct afp_server * s, char * mesg, ++ unsigned int *l, unsigned int max); ++int afp_server_connect(struct afp_server *s, int full); ++ ++struct afp_server * afp_server_complete_connection( ++ void * priv, ++ struct afp_server * server, ++ struct sockaddr_in * address, unsigned char * versions, ++ unsigned int uams, char * username, char * password, ++ unsigned int requested_version, unsigned int uam_mask); ++ ++int afp_connect_volume(struct afp_volume * volume, struct afp_server * server, ++ char * mesg, unsigned int * l, unsigned int max); ++int something_is_mounted(struct afp_server * server); ++ ++int add_cache_entry(struct afp_file_info * file) ; ++struct afp_file_info * get_cache_by_name(char * name); ++struct afp_server * find_server_by_address(struct sockaddr_in * address); ++struct afp_server * find_server_by_signature(char * signature); ++struct afp_server * find_server_by_name(char * name); ++int server_still_valid(struct afp_server * server); ++ ++ ++struct afp_server * get_server_base(void); ++int afp_server_remove(struct afp_server * server); ++ ++int afp_unmount_volume(struct afp_volume * volume); ++int afp_unmount_all_volumes(struct afp_server * server); ++ ++#define volume_is_readonly(x) (((x)->attributes&kReadOnly) || \ ++ ((x)->extra_flags & VOLUME_EXTRA_FLAGS_READONLY)) ++ ++int afp_opendt(struct afp_volume *volume, unsigned short * refnum); ++ ++int afp_closedt(struct afp_server * server, unsigned short * refnum); ++ ++int afp_getcomment(struct afp_volume *volume, unsigned int did, ++ const char * pathname, struct afp_comment * comment); ++ ++int afp_addcomment(struct afp_volume *volume, unsigned int did, ++ const char * pathname, char * comment,uint64_t *size); ++ ++int afp_geticon(struct afp_volume * volume, unsigned int filecreator, ++ unsigned int filetype, unsigned char icontype, ++ unsigned short length, struct afp_icon * icon); ++ ++/* Things you want to do to a server */ ++ ++int afp_getsrvrmsg(struct afp_server *server, unsigned short messagetype,unsigned char utf8, unsigned char block, char * mesg); ++ ++int afp_login(struct afp_server *server, char * uaname, ++ char * userauthinfo, unsigned int userauthinfo_len, ++ struct afp_rx_buffer *rx); ++ ++int afp_changepassword(struct afp_server *server, char * uaname, ++ char * userauthinfo, unsigned int userauthinfo_len, ++ struct afp_rx_buffer *rx); ++ ++int afp_logincont(struct afp_server *server, unsigned short id, ++ char * userauthinfo, unsigned int userauthinfo_len, ++ struct afp_rx_buffer *rx); ++ ++int afp_getsessiontoken(struct afp_server * server, int type, ++ unsigned int timestamp, struct afp_token *outgoing_token, ++ struct afp_token * incoming_token); ++ ++int afp_getsrvrparms(struct afp_server *server); ++ ++int afp_logout(struct afp_server *server,unsigned char wait); ++ ++int afp_mapname(struct afp_server * server, unsigned char subfunction, ++ char * name, unsigned int * id); ++ ++int afp_mapid(struct afp_server * server, unsigned char subfunction, ++ unsigned int id, char *name); ++ ++int afp_getuserinfo(struct afp_server * server, int thisuser, ++ unsigned int userid, unsigned short bitmap, ++ unsigned int *newuid, unsigned int *newgid); ++ ++int afp_zzzzz(struct afp_server *server); ++ ++int afp_volopen(struct afp_volume * volume, ++ unsigned short bitmap, char * password); ++ ++int afp_flush(struct afp_volume * volume); ++ ++int afp_getfiledirparms(struct afp_volume *volume, unsigned int did, ++ unsigned int filebitmap, unsigned int dirbitmap, const char * pathname, ++ struct afp_file_info *fp); ++ ++int afp_enumerate(struct afp_volume * volume, ++ unsigned int dirid, ++ unsigned int filebitmap, unsigned int dirbitmap, ++ unsigned short reqcount, ++ unsigned short startindex, ++ char * path, ++ struct afp_file_info ** file_p); ++ ++int afp_enumerateext2(struct afp_volume * volume, ++ unsigned int dirid, ++ unsigned int filebitmap, unsigned int dirbitmap, ++ unsigned short reqcount, ++ unsigned long startindex, ++ char * path, ++ struct afp_file_info ** file_p); ++ ++int afp_openfork(struct afp_volume * volume, ++ unsigned char forktype, ++ unsigned int dirid, ++ unsigned short accessmode, ++ char * filename, ++ struct afp_file_info *fp); ++ ++int afp_read(struct afp_volume * volume, unsigned short forkid, ++ uint32_t offset, ++ uint32_t count, struct afp_rx_buffer * rx); ++ ++int afp_readext(struct afp_volume * volume, unsigned short forkid, ++ uint64_t offset, ++ uint64_t count, struct afp_rx_buffer * rx); ++ ++int afp_getvolparms(struct afp_volume * volume, unsigned short bitmap); ++ ++ ++int afp_createdir(struct afp_volume * volume, unsigned int dirid, const char * pathname, unsigned int *did_p); ++ ++int afp_delete(struct afp_volume * volume, ++ unsigned int dirid, char * pathname); ++ ++ ++int afp_createfile(struct afp_volume * volume, unsigned char flag, ++ unsigned int did, char * pathname); ++ ++int afp_write(struct afp_volume * volume, unsigned short forkid, ++ uint32_t offset, uint32_t reqcount, ++ char * data, uint32_t * written); ++ ++int afp_writeext(struct afp_volume * volume, unsigned short forkid, ++ uint64_t offset, uint64_t reqcount, ++ char * data, uint64_t * written); ++ ++int afp_flushfork(struct afp_volume * volume, unsigned short forkid); ++ ++int afp_closefork(struct afp_volume * volume, unsigned short forkid); ++int afp_setfileparms(struct afp_volume * volume, ++ unsigned int dirid, const char * pathname, unsigned short bitmap, ++ struct afp_file_info *fp); ++int afp_setfiledirparms(struct afp_volume * volume, ++ unsigned int dirid, const char * pathname, unsigned short bitmap, ++ struct afp_file_info *fp); ++ ++int afp_setdirparms(struct afp_volume * volume, ++ unsigned int dirid, const char * pathname, unsigned short bitmap, ++ struct afp_file_info *fp); ++ ++int afp_volclose(struct afp_volume * volume); ++ ++ ++int afp_setforkparms(struct afp_volume *volume, ++ unsigned short forkid, unsigned short bitmap, unsigned long len); ++ ++int afp_byterangelock(struct afp_volume * volume, ++ unsigned char flag, ++ unsigned short forkid, ++ uint32_t offset, ++ uint32_t len, uint32_t *generated_offset); ++ ++int afp_byterangelockext(struct afp_volume * volume, ++ unsigned char flag, ++ unsigned short forkid, ++ uint64_t offset, ++ uint64_t len, uint64_t *generated_offset); ++ ++int afp_moveandrename(struct afp_volume *volume, ++ unsigned int src_did, ++ unsigned int dst_did, ++ char * src_path, char * dst_path, char *new_name); ++ ++int afp_rename(struct afp_volume * volume, ++ unsigned int dirid, ++ char * path_from, char * path_to); ++ ++int afp_listextattr(struct afp_volume * volume, ++ unsigned int dirid, unsigned short bitmap, ++ char * pathname, struct afp_extattr_info * info); ++ ++/* This is a currently undocumented command */ ++int afp_newcommand76(struct afp_volume * volume, unsigned int dlen, char * data); ++ ++/* For debugging */ ++char * afp_get_command_name(char code); ++ ++ ++#endif +diff -Naur afpfs-ng-0.8.1/include/afpfs-ng/afp_protocol.h afpfs-ng-0.8.1.patch/include/afpfs-ng/afp_protocol.h +--- afpfs-ng-0.8.1/include/afpfs-ng/afp_protocol.h 1970-01-01 01:00:00.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/afpfs-ng/afp_protocol.h 2011-09-10 12:13:50.112124505 +0200 +@@ -0,0 +1,361 @@ ++ ++#ifndef _AFP_PROTOCOL_H_ ++#define _AFP_PROTOCOL_H_ ++ ++#include <sys/types.h> ++#include <stddef.h> ++#include <unistd.h> ++#include <stdint.h> ++ ++/* This file defines constants for the Apple File Protocol. ++ All page references are from "Apple Filing Protocol Programming" version 3.2. ++ except where noted. ++*/ ++ ++#define AFP_SERVER_NAME_LEN 33 ++#define AFP_SERVER_NAME_UTF8_LEN 255 ++#define AFP_VOLUME_NAME_LEN 33 ++#define AFP_VOLUME_NAME_UTF8_LEN 33 ++#define AFP_SIGNATURE_LEN 16 ++#define AFP_MACHINETYPE_LEN 33 ++#define AFP_LOGINMESG_LEN 200 ++#define AFP_VOLPASS_LEN 8 ++#define AFP_HOSTNAME_LEN 255 ++/* This is actually just a guess, and only used for appletalk */ ++#define AFP_ZONE_LEN 255 ++ ++#define AFP_SERVER_ICON_LEN 256 ++ ++ ++#define AFP_MAX_USERNAME_LEN 127 ++#define AFP_MAX_PASSWORD_LEN 127 ++ ++ ++/* This is the maximum length of any UAM string */ ++#define AFP_UAM_LENGTH 24 ++ ++/* This is the maximum length of any path description */ ++#define AFP_MAX_PATH 768 ++ ++#define AFP_VOL_FLAT 1 ++#define AFP_VOL_FIXED 2 ++#define AFP_VOL_VARIABLE 3 ++ ++/* The root directory ID, p.26 */ ++ ++#define AFP_ROOT_DID 2 ++ ++/* Path type constants, p.249 */ ++ ++enum { ++kFPShortName = 1, ++kFPLongName = 2, ++kFPUTF8Name = 3 ++}; ++ ++/* fork types */ ++ ++#define AFP_FORKTYPE_DATA 0x0 ++#define AFP_FORKTYPE_RESOURCE 0x80 ++ ++/* openfork access modes, from p.196 */ ++ ++#define AFP_OPENFORK_ALLOWREAD 1 ++#define AFP_OPENFORK_ALLOWWRITE 2 ++#define AFP_OPENFORK_DENYREAD 0x10 ++#define AFP_OPENFORK_DENYWRITE 0x20 ++ ++/* Message type for getsrvmesg, p. 169*/ ++ ++typedef enum { ++ AFPMESG_LOGIN = 0, ++ AFPMESG_SERVER = 1 ++} afpmessage_t; ++ ++/* Message bitmap for getsrvrmsg */ ++ ++#define AFP_GETSRVRMSG_UTF8 0x2 ++#define AFP_GETSRVRMSG_GETMSG 0x1 ++ ++ ++/* Maximum Version length, p.17 */ ++#define AFP_MAX_VERSION_LENGTH 16 ++ ++/* Maximum length of a token, this is undocumented */ ++#define AFP_TOKEN_MAX_LEN 256 ++ ++/* The maximum size of a file for AFP 2 */ ++#define AFP_MAX_AFP2_FILESIZE (4294967296) ++ ++/* Unix privs, p.240 */ ++ ++struct afp_unixprivs { ++ uint32_t uid __attribute__((__packed__)); ++ uint32_t gid __attribute__((__packed__)); ++ uint32_t permissions __attribute__((__packed__)); ++ uint32_t ua_permissions __attribute__((__packed__)); ++ ++}; ++ ++ ++/* AFP Volume attributes bitmap, p.241 */ ++ ++enum { ++ kReadOnly = 0x01, ++ kHasVolumePassword = 0x02, ++ kSupportsFileIDs = 0x04, ++ kSupportsCatSearch = 0x08, ++ kSupportsBlankAccessPrivs = 0x10, ++ kSupportsUnixPrivs = 0x20, ++ kSupportsUTF8Names = 0x40, ++ kNoNetworkUserIDs = 0x80, ++ kDefaultPrivsFromParent = 0x100, ++ kNoExchangeFiles = 0x200, ++ kSupportsExtAttrs = 0x400, ++ kSupportsACLs=0x800 ++}; ++ ++/* AFP file creation constantes, p.250 */ ++enum { ++kFPSoftCreate = 0, ++kFPHardCreate = 0x80 ++}; ++ ++/* AFP Directory attributes, taken from the protocol guide p.236 */ ++ ++enum { ++ kFPAttributeBit = 0x1, ++ kFPParentDirIDBit = 0x2, ++ kFPCreateDateBit = 0x4, ++ kFPModDateBit = 0x8, ++ kFPBackupDateBit = 0x10, ++ kFPFinderInfoBit = 0x20, ++ kFPLongNameBit = 0x40, ++ kFPShortNameBit = 0x80, ++ kFPNodeIDBit = 0x100, ++ kFPOffspringCountBit = 0x0200, ++ kFPOwnerIDBit = 0x0400, ++ kFPGroupIDBit = 0x0800, ++ kFPAccessRightsBit = 0x1000, ++ kFPProDOSInfoBit = 0x2000, // AFP version 2.2 and earlier ++ kFPUTF8NameBit = 0x2000, // AFP version 3.0 and later ++ kFPUnixPrivsBit = 0x8000 // AFP version 3.0 and later ++}; ++ ++/* AFP File bitmap, p.238. These are the ones not in the AFP Directory ++ attributes map. */ ++ ++enum { ++ kFPDataForkLenBit = 0x0200, ++ kFPRsrcForkLenBit = 0x0400, ++ kFPExtDataForkLenBit = 0x0800, // AFP version 3.0 and later ++ kFPLaunchLimitBit = 0x1000, ++ kFPExtRsrcForkLenBit = 0x4000, // AFP version 3.0 and later ++}; ++ ++/* AFP Extended Attributes Bitmap, p.238 */ ++ ++enum { ++ kXAttrNoFollow = 0x1, ++ kXAttrCreate = 0x2, ++ kXAttrREplace=0x4 ++}; ++ ++ ++/* AFP function codes */ ++enum AFPFunction ++{ ++ afpByteRangeLock = 1, afpCloseVol, afpCloseDir, afpCloseFork, ++ afpCopyFile, afpCreateDir, afpCreateFile, ++ afpDelete, afpEnumerate, afpFlush, afpFlushFork, ++ afpGetForkParms = 14, afpGetSrvrInfo, afpGetSrvrParms, ++ afpGetVolParms, afpLogin, afpLoginCont, afpLogout, afpMapID, ++ afpMapName, afpMoveAndRename, afpOpenVol, afpOpenDir, afpOpenFork, ++ afpRead, afpRename, afpSetDirParms, afpSetFileParms, ++ afpSetForkParms, afpSetVolParms, afpWrite, afpGetFileDirParms, ++ afpSetFileDirParms, afpChangePassword, ++ afpGetUserInfo=37,afpGetSrvrMsg = 38, ++ afpOpenDT=48, ++ afpCloseDT=49, ++ afpGetIcon=51, afpGetIconInfo=52, ++ afpAddComment=56, afpRemoveComment=57, afpGetComment=58, ++ afpByteRangeLockExt=59, afpReadExt, afpWriteExt, ++ afpGetAuthMethods=62, ++ afp_LoginExt=63, ++ afpGetSessionToken=64, ++ afpDisconnectOldSession=65, ++ afpEnumerateExt=66, ++ afpCatSearchExt = 67, ++ afpEnumerateExt2 = 68, afpGetExtAttr, afpSetExtAttr, ++ afpRemoveExtAttr , afpListExtAttrs, ++ afpZzzzz = 122, ++ afpAddIcon=192, ++}; ++ ++/* AFP Volume bitmap. Take from 242 of the protocol guide. */ ++enum { ++ kFPBadVolPre222Bitmap = 0xFe00, ++ kFPBadVolBitmap = 0xF000, ++ kFPVolAttributeBit = 0x1, ++ kFPVolSignatureBit = 0x2, ++ kFPVolCreateDateBit = 0x4, ++ kFPVolModDateBit = 0x8, ++ kFPVolBackupDateBit = 0x10, ++ kFPVolIDBit = 0x20, ++ kFPVolBytesFreeBit = 0x40, ++ kFPVolBytesTotalBit = 0x80, ++ kFPVolNameBit = 0x100, ++ kFPVolExtBytesFreeBit = 0x200, ++ kFPVolExtBytesTotalBit = 0x400, ++ kFPVolBlockSizeBit = 0x800 ++}; ++ ++/* AFP Attention Codes -- 4 bits */ ++#define AFPATTN_SHUTDOWN (1 << 15) /* shutdown/disconnect */ ++#define AFPATTN_CRASH (1 << 14) /* server crashed */ ++#define AFPATTN_MESG (1 << 13) /* server has message */ ++#define AFPATTN_NORECONNECT (1 << 12) /* don't reconnect */ ++/* server notification */ ++#define AFPATTN_NOTIFY (AFPATTN_MESG | AFPATTN_NORECONNECT) ++ ++/* extended bitmap -- 12 bits. volchanged is only useful w/ a server ++ * notification, and time is only useful for shutdown. */ ++#define AFPATTN_VOLCHANGED (1 << 0) /* volume has changed */ ++#define AFPATTN_TIME(x) ((x) & 0xfff) /* time in minutes */ ++ ++#define kFPNoErr 0 ++ ++/* AFP result codes, p252 */ ++#define kASPSessClosed -1072 ++#define kFPAccessDenied -5000 ++#define kFPAuthContinue -5001 ++#define kFPBadUAM -5002 ++#define kFPBadVersNum -5003 ++#define kFPBitmapErr -5004 ++#define kFPCantMove -5005 ++#define kFPDenyConflict -5006 ++#define kFPDirNotEmpty -5007 ++#define kFPDiskFull -5008 ++#define kFPEOFErr -5009 ++#define kFPFileBusy -5010 ++#define kFPFlatVol -5011 ++#define kFPItemNotFound -5012 ++#define kFPLockErr -5013 ++#define kFPMiscErr -5014 ++#define kFPNoMoreLocks -5015 ++#define kFPNoServer -5016 ++#define kFPObjectExists -5017 ++#define kFPObjectNotFound -5018 ++#define kFPParamErr -5019 ++#define kFPRangeNotLocked -5020 ++#define kFPRangeOverlap -5021 ++#define kFPSessClosed -5022 ++#define kFPUserNotAuth -5023 ++#define kFPCallNotSupported -5024 ++#define kFPObjectTypeErr -5025 ++#define kFPTooManyFilesOpen -5026 ++#define kFPServerGoingDown -5027 ++#define kFPCantRename -5028 ++#define kFPDirNotFound -5029 ++#define kFPIconTypeError -5030 ++#define kFPVolLocked -5031 ++#define kFPObjectLocked -5032 ++#define kFPContainsSharedErr -5033 ++#define kFPIDNotFound -5034 ++#define kFPIDExists -5035 ++#define kFPDiffVolErr -5036 ++#define kFPCatalogChanged -5037 ++#define kFPSameObjectErr -5038 ++#define kFPBadIDErr -5039 ++#define kFPPwdSameErr -5040 ++#define kFPPwdTooShortErr -5041 ++#define kFPPwdExpiredErr -5042 ++#define kFPInsideSharedErr -5043 ++#define kFPInsideTrashErr -5044 ++#define kFPPwdNeedsChangeErr -5045 ++#define kFPPwdPolicyErr -5046 ++#define kFPDiskQuotaExceeded –5047 ++ ++ ++ ++/* These flags determine to lock or unlock in ByteRangeLock(Ext) */ ++ ++enum { ++ByteRangeLock_Lock = 0, ++ByteRangeLock_Unlock = 1 ++}; ++ ++/* These flags are used in volopen and getsrvrparm replies, p.171 */ ++ ++#define HasConfigInfo 0x1 ++#define HasPassword 0x80 ++ ++/* These are the subfunction for kFPMapID, as per p.248 */ ++ ++enum { ++kUserIDToName = 1, ++kGroupIDToName = 2, ++kUserIDToUTF8Name = 3, ++kGroupIDToUTF8Name = 4, ++kUserUUIDToUTF8Name = 5, ++kGroupUUIDToUTF8Name = 6 ++}; ++ ++ ++/* These are the subfunction flags described in the FPMapName command, p.286. ++ Note that this is different than what's described on p. 186. */ ++ ++enum { ++kNameToUserID = 1, ++kNameToGroupID = 2, ++kUTF8NameToUserID = 3, ++kUTF8NameToGroupID = 4, ++kUTF8NameToUserUUID = 5, ++kUTF8NameToGroupUUID = 6 ++}; ++ ++/* These are bits for FPGetUserInfo, p.173. */ ++#define kFPGetUserInfo_USER_ID 1 ++#define kFPGetUserInfo_PRI_GROUPID 2 ++ ++/* Flags for the replies of GetSrvrInfo and DSI GetStatus, p.240 */ ++ ++enum { ++ kSupportsCopyfile = 0x01, ++ kSupportsChgPwd = 0x02, ++ kDontAllowSavePwd = 0x04, ++ kSupportsSrvrMsg = 0x08, ++ kSrvrSig = 0x10, ++ kSupportsTCP = 0x20, ++ kSupportsSrvrNotify = 0x40, ++ kSupportsReconnect = 0x80, ++ kSupportsDirServices = 0x100, ++ kSupportsUTF8SrvrName = 0x200, ++ kSupportsUUIDs = 0x400, ++ kSupportsSuperClient = 0x8000 ++}; ++ ++ ++/* p.247 */ ++ ++enum { ++ kLoginWithoutID = 0, ++ kLoginWithID = 1, ++ kReconnWithID = 2, ++ kLoginWithTimeAndID = 3, ++ kReconnWithTimeAndID = 4, ++ kRecon1Login = 5, ++ kRecon1ReconnectLogin = 6, ++ kRecon1Refresh = 7, kGetKerberosSessionKey = 8 ++}; ++ ++ ++#define AFP_CHMOD_ALLOWED_BITS_22 \ ++ (S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP |S_IROTH | S_IWOTH | S_IFREG ) ++ ++ ++#endif ++ ++ ++ ++ +diff -Naur afpfs-ng-0.8.1/include/afpfs-ng/codepage.h afpfs-ng-0.8.1.patch/include/afpfs-ng/codepage.h +--- afpfs-ng-0.8.1/include/afpfs-ng/codepage.h 1970-01-01 01:00:00.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/afpfs-ng/codepage.h 2011-09-10 12:13:50.113124518 +0200 +@@ -0,0 +1,11 @@ ++#ifndef __CODE_PAGE_H_ ++#define __CODE_PAGE_H_ ++int convert_utf8dec_to_utf8pre(const char *src, int src_len, ++ char * dest, int dest_len); ++int convert_utf8pre_to_utf8dec(const char * src, int src_len, ++ char * dest, int dest_len); ++int convert_path_to_unix(char encoding, char * dest, ++ char * src, int dest_len); ++int convert_path_to_afp(char encoding, char * dest, ++ char * src, int dest_len); ++#endif +diff -Naur afpfs-ng-0.8.1/include/afpfs-ng/dsi.h afpfs-ng-0.8.1.patch/include/afpfs-ng/dsi.h +--- afpfs-ng-0.8.1/include/afpfs-ng/dsi.h 1970-01-01 01:00:00.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/afpfs-ng/dsi.h 2011-09-10 12:13:50.115124544 +0200 +@@ -0,0 +1,33 @@ ++ ++#ifndef __DSI_H_ ++#define __DSI_H_ ++ ++#include "afpfs-ng/afp.h" ++ ++struct dsi_request ++{ ++ unsigned short requestid; ++ unsigned char subcommand; ++ void * other; ++ unsigned char wait; ++ pthread_cond_t condition_cond; ++ struct dsi_request * next; ++ int return_code; ++}; ++ ++int dsi_receive(struct afp_server * server, void * data, int size); ++int dsi_getstatus(struct afp_server * server); ++ ++int dsi_opensession(struct afp_server *server); ++ ++int dsi_send(struct afp_server *server, char * msg, int size,int wait,unsigned char subcommand, void ** other); ++struct dsi_session * dsi_create(struct afp_server *server); ++int dsi_restart(struct afp_server *server); ++int dsi_recv(struct afp_server * server); ++ ++#define DSI_BLOCK_TIMEOUT -1 ++#define DSI_DONT_WAIT 0 ++#define DSI_DEFAULT_TIMEOUT 5 ++ ++ ++#endif +diff -Naur afpfs-ng-0.8.1/include/afpfs-ng/libafpclient.h afpfs-ng-0.8.1.patch/include/afpfs-ng/libafpclient.h +--- afpfs-ng-0.8.1/include/afpfs-ng/libafpclient.h 1970-01-01 01:00:00.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/afpfs-ng/libafpclient.h 2011-09-10 12:13:50.115124544 +0200 +@@ -0,0 +1,50 @@ ++ ++#ifndef __CLIENT_H_ ++#define __CLIENT_H_ ++ ++#include <unistd.h> ++#include <syslog.h> ++ ++#define MAX_CLIENT_RESPONSE 2048 ++ ++ ++enum loglevels { ++ AFPFSD, ++}; ++ ++struct afp_server; ++struct afp_volume; ++ ++struct libafpclient { ++ int (*unmount_volume) (struct afp_volume * volume); ++ void (*log_for_client)(void * priv, ++ enum loglevels loglevel, int logtype, const char *message); ++ void (*forced_ending_hook)(void); ++ int (*scan_extra_fds)(int command_fd,fd_set *set, int * max_fd); ++ void (*loop_started)(void); ++} ; ++ ++extern struct libafpclient * libafpclient; ++ ++void libafpclient_register(struct libafpclient * tmpclient); ++ ++ ++void signal_main_thread(void); ++ ++/* These are logging functions */ ++ ++#define MAXLOGSIZE 2048 ++ ++#define LOG_METHOD_SYSLOG 1 ++#define LOG_METHOD_STDOUT 2 ++ ++void set_log_method(int m); ++ ++ ++void log_for_client(void * priv, ++ enum loglevels loglevel, int logtype, char * message,...); ++ ++void stdout_log_for_client(void * priv, ++ enum loglevels loglevel, int logtype, const char *message); ++ ++#endif +diff -Naur afpfs-ng-0.8.1/include/afpfs-ng/Makefile.am afpfs-ng-0.8.1.patch/include/afpfs-ng/Makefile.am +--- afpfs-ng-0.8.1/include/afpfs-ng/Makefile.am 1970-01-01 01:00:00.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/afpfs-ng/Makefile.am 2011-09-10 12:13:50.115124544 +0200 +@@ -0,0 +1,6 @@ ++## Process this file with automake to produce Makefile.in ++ ++afpfsincludedir = $(includedir)/afpfs-ng ++ ++afpfsinclude_HEADERS = afp.h afp_protocol.h libafpclient.h ++nodist_afpfsinclude_HEADERS = codepage.h dsi.h map_def.h midlevel.h uams_def.h utils.h +diff -Naur afpfs-ng-0.8.1/include/afpfs-ng/map_def.h afpfs-ng-0.8.1.patch/include/afpfs-ng/map_def.h +--- afpfs-ng-0.8.1/include/afpfs-ng/map_def.h 1970-01-01 01:00:00.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/afpfs-ng/map_def.h 2011-09-10 12:13:50.116124557 +0200 +@@ -0,0 +1,15 @@ ++#ifndef __MAP_H_ ++#define __MAP_H_ ++ ++#include "afpfs-ng/afp.h" ++ ++#define AFP_MAPPING_UNKNOWN 0 ++#define AFP_MAPPING_COMMON 1 ++#define AFP_MAPPING_LOGINIDS 2 ++#define AFP_MAPPING_NAME 3 ++ ++unsigned int map_string_to_num(char * name); ++char * get_mapping_name(struct afp_volume * volume); ++ ++ ++#endif +diff -Naur afpfs-ng-0.8.1/include/afpfs-ng/midlevel.h afpfs-ng-0.8.1.patch/include/afpfs-ng/midlevel.h +--- afpfs-ng-0.8.1/include/afpfs-ng/midlevel.h 1970-01-01 01:00:00.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/afpfs-ng/midlevel.h 2011-09-10 12:13:50.116124557 +0200 +@@ -0,0 +1,64 @@ ++#ifndef __MIDLEVEL_H_ ++#define __MIDLEVEL_H_ ++ ++#include <utime.h> ++#include "afpfs-ng/afp.h" ++ ++int ml_open(struct afp_volume * volume, const char *path, int flags, ++ struct afp_file_info **newfp); ++ ++int ml_creat(struct afp_volume * volume, const char *path,mode_t mode); ++ ++int ml_readdir(struct afp_volume * volume, ++ const char *path, ++ struct afp_file_info **base); ++ ++int ml_read(struct afp_volume * volume, const char *path, ++ char *buf, size_t size, off_t offset, ++ struct afp_file_info *fp, int * eof); ++ ++int ml_chmod(struct afp_volume * vol, const char * path, mode_t mode); ++ ++int ml_unlink(struct afp_volume * vol, const char *path); ++ ++int ml_mkdir(struct afp_volume * vol, const char * path, mode_t mode); ++ ++int ml_close(struct afp_volume * volume, const char * path, ++ struct afp_file_info * fp); ++ ++int ml_getattr(struct afp_volume * volume, const char *path, ++ struct stat *stbuf); ++ ++int ml_write(struct afp_volume * volume, const char * path, ++ const char *data, size_t size, off_t offset, ++ struct afp_file_info * fp, uid_t uid, ++ gid_t gid); ++ ++int ml_readlink(struct afp_volume * vol, const char * path, ++ char *buf, size_t size); ++ ++int ml_rmdir(struct afp_volume * vol, const char *path); ++ ++int ml_chown(struct afp_volume * vol, const char * path, ++ uid_t uid, gid_t gid); ++ ++int ml_truncate(struct afp_volume * vol, const char * path, off_t offset); ++ ++int ml_utime(struct afp_volume * vol, const char * path, ++ struct utimbuf * timebuf); ++ ++int ml_symlink(struct afp_volume *vol, const char * path1, const char * path2); ++ ++int ml_rename(struct afp_volume * vol, ++ const char * path_from, const char * path_to); ++ ++int ml_statfs(struct afp_volume * vol, const char *path, struct statvfs *stat); ++ ++void afp_ml_filebase_free(struct afp_file_info **filebase); ++ ++int ml_passwd(struct afp_server *server, ++ char * username, char * oldpasswd, char * newpasswd); ++ ++ ++ ++#endif +diff -Naur afpfs-ng-0.8.1/include/afpfs-ng/uams_def.h afpfs-ng-0.8.1.patch/include/afpfs-ng/uams_def.h +--- afpfs-ng-0.8.1/include/afpfs-ng/uams_def.h 1970-01-01 01:00:00.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/afpfs-ng/uams_def.h 2011-09-10 12:13:50.116124557 +0200 +@@ -0,0 +1,16 @@ ++#ifndef __UAM_DEFS_H_ ++#define __UAM_DEFS_H_ ++ ++#define UAM_NOUSERAUTHENT 0x1 ++#define UAM_CLEARTXTPASSWRD 0x2 ++#define UAM_RANDNUMEXCHANGE 0x4 ++#define UAM_2WAYRANDNUM 0x8 ++#define UAM_DHCAST128 0x10 ++#define UAM_CLIENTKRB 0x20 ++#define UAM_DHX2 0x40 ++#define UAM_RECON1 0x80 ++ ++int uam_string_to_bitmap(char * name); ++char * uam_bitmap_to_string(unsigned int bitmap); ++ ++#endif +diff -Naur afpfs-ng-0.8.1/include/afpfs-ng/utils.h afpfs-ng-0.8.1.patch/include/afpfs-ng/utils.h +--- afpfs-ng-0.8.1/include/afpfs-ng/utils.h 1970-01-01 01:00:00.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/afpfs-ng/utils.h 2011-09-10 12:13:50.116124557 +0200 +@@ -0,0 +1,43 @@ ++#ifndef __UTILS_H_ ++#define __UTILS_H_ ++#include <stdio.h> ++ ++#include "afpfs-ng/afp.h" ++ ++#if BYTE_ORDER == BIG_ENDIAN ++#define hton64(x) (x) ++#define ntoh64(x) (x) ++#else /* BYTE_ORDER == BIG_ENDIAN */ ++#define hton64(x) ((u_int64_t) (htonl(((x) >> 32) & 0xffffffffLL)) | \ ++ (u_int64_t) ((htonl(x) & 0xffffffffLL) << 32)) ++#define ntoh64(x) (hton64(x)) ++#endif /* BYTE_ORDER == BIG_ENDIAN */ ++ ++#define min(a,b) (((a)<(b)) ? (a) : (b)) ++#define max(a,b) (((a)>(b)) ? (a) : (b)) ++ ++ ++ ++unsigned char unixpath_to_afppath( ++ struct afp_server * server, ++ char * buf); ++ ++unsigned char sizeof_path_header(struct afp_server * server); ++ ++ ++ ++unsigned char copy_from_pascal(char *dest, char *pascal,unsigned int max_len) ; ++unsigned short copy_from_pascal_two(char *dest, char *pascal,unsigned int max_len); ++ ++unsigned char copy_to_pascal(char *dest, const char *src); ++unsigned short copy_to_pascal_two(char *dest, const char *src); ++ ++void copy_path(struct afp_server * server, char * dest, const char * pathname, unsigned char len); ++ ++ ++char * create_path(struct afp_server * server, char * pathname, unsigned short * len); ++ ++ ++int invalid_filename(struct afp_server * server, const char * filename); ++ ++#endif +diff -Naur afpfs-ng-0.8.1/include/afp.h afpfs-ng-0.8.1.patch/include/afp.h +--- afpfs-ng-0.8.1/include/afp.h 2008-03-08 17:08:18.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/afp.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,533 +0,0 @@ +- +-#ifndef _AFP_H_ +-#define _AFP_H_ +- +-#include <arpa/inet.h> +-#include <pthread.h> +-#include <netdb.h> +-#include <sys/statvfs.h> +-#include <pwd.h> +-#include <afp_protocol.h> +-#include <libafpclient.h> +-#include <sys/types.h> +-#include <sys/stat.h> +-#include <unistd.h> +-#include <netinet/in.h> +- +- +-#define AFPFS_VERSION "0.8.1" +- +-/* This is the maximum AFP version this library supports */ +-#define AFP_MAX_SUPPORTED_VERSION 32 +- +-/* afp_url is used to pass locations around */ +-struct afp_url { +- enum {TCPIP,AT} protocol; +- char username[AFP_MAX_USERNAME_LEN]; +- char uamname[50]; +- char password[AFP_MAX_PASSWORD_LEN]; +- char servername[AFP_SERVER_NAME_UTF8_LEN]; +- int port; +- char volumename[AFP_VOLUME_NAME_UTF8_LEN]; +- char path[AFP_MAX_PATH]; +- +- int requested_version; +- char zone[AFP_ZONE_LEN]; /* Only used for Appletalk */ +- char volpassword[9];; +-}; +- +-struct afp_token { +- unsigned int length; +- char data[AFP_TOKEN_MAX_LEN]; +-}; +- +-#define SERVER_MAX_VERSIONS 10 +-#define SERVER_MAX_UAMS 10 +- +-struct afp_rx_buffer { +- unsigned int size; +- unsigned int maxsize; +- char * data; +- int errorcode; +-}; +- +- +-struct afp_file_info { +- unsigned short attributes; +- unsigned int did; +- unsigned int creation_date; +- unsigned int modification_date; +- unsigned int backup_date; +- unsigned int fileid; +- unsigned short offspring; +- char sync; +- char finderinfo[32]; +- char name[AFP_MAX_PATH]; +- char basename[AFP_MAX_PATH]; +- char translated_name[AFP_MAX_PATH]; +- struct afp_unixprivs unixprivs; +- unsigned int accessrights; +- struct afp_file_info * next; +- struct afp_file_info * largelist_next; +- unsigned char isdir; +- unsigned long long size; +- unsigned short resourcesize; +- unsigned int resource; +- unsigned short forkid; +- struct afp_icon * icon; +- int eof; +-}; +- +- +-#define VOLUME_EXTRA_FLAGS_VOL_CHMOD_KNOWN 0x1 +-#define VOLUME_EXTRA_FLAGS_VOL_CHMOD_BROKEN 0x2 +-#define VOLUME_EXTRA_FLAGS_SHOW_APPLEDOUBLE 0x4 +-#define VOLUME_EXTRA_FLAGS_VOL_SUPPORTS_UNIX 0x8 +-#define VOLUME_EXTRA_FLAGS_NO_LOCKING 0x10 +-#define VOLUME_EXTRA_FLAGS_IGNORE_UNIXPRIVS 0x20 +-#define VOLUME_EXTRA_FLAGS_READONLY 0x40 +- +-#define AFP_VOLUME_UNMOUNTED 0 +-#define AFP_VOLUME_MOUNTED 1 +-#define AFP_VOLUME_UNMOUNTING 2 +- +-struct afp_volume { +- unsigned short volid; +- char flags; /* This is from afpGetSrvrParms */ +- unsigned short attributes; /* This is from VolOpen */ +- unsigned short signature; /* This is fixed or variable */ +- unsigned int creation_date; +- unsigned int modification_date; +- unsigned int backup_date; +- struct statvfs stat; +- unsigned char mounted; +- char mountpoint[255]; +- struct afp_server * server; +- char volume_name[AFP_VOLUME_NAME_LEN]; +- char volume_name_printable[AFP_VOLUME_NAME_UTF8_LEN]; +- unsigned short dtrefnum; +- char volpassword[AFP_VOLPASS_LEN]; +- unsigned int extra_flags; /* This is an afpfs-ng specific field */ +- +- /* Our directory ID cache */ +- struct did_cache_entry * did_cache_base; +- pthread_mutex_t did_cache_mutex; +- +- /* Our journal of open forks */ +- struct afp_file_info * open_forks; +- pthread_mutex_t open_forks_mutex; +- +- /* Used to trigger startup */ +- pthread_cond_t startup_condition_cond; +- +- struct { +- uint64_t hits; +- uint64_t misses; +- uint64_t expired; +- uint64_t force_removed; +- } did_cache_stats; +- +- void * priv; /* This is a private structure for fuse/cmdline, etc */ +- pthread_t thread; /* This is the per-volume thread */ +- +- int mapping; +- +-}; +- +-#define SERVER_STATE_CONNECTED 1 +-#define SERVER_STATE_DISCONNECTED 2 +- +-enum server_type{ +- AFPFS_SERVER_TYPE_UNKNOWN, +- AFPFS_SERVER_TYPE_NETATALK, +- AFPFS_SERVER_TYPE_AIRPORT, +- AFPFS_SERVER_TYPE_MACINTOSH, +-}; +- +-#define is_netatalk(x) ( (x)->machine_type == AFPFS_SERVER_TYPE_NETATALK ) +-#define is_airport(x) ( (x)->machine_type == AFPFS_SERVER_TYPE_AIRPORT ) +-#define is_macintosh(x) ( (x)->machine_type == AFPFS_SERVER_TYPE_MACINTOSH ) +- +- +- +-struct afp_versions { +- char *av_name; +- int av_number; +-}; +-extern struct afp_versions afp_versions[]; +- +-struct afp_server { +- +- /* Our buffer sizes */ +- unsigned int tx_quantum; +- unsigned int rx_quantum; +- +- unsigned int tx_delay; +- +- /* Connection information */ +- struct sockaddr_in address; +- int fd; +- +- /* Some stats, for information only */ +- struct { +- uint64_t runt_packets; +- uint64_t incoming_dsi; +- uint64_t rx_bytes; +- uint64_t tx_bytes; +- uint64_t requests_pending; +- } stats; +- +- /* General information */ +- char server_name[AFP_SERVER_NAME_LEN]; +- char server_name_utf8[AFP_SERVER_NAME_UTF8_LEN]; +- char server_name_printable[AFP_SERVER_NAME_UTF8_LEN]; +- +- char machine_type[17]; +- char icon[256]; +- char signature[16]; +- unsigned short flags; +- int connect_state; +- enum server_type server_type; +- +- /* This is the time we connected */ +- time_t connect_time; +- +- /* UAMs */ +- unsigned int supported_uams; +- unsigned int using_uam; +- +- /* Authentication */ +- char username[AFP_MAX_USERNAME_LEN]; +- char password[AFP_MAX_PASSWORD_LEN]; +- +- /* Session */ +- struct afp_token token; +- char need_resume; +- +- /* Versions */ +- unsigned char requested_version; +- unsigned char versions[SERVER_MAX_VERSIONS]; +- struct afp_versions *using_version; +- +- /* Volumes */ +- unsigned char num_volumes; +- struct afp_volume * volumes; +- +- void * dsi; +- unsigned int exit_flag; +- +- /* Our DSI request queue */ +- pthread_mutex_t requestid_mutex; +- pthread_mutex_t request_queue_mutex; +- unsigned short lastrequestid; +- unsigned short expectedrequestid; +- struct dsi_request * command_requests; +- +- +- char loginmesg[200]; +- char servermesg[200]; +- char path_encoding; +- +- /* This is the data for the incoming buffer */ +- char * incoming_buffer; +- int data_read; +- int bufsize; +- +- /* And this is for the outgoing queue */ +- pthread_mutex_t send_mutex; +- +- /* This is for user mapping */ +- struct passwd passwd; +- unsigned int server_uid, server_gid; +- int server_gid_valid; +- +- struct afp_server *next; +- +- /* These are for DSI attention packets */ +- unsigned int attention_quantum; +- unsigned int attention_len; +- char * attention_buffer; +- +-}; +- +-struct afp_extattr_info { +- unsigned int maxsize; +- unsigned int size; +- char data[1024]; +-}; +-struct afp_comment { +- unsigned int maxsize; +- unsigned int size; +- char *data; +-}; +- +-struct afp_icon { +- unsigned int maxsize; +- unsigned int size; +- char *data; +-}; +- +-#define AFP_DEFAULT_ATTENTION_QUANTUM 1024 +- +-void afp_unixpriv_to_stat(struct afp_file_info *fp, +- struct stat *stat); +- +-int init_uams(void) ; +- +-unsigned int find_uam_by_name(const char * name); +-char * uam_bitmap_to_string(unsigned int bitmap); +- +- +-char * get_uam_names_list(void); +- +-unsigned int default_uams_mask(void); +- +-struct afp_volume * find_volume_by_name(struct afp_server * server, +- const char * volname); +- +-struct afp_connection_request { +- unsigned int uam_mask; +- struct afp_url url; +-}; +- +-void afp_default_url(struct afp_url *url); +-int afp_parse_url(struct afp_url * url, const char * toparse, int verbose); +-void afp_print_url(struct afp_url * url); +-int afp_url_validate(char * url_string, struct afp_url * valid_url); +- +-int afp_list_volnames(struct afp_server * server, char * names, int max); +- +-/* User mapping */ +-int afp_detect_mapping(struct afp_volume * volume); +- +-/* These are some functions that help with simple status text generation */ +- +-int afp_status_header(char * text, int * len); +-int afp_status_server(struct afp_server * s,char * text, int * len); +- +- +-struct afp_server * afp_server_full_connect(void * priv, struct afp_connection_request * req); +- +-void * just_end_it_now(void *other); +-void add_fd_and_signal(int fd); +-void loop_disconnect(struct afp_server *s); +-void afp_wait_for_started_loop(void); +- +- +-struct afp_versions * pick_version(unsigned char *versions, +- unsigned char requested) ; +-int pick_uam(unsigned int u1, unsigned int u2); +- +-int afp_server_login(struct afp_server *server, +- char * mesg, unsigned int *l, unsigned int max); +- +- +-int afp_dologin(struct afp_server *server, +- unsigned int uam, char * username, char * passwd); +- +-void afp_free_server(struct afp_server **server); +- +-struct afp_server * afp_server_init(struct sockaddr_in * address); +-int afp_get_address(void * priv, const char * hostname, unsigned int port, +- struct sockaddr_in * address); +- +- +-int afp_main_loop(int command_fd); +-int afp_main_quick_startup(pthread_t * thread); +- +-int afp_server_destroy(struct afp_server *s) ; +-int afp_server_reconnect(struct afp_server * s, char * mesg, +- unsigned int *l, unsigned int max); +-int afp_server_connect(struct afp_server *s, int full); +- +-struct afp_server * afp_server_complete_connection( +- void * priv, +- struct afp_server * server, +- struct sockaddr_in * address, unsigned char * versions, +- unsigned int uams, char * username, char * password, +- unsigned int requested_version, unsigned int uam_mask); +- +-int afp_connect_volume(struct afp_volume * volume, struct afp_server * server, +- char * mesg, unsigned int * l, unsigned int max); +-int something_is_mounted(struct afp_server * server); +- +-int add_cache_entry(struct afp_file_info * file) ; +-struct afp_file_info * get_cache_by_name(char * name); +-struct afp_server * find_server_by_address(struct sockaddr_in * address); +-struct afp_server * find_server_by_signature(char * signature); +-struct afp_server * find_server_by_name(char * name); +-int server_still_valid(struct afp_server * server); +- +- +-struct afp_server * get_server_base(void); +-int afp_server_remove(struct afp_server * server); +- +-int afp_unmount_volume(struct afp_volume * volume); +-int afp_unmount_all_volumes(struct afp_server * server); +- +-#define volume_is_readonly(x) (((x)->attributes&kReadOnly) || \ +- ((x)->extra_flags & VOLUME_EXTRA_FLAGS_READONLY)) +- +-int afp_opendt(struct afp_volume *volume, unsigned short * refnum); +- +-int afp_closedt(struct afp_server * server, unsigned short * refnum); +- +-int afp_getcomment(struct afp_volume *volume, unsigned int did, +- const char * pathname, struct afp_comment * comment); +- +-int afp_addcomment(struct afp_volume *volume, unsigned int did, +- const char * pathname, char * comment,uint64_t *size); +- +-int afp_geticon(struct afp_volume * volume, unsigned int filecreator, +- unsigned int filetype, unsigned char icontype, +- unsigned short length, struct afp_icon * icon); +- +-/* Things you want to do to a server */ +- +-int afp_getsrvrmsg(struct afp_server *server, unsigned short messagetype,unsigned char utf8, unsigned char block, char * mesg); +- +-int afp_login(struct afp_server *server, char * uaname, +- char * userauthinfo, unsigned int userauthinfo_len, +- struct afp_rx_buffer *rx); +- +-int afp_changepassword(struct afp_server *server, char * uaname, +- char * userauthinfo, unsigned int userauthinfo_len, +- struct afp_rx_buffer *rx); +- +-int afp_logincont(struct afp_server *server, unsigned short id, +- char * userauthinfo, unsigned int userauthinfo_len, +- struct afp_rx_buffer *rx); +- +-int afp_getsessiontoken(struct afp_server * server, int type, +- unsigned int timestamp, struct afp_token *outgoing_token, +- struct afp_token * incoming_token); +- +-int afp_getsrvrparms(struct afp_server *server); +- +-int afp_logout(struct afp_server *server,unsigned char wait); +- +-int afp_mapname(struct afp_server * server, unsigned char subfunction, +- char * name, unsigned int * id); +- +-int afp_mapid(struct afp_server * server, unsigned char subfunction, +- unsigned int id, char *name); +- +-int afp_getuserinfo(struct afp_server * server, int thisuser, +- unsigned int userid, unsigned short bitmap, +- unsigned int *newuid, unsigned int *newgid); +- +-int afp_zzzzz(struct afp_server *server); +- +-int afp_volopen(struct afp_volume * volume, +- unsigned short bitmap, char * password); +- +-int afp_flush(struct afp_volume * volume); +- +-int afp_getfiledirparms(struct afp_volume *volume, unsigned int did, +- unsigned int filebitmap, unsigned int dirbitmap, const char * pathname, +- struct afp_file_info *fp); +- +-int afp_enumerate(struct afp_volume * volume, +- unsigned int dirid, +- unsigned int filebitmap, unsigned int dirbitmap, +- unsigned short reqcount, +- unsigned short startindex, +- char * path, +- struct afp_file_info ** file_p); +- +-int afp_enumerateext2(struct afp_volume * volume, +- unsigned int dirid, +- unsigned int filebitmap, unsigned int dirbitmap, +- unsigned short reqcount, +- unsigned long startindex, +- char * path, +- struct afp_file_info ** file_p); +- +-int afp_openfork(struct afp_volume * volume, +- unsigned char forktype, +- unsigned int dirid, +- unsigned short accessmode, +- char * filename, +- struct afp_file_info *fp); +- +-int afp_read(struct afp_volume * volume, unsigned short forkid, +- uint32_t offset, +- uint32_t count, struct afp_rx_buffer * rx); +- +-int afp_readext(struct afp_volume * volume, unsigned short forkid, +- uint64_t offset, +- uint64_t count, struct afp_rx_buffer * rx); +- +-int afp_getvolparms(struct afp_volume * volume, unsigned short bitmap); +- +- +-int afp_createdir(struct afp_volume * volume, unsigned int dirid, const char * pathname, unsigned int *did_p); +- +-int afp_delete(struct afp_volume * volume, +- unsigned int dirid, char * pathname); +- +- +-int afp_createfile(struct afp_volume * volume, unsigned char flag, +- unsigned int did, char * pathname); +- +-int afp_write(struct afp_volume * volume, unsigned short forkid, +- uint32_t offset, uint32_t reqcount, +- char * data, uint32_t * written); +- +-int afp_writeext(struct afp_volume * volume, unsigned short forkid, +- uint64_t offset, uint64_t reqcount, +- char * data, uint64_t * written); +- +-int afp_flushfork(struct afp_volume * volume, unsigned short forkid); +- +-int afp_closefork(struct afp_volume * volume, unsigned short forkid); +-int afp_setfileparms(struct afp_volume * volume, +- unsigned int dirid, const char * pathname, unsigned short bitmap, +- struct afp_file_info *fp); +-int afp_setfiledirparms(struct afp_volume * volume, +- unsigned int dirid, const char * pathname, unsigned short bitmap, +- struct afp_file_info *fp); +- +-int afp_setdirparms(struct afp_volume * volume, +- unsigned int dirid, const char * pathname, unsigned short bitmap, +- struct afp_file_info *fp); +- +-int afp_volclose(struct afp_volume * volume); +- +- +-int afp_setforkparms(struct afp_volume *volume, +- unsigned short forkid, unsigned short bitmap, unsigned long len); +- +-int afp_byterangelock(struct afp_volume * volume, +- unsigned char flag, +- unsigned short forkid, +- uint32_t offset, +- uint32_t len, uint32_t *generated_offset); +- +-int afp_byterangelockext(struct afp_volume * volume, +- unsigned char flag, +- unsigned short forkid, +- uint64_t offset, +- uint64_t len, uint64_t *generated_offset); +- +-int afp_moveandrename(struct afp_volume *volume, +- unsigned int src_did, +- unsigned int dst_did, +- char * src_path, char * dst_path, char *new_name); +- +-int afp_rename(struct afp_volume * volume, +- unsigned int dirid, +- char * path_from, char * path_to); +- +-int afp_listextattr(struct afp_volume * volume, +- unsigned int dirid, unsigned short bitmap, +- char * pathname, struct afp_extattr_info * info); +- +-/* This is a currently undocumented command */ +-int afp_newcommand76(struct afp_volume * volume, unsigned int dlen, char * data); +- +-/* For debugging */ +-char * afp_get_command_name(char code); +- +- +-#endif +diff -Naur afpfs-ng-0.8.1/include/afp_protocol.h afpfs-ng-0.8.1.patch/include/afp_protocol.h +--- afpfs-ng-0.8.1/include/afp_protocol.h 2008-02-18 04:33:43.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/afp_protocol.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,361 +0,0 @@ +- +-#ifndef _AFP_PROTOCOL_H_ +-#define _AFP_PROTOCOL_H_ +- +-#include <sys/types.h> +-#include <stddef.h> +-#include <unistd.h> +-#include <stdint.h> +- +-/* This file defines constants for the Apple File Protocol. +- All page references are from "Apple Filing Protocol Programming" version 3.2. +- except where noted. +-*/ +- +-#define AFP_SERVER_NAME_LEN 33 +-#define AFP_SERVER_NAME_UTF8_LEN 255 +-#define AFP_VOLUME_NAME_LEN 33 +-#define AFP_VOLUME_NAME_UTF8_LEN 33 +-#define AFP_SIGNATURE_LEN 16 +-#define AFP_MACHINETYPE_LEN 33 +-#define AFP_LOGINMESG_LEN 200 +-#define AFP_VOLPASS_LEN 8 +-#define AFP_HOSTNAME_LEN 255 +-/* This is actually just a guess, and only used for appletalk */ +-#define AFP_ZONE_LEN 255 +- +-#define AFP_SERVER_ICON_LEN 256 +- +- +-#define AFP_MAX_USERNAME_LEN 127 +-#define AFP_MAX_PASSWORD_LEN 127 +- +- +-/* This is the maximum length of any UAM string */ +-#define AFP_UAM_LENGTH 24 +- +-/* This is the maximum length of any path description */ +-#define AFP_MAX_PATH 768 +- +-#define AFP_VOL_FLAT 1 +-#define AFP_VOL_FIXED 2 +-#define AFP_VOL_VARIABLE 3 +- +-/* The root directory ID, p.26 */ +- +-#define AFP_ROOT_DID 2 +- +-/* Path type constants, p.249 */ +- +-enum { +-kFPShortName = 1, +-kFPLongName = 2, +-kFPUTF8Name = 3 +-}; +- +-/* fork types */ +- +-#define AFP_FORKTYPE_DATA 0x0 +-#define AFP_FORKTYPE_RESOURCE 0x80 +- +-/* openfork access modes, from p.196 */ +- +-#define AFP_OPENFORK_ALLOWREAD 1 +-#define AFP_OPENFORK_ALLOWWRITE 2 +-#define AFP_OPENFORK_DENYREAD 0x10 +-#define AFP_OPENFORK_DENYWRITE 0x20 +- +-/* Message type for getsrvmesg, p. 169*/ +- +-typedef enum { +- AFPMESG_LOGIN = 0, +- AFPMESG_SERVER = 1 +-} afpmessage_t; +- +-/* Message bitmap for getsrvrmsg */ +- +-#define AFP_GETSRVRMSG_UTF8 0x2 +-#define AFP_GETSRVRMSG_GETMSG 0x1 +- +- +-/* Maximum Version length, p.17 */ +-#define AFP_MAX_VERSION_LENGTH 16 +- +-/* Maximum length of a token, this is undocumented */ +-#define AFP_TOKEN_MAX_LEN 256 +- +-/* The maximum size of a file for AFP 2 */ +-#define AFP_MAX_AFP2_FILESIZE (4294967296) +- +-/* Unix privs, p.240 */ +- +-struct afp_unixprivs { +- uint32_t uid __attribute__((__packed__)); +- uint32_t gid __attribute__((__packed__)); +- uint32_t permissions __attribute__((__packed__)); +- uint32_t ua_permissions __attribute__((__packed__)); +- +-}; +- +- +-/* AFP Volume attributes bitmap, p.241 */ +- +-enum { +- kReadOnly = 0x01, +- kHasVolumePassword = 0x02, +- kSupportsFileIDs = 0x04, +- kSupportsCatSearch = 0x08, +- kSupportsBlankAccessPrivs = 0x10, +- kSupportsUnixPrivs = 0x20, +- kSupportsUTF8Names = 0x40, +- kNoNetworkUserIDs = 0x80, +- kDefaultPrivsFromParent = 0x100, +- kNoExchangeFiles = 0x200, +- kSupportsExtAttrs = 0x400, +- kSupportsACLs=0x800 +-}; +- +-/* AFP file creation constantes, p.250 */ +-enum { +-kFPSoftCreate = 0, +-kFPHardCreate = 0x80 +-}; +- +-/* AFP Directory attributes, taken from the protocol guide p.236 */ +- +-enum { +- kFPAttributeBit = 0x1, +- kFPParentDirIDBit = 0x2, +- kFPCreateDateBit = 0x4, +- kFPModDateBit = 0x8, +- kFPBackupDateBit = 0x10, +- kFPFinderInfoBit = 0x20, +- kFPLongNameBit = 0x40, +- kFPShortNameBit = 0x80, +- kFPNodeIDBit = 0x100, +- kFPOffspringCountBit = 0x0200, +- kFPOwnerIDBit = 0x0400, +- kFPGroupIDBit = 0x0800, +- kFPAccessRightsBit = 0x1000, +- kFPProDOSInfoBit = 0x2000, // AFP version 2.2 and earlier +- kFPUTF8NameBit = 0x2000, // AFP version 3.0 and later +- kFPUnixPrivsBit = 0x8000 // AFP version 3.0 and later +-}; +- +-/* AFP File bitmap, p.238. These are the ones not in the AFP Directory +- attributes map. */ +- +-enum { +- kFPDataForkLenBit = 0x0200, +- kFPRsrcForkLenBit = 0x0400, +- kFPExtDataForkLenBit = 0x0800, // AFP version 3.0 and later +- kFPLaunchLimitBit = 0x1000, +- kFPExtRsrcForkLenBit = 0x4000, // AFP version 3.0 and later +-}; +- +-/* AFP Extended Attributes Bitmap, p.238 */ +- +-enum { +- kXAttrNoFollow = 0x1, +- kXAttrCreate = 0x2, +- kXAttrREplace=0x4 +-}; +- +- +-/* AFP function codes */ +-enum AFPFunction +-{ +- afpByteRangeLock = 1, afpCloseVol, afpCloseDir, afpCloseFork, +- afpCopyFile, afpCreateDir, afpCreateFile, +- afpDelete, afpEnumerate, afpFlush, afpFlushFork, +- afpGetForkParms = 14, afpGetSrvrInfo, afpGetSrvrParms, +- afpGetVolParms, afpLogin, afpLoginCont, afpLogout, afpMapID, +- afpMapName, afpMoveAndRename, afpOpenVol, afpOpenDir, afpOpenFork, +- afpRead, afpRename, afpSetDirParms, afpSetFileParms, +- afpSetForkParms, afpSetVolParms, afpWrite, afpGetFileDirParms, +- afpSetFileDirParms, afpChangePassword, +- afpGetUserInfo=37,afpGetSrvrMsg = 38, +- afpOpenDT=48, +- afpCloseDT=49, +- afpGetIcon=51, afpGetIconInfo=52, +- afpAddComment=56, afpRemoveComment=57, afpGetComment=58, +- afpByteRangeLockExt=59, afpReadExt, afpWriteExt, +- afpGetAuthMethods=62, +- afp_LoginExt=63, +- afpGetSessionToken=64, +- afpDisconnectOldSession=65, +- afpEnumerateExt=66, +- afpCatSearchExt = 67, +- afpEnumerateExt2 = 68, afpGetExtAttr, afpSetExtAttr, +- afpRemoveExtAttr , afpListExtAttrs, +- afpZzzzz = 122, +- afpAddIcon=192, +-}; +- +-/* AFP Volume bitmap. Take from 242 of the protocol guide. */ +-enum { +- kFPBadVolPre222Bitmap = 0xFe00, +- kFPBadVolBitmap = 0xF000, +- kFPVolAttributeBit = 0x1, +- kFPVolSignatureBit = 0x2, +- kFPVolCreateDateBit = 0x4, +- kFPVolModDateBit = 0x8, +- kFPVolBackupDateBit = 0x10, +- kFPVolIDBit = 0x20, +- kFPVolBytesFreeBit = 0x40, +- kFPVolBytesTotalBit = 0x80, +- kFPVolNameBit = 0x100, +- kFPVolExtBytesFreeBit = 0x200, +- kFPVolExtBytesTotalBit = 0x400, +- kFPVolBlockSizeBit = 0x800 +-}; +- +-/* AFP Attention Codes -- 4 bits */ +-#define AFPATTN_SHUTDOWN (1 << 15) /* shutdown/disconnect */ +-#define AFPATTN_CRASH (1 << 14) /* server crashed */ +-#define AFPATTN_MESG (1 << 13) /* server has message */ +-#define AFPATTN_NORECONNECT (1 << 12) /* don't reconnect */ +-/* server notification */ +-#define AFPATTN_NOTIFY (AFPATTN_MESG | AFPATTN_NORECONNECT) +- +-/* extended bitmap -- 12 bits. volchanged is only useful w/ a server +- * notification, and time is only useful for shutdown. */ +-#define AFPATTN_VOLCHANGED (1 << 0) /* volume has changed */ +-#define AFPATTN_TIME(x) ((x) & 0xfff) /* time in minutes */ +- +-#define kFPNoErr 0 +- +-/* AFP result codes, p252 */ +-#define kASPSessClosed -1072 +-#define kFPAccessDenied -5000 +-#define kFPAuthContinue -5001 +-#define kFPBadUAM -5002 +-#define kFPBadVersNum -5003 +-#define kFPBitmapErr -5004 +-#define kFPCantMove -5005 +-#define kFPDenyConflict -5006 +-#define kFPDirNotEmpty -5007 +-#define kFPDiskFull -5008 +-#define kFPEOFErr -5009 +-#define kFPFileBusy -5010 +-#define kFPFlatVol -5011 +-#define kFPItemNotFound -5012 +-#define kFPLockErr -5013 +-#define kFPMiscErr -5014 +-#define kFPNoMoreLocks -5015 +-#define kFPNoServer -5016 +-#define kFPObjectExists -5017 +-#define kFPObjectNotFound -5018 +-#define kFPParamErr -5019 +-#define kFPRangeNotLocked -5020 +-#define kFPRangeOverlap -5021 +-#define kFPSessClosed -5022 +-#define kFPUserNotAuth -5023 +-#define kFPCallNotSupported -5024 +-#define kFPObjectTypeErr -5025 +-#define kFPTooManyFilesOpen -5026 +-#define kFPServerGoingDown -5027 +-#define kFPCantRename -5028 +-#define kFPDirNotFound -5029 +-#define kFPIconTypeError -5030 +-#define kFPVolLocked -5031 +-#define kFPObjectLocked -5032 +-#define kFPContainsSharedErr -5033 +-#define kFPIDNotFound -5034 +-#define kFPIDExists -5035 +-#define kFPDiffVolErr -5036 +-#define kFPCatalogChanged -5037 +-#define kFPSameObjectErr -5038 +-#define kFPBadIDErr -5039 +-#define kFPPwdSameErr -5040 +-#define kFPPwdTooShortErr -5041 +-#define kFPPwdExpiredErr -5042 +-#define kFPInsideSharedErr -5043 +-#define kFPInsideTrashErr -5044 +-#define kFPPwdNeedsChangeErr -5045 +-#define kFPPwdPolicyErr -5046 +-#define kFPDiskQuotaExceeded –5047 +- +- +- +-/* These flags determine to lock or unlock in ByteRangeLock(Ext) */ +- +-enum { +-ByteRangeLock_Lock = 0, +-ByteRangeLock_Unlock = 1 +-}; +- +-/* These flags are used in volopen and getsrvrparm replies, p.171 */ +- +-#define HasConfigInfo 0x1 +-#define HasPassword 0x80 +- +-/* These are the subfunction for kFPMapID, as per p.248 */ +- +-enum { +-kUserIDToName = 1, +-kGroupIDToName = 2, +-kUserIDToUTF8Name = 3, +-kGroupIDToUTF8Name = 4, +-kUserUUIDToUTF8Name = 5, +-kGroupUUIDToUTF8Name = 6 +-}; +- +- +-/* These are the subfunction flags described in the FPMapName command, p.286. +- Note that this is different than what's described on p. 186. */ +- +-enum { +-kNameToUserID = 1, +-kNameToGroupID = 2, +-kUTF8NameToUserID = 3, +-kUTF8NameToGroupID = 4, +-kUTF8NameToUserUUID = 5, +-kUTF8NameToGroupUUID = 6 +-}; +- +-/* These are bits for FPGetUserInfo, p.173. */ +-#define kFPGetUserInfo_USER_ID 1 +-#define kFPGetUserInfo_PRI_GROUPID 2 +- +-/* Flags for the replies of GetSrvrInfo and DSI GetStatus, p.240 */ +- +-enum { +- kSupportsCopyfile = 0x01, +- kSupportsChgPwd = 0x02, +- kDontAllowSavePwd = 0x04, +- kSupportsSrvrMsg = 0x08, +- kSrvrSig = 0x10, +- kSupportsTCP = 0x20, +- kSupportsSrvrNotify = 0x40, +- kSupportsReconnect = 0x80, +- kSupportsDirServices = 0x100, +- kSupportsUTF8SrvrName = 0x200, +- kSupportsUUIDs = 0x400, +- kSupportsSuperClient = 0x8000 +-}; +- +- +-/* p.247 */ +- +-enum { +- kLoginWithoutID = 0, +- kLoginWithID = 1, +- kReconnWithID = 2, +- kLoginWithTimeAndID = 3, +- kReconnWithTimeAndID = 4, +- kRecon1Login = 5, +- kRecon1ReconnectLogin = 6, +- kRecon1Refresh = 7, kGetKerberosSessionKey = 8 +-}; +- +- +-#define AFP_CHMOD_ALLOWED_BITS_22 \ +- (S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP |S_IROTH | S_IWOTH | S_IFREG ) +- +- +-#endif +- +- +- +- +diff -Naur afpfs-ng-0.8.1/include/codepage.h afpfs-ng-0.8.1.patch/include/codepage.h +--- afpfs-ng-0.8.1/include/codepage.h 2007-09-23 16:21:30.000000000 +0200 ++++ afpfs-ng-0.8.1.patch/include/codepage.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,11 +0,0 @@ +-#ifndef __CODE_PAGE_H_ +-#define __CODE_PAGE_H_ +-int convert_utf8dec_to_utf8pre(const char *src, int src_len, +- char * dest, int dest_len); +-int convert_utf8pre_to_utf8dec(const char * src, int src_len, +- char * dest, int dest_len); +-int convert_path_to_unix(char encoding, char * dest, +- char * src, int dest_len); +-int convert_path_to_afp(char encoding, char * dest, +- char * src, int dest_len); +-#endif +diff -Naur afpfs-ng-0.8.1/include/dsi.h afpfs-ng-0.8.1.patch/include/dsi.h +--- afpfs-ng-0.8.1/include/dsi.h 2008-02-18 04:33:24.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/dsi.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,33 +0,0 @@ +- +-#ifndef __DSI_H_ +-#define __DSI_H_ +- +-#include "afp.h" +- +-struct dsi_request +-{ +- unsigned short requestid; +- unsigned char subcommand; +- void * other; +- unsigned char wait; +- pthread_cond_t condition_cond; +- struct dsi_request * next; +- int return_code; +-}; +- +-int dsi_receive(struct afp_server * server, void * data, int size); +-int dsi_getstatus(struct afp_server * server); +- +-int dsi_opensession(struct afp_server *server); +- +-int dsi_send(struct afp_server *server, char * msg, int size,int wait,unsigned char subcommand, void ** other); +-struct dsi_session * dsi_create(struct afp_server *server); +-int dsi_restart(struct afp_server *server); +-int dsi_recv(struct afp_server * server); +- +-#define DSI_BLOCK_TIMEOUT -1 +-#define DSI_DONT_WAIT 0 +-#define DSI_DEFAULT_TIMEOUT 5 +- +- +-#endif +diff -Naur afpfs-ng-0.8.1/include/libafpclient.h afpfs-ng-0.8.1.patch/include/libafpclient.h +--- afpfs-ng-0.8.1/include/libafpclient.h 2008-01-30 05:37:59.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/libafpclient.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,50 +0,0 @@ +- +-#ifndef __CLIENT_H_ +-#define __CLIENT_H_ +- +-#include <unistd.h> +-#include <syslog.h> +- +-#define MAX_CLIENT_RESPONSE 2048 +- +- +-enum loglevels { +- AFPFSD, +-}; +- +-struct afp_server; +-struct afp_volume; +- +-struct libafpclient { +- int (*unmount_volume) (struct afp_volume * volume); +- void (*log_for_client)(void * priv, +- enum loglevels loglevel, int logtype, const char *message); +- void (*forced_ending_hook)(void); +- int (*scan_extra_fds)(int command_fd,fd_set *set, int * max_fd); +- void (*loop_started)(void); +-} ; +- +-extern struct libafpclient * libafpclient; +- +-void libafpclient_register(struct libafpclient * tmpclient); +- +- +-void signal_main_thread(void); +- +-/* These are logging functions */ +- +-#define MAXLOGSIZE 2048 +- +-#define LOG_METHOD_SYSLOG 1 +-#define LOG_METHOD_STDOUT 2 +- +-void set_log_method(int m); +- +- +-void log_for_client(void * priv, +- enum loglevels loglevel, int logtype, char * message,...); +- +-void stdout_log_for_client(void * priv, +- enum loglevels loglevel, int logtype, const char *message); +- +-#endif +diff -Naur afpfs-ng-0.8.1/include/Makefile.am afpfs-ng-0.8.1.patch/include/Makefile.am +--- afpfs-ng-0.8.1/include/Makefile.am 1970-01-01 01:00:00.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/Makefile.am 2011-09-10 12:13:50.126124692 +0200 +@@ -0,0 +1,3 @@ ++## Process this file with automake to produce Makefile.in ++ ++SUBDIRS = afpfs-ng +diff -Naur afpfs-ng-0.8.1/include/map_def.h afpfs-ng-0.8.1.patch/include/map_def.h +--- afpfs-ng-0.8.1/include/map_def.h 2008-01-17 05:55:46.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/map_def.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,15 +0,0 @@ +-#ifndef __MAP_H_ +-#define __MAP_H_ +- +-#include "afp.h" +- +-#define AFP_MAPPING_UNKNOWN 0 +-#define AFP_MAPPING_COMMON 1 +-#define AFP_MAPPING_LOGINIDS 2 +-#define AFP_MAPPING_NAME 3 +- +-unsigned int map_string_to_num(char * name); +-char * get_mapping_name(struct afp_volume * volume); +- +- +-#endif +diff -Naur afpfs-ng-0.8.1/include/midlevel.h afpfs-ng-0.8.1.patch/include/midlevel.h +--- afpfs-ng-0.8.1/include/midlevel.h 2007-12-24 20:39:25.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/midlevel.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,64 +0,0 @@ +-#ifndef __MIDLEVEL_H_ +-#define __MIDLEVEL_H_ +- +-#include <utime.h> +-#include "afp.h" +- +-int ml_open(struct afp_volume * volume, const char *path, int flags, +- struct afp_file_info **newfp); +- +-int ml_creat(struct afp_volume * volume, const char *path,mode_t mode); +- +-int ml_readdir(struct afp_volume * volume, +- const char *path, +- struct afp_file_info **base); +- +-int ml_read(struct afp_volume * volume, const char *path, +- char *buf, size_t size, off_t offset, +- struct afp_file_info *fp, int * eof); +- +-int ml_chmod(struct afp_volume * vol, const char * path, mode_t mode); +- +-int ml_unlink(struct afp_volume * vol, const char *path); +- +-int ml_mkdir(struct afp_volume * vol, const char * path, mode_t mode); +- +-int ml_close(struct afp_volume * volume, const char * path, +- struct afp_file_info * fp); +- +-int ml_getattr(struct afp_volume * volume, const char *path, +- struct stat *stbuf); +- +-int ml_write(struct afp_volume * volume, const char * path, +- const char *data, size_t size, off_t offset, +- struct afp_file_info * fp, uid_t uid, +- gid_t gid); +- +-int ml_readlink(struct afp_volume * vol, const char * path, +- char *buf, size_t size); +- +-int ml_rmdir(struct afp_volume * vol, const char *path); +- +-int ml_chown(struct afp_volume * vol, const char * path, +- uid_t uid, gid_t gid); +- +-int ml_truncate(struct afp_volume * vol, const char * path, off_t offset); +- +-int ml_utime(struct afp_volume * vol, const char * path, +- struct utimbuf * timebuf); +- +-int ml_symlink(struct afp_volume *vol, const char * path1, const char * path2); +- +-int ml_rename(struct afp_volume * vol, +- const char * path_from, const char * path_to); +- +-int ml_statfs(struct afp_volume * vol, const char *path, struct statvfs *stat); +- +-void afp_ml_filebase_free(struct afp_file_info **filebase); +- +-int ml_passwd(struct afp_server *server, +- char * username, char * oldpasswd, char * newpasswd); +- +- +- +-#endif +diff -Naur afpfs-ng-0.8.1/include/uams_def.h afpfs-ng-0.8.1.patch/include/uams_def.h +--- afpfs-ng-0.8.1/include/uams_def.h 2007-09-07 15:10:51.000000000 +0200 ++++ afpfs-ng-0.8.1.patch/include/uams_def.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,16 +0,0 @@ +-#ifndef __UAM_DEFS_H_ +-#define __UAM_DEFS_H_ +- +-#define UAM_NOUSERAUTHENT 0x1 +-#define UAM_CLEARTXTPASSWRD 0x2 +-#define UAM_RANDNUMEXCHANGE 0x4 +-#define UAM_2WAYRANDNUM 0x8 +-#define UAM_DHCAST128 0x10 +-#define UAM_CLIENTKRB 0x20 +-#define UAM_DHX2 0x40 +-#define UAM_RECON1 0x80 +- +-int uam_string_to_bitmap(char * name); +-char * uam_bitmap_to_string(unsigned int bitmap); +- +-#endif +diff -Naur afpfs-ng-0.8.1/include/utils.h afpfs-ng-0.8.1.patch/include/utils.h +--- afpfs-ng-0.8.1/include/utils.h 2008-02-18 04:33:58.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/include/utils.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,43 +0,0 @@ +-#ifndef __UTILS_H_ +-#define __UTILS_H_ +-#include <stdio.h> +- +-#include "afp.h" +- +-#if BYTE_ORDER == BIG_ENDIAN +-#define hton64(x) (x) +-#define ntoh64(x) (x) +-#else /* BYTE_ORDER == BIG_ENDIAN */ +-#define hton64(x) ((u_int64_t) (htonl(((x) >> 32) & 0xffffffffLL)) | \ +- (u_int64_t) ((htonl(x) & 0xffffffffLL) << 32)) +-#define ntoh64(x) (hton64(x)) +-#endif /* BYTE_ORDER == BIG_ENDIAN */ +- +-#define min(a,b) (((a)<(b)) ? (a) : (b)) +-#define max(a,b) (((a)>(b)) ? (a) : (b)) +- +- +- +-unsigned char unixpath_to_afppath( +- struct afp_server * server, +- char * buf); +- +-unsigned char sizeof_path_header(struct afp_server * server); +- +- +- +-unsigned char copy_from_pascal(char *dest, char *pascal,unsigned int max_len) ; +-unsigned short copy_from_pascal_two(char *dest, char *pascal,unsigned int max_len); +- +-unsigned char copy_to_pascal(char *dest, const char *src); +-unsigned short copy_to_pascal_two(char *dest, const char *src); +- +-void copy_path(struct afp_server * server, char * dest, const char * pathname, unsigned char len); +- +- +-char * create_path(struct afp_server * server, char * pathname, unsigned short * len); +- +- +-int invalid_filename(struct afp_server * server, const char * filename); +- +-#endif +diff -Naur afpfs-ng-0.8.1/lib/afp.c afpfs-ng-0.8.1.patch/lib/afp.c +--- afpfs-ng-0.8.1/lib/afp.c 2008-03-08 03:44:16.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/afp.c 2011-09-10 12:13:50.131124759 +0200 +@@ -9,7 +9,7 @@ + + + +-#include "afp.h" ++#include "afpfs-ng/afp.h" + #include <config.h> + + #include <stdio.h> +@@ -21,17 +21,17 @@ + #include <sys/socket.h> + #include <errno.h> + +-#include "afp_protocol.h" +-#include "libafpclient.h" ++#include "afpfs-ng/afp_protocol.h" ++#include "afpfs-ng/libafpclient.h" + #include "server.h" +-#include "dsi.h" ++#include "afpfs-ng/dsi.h" + #include "dsi_protocol.h" +-#include "utils.h" ++#include "afpfs-ng/utils.h" + #include "afp_replies.h" + #include "afp_internal.h" + #include "did.h" + #include "forklist.h" +-#include "codepage.h" ++#include "afpfs-ng/codepage.h" + + struct afp_versions afp_versions[] = { + { "AFPVersion 1.1", 11 }, +diff -Naur afpfs-ng-0.8.1/lib/afp_internal.h afpfs-ng-0.8.1.patch/lib/afp_internal.h +--- afpfs-ng-0.8.1/lib/afp_internal.h 2007-11-09 05:27:20.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/afp_internal.h 2011-09-10 12:13:50.132124772 +0200 +@@ -1,7 +1,7 @@ + #ifndef _AFP_INTERNAL_H_ + #define _AFP_INTERNAL_H_ + +-#include "afp.h" ++#include "afpfs-ng/afp.h" + + extern struct afp_versions afp_versions[]; + +diff -Naur afpfs-ng-0.8.1/lib/afp_url.c afpfs-ng-0.8.1.patch/lib/afp_url.c +--- afpfs-ng-0.8.1/lib/afp_url.c 2008-03-04 21:16:49.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/afp_url.c 2011-09-10 12:13:50.132124772 +0200 +@@ -3,7 +3,7 @@ + #include <stdio.h> + #include <stdlib.h> + #include <errno.h> +-#include "afp.h" ++#include "afpfs-ng/afp.h" + + void afp_default_url(struct afp_url *url) + { +diff -Naur afpfs-ng-0.8.1/lib/client.c afpfs-ng-0.8.1.patch/lib/client.c +--- afpfs-ng-0.8.1/lib/client.c 2008-02-18 04:36:30.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/client.c 2011-09-10 12:13:50.132124772 +0200 +@@ -1,5 +1,5 @@ +-#include <afp.h> +-#include <libafpclient.h> ++#include <afpfs-ng/afp.h> ++#include <afpfs-ng/libafpclient.h> + + + struct libafpclient * libafpclient = NULL; +diff -Naur afpfs-ng-0.8.1/lib/codepage.c afpfs-ng-0.8.1.patch/lib/codepage.c +--- afpfs-ng-0.8.1/lib/codepage.c 2008-02-18 04:36:54.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/codepage.c 2011-09-10 12:13:50.133124786 +0200 +@@ -14,8 +14,8 @@ + + #include <string.h> + #include <stdlib.h> +-#include "afp_protocol.h" +-#include "utils.h" ++#include "afpfs-ng/afp_protocol.h" ++#include "afpfs-ng/utils.h" + #include "unicode.h" + + int convert_utf8dec_to_utf8pre(const char *src, int src_len, +diff -Naur afpfs-ng-0.8.1/lib/connect.c afpfs-ng-0.8.1.patch/lib/connect.c +--- afpfs-ng-0.8.1/lib/connect.c 2008-02-18 04:38:59.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/connect.c 2011-09-10 12:13:50.133124786 +0200 +@@ -10,13 +10,13 @@ + #include <string.h> + #include <sys/socket.h> + +-#include "afp.h" +-#include "dsi.h" +-#include "utils.h" +-#include "uams_def.h" +-#include "codepage.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/utils.h" ++#include "afpfs-ng/uams_def.h" ++#include "afpfs-ng/codepage.h" + #include "users.h" +-#include "libafpclient.h" ++#include "afpfs-ng/libafpclient.h" + #include "server.h" + + +diff -Naur afpfs-ng-0.8.1/lib/did.c afpfs-ng-0.8.1.patch/lib/did.c +--- afpfs-ng-0.8.1/lib/did.c 2008-02-18 04:39:17.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/did.c 2011-09-10 12:13:50.133124786 +0200 +@@ -9,8 +9,8 @@ + #include <string.h> + #include <stdio.h> + +-#include "afp.h" +-#include "afp_protocol.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/afp_protocol.h" + + #undef DID_CACHE_DISABLE + +diff -Naur afpfs-ng-0.8.1/lib/dsi.c afpfs-ng-0.8.1.patch/lib/dsi.c +--- afpfs-ng-0.8.1/lib/dsi.c 2008-02-18 04:53:03.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/dsi.c 2011-09-10 12:13:50.134124800 +0200 +@@ -19,12 +19,12 @@ + #include <signal.h> + #include <iconv.h> + +-#include "utils.h" +-#include "dsi.h" +-#include "afp.h" +-#include "uams_def.h" ++#include "afpfs-ng/utils.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/uams_def.h" + #include "dsi_protocol.h" +-#include "libafpclient.h" ++#include "afpfs-ng/libafpclient.h" + #include "afp_internal.h" + #include "afp_replies.h" + +diff -Naur afpfs-ng-0.8.1/lib/forklist.c afpfs-ng-0.8.1.patch/lib/forklist.c +--- afpfs-ng-0.8.1/lib/forklist.c 2008-01-17 05:49:16.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/forklist.c 2011-09-10 12:13:50.135124814 +0200 +@@ -10,7 +10,7 @@ + */ + + +-#include "afp.h" ++#include "afpfs-ng/afp.h" + + #include <stdlib.h> + #include <pthread.h> +diff -Naur afpfs-ng-0.8.1/lib/log.c afpfs-ng-0.8.1.patch/lib/log.c +--- afpfs-ng-0.8.1/lib/log.c 2008-01-30 05:37:58.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/log.c 2011-09-10 12:13:50.135124814 +0200 +@@ -3,7 +3,7 @@ + #include <stdarg.h> + #include <string.h> + #include <stdlib.h> +-#include "libafpclient.h" ++#include "afpfs-ng/libafpclient.h" + + void log_for_client(void * priv, + enum loglevels loglevel, int logtype, char *format, ...) { +diff -Naur afpfs-ng-0.8.1/lib/loop.c afpfs-ng-0.8.1.patch/lib/loop.c +--- afpfs-ng-0.8.1/lib/loop.c 2008-02-18 04:40:11.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/loop.c 2011-09-10 12:13:50.135124814 +0200 +@@ -16,9 +16,9 @@ + #include <sys/time.h> + #include <signal.h> + +-#include "afp.h" +-#include "dsi.h" +-#include "utils.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/utils.h" + + #define SIGNAL_TO_USE SIGUSR2 + +diff -Naur afpfs-ng-0.8.1/lib/lowlevel.c afpfs-ng-0.8.1.patch/lib/lowlevel.c +--- afpfs-ng-0.8.1/lib/lowlevel.c 2008-02-20 02:33:17.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/lowlevel.c 2011-09-10 12:13:50.136124828 +0200 +@@ -19,10 +19,10 @@ + #else + #include <fcntl.h> + #endif +-#include "afp.h" +-#include "afp_protocol.h" +-#include "codepage.h" +-#include "utils.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/afp_protocol.h" ++#include "afpfs-ng/codepage.h" ++#include "afpfs-ng/utils.h" + #include "did.h" + #include "users.h" + +diff -Naur afpfs-ng-0.8.1/lib/map_def.c afpfs-ng-0.8.1.patch/lib/map_def.c +--- afpfs-ng-0.8.1/lib/map_def.c 2007-09-07 15:10:59.000000000 +0200 ++++ afpfs-ng-0.8.1.patch/lib/map_def.c 2011-09-10 12:13:50.136124828 +0200 +@@ -1,6 +1,6 @@ + #include <string.h> +-#include "afp.h" +-#include "map_def.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/map_def.h" + + static char *afp_map_strings[] = { + "Unknown", +diff -Naur afpfs-ng-0.8.1/lib/meta.c afpfs-ng-0.8.1.patch/lib/meta.c +--- afpfs-ng-0.8.1/lib/meta.c 2008-01-04 04:52:44.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/meta.c 2011-09-10 12:13:50.137124841 +0200 +@@ -17,10 +17,10 @@ + #include <unistd.h> + #include <sys/time.h> + +-#include "afp.h" +-#include "dsi.h" +-#include "afp_protocol.h" +-#include "utils.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp_protocol.h" ++#include "afpfs-ng/utils.h" + + + int afp_meta_getattr(const char *path, struct stat *stbuf) +diff -Naur afpfs-ng-0.8.1/lib/midlevel.c afpfs-ng-0.8.1.patch/lib/midlevel.c +--- afpfs-ng-0.8.1/lib/midlevel.c 2008-03-08 17:08:18.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/midlevel.c 2011-09-10 12:13:50.160125150 +0200 +@@ -10,7 +10,7 @@ + */ + + +-#include "afp.h" ++#include "afpfs-ng/afp.h" + + #include <sys/stat.h> + #include <string.h> +@@ -28,9 +28,9 @@ + #include "users.h" + #include "did.h" + #include "resource.h" +-#include "utils.h" +-#include "codepage.h" +-#include "midlevel.h" ++#include "afpfs-ng/utils.h" ++#include "afpfs-ng/codepage.h" ++#include "afpfs-ng/midlevel.h" + #include "afp_internal.h" + #include "forklist.h" + #include "uams.h" +diff -Naur afpfs-ng-0.8.1/lib/proto_attr.c afpfs-ng-0.8.1.patch/lib/proto_attr.c +--- afpfs-ng-0.8.1/lib/proto_attr.c 2008-01-30 05:37:58.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/proto_attr.c 2011-09-10 12:13:50.168125257 +0200 +@@ -7,10 +7,10 @@ + + #include <string.h> + #include <stdlib.h> +-#include "dsi.h" +-#include "afp.h" +-#include "utils.h" +-#include "afp_protocol.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" ++#include "afpfs-ng/afp_protocol.h" + #include "dsi_protocol.h" + + /* This is a new command, function 76. There are currently no docs, so this +diff -Naur afpfs-ng-0.8.1/lib/proto_desktop.c afpfs-ng-0.8.1.patch/lib/proto_desktop.c +--- afpfs-ng-0.8.1/lib/proto_desktop.c 2008-02-18 04:44:11.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/proto_desktop.c 2011-09-10 12:13:50.168125257 +0200 +@@ -9,10 +9,10 @@ + #include <string.h> + #include <stdlib.h> + +-#include "dsi.h" +-#include "afp.h" +-#include "utils.h" +-#include "afp_protocol.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" ++#include "afpfs-ng/afp_protocol.h" + #include "dsi_protocol.h" + + /* closedt, addicon, geticoninfo, addappl, removeappl */ +diff -Naur afpfs-ng-0.8.1/lib/proto_directory.c afpfs-ng-0.8.1.patch/lib/proto_directory.c +--- afpfs-ng-0.8.1/lib/proto_directory.c 2008-02-19 03:39:29.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/proto_directory.c 2011-09-10 12:13:50.168125257 +0200 +@@ -9,10 +9,10 @@ + #include <string.h> + #include <stdlib.h> + +-#include "dsi.h" +-#include "afp.h" +-#include "utils.h" +-#include "afp_protocol.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" ++#include "afpfs-ng/afp_protocol.h" + #include "dsi_protocol.h" + #include "afp_replies.h" + +diff -Naur afpfs-ng-0.8.1/lib/proto_files.c afpfs-ng-0.8.1.patch/lib/proto_files.c +--- afpfs-ng-0.8.1/lib/proto_files.c 2008-02-18 04:46:18.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/proto_files.c 2011-09-10 12:13:50.169125270 +0200 +@@ -8,11 +8,11 @@ + + #include <stdlib.h> + #include <string.h> +-#include "dsi.h" +-#include "afp.h" +-#include "utils.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" + #include "dsi_protocol.h" +-#include "afp_protocol.h" ++#include "afpfs-ng/afp_protocol.h" + #include "afp_internal.h" + + /* afp_setfileparms, afp_setdirparms and afpsetfiledirparms are all remarkably +diff -Naur afpfs-ng-0.8.1/lib/proto_fork.c afpfs-ng-0.8.1.patch/lib/proto_fork.c +--- afpfs-ng-0.8.1/lib/proto_fork.c 2008-01-30 05:37:58.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/proto_fork.c 2011-09-10 12:13:50.169125270 +0200 +@@ -9,11 +9,11 @@ + #include <stdlib.h> + #include <string.h> + +-#include "dsi.h" +-#include "afp.h" +-#include "utils.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" + #include "dsi_protocol.h" +-#include "afp_protocol.h" ++#include "afpfs-ng/afp_protocol.h" + + int afp_setforkparms(struct afp_volume * volume, + unsigned short forkid, unsigned short bitmap, unsigned long len) +diff -Naur afpfs-ng-0.8.1/lib/proto_login.c afpfs-ng-0.8.1.patch/lib/proto_login.c +--- afpfs-ng-0.8.1/lib/proto_login.c 2008-01-30 05:37:59.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/proto_login.c 2011-09-10 12:13:50.169125270 +0200 +@@ -10,10 +10,10 @@ + + #include <stdlib.h> + #include <string.h> +-#include "dsi.h" ++#include "afpfs-ng/dsi.h" + #include "dsi_protocol.h" +-#include "afp.h" +-#include "utils.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" + #include "afp_internal.h" + + +diff -Naur afpfs-ng-0.8.1/lib/proto_map.c afpfs-ng-0.8.1.patch/lib/proto_map.c +--- afpfs-ng-0.8.1/lib/proto_map.c 2008-01-30 05:37:59.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/proto_map.c 2011-09-10 12:13:50.170125283 +0200 +@@ -9,11 +9,11 @@ + #include <stdlib.h> + #include <string.h> + +-#include "dsi.h" +-#include "afp.h" +-#include "utils.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" + #include "dsi_protocol.h" +-#include "afp_protocol.h" ++#include "afpfs-ng/afp_protocol.h" + + /* This is used to pass the return values back from afp_getuserinfo_reply() */ + struct uidgid { +diff -Naur afpfs-ng-0.8.1/lib/proto_replyblock.c afpfs-ng-0.8.1.patch/lib/proto_replyblock.c +--- afpfs-ng-0.8.1/lib/proto_replyblock.c 2008-02-18 04:46:19.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/proto_replyblock.c 2011-09-10 12:13:50.170125283 +0200 +@@ -6,9 +6,9 @@ + */ + + #include <string.h> +-#include "dsi.h" +-#include "afp.h" +-#include "utils.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" + #include "afp_internal.h" + + +diff -Naur afpfs-ng-0.8.1/lib/proto_server.c afpfs-ng-0.8.1.patch/lib/proto_server.c +--- afpfs-ng-0.8.1/lib/proto_server.c 2008-02-19 02:56:21.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/proto_server.c 2011-09-10 12:13:50.170125283 +0200 +@@ -7,12 +7,12 @@ + */ + #include <stdlib.h> + #include <string.h> +-#include "dsi.h" +-#include "afp.h" +-#include "utils.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" + #include "dsi_protocol.h" +-#include "afp_protocol.h" +-#include "codepage.h" ++#include "afpfs-ng/afp_protocol.h" ++#include "afpfs-ng/codepage.h" + #include "afp_internal.h" + + int afp_getsrvrparms(struct afp_server *server) +diff -Naur afpfs-ng-0.8.1/lib/proto_session.c afpfs-ng-0.8.1.patch/lib/proto_session.c +--- afpfs-ng-0.8.1/lib/proto_session.c 2008-02-18 04:46:19.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/proto_session.c 2011-09-10 12:13:50.170125283 +0200 +@@ -8,10 +8,10 @@ + */ + #include <stdlib.h> + #include <string.h> +-#include "dsi.h" ++#include "afpfs-ng/dsi.h" + #include "dsi_protocol.h" +-#include "afp.h" +-#include "utils.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" + + int afp_getsessiontoken(struct afp_server * server, int type, + unsigned int timestamp, struct afp_token *outgoing_token, +diff -Naur afpfs-ng-0.8.1/lib/proto_volume.c afpfs-ng-0.8.1.patch/lib/proto_volume.c +--- afpfs-ng-0.8.1/lib/proto_volume.c 2008-02-18 04:47:48.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/proto_volume.c 2011-09-10 12:13:50.171125296 +0200 +@@ -8,13 +8,13 @@ + + #include <string.h> + #include <stdlib.h> +-#include "dsi.h" +-#include "afp.h" +-#include "utils.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" + #include "dsi_protocol.h" +-#include "afp_protocol.h" ++#include "afpfs-ng/afp_protocol.h" + #include "afp_internal.h" +-#include "codepage.h" ++#include "afpfs-ng/codepage.h" + + static int parse_volbitmap_reply(struct afp_server * server, + struct afp_volume * tmpvol, +diff -Naur afpfs-ng-0.8.1/lib/resource.c afpfs-ng-0.8.1.patch/lib/resource.c +--- afpfs-ng-0.8.1/lib/resource.c 2008-02-18 04:46:56.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/resource.c 2011-09-10 12:13:50.171125296 +0200 +@@ -3,11 +3,11 @@ + #include <string.h> + #include <errno.h> + #include <fcntl.h> +-#include "afp.h" ++#include "afpfs-ng/afp.h" + #include "resource.h" + #include "lowlevel.h" + #include "did.h" +-#include "midlevel.h" ++#include "afpfs-ng/midlevel.h" + + #define appledouble ".AppleDouble" + #define finderinfo_string ".finderinfo" +diff -Naur afpfs-ng-0.8.1/lib/server.c afpfs-ng-0.8.1.patch/lib/server.c +--- afpfs-ng-0.8.1/lib/server.c 2008-02-19 02:56:21.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/server.c 2011-09-10 12:13:50.172125310 +0200 +@@ -8,15 +8,15 @@ + #include <string.h> + #include <time.h> + +-#include "afp.h" +-#include "dsi.h" +-#include "utils.h" +-#include "uams_def.h" +-#include "codepage.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/utils.h" ++#include "afpfs-ng/uams_def.h" ++#include "afpfs-ng/codepage.h" + #include "users.h" +-#include "libafpclient.h" ++#include "afpfs-ng/libafpclient.h" + #include "afp_internal.h" +-#include "dsi.h" ++#include "afpfs-ng/dsi.h" + + + struct afp_server * afp_server_complete_connection( +diff -Naur afpfs-ng-0.8.1/lib/status.c afpfs-ng-0.8.1.patch/lib/status.c +--- afpfs-ng-0.8.1/lib/status.c 2008-03-08 17:08:38.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/status.c 2011-09-10 12:13:50.172125310 +0200 +@@ -1,8 +1,8 @@ + #include <string.h> + #include <stdio.h> +-#include "map_def.h" +-#include "dsi.h" +-#include "afp.h" ++#include "afpfs-ng/map_def.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp.h" + + int afp_status_header(char * text, int * len) + { +diff -Naur afpfs-ng-0.8.1/lib/uams.c afpfs-ng-0.8.1.patch/lib/uams.c +--- afpfs-ng-0.8.1/lib/uams.c 2008-01-04 04:52:44.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/uams.c 2011-09-10 12:13:50.173125324 +0200 +@@ -8,10 +8,10 @@ + + #include <string.h> + #include <stdlib.h> +-#include "dsi.h" +-#include "afp.h" +-#include "utils.h" +-#include "uams_def.h" ++#include "afpfs-ng/dsi.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" ++#include "afpfs-ng/uams_def.h" + #include "config.h" + + #ifdef HAVE_LIBGCRYPT +diff -Naur afpfs-ng-0.8.1/lib/users.c afpfs-ng-0.8.1.patch/lib/users.c +--- afpfs-ng-0.8.1/lib/users.c 2008-02-18 04:48:56.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/users.c 2011-09-10 12:13:50.174125338 +0200 +@@ -3,8 +3,8 @@ + #include <grp.h> + #include <string.h> + +-#include "afp.h" +-#include "map_def.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/map_def.h" + + /* How mapping works + * +diff -Naur afpfs-ng-0.8.1/lib/utils.c afpfs-ng-0.8.1.patch/lib/utils.c +--- afpfs-ng-0.8.1/lib/utils.c 2008-02-18 04:53:37.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/lib/utils.c 2011-09-10 12:13:50.174125338 +0200 +@@ -8,10 +8,10 @@ + #include <stdio.h> + #include <string.h> + #include <stdlib.h> +-#include "afp.h" +-#include "utils.h" ++#include "afpfs-ng/afp.h" ++#include "afpfs-ng/utils.h" + #include "afp_internal.h" +-#include "afp_protocol.h" ++#include "afpfs-ng/afp_protocol.h" + + struct afp_path_header_long { + unsigned char type; +diff -Naur afpfs-ng-0.8.1/Makefile.am afpfs-ng-0.8.1.patch/Makefile.am +--- afpfs-ng-0.8.1/Makefile.am 2008-02-18 04:24:14.000000000 +0100 ++++ afpfs-ng-0.8.1.patch/Makefile.am 2011-09-10 12:13:50.176125365 +0200 +@@ -1,5 +1,5 @@ + if HAVE_LIBFUSE +-SUBDIRS = lib fuse cmdline docs ++SUBDIRS = lib fuse cmdline include docs + else +-SUBDIRS = lib cmdline docs ++SUBDIRS = lib cmdline include docs + endif diff --git a/tools/android/depends/alsa-lib/Makefile b/tools/android/depends/alsa-lib/Makefile new file mode 100644 index 0000000000..aba5badb6e --- /dev/null +++ b/tools/android/depends/alsa-lib/Makefile @@ -0,0 +1,60 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile removeshm-2.patch removeshm-3.patch removeshm-upstream.patch timeval.patch + +# lib name, version +LIBNAME=libasound +VERSION=1.0.23 +SOURCE=alsa-lib-$(VERSION) +ARCHIVE=$(SOURCE).tar.bz2 + +# configuration settings +CFLAGS += \ + -fPIC -DPIC \ + -finline-limit=300 -finline-functions -fno-inline-functions-called-once \ + +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + $(AUTORECONF) -vif; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) \ + --with-alsa-devdir=/dev/snd/ --with-plugindir=/system/usr/lib/alsa-lib --with-configdir=/system/usr/share/alsa \ + --with-ctl-plugins=ext \ + --with-pcm-plugins="copy,linear,route,mulaw,alaw,adpcm,rate,plug,multi,file,null,empty,share,meter,hooks,lfloat,ladspa,asym,iec958,softvol,extplug,ioplug,mmap_emul" \ + --disable-resmgr --enable-aload --enable-mixer --enable-pcm --disable-rawmidi --enable-hwdep --disable-seq --disable-alisp --disable-old-symbols --disable-python \ + --with-softfloat=yes --with-libdl=yes --with-pthread=yes --with-librt=no \ + +LIBDYLIB=$(PLATFORM)/src/.libs/$(LIBNAME).so + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 < ../removeshm-upstream.patch + cd $(PLATFORM); patch -p0 < ../removeshm-2.patch + cd $(PLATFORM); patch -p0 < ../removeshm-3.patch + cd $(PLATFORM); patch -p0 < ../timeval.patch + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM)/src + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM)/src install-libLTLIBRARIES + $(MAKE) -C $(PLATFORM)/include install + $(MAKE) -C $(PLATFORM)/utils install + rm -f $(PREFIX)/lib/libasound.la $(PREFIX)/lib/libasound.so $(PREFIX)/lib/libxbasound.so $(PREFIX)/lib/libasound.so.2 + mv -f $(PREFIX)/lib/libasound.so.2.0.0 $(PREFIX)/lib/libasound.so + $(RPL) -e "libasound.so.2" "libasound.so\x00\x00" $(PREFIX)/lib/libasound.so + -$(READELF) --dynamic $(PREFIX)/lib/libasound.so | grep ibrary + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/alsa-lib/removeshm-2.patch b/tools/android/depends/alsa-lib/removeshm-2.patch new file mode 100644 index 0000000000..0bf5b18a4b --- /dev/null +++ b/tools/android/depends/alsa-lib/removeshm-2.patch @@ -0,0 +1,11 @@ +--- src/compat/Makefile.am 2012-05-25 00:00:09.824890740 -0400 ++++ src/compat/Makefile.am 2012-05-25 14:47:53.694857153 -0400 +@@ -1,8 +1,3 @@ + noinst_LTLIBRARIES = libcompat.la +-EXTRA_libcompat_la_SOURCES = hsearch_r.c + +-if ALSA_HSEARCH_R +-libcompat_la_SOURCES = empty.c hsearch_r.c +-else + libcompat_la_SOURCES = empty.c +-endif diff --git a/tools/android/depends/alsa-lib/removeshm-3.patch b/tools/android/depends/alsa-lib/removeshm-3.patch new file mode 100644 index 0000000000..8f651fea39 --- /dev/null +++ b/tools/android/depends/alsa-lib/removeshm-3.patch @@ -0,0 +1,11 @@ +--- src/Makefile.am 2011-01-12 17:02:37.000000000 -0500 ++++ src/Makefile.am 2012-05-25 00:10:22.184890354 -0400 +@@ -14,7 +14,7 @@ + endif + + lib_LTLIBRARIES = libasound.la +-libasound_la_SOURCES = conf.c confmisc.c input.c output.c async.c error.c dlmisc.c socket.c shmarea.c userfile.c names.c ++libasound_la_SOURCES = conf.c confmisc.c input.c output.c async.c error.c dlmisc.c socket.c userfile.c names.c + + SUBDIRS=control + libasound_la_LIBADD = control/libcontrol.la diff --git a/tools/android/depends/alsa-lib/removeshm-upstream.patch b/tools/android/depends/alsa-lib/removeshm-upstream.patch new file mode 100644 index 0000000000..ab899c3ed6 --- /dev/null +++ b/tools/android/depends/alsa-lib/removeshm-upstream.patch @@ -0,0 +1,187 @@ +From: Sean McNeil <sean.mcneil@windriver.com> +Date: Wed, 7 Jul 2010 02:03:47 +0000 (+0700) +Subject: Remove shared memory access. +X-Git-Tag: tegra-10.11.0~2 +X-Git-Url: http://nv-tegra.nvidia.com/gitweb/?p=android%2Fplatform%2Fexternal%2Falsa-lib.git;a=commitdiff_plain;h=24def9277c1bf4ed5c19b73ed3e76d761f992ddb + +Remove shared memory access. + +Somehow these changes didn't get committed. + +Change-Id: Ida7b706de56d95c8fb22d2708711a4d68c41ddaa +--- + +diff --git a/src/alisp/alisp.c b/src/alisp/alisp.c +index f3580f9..279a24c 100644 +--- a/src/alisp/alisp.c ++++ b/src/alisp/alisp.c +@@ -1025,6 +1025,7 @@ static const char *obj_type_str(struct alisp_object * p) + case ALISP_OBJ_CONS: return "cons"; + default: assert(0); + } ++ return 0; /* make compiler happy */ + } + + static void print_obj_lists(struct alisp_instance *instance, snd_output_t *out) +diff --git a/src/dlmisc.c b/src/dlmisc.c +index a0d62d3..b84eaf6 100644 +--- a/src/dlmisc.c ++++ b/src/dlmisc.c +@@ -27,6 +27,7 @@ + * + */ + ++#define _GNU_SOURCE + #include "list.h" + #include "local.h" + +@@ -53,13 +54,13 @@ void *snd_dlopen(const char *name, int mode) + #else + #ifdef HAVE_LIBDL + if (name == NULL) { +- static const char * self = NULL; +- if (self == NULL) { +- Dl_info dlinfo; +- if (dladdr(snd_dlopen, &dlinfo) > 0) +- self = dlinfo.dli_fname; +- } +- name = self; ++#ifdef ANDROID ++ return RTLD_DEFAULT; ++#else ++ Dl_info dlinfo; ++ if (dladdr(snd_dlopen, &dlinfo) > 0) ++ name = dlinfo.dli_fname; ++#endif + } + #endif + #endif +@@ -85,6 +86,10 @@ int snd_dlclose(void *handle) + return 0; + #endif + #ifdef HAVE_LIBDL ++#ifdef ANDROID ++ if (handle == RTLD_DEFAULT) ++ return 0; ++#endif + return dlclose(handle); + #else + return 0; +diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c +index f910189..71d5e99 100644 +--- a/src/pcm/pcm.c ++++ b/src/pcm/pcm.c +@@ -634,7 +634,6 @@ playback devices. + #include <stdarg.h> + #include <signal.h> + #include <sys/poll.h> +-#include <sys/shm.h> + #include <sys/mman.h> + #include <limits.h> + #include "pcm_local.h" +diff --git a/src/pcm/pcm_generic.c b/src/pcm/pcm_generic.c +index 84ea85f..d26aead 100644 +--- a/src/pcm/pcm_generic.c ++++ b/src/pcm/pcm_generic.c +@@ -26,7 +26,6 @@ + * + */ + +-#include <sys/shm.h> + #include <sys/ioctl.h> + #include <limits.h> + #include "pcm_local.h" +diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c +index 9d243d5..7f88a5b 100644 +--- a/src/pcm/pcm_hw.c ++++ b/src/pcm/pcm_hw.c +@@ -36,7 +36,6 @@ + #include <fcntl.h> + #include <sys/ioctl.h> + #include <sys/mman.h> +-#include <sys/shm.h> + #include "pcm_local.h" + #include "../control/control_local.h" + #include "../timer/timer_local.h" +diff --git a/src/pcm/pcm_mmap.c b/src/pcm/pcm_mmap.c +index 4621fe6..4b7a353 100644 +--- a/src/pcm/pcm_mmap.c ++++ b/src/pcm/pcm_mmap.c +@@ -23,7 +23,9 @@ + #include <string.h> + #include <sys/poll.h> + #include <sys/mman.h> ++#ifndef ANDROID + #include <sys/shm.h> ++#endif + #include "pcm_local.h" + + size_t page_size(void) +@@ -371,6 +373,7 @@ int snd_pcm_mmap(snd_pcm_t *pcm) + } + i->addr = ptr; + break; ++#ifndef ANDROID + case SND_PCM_AREA_SHM: + if (i->u.shm.shmid < 0) { + int id; +@@ -416,6 +419,7 @@ int snd_pcm_mmap(snd_pcm_t *pcm) + } + i->addr = ptr; + break; ++#endif + case SND_PCM_AREA_LOCAL: + ptr = malloc(size); + if (ptr == NULL) { +@@ -496,6 +500,7 @@ int snd_pcm_munmap(snd_pcm_t *pcm) + } + errno = 0; + break; ++#ifndef ANDROID + case SND_PCM_AREA_SHM: + if (i->u.shm.area) { + snd_shm_area_destroy(i->u.shm.area); +@@ -513,6 +518,7 @@ int snd_pcm_munmap(snd_pcm_t *pcm) + } + } + break; ++#endif + case SND_PCM_AREA_LOCAL: + free(i->addr); + break; +diff --git a/src/pcm/pcm_null.c b/src/pcm/pcm_null.c +index 692254a..2f2a42f 100644 +--- a/src/pcm/pcm_null.c ++++ b/src/pcm/pcm_null.c +@@ -28,7 +28,6 @@ + + #include <byteswap.h> + #include <limits.h> +-#include <sys/shm.h> + #include "pcm_local.h" + #include "pcm_plugin.h" + +diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c +index 0ef394a..a751deb 100644 +--- a/src/pcm/pcm_plugin.c ++++ b/src/pcm/pcm_plugin.c +@@ -82,7 +82,6 @@ pcm.rate44100Hz { + + */ + +-#include <sys/shm.h> + #include <limits.h> + #include "pcm_local.h" + #include "pcm_plugin.h" +diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c +index 56a8685..72084fc 100644 +--- a/src/pcm/pcm_share.c ++++ b/src/pcm/pcm_share.c +@@ -35,7 +35,6 @@ + #include <math.h> + #include <sys/socket.h> + #include <sys/poll.h> +-#include <sys/shm.h> + #include <pthread.h> + #include "pcm_local.h" + diff --git a/tools/android/depends/alsa-lib/timeval.patch b/tools/android/depends/alsa-lib/timeval.patch new file mode 100644 index 0000000000..0c8cbe718c --- /dev/null +++ b/tools/android/depends/alsa-lib/timeval.patch @@ -0,0 +1,11 @@ +--- include/global.h 2010-04-16 07:11:05.000000000 -0400 ++++ include/global.h 2012-05-25 15:38:15.494855247 -0400 +@@ -133,7 +133,7 @@ + + int snd_user_file(const char *file, char **result); + +-#if !defined(_POSIX_C_SOURCE) && !defined(_POSIX_SOURCE) ++#if 0 + struct timeval { + time_t tv_sec; /* seconds */ + long tv_usec; /* microseconds */ diff --git a/tools/android/depends/android-sys/Makefile b/tools/android/depends/android-sys/Makefile new file mode 100644 index 0000000000..036ecc3d77 --- /dev/null +++ b/tools/android/depends/android-sys/Makefile @@ -0,0 +1,53 @@ +include ../Makefile.include +DEPS = ../Makefile.include Makefile iomx.cpp + +LIBNAME=android-sys +VERSION=0.1 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +PRIVATE_LIBDIR=$(PLATFORM)/android-libs +PRIVATE_LIBS =$(PRIVATE_LIBDIR)/libutils.so +PRIVATE_LIBS+=$(PRIVATE_LIBDIR)/libmedia.so +PRIVATE_LIBS+=$(PRIVATE_LIBDIR)/libbinder.so +PRIVATE_LIBS+=$(PRIVATE_LIBDIR)/libstagefright.so + +CXXFLAGS =$(PLATFORM_FLAGS) -I$(PREFIX)/include -fexceptions +LDFLAGS += -L$(PRIVATE_LIBDIR) -lmedia -lutils -lbinder +INCLUDES+=-I$(PLATFORM)/$(SDK_PLATFORM)/system/core/include +INCLUDES+=-I$(PLATFORM)/$(SDK_PLATFORM)/frameworks/base/include +INCLUDES+=-I$(PLATFORM)/$(SDK_PLATFORM)/frameworks/base/include/media/stagefright/openmax + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + +$(PRIVATE_LIBS:.so=.symbols): $(PLATFORM) + +$(PRIVATE_LIBS:.so=.c): $(PRIVATE_LIBS:.so=.symbols) + rm -f $@ + for s in `cat $(@:.c=.symbols)`; do echo "void $$s() {}" >> $@; done + +$(PRIVATE_LIBS): $(PRIVATE_LIBS:.so=.c) + $(CC) $(@:.so=.c) -shared -o $@ + +$(PLATFORM)/$(SDK_PLATFORM)/libiomx.so: iomx.cpp + $(CXX) $(CXXFLAGS) $(INCLUDES) -shared -o $@ iomx.cpp $(LDFLAGS) -lstagefright + +.installed-$(PLATFORM): $(PRIVATE_LIBS) $(PLATFORM)/$(SDK_PLATFORM)/libiomx.so + mkdir -p $(PREFIX)/include/$(SDK_PLATFORM) + mkdir -p $(PREFIX)/lib/$(SDK_PLATFORM) + cp -f $(PLATFORM)/$(SDK_PLATFORM)/libiomx.so $(PREFIX)/lib/$(SDK_PLATFORM)/ + cp -f $(PLATFORM)/$(SDK_PLATFORM)/frameworks/base/include/media/stagefright/openmax/* $(PREFIX)/include/$(SDK_PLATFORM)/ + touch $@ + +clean: + rm -f .installed-$(PLATFORM) $(PLATFORM)/libiomx.so $(PRIVATE_LIBS) $(PRIVATE_LIBS:.so=.c) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/android-sys/iomx.cpp b/tools/android/depends/android-sys/iomx.cpp new file mode 100644 index 0000000000..d21fae74ca --- /dev/null +++ b/tools/android/depends/android-sys/iomx.cpp @@ -0,0 +1,473 @@ +/***************************************************************************** + * iomx.cpp: OpenMAX interface implementation based on IOMX + ***************************************************************************** + * Copyright (C) 2011 VLC authors and VideoLAN + * + * Authors: Martin Storsjo <martin@martin.st> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ + +#include <media/stagefright/OMXClient.h> +#include <media/IOMX.h> +#include <binder/MemoryDealer.h> +#include <OMX_Component.h> + +extern "C" { + +int android_printf(const char *format, ...) +{ + // For use before CLog is setup by XBMC_Run() + va_list args; + va_start(args, format); + int result = __android_log_vprint(ANDROID_LOG_VERBOSE, "XBMC", format, args); + va_end(args); + return result; +} +} + +//#define PREFIX(x) I ## x +#define PREFIX(x) x + +using namespace android; + +class IOMXContext { +public: + IOMXContext() { + } + + sp<IOMX> iomx; + List<IOMX::ComponentInfo> components; +}; + +static IOMXContext *ctx; + +class OMXNode; + +class OMXCodecObserver : public BnOMXObserver { +public: + OMXCodecObserver() { + node = NULL; + } + void setNode(OMXNode* n) { + node = n; + } + void onMessage(const omx_message &msg); + void registerBuffers(const sp<IMemoryHeap> &) { + } +private: + OMXNode *node; +}; + +class OMXNode { +public: + IOMX::node_id node; + sp<OMXCodecObserver> observer; + OMX_CALLBACKTYPE callbacks; + OMX_PTR app_data; + OMX_STATETYPE state; + List<OMX_BUFFERHEADERTYPE*> buffers; + OMX_HANDLETYPE handle; + String8 component_name; +}; + +class OMXBuffer { +public: + sp<MemoryDealer> dealer; + IOMX::buffer_id id; +}; + +void OMXCodecObserver::onMessage(const omx_message &msg) +{ + if (!node) + return; + switch (msg.type) { + case omx_message::EVENT: + // TODO: Needs locking + if (msg.u.event_data.event == OMX_EventCmdComplete && msg.u.event_data.data1 == OMX_CommandStateSet) + node->state = (OMX_STATETYPE) msg.u.event_data.data2; + node->callbacks.EventHandler(node->handle, node->app_data, msg.u.event_data.event, msg.u.event_data.data1, msg.u.event_data.data2, NULL); + break; + case omx_message::EMPTY_BUFFER_DONE: + for( List<OMX_BUFFERHEADERTYPE*>::iterator it = node->buffers.begin(); it != node->buffers.end(); it++ ) { + OMXBuffer* info = (OMXBuffer*) (*it)->pPlatformPrivate; + if (msg.u.buffer_data.buffer == info->id) { + node->callbacks.EmptyBufferDone(node->handle, node->app_data, *it); + break; + } + } + break; + case omx_message::FILL_BUFFER_DONE: + for( List<OMX_BUFFERHEADERTYPE*>::iterator it = node->buffers.begin(); it != node->buffers.end(); it++ ) { + OMXBuffer* info = (OMXBuffer*) (*it)->pPlatformPrivate; + if (msg.u.extended_buffer_data.buffer == info->id) { + OMX_BUFFERHEADERTYPE *buffer = *it; + buffer->nOffset = msg.u.extended_buffer_data.range_offset; + buffer->nFilledLen = msg.u.extended_buffer_data.range_length; + buffer->nFlags = msg.u.extended_buffer_data.flags; + buffer->nTimeStamp = msg.u.extended_buffer_data.timestamp; + node->callbacks.FillBufferDone(node->handle, node->app_data, buffer); + break; + } + } + break; + default: + break; + } +} + +static OMX_ERRORTYPE get_error(status_t err) +{ + if (err == OK) + return OMX_ErrorNone; + return OMX_ErrorUndefined; +} + +static int get_param_size(OMX_INDEXTYPE param_index) +{ + switch (param_index) { + case OMX_IndexParamPortDefinition: + return sizeof(OMX_PARAM_PORTDEFINITIONTYPE); + case OMX_IndexParamStandardComponentRole: + return sizeof(OMX_PARAM_COMPONENTROLETYPE); + case OMX_IndexParamVideoInit: + case OMX_IndexParamAudioInit: + case OMX_IndexParamImageInit: + case OMX_IndexParamOtherInit: + return sizeof(OMX_PORT_PARAM_TYPE); + case OMX_IndexParamNumAvailableStreams: + return sizeof(OMX_PARAM_U32TYPE); + case OMX_IndexParamAudioPcm: + return sizeof(OMX_AUDIO_PARAM_PCMMODETYPE); + case OMX_IndexParamAudioAdpcm: + return sizeof(OMX_AUDIO_PARAM_AMRTYPE); + case OMX_IndexParamAudioAmr: + return sizeof(OMX_AUDIO_PARAM_AMRTYPE); + case OMX_IndexParamAudioG723: + return sizeof(OMX_AUDIO_PARAM_G723TYPE); + case OMX_IndexParamAudioG726: + return sizeof(OMX_AUDIO_PARAM_G726TYPE); + case OMX_IndexParamAudioG729: + return sizeof(OMX_AUDIO_PARAM_G729TYPE); + case OMX_IndexParamAudioAac: + return sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE); + case OMX_IndexParamAudioMp3: + return sizeof(OMX_AUDIO_PARAM_MP3TYPE); + case OMX_IndexParamAudioSbc: + return sizeof(OMX_AUDIO_PARAM_SBCTYPE); + case OMX_IndexParamAudioVorbis: + return sizeof(OMX_AUDIO_PARAM_VORBISTYPE); + case OMX_IndexParamAudioWma: + return sizeof(OMX_AUDIO_PARAM_WMATYPE); + case OMX_IndexParamAudioRa: + return sizeof(OMX_AUDIO_PARAM_RATYPE); + case OMX_IndexParamVideoPortFormat: + return sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); + case OMX_IndexParamVideoBitrate: + return sizeof(OMX_VIDEO_PARAM_BITRATETYPE); + case OMX_IndexParamVideoH263: + return sizeof(OMX_VIDEO_PARAM_H263TYPE); + case OMX_IndexParamVideoMpeg4: + return sizeof(OMX_VIDEO_PARAM_MPEG4TYPE); + case OMX_IndexParamVideoAvc: + return sizeof(OMX_VIDEO_PARAM_AVCTYPE); + default: + return 0; + } +} + +static int get_config_size(OMX_INDEXTYPE param_index) +{ + switch (param_index) { + case OMX_IndexConfigCommonOutputCrop: + return sizeof(OMX_CONFIG_RECTTYPE); + default: + /* Dynamically queried config indices could have any size, but + * are currently only used with OMX_BOOL. */ + return sizeof(OMX_BOOL); + } +} + +static OMX_ERRORTYPE iomx_send_command(OMX_HANDLETYPE component, OMX_COMMANDTYPE command, OMX_U32 param1, OMX_PTR) +{ + android_printf("iomx_send_command\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)component)->pComponentPrivate; + return get_error(ctx->iomx->sendCommand(node->node, command, param1)); +} + +static OMX_ERRORTYPE iomx_get_parameter(OMX_HANDLETYPE component, OMX_INDEXTYPE param_index, OMX_PTR param) +{ + android_printf("iomx_get_parameter\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)component)->pComponentPrivate; + return get_error(ctx->iomx->getParameter(node->node, param_index, param, get_param_size(param_index))); +} + +static OMX_ERRORTYPE iomx_set_parameter(OMX_HANDLETYPE component, OMX_INDEXTYPE param_index, OMX_PTR param) +{ + android_printf("iomx_set_parameter\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)component)->pComponentPrivate; + return get_error(ctx->iomx->setParameter(node->node, param_index, param, get_param_size(param_index))); +} + +static OMX_ERRORTYPE iomx_get_state(OMX_HANDLETYPE component, OMX_STATETYPE *ptr) +{ + android_printf("iomx_get_state\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)component)->pComponentPrivate; + *ptr = node->state; + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE iomx_allocate_buffer(OMX_HANDLETYPE component, OMX_BUFFERHEADERTYPE **bufferptr, OMX_U32 port_index, OMX_PTR app_private, OMX_U32 size) +{ + android_printf("iomx_allocate_buffer\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)component)->pComponentPrivate; + OMXBuffer* info = new OMXBuffer; + info->dealer = new MemoryDealer(size + 4096); // Do we need to keep this around, or is it kept alive via the IMemory that references it? + sp<IMemory> mem = info->dealer->allocate(size); + int ret = ctx->iomx->allocateBufferWithBackup(node->node, port_index, mem, &info->id); + if (ret != OK) + return OMX_ErrorUndefined; + OMX_BUFFERHEADERTYPE *buffer = (OMX_BUFFERHEADERTYPE*) calloc(1, sizeof(OMX_BUFFERHEADERTYPE)); + *bufferptr = buffer; + buffer->pPlatformPrivate = info; + buffer->pAppPrivate = app_private; + buffer->nAllocLen = size; + buffer->pBuffer = (OMX_U8*) mem->pointer(); + node->buffers.push_back(buffer); + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE iomx_free_buffer(OMX_HANDLETYPE component, OMX_U32 port, OMX_BUFFERHEADERTYPE *buffer) +{ + android_printf("iomx_free_buffer\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)component)->pComponentPrivate; + OMXBuffer* info = (OMXBuffer*) buffer->pPlatformPrivate; + status_t ret = ctx->iomx->freeBuffer(node->node, port, info->id); + for( List<OMX_BUFFERHEADERTYPE*>::iterator it = node->buffers.begin(); it != node->buffers.end(); it++ ) { + if (buffer == *it) { + node->buffers.erase(it); + break; + } + } + free(buffer); + delete info; + return get_error(ret); +} + +static OMX_ERRORTYPE iomx_empty_this_buffer(OMX_HANDLETYPE component, OMX_BUFFERHEADERTYPE *buffer) +{ + android_printf("iomx_empty_this_buffer\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)component)->pComponentPrivate; + OMXBuffer* info = (OMXBuffer*) buffer->pPlatformPrivate; + return get_error(ctx->iomx->emptyBuffer(node->node, info->id, buffer->nOffset, buffer->nFilledLen, buffer->nFlags, buffer->nTimeStamp)); +} + +static OMX_ERRORTYPE iomx_fill_this_buffer(OMX_HANDLETYPE component, OMX_BUFFERHEADERTYPE *buffer) +{ + android_printf("iomx_fill_this_buffer\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)component)->pComponentPrivate; + OMXBuffer* info = (OMXBuffer*) buffer->pPlatformPrivate; + return get_error(ctx->iomx->fillBuffer(node->node, info->id)); +} + +static OMX_ERRORTYPE iomx_component_role_enum(OMX_HANDLETYPE component, OMX_U8 *role, OMX_U32 index) +{ + android_printf("iomx_component_role_enum\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)component)->pComponentPrivate; + for( List<IOMX::ComponentInfo>::iterator it = ctx->components.begin(); it != ctx->components.end(); it++ ) { + if (node->component_name == it->mName) { + if (index >= it->mRoles.size()) + return OMX_ErrorNoMore; + List<String8>::iterator it2 = it->mRoles.begin(); + for( OMX_U32 i = 0; it2 != it->mRoles.end() && i < index; i++, it2++ ) ; + strncpy((char*)role, it2->string(), OMX_MAX_STRINGNAME_SIZE); + if (it2->length() >= OMX_MAX_STRINGNAME_SIZE) + role[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; + return OMX_ErrorNone; + } + } + return OMX_ErrorInvalidComponentName; +} + +static OMX_ERRORTYPE iomx_get_extension_index(OMX_HANDLETYPE component, OMX_STRING parameter, OMX_INDEXTYPE *index) +{ + android_printf("iomx_get_extension_index\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)component)->pComponentPrivate; + return get_error(ctx->iomx->getExtensionIndex(node->node, parameter, index)); +} + +static OMX_ERRORTYPE iomx_set_config(OMX_HANDLETYPE component, OMX_INDEXTYPE index, OMX_PTR param) +{ + android_printf("iomx_set_config\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)component)->pComponentPrivate; + return get_error(ctx->iomx->setConfig(node->node, index, param, get_config_size(index))); +} + +static OMX_ERRORTYPE iomx_get_config(OMX_HANDLETYPE component, OMX_INDEXTYPE index, OMX_PTR param) +{ + android_printf("iomx_get_config\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)component)->pComponentPrivate; + return get_error(ctx->iomx->getConfig(node->node, index, param, get_config_size(index))); +} + +extern "C" { +OMX_ERRORTYPE PREFIX(OMX_GetHandle)(OMX_HANDLETYPE *handle_ptr, OMX_STRING component_name, OMX_PTR app_data, OMX_CALLBACKTYPE *callbacks) +{ + android_printf("OMX_GetHandle\n"); + OMXNode* node = new OMXNode(); + node->app_data = app_data; + node->callbacks = *callbacks; + node->observer = new OMXCodecObserver(); + node->observer->setNode(node); + node->state = OMX_StateLoaded; + node->component_name = component_name; + + OMX_COMPONENTTYPE* component = (OMX_COMPONENTTYPE*) malloc(sizeof(OMX_COMPONENTTYPE)); + memset(component, 0, sizeof(OMX_COMPONENTTYPE)); + component->nSize = sizeof(OMX_COMPONENTTYPE); + component->nVersion.s.nVersionMajor = 1; + component->nVersion.s.nVersionMinor = 0; + component->nVersion.s.nRevision = 0; + component->nVersion.s.nStep = 0; + component->pComponentPrivate = node; + component->SendCommand = iomx_send_command; + component->GetParameter = iomx_get_parameter; + component->SetParameter = iomx_set_parameter; + component->FreeBuffer = iomx_free_buffer; + component->EmptyThisBuffer = iomx_empty_this_buffer; + component->FillThisBuffer = iomx_fill_this_buffer; + component->GetState = iomx_get_state; + component->AllocateBuffer = iomx_allocate_buffer; + component->ComponentRoleEnum = iomx_component_role_enum; + component->GetExtensionIndex = iomx_get_extension_index; + component->SetConfig = iomx_set_config; + component->GetConfig = iomx_get_config; + + *handle_ptr = component; + node->handle = component; + status_t ret; + if ((ret = ctx->iomx->allocateNode( component_name, node->observer, &node->node )) != OK) + return OMX_ErrorUndefined; + return OMX_ErrorNone; +} + +OMX_ERRORTYPE PREFIX(OMX_FreeHandle)(OMX_HANDLETYPE handle) +{ + android_printf("OMX_FreeHandle\n"); + OMXNode* node = (OMXNode*) ((OMX_COMPONENTTYPE*)handle)->pComponentPrivate; + ctx->iomx->freeNode( node->node ); + node->observer->setNode(NULL); + delete node; + free(handle); + return OMX_ErrorNone; +} + +OMX_ERRORTYPE PREFIX(OMX_Init)(void) +{ + android_printf("OMX_Init\n"); + OMXClient client; + if (client.connect() != OK) + return OMX_ErrorUndefined; + + if (!ctx) + ctx = new IOMXContext(); + ctx->iomx = client.interface(); + ctx->iomx->listNodes(&ctx->components); + + for (List<IOMX::ComponentInfo>::iterator it = ctx->components.begin(); it != ctx->components.end(); it++) + { + const IOMX::ComponentInfo &info = *it; + const char* componentName = info.mName.string(); + for (List<String8>::const_iterator role_it = info.mRoles.begin(); role_it != info.mRoles.end(); role_it++) + { + const char* componentRole = (*role_it).string(); + android_printf("componentName:%s,componentRole:%s\n", componentName, componentRole); + } + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE PREFIX(OMX_Deinit)(void) +{ + android_printf("OMX_Deinit\n"); + ctx->iomx = NULL; + delete ctx; + ctx = NULL; + return OMX_ErrorNone; +} + +OMX_ERRORTYPE PREFIX(OMX_ComponentNameEnum)(OMX_STRING component_name, OMX_U32 name_length, OMX_U32 index) +{ + android_printf("OMX_ComponentNameEnum\n"); + if (index >= ctx->components.size()) + return OMX_ErrorNoMore; + List<IOMX::ComponentInfo>::iterator it = ctx->components.begin(); + for( OMX_U32 i = 0; i < index; i++ ) + it++; + strncpy(component_name, it->mName.string(), name_length); + component_name[name_length - 1] = '\0'; + return OMX_ErrorNone; +} + +OMX_ERRORTYPE PREFIX(OMX_GetRolesOfComponent)(OMX_STRING component_name, OMX_U32 *num_roles, OMX_U8 **roles) +{ + android_printf("OMX_GetRolesOfComponent\n"); + for( List<IOMX::ComponentInfo>::iterator it = ctx->components.begin(); it != ctx->components.end(); it++ ) { + if (!strcmp(component_name, it->mName.string())) { + if (!roles) { + *num_roles = it->mRoles.size(); + return OMX_ErrorNone; + } + if (*num_roles < it->mRoles.size()) + return OMX_ErrorInsufficientResources; + *num_roles = it->mRoles.size(); + OMX_U32 i = 0; + for( List<String8>::iterator it2 = it->mRoles.begin(); it2 != it->mRoles.end(); i++, it2++ ) { + strncpy((char*)roles[i], it2->string(), OMX_MAX_STRINGNAME_SIZE); + roles[i][OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; + } + return OMX_ErrorNone; + } + } + return OMX_ErrorInvalidComponentName; +} + +OMX_ERRORTYPE PREFIX(OMX_GetComponentsOfRole)(OMX_STRING role, OMX_U32 *num_comps, OMX_U8 **comp_names) +{ + android_printf("OMX_GetComponentsOfRole\n"); + OMX_U32 i = 0; + for( List<IOMX::ComponentInfo>::iterator it = ctx->components.begin(); it != ctx->components.end(); it++ ) { + for( List<String8>::iterator it2 = it->mRoles.begin(); it2 != it->mRoles.end(); it2++ ) { + if (!strcmp(it2->string(), role)) { + if (comp_names) { + if (*num_comps < i) + return OMX_ErrorInsufficientResources; + strncpy((char*)comp_names[i], it->mName.string(), OMX_MAX_STRINGNAME_SIZE); + comp_names[i][OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; + } + i++; + break; + } + } + } + *num_comps = i; + return OMX_ErrorNone; +} +} + diff --git a/tools/android/depends/autoconf/Makefile b/tools/android/depends/autoconf/Makefile new file mode 100644 index 0000000000..7bd9cae384 --- /dev/null +++ b/tools/android/depends/autoconf/Makefile @@ -0,0 +1,40 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=autoconf +VERSION=2.68 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) + +LIBDYLIB=$(PLATFORM)/bin/autoconf + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + +$(LIBDYLIB): $(PLATFORM) + cd $(PLATFORM); $(CONFIGURE) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/automake/Makefile b/tools/android/depends/automake/Makefile new file mode 100644 index 0000000000..a74ffef8fc --- /dev/null +++ b/tools/android/depends/automake/Makefile @@ -0,0 +1,40 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=automake +VERSION=1.11.3 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) + +LIBDYLIB=$(PLATFORM)/automake + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/boost/Makefile b/tools/android/depends/boost/Makefile new file mode 100644 index 0000000000..76af96f721 --- /dev/null +++ b/tools/android/depends/boost/Makefile @@ -0,0 +1,34 @@ +include ../Makefile.include +DEPS= ../Makefile.include add-arm-mem-barrier.patch fix-deprecated-swp.patch Makefile + +#Headers Only! +LIBNAME=boost +VERSION=1_44_0 +SOURCE=$(LIBNAME)_$(VERSION) +ARCHIVE=$(SOURCE).tar.bz2 + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +.installed-$(PLATFORM): $(LIBDYLIB) $(TARBALLS_LOCATION)/$(ARCHIVE) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + echo 'using gcc : : $(CC) : ' > $(PLATFORM)/tools/build/v2/user-config.jam + echo ' <cflags>"$(CFLAGS)"' >> $(PLATFORM)/tools/build/v2/user-config.jam + echo ' <cxxflags>"$(CXXFLAGS)"' >> $(PLATFORM)/tools/build/v2/user-config.jam + echo ' ;' >> $(PLATFORM)/tools/build/v2/user-config.jam + cd $(PLATFORM); patch -p1 < ../add-arm-mem-barrier.patch + cd $(PLATFORM); patch -p1 < ../fix-deprecated-swp.patch + cd $(PLATFORM); ./bootstrap.sh --prefix=$(PREFIX) + cd $(PLATFORM); ./bjam --prefix=$(PREFIX) toolset=gcc --toolset-root=$(TOOLCHAIN)/$(HOST)/bin --disable-icu \ + --without-date_time --without-filesystem --without-graph --without-graph_parallel --without-iostreams --without-math --without-mpi --without-program_options \ +--without-python --without-random --without-regex --without-serialization --without-signals --without-system --without-test --without-thread --without-wave install + touch .installed-$(PLATFORM) + +clean: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/boost/add-arm-mem-barrier.patch b/tools/android/depends/boost/add-arm-mem-barrier.patch new file mode 100644 index 0000000000..86f8985ee2 --- /dev/null +++ b/tools/android/depends/boost/add-arm-mem-barrier.patch @@ -0,0 +1,73 @@ +From c87ad09331d239d6566e5eb409898ae38f04799a Mon Sep 17 00:00:00 2001 +From: Peter Dimov <pdimov@boostpro.com> +Date: Mon, 7 Nov 2011 17:50:31 +0000 +Subject: [PATCH] Add ARM memory barriers. Refs #5372. + +SVN-Revision: 75389 +--- + boost/smart_ptr/detail/spinlock_gcc_arm.hpp | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) + +diff --git a/boost/smart_ptr/detail/spinlock_gcc_arm.hpp b/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +index ba6c511..f58ea44 100644 +--- a/boost/smart_ptr/detail/spinlock_gcc_arm.hpp ++++ b/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +@@ -2,7 +2,7 @@ + #define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED + + // +-// Copyright (c) 2008 Peter Dimov ++// Copyright (c) 2008, 2011 Peter Dimov + // + // Distributed under the Boost Software License, Version 1.0. + // See accompanying file LICENSE_1_0.txt or copy at +@@ -11,6 +11,20 @@ + + #include <boost/smart_ptr/detail/yield_k.hpp> + ++#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) ++ ++# define BOOST_SP_ARM_BARRIER "dmb" ++ ++#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ++ ++# define BOOST_SP_ARM_BARRIER "mcr p15, 0, r0, c7, c10, 5" ++ ++#else ++ ++# define BOOST_SP_ARM_BARRIER "" ++ ++#endif ++ + namespace boost + { + +@@ -30,7 +44,8 @@ class spinlock + int r; + + __asm__ __volatile__( +- "swp %0, %1, [%2]": ++ "swp %0, %1, [%2]\n\t" ++ BOOST_SP_ARM_BARRIER : + "=&r"( r ): // outputs + "r"( 1 ), "r"( &v_ ): // inputs + "memory", "cc" ); +@@ -48,7 +63,7 @@ class spinlock + + void unlock() + { +- __asm__ __volatile__( "" ::: "memory" ); ++ __asm__ __volatile__( BOOST_SP_ARM_BARRIER ::: "memory" ); + *const_cast< int volatile* >( &v_ ) = 0; + } + +@@ -82,4 +97,6 @@ class spinlock + + #define BOOST_DETAIL_SPINLOCK_INIT {0} + ++#undef BOOST_SP_ARM_BARRIER ++ + #endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED +-- +1.7.10 + diff --git a/tools/android/depends/boost/fix-deprecated-swp.patch b/tools/android/depends/boost/fix-deprecated-swp.patch new file mode 100644 index 0000000000..de5888d737 --- /dev/null +++ b/tools/android/depends/boost/fix-deprecated-swp.patch @@ -0,0 +1,58 @@ +From 8d1ba081260f98d879759433a9d7248d6bd98966 Mon Sep 17 00:00:00 2001 +From: Peter Dimov <pdimov@boostpro.com> +Date: Mon, 12 Mar 2012 17:31:21 +0000 +Subject: [PATCH] Apply patch from #5331. Refs #5331. + +SVN-Revision: 77315 +--- + boost/smart_ptr/detail/spinlock_gcc_arm.hpp | 29 +++++++++++++++++++++++++-- + 1 file changed, 27 insertions(+), 2 deletions(-) + +diff --git a/boost/smart_ptr/detail/spinlock_gcc_arm.hpp b/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +index f58ea44..f1bbaf6 100644 +--- a/boost/smart_ptr/detail/spinlock_gcc_arm.hpp ++++ b/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +@@ -43,13 +43,38 @@ class spinlock + { + int r; + ++#if defined(__ARM_ARCH_6__) \ ++ || defined(__ARM_ARCH_6J__) \ ++ || defined(__ARM_ARCH_6K__) \ ++ || defined(__ARM_ARCH_6Z__) \ ++ || defined(__ARM_ARCH_6ZK__) \ ++ || defined(__ARM_ARCH_6T2__) \ ++ || defined(__ARM_ARCH_7__) \ ++ || defined(__ARM_ARCH_7A__) \ ++ || defined(__ARM_ARCH_7R__) \ ++ || defined(__ARM_ARCH_7M__) \ ++ || defined(__ARM_ARCH_7EM__) ++ ++ __asm__ __volatile__( ++ "ldrex %0, [%2]; \n" ++ "cmp %0, %1; \n" ++ "strexne %0, %1, [%2]; \n" ++ BOOST_SP_ARM_BARRIER : ++ "=&r"( r ): // outputs ++ "r"( 1 ), "r"( &v_ ): // inputs ++ "memory", "cc" ); ++ ++#else ++ + __asm__ __volatile__( +- "swp %0, %1, [%2]\n\t" +- BOOST_SP_ARM_BARRIER : ++ "swp %0, %1, [%2];\n" ++ BOOST_SP_ARM_BARRIER : + "=&r"( r ): // outputs + "r"( 1 ), "r"( &v_ ): // inputs + "memory", "cc" ); + ++#endif ++ + return r == 0; + } + +-- +1.7.10 + diff --git a/tools/android/depends/bootstrap b/tools/android/depends/bootstrap new file mode 100755 index 0000000000..171a93908c --- /dev/null +++ b/tools/android/depends/bootstrap @@ -0,0 +1 @@ +autoconf diff --git a/tools/android/depends/bzip2/Makefile b/tools/android/depends/bzip2/Makefile new file mode 100644 index 0000000000..bb59fadb1c --- /dev/null +++ b/tools/android/depends/bzip2/Makefile @@ -0,0 +1,40 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile Makefile.patch + +# lib name, version +LIBNAME=bzip2 +VERSION=1.0.6 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared + +LIBDYLIB=$(PLATFORM)/libbz2.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 <../Makefile.patch + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) PREFIX=$(PREFIX) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install PREFIX=$(PREFIX) + rm $(PREFIX)/bin/bzip2 + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/bzip2/Makefile.patch b/tools/android/depends/bzip2/Makefile.patch new file mode 100644 index 0000000000..40dc70a2c2 --- /dev/null +++ b/tools/android/depends/bzip2/Makefile.patch @@ -0,0 +1,34 @@ +--- Makefile 2008-02-14 14:39:18.000000000 +0200 ++++ ../Makefile 2009-08-30 15:59:16.000000000 +0300 +@@ -15,16 +15,16 @@ + SHELL=/bin/sh + + # To assist in cross-compiling +-CC=gcc +-AR=ar +-RANLIB=ranlib +-LDFLAGS= ++#CC=gcc ++#AR=ar ++#RANLIB=ranlib ++#LDFLAGS= + + BIGFILES=-D_FILE_OFFSET_BITS=64 +-CFLAGS=-Wall -Winline -O2 -g $(BIGFILES) ++#CFLAGS=-Wall -Winline -O2 -g $(BIGFILES) + + # Where you want it installed when you do 'make install' +-PREFIX=/usr/local ++#PREFIX=/usr/local + + + OBJS= blocksort.o \ +@@ -35,7 +35,7 @@ + decompress.o \ + bzlib.o + +-all: libbz2.a bzip2 bzip2recover test ++all: libbz2.a bzip2 bzip2recover + + bzip2: libbz2.a bzip2.o + $(CC) $(CFLAGS) $(LDFLAGS) -o bzip2 bzip2.o -L. -lbz2 diff --git a/tools/android/depends/cmake/Makefile b/tools/android/depends/cmake/Makefile new file mode 100644 index 0000000000..3237d57e52 --- /dev/null +++ b/tools/android/depends/cmake/Makefile @@ -0,0 +1,40 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +APPNAME=cmake +VERSION=2.8.4 +SOURCE=$(APPNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./bootstrap --prefix=$(PREFIX) + +APP=$(PLATFORM)/bin/$(APPNAME) + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(APP): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(APP) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/configure.in b/tools/android/depends/configure.in new file mode 100644 index 0000000000..629c46950d --- /dev/null +++ b/tools/android/depends/configure.in @@ -0,0 +1,151 @@ +AC_PREREQ(2.59) +AC_INIT([android-depends], [2.00], [http://trac.xbmc.org]) +AC_CONFIG_FILES([Makefile Makefile.include]) + +AC_ARG_VAR(XBMC_ANDROID_NDK, path to android ndk) +AC_ARG_VAR(XBMC_ANDROID_SDK, path to android sdk) +AC_ARG_VAR(XBMC_ANDROID_TARBALLS, path where tarballs will be saved) + +use_ndk=$XBMC_ANDROID_NDK +use_sdk=$XBMC_ANDROID_SDK +use_staging=$XBMC_ANDROID_STAGING +use_tarballs=$XBMC_ANDROID_TARBALLS + +AC_ARG_WITH([toolchain], + [AS_HELP_STRING([--with-toolchain], + [specify path to android toolchain])], + [use_toolchain=$withval],AC_MSG_ERROR([No toolchain defined])) + +AC_ARG_WITH([sdk], + [AS_HELP_STRING([--with-sdk], + [specify path to android sdk])], + [use_sdk=$withval],[if test -z $use_sdk; then AC_MSG_ERROR([No SDK path defined]); fi]) + +AC_ARG_WITH([ndk], + [AS_HELP_STRING([--with-ndk], + [specify path to android ndk])], + [use_ndk=$withval],[if test -z $use_ndk; then AC_MSG_ERROR([No NDK path defined]); fi]) + +AC_ARG_WITH([tarballs], + [AS_HELP_STRING([--with-tarballs], + [path where tarballs will be saved])], + [use_tarballs=$withval], [if test -z $use_tarballs; then AC_MSG_ERROR([No tarballs path defined]); fi]) + +AC_ARG_WITH([staging], + [AS_HELP_STRING([--with-staging], + [optional. path for staging sysroot. defaults to $toolchain/staging])], + [use_staging=$withval],[use_staging=$use_toolchain/staging]) + +AC_ARG_WITH([cpu], + [AS_HELP_STRING([--with-cpu], + [optional. specify target cpu. guessed if not specified])], + [use_cpu=$withval],use_cpu=no) + +AC_ARG_WITH([sdk-platform], + [AS_HELP_STRING([--with-sdk-platform], + [optional. spcify sdk platform version (for android headers). default is android-10])], + [use_sdk_platform=$withval],use_sdk_platform=android-10) + +AC_PROG_CXX +AC_PROG_CC +AC_CHECK_LIB([z], [main],, AC_MSG_ERROR("Missing libz development files")) + +AC_CHECK_PROG(HAVE_UNZIP,unzip,"yes","no",) +if test "x$HAVE_UNZIP" = "xno" ; then + AC_MSG_ERROR("Missing program: unzip") +fi + +AC_CHECK_PROG(HAVE_ZIP,zip,"yes","no",) +if test "x$HAVE_ZIP" = "xno" ; then + AC_MSG_ERROR("Missing program: zip") +fi + +AC_PATH_PROG(CURL,curl,"no") +if test "x$CURL" = "xno" ; then + AC_MSG_ERROR("Missing program: curl") +fi + +AC_PATH_PROG(TAR,tar,"no") +if test "x$TAR" = "xno" ; then + AC_MSG_ERROR("Missing program: tar") +fi + +#find host toolchain +AC_CHECK_PROG(host_gcc,$host-gcc,yes,no,$use_toolchain/bin) +if test "$host_gcc" = "no"; then + AC_MSG_WARN(host was not specified. guessing.) + AC_PATH_PROG(host_gcc,gcc,no,[$use_toolchain/*/bin]) + if test "$host_gcc" = "no"; then + AC_MSG_ERROR([Arm toolchain not found at specified path]) + fi + use_host=`$host_gcc -dumpmachine 2>/dev/null` +else + use_host=$host +fi + +#guess host cpu +if test "$use_cpu" = "no"; then + case $use_host in + arm*) + use_cpu="armeabi-v7a" + ;; + *i686*) + use_cpu="x86" + ;; + *) + AC_MSG_ERROR(unsupported host ($host)) + esac +fi + + +# Some dumb checks to see if paths might be correct. + +if [ ! `mkdir -p $use_staging/$use_cpu/include` ]; then + AC_MSG_ERROR(unable to create $use_staging/$use_cpu/include. verify that the path and permissions are correct.) +fi + +if [ ! `mkdir -p $use_staging/$use_cpu/lib` ]; then + AC_MSG_ERROR(unable to create $use_staging/$use_cpu/lib. verify that the path and permissions are correct.) +fi + +if [ ! `mkdir -p $use_staging/$use_cpu-native/include` ]; then + AC_MSG_ERROR(unable to create $use_staging/$use_cpu-native/include. verify that the path and permissions are correct.) +fi + +if [ ! `mkdir -p $use_staging/$use_cpu-native/lib` ]; then + AC_MSG_ERROR(unable to create $use_staging/$use_cpu-native/lib. verify that the path and permissions are correct.) +fi + +if [ ! `mkdir -p $use_staging/$use_cpu/include/$use_sdk_platform` ]; then + AC_MSG_ERROR(unable to create $use_staging/$use_cpu/include/$use_sdk_platform. verify that the path and permissions are correct.) +fi + +if [ ! `mkdir -p $use_staging/$use_cpu/lib/$use_sdk_platform` ]; then + AC_MSG_ERROR(unable to create $use_staging/$use_cpu/lib/$use_sdk_platform. verify that the path and permissions are correct.) +fi + +if [ ! `mkdir -p $use_tarballs` ]; then + AC_MSG_ERROR(unable to create tarballs dir. verify that the path and permissions are correct.) +fi + +if [ ! test -f $use_sdk/tools/zipalign ]; then + AC_MSG_ERROR(verify sdk path) +fi + +if [ ! test -f $use_ndk/sources/android/native_app_glue/android_native_app_glue.h ]; then + AC_MSG_ERROR(verify ndk path) +fi + +AC_SUBST(use_sdk) +AC_SUBST(use_ndk) +AC_SUBST(use_arch) +AC_SUBST(use_host) +AC_SUBST(use_cpu) +AC_SUBST(use_staging) +AC_SUBST(use_toolchain) +AC_SUBST(use_tarballs) +AC_SUBST(use_sdk_platform) + +echo -e " \ttoolchain:\t $use_toolchain\n \tcpu:\t\t $use_cpu\n \thost:\t\t $use_host\n \tsdk-platform:\t $use_sdk_platform" + +AC_OUTPUT diff --git a/tools/android/depends/curl/Makefile b/tools/android/depends/curl/Makefile new file mode 100644 index 0000000000..282ea5b825 --- /dev/null +++ b/tools/android/depends/curl/Makefile @@ -0,0 +1,47 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=curl +VERSION=7.21.3 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.bz2 +CFLAGS+=-DANDROID + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --without-libssh2 \ +ac_cv_file__dev_urandom=yes \ + +LIBDYLIB=$(PLATFORM)/lib/.libs/lib$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libcurl.la $(PREFIX)/lib/libcurl.so $(PREFIX)/lib/libcurl.so.5 + mv -f $(PREFIX)/lib/libcurl.so.5.2.0 $(PREFIX)/lib/libcurl.so + $(RPL) -e "libcurl.so.5" "libcurl.so\x00\x00" $(PREFIX)/lib/libcurl.so + -$(READELF) --dynamic $(PREFIX)/lib/libcurl.so | grep ibrary + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/dbus/Makefile b/tools/android/depends/dbus/Makefile new file mode 100644 index 0000000000..c0df9c4a51 --- /dev/null +++ b/tools/android/depends/dbus/Makefile @@ -0,0 +1,40 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=dbus +VERSION=1.4.6 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) --host=$(HOST) \ + --without-x --disable-xml-docs --disable-doxygen-docs + +LIBDYLIB=$(PLATFORM)/$(LIBNAME)/.libs/$(LIBNAME).so + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: $(LIBDYLIB) .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/dummy-libxbmc/Makefile b/tools/android/depends/dummy-libxbmc/Makefile new file mode 100644 index 0000000000..4b72d51cfd --- /dev/null +++ b/tools/android/depends/dummy-libxbmc/Makefile @@ -0,0 +1,24 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile dummy-libxbmc.c + +LIBDYLIB=libxbmc.so + +all: $(PLATFORM)/$(LIBDYLIB) .installed-$(PLATFORM) + +$(PLATFORM): + mkdir -p $(PLATFORM) + +$(PLATFORM)/$(LIBDYLIB): $(PLATFORM) $(DEPS) + $(CC) -shared -o $(PLATFORM)/libxbmc.so dummy-libxbmc.c + +.installed-$(PLATFORM): $(PLATFORM)/$(LIBDYLIB) + mkdir -p $(PREFIX)/lib/dummy-libxbmc + cp $(PLATFORM)/libxbmc.so $(PREFIX)/lib/dummy-libxbmc + touch $@ + +clean: + rm -rf $(PLATFORM) + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/dummy-libxbmc/dummy-libxbmc.c b/tools/android/depends/dummy-libxbmc/dummy-libxbmc.c new file mode 100644 index 0000000000..2d72d2be7c --- /dev/null +++ b/tools/android/depends/dummy-libxbmc/dummy-libxbmc.c @@ -0,0 +1,4 @@ +void xbmc_dummy_function() +{ + return; +} diff --git a/tools/android/depends/expat/Makefile b/tools/android/depends/expat/Makefile new file mode 100644 index 0000000000..88353d3ace --- /dev/null +++ b/tools/android/depends/expat/Makefile @@ -0,0 +1,40 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=expat +VERSION=2.0.1 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) ./conftools; ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared + +LIBDYLIB=$(PLATFORM)/.libs/lib$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/fontconfig/01-fontconfig-cross-compile-fix.patch b/tools/android/depends/fontconfig/01-fontconfig-cross-compile-fix.patch new file mode 100644 index 0000000000..334cbbaf81 --- /dev/null +++ b/tools/android/depends/fontconfig/01-fontconfig-cross-compile-fix.patch @@ -0,0 +1,80 @@ +diff -Naur fontconfig-2.6.0.orig/doc/Makefile.am fontconfig-2.6.0/doc/Makefile.am +--- fontconfig-2.6.0.orig/doc/Makefile.am 2007-11-06 01:05:37.000000000 +0100 ++++ fontconfig-2.6.0/doc/Makefile.am 2010-05-22 00:03:00.000000000 +0200 +@@ -21,9 +21,10 @@ + # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + # PERFORMANCE OF THIS SOFTWARE. + +-CC = @CC_FOR_BUILD@ + EXEEXT = @EXEEXT_FOR_BUILD@ +-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ ++COMPILE = $(CC_FOR_BUILD) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ ++ $(CPPFLAGS_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) ++LINK = $(CC_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) $(AM_LDFLAGS) $(LDFLAGS_FOR_BUILD) -o $@ + + DOC_SRC = $(srcdir) + DOC_MODULE = fontconfig +diff -Naur fontconfig-2.6.0.orig/fc-arch/Makefile.am fontconfig-2.6.0/fc-arch/Makefile.am +--- fontconfig-2.6.0.orig/fc-arch/Makefile.am 2008-01-02 17:44:39.000000000 +0100 ++++ fontconfig-2.6.0/fc-arch/Makefile.am 2010-05-21 23:59:18.000000000 +0200 +@@ -22,9 +22,10 @@ + # PERFORMANCE OF THIS SOFTWARE. + # + +-CC = @CC_FOR_BUILD@ + EXEEXT = @EXEEXT_FOR_BUILD@ +-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ ++COMPILE = $(CC_FOR_BUILD) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ ++ $(CPPFLAGS_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) ++LINK = $(CC_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) $(AM_LDFLAGS) $(LDFLAGS_FOR_BUILD) -o $@ + + INCLUDES=-I${top_srcdir}/src -I${top_srcdir} $(WARN_CFLAGS) + +diff -Naur fontconfig-2.6.0.orig/fc-case/Makefile.am fontconfig-2.6.0/fc-case/Makefile.am +--- fontconfig-2.6.0.orig/fc-case/Makefile.am 2010-05-21 23:55:02.000000000 +0200 ++++ fontconfig-2.6.0/fc-case/Makefile.am 2010-05-22 00:04:09.000000000 +0200 +@@ -22,9 +22,10 @@ + # PERFORMANCE OF THIS SOFTWARE. + # + +-CC = @CC_FOR_BUILD@ + EXEEXT = @EXEEXT_FOR_BUILD@ +-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ ++COMPILE = $(CC_FOR_BUILD) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ ++ $(CPPFLAGS_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) ++LINK = $(CC_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) $(AM_LDFLAGS) $(LDFLAGS_FOR_BUILD) -o $@ + + INCLUDES=-I${top_srcdir}/src -I${top_srcdir} $(WARN_CFLAGS) + +diff -Naur fontconfig-2.6.0.orig/fc-glyphname/Makefile.am fontconfig-2.6.0/fc-glyphname/Makefile.am +--- fontconfig-2.6.0.orig/fc-glyphname/Makefile.am 2008-01-02 17:44:39.000000000 +0100 ++++ fontconfig-2.6.0/fc-glyphname/Makefile.am 2010-05-22 00:04:54.000000000 +0200 +@@ -22,9 +22,10 @@ + # PERFORMANCE OF THIS SOFTWARE. + # + +-CC = @CC_FOR_BUILD@ + EXEEXT = @EXEEXT_FOR_BUILD@ +-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ ++COMPILE = $(CC_FOR_BUILD) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ ++ $(CPPFLAGS_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) ++LINK = $(CC_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) $(AM_LDFLAGS) $(LDFLAGS_FOR_BUILD) -o $@ + + INCLUDES=-I${top_srcdir}/src -I${top_srcdir} $(WARN_CFLAGS) + +diff -Naur fontconfig-2.6.0.orig/fc-lang/Makefile.am fontconfig-2.6.0/fc-lang/Makefile.am +--- fontconfig-2.6.0.orig/fc-lang/Makefile.am 2008-01-02 17:44:39.000000000 +0100 ++++ fontconfig-2.6.0/fc-lang/Makefile.am 2010-05-22 00:05:44.000000000 +0200 +@@ -22,9 +22,10 @@ + # PERFORMANCE OF THIS SOFTWARE. + # + +-CC = @CC_FOR_BUILD@ + EXEEXT = @EXEEXT_FOR_BUILD@ +-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ ++COMPILE = $(CC_FOR_BUILD) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ ++ $(CPPFLAGS_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) ++LINK = $(CC_FOR_BUILD) $(AM_CFLAGS) $(CFLAGS_FOR_BUILD) $(AM_LDFLAGS) $(LDFLAGS_FOR_BUILD) -o $@ + + INCLUDES=-I${top_srcdir}/src -I${top_srcdir} $(WARN_CFLAGS) + diff --git a/tools/android/depends/fontconfig/Makefile b/tools/android/depends/fontconfig/Makefile new file mode 100644 index 0000000000..46b0fb151d --- /dev/null +++ b/tools/android/depends/fontconfig/Makefile @@ -0,0 +1,45 @@ +include ../Makefile.include +DEPS= ../Makefile.include 01-fontconfig-cross-compile-fix.patch lconv.patch Makefile + +# lib name, version +LIBNAME=fontconfig +VERSION=2.8.0 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) --host=$(HOST) \ + --with-freetype-config=$(PREFIX)/bin/freetype-config \ + --disable-libxml2 --disable-docs --with-arch=arm --disable-shared + +LIBDYLIB=$(PLATFORM)/src/.libs/lib$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 < ../01-fontconfig-cross-compile-fix.patch + cd $(PLATFORM); patch -p1 < ../lconv.patch + cd $(PLATFORM); $(AUTORECONF) -vif + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/fontconfig/lconv.patch b/tools/android/depends/fontconfig/lconv.patch new file mode 100644 index 0000000000..c760d7f7a4 --- /dev/null +++ b/tools/android/depends/fontconfig/lconv.patch @@ -0,0 +1,18 @@ +--- fontconfig-2.6.0.old/src/fcxml.c 2011-10-15 16:16:43.809967115 -0400 ++++ fontconfig-2.6.0/src/fcxml.c 2011-10-15 16:18:39.059967042 -0400 +@@ -1139,6 +1139,7 @@ + static double + FcStrtod (char *s, char **end) + { ++#if 0 + struct lconv *locale_data; + char *dot; + double v; +@@ -1185,6 +1186,7 @@ + else + v = strtod (s, end); + return v; ++#endif + } + + static void
\ No newline at end of file diff --git a/tools/android/depends/freetype2/Makefile b/tools/android/depends/freetype2/Makefile new file mode 100644 index 0000000000..d25a378623 --- /dev/null +++ b/tools/android/depends/freetype2/Makefile @@ -0,0 +1,43 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=freetype +VERSION=2.3.9 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.bz2 + +# configuration settings +# force using internal libtool +export LIBTOOL=builds/unix/libtool +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) builds/unix; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared + +LIBDYLIB=$(PLATFORM)/objs/.libs/lib$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/fribidi/Makefile b/tools/android/depends/fribidi/Makefile new file mode 100644 index 0000000000..0a36bda101 --- /dev/null +++ b/tools/android/depends/fribidi/Makefile @@ -0,0 +1,42 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=fribidi +VERSION=0.19.1 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz +CFLAGS+=-D__STDC_INT64__ +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-docs --enable-malloc \ + --disable-shared + +LIBDYLIB=$(PLATFORM)/.libs/lib$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/gettext-native/Makefile b/tools/android/depends/gettext-native/Makefile new file mode 100644 index 0000000000..35aecf8345 --- /dev/null +++ b/tools/android/depends/gettext-native/Makefile @@ -0,0 +1,52 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=gettext +VERSION=0.18.1.1 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) \ + --disable-csharp --disable-native-java --disable-java --without-emacs \ + --disable-libasprintf --disable-openmp \ + --with-included-gettext \ + --with-included-glib \ + --with-included-libcroco \ + --with-included-libxml \ + --without-git --without-cvs \ + --disable-shared + +LIBDYLIB=$(PLATFORM)/gettext-tools/src/.libs/libgettextsrc.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); sed -ie '/gets is a security hole/d' gettext-tools/gnulib-lib/stdio.in.h + cd $(PLATFORM); sed -ie '/gets is a security hole/d' gettext-tools/libgettextpo/stdio.in.h + cd $(PLATFORM); sed -ie '/gets is a security hole/d' gettext-runtime/gnulib-lib/stdio.in.h + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/gettext/02-gettext_msginit.patch b/tools/android/depends/gettext/02-gettext_msginit.patch new file mode 100644 index 0000000000..3a63ba5aaa --- /dev/null +++ b/tools/android/depends/gettext/02-gettext_msginit.patch @@ -0,0 +1,12 @@ +--- gettext-tools/src/msginit.c 2010-06-06 08:49:58.000000000 -0400 ++++ gettext-tools/src/msginit.c 2012-07-25 14:54:54.511533424 -0400 +@@ -1073,7 +1073,7 @@ + struct passwd *pwd; + + pwd = get_user_pwd (); +-#if HAVE_PWD_H ++#if HAVE_PWD_H && !defined(__ANDROID__) + if (pwd != NULL) + { + const char *fullname; + diff --git a/tools/android/depends/gettext/Makefile b/tools/android/depends/gettext/Makefile new file mode 100644 index 0000000000..85344e5402 --- /dev/null +++ b/tools/android/depends/gettext/Makefile @@ -0,0 +1,50 @@ +include ../Makefile.include +DEPS= ../Makefile.include 02-gettext_msginit.patch Makefile + +# lib name, version +LIBNAME=gettext +VERSION=0.18.1.1 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) build-aux/; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) \ + --disable-csharp --disable-native-java --disable-java --without-emacs \ + --disable-libasprintf --disable-openmp \ + --with-included-gettext \ + --with-included-glib \ + --with-included-libcroco \ + --with-included-libxml \ + --without-git --without-cvs \ + --disable-shared gl_cv_header_working_stdint_h=yes + +LIBDYLIB=$(PLATFORM)/gettext-tools/src/.libs/libgettextsrc.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p0 < ../02-gettext_msginit.patch + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/help2man/Makefile b/tools/android/depends/help2man/Makefile new file mode 100644 index 0000000000..e4c0d7ae35 --- /dev/null +++ b/tools/android/depends/help2man/Makefile @@ -0,0 +1,40 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=help2man +VERSION=1.38.2 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +LIBDYLIB=$(PLATFORM)/help2man + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/jasper/Makefile b/tools/android/depends/jasper/Makefile new file mode 100644 index 0000000000..aaa98868b7 --- /dev/null +++ b/tools/android/depends/jasper/Makefile @@ -0,0 +1,44 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=jasper +VERSION=1.900.1 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).zip +ARCHIVE_TOOL=unzip +ARCHIVE_TOOL_FLAGS= + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) acaux/ ;\ + ./configure --prefix=$(PREFIX) --host=$(HOST) + +LIBDYLIB=$(PLATFORM)/src/lib$(LIBNAME)/.libs/lib$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + mv $(SOURCE)/* $(PLATFORM) && rm -rf $(SOURCE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/jpeg/Makefile b/tools/android/depends/jpeg/Makefile new file mode 100644 index 0000000000..e781d74076 --- /dev/null +++ b/tools/android/depends/jpeg/Makefile @@ -0,0 +1,39 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=jpeg +VERSION=8b +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(LIBNAME)src.v$(VERSION).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) --host=$(HOST) + +LIBDYLIB=$(PLATFORM)/.libs/lib$(LIBNAME).so + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: $(LIBDYLIB) .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/libamplayer/Makefile b/tools/android/depends/libamplayer/Makefile new file mode 100644 index 0000000000..f11183a2c9 --- /dev/null +++ b/tools/android/depends/libamplayer/Makefile @@ -0,0 +1,14 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +all: .installed-$(PLATFORM) + +.installed-$(PLATFORM): $(DEPS) + mkdir -p $(PREFIX)/include/amlplayer + cp -rf libamplayer/include/* $(PREFIX)/include/amlplayer + touch $@ + +clean: + rm -f .installed-$(PLATFORM) + +distclean:: clean diff --git a/tools/android/depends/libamplayer/libamplayer/include/amports/aformat.h b/tools/android/depends/libamplayer/libamplayer/include/amports/aformat.h new file mode 100644 index 0000000000..25cb852b05 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/amports/aformat.h @@ -0,0 +1,89 @@ +/** +* @file aformat.h +* @brief Porting from decoder driver for audio format +* @author Tim Yao <timyao@amlogic.com> +* @version 1.0.0 +* @date 2011-02-24 +*/ +/* Copyright (C) 2007-2011, Amlogic Inc. +* All right reserved +* +*/ + +/* + * AMLOGIC Audio/Video streaming port driver. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the named License, + * or any later version. + * + * This program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Author: Tim Yao <timyao@amlogic.com> + * + */ + +#ifndef AFORMAT_H +#define AFORMAT_H + +typedef enum { + AFORMAT_UNKNOWN = -1, + AFORMAT_MPEG = 0, + AFORMAT_PCM_S16LE = 1, + AFORMAT_AAC = 2, + AFORMAT_AC3 = 3, + AFORMAT_ALAW = 4, + AFORMAT_MULAW = 5, + AFORMAT_DTS = 6, + AFORMAT_PCM_S16BE = 7, + AFORMAT_FLAC = 8, + AFORMAT_COOK = 9, + AFORMAT_PCM_U8 = 10, + AFORMAT_ADPCM = 11, + AFORMAT_AMR = 12, + AFORMAT_RAAC = 13, + AFORMAT_WMA = 14, + AFORMAT_WMAPRO = 15, + AFORMAT_PCM_BLURAY = 16, + AFORMAT_ALAC = 17, + AFORMAT_VORBIS = 18, + AFORMAT_AAC_LATM = 19, + AFORMAT_APE = 20, + AFORMAT_UNSUPPORT , + AFORMAT_MAX + +} aformat_t; + +#define AUDIO_EXTRA_DATA_SIZE (4096) +#define IS_AFMT_VALID(afmt) ((afmt > AFORMAT_UNKNOWN) && (afmt < AFORMAT_MAX)) + +#define IS_AUIDO_NEED_EXT_INFO(afmt) ((afmt == AFORMAT_ADPCM) \ + ||(afmt == AFORMAT_WMA) \ + ||(afmt == AFORMAT_WMAPRO) \ + ||(afmt == AFORMAT_PCM_S16BE) \ + ||(afmt == AFORMAT_PCM_S16LE) \ + ||(afmt == AFORMAT_PCM_U8) \ + ||(afmt == AFORMAT_PCM_BLURAY) \ + ||(afmt == AFORMAT_AMR)\ + ||(afmt == AFORMAT_ALAC)\ + ||(afmt == AFORMAT_AC3) \ + ||(afmt == AFORMAT_APE) \ + ||(afmt == AFORMAT_FLAC) ) + + +#define IS_AUDIO_NOT_SUPPORT_EXCEED_2CH(afmt) ((afmt == AFORMAT_RAAC) \ + ||(afmt == AFORMAT_COOK) \ + ||(afmt == AFORMAT_FLAC)) + +#define IS_AUIDO_NEED_PREFEED_HEADER(afmt) ((afmt == AFORMAT_VORBIS) ) + +#endif /* AFORMAT_H */ + diff --git a/tools/android/depends/libamplayer/libamplayer/include/amports/amstream.h b/tools/android/depends/libamplayer/libamplayer/include/amports/amstream.h new file mode 100644 index 0000000000..09f6a4a8a9 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/amports/amstream.h @@ -0,0 +1,148 @@ +/** +* @file amstream.h +* @brief Porting from decoder driver for codec ioctl commands +* @author Tim Yao <timyao@amlogic.com> +* @version 1.0.0 +* @date 2011-02-24 +*/ +/* Copyright (C) 2007-2011, Amlogic Inc. +* All right reserved +* +*/ + +/* + * AMLOGIC Audio/Video streaming port driver. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the named License, + * or any later version. + * + * This program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Author: Tim Yao <timyao@amlogic.com> + * + */ + +#ifndef AMSTREAM_H +#define AMSTREAM_H + +#define PORT_FLAG_IN_USE 0x0001 +#define PORT_FLAG_VFORMAT 0x0002 +#define PORT_FLAG_AFORMAT 0x0004 +#define PORT_FLAG_FORMAT (PORT_FLAG_VFORMAT | PORT_FLAG_AFORMAT) +#define PORT_FLAG_VID 0x0008 +#define PORT_FLAG_AID 0x0010 +#define PORT_FLAG_ID (PORT_FLAG_VID | PORT_FLAG_AID) +#define PORT_FLAG_INITED 0x100 + +#define PORT_TYPE_VIDEO 0x01 +#define PORT_TYPE_AUDIO 0x02 +#define PORT_TYPE_MPTS 0x04 +#define PORT_TYPE_MPPS 0x08 +#define PORT_TYPE_ES 0x10 +#define PORT_TYPE_RM 0x20 + +#define AMSTREAM_IOC_MAGIC 'S' + +#define AMSTREAM_IOC_VB_START _IOW(AMSTREAM_IOC_MAGIC, 0x00, int) +#define AMSTREAM_IOC_VB_SIZE _IOW(AMSTREAM_IOC_MAGIC, 0x01, int) +#define AMSTREAM_IOC_AB_START _IOW(AMSTREAM_IOC_MAGIC, 0x02, int) +#define AMSTREAM_IOC_AB_SIZE _IOW(AMSTREAM_IOC_MAGIC, 0x03, int) +#define AMSTREAM_IOC_VFORMAT _IOW(AMSTREAM_IOC_MAGIC, 0x04, int) +#define AMSTREAM_IOC_AFORMAT _IOW(AMSTREAM_IOC_MAGIC, 0x05, int) +#define AMSTREAM_IOC_VID _IOW(AMSTREAM_IOC_MAGIC, 0x06, int) +#define AMSTREAM_IOC_AID _IOW(AMSTREAM_IOC_MAGIC, 0x07, int) +#define AMSTREAM_IOC_VB_STATUS _IOR(AMSTREAM_IOC_MAGIC, 0x08, unsigned long) +#define AMSTREAM_IOC_AB_STATUS _IOR(AMSTREAM_IOC_MAGIC, 0x09, unsigned long) +#define AMSTREAM_IOC_SYSINFO _IOW(AMSTREAM_IOC_MAGIC, 0x0a, int) +#define AMSTREAM_IOC_ACHANNEL _IOW(AMSTREAM_IOC_MAGIC, 0x0b, int) +#define AMSTREAM_IOC_SAMPLERATE _IOW(AMSTREAM_IOC_MAGIC, 0x0c, int) +#define AMSTREAM_IOC_DATAWIDTH _IOW(AMSTREAM_IOC_MAGIC, 0x0d, int) +#define AMSTREAM_IOC_TSTAMP _IOW(AMSTREAM_IOC_MAGIC, 0x0e, unsigned long) +#define AMSTREAM_IOC_VDECSTAT _IOR(AMSTREAM_IOC_MAGIC, 0x0f, unsigned long) +#define AMSTREAM_IOC_ADECSTAT _IOR(AMSTREAM_IOC_MAGIC, 0x10, unsigned long) +#define AMSTREAM_IOC_PORT_INIT _IO(AMSTREAM_IOC_MAGIC, 0x11) +#define AMSTREAM_IOC_TRICKMODE _IOW(AMSTREAM_IOC_MAGIC, 0x12, unsigned long) +#define AMSTREAM_IOC_AUDIO_INFO _IOW(AMSTREAM_IOC_MAGIC, 0x13, unsigned long) +#define AMSTREAM_IOC_TRICK_STAT _IOR(AMSTREAM_IOC_MAGIC, 0x14, unsigned long) +#define AMSTREAM_IOC_AUDIO_RESET _IO(AMSTREAM_IOC_MAGIC, 0x15) +#define AMSTREAM_IOC_SID _IOW(AMSTREAM_IOC_MAGIC, 0x16, int) +#define AMSTREAM_IOC_VPAUSE _IOW(AMSTREAM_IOC_MAGIC, 0x17, int) +#define AMSTREAM_IOC_AVTHRESH _IOW(AMSTREAM_IOC_MAGIC, 0x18, int) +#define AMSTREAM_IOC_SYNCTHRESH _IOW(AMSTREAM_IOC_MAGIC, 0x19, int) +#define AMSTREAM_IOC_SUB_RESET _IOW(AMSTREAM_IOC_MAGIC, 0x1a, int) +#define AMSTREAM_IOC_SUB_LENGTH _IOR(AMSTREAM_IOC_MAGIC, 0x1b, unsigned long) +#define AMSTREAM_IOC_SET_DEC_RESET _IOW(AMSTREAM_IOC_MAGIC, 0x1c, int) +#define AMSTREAM_IOC_TS_SKIPBYTE _IOW(AMSTREAM_IOC_MAGIC, 0x1d, int) +#define AMSTREAM_IOC_SUB_TYPE _IOW(AMSTREAM_IOC_MAGIC, 0x1e, int) +#define AMSTREAM_IOC_APTS _IOR(AMSTREAM_IOC_MAGIC, 0x40, unsigned long) +#define AMSTREAM_IOC_VPTS _IOR(AMSTREAM_IOC_MAGIC, 0x41, unsigned long) +#define AMSTREAM_IOC_PCRSCR _IOR(AMSTREAM_IOC_MAGIC, 0x42, unsigned long) +#define AMSTREAM_IOC_SYNCENABLE _IOW(AMSTREAM_IOC_MAGIC, 0x43, unsigned long) +#define AMSTREAM_IOC_GET_SYNC_ADISCON _IOR(AMSTREAM_IOC_MAGIC, 0x44, unsigned long) +#define AMSTREAM_IOC_SET_SYNC_ADISCON _IOW(AMSTREAM_IOC_MAGIC, 0x45, unsigned long) +#define AMSTREAM_IOC_GET_SYNC_VDISCON _IOR(AMSTREAM_IOC_MAGIC, 0x46, unsigned long) +#define AMSTREAM_IOC_SET_SYNC_VDISCON _IOW(AMSTREAM_IOC_MAGIC, 0x47, unsigned long) +#define AMSTREAM_IOC_GET_VIDEO_DISABLE _IOR(AMSTREAM_IOC_MAGIC, 0x48, unsigned long) +#define AMSTREAM_IOC_SET_VIDEO_DISABLE _IOW(AMSTREAM_IOC_MAGIC, 0x49, unsigned long) +#define AMSTREAM_IOC_SET_PCRSCR _IOW(AMSTREAM_IOC_MAGIC, 0x4a, unsigned long) +#define AMSTREAM_IOC_GET_VIDEO_AXIS _IOR(AMSTREAM_IOC_MAGIC, 0x4b, unsigned long) +#define AMSTREAM_IOC_SET_VIDEO_AXIS _IOW(AMSTREAM_IOC_MAGIC, 0x4c, unsigned long) +#define AMSTREAM_IOC_SUB_NUM _IOR(AMSTREAM_IOC_MAGIC, 0x50, unsigned long) +#define AMSTREAM_IOC_SUB_INFO _IOR(AMSTREAM_IOC_MAGIC, 0x51, unsigned long) + +#define AMSTREAM_IOC_SET_DEMUX _IOW(AMSTREAM_IOC_MAGIC, 0x90, unsigned long) + +struct buf_status { + int size; + int data_len; + int free_len; + unsigned int read_pointer; + unsigned int write_pointer; +}; + + +struct vdec_status { + unsigned int width; + unsigned int height; + unsigned int fps; + unsigned int error_count; + unsigned int status; +}; + +struct adec_status { + unsigned int channels; + unsigned int sample_rate; + unsigned int resolution; + unsigned int error_count; + unsigned int status; +}; + +struct am_io_param { + union { + int data; + int id;//get bufstatus? //or others + }; + + int len; //buffer size; + + union { + char buf[1]; + struct buf_status status; + struct vdec_status vstatus; + struct adec_status astatus; + }; +}; +void set_vdec_func(int (*vdec_func)(struct vdec_status *)); +void set_adec_func(int (*adec_func)(struct adec_status *)); + +#endif /* AMSTREAM_H */ + diff --git a/tools/android/depends/libamplayer/libamplayer/include/amports/vformat.h b/tools/android/depends/libamplayer/libamplayer/include/amports/vformat.h new file mode 100644 index 0000000000..6ded0d47d2 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/amports/vformat.h @@ -0,0 +1,111 @@ +/** +* @file vformat.h +* @brief Porting from decoder driver for video format +* @author Tim Yao <timyao@amlogic.com> +* @version 1.0.0 +* @date 2011-02-24 +*/ +/* Copyright (C) 2007-2011, Amlogic Inc. +* All right reserved +* +*/ + +/* + * AMLOGIC Audio/Video streaming port driver. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the named License, + * or any later version. + * + * This program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Author: Tim Yao <timyao@amlogic.com> + * + */ + +#ifndef VFORMAT_H +#define VFORMAT_H + +typedef enum { + VIDEO_DEC_FORMAT_UNKNOW, + VIDEO_DEC_FORMAT_MPEG4_3, + VIDEO_DEC_FORMAT_MPEG4_4, + VIDEO_DEC_FORMAT_MPEG4_5, + VIDEO_DEC_FORMAT_H264, + VIDEO_DEC_FORMAT_MJPEG, + VIDEO_DEC_FORMAT_MP4, + VIDEO_DEC_FORMAT_H263, + VIDEO_DEC_FORMAT_REAL_8, + VIDEO_DEC_FORMAT_REAL_9, + VIDEO_DEC_FORMAT_WMV3, + VIDEO_DEC_FORMAT_WVC1, + VIDEO_DEC_FORMAT_SW, + VIDEO_DEC_FORMAT_MAX +} vdec_type_t; + +typedef enum { + VFORMAT_UNKNOWN = -1, + VFORMAT_MPEG12 = 0, + VFORMAT_MPEG4, + VFORMAT_H264, + VFORMAT_MJPEG, + VFORMAT_REAL, + VFORMAT_JPEG, + VFORMAT_VC1, + VFORMAT_AVS, + VFORMAT_SW, + VFORMAT_H264MVC, + VFORMAT_UNSUPPORT, + VFORMAT_MAX +} vformat_t; + +#define IS_VFMT_VALID(vfmt) ((vfmt > VFORMAT_UNKNOWN) && (vfmt < VFORMAT_MAX)) +#define IS_NEED_VDEC_INFO(vfmt) ((vfmt == VFORMAT_MPEG4) || (vfmt == VFORMAT_REAL)) + +#define CODEC_TAG_MJPEG (0x47504a4d) +#define CODEC_TAG_mjpeg (0x47504a4c) +#define CODEC_TAG_jpeg (0x6765706a) +#define CODEC_TAG_mjpa (0x61706a6d) +#define CODEC_TAG_XVID (0x44495658) +#define CODEC_TAG_xvid (0x64697678) +#define CODEC_TAG_XVIX (0x58495658) +#define CODEC_TAG_xvix (0x78697678) +#define CODEC_TAG_MP4 (0x8e22ada) +#define CODEC_TAG_COL1 (0x314c4f43) +#define CODEC_TAG_DIV3 (0x33564944) +#define CODEC_TAG_MP43 (0x3334504d) +#define CODEC_TAG_M4S2 (0x3253344d) +#define CODEC_TAG_DIV4 (0x34564944) +#define CODEC_TAG_DIVX (0x58564944) +#define CODEC_TAG_DIV5 (0x35564944) +#define CODEC_TAG_DX50 (0x30355844) +#define CODEC_TAG_DIV6 (0x36564944) +#define CODEC_TAG_RMP4 (0x34504d52) +#define CODEC_TAG_MP42 (0x3234504d) +#define CODEC_TAG_MPG4 (0x3447504d) +#define CODEC_TAG_MP4V (0x5634504d) +#define CODEC_TAG_mp4v (0x7634706d) +#define CODEC_TAG_AVC1 (0x31435641) +#define CODEC_TAG_avc1 (0x31637661) +#define CODEC_TAG_H264 (0x34363248) +#define CODEC_TAG_h264 (0x34363268) +#define CODEC_TAG_H263 (0x33363248) +#define CODEC_TAG_h263 (0x33363268) +#define CODEC_TAG_s263 (0x33363273) +#define CODEC_TAG_F263 (0x33363246) +#define CODEC_TAG_WMV1 (0x31564d57) +#define CODEC_TAG_WMV2 (0x32564d57) +#define CODEC_TAG_WMV3 (0x33564d57) +#define CODEC_TAG_WVC1 (0x31435657) +#define CODEC_TAG_WMVA (0x41564d57) +#define CODEC_TAG_FMP4 (0x34504d46) + +#endif /* VFORMAT_H */ diff --git a/tools/android/depends/libamplayer/libamplayer/include/log_print.h b/tools/android/depends/libamplayer/libamplayer/include/log_print.h new file mode 100644 index 0000000000..773727fe1e --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/log_print.h @@ -0,0 +1,40 @@ + +#ifndef PLAYER_LOG_H +#define PLAYER_LOG_H + +#define MAX_LOG_SIZE (20*1024) + +__attribute__ ((format (printf, 2, 3))) +void log_lprint(const int level, const char *fmt, ...); + + +#define AM_LOG_PANIC 0 +#define AM_LOG_FATAL 8 +#define AM_LOG_ERROR 16 +#define AM_LOG_WARNING 24 +#define AM_LOG_INFO 32 +#define AM_LOG_VERBOSE 40 +#define AM_LOG_DEBUG 60 +#define AM_LOG_DEBUG1 70 +#define AM_LOG_DEBUG2 80 +#define AM_LOG_TRACE 90 + + +#define log_print(fmt...) log_lprint(0,##fmt) +#define log_error(fmt...) log_lprint(AM_LOG_ERROR,##fmt) +#define log_warning(fmt...) log_lprint(AM_LOG_WARNING,##fmt) +#define log_info(fmt...) log_lprint(AM_LOG_INFO,##fmt) +/*default global_level=5, +if the level<global_level print out +*/ +#define log_debug(fmt...) log_lprint(AM_LOG_DEBUG,##fmt) +#define log_debug1(fmt...) log_lprint(AM_LOG_DEBUG1,##fmt) +#define log_debug2(fmt...) log_lprint(AM_LOG_DEBUG2,##fmt) +#define log_trace(fmt...) log_lprint(AM_LOG_TRACE,##fmt) + +#define DEBUG_PN() log_print("[%s:%d]\n", __FUNCTION__, __LINE__) + +void log_close(void); +int log_open(const char *name); +int update_loglevel_setting(void); +#endif diff --git a/tools/android/depends/libamplayer/libamplayer/include/message.h b/tools/android/depends/libamplayer/libamplayer/include/message.h new file mode 100644 index 0000000000..0ddedf1a2d --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/message.h @@ -0,0 +1,90 @@ +#ifndef PLAYER_MESSAGE_H +#define PLAYER_MESSAGE_H + +#define MESSAGE_MAX 4 + +#define CTRL_CMD_RESPONSE (0xffff) + +typedef enum { + CMD_EXIT = (1 << 0), + CMD_PLAY = (1 << 1), + CMD_PLAY_START = (1 << 2), + CMD_STOP = (1 << 3), + CMD_START = (1 << 4), + CMD_NEXT = (1 << 5), + CMD_PREV = (1 << 6), + CMD_PAUSE = (1 << 7), + CMD_RESUME = (1 << 8), + CMD_SEARCH = (1 << 9), + CMD_FF = (1 << 10), + CMD_FB = (1 << 11), + CMD_SWITCH_AID = (1 << 12), + CMD_SWITCH_SID = (1 << 13), + CMD_CTRL_MAX = (1 << 31), +} ctrl_cmd_t; + +typedef enum { + CMD_LOOP = (1 << 0), + CMD_NOLOOP = (1 << 1), + CMD_BLACKOUT = (1 << 2), + CMD_NOBLACK = (1 << 3), + CMD_NOAUDIO = (1 << 4), + CMD_NOVIDEO = (1 << 5), + CMD_MUTE = (1 << 6), + CMD_UNMUTE = (1 << 7), + CMD_SET_VOLUME = (1 << 8), + CMD_SPECTRUM_SWITCH = (1 << 9), + CMD_SET_BALANCE = (1 << 10), + CMD_SWAP_LR = (1 << 11), + CMD_LEFT_MONO = (1 << 12), + CMD_RIGHT_MONO = (1 << 13), + CMD_SET_STEREO = (1 << 14), + CMD_EN_AUTOBUF = (1 << 15), + CMD_SET_AUTOBUF_LEV = (1 << 16), + CMD_MODE_MAX = (1 << 31), +} ctrl_mode_t; + +typedef enum { + CMD_GET_VOLUME = (1 << 0), + CMD_GET_VOL_RANGE = (1 << 1), + CMD_GET_PLAY_STA = (1 << 2), + CMD_GET_CURTIME = (1 << 3), + CMD_GET_DURATION = (1 << 4), + CMD_GET_MEDIA_INFO = (1 << 5), + CMD_LIST_PID = (1 << 6), + CMD_GET_MAX = (1 << 31), +} get_info_t; + +typedef struct { + float min; + float max; +} volume_range_t; + +typedef struct { + ctrl_cmd_t ctrl_cmd; + get_info_t info_cmd; + ctrl_mode_t set_mode; + int pid; + int cid; + union { + char *filename; + char *file_list; + int param; + float f_param; + }; + union { + int param1; + float f_param1; + }; + union { + int param2; + float f_param2; + }; +} player_cmd_t; + +int message_free(player_cmd_t * cmd); +player_cmd_t * message_alloc(void); +int cmd2str(player_cmd_t *cmd, char *buf); + +#endif + diff --git a/tools/android/depends/libamplayer/libamplayer/include/player.h b/tools/android/depends/libamplayer/libamplayer/include/player.h new file mode 100644 index 0000000000..b3eedc98b5 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/player.h @@ -0,0 +1,80 @@ +#ifndef _PLAYER_H_ +#define _PLAYER_H_ + + +#include <codec.h> +#include <player_type.h> +#include <player_error.h> +#include <message.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +int player_init(); +int player_start(play_control_t *p,unsigned long priv); +int player_stop(int pid); +int player_stop_async(int pid); +int player_exit(int pid); +int player_pause(int pid); +int player_resume(int pid); +int player_timesearch(int pid,float s_time); +int player_forward(int pid,int speed); +int player_backward(int pid,int speed); +int player_aid(int pid,int audio_id); +int player_sid(int pid,int sub_id); +int player_progress_exit(void); +int player_list_allpid(pid_info_t *pid); +int check_pid_valid(int pid); +int player_get_play_info(int pid,player_info_t *info); +int player_get_media_info(int pid,media_info_t *minfo); +int player_video_overlay_en(unsigned enable); +int player_start_play(int pid); +int player_send_message(int pid, player_cmd_t *cmd); +player_status player_get_state(int pid); +unsigned int player_get_extern_priv(int pid); +int player_enable_autobuffer(int pid, int enable); +int player_set_autobuffer_level(int pid, float min, float middle, float max); + +int audio_set_mute(int pid,int mute); +int audio_get_volume_range(int pid,float *min,float *max); +int audio_set_volume(int pid,float val); +int audio_get_volume(int pid, float *val); + +int audio_set_lrvolume(int pid,float lvol,float rvol); +int audio_get_lrvolume(int pid, float* lvol,float* rvol); + +int audio_set_volume_balance(int pid,int balance); +int audio_swap_left_right(int pid); +int audio_left_mono(int pid); +int audio_right_mono(int pid); +int audio_stereo(int pid); +int audio_set_spectrum_switch(int pid,int isStart,int interval); +int player_register_update_callback(callback_t *cb,update_state_fun_t up_fn,int interval_s); +char *player_status2str(player_status status); +int player_cache_system_init(int enable,const char*dir,int max_size,int block_size); + +//control interface +int player_loop(int pid); +int player_noloop(int pid); + +int check_url_type(char *filename); +int play_list_player(play_control_t *pctrl,unsigned long priv); + +//freescale +int enable_freescale(int cfg); +int disable_freescale(int cfg); +int disable_freescale_MBX(); +int enable_2Xscale(); +int enable_2XYscale(); +int enable_freescale_MBX(); +int disable_2X_2XYscale(); +int GL_2X_scale(int mSwitch); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/tools/android/depends/libamplayer/libamplayer/include/player_error.h b/tools/android/depends/libamplayer/libamplayer/include/player_error.h new file mode 100644 index 0000000000..0d222118f6 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/player_error.h @@ -0,0 +1,63 @@ +#ifndef _PLAYER_ERROR_H_ +#define _PLAYER_ERROR_H_ + +#define P_PRE (0x02000000) +#define F_PRE (0x03000000) +#define X_PRE (0x04000000) +#define D_PRE (0x05000000) + +#define PLAYER_SUCCESS (0) +#define PLAYER_FAILED (-(P_PRE|0x01)) +#define PLAYER_NOMEM (-(P_PRE|0x02)) +#define PLAYER_EMPTY_P (-(P_PRE|0x03)) +#define PLAYER_NOT_VALID_PID (-(P_PRE|0x04)) +#define PLAYER_CAN_NOT_CREAT_THREADS (-(P_PRE|0x05)) +#define PLAYER_ERROR_PARAM (-(P_PRE|0x06)) +#define PLAYER_ERROR_CALLBACK (-(P_PRE|0x07)) + +#define PLAYER_RD_FAILED (-(P_PRE|0x11)) +#define PLAYER_RD_EMPTYP (-(P_PRE|0x12)) +#define PLAYER_RD_TIMEOUT (-(P_PRE|0x13)) +#define PLAYER_RD_AGAIN (-(P_PRE|0x14)) + +#define PLAYER_WR_FAILED (-(P_PRE|0x21)) +#define PLAYER_WR_EMPTYP (-(P_PRE|0x22)) +#define PLAYER_WR_AGAIN (-(P_PRE|0x23)) +#define PLAYER_WR_FINISH (P_PRE|0x1) + +#define PLAYER_PTS_ERROR (-(P_PRE|0x31)) +#define PLAYER_NO_DECODER (-(P_PRE|0x32)) +#define DECODER_RESET_FAILED (-(P_PRE|0x33)) +#define DECODER_INIT_FAILED (-(P_PRE|0x34)) +#define PLAYER_UNSUPPORT (-(P_PRE|0x35)) +#define PLAYER_UNSUPPORT_VIDEO (-(P_PRE|0x36)) +#define PLAYER_UNSUPPORT_AUDIO (-(P_PRE|0x37)) +#define PLAYER_SEEK_OVERSPILL (-(P_PRE|0x38)) +#define PLAYER_CHECK_CODEC_ERROR (-(P_PRE|0x39)) +#define PLAYER_INVALID_CMD (-(P_PRE|0x40)) +#define PLAYER_REAL_AUDIO_FAILED (-(P_PRE|0x41)) +#define PLAYER_ADTS_NOIDX (-(P_PRE|0x42)) +#define PLAYER_SEEK_FAILED (-(P_PRE|0x43)) +#define PLAYER_NO_VIDEO (-(P_PRE|0x44)) +#define PLAYER_NO_AUDIO (-(P_PRE|0x45)) +#define PLAYER_SET_NOVIDEO (-(P_PRE|0x46)) +#define PLAYER_SET_NOAUDIO (-(P_PRE|0x47)) +#define PLAYER_FFFB_UNSUPPORT (-(P_PRE|0x48)) +#define PLAYER_UNSUPPORT_VCODEC (-(P_PRE|0x49)) +#define PLAYER_UNSUPPORT_ACODEC (-(P_PRE|0x4a)) + +#define FFMPEG_SUCCESS (0) +#define FFMPEG_OPEN_FAILED (-(F_PRE|0x1)) +#define FFMPEG_PARSE_FAILED (-(F_PRE|0x2)) +#define FFMPEG_EMP_POINTER (-(F_PRE|0x3)) +#define FFMPEG_NO_FILE (-(F_PRE|0x4)) + +#define DIVX_SUCCESS (0) +#define DIVX_AUTHOR_ERR (-(X_PRE|0x1)) +#define DIVX_EXPIRED (-(X_PRE|0x2)) + +#define DRM_NOERROR (0) +#define DRM_UNSUPPORT (-(D_PRE|0x1)) + +char * player_error_msg(int error); +#endif diff --git a/tools/android/depends/libamplayer/libamplayer/include/player_id.h b/tools/android/depends/libamplayer/libamplayer/include/player_id.h new file mode 100644 index 0000000000..45ae74d4c5 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/player_id.h @@ -0,0 +1,14 @@ +#ifndef PLAYER_ID_MGT__ +#define PLAYER_ID_MGT__ + +int player_request_pid(void); +int player_release_pid(int pid); +int player_init_pid_data(int pid,void * data); +void * player_open_pid_data(int pid); +int player_close_pid_data(int pid); +int player_id_pool_init(void); +int player_list_pid(char id[],int size); + +#endif + + diff --git a/tools/android/depends/libamplayer/libamplayer/include/player_set_sys.h b/tools/android/depends/libamplayer/libamplayer/include/player_set_sys.h new file mode 100644 index 0000000000..c47dfd2b05 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/player_set_sys.h @@ -0,0 +1,80 @@ +#ifndef _PLAYER_SET_DISP_H_ +#define _PLAYER_SET_DISP_H_ + +#define MID_800_400_FREESCALE (0x10001) //mid 800*400 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + DISP_MODE_480I = 1, + DISP_MODE_480P = 2, + DISP_MODE_576I = 3, + DISP_MODE_576P = 4, + DISP_MODE_720P = 5, + DISP_MODE_1080I = 6, + DISP_MODE_1080P = 7 +} display_mode; + +typedef struct { + display_mode disp_mode; + int osd_disble_coordinate[8]; + int osd_enable_coordinate[8]; + int video_enablecoordinate[4]; + int fb0_freescale_width; + int fb0_freescale_height; + int fb1_freescale_width; + int fb1_freescale_height; +} freescale_setting_t; + + + +int set_sysfs_str(const char *path, const char *val); +int get_sysfs_str(const char *path, char *valstr, int size); +int set_sysfs_int(const char *path, int val); +int get_sysfs_int(const char *path); + +int set_black_policy(int blackout); +int get_black_policy(); +int get_karaok_flag(); +int set_tsync_enable(int enable); +int set_tsync_discontinue(int enable); +int get_pts_discontinue(); +int set_fb0_blank(int blank); +int set_fb1_blank(int blank); +int set_subtitle_num(int num); +int av_get_subtitle_curr(); +int set_subtitle_startpts(int pts); +int set_subtitle_fps(int fps); +int set_subtitle_subtype(int subtype); +void get_display_mode(char *mode); +int set_fb0_freescale(int freescale); +int set_fb1_freescale(int freescale); +int set_display_axis(int *coordinate); +int set_video_axis(int *coordinate); +int set_fb0_scale_width(int width); +int set_fb0_scale_height(int height); +int set_fb1_scale_width(int width); +int set_fb1_scale_height(int height); +int check_audiodsp_fatal_err(void); +int set_stb_source_hiu(void); +int set_stb_demux_source_hiu(void); +int get_stb_demux_source(char *strval, int size); +int get_stb_source(char *strval, int size); + +int set_subtitle_enable(int num); +int set_subtitle_curr(int num); +int check_file_same(char *filename2); + +//player sysfs API channel +int set_amutils_enable(int isOn); +int set_amutils_cmd(const char* cmd); +int get_amutils_cmd(char* cmd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/android/depends/libamplayer/libamplayer/include/player_thumbnail.h b/tools/android/depends/libamplayer/libamplayer/include/player_thumbnail.h new file mode 100644 index 0000000000..d1387e2a00 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/player_thumbnail.h @@ -0,0 +1,27 @@ +#ifndef PLAYER_THUMBNAIL_H +#define PLAYER_THUMBNAIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +void * thumbnail_res_alloc(void); +int thumbnail_find_stream_info(void *handle, const char* filename); +int thumbnail_find_stream_info_end(void *handle); +int thumbnail_decoder_open(void *handle, const char* filename); +int thumbnail_extract_video_frame(void * handle, int64_t time, int flag); +int thumbnail_read_frame(void *handle, char* buffer); +void thumbnail_get_video_size(void *handle, int* width, int* height); +float thumbnail_get_aspect_ratio(void *handle); +void thumbnail_get_duration(void *handle, int64_t *duration); +int thumbnail_get_key_metadata(void* handle, char* key, const char** value); +int thumbnail_get_key_data(void* handle, char* key, const void** data, int* data_size); +void thumbnail_get_video_rotation(void *handle, int* rotation); +int thumbnail_decoder_close(void *handle); +void thumbnail_res_free(void* handle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/android/depends/libamplayer/libamplayer/include/player_type.h b/tools/android/depends/libamplayer/libamplayer/include/player_type.h new file mode 100644 index 0000000000..2abd1940f3 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/player_type.h @@ -0,0 +1,271 @@ +#ifndef _PLAYER_TYPE_H_ +#define _PLAYER_TYPE_H_ + +#include <libavformat/avformat.h> +#include <stream_format.h> + +#define MSG_SIZE 64 +#define MAX_VIDEO_STREAMS 8 +#define MAX_AUDIO_STREAMS 8 +#define MAX_SUB_INTERNAL 8 +#define MAX_SUB_EXTERNAL 24 +#define MAX_SUB_STREAMS (MAX_SUB_INTERNAL + MAX_SUB_EXTERNAL) +#define MAX_PLAYER_THREADS 32 + +#define CALLBACK_INTERVAL (300) + +//#define DEBUG_VARIABLE_DUR + +typedef enum +{ + /****************************** + * 0x1000x: + * player do parse file + * decoder not running + ******************************/ + PLAYER_INITING = 0x10001, + PLAYER_TYPE_REDY = 0x10002, + PLAYER_INITOK = 0x10003, + + /****************************** + * 0x2000x: + * playback status + * decoder is running + ******************************/ + PLAYER_RUNNING = 0x20001, + PLAYER_BUFFERING = 0x20002, + PLAYER_PAUSE = 0x20003, + PLAYER_SEARCHING = 0x20004, + + PLAYER_SEARCHOK = 0x20005, + PLAYER_START = 0x20006, + PLAYER_FF_END = 0x20007, + PLAYER_FB_END = 0x20008, + + PLAYER_PLAY_NEXT = 0x20009, + PLAYER_BUFFER_OK = 0x2000a, + PLAYER_FOUND_SUB = 0x2000b, + + /****************************** + * 0x3000x: + * player will exit + ******************************/ + PLAYER_ERROR = 0x30001, + PLAYER_PLAYEND = 0x30002, + PLAYER_STOPED = 0x30003, + PLAYER_EXIT = 0x30004, + + /****************************** + * 0x4000x: + * divx drm + * decoder will exit or give + * a message dialog + * ****************************/ + PLAYER_DIVX_AUTHORERR = 0x40001, + PLAYER_DIVX_RENTAL_EXPIRED = 0x40002, + PLAYER_DIVX_RENTAL_VIEW = 0x40003, + + +}player_status; + + +typedef struct +{ + int index; + int id; + int width; + int height; + int aspect_ratio_num; + int aspect_ratio_den; + int frame_rate_num; + int frame_rate_den; + int bit_rate; + vformat_t format; + int duartion; + unsigned int video_rotation_degree; +}mvideo_info_t; + +typedef enum +{ + ACOVER_NONE = 0, + ACOVER_JPG , + ACOVER_PNG , +}audio_cover_type; + +typedef struct +{ + char title[512]; + char author[512]; + char album[512]; + char comment[512]; + char year[4]; + int track; + char genre[32]; + char copyright[512]; + audio_cover_type pic; +}audio_tag_info; + +typedef struct +{ + int id; + int channel; + int sample_rate; + int bit_rate; + aformat_t aformat; + int duration; + audio_tag_info *audio_tag; +}maudio_info_t; + +typedef struct +{ + char id; + char internal_external; //0:internal_sub 1:external_sub + unsigned short width; + unsigned short height; + unsigned int sub_type; + char resolution; + long long subtitle_size; + char *sub_language; +}msub_info_t; + +typedef struct +{ + char *filename; + int duration; + long long file_size; + pfile_type type; + int bitrate; + int has_video; + int has_audio; + int has_sub; + int nb_streams; + int total_video_num; + int cur_video_index; + int total_audio_num; + int cur_audio_index; + int total_sub_num; + int cur_sub_index; + int seekable; + int drm_check; +}mstream_info_t; + +typedef struct +{ + mstream_info_t stream_info; + mvideo_info_t *video_info[MAX_VIDEO_STREAMS]; + maudio_info_t *audio_info[MAX_AUDIO_STREAMS]; + msub_info_t *sub_info[MAX_SUB_STREAMS]; +}media_info_t; + +typedef struct player_info +{ + char *name; + player_status last_sta; + player_status status; /*stop,pause */ + int full_time; /*Seconds */ + int full_time_ms; /* mSeconds */ + int current_time; /*Seconds */ + int current_ms; /*ms*/ + int last_time; + int error_no; + int start_time; + int first_time; + int pts_video; + //int pts_pcrscr; + unsigned int current_pts; + long curtime_old_time; + unsigned int video_error_cnt; + unsigned int audio_error_cnt; + float audio_bufferlevel; // relative value + float video_bufferlevel; // relative value + int64_t bufed_pos; + int bufed_time;/* Second*/ + unsigned int drm_rental; +}player_info_t; + +typedef struct pid_info +{ + int num; + int pid[MAX_PLAYER_THREADS]; +}pid_info_t; + +typedef struct player_file_type +{ + const char *fmt_string; + int video_tracks; + int audio_tracks; + int subtitle_tracks; + /**/ +}player_file_type_t; + + +#define STATE_PRE(sta) (sta>>16) +#define PLAYER_THREAD_IS_INITING(sta) (STATE_PRE(sta)==0x1) +#define PLAYER_THREAD_IS_RUNNING(sta) (STATE_PRE(sta)==0x2) +#define PLAYER_THREAD_IS_STOPPED(sta) (STATE_PRE(sta)==0x3) + +typedef int (*update_state_fun_t)(int pid,player_info_t *) ; +typedef int (*notify_callback)(int pid,int msg,unsigned long ext1,unsigned long ext2); +typedef enum +{ + PLAYER_EVENTS_PLAYER_INFO=1, ///<ext1=player_info*,ext2=0,same as update_statue_callback + PLAYER_EVENTS_STATE_CHANGED, ///<ext1=new_state,ext2=0, + PLAYER_EVENTS_ERROR, ///<ext1=error_code,ext2=message char * + PLAYER_EVENTS_BUFFERING, ///<ext1=buffered=d,d={0-100},ext2=0, + PLAYER_EVENTS_FILE_TYPE, ///<ext1=player_file_type_t*,ext2=0 +}player_events; + +typedef struct +{ + update_state_fun_t update_statue_callback; + int update_interval; + long callback_old_time; + notify_callback notify_fn; +}callback_t; + +typedef struct + { + char *file_name; //file url + char *headers; //file name's authentication information,maybe used in network streaming + //List *play_list; + int video_index; //video track, no assigned, please set to -1 + int audio_index; //audio track, no assigned, please set to -1 + int sub_index; //subtitle track, no assigned, please set to -1 + int t_pos; //start postion, use second as unit + int read_max_cnt; //read retry maxium counts, if exceed it, return error + int avsync_threshold; //for adec av sync threshold in ms + union + { + struct{ + unsigned int loop_mode:1; //file loop mode 0:loop 1:not loop + unsigned int nosound:1; //0:play with audio 1:play without audio + unsigned int novideo:1; //0:play with video 1:play without video + unsigned int hassub:1; //0:ignore subtitle 1:extract subtitle if have + unsigned int need_start:1;/*If set need_start, we need call player_start_play to playback*/ + #ifdef DEBUG_VARIABLE_DUR + unsigned int is_variable:1; //0:extrack duration from header 1:update duration during playback + #endif + unsigned int displast_frame : 1;//0:black out when player exit 1:keep last frame when player exit + }; + int mode; //no use + }; + callback_t callback_fn; //callback function + int byteiobufsize; //byteio buffer size used in ffmpeg + int loopbufsize; //loop buffer size used in ffmpeg + int enable_rw_on_pause; //no use + /* + data%<min && data% <max enter buffering; + data% >middle exit buffering; + */ + int auto_buffing_enable; //auto buffering switch + float buffing_min; //auto buffering low limit + float buffing_middle; //auto buffering middle limit + float buffing_max; //auto buffering high limit + int is_playlist; //no use + int is_type_parser; //is try to get file type + int buffing_starttime_s; //for rest buffing_middle,buffering seconds data to start. + int buffing_force_delay_s; + int reserved [56]; //reserved for furthur used,some one add more ,can del reserved num + }play_control_t; + +#endif diff --git a/tools/android/depends/libamplayer/libamplayer/include/stream_format.h b/tools/android/depends/libamplayer/libamplayer/include/stream_format.h new file mode 100644 index 0000000000..5444f528eb --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/stream_format.h @@ -0,0 +1,43 @@ +#ifndef _STREAM_FORMAT_H_ +#define _STREAM_FORMAT_H_ + +#include "amports/vformat.h" +#include "amports/aformat.h" + +typedef enum +{ + NONE = 0, + ID3V1, + ID3V2, + APEV1, + APEV2, + WMATAG, + MPEG4TAG, +}audio_tag_type; + +typedef enum +{ + UNKNOWN_FILE = 0, + AVI_FILE = 1, + MPEG_FILE = 2, + WAV_FILE = 3, + MP3_FILE = 4, + AAC_FILE = 5, + AC3_FILE = 6, + RM_FILE = 7, + DTS_FILE = 8, + MKV_FILE = 9, + MOV_FILE = 10, + MP4_FILE = 11, + FLAC_FILE = 12, + H264_FILE = 13, + M2V_FILE = 14, + FLV_FILE = 15, + P2P_FILE = 16, + ASF_FILE = 17, + STREAM_FILE = 18, + APE_FILE = 19, + FILE_MAX = 20, +}pfile_type; + +#endif diff --git a/tools/android/depends/libass/Makefile b/tools/android/depends/libass/Makefile new file mode 100644 index 0000000000..c02f5972cb --- /dev/null +++ b/tools/android/depends/libass/Makefile @@ -0,0 +1,45 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libass +VERSION=0.9.11 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.bz2 + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) + +LIBDYLIB=$(PLATFORM)/$(LIBNAME)/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libass.la $(PREFIX)/lib/libass.so $(PREFIX)/lib/libass.so.4 + mv -f $(PREFIX)/lib/libass.so.4.1.0 $(PREFIX)/lib/libass.so + $(RPL) -e "libass.so.4" "libass.so\x00\x00" $(PREFIX)/lib/libass.so + -$(READELF) --dynamic $(PREFIX)/lib/libass.so | grep ibrary + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libbluray/Makefile b/tools/android/depends/libbluray/Makefile new file mode 100644 index 0000000000..ca4e428a70 --- /dev/null +++ b/tools/android/depends/libbluray/Makefile @@ -0,0 +1,46 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libbluray +VERSION=0.2.1 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.bz2 + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) --exec-prefix=$(PREFIX) --host=$(HOST) \ + --disable-examples --disable-doxygen-doc + +LIBDYLIB=$(PLATFORM)/src/.libs/libbluray.so.1.0.0 + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + # libbluray has borked Makefile.am with respect to CFLAGS, remove the offending line + sed -i -e "s|CFLAGS=|#CFLAGS=|" $(PLATFORM)/src/Makefile.am + sed -i -e "s|CFLAGS=|#CFLAGS=|" $(PLATFORM)/src/examples/Makefile.am + cd $(PLATFORM); ./bootstrap + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libbluray.la $(PREFIX)/lib/libbluray.so $(PREFIX)/lib/libbluray.so.1 + mv -f $(PREFIX)/lib/libbluray.so.1.0.0 $(PREFIX)/lib/libbluray.so + $(RPL) -e "libbluray.so.1" "libbluray.so\x00\x00" $(PREFIX)/lib/libbluray.so + -$(READELF) --dynamic $(PREFIX)/lib/libbluray.so | grep ibrary + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/libcdio/Makefile b/tools/android/depends/libcdio/Makefile new file mode 100644 index 0000000000..7532085701 --- /dev/null +++ b/tools/android/depends/libcdio/Makefile @@ -0,0 +1,47 @@ +include ../Makefile.include +DEPS= ../Makefile.include configure.patch Makefile + +# lib name, version +LIBNAME=libcdio +VERSION=0.82 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --without-cd-drive --without-cd-info --without-cd-paranoia \ + --without-cdda-player --without-cd-read --without-iso-info --without-iso-read --disable-example-progs \ + --disable-cpp-progs --without-cd-drive --without-cd-info --without-cd-paranoia --without-cdda-player \ + --without-cd-read --without-iso-info --without-iso-read --disable-shared + +LIBDYLIB=$(PLATFORM)/lib/driver/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p0 < ../configure.patch + cd $(PLATFORM); $(AUTORECONF) -vif + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + cp $(PLATFORM)/include/cdio/cdtext.h $(PREFIX)/include/cdio/ + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libcdio/configure.patch b/tools/android/depends/libcdio/configure.patch new file mode 100644 index 0000000000..a4110ef9cb --- /dev/null +++ b/tools/android/depends/libcdio/configure.patch @@ -0,0 +1,11 @@ +--- configure.ac 2012-05-27 15:06:13.044747493 -0400 ++++ configure.ac 2012-05-27 15:05:52.364747505 -0400 +@@ -378,7 +378,7 @@ + ;; + linux*|uclinux) + AC_CHECK_HEADERS(linux/version.h linux/major.h) +- AC_CHECK_HEADERS(linux/cdrom.h, [have_linux_cdrom_h="yes"]) ++ AC_CHECK_HEADERS(linux/cdrom.h, [have_linux_cdrom_h="no"]) + if test "x$have_linux_cdrom_h" = "xyes" ; then + AC_TRY_COMPILE(,[ + #include <linux/cdrom.h> diff --git a/tools/android/depends/libcec/Makefile b/tools/android/depends/libcec/Makefile new file mode 100644 index 0000000000..2c9565bae2 --- /dev/null +++ b/tools/android/depends/libcec/Makefile @@ -0,0 +1,44 @@ +include ../Makefile.include +DEPS= ../Makefile.include android.patch Makefile + +# lib name, version +LIBNAME=libcec +VERSION=1.5.2 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) --host=$(HOST) \ + ac_cv_search_dlopen=yes + +LIBDYLIB=$(PLATFORM)/src/lib/.libs/libcec.so.1.0.5 + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 < ../android.patch + cd $(PLATFORM); $(AUTORECONF) -vif + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM)/src/lib + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM)/src/lib install + rm -f $(PREFIX)/lib/libcec.la $(PREFIX)/lib/libcec.so $(PREFIX)/lib/libcec.so.1 + mv -f $(PREFIX)/lib/libcec.so.1.0.5 $(PREFIX)/lib/libcec.so + $(RPL) -e "libcec.so.1" "libcec.so\x00\x00" $(PREFIX)/lib/libcec.so + -$(READELF) --dynamic $(PREFIX)/lib/libcec.so | grep ibrary + touch $@ + +clean: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libcec/android.patch b/tools/android/depends/libcec/android.patch new file mode 100644 index 0000000000..200c5a1482 --- /dev/null +++ b/tools/android/depends/libcec/android.patch @@ -0,0 +1,10 @@ +--- armeabi-v7a/configure.ac 2012-06-04 00:15:13.054345341 -0400 ++++ armeabi-v7a-good/configure.ac 2012-06-04 00:15:28.624345331 -0400 +@@ -8,7 +8,6 @@ + case "${host}" in + *-*-linux*) + PKG_CHECK_MODULES([UDEV],[libudev],,[has_libudev="no";AC_MSG_WARN("library 'udev' is missing - adapter detection will not be available")]) +- LIBS+=" -lrt" + ;; + *-apple-darwin*) + has_libudev="no"; diff --git a/tools/android/depends/libffi/Makefile b/tools/android/depends/libffi/Makefile new file mode 100644 index 0000000000..26a56e1f03 --- /dev/null +++ b/tools/android/depends/libffi/Makefile @@ -0,0 +1,39 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libffi +VERSION=3.0.11 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE= ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared --disable-builddir + +LIBDYLIB=$(PLATFORM)/.libs/$(LIBNAME).a + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -j 1 -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + mkdir -p $(PREFIX)/include/ffi + cp $(PREFIX)/lib/$(SOURCE)/include/* $(PREFIX)/include/ffi/ + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed + +distclean:: + rm -rf $(PLATFORM) .installed diff --git a/tools/android/depends/libflac/Makefile b/tools/android/depends/libflac/Makefile new file mode 100644 index 0000000000..c88ea559df --- /dev/null +++ b/tools/android/depends/libflac/Makefile @@ -0,0 +1,48 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile nasm.patch + +# lib name, version +LIBNAME=flac +VERSION=1.2.1 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz +export NASM= +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-xmms-plugin --disable-cpplibs + +LIBDYLIB=$(PLATFORM)/src/libFLAC/.libs/libFLAC.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p0 < ../nasm.patch + cd $(PLATFORM); $(AUTOCONF) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libFLAC.la $(PREFIX)/lib/libFLAC.so $(PREFIX)/lib/libFLAC.so.8 + mv -f $(PREFIX)/lib/libFLAC.so.8.2.0 $(PREFIX)/lib/libxbFLAC.so + ln -sf $(PREFIX)/lib/libxbFLAC.so $(PREFIX)/lib/libFLAC.so + $(RPL) -e "libFLAC.so.8" "libxbFLAC.so" $(PREFIX)/lib/libxbFLAC.so + -$(READELF) --dynamic $(PREFIX)/lib/libxbFLAC.so | grep ibrary + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libflac/nasm.patch b/tools/android/depends/libflac/nasm.patch new file mode 100644 index 0000000000..0371cb9e0e --- /dev/null +++ b/tools/android/depends/libflac/nasm.patch @@ -0,0 +1,14 @@ +diff -ruN configure.in configure.in +--- configure.in 2007-09-13 11:48:42.000000000 -0400 ++++ configure.in 2012-06-10 20:13:50.543973093 -0400 +@@ -269,10 +269,6 @@ + # only matters for x86 + AC_CHECK_PROGS(NASM, nasm) + AM_CONDITIONAL(FLaC__HAS_NASM, test -n "$NASM") +-if test -n "$NASM" ; then +-AC_DEFINE(FLAC__HAS_NASM) +-AH_TEMPLATE(FLAC__HAS_NASM, [define if you are compiling for x86 and have the NASM assembler]) +-fi + + # only matters for PowerPC + AC_CHECK_PROGS(AS, as, as) diff --git a/tools/android/depends/libgcrypt/01-gcrypt-android-select.patch b/tools/android/depends/libgcrypt/01-gcrypt-android-select.patch new file mode 100644 index 0000000000..2e26a211cb --- /dev/null +++ b/tools/android/depends/libgcrypt/01-gcrypt-android-select.patch @@ -0,0 +1,13 @@ +--- libgcrypt-1.4.0/src/gcrypt.h 2007-12-10 10:05:46.000000000 +0100 ++++ libgcrypt-1.4.0.new/src/gcrypt.h 2011-11-13 12:12:23.000000000 +0100 +@@ -37,6 +37,10 @@ + # include <sys/socket.h> + #endif /*!_WIN32*/ + ++#if defined(__ANDROID__) ++#include <sys/select.h> ++#endif ++ + typedef socklen_t gcry_socklen_t; + + #include <sys/time.h> diff --git a/tools/android/depends/libgcrypt/Makefile b/tools/android/depends/libgcrypt/Makefile new file mode 100644 index 0000000000..4807eff051 --- /dev/null +++ b/tools/android/depends/libgcrypt/Makefile @@ -0,0 +1,48 @@ +include ../Makefile.include +DEPS= ../Makefile.include 01-gcrypt-android-select.patch gcrypt-disable-tests.patch Makefile + +# lib name, version +LIBNAME=libgcrypt +VERSION=1.4.0 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.bz2 + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared \ + ac_cv_path_GPG_ERROR_CONFIG=$(PREFIX)/bin/gpg-error-config +# ac_cv_sys_symbol_underscore=no \ + +ifeq ($(PLATFORM),x86) +CONFIGURE+=--disable-asm +endif + +LIBDYLIB=$(PLATFORM)/src/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 < ../gcrypt-disable-tests.patch + cd $(PLATFORM); $(CONFIGURE) + cd $(PLATFORM); patch -p1 < ../01-gcrypt-android-select.patch + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/libgcrypt/gcrypt-disable-tests.patch b/tools/android/depends/libgcrypt/gcrypt-disable-tests.patch new file mode 100644 index 0000000000..9ff4445d3f --- /dev/null +++ b/tools/android/depends/libgcrypt/gcrypt-disable-tests.patch @@ -0,0 +1,24 @@ +diff -ruN libgcrypt-1.4.0/Makefile.am libgcrypt-1.4.0-good//Makefile.am +--- libgcrypt-1.4.0/Makefile.am 2007-05-04 06:11:28.000000000 -0400 ++++ libgcrypt-1.4.0-good//Makefile.am 2012-04-27 15:13:42.526381700 -0400 +@@ -23,7 +23,7 @@ + --enable-ciphers=arcfour:blowfish:cast5:des:aes:twofish:serpent:rfc2268:seed:camellia + + DIST_SUBDIRS = m4 mpi cipher src doc tests +-SUBDIRS = mpi cipher src doc tests ++SUBDIRS = mpi cipher src + EXTRA_DIST = BUGS autogen.sh README.SVN + DISTCLEANFILES = + +diff -ruN libgcrypt-1.4.0/Makefile.in libgcrypt-1.4.0-good//Makefile.in +--- libgcrypt-1.4.0/Makefile.in 2007-12-10 04:05:13.000000000 -0500 ++++ libgcrypt-1.4.0-good//Makefile.in 2012-04-27 15:14:14.186381680 -0400 +@@ -237,7 +237,7 @@ + --enable-ciphers=arcfour:blowfish:cast5:des:aes:twofish:serpent:rfc2268:seed:camellia + + DIST_SUBDIRS = m4 mpi cipher src doc tests +-SUBDIRS = mpi cipher src doc tests ++SUBDIRS = mpi cipher src + EXTRA_DIST = BUGS autogen.sh README.SVN + DISTCLEANFILES = + all: config.h diff --git a/tools/android/depends/libgpg-error/Makefile b/tools/android/depends/libgpg-error/Makefile new file mode 100644 index 0000000000..cb43d1939f --- /dev/null +++ b/tools/android/depends/libgpg-error/Makefile @@ -0,0 +1,41 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libgpg-error +VERSION=1.10 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.bz2 + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) --host=$(HOST) \ + --disable-languages \ + --disable-nls --disable-shared + +LIBDYLIB=$(PLATFORM)/src/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/libiconv/Makefile b/tools/android/depends/libiconv/Makefile new file mode 100644 index 0000000000..a54de13ca6 --- /dev/null +++ b/tools/android/depends/libiconv/Makefile @@ -0,0 +1,42 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libiconv +VERSION=1.13.1 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) build-aux/; \ + cp -f $(CONFIG_SUB) $(CONFIG_GUESS) libcharset/build-aux/; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) gl_cv_header_working_stdint_h=yes --disable-shared + +LIBDYLIB=$(PLATFORM)/lib/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libid3tag/Makefile b/tools/android/depends/libid3tag/Makefile new file mode 100644 index 0000000000..18d1e859c8 --- /dev/null +++ b/tools/android/depends/libid3tag/Makefile @@ -0,0 +1,45 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libid3tag +VERSION=0.15.1b +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings + +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --build=$(BUILD) --host=$(HOST) \ + +LIBDYLIB=$(PLATFORM)/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -j 1 -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libid3tag.la $(PREFIX)/lib/libid3tag.so $(PREFIX)/lib/libid3tag.so.0 + mv -f $(PREFIX)/lib/libid3tag.so.0.3.0 $(PREFIX)/lib/libid3tag.so + $(RPL) -e "libid3tag.so.0" "libid3tag.so\x00\x00" $(PREFIX)/lib/libid3tag.so + -$(READELF) --dynamic $(PREFIX)/lib/libid3tag.so | grep ibrary + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/libjpeg-turbo-native/Makefile b/tools/android/depends/libjpeg-turbo-native/Makefile new file mode 100644 index 0000000000..434b60905a --- /dev/null +++ b/tools/android/depends/libjpeg-turbo-native/Makefile @@ -0,0 +1,42 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libjpeg-turbo +VERSION=1.2.0 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + NASM=$(YASM) ./configure --prefix=$(PREFIX) --with-jpeg8 + +CFLAGS+=-O3 + +LIBDYLIB=$(PLATFORM)/.libs/libjpeg.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +jpegtest: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -j 1 -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/libjpeg-turbo/Makefile b/tools/android/depends/libjpeg-turbo/Makefile new file mode 100644 index 0000000000..f0c9391988 --- /dev/null +++ b/tools/android/depends/libjpeg-turbo/Makefile @@ -0,0 +1,41 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libjpeg-turbo +VERSION=1.2.0 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + NASM=$(YASM) ./configure --prefix=$(PREFIX) --host=$(HOST) --with-jpeg8 --disable-shared + +CFLAGS+=-O3 + +LIBDYLIB=$(PLATFORM)/.libs/libjpeg.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -j 1 -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/liblzo2-native/Makefile b/tools/android/depends/liblzo2-native/Makefile new file mode 100644 index 0000000000..451c58b1b1 --- /dev/null +++ b/tools/android/depends/liblzo2-native/Makefile @@ -0,0 +1,42 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=lzo +VERSION=2.03 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) autoconf/; \ + ./configure --prefix=$(PREFIX) --enable-shared + +LIBDYLIB=$(PLATFORM)/src/.libs/lib$(LIBNAME)2.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/liblzo2/Makefile b/tools/android/depends/liblzo2/Makefile new file mode 100644 index 0000000000..b5a7e47f33 --- /dev/null +++ b/tools/android/depends/liblzo2/Makefile @@ -0,0 +1,41 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=lzo +VERSION=2.03 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) autoconf/; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) + +LIBDYLIB=$(PLATFORM)/src/.libs/lib$(LIBNAME)2.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libmad/01-libmad-pkgconfig.patch b/tools/android/depends/libmad/01-libmad-pkgconfig.patch new file mode 100644 index 0000000000..fcfd34164a --- /dev/null +++ b/tools/android/depends/libmad/01-libmad-pkgconfig.patch @@ -0,0 +1,118 @@ +diff -ruN libmad-0.15.1b.orig/Makefile.am libmad-0.15.1b/Makefile.am +--- libmad-0.15.1b.orig/Makefile.am 2004-02-17 02:02:03.000000000 +0000 ++++ libmad-0.15.1b/Makefile.am 2005-08-25 12:08:04.000000000 +0000 +@@ -33,9 +33,12 @@ + minimad_INCLUDES = + minimad_LDADD = libmad.la + +-EXTRA_DIST = mad.h.sed \ ++EXTRA_DIST = mad.h.sed mad.pc.in \ + CHANGES COPYRIGHT CREDITS README TODO VERSION + ++pkgconfigdir = $(libdir)/pkgconfig ++pkgconfig_DATA= mad.pc ++ + exported_headers = version.h fixed.h bit.h timer.h stream.h frame.h \ + synth.h decoder.h + +diff -ruN libmad-0.15.1b.orig/Makefile.in libmad-0.15.1b/Makefile.in +--- libmad-0.15.1b.orig/Makefile.in 2004-02-17 02:33:23.000000000 +0000 ++++ libmad-0.15.1b/Makefile.in 2005-08-25 12:09:34.000000000 +0000 +@@ -14,6 +14,8 @@ + + @SET_MAKE@ + ++pkgconfigdir = $(libdir)/pkgconfig ++pkgconfig_DATA = mad.pc + + SOURCES = $(libmad_la_SOURCES) $(EXTRA_libmad_la_SOURCES) $(minimad_SOURCES) + +@@ -43,7 +45,7 @@ + $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/config.h.in $(srcdir)/libmad.list.in \ + $(top_srcdir)/configure COPYING INSTALL TODO config.guess \ +- config.sub depcomp install-sh ltmain.sh missing mkinstalldirs ++ config.sub depcomp install-sh ltmain.sh missing mkinstalldirs mad.pc.in + subdir = . + ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 + am__aclocal_m4_deps = $(top_srcdir)/configure.ac +@@ -53,7 +55,7 @@ + configure.lineno configure.status.lineno + mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs + CONFIG_HEADER = config.h +-CONFIG_CLEAN_FILES = libmad.list ++CONFIG_CLEAN_FILES = libmad.list mad.pc + am__installdirs = $(DESTDIR)$(libdir) $(DESTDIR)$(includedir) + libLTLIBRARIES_INSTALL = $(INSTALL) + LTLIBRARIES = $(lib_LTLIBRARIES) +@@ -218,7 +220,7 @@ + minimad_SOURCES = minimad.c + minimad_INCLUDES = + minimad_LDADD = libmad.la +-EXTRA_DIST = mad.h.sed \ ++EXTRA_DIST = mad.h.sed mad.pc.in \ + CHANGES COPYRIGHT CREDITS README TODO VERSION + + exported_headers = version.h fixed.h bit.h timer.h stream.h frame.h \ +@@ -298,6 +300,28 @@ + rm -f stamp-h1 + touch $@ + ++mad.pc: $(top_builddir)/config.status mad.pc.in ++ cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status ++ ++install-pkgconfigDATA: $(pkgconfig_DATA) ++ @$(NORMAL_INSTALL) ++ $(mkinstalldirs) $(DESTDIR)$(pkgconfigdir) ++ @list='$(pkgconfig_DATA)'; for p in $$list; do \ ++ if test -f $(srcdir)/$$p; then \ ++ echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkgconfigdir)/$$p"; \ ++ $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkgconfigdir)/$$p; \ ++ else if test -f $$p; then \ ++ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(pkgconfigdir)/$$p"; \ ++ $(INSTALL_DATA) $$p $(DESTDIR)$(pkgconfigdir)/$$p; \ ++ fi; fi; \ ++ done ++ ++uninstall-pkgconfigDATA: ++ @$(NORMAL_UNINSTALL) ++ list='$(pkgconfig_DATA)'; for p in $$list; do \ ++ rm -f $(DESTDIR)$(pkgconfigdir)/$$p; \ ++ done ++ + distclean-hdr: + -rm -f config.h stamp-h1 + libmad.list: $(top_builddir)/config.status $(srcdir)/libmad.list.in +@@ -726,7 +750,7 @@ + + info-am: + +-install-data-am: install-includeHEADERS ++install-data-am: install-includeHEADERS install-pkgconfigDATA + + install-exec-am: install-libLTLIBRARIES + +@@ -757,7 +781,7 @@ + ps-am: + + uninstall-am: uninstall-includeHEADERS uninstall-info-am \ +- uninstall-libLTLIBRARIES ++ uninstall-libLTLIBRARIES install-pkgconfigDATA + + uninstall-info: uninstall-info-recursive + +diff -ruN libmad-0.15.1b.orig/mad.pc.in libmad-0.15.1b/mad.pc.in +--- libmad-0.15.1b.orig/mad.pc.in 1970-01-01 00:00:00.000000000 +0000 ++++ libmad-0.15.1b/mad.pc.in 2005-08-25 12:08:04.000000000 +0000 +@@ -0,0 +1,10 @@ ++prefix=@prefix@ ++exec_prefix=@exec_prefix@ ++libdir=@libdir@ ++includedir=@includedir@ ++ ++Name: MAD ++Description: libmad - MPEG audio decoder library ++Version: @VERSION@ ++Libs: -L${libdir} -lmad ++Cflags: + diff --git a/tools/android/depends/libmad/Makefile b/tools/android/depends/libmad/Makefile new file mode 100644 index 0000000000..4279838e12 --- /dev/null +++ b/tools/android/depends/libmad/Makefile @@ -0,0 +1,50 @@ +include ../Makefile.include +DEPS= ../Makefile.include 01-libmad-pkgconfig.patch Makefile + +# lib name, version +LIBNAME=libmad +VERSION=0.15.1b +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +#Arm build borks with -mthumb +ifeq ($(findstring arm,$(PLATFORM)),arm) +export CFLAGS+=-marm +endif + +# configuration settings +CONFIGURE=rm config.sub config.guess; $(AUTOMAKE) -ac; ./configure --prefix=$(PREFIX) --host=$(HOST) + +LIBDYLIB=$(PLATFORM)/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 < ../01-libmad-pkgconfig.patch + cd $(PLATFORM); sed -i '/-fforce-mem/d' configure; $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libmad.la $(PREFIX)/lib/libmad.so $(PREFIX)/lib/libmad.so.0 + mv -f $(PREFIX)/lib/libmad.so.0.2.1 $(PREFIX)/lib/libmad.so + $(RPL) -e "libmad.so.0" "libmad.so\x00\x00" $(PREFIX)/lib/libmad.so + -$(READELF) --dynamic $(PREFIX)/lib/libmad.so | grep ibrary + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libmicrohttpd/Makefile b/tools/android/depends/libmicrohttpd/Makefile new file mode 100644 index 0000000000..e55b03a9e9 --- /dev/null +++ b/tools/android/depends/libmicrohttpd/Makefile @@ -0,0 +1,44 @@ +include ../Makefile.include +DEPS= ../Makefile.include fix-android-include.patch Makefile + +# lib name, version +LIBNAME=libmicrohttpd +VERSION=0.4.6 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared + +LIBDYLIB=$(PLATFORM)/src/daemon/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p0 < ../fix-android-include.patch + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM)/src/daemon + $(MAKE) -C $(PLATFORM)/src/include install + +.installed-$(PLATFORM): $(LIBDYLIB) + rm -f $(PREFIX)/lib/libmicrohttpd.so $(PREFIX)/lib/libmicrohttpd.so.5 $(PREFIX)/lib/libmicrohttpd.so.5.2.1 + $(MAKE) -C $(PLATFORM)/src/daemon install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libmicrohttpd/fix-android-include.patch b/tools/android/depends/libmicrohttpd/fix-android-include.patch new file mode 100644 index 0000000000..5c14087f06 --- /dev/null +++ b/tools/android/depends/libmicrohttpd/fix-android-include.patch @@ -0,0 +1,33 @@ +diff -ruN src/daemon/daemon.c src/daemon/daemon.c +--- src/daemon/daemon.c 2012-05-07 17:21:43.695832026 -0400 ++++ src/daemon/daemon.c 2012-05-07 17:20:20.365832079 -0400 +@@ -244,7 +244,7 @@ + MHD_ip_count_lock (daemon); + + /* Search for the IP address */ +- node = (void*)TSEARCH (key, &daemon->per_ip_connection_count, MHD_ip_addr_compare); ++// node = (void*)TSEARCH (key, &daemon->per_ip_connection_count, MHD_ip_addr_compare); + if (!node) + { + #if HAVE_MESSAGES +@@ -296,7 +296,7 @@ + MHD_ip_count_lock (daemon); + + /* Search for the IP address */ +- node = (void*)TFIND (&search_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare); ++// node = (void*)TFIND (&search_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare); + + /* Something's wrong if we couldn't find an IP address + * that was previously added */ +diff -ruN src/include/platform.h src/include/platform.h +--- src/include/platform.h 2012-05-07 17:34:57.345831526 -0400 ++++ src/include/platform.h 2012-05-07 17:20:20.375832079 -0400 +@@ -53,7 +53,7 @@ + #include <errno.h> + #include <fcntl.h> + #include <signal.h> +-#if !defined(MINGW) && !defined(__SYMBIAN32__) ++#if !defined(MINGW) && !defined(__SYMBIAN32__) && !defined(ANDROID) + #include <search.h> + #endif + #include <stddef.h> diff --git a/tools/android/depends/libmodplug/Makefile b/tools/android/depends/libmodplug/Makefile new file mode 100644 index 0000000000..f38b6d915e --- /dev/null +++ b/tools/android/depends/libmodplug/Makefile @@ -0,0 +1,45 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libmodplug +VERSION=0.8.7 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) + +LIBDYLIB=$(PLATFORM)/src/.libs/$(LIBNAME).so + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libmodplug.la $(PREFIX)/lib/libmodplug.so $(PREFIX)/lib/libmodplug.so.0 + mv -f $(PREFIX)/lib/libmodplug.so.0.0.0 $(PREFIX)/lib/libmodplug.so + $(RPL) -e "libmodplug.so.0" "libmodplug.so\x00\x00" $(PREFIX)/lib/libmodplug.so + -$(READELF) --dynamic $(PREFIX)/lib/libmodplug.so | grep ibrary + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libmpeg2/Makefile b/tools/android/depends/libmpeg2/Makefile new file mode 100644 index 0000000000..8bd2eb7981 --- /dev/null +++ b/tools/android/depends/libmpeg2/Makefile @@ -0,0 +1,53 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libmpeg2 +VERSION=0.5.1 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .auto/ ; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-sdl + +LIBDYLIB=$(PLATFORM)/$(LIBNAME)/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libmpeg2.la $(PREFIX)/lib/libmpeg2.so $(PREFIX)/lib/libmpeg2.so.0 + mv -f $(PREFIX)/lib/libmpeg2.so.0.1.0 $(PREFIX)/lib/libxbmpeg2.so + ln -sf $(PREFIX)/lib/libxbmpeg2.so $(PREFIX)/lib/libmpeg2.so + $(RPL) -e "libmpeg2.so.0" "libxbmpeg2.so" $(PREFIX)/lib/libxbmpeg2.so + -$(READELF) --dynamic $(PREFIX)/lib/libxbmpeg2.so | grep ibrary + # + rm -f $(PREFIX)/lib/libmpeg2convert.la $(PREFIX)/lib/libmpeg2convert.so $(PREFIX)/lib/libmpeg2convert.so.0 + mv -f $(PREFIX)/lib/libmpeg2convert.so.0.0.0 $(PREFIX)/lib/libxbmpeg2convert.so + ln -sf $(PREFIX)/lib/libxbmpeg2convert.so $(PREFIX)/lib/libmpeg2convert.so + $(RPL) -e "libmpeg2convert.so.0" "libxbmpeg2convert.so" $(PREFIX)/lib/libxbmpeg2convert.so + -$(READELF) --dynamic $(PREFIX)/lib/libxbmpeg2convert.so | grep ibrary + # + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libnfs/001_fix_hanewin.patch b/tools/android/depends/libnfs/001_fix_hanewin.patch new file mode 100644 index 0000000000..507fbe6988 --- /dev/null +++ b/tools/android/depends/libnfs/001_fix_hanewin.patch @@ -0,0 +1,12 @@ +--- lib/libnfs.c 2011-09-02 12:45:30.000000000 +0200 ++++ lib/libnfs.c 2011-12-04 21:16:07.000000000 +0100 +@@ -666,6 +666,9 @@ + if (res->GETATTR3res_u.resok.obj_attributes.type == NF3DIR) { + st.st_mode |= S_IFDIR ; + } ++ if (res->GETATTR3res_u.resok.obj_attributes.type == NF3REG) { ++ st.st_mode |= S_IFREG ; ++ } + st.st_nlink = res->GETATTR3res_u.resok.obj_attributes.nlink; + st.st_uid = res->GETATTR3res_u.resok.obj_attributes.uid; + st.st_gid = res->GETATTR3res_u.resok.obj_attributes.gid; diff --git a/tools/android/depends/libnfs/Makefile b/tools/android/depends/libnfs/Makefile new file mode 100644 index 0000000000..779b39546d --- /dev/null +++ b/tools/android/depends/libnfs/Makefile @@ -0,0 +1,52 @@ +include ../Makefile.include +DEPS= ../Makefile.include 001_fix_hanewin.patch libnfs_android.patch Makefile rpcinc/* + +# lib name, version +LIBNAME=libnfs +VERSION=0804e67 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) --host=$(HOST) + +RPC_HEADERS=rpcinc/auth.h rpcinc/auth_unix.h rpcinc/clnt.h rpcinc/pmap_clnt.h rpcinc/pmap_prot.h rpcinc/pmap_rmt.h rpcinc/rpc.h rpcinc/rpc_msg.h rpcinc/svc.h rpcinc/svc_auth.h rpcinc/types.h rpcinc/xdr.h + +LIBDYLIB=$(PLATFORM)/lib/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + -rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + mkdir -p $(PLATFORM)/include/rpc + install -c -m 644 $(RPC_HEADERS) $(PLATFORM)/include/rpc/ + cd $(PLATFORM); patch -p0 < ../001_fix_hanewin.patch + cd $(PLATFORM); patch -p0 < ../libnfs_android.patch + cd $(PLATFORM); ./bootstrap + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libnfs.la $(PREFIX)/lib/libnfs.so $(PREFIX)/lib/libnfs.so.0 + mv -f $(PREFIX)/lib/libnfs.so.0.0.0 $(PREFIX)/lib/libnfs.so + mkdir -p $(PREFIX)/include/rpc + cp -f rpcinc/* $(PREFIX)/include/rpc + $(RPL) -e "libnfs.so.0" "libnfs.so\x00\x00" $(PREFIX)/lib/libnfs.so + -$(READELF) --dynamic $(PREFIX)/lib/libnfs.so | grep ibrary + touch $@ +clean: + $(MAKE) -C $(PLATFORM) clean + rm -r .installed-$(PLATFORM) + rm -rf $(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/libnfs/libnfs_android.patch b/tools/android/depends/libnfs/libnfs_android.patch new file mode 100644 index 0000000000..4a084f1b19 --- /dev/null +++ b/tools/android/depends/libnfs/libnfs_android.patch @@ -0,0 +1,45 @@ +--- lib/libnfs-sync.c 2011-09-02 06:45:30.000000000 -0400 ++++ lib/libnfs-sync.c 2012-06-02 22:17:11.904404289 -0400 +@@ -25,7 +25,13 @@ + #include <strings.h> + #include <sys/types.h> + #include <sys/stat.h> +-#include <sys/statvfs.h> ++#ifndef ANDROID ++#include <sys/statvfs.h> ++#else ++#include <sys/vfs.h> ++#define statvfs statfs ++#define fstatvfs fstatfs ++#endif + #include <sys/ioctl.h> + #include <unistd.h> + #include <fcntl.h> +--- lib/libnfs.c 2012-06-02 22:17:23.324404282 -0400 ++++ lib/libnfs.c 2012-06-02 22:17:11.904404289 -0400 +@@ -27,7 +27,13 @@ + #include <errno.h> + #include <sys/types.h> + #include <sys/stat.h> +-#include <sys/statvfs.h> ++#ifndef ANDROID ++#include <sys/statvfs.h> ++#else ++#include <sys/vfs.h> ++#define statvfs statfs ++#define fstatvfs fstatfs ++#endif + #include <utime.h> + #include <unistd.h> + #include <fcntl.h> +@@ -1919,10 +1925,6 @@ + svfs.f_bavail = res->FSSTAT3res_u.resok.abytes/4096; + svfs.f_files = res->FSSTAT3res_u.resok.tfiles; + svfs.f_ffree = res->FSSTAT3res_u.resok.ffiles; +- svfs.f_favail = res->FSSTAT3res_u.resok.afiles; +- svfs.f_fsid = 0; +- svfs.f_flag = 0; +- svfs.f_namemax = 256; + + data->cb(0, nfs, &svfs, data->private_data); + free_nfs_cb_data(data); diff --git a/tools/android/depends/libnfs/rpcinc/auth.h b/tools/android/depends/libnfs/rpcinc/auth.h new file mode 100644 index 0000000000..97a289c821 --- /dev/null +++ b/tools/android/depends/libnfs/rpcinc/auth.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)auth.h 1.17 88/02/08 SMI + * from: @(#)auth.h 2.3 88/08/07 4.0 RPCSRC + * $Id: auth.h,v 1.4 2004/11/25 19:41:19 emoy Exp $ + */ + +/* + * auth.h, Authentication interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * The data structures are completely opaque to the client. The client + * is required to pass a AUTH * to routines that create rpc + * "sessions". + */ + +#ifndef _RPC_AUTH_H +#define _RPC_AUTH_H +#include <sys/cdefs.h> + +#define MAX_AUTH_BYTES 400 +#define MAXNETNAMELEN 255 /* maximum length of network user's name */ + +/* + * Status returned from authentication check + */ +enum auth_stat { + AUTH_OK=0, + /* + * failed at remote end + */ + AUTH_BADCRED=1, /* bogus credentials (seal broken) */ + AUTH_REJECTEDCRED=2, /* client should begin new session */ + AUTH_BADVERF=3, /* bogus verifier (seal broken) */ + AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */ + AUTH_TOOWEAK=5, /* rejected due to security reasons */ + /* + * failed locally + */ + AUTH_INVALIDRESP=6, /* bogus response verifier */ + AUTH_FAILED=7 /* some unknown reason */ +}; + +/* 32-bit unsigned integers */ +#ifdef __LP64__ +typedef unsigned int u_int32; +#else +typedef unsigned long u_int32; +#endif + +union des_block { + struct { + u_int32 high; + u_int32 low; + } key; + char c[8]; +}; +typedef union des_block des_block; +__BEGIN_DECLS +extern bool_t xdr_des_block __P((XDR *, des_block *)); +__END_DECLS + +/* + * Authentication info. Opaque to client. + */ +struct opaque_auth { + enum_t oa_flavor; /* flavor of auth */ + caddr_t oa_base; /* address of more auth stuff */ + unsigned int oa_length; /* not to exceed MAX_AUTH_BYTES */ +}; + + +/* + * Auth handle, interface to client side authenticators. + */ +struct AUTH{ + struct opaque_auth ah_cred; + struct opaque_auth ah_verf; + union des_block ah_key; + struct auth_ops { +#ifdef __cplusplus + void (*ah_nextverf)(...); + int (*ah_marshal)(...); /* nextverf & serialize */ + int (*ah_validate)(...); /* validate varifier */ + int (*ah_refresh)(...); /* refresh credentials */ + void (*ah_destroy)(...); /* destroy this structure */ +#else + /* DO NOT REMOVE THE COMMENTED OUT ...: fixincludes needs to see them */ + void (*ah_nextverf)(/*...*/); + int (*ah_marshal)(/*...*/); /* nextverf & serialize */ + int (*ah_validate)(/*...*/); /* validate varifier */ + int (*ah_refresh)(/*...*/); /* refresh credentials */ + void (*ah_destroy)(/*...*/); /* destroy this structure */ +#endif + } *ah_ops; + caddr_t ah_private; +}; +typedef struct AUTH AUTH; + + +/* + * Authentication ops. + * The ops and the auth handle provide the interface to the authenticators. + * + * AUTH *auth; + * XDR *xdrs; + * struct opaque_auth verf; + */ +#define AUTH_NEXTVERF(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) +#define auth_nextverf(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) + +#define AUTH_MARSHALL(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) +#define auth_marshall(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) + +#define AUTH_VALIDATE(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) +#define auth_validate(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) + +#define AUTH_REFRESH(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) +#define auth_refresh(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) + +#define AUTH_DESTROY(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) +#define auth_destroy(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) + + +extern struct opaque_auth _null_auth; + + +/* + * These are the various implementations of client side authenticators. + */ + +/* + * Unix style authentication + * AUTH *authunix_create(machname, uid, gid, len, aup_gids) + * char *machname; + * int uid; + * int gid; + * int len; + * int *aup_gids; + */ +__BEGIN_DECLS +extern AUTH *authunix_create __P((char *, int, int, int, int *)); +extern AUTH *authunix_create_default __P((void)); +extern AUTH *authnone_create __P((void)); +extern AUTH *authdes_create __P((char *, unsigned int, + struct sockaddr_in *, + des_block *)); +__END_DECLS + +#define AUTH_NONE 0 /* no authentication */ +#define AUTH_NULL 0 /* backward compatibility */ +#define AUTH_UNIX 1 /* unix style (uid, gids) */ +#define AUTH_SHORT 2 /* short hand unix style */ +#define AUTH_DES 3 /* des style (encrypted timestamps) */ + +#endif /* !_RPC_AUTH_H */ diff --git a/tools/android/depends/libnfs/rpcinc/auth_unix.h b/tools/android/depends/libnfs/rpcinc/auth_unix.h new file mode 100644 index 0000000000..496defb79a --- /dev/null +++ b/tools/android/depends/libnfs/rpcinc/auth_unix.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)auth_unix.h 1.8 88/02/08 SMI + * from: @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC + * $Id: auth_unix.h,v 1.4 2004/10/28 21:58:21 emoy Exp $ + */ + +/* + * auth_unix.h, Protocol for UNIX style authentication parameters for RPC + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +/* + * The system is very weak. The client uses no encryption for it + * credentials and only sends null verifiers. The server sends backs + * null verifiers or optionally a verifier that suggests a new short hand + * for the credentials. + */ + +#ifndef _RPC_AUTH_UNIX_H +#define _RPC_AUTH_UNIX_H +#include <sys/cdefs.h> + +/* The machine name is part of a credential; it may not exceed 255 bytes */ +#define MAX_MACHINE_NAME 255 + +/* + * Unix style credentials. + */ +struct authunix_parms { +#ifdef __LP64__ + unsigned int aup_time; +#else + unsigned long aup_time; +#endif + char *aup_machname; + int aup_uid; + int aup_gid; + unsigned int aup_len; + int *aup_gids; +}; + +__BEGIN_DECLS +extern bool_t xdr_authunix_parms __P((XDR *, struct authunix_parms *)); +__END_DECLS + +/* + * If a response verifier has flavor AUTH_SHORT, + * then the body of the response verifier encapsulates the following structure; + * again it is serialized in the obvious fashion. + */ +struct short_hand_verf { + struct opaque_auth new_cred; +}; + +#endif /* !_RPC_AUTH_UNIX_H */ diff --git a/tools/android/depends/libnfs/rpcinc/clnt.h b/tools/android/depends/libnfs/rpcinc/clnt.h new file mode 100644 index 0000000000..4ed9b51bf3 --- /dev/null +++ b/tools/android/depends/libnfs/rpcinc/clnt.h @@ -0,0 +1,445 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)clnt.h 1.31 88/02/08 SMI + * from: @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC + * $Id: clnt.h,v 1.4 2004/10/28 21:58:22 emoy Exp $ + */ + +/* + * clnt.h - Client side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_CLNT_H_ +#define _RPC_CLNT_H_ +#include <sys/cdefs.h> + +/* + * Rpc calls return an enum clnt_stat. This should be looked at more, + * since each implementation is required to live with this (implementation + * independent) list of errors. + */ + +/* Avoid collision with mach definition */ +#if defined(RPC_SUCCESS) +#undef RPC_SUCCESS +#endif + +enum clnt_stat { + RPC_SUCCESS=0, /* call succeeded */ + /* + * local errors + */ + RPC_CANTENCODEARGS=1, /* can't encode arguments */ + RPC_CANTDECODERES=2, /* can't decode results */ + RPC_CANTSEND=3, /* failure in sending call */ + RPC_CANTRECV=4, /* failure in receiving result */ + RPC_TIMEDOUT=5, /* call timed out */ + /* + * remote errors + */ + RPC_VERSMISMATCH=6, /* rpc versions not compatible */ + RPC_AUTHERROR=7, /* authentication error */ + RPC_PROGUNAVAIL=8, /* program not available */ + RPC_PROGVERSMISMATCH=9, /* program version mismatched */ + RPC_PROCUNAVAIL=10, /* procedure unavailable */ + RPC_CANTDECODEARGS=11, /* decode arguments error */ + RPC_SYSTEMERROR=12, /* generic "other problem" */ + + /* + * callrpc & clnt_create errors + */ + RPC_UNKNOWNHOST=13, /* unknown host name */ + RPC_UNKNOWNPROTO=17, /* unkown protocol */ + + /* + * _ create errors + */ + RPC_PMAPFAILURE=14, /* the pmapper failed in its call */ + RPC_PROGNOTREGISTERED=15, /* remote program is not registered */ + /* + * unspecified error + */ + RPC_FAILED=16 +}; + + +/* + * Error info. + */ +struct rpc_err { + enum clnt_stat re_status; + union { + int RE_errno; /* realated system error */ + enum auth_stat RE_why; /* why the auth error occurred */ + struct { +#ifdef __LP64__ + unsigned int low; /* lowest verion supported */ + unsigned int high; /* highest verion supported */ +#else + unsigned long low; /* lowest verion supported */ + unsigned long high; /* highest verion supported */ +#endif + } RE_vers; + struct { /* maybe meaningful if RPC_FAILED */ +#ifdef __LP64__ + int s1; + int s2; +#else + long s1; + long s2; +#endif + } RE_lb; /* life boot & debugging only */ + } ru; +#define re_errno ru.RE_errno +#define re_why ru.RE_why +#define re_vers ru.RE_vers +#define re_lb ru.RE_lb +}; + + +/* + * Client rpc handle. + * Created by individual implementations, see e.g. rpc_udp.c. + * Client is responsible for initializing auth, see e.g. auth_none.c. + */ +typedef struct CLIENT CLIENT; +struct CLIENT +{ + AUTH *cl_auth; /* authenticator */ + struct clnt_ops { +#ifdef __LP64__ + enum clnt_stat (*cl_call)(CLIENT *, unsigned int, xdrproc_t, void *, xdrproc_t, void *, struct timeval); /* call remote procedure */ +#else + enum clnt_stat (*cl_call)(CLIENT *, unsigned long, xdrproc_t, void *, xdrproc_t, void *, struct timeval); /* call remote procedure */ +#endif + void (*cl_abort)(void); /* abort a call */ + void (*cl_geterr)(CLIENT *, struct rpc_err *); /* get specific error code */ + bool_t (*cl_freeres)(CLIENT *, xdrproc_t, void *); /* frees results */ + void (*cl_destroy)(CLIENT *); /* destroy this structure */ + bool_t (*cl_control)(CLIENT *, int, char *); /* the ioctl() of rpc */ + } *cl_ops; + caddr_t cl_private; /* private stuff */ +}; + +/* + * client side rpc interface ops + * + * Parameter types are: + * + */ + +/* + * enum clnt_stat + * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) + * CLIENT *rh; + * u_long proc; + * xdrproc_t xargs; + * caddr_t argsp; + * xdrproc_t xres; + * caddr_t resp; + * struct timeval timeout; + */ +#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) +#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) + +/* + * void + * CLNT_ABORT(rh); + * CLIENT *rh; + */ +#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh)) +#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh)) + +/* + * struct rpc_err + * CLNT_GETERR(rh); + * CLIENT *rh; + */ +#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) +#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) + + +/* + * bool_t + * CLNT_FREERES(rh, xres, resp); + * CLIENT *rh; + * xdrproc_t xres; + * caddr_t resp; + */ +#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) +#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) + +/* + * bool_t + * CLNT_CONTROL(cl, request, info) + * CLIENT *cl; + * unsigned int request; + * char *info; + */ +#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) +#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) + +/* + * control operations that apply to both udp and tcp transports + */ +#define CLSET_TIMEOUT 1 /* set timeout (timeval) */ +#define CLGET_TIMEOUT 2 /* get timeout (timeval) */ +#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */ +/* + * udp only control operations + */ +#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ +#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ + +/* + * void + * CLNT_DESTROY(rh); + * CLIENT *rh; + */ +#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) +#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) + + +/* + * RPCTEST is a test program which is accessable on every rpc + * transport/port. It is used for testing, performance evaluation, + * and network administration. + */ + +#ifdef __LP64__ +#define RPCTEST_PROGRAM ((unsigned int)1) +#define RPCTEST_VERSION ((unsigned int)1) +#define RPCTEST_NULL_PROC ((unsigned int)2) +#define RPCTEST_NULL_BATCH_PROC ((unsigned int)3) +#else +#define RPCTEST_PROGRAM ((unsigned long)1) +#define RPCTEST_VERSION ((unsigned long)1) +#define RPCTEST_NULL_PROC ((unsigned long)2) +#define RPCTEST_NULL_BATCH_PROC ((unsigned long)3) +#endif + +/* + * By convention, procedure 0 takes null arguments and returns them + */ + +#ifdef __LP64__ +#define NULLPROC ((unsigned int)0) +#else +#define NULLPROC ((unsigned long)0) +#endif + +/* + * Below are the client handle creation routines for the various + * implementations of client side rpc. They can return NULL if a + * creation failure occurs. + */ + +/* + * Memory based rpc (for speed check and testing) + * CLIENT * + * clntraw_create(prog, vers) + * u_long prog; + * u_long vers; + */ +__BEGIN_DECLS +#ifdef __LP64__ +extern CLIENT *clntraw_create __P((unsigned int, unsigned int)); +#else +extern CLIENT *clntraw_create __P((unsigned long, unsigned long)); +#endif +__END_DECLS + + +/* + * Generic client creation routine. Supported protocols are "udp" and "tcp" + * CLIENT * + * clnt_create(host, prog, vers, prot); + * char *host; -- hostname + * u_long prog; -- program number + * u_long vers; -- version number + * char *prot; -- protocol + */ +__BEGIN_DECLS +#ifdef __LP64__ +extern CLIENT *clnt_create __P((char *, unsigned int, unsigned int, char *)); +#else +extern CLIENT *clnt_create __P((char *, unsigned long, unsigned long, char *)); +#endif +__END_DECLS + + +/* + * TCP based rpc + * CLIENT * + * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long prog; + * u_long version; + * register int *sockp; + * unsigned int sendsz; + * unsigned int recvsz; + */ +__BEGIN_DECLS +#ifdef __LP64__ +extern CLIENT *clnttcp_create __P((struct sockaddr_in *, + unsigned int, + unsigned int, + int *, + unsigned int, + unsigned int)); +#else +extern CLIENT *clnttcp_create __P((struct sockaddr_in *, + unsigned long, + unsigned long, + int *, + unsigned int, + unsigned int)); +#endif +__END_DECLS + + +/* + * UDP based rpc. + * CLIENT * + * clntudp_create(raddr, program, version, wait, sockp) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait; + * int *sockp; + * + * Same as above, but you specify max packet sizes. + * CLIENT * + * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait; + * int *sockp; + * unsigned int sendsz; + * unsigned int recvsz; + */ +__BEGIN_DECLS +#ifdef __LP64__ +extern CLIENT *clntudp_create __P((struct sockaddr_in *, + unsigned int, + unsigned int, + struct timeval, + int *)); +extern CLIENT *clntudp_bufcreate __P((struct sockaddr_in *, + unsigned int, + unsigned int, + struct timeval, + int *, + unsigned int, + unsigned int)); +#else +extern CLIENT *clntudp_create __P((struct sockaddr_in *, + unsigned long, + unsigned long, + struct timeval, + int *)); +extern CLIENT *clntudp_bufcreate __P((struct sockaddr_in *, + unsigned long, + unsigned long, + struct timeval, + int *, + unsigned int, + unsigned int)); +#endif +__END_DECLS + + +/* + * Print why creation failed + */ +__BEGIN_DECLS +extern void clnt_pcreateerror __P((char *)); /* stderr */ +extern char *clnt_spcreateerror __P((char *)); /* string */ +__END_DECLS + +/* + * Like clnt_perror(), but is more verbose in its output + */ +__BEGIN_DECLS +extern void clnt_perrno __P((enum clnt_stat)); /* stderr */ +extern char *clnt_sperrno __P((enum clnt_stat)); /* string */ +__END_DECLS + +/* + * Print an English error message, given the client error code + */ +__BEGIN_DECLS +extern void clnt_perror __P((CLIENT *, char *)); /* stderr */ +extern char *clnt_sperror __P((CLIENT *, char *)); /* string */ +__END_DECLS + + +/* + * If a creation fails, the following allows the user to figure out why. + */ +struct rpc_createerr { + enum clnt_stat cf_stat; + struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */ +}; + +extern struct rpc_createerr rpc_createerr; + + +#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */ +#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */ + +#endif /* !_RPC_CLNT_H */ diff --git a/tools/android/depends/libnfs/rpcinc/pmap_clnt.h b/tools/android/depends/libnfs/rpcinc/pmap_clnt.h new file mode 100644 index 0000000000..c07a81902b --- /dev/null +++ b/tools/android/depends/libnfs/rpcinc/pmap_clnt.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)pmap_clnt.h 1.11 88/02/08 SMI + * from: @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC + * $Id: pmap_clnt.h,v 1.3 2004/10/28 21:58:22 emoy Exp $ + */ + +/* + * pmap_clnt.h + * Supplies C routines to get to portmap services. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +/* + * Usage: + * success = pmap_set(program, version, protocol, port); + * success = pmap_unset(program, version); + * port = pmap_getport(address, program, version, protocol); + * head = pmap_getmaps(address); + * clnt_stat = pmap_rmtcall(address, program, version, procedure, + * xdrargs, argsp, xdrres, resp, tout, port_ptr) + * (works for udp only.) + * clnt_stat = clnt_broadcast(program, version, procedure, + * xdrargs, argsp, xdrres, resp, eachresult) + * (like pmap_rmtcall, except the call is broadcasted to all + * locally connected nets. For each valid response received, + * the procedure eachresult is called. Its form is: + * done = eachresult(resp, raddr) + * bool_t done; + * caddr_t resp; + * struct sockaddr_in raddr; + * where resp points to the results of the call and raddr is the + * address if the responder to the broadcast. + */ + +#ifndef _RPC_PMAPCLNT_H +#define _RPC_PMAPCLNT_H +#include <sys/cdefs.h> + +__BEGIN_DECLS +#ifdef __LP64__ +extern bool_t pmap_set __P((unsigned int, unsigned int, int, int)); +extern bool_t pmap_unset __P((unsigned int, unsigned int)); +extern enum clnt_stat pmap_rmtcall __P((struct sockaddr_in *, + unsigned int, unsigned int, unsigned int, + xdrproc_t, caddr_t, + xdrproc_t, caddr_t, + struct timeval, unsigned int *)); +extern enum clnt_stat clnt_broadcast __P((unsigned int, unsigned int, unsigned int, + xdrproc_t, char *, + xdrproc_t, char *, + bool_t (*)())); +extern unsigned short pmap_getport __P((struct sockaddr_in *, + unsigned int, unsigned int, unsigned int)); +#else +extern bool_t pmap_set __P((unsigned long, unsigned long, int, int)); +extern bool_t pmap_unset __P((unsigned long, unsigned long)); +extern enum clnt_stat pmap_rmtcall __P((struct sockaddr_in *, + unsigned long, unsigned long, unsigned long, + xdrproc_t, caddr_t, + xdrproc_t, caddr_t, + struct timeval, unsigned long *)); +extern enum clnt_stat clnt_broadcast __P((unsigned long, unsigned long, unsigned long, + xdrproc_t, char *, + xdrproc_t, char *, + bool_t (*)())); +extern unsigned short pmap_getport __P((struct sockaddr_in *, + unsigned long, unsigned long, unsigned int)); +#endif +extern struct pmaplist *pmap_getmaps __P((struct sockaddr_in *)); +extern int getrpcport __P((char *, int, int, int)); +__END_DECLS + +#endif /* !_RPC_PMAPCLNT_H */ diff --git a/tools/android/depends/libnfs/rpcinc/pmap_prot.h b/tools/android/depends/libnfs/rpcinc/pmap_prot.h new file mode 100644 index 0000000000..c5dc139e41 --- /dev/null +++ b/tools/android/depends/libnfs/rpcinc/pmap_prot.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)pmap_prot.h 1.14 88/02/08 SMI + * from: @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC + * $Id: pmap_prot.h,v 1.3 2004/10/28 21:58:22 emoy Exp $ + */ + +/* + * pmap_prot.h + * Protocol for the local binder service, or pmap. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * The following procedures are supported by the protocol: + * + * PMAPPROC_NULL() returns () + * takes nothing, returns nothing + * + * PMAPPROC_SET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Registers the tuple + * [prog, vers, prot, port]. + * + * PMAPPROC_UNSET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Un-registers pair + * [prog, vers]. prot and port are ignored. + * + * PMAPPROC_GETPORT(struct pmap) returns (long unsigned). + * 0 is failure. Otherwise returns the port number where the pair + * [prog, vers] is registered. It may lie! + * + * PMAPPROC_DUMP() RETURNS (struct pmaplist *) + * + * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>) + * RETURNS (port, string<>); + * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs); + * Calls the procedure on the local machine. If it is not registered, + * this procedure is quite; ie it does not return error information!!! + * This procedure only is supported on rpc/udp and calls via + * rpc/udp. This routine only passes null authentication parameters. + * This file has no interface to xdr routines for PMAPPROC_CALLIT. + * + * The service supports remote procedure calls on udp/ip or tcp/ip socket 111. + */ + +#ifndef _RPC_PMAPPROT_H +#define _RPC_PMAPPROT_H +#include <sys/cdefs.h> + +#define PMAPPORT ((unsigned short)111) +#ifdef __LP64__ +#define PMAPPROG ((unsigned int)100000) +#define PMAPVERS ((unsigned int)2) +#define PMAPVERS_PROTO ((unsigned int)2) +#define PMAPVERS_ORIG ((unsigned int)1) +#define PMAPPROC_NULL ((unsigned int)0) +#define PMAPPROC_SET ((unsigned int)1) +#define PMAPPROC_UNSET ((unsigned int)2) +#define PMAPPROC_GETPORT ((unsigned int)3) +#define PMAPPROC_DUMP ((unsigned int)4) +#define PMAPPROC_CALLIT ((unsigned int)5) +#else +#define PMAPPROG ((unsigned long)100000) +#define PMAPVERS ((unsigned long)2) +#define PMAPVERS_PROTO ((unsigned long)2) +#define PMAPVERS_ORIG ((unsigned long)1) +#define PMAPPROC_NULL ((unsigned long)0) +#define PMAPPROC_SET ((unsigned long)1) +#define PMAPPROC_UNSET ((unsigned long)2) +#define PMAPPROC_GETPORT ((unsigned long)3) +#define PMAPPROC_DUMP ((unsigned long)4) +#define PMAPPROC_CALLIT ((unsigned long)5) +#endif + +struct pmap { +#ifdef __LP64__ + unsigned int pm_prog; + unsigned int pm_vers; + unsigned int pm_prot; + unsigned int pm_port; +#else + long unsigned pm_prog; + long unsigned pm_vers; + long unsigned pm_prot; + long unsigned pm_port; +#endif +}; + +struct pmaplist { + struct pmap pml_map; + struct pmaplist *pml_next; +}; + +__BEGIN_DECLS +extern bool_t xdr_pmap __P((XDR *, struct pmap *)); +extern bool_t xdr_pmaplist __P((XDR *, struct pmaplist **)); +__END_DECLS + +#endif /* !_RPC_PMAPPROT_H */ diff --git a/tools/android/depends/libnfs/rpcinc/pmap_rmt.h b/tools/android/depends/libnfs/rpcinc/pmap_rmt.h new file mode 100644 index 0000000000..9ffbd1cb45 --- /dev/null +++ b/tools/android/depends/libnfs/rpcinc/pmap_rmt.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)pmap_rmt.h 1.2 88/02/08 SMI + * from: @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC + * $Id: pmap_rmt.h,v 1.3 2004/10/28 21:58:23 emoy Exp $ + */ + +/* + * Structures and XDR routines for parameters to and replies from + * the portmapper remote-call-service. + * + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +#ifndef _RPC_PMAPRMT_H +#define _RPC_PMAPRMT_H +#include <sys/cdefs.h> + +struct rmtcallargs { +#ifdef __LP64__ + unsigned int prog, vers, proc, arglen; +#else + unsigned long prog, vers, proc, arglen; +#endif + caddr_t args_ptr; + xdrproc_t xdr_args; +}; + +struct rmtcallres { +#ifdef __LP64__ + unsigned int *port_ptr; + unsigned int resultslen; +#else + unsigned long *port_ptr; + unsigned long resultslen; +#endif + caddr_t results_ptr; + xdrproc_t xdr_results; +}; + +__BEGIN_DECLS +extern bool_t xdr_rmtcall_args __P((XDR *, struct rmtcallargs *)); +extern bool_t xdr_rmtcallres __P((XDR *, struct rmtcallres *)); +__END_DECLS + +#endif /* !_RPC_PMAPRMT_H */ diff --git a/tools/android/depends/libnfs/rpcinc/rpc.h b/tools/android/depends/libnfs/rpcinc/rpc.h new file mode 100644 index 0000000000..da89dff563 --- /dev/null +++ b/tools/android/depends/libnfs/rpcinc/rpc.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)rpc.h 1.9 88/02/08 SMI + * from: @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC + * $Id: rpc.h,v 1.2 1999/10/14 21:56:53 wsanchez Exp $ + */ + +/* + * rpc.h, Just includes the billions of rpc header files necessary to + * do remote procedure calling. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +#ifndef _RPC_RPC_H +#define _RPC_RPC_H + +#include <rpc/types.h> /* some typedefs */ +#include <netinet/in.h> + +/* external data representation interfaces */ +#include <rpc/xdr.h> /* generic (de)serializer */ + +/* Client side only authentication */ +#include <rpc/auth.h> /* generic authenticator (client side) */ + +/* Client side (mostly) remote procedure call */ +#include <rpc/clnt.h> /* generic rpc stuff */ + +/* semi-private protocol headers */ +#include <rpc/rpc_msg.h> /* protocol for rpc messages */ +#include <rpc/auth_unix.h> /* protocol for unix style cred */ +/* + * Uncomment-out the next line if you are building the rpc library with + * DES Authentication (see the README file in the secure_rpc/ directory). + */ +/*#include <rpc/auth_des.h> protocol for des style cred */ + +/* Server side only remote procedure callee */ +#include <rpc/svc.h> /* service manager and multiplexer */ +#include <rpc/svc_auth.h> /* service side authenticator */ + +#include <netdb.h> + +#endif /* !_RPC_RPC_H */ diff --git a/tools/android/depends/libnfs/rpcinc/rpc_msg.h b/tools/android/depends/libnfs/rpcinc/rpc_msg.h new file mode 100644 index 0000000000..ec2d929c61 --- /dev/null +++ b/tools/android/depends/libnfs/rpcinc/rpc_msg.h @@ -0,0 +1,243 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)rpc_msg.h 1.7 86/07/16 SMI + * from: @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC + * $Id: rpc_msg.h,v 1.3 2004/10/28 21:58:24 emoy Exp $ + */ + +/* + * rpc_msg.h + * rpc message definition + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_RPCMSG_H +#define _RPC_RPCMSG_H + +#ifdef __LP64__ +#define RPC_MSG_VERSION ((unsigned int) 2) +#else +#define RPC_MSG_VERSION ((unsigned long) 2) +#endif +#define RPC_SERVICE_PORT ((unsigned short) 2048) + +/* + * Bottom up definition of an rpc message. + * NOTE: call and reply use the same overall stuct but + * different parts of unions within it. + */ + +enum msg_type { + CALL=0, + REPLY=1 +}; + +enum reply_stat { + MSG_ACCEPTED=0, + MSG_DENIED=1 +}; + +enum accept_stat { + SUCCESS=0, + PROG_UNAVAIL=1, + PROG_MISMATCH=2, + PROC_UNAVAIL=3, + GARBAGE_ARGS=4, + SYSTEM_ERR=5 +}; + +enum reject_stat { + RPC_MISMATCH=0, + AUTH_ERROR=1 +}; + +/* + * Reply part of an rpc exchange + */ + +/* + * Reply to an rpc request that was accepted by the server. + * Note: there could be an error even though the request was + * accepted. + */ +struct accepted_reply { + struct opaque_auth ar_verf; + enum accept_stat ar_stat; + union { + struct { +#ifdef __LP64__ + unsigned int low; + unsigned int high; +#else + unsigned long low; + unsigned long high; +#endif + } AR_versions; + struct { + caddr_t where; + xdrproc_t proc; + } AR_results; + /* and many other null cases */ + } ru; +#define ar_results ru.AR_results +#define ar_vers ru.AR_versions +}; + +/* + * Reply to an rpc request that was rejected by the server. + */ +struct rejected_reply { + enum reject_stat rj_stat; + union { + struct { +#ifdef __LP64__ + unsigned int low; + unsigned int high; +#else + unsigned long low; + unsigned long high; +#endif + } RJ_versions; + enum auth_stat RJ_why; /* why authentication did not work */ + } ru; +#define rj_vers ru.RJ_versions +#define rj_why ru.RJ_why +}; + +/* + * Body of a reply to an rpc request. + */ +struct reply_body { + enum reply_stat rp_stat; + union { + struct accepted_reply RP_ar; + struct rejected_reply RP_dr; + } ru; +#define rp_acpt ru.RP_ar +#define rp_rjct ru.RP_dr +}; + +/* + * Body of an rpc request call. + */ +struct call_body { +#ifdef __LP64__ + unsigned int cb_rpcvers; /* must be equal to two */ + unsigned int cb_prog; + unsigned int cb_vers; + unsigned int cb_proc; +#else + unsigned long cb_rpcvers; /* must be equal to two */ + unsigned long cb_prog; + unsigned long cb_vers; + unsigned long cb_proc; +#endif + struct opaque_auth cb_cred; + struct opaque_auth cb_verf; /* protocol specific - provided by client */ +}; + +/* + * The rpc message + */ +struct rpc_msg { +#ifdef __LP64__ + unsigned int rm_xid; +#else + unsigned long rm_xid; +#endif + enum msg_type rm_direction; + union { + struct call_body RM_cmb; + struct reply_body RM_rmb; + } ru; +#define rm_call ru.RM_cmb +#define rm_reply ru.RM_rmb +}; +#define acpted_rply ru.RM_rmb.ru.RP_ar +#define rjcted_rply ru.RM_rmb.ru.RP_dr + +__BEGIN_DECLS +/* + * XDR routine to handle a rpc message. + * xdr_callmsg(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callmsg __P((XDR *, struct rpc_msg *)); + +/* + * XDR routine to pre-serialize the static part of a rpc message. + * xdr_callhdr(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callhdr __P((XDR *, struct rpc_msg *)); + +/* + * XDR routine to handle a rpc reply. + * xdr_replymsg(xdrs, rmsg) + * XDR *xdrs; + * struct rpc_msg *rmsg; + */ +extern bool_t xdr_replymsg __P((XDR *, struct rpc_msg *)); + +/* + * Fills in the error part of a reply message. + * _seterr_reply(msg, error) + * struct rpc_msg *msg; + * struct rpc_err *error; + */ +extern void _seterr_reply __P((struct rpc_msg *, struct rpc_err *)); +__END_DECLS + +#endif /* !_RPC_RPCMSG_H */ diff --git a/tools/android/depends/libnfs/rpcinc/svc.h b/tools/android/depends/libnfs/rpcinc/svc.h new file mode 100644 index 0000000000..d671045f17 --- /dev/null +++ b/tools/android/depends/libnfs/rpcinc/svc.h @@ -0,0 +1,360 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)svc.h 1.20 88/02/08 SMI + * from: @(#)svc.h 2.2 88/07/29 4.0 RPCSRC + * $Id: svc.h,v 1.4 2004/11/25 19:41:19 emoy Exp $ + */ + +/* + * svc.h, Server-side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_SVC_H +#define _RPC_SVC_H +#include <sys/cdefs.h> + +/* + * This interface must manage two items concerning remote procedure calling: + * + * 1) An arbitrary number of transport connections upon which rpc requests + * are received. The two most notable transports are TCP and UDP; they are + * created and registered by routines in svc_tcp.c and svc_udp.c, respectively; + * they in turn call xprt_register and xprt_unregister. + * + * 2) An arbitrary number of locally registered services. Services are + * described by the following four data: program number, version number, + * "service dispatch" function, a transport handle, and a boolean that + * indicates whether or not the exported program should be registered with a + * local binder service; if true the program's number and version and the + * port number from the transport handle are registered with the binder. + * These data are registered with the rpc svc system via svc_register. + * + * A service's dispatch function is called whenever an rpc request comes in + * on a transport. The request's program and version numbers must match + * those of the registered service. The dispatch function is passed two + * parameters, struct svc_req * and SVCXPRT *, defined below. + */ + +enum xprt_stat { + XPRT_DIED, + XPRT_MOREREQS, + XPRT_IDLE +}; + +/* + * Server side transport handle + */ +typedef struct { + int xp_sock; + unsigned short xp_port; /* associated port number */ + struct xp_ops { +#ifdef __cplusplus + bool_t (*xp_recv)(...); /* receive incomming requests */ + enum xprt_stat (*xp_stat)(...); /* get transport status */ + bool_t (*xp_getargs)(...); /* get arguments */ + bool_t (*xp_reply)(...); /* send reply */ + bool_t (*xp_freeargs)(...);/* free mem allocated for args */ + void (*xp_destroy)(...); /* destroy this struct */ +#else + /* DO NOT REMOVE THE COMMENTED OUT ...: fixincludes needs to see them */ + bool_t (*xp_recv)(/*...*/); /* receive incomming requests */ + enum xprt_stat (*xp_stat)(/*...*/); /* get transport status */ + bool_t (*xp_getargs)(/*...*/); /* get arguments */ + bool_t (*xp_reply)(/*...*/); /* send reply */ + bool_t (*xp_freeargs)(/*...*/);/* free mem allocated for args */ + void (*xp_destroy)(/*...*/); /* destroy this struct */ +#endif + } *xp_ops; + int xp_addrlen; /* length of remote address */ + struct sockaddr_in xp_raddr; /* remote address */ + struct opaque_auth xp_verf; /* raw response verifier */ + caddr_t xp_p1; /* private */ + caddr_t xp_p2; /* private */ +} SVCXPRT; + +/* + * Approved way of getting address of caller + */ +#define svc_getcaller(x) (&(x)->xp_raddr) + +/* + * Operations defined on an SVCXPRT handle + * + * SVCXPRT *xprt; + * struct rpc_msg *msg; + * xdrproc_t xargs; + * caddr_t argsp; + */ +#define SVC_RECV(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) +#define svc_recv(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) + +#define SVC_STAT(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) +#define svc_stat(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) + +#define SVC_GETARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) +#define svc_getargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) + +#define SVC_REPLY(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) +#define svc_reply(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) + +#define SVC_FREEARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) +#define svc_freeargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) + +#define SVC_DESTROY(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) +#define svc_destroy(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) + + +/* + * Service request + */ +struct svc_req { +#ifdef __LP64__ + unsigned int rq_prog; /* service program number */ + unsigned int rq_vers; /* service protocol version */ + unsigned int rq_proc; /* the desired procedure */ +#else + unsigned long rq_prog; /* service program number */ + unsigned long rq_vers; /* service protocol version */ + unsigned long rq_proc; /* the desired procedure */ +#endif + struct opaque_auth rq_cred; /* raw creds from the wire */ + caddr_t rq_clntcred; /* read only cooked cred */ + SVCXPRT *rq_xprt; /* associated transport */ +}; + + +/* + * Service registration + * + * svc_register(xprt, prog, vers, dispatch, protocol) + * SVCXPRT *xprt; + * u_long prog; + * u_long vers; + * void (*dispatch)(...); // fixincludes needs the ..., even in a comment + * int protocol; like TCP or UDP, zero means do not register + */ +__BEGIN_DECLS +#ifdef __LP64__ +extern bool_t svc_register __P((SVCXPRT *, unsigned int, unsigned int, void (*)(), int)); +#else +extern bool_t svc_register __P((SVCXPRT *, unsigned long, unsigned long, void (*)(), int)); +#endif +__END_DECLS + +/* + * Service un-registration + * + * svc_unregister(prog, vers) + * u_long prog; + * u_long vers; + */ +__BEGIN_DECLS +#ifdef __LP64__ +extern void svc_unregister __P((unsigned int, unsigned int)); +#else +extern void svc_unregister __P((unsigned long, unsigned long)); +#endif +__END_DECLS + +/* + * Transport registration. + * + * xprt_register(xprt) + * SVCXPRT *xprt; + */ +__BEGIN_DECLS +extern void xprt_register __P((SVCXPRT *)); +__END_DECLS + +/* + * Transport un-register + * + * xprt_unregister(xprt) + * SVCXPRT *xprt; + */ +__BEGIN_DECLS +extern void xprt_unregister __P((SVCXPRT *)); +__END_DECLS + + + + +/* + * When the service routine is called, it must first check to see if it + * knows about the procedure; if not, it should call svcerr_noproc + * and return. If so, it should deserialize its arguments via + * SVC_GETARGS (defined above). If the deserialization does not work, + * svcerr_decode should be called followed by a return. Successful + * decoding of the arguments should be followed the execution of the + * procedure's code and a call to svc_sendreply. + * + * Also, if the service refuses to execute the procedure due to too- + * weak authentication parameters, svcerr_weakauth should be called. + * Note: do not confuse access-control failure with weak authentication! + * + * NB: In pure implementations of rpc, the caller always waits for a reply + * msg. This message is sent when svc_sendreply is called. + * Therefore pure service implementations should always call + * svc_sendreply even if the function logically returns void; use + * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows + * for the abuse of pure rpc via batched calling or pipelining. In the + * case of a batched call, svc_sendreply should NOT be called since + * this would send a return message, which is what batching tries to avoid. + * It is the service/protocol writer's responsibility to know which calls are + * batched and which are not. Warning: responding to batch calls may + * deadlock the caller and server processes! + */ + +__BEGIN_DECLS +extern bool_t svc_sendreply __P((SVCXPRT *, xdrproc_t, char *)); +extern void svcerr_decode __P((SVCXPRT *)); +extern void svcerr_weakauth __P((SVCXPRT *)); +extern void svcerr_noproc __P((SVCXPRT *)); +#ifdef __LP64__ +extern void svcerr_progvers __P((SVCXPRT *, unsigned int, unsigned int)); +#else +extern void svcerr_progvers __P((SVCXPRT *, unsigned long, unsigned long)); +#endif +extern void svcerr_auth __P((SVCXPRT *, enum auth_stat)); +extern void svcerr_noprog __P((SVCXPRT *)); +extern void svcerr_systemerr __P((SVCXPRT *)); +__END_DECLS + +/* + * Lowest level dispatching -OR- who owns this process anyway. + * Somebody has to wait for incoming requests and then call the correct + * service routine. The routine svc_run does infinite waiting; i.e., + * svc_run never returns. + * Since another (co-existant) package may wish to selectively wait for + * incoming calls or other events outside of the rpc architecture, the + * routine svc_getreq is provided. It must be passed readfds, the + * "in-place" results of a select system call (see select, section 2). + */ + +/* + * Global keeper of rpc service descriptors in use + * dynamic; must be inspected before each call to select + */ +#ifdef FD_SETSIZE +extern fd_set svc_fdset; +#define svc_fds svc_fdset.fds_bits[0] /* compatibility */ +#else +extern int svc_fds; +#endif /* def FD_SETSIZE */ + +/* + * a small program implemented by the svc_rpc implementation itself; + * also see clnt.h for protocol numbers. + */ +extern void rpctest_service(); + +__BEGIN_DECLS +extern void svc_getreq __P((int)); +extern void svc_getreqset __P((fd_set *)); +extern void svc_run __P((void)); +__END_DECLS + +/* + * Socket to use on svcxxx_create call to get default socket + */ +#define RPC_ANYSOCK -1 + +/* + * These are the existing service side transport implementations + */ + +/* + * Memory based rpc for testing and timing. + */ +__BEGIN_DECLS +extern SVCXPRT *svcraw_create __P((void)); +__END_DECLS + + +/* + * Udp based rpc. + */ +__BEGIN_DECLS +extern SVCXPRT *svcudp_create __P((int)); +extern SVCXPRT *svcudp_bufcreate __P((int, unsigned int, unsigned int)); +__END_DECLS + + +/* + * Tcp based rpc. + */ +__BEGIN_DECLS +extern SVCXPRT *svctcp_create __P((int, unsigned int, unsigned int)); +__END_DECLS + +/* + * Any open file descriptor based rpc. + */ +__BEGIN_DECLS +extern SVCXPRT *svcfd_create __P((int, u_int, u_int)); +__END_DECLS + +#endif /* !_RPC_SVC_H */ diff --git a/tools/android/depends/libnfs/rpcinc/svc_auth.h b/tools/android/depends/libnfs/rpcinc/svc_auth.h new file mode 100644 index 0000000000..3dc09591f2 --- /dev/null +++ b/tools/android/depends/libnfs/rpcinc/svc_auth.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)svc_auth.h 1.6 86/07/16 SMI + * from: @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC + * $Id: svc_auth.h,v 1.2 1999/10/14 21:56:54 wsanchez Exp $ + */ + +/* + * svc_auth.h, Service side of rpc authentication. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_SVCAUTH_H +#define _RPC_SVCAUTH_H + +/* + * Server side authenticator + */ +__BEGIN_DECLS +extern enum auth_stat _authenticate __P((struct svc_req *, struct rpc_msg *)); +__END_DECLS + +#endif /* !_RPC_SVCAUTH_H */ diff --git a/tools/android/depends/libnfs/rpcinc/types.h b/tools/android/depends/libnfs/rpcinc/types.h new file mode 100644 index 0000000000..0fe5adc1c0 --- /dev/null +++ b/tools/android/depends/libnfs/rpcinc/types.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)types.h 1.18 87/07/24 SMI + * from: @(#)types.h 2.3 88/08/15 4.0 RPCSRC + * $Id: types.h,v 1.4 2003/10/16 22:15:15 majka Exp $ + */ + +/* + * Rpc additions to <sys/types.h> + */ +#ifndef _RPC_TYPES_H +#define _RPC_TYPES_H + +#define bool_t int +#define enum_t int +#define __dontcare__ -1 + +#ifndef FALSE +# define FALSE (0) +#endif +#ifndef TRUE +# define TRUE (1) +#endif + +#ifndef NULL +#ifdef __GNUG__ +#define NULL __null +#else /* ! __GNUG__ */ +#ifndef __cplusplus +#define NULL ((void *)0) +#else /* __cplusplus */ +#define NULL 0 +#endif /* ! __cplusplus */ +#endif /* __GNUG__ */ +#endif /* ! NULL */ + +#define mem_alloc(bsize) calloc(1, bsize) +#define mem_free(ptr, bsize) free(ptr) + +#ifndef makedev /* ie, we haven't already included it */ +#include <sys/types.h> +#endif +#include <sys/time.h> + +#ifdef __LP64__ +typedef int rpc_int; +typedef unsigned int rpc_uint; +#else +typedef long rpc_int; +typedef unsigned long rpc_uint; +#endif + +#endif /* !_RPC_TYPES_H */ diff --git a/tools/android/depends/libnfs/rpcinc/xdr.h b/tools/android/depends/libnfs/rpcinc/xdr.h new file mode 100644 index 0000000000..60bc672407 --- /dev/null +++ b/tools/android/depends/libnfs/rpcinc/xdr.h @@ -0,0 +1,431 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + * from: @(#)xdr.h 1.19 87/04/22 SMI + * from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC + * $FreeBSD: src/include/rpc/xdr.h,v 1.23 2003/03/07 13:19:40 nectar Exp $ + */ + +/* + * xdr.h, External Data Representation Serialization Routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_XDR_H +#define _RPC_XDR_H +#include <sys/cdefs.h> +#include <sys/types.h> +#include <sys/select.h> +#include <linux/coda.h> +/* + * XDR provides a conventional way for converting between C data + * types and an external bit-string representation. Library supplied + * routines provide for the conversion on built-in C data types. These + * routines and utility routines defined here are used to help implement + * a type encode/decode routine for each user-defined type. + * + * Each data type provides a single procedure which takes two arguments: + * + * bool_t + * xdrproc(xdrs, argresp) + * XDR *xdrs; + * <type> *argresp; + * + * xdrs is an instance of a XDR handle, to which or from which the data + * type is to be converted. argresp is a pointer to the structure to be + * converted. The XDR handle contains an operation field which indicates + * which of the operations (ENCODE, DECODE * or FREE) is to be performed. + * + * XDR_DECODE may allocate space if the pointer argresp is null. This + * data can be freed with the XDR_FREE operation. + * + * We write only one procedure per data type to make it easy + * to keep the encode and decode procedures for a data type consistent. + * In many cases the same code performs all operations on a user defined type, + * because all the hard work is done in the component type routines. + * decode as a series of calls on the nested data types. + */ + +/* + * Xdr operations. XDR_ENCODE causes the type to be encoded into the + * stream. XDR_DECODE causes the type to be extracted from the stream. + * XDR_FREE can be used to release the space allocated by an XDR_DECODE + * request. + */ +enum xdr_op { + XDR_ENCODE=0, + XDR_DECODE=1, + XDR_FREE=2 +}; +/* + * This is the number of bytes per unit of external data. + */ +#define BYTES_PER_XDR_UNIT (4) +#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ + * BYTES_PER_XDR_UNIT) + +/* + * The XDR handle. + * Contains operation which is being applied to the stream, + * an operations vector for the particular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular implementation. + */ +typedef struct __rpc_xdr { + enum xdr_op x_op; /* operation; fast additional param */ + const struct xdr_ops { +#ifdef __LP64__ + /* get an int from underlying stream */ + bool_t (*x_getlong)(struct __rpc_xdr *, int *); + /* put an int to " */ + bool_t (*x_putlong)(struct __rpc_xdr *, const int *); +#else + /* get a long from underlying stream */ + bool_t (*x_getlong)(struct __rpc_xdr *, long *); + /* put a long to " */ + bool_t (*x_putlong)(struct __rpc_xdr *, const long *); +#endif + /* get some bytes from " */ + bool_t (*x_getbytes)(struct __rpc_xdr *, char *, unsigned int); + /* put some bytes to " */ + bool_t (*x_putbytes)(struct __rpc_xdr *, const char *, unsigned int); + /* returns bytes off from beginning */ + unsigned int (*x_getpostn)(struct __rpc_xdr *); + /* lets you reposition the stream */ + bool_t (*x_setpostn)(struct __rpc_xdr *, unsigned int); + /* buf quick ptr to buffered data */ + int32_t *(*x_inline)(struct __rpc_xdr *, unsigned int); + /* free privates of this xdr_stream */ + void (*x_destroy)(struct __rpc_xdr *); + bool_t (*x_control)(struct __rpc_xdr *, int, void *); + } *x_ops; + char * x_public; /* users' data */ + void * x_private; /* pointer to private data */ + char * x_base; /* private used for position info */ + unsigned int x_handy; /* extra private word */ +} XDR; + +/* + * A xdrproc_t exists for each data type which is to be encoded or decoded. + * + * The second argument to the xdrproc_t is a pointer to an opaque pointer. + * The opaque pointer generally points to a structure of the data type + * to be decoded. If this pointer is 0, then the type routines should + * allocate dynamic storage of the appropriate size and return it. + */ +#ifdef _KERNEL +typedef bool_t (*xdrproc_t)(XDR *, void *, unsigned int); +#else +/* + * XXX can't actually prototype it, because some take three args!!! + */ +typedef bool_t (*xdrproc_t)(XDR *, ...); +#endif + +/* + * Operations defined on a XDR handle + * + * XDR *xdrs; + * long *longp; + * char * addr; + * unsigned int len; + * unsigned int pos; + */ +#define XDR_GETLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) +#define xdr_getlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) + +#define XDR_PUTLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) +#define xdr_putlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) + + +#ifdef __LP64__ +static __inline int +xdr_getint32(XDR *xdrs, int32_t *ip) +{ + int32_t l; + + if (!xdr_getlong(xdrs, &l)) + return (FALSE); + *ip = l; + return (TRUE); +} + +static __inline int +xdr_putint32(XDR *xdrs, int32_t *ip) +{ + int32_t l; + + l = *ip; + return xdr_putlong(xdrs, &l); +} +#else +static __inline int +xdr_getint32(XDR *xdrs, int32_t *ip) +{ + int32_t l; + + if (!xdr_getlong(xdrs, (long *)&l)) + return (FALSE); + *ip = l; + return (TRUE); +} + +static __inline int +xdr_putint32(XDR *xdrs, int32_t *ip) +{ + int32_t l; + + l = *ip; + return xdr_putlong(xdrs, (long *)&l); +} +#endif + +#define XDR_GETINT32(xdrs, int32p) xdr_getint32(xdrs, int32p) +#define XDR_PUTINT32(xdrs, int32p) xdr_putint32(xdrs, int32p) + +#define XDR_GETBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) +#define xdr_getbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) + +#define XDR_PUTBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) +#define xdr_putbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) + +#define XDR_GETPOS(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) +#define xdr_getpos(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) + +#define XDR_SETPOS(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) +#define xdr_setpos(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) + +#define XDR_INLINE(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) +#define xdr_inline(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) + +#define XDR_DESTROY(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) +#define xdr_destroy(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) + +#define XDR_CONTROL(xdrs, req, op) \ + if ((xdrs)->x_ops->x_control) \ + (*(xdrs)->x_ops->x_control)(xdrs, req, op) +#define xdr_control(xdrs, req, op) XDR_CONTROL(xdrs, req, op) + +/* + * Solaris strips the '_t' from these types -- not sure why. + * But, let's be compatible. + */ +#define xdr_rpcvers(xdrs, versp) xdr_u_int32(xdrs, versp) +#define xdr_rpcprog(xdrs, progp) xdr_u_int32(xdrs, progp) +#define xdr_rpcproc(xdrs, procp) xdr_u_int32(xdrs, procp) +#define xdr_rpcprot(xdrs, protp) xdr_u_int32(xdrs, protp) +#define xdr_rpcport(xdrs, portp) xdr_u_int32(xdrs, portp) + +/* + * Support struct for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * an entry with a null procedure pointer. The xdr_union routine gets + * the discriminant value and then searches the array of structures + * for a matching value. If a match is found the associated xdr routine + * is called to handle that part of the union. If there is + * no match, then a default routine may be called. + * If there is no match and no default routine it is an error. + */ +#define NULL_xdrproc_t ((xdrproc_t)0) +struct xdr_discrim { + int value; + xdrproc_t proc; +}; + +/* + * In-line routines for fast encode/decode of primitive data types. + * Caveat emptor: these use single memory cycles to get the + * data from the underlying buffer, and will fail to operate + * properly if the data is not aligned. The standard way to use these + * is to say: + * if ((buf = XDR_INLINE(xdrs, count)) == NULL) + * return (FALSE); + * <<< macro calls >>> + * where ``count'' is the number of bytes of data occupied + * by the primitive data types. + * + * N.B. and frozen for all time: each data type here uses 4 bytes + * of external representation. + */ +#define IXDR_GET_INT32(buf) ((int32_t)ntohl((u_int32_t)*(buf)++)) +#define IXDR_PUT_INT32(buf, v) (*(buf)++ =(int32_t)htonl((u_int32_t)v)) +#define IXDR_GET_U_INT32(buf) ((u_int32_t)IXDR_GET_INT32(buf)) +#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32((buf), ((int32_t)(v))) + +#ifdef __LP64__ +#define IXDR_GET_LONG(buf) (ntohl((u_int32_t)*(buf)++)) +#define IXDR_PUT_LONG(buf, v) (*(buf)++ = htonl((u_int32_t)v)) +#else +#define IXDR_GET_LONG(buf) ((long)ntohl((u_int32_t)*(buf)++)) +#define IXDR_PUT_LONG(buf, v) (*(buf)++ =(int32_t)htonl((u_int32_t)v)) +#endif + +#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) +#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) +#ifdef __LP64__ +#define IXDR_GET_U_LONG(buf) ((unsigned int)IXDR_GET_LONG(buf)) +#else +#define IXDR_GET_U_LONG(buf) ((unsigned long)IXDR_GET_LONG(buf)) +#endif +#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_SHORT(buf) ((unsigned short)IXDR_GET_LONG(buf)) + +#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), (v)) +#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), (v)) +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), (v)) +#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), (v)) +#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), (v)) + +/* + * These are the "generic" xdr routines. + */ +__BEGIN_DECLS +extern bool_t xdr_void(void); +extern bool_t xdr_int(XDR *, int *); +extern bool_t xdr_u_int(XDR *, unsigned int *); +#ifdef __LP64__ +extern bool_t xdr_long(XDR *, int *); +extern bool_t xdr_u_long(XDR *, unsigned int *); +#else +extern bool_t xdr_long(XDR *, long *); +extern bool_t xdr_u_long(XDR *, unsigned long *); +#endif +extern bool_t xdr_short(XDR *, short *); +extern bool_t xdr_u_short(XDR *, unsigned short *); +extern bool_t xdr_int16_t(XDR *, int16_t *); +extern bool_t xdr_u_int16_t(XDR *, u_int16_t *); +extern bool_t xdr_int32_t(XDR *, int32_t *); +extern bool_t xdr_u_int32_t(XDR *, u_int32_t *); +extern bool_t xdr_int64_t(XDR *, int64_t *); +extern bool_t xdr_u_int64_t(XDR *, u_int64_t *); +extern bool_t xdr_bool(XDR *, bool_t *); +extern bool_t xdr_enum(XDR *, enum_t *); +extern bool_t xdr_array(XDR *, char **, unsigned int *, unsigned int, unsigned int, xdrproc_t); +extern bool_t xdr_bytes(XDR *, char **, unsigned int *, unsigned int); +extern bool_t xdr_opaque(XDR *, char *, unsigned int); +extern bool_t xdr_string(XDR *, char **, unsigned int); +extern bool_t xdr_union(XDR *, enum_t *, char *, const struct xdr_discrim *, xdrproc_t); +extern bool_t xdr_char(XDR *, char *); +extern bool_t xdr_u_char(XDR *, unsigned char *); +extern bool_t xdr_vector(XDR *, char *, unsigned int, unsigned int, xdrproc_t); +extern bool_t xdr_float(XDR *, float *); +extern bool_t xdr_double(XDR *, double *); +extern bool_t xdr_quadruple(XDR *, long double *); +extern bool_t xdr_reference(XDR *, char **, unsigned int, xdrproc_t); +extern bool_t xdr_pointer(XDR *, char **, unsigned int, xdrproc_t); +extern bool_t xdr_wrapstring(XDR *, char **); +extern void xdr_free(xdrproc_t, void *); +extern bool_t xdr_hyper(XDR *, u_quad_t *); +extern bool_t xdr_u_hyper(XDR *, u_quad_t *); +extern bool_t xdr_longlong_t(XDR *, u_quad_t *); +extern bool_t xdr_u_longlong_t(XDR *, u_quad_t *); +__END_DECLS + +/* + * Common opaque bytes objects used by many rpc protocols; + * declared here due to commonality. + */ +#define MAX_NETOBJ_SZ 1024 +struct netobj { + unsigned int n_len; + char *n_bytes; +}; +typedef struct netobj netobj; +extern bool_t xdr_netobj(XDR *, struct netobj *); + +/* + * These are the public routines for the various implementations of + * xdr streams. + */ +__BEGIN_DECLS +/* XDR using memory buffers */ +extern void xdrmem_create(XDR *, char *, unsigned int, enum xdr_op); + +/* XDR using stdio library */ +#ifdef _STDIO_H_ +extern void xdrstdio_create(XDR *, FILE *, enum xdr_op); +#endif + +/* XDR pseudo records for tcp */ +extern void xdrrec_create(XDR *, unsigned int, unsigned int, void *, + int (*)(void *, void *, int), + int (*)(void *, void *, int)); + +/* make end of xdr record */ +extern bool_t xdrrec_endofrecord(XDR *, int); + +/* move to beginning of next record */ +extern bool_t xdrrec_skiprecord(XDR *); + +/* true if no more input */ +extern bool_t xdrrec_eof(XDR *); +extern unsigned int xdrrec_readbytes(XDR *, caddr_t, unsigned int); +__END_DECLS + +#endif /* !_RPC_XDR_H */ diff --git a/tools/android/depends/libogg/Makefile b/tools/android/depends/libogg/Makefile new file mode 100644 index 0000000000..4a84d34d97 --- /dev/null +++ b/tools/android/depends/libogg/Makefile @@ -0,0 +1,46 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libogg +VERSION=1.1.4 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) + +LIBDYLIB=$(PLATFORM)/src/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libogg.la $(PREFIX)/lib/libogg.so $(PREFIX)/lib/libogg.so.0 + mv -f $(PREFIX)/lib/libogg.so.0.6.0 $(PREFIX)/lib/libxbogg.so + ln -sf $(PREFIX)/lib/libxbogg.so $(PREFIX)/lib/libogg.so + $(RPL) -e "libogg.so.0" "libxbogg.so" $(PREFIX)/lib/libxbogg.so + -$(READELF) --dynamic $(PREFIX)/lib/libxbogg.so | grep ibrary + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libomxil-bellagio/Makefile b/tools/android/depends/libomxil-bellagio/Makefile new file mode 100644 index 0000000000..d1317f885d --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/Makefile @@ -0,0 +1,43 @@ +include ../Makefile.include +DEPS= ../Makefile.include android-fix-build.patch Makefile oscl/* + +# lib name, version +LIBNAME=libomxil-bellagio +VERSION=0.9.3 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +# configuration settings +CFLAGS+=-I$(CURDIR)/oscl +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared \ + --enable-android ac_cv_func_malloc_0_nonnull=yes + +LIBDYLIB=$(PLATFORM)/src/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) "$(BASE_URL)/$(ARCHIVE)" + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 < ../android-fix-build.patch + cd $(PLATFORM); autoreconf -vif + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -j 1 -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/libomxil-bellagio/android-fix-build.patch b/tools/android/depends/libomxil-bellagio/android-fix-build.patch new file mode 100644 index 0000000000..a6e61db326 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/android-fix-build.patch @@ -0,0 +1,33 @@ +diff -ruN armeabi-v7a/configure.ac armeabi-v7a-good/configure.ac +--- armeabi-v7a/configure.ac 2011-05-20 01:44:18.000000000 -0400 ++++ armeabi-v7a-good/configure.ac 2012-06-19 01:58:45.483524179 -0400 +@@ -5,7 +5,7 @@ + AC_PREREQ([2.59]) + + AC_CONFIG_HEADERS([config.h]) +-CFLAGS="${CFLAGS} -Wall -Werror" ++CFLAGS="${CFLAGS} -Wall" + + ################################################################################ + # Set the shared versioning info, according to section 6.3 of the libtool info # +@@ -149,8 +149,6 @@ + # Check for libraries # + ################################################################################ + +-AC_CHECK_LIB([pthread], [pthread_create]) +- + # Check for libdl + AC_SEARCH_LIBS([dlopen], [dl], [], [AC_MSG_ERROR([libdl is required])]) + +diff -ruN armeabi-v7a/src/Makefile.am armeabi-v7a-good/src/Makefile.am +--- armeabi-v7a/src/Makefile.am 2011-05-20 01:28:17.000000000 -0400 ++++ armeabi-v7a-good/src/Makefile.am 2012-06-19 01:59:23.603524155 -0400 +@@ -27,7 +27,7 @@ + + libomxil_bellagio_la_CFLAGS = -I$(top_srcdir)/include -I$(srcdir)/base -I$(srcdir)/core_extensions \ + -DINSTALL_PATH_STR=\"$(plugindir)\" -DOMX_LOADERS_DIRNAME=\"$(libdir)/omxloaders\/\" +-libomxil_bellagio_la_LIBADD = base/libomxbase.la core_extensions/libomxcoreext.la -lpthread ++libomxil_bellagio_la_LIBADD = base/libomxbase.la core_extensions/libomxcoreext.la + libomxil_bellagio_la_LDFLAGS = -version-info @SHARED_VERSION_INFO@ + + include_extradir = $(includedir)/bellagio diff --git a/tools/android/depends/libomxil-bellagio/oscl/oscl_base_macros.h b/tools/android/depends/libomxil-bellagio/oscl/oscl_base_macros.h new file mode 100644 index 0000000000..30fc86863d --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/oscl_base_macros.h @@ -0,0 +1,159 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2010 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L B A S E _ M A C R O S + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +/*! \addtogroup osclbase OSCL Base + * + * @{ + */ + + +/*! \file oscl_base_macros.h + \brief This file defines common macros and constants for basic compilation support. +*/ + +#ifndef OSCL_BASE_MACROS_H_INCLUDED +#define OSCL_BASE_MACROS_H_INCLUDED + +// Pick up any platform-specific definitions for the common +// macros. +#include "osclconfig.h" + +// Define default values for the common macros +#ifndef OSCL_EXPORT_REF +#define OSCL_EXPORT_REF +#endif + +#ifndef OSCL_IMPORT_REF +#define OSCL_IMPORT_REF +#endif + +//! The NULL_TERM_CHAR is used to terminate c-style strings. +//static const char NULL_TERM_CHAR = '\0'; +#ifndef NULL_TERM_CHAR +#define NULL_TERM_CHAR '\0' +#endif + +//! if the NULL macro isn't already defined, then define it as zero. +#ifndef NULL +#define NULL (0) +#endif + +#if (OSCL_DISABLE_INLINES) +#define OSCL_INLINE +#define OSCL_COND_EXPORT_REF OSCL_EXPORT_REF +#define OSCL_COND_IMPORT_REF OSCL_IMPORT_REF +#else +#define OSCL_INLINE inline +#define OSCL_COND_EXPORT_REF +#define OSCL_COND_IMPORT_REF +#endif + +//this macro may not be defined in all configurations +//so a default is defined here. + +//! Type casting macros +/*! + \param type Destination type of cast + \param exp Expression to cast +*/ + +#define OSCL_CONST_CAST(type,exp) ((type)(exp)) +#define OSCL_STATIC_CAST(type,exp) ((type)(exp)) +#define OSCL_REINTERPRET_CAST(type,exp) ((type)(exp)) +#define OSCL_DYNAMIC_CAST(type, exp) ((type)(exp)) +#define OSCL_VIRTUAL_BASE(type) type + + +/** + * The following two macros are used to avoid compiler warnings. + * + * OSCL_UNUSED_ARG(vbl) is used to "reference" an otherwise unused + * parameter or variable, often one which is used only in an + * OSCL_ASSERT and thus unreferenced in release mode + * OSCL_UNUSED_RETURN(val) provides a "return" of a value, in places + * which will not actually be executed, such as after an + * OSCL_LEAVE or Thread::exit or abort. The value needs to + * be of an appropriate type for the current function, though + * zero will usually suffice. Note that OSCL_UNUSED_RETURN + * will not be necessary for 'void' functions, as there is no + * requirement for a value-return operation. + */ +#define OSCL_UNUSED_ARG(vbl) (void)(vbl) +#define OSCL_UNUSED_RETURN(value) return value + +/* The __TFS__ macro is used to optionally expand to "<>" depending on the + * compiler. Some compilers require it to indicate that the friend function + * is a template function as specified in the standard, but others don't + * like it so it will handled with a macro expansion that depends on the + * compiler. + */ +#ifndef __TFS__ +#define __TFS__ +#endif + +#define OSCL_MIN(a,b) ((a) < (b) ? (a) : (b)) +#define OSCL_MAX(a,b) ((a) > (b) ? (a) : (b)) +#define OSCL_ABS(a) ((a) > (0) ? (a) : -(a)) + +// the syntax for explicitly calling the destructor varies on some platforms +// below is the default syntax as defined in the C++ standard +#ifndef OSCL_TEMPLATED_DESTRUCTOR_CALL +#define OSCL_TEMPLATED_DESTRUCTOR_CALL(type,simple_type) type :: ~simple_type () +#endif + + +/* + * The OSCL_UNSIGNED_CONST macro is used to optionally add a suffix to the + * end of integer constants to identify them as unsigned constants. It is + * usually only necessary to do that for very large constants that are too + * big to fit within the range of a signed integer. Some compilers will issue + * warnings for that. The default behavior will be to add no suffix. + */ + +#ifndef OSCL_UNSIGNED_CONST +#define OSCL_UNSIGNED_CONST(x) x +#endif + +/* + * These macros are used by MTP to avoid byte aligning structures. + */ +#ifndef OSCL_PACKED_VAR +#define OSCL_PACKED_VAR "error" +#endif + + +/* The following macros enumerate the possible values of the build flag PV_COMPILER */ + +#define EPV_ARM_GNUC 1 /* for GNU compiler */ +#define EPV_ARM_RVCT 2 /* for RVCT compiler from ARM */ +#define EPV_ARM_MSEVC 3 /* for MS Embedded VC compiler */ + +/* PV_COMPILER value must be set to build command. + In addition, PV_CPU_ARCH_VERSION must be defined to take on an integer value that specifies the version of target + ARM architecture. */ + + +/*! @} */ + +#endif // OSCL_BASE_MACROS_H_INCLUDED diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig.h new file mode 100644 index 0000000000..e664e19008 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig.h @@ -0,0 +1,105 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2010 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G ( P L A T F O R M C O N F I G I N F O ) + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig.h + * \brief This file contains configuration information for the linux platform + * + */ + +#ifndef OSCLCONFIG_H_INCLUDED +#define OSCLCONFIG_H_INCLUDED + +// system includes for dynamic registry +#include <dirent.h> +#include <dlfcn.h> + +#define OSCL_HAS_ANDROID_SUPPORT 1 +#define OSCL_HAS_ANDROID_FILE_IO_SUPPORT 1 + +#define OSCL_EXPORT_REF __attribute__ ((visibility("default"))) +#define OSCL_IMPORT_REF __attribute__ ((visibility("default"))) + +// include common include for determining sizes from limits.h +#include "osclconfig_limits_typedefs.h" + +//This switch turns off some profiling and debug settings +#ifndef OSCL_RELEASE_BUILD +#ifdef NDEBUG +#define OSCL_RELEASE_BUILD 1 +#else +#define OSCL_RELEASE_BUILD 0 +#endif +#endif + +#ifndef PVLOGGER_INST_LEVEL +#if (OSCL_RELEASE_BUILD) +//Release mode logging - should be kept minimum +#define PVLOGGER_INST_LEVEL 2 +#else +//full logging +#define PVLOGGER_INST_LEVEL 5 +#endif +#endif + +// include common unix definitions +#include "osclconfig_unix_android.h" + +// define the suffix for unsigned constants +#define OSCL_UNSIGNED_CONST(x) x##u + +// override the common definition for +#undef OSCL_NATIVE_UINT64_TYPE +#define OSCL_NATIVE_UINT64_TYPE u_int64_t + +// include the definitions for the processor +#include "osclconfig_ix86.h" + +// the syntax for explicitly calling the destructor varies on some platforms +// below is the default syntax as defined by another ARM project +#define OSCL_TEMPLATED_DESTRUCTOR_CALL(type,simple_type) ~type () + + +/* The __TFS__ macro is used to optionally expand to "<>" depending on the + * compiler. Some compilers require it to indicate that the friend function + * is a template function as specified in the standard, but others don't + * like it so it will handled with a macro expansion that depends on the + * compiler. + */ +#define __TFS__ <> + +#define OSCL_HAS_PRAGMA_PACK 0 +#define OSCL_HAS_PACKED_STRUCT 1 +#define OSCL_PACKED_VAR(x) x __attribute__((packed)) +#define OSCL_PACKED_STRUCT_BEGIN +#define OSCL_PACKED_STRUCT_END __attribute__((packed)) + +//set this to 1 to enable OSCL_ASSERT in release builds. +#define OSCL_ASSERT_ALWAYS 0 + + +// check all osclconfig required macros are defined +#include "osclconfig_check.h" + +#endif diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_ansi_memory.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_ansi_memory.h new file mode 100644 index 0000000000..fb53ea1326 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_ansi_memory.h @@ -0,0 +1,42 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G _ A N S I _ M E M O R Y + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig_ansi_memory.h + * \brief This file contains common typedefs based on the ANSI C limits.h header + * + * This header file should work for any ANSI C compiler to determine the + * proper native C types to use for OSCL integer types. + */ + + +#ifndef OSCLCONFIG_ANSI_MEMORY_H_INCLUDED +#define OSCLCONFIG_ANSI_MEMORY_H_INCLUDED + +#include <memory.h> +typedef size_t oscl_memsize_t; +#define OSCL_HAS_ANSI_MEMORY_FUNCS 1 + + +#endif diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_check.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_check.h new file mode 100644 index 0000000000..19d0b63e61 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_check.h @@ -0,0 +1,423 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2010 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#ifndef OSCLCONFIG_CHECK_H_INCLUDED +#define OSCLCONFIG_CHECK_H_INCLUDED + +/*! \addtogroup osclconfig OSCL config + * + * @{ + */ + +/** +\def Make sure the basic types are defined, +either in osclconfig_limits_typedefs.h or elsewhere. +*/ +typedef int8 __int8__check__; +typedef uint8 __uint8__check__; +typedef int16 __int16__check__; +typedef uint16 __uint16__check__; +typedef int32 __int32__check__; +typedef uint32 __uint32__check__; + +/** +\def OSCL_ASSERT_ALWAYS macro should be set to 0 or 1. +When set to 1, OSCL_ASSERT will be compiled in release mode as well +as debug mode. +*/ +#ifndef OSCL_ASSERT_ALWAYS +#error "ERROR: OSCL_ASSERT_ALWAYS has to be defined to either 1 or 0." +#endif + + +/** +\def OSCL_DISABLE_INLINES macro should be set to 1 if +the target compiler supports 'inline' function definitions. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_DISABLE_INLINES +#error "ERROR: OSCL_DISABLE_INLINES has to be defined to either 1 or 0." +#endif + +/** +\def OSCL_HAS_ANSI_STDLIB_SUPPORT macro should be set to 1 if +the target compiler supports ANSI C standard lib functions. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_ANSI_STDLIB_SUPPORT +#error "ERROR: OSCL_HAS_ANSI_STDLIB_SUPPORT has to be defined to either 1 or 0." +#endif + +/** +\def OSCL_HAS_ANSI_STDIO_SUPPORT macro should be set to 1 if +the target compiler supports ANSI C standard I/O functions. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_ANSI_STDIO_SUPPORT +#error "ERROR: OSCL_HAS_ANSI_STDIO_SUPPORT has to be defined to either 1 or 0." +#endif + +/** +\def OSCL_HAS_ANSI_STRING_SUPPORT macro should be set to 1 if +the target compiler supports ANSI C standard string functions. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_ANSI_STRING_SUPPORT +#error "ERROR: OSCL_HAS_ANSI_STRING_SUPPORT has to be defined to either 1 or 0." +#endif + +/** +\def OSCL_HAS_UNICODE_SUPPORT macro should be set to 1 if +the target platform has a native 16-bit (wide) character type. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_UNICODE_SUPPORT +#error "ERROR: OSCL_HAS_UNICODE_SUPPORT has to be defined to either 1 or 0." +#endif + +/** +\def _STRLIT macro should be set to an expression to convert +a constant character string into a string literal type +appropriate for the platform. +Otherwise it should be set to 0. +*/ +#ifndef _STRLIT +#error "ERROR: _STRLIT has to be defined." +#endif + +/** +\def _STRLIT_CHAR macro should be set to an expression to convert +a constant character string into a char string literal type +appropriate for the platform. +Otherwise it should be set to 0. +*/ +#ifndef _STRLIT_CHAR +#error "ERROR: _STRLIT_CHAR has to be defined." +#endif + +/** +When OSCL_HAS_UNICODE_SUPPORT==1, +\def _STRLIT_WCHAR macro should be set to an expression to convert +a constant character string into a wchar string literal type +appropriate for the platform. +Otherwise it should be set to 0. +*/ +#if (OSCL_HAS_UNICODE_SUPPORT) && !defined(_STRLIT_WCHAR) +#error "ERROR: _STRLIT_WCHAR has to be defined" +#endif + +/** +When OSCL_HAS_UNICODE_SUPPORT==1, +\def OSCL_NATIVE_WCHAR_TYPE macro should be set to +the native wide character type for the platform. +Otherwise it should be set to 0. +*/ +#if (OSCL_HAS_UNICODE_SUPPORT) && !defined(OSCL_NATIVE_WCHAR_TYPE) +#error "ERROR: OSCL_NATIVE_WCHAR_TYPE has to be defined." +#endif + +/** +\def OSCL_HAS_MSWIN_SUPPORT macro should be set to 1 if +the target platform supports the Win32 API. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_MSWIN_SUPPORT +#error "ERROR: OSCL_HAS_MSWIN_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +\def OSCL_HAS_MSWIN_PARTIAL_SUPPORT macro should be set to 1 if +the target platform supports the WinMobile API. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_MSWIN_PARTIAL_SUPPORT +#error "ERROR: OSCL_HAS_MSWIN_PARTIAL_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +\def OSCL_HAS_UNIX_SUPPORT macro should be set to 1 if +the target platform supports the Unix API. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_UNIX_SUPPORT +#error "ERROR: OSCL_HAS_UNIX_SUPPORT has to be defined to either 1 or 0." +#endif + +/** +\def OSCL_HAS_SYMBIAN_SUPPORT macro should be set to 1 if +the target platform supports the Symbian API. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_SYMBIAN_SUPPORT +#error "ERROR: OSCL_HAS_SYMBIAN_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +\def OSCL_HAS_ANDROID_SUPPORT macro should be set to 1 if +the target platform supports the Android API. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_ANDROID_SUPPORT +#error "ERROR: OSCL_HAS_ANDROID_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +\def OSCL_HAS_IPHONE_SUPPORT macro should be set to 1 if +the target platform supports the iPhone API. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_IPHONE_SUPPORT +#error "ERROR: OSCL_HAS_IPHONE_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +\def OSCL_INTEGERS_WORD_ALIGNED macro should be set to 1 if +the target platform requires integers to be word-aligned in memory. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_INTEGERS_WORD_ALIGNED +#error "ERROR: OSCL_INTEGERS_WORD_ALIGNED has to be defined to either 1 or 0." +#endif + +/** +\def OSCL_BYTE_ORDER_BIG_ENDIAN macro should be set to 1 if +the target platform uses big-endian byte order in memory. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_BYTE_ORDER_BIG_ENDIAN +#error "ERROR: OSCL_BYTE_ORDER_BIG_ENDIAN has to be defined to either 1 or 0." +#endif + +/** +\def OSCL_BYTE_ORDER_LITTLE_ENDIAN macro should be set to 1 if +the target platform uses little-endian byte order in memory. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_BYTE_ORDER_LITTLE_ENDIAN +#error "ERROR: OSCL_BYTE_ORDER_LITTLE_ENDIAN has to be defined to either 1 or 0." +#endif + +/** +\def Either OSCL_BYTE_ORDER_BIG_ENDIAN must be set to 1 +or else OSCL_BYTE_ORDER_LITTLE_ENDIAN must be set to 1. +*/ +#if !(OSCL_BYTE_ORDER_BIG_ENDIAN) && !(OSCL_BYTE_ORDER_LITTLE_ENDIAN) +#error "ERROR: either OSCL_BYTE_ORDER_LITTLE_ENDIAN or else OSCL_BYTE_ORDER_BIG_ENDIAN must be 1." +#endif +#if (OSCL_BYTE_ORDER_BIG_ENDIAN) && (OSCL_BYTE_ORDER_LITTLE_ENDIAN) +#error "ERROR: either OSCL_BYTE_ORDER_LITTLE_ENDIAN or else OSCL_BYTE_ORDER_BIG_ENDIAN must be 1." +#endif + +/** +\def OSCL_HAS_GLOBAL_VARIABLE_SUPPORT macro should be set to 1 if +the target platform allows global variable definitions. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_GLOBAL_VARIABLE_SUPPORT +#error "ERROR: OSCL_HAS_GLOBAL_VARIABLE_SUPPORT has to be defined to either 1 or 0." +#endif + +/** +Note: only one byte order mode can be defined per platform. +*/ +#if (OSCL_BYTE_ORDER_LITTLE_ENDIAN) && (OSCL_BYTE_ORDER_BIG_ENDIAN) +#error "ERROR: Multiple selection for OSCL_BYTE_ORDER." +#endif + +/** +\def OSCL_HAS_ANSI_STRING_SUPPORT macro should be set to 1 if +the target platform supports C standard string functions (string.h). +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_ANSI_STRING_SUPPORT +#error "ERROR: OSCL_HAS_ANSI_STRING_SUPPORT has to be defined to either 1 or 0." +#endif + +/** +\def OSCL_NATIVE_INT64_TYPE has to be defined to the native +signed 64-bit integer type. +*/ +#ifndef OSCL_NATIVE_INT64_TYPE +#error "ERROR: OSCL_NATIVE_INT64_TYPE has to be defined." +#endif + +/** +\def OSCL_NATIVE_UINT64_TYPE has to be defined to the native +unsigned 64-bit integer type. +*/ +#ifndef OSCL_NATIVE_UINT64_TYPE +#error "ERROR: OSCL_NATIVE_UINT64_TYPE has to be defined." +#endif + +/** +\def INT64(x) has to be defined to the expression for a signed +64-bit literal. +*/ +#ifndef INT64 +#error "ERROR: INT64(x) has to be defined." +#endif + +/** +\def UINT64(x) has to be defined to the expression for an unsigned +64-bit literal. +*/ +#ifndef UINT64 +#error "ERROR: UINT64(x) has to be defined." +#endif + +/** +\def INT64_HILO(high,low) has to be defined to an expression +to create a signed 64-bit integer from 2 32-bit integers. +*/ +#ifndef INT64_HILO +#error "ERROR: INT64_HILO(high,low) has to be defined." +#endif + +/** +\def UINT64_HILO(high,low) has to be defined to an expression +to create an unsigned 64-bit integer from 2 32-bit integers. +*/ +#ifndef UINT64_HILO +#error "ERROR: UINT64_HILO(high,low) has to be defined." +#endif + +/** +\def OSCL_MEMFRAG_PTR_BEFORE_LEN macro should be set to 1 if +memory fragements data structures, such as used by sendmsg +(i.e., the iovec data structures), should use ptr before length. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_MEMFRAG_PTR_BEFORE_LEN +#error "ERROR: OSCL_MEMFRAG_PTR_BEFORE_LEN has to be defined to either 0 or 1" +#endif + +/** +\def OSCL_HAS_TLS_SUPPORT macro should be set to 1 if +the target platform has thread-local storage functions. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_TLS_SUPPORT +#error "ERROR: OSCL_HAS_TLS_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +\def OSCL_TLS_IS_KEYED macro should be set to 1 if +the target platform's thread local storage function requires an +input key value to uniquely identify the TLS. +If the thread local storage function does not require any key, +or thread local storage is not supported, it should be set to 0. +*/ +#ifndef OSCL_TLS_IS_KEYED +#error "ERROR: OSCL_TLS_IS_KEYED has to be defined to either 1 or 0" +#endif + + +/** +When OSCL_TLS_IS_KEYED==1, +\def OSCL_TLS_STORE_FUNC macro must be set to an expression that will +set the TLS value and evalutes to true on success, false on failure. +The macro takes 2 input parameters (key, ptr). +*/ +#if (OSCL_TLS_IS_KEYED) && !defined(OSCL_TLS_STORE_FUNC) +#error "ERROR: OSCL_TLS_STORE_FUNC has to be defined" +#endif + +/** +When OSCL_TLS_IS_KEYED==1, +\def OSCL_TLS_GET_FUNC macro should be set to an expression that +returns the TLS value. +The macro takes 1 input parameter (key). +*/ +#if (OSCL_TLS_IS_KEYED) && !defined(OSCL_TLS_GET_FUNC) +#error "ERROR: OSCL_TLS_GET_FUNC has to be defined" +#endif + +/** +When OSCL_TLS_IS_KEYED==1, +\def OSCL_TLS_GET_FUNC macro should be set to an expression that +creates a TLS entry and evalutes to true on success, false on failure. +The macro takes 1 input parameter (key). +*/ +#if (OSCL_TLS_IS_KEYED) && !defined(OSCL_TLS_KEY_CREATE_FUNC) +#error "ERROR: OSCL_TLS_KEY_CREATE_FUNC has to be defined" +#endif + +/** +When OSCL_TLS_IS_KEYED==1, +\def OSCL_TLS_GET_FUNC macro should be set to an expression that +deletes a TLS entry. +The macro takes 1 input parameter (key). +*/ +#if (OSCL_TLS_IS_KEYED) && !defined(OSCL_TLS_KEY_DELETE_FUNC) +#error "ERROR: OSCL_TLS_KEY_DELETE_FUNC has to be defined" +#endif + + +/** +When OSCL_TLS_IS_KEYED==0, +\def OSCL_TLS_STORE_FUNC macro must be set to an expression that will +set the TLS value and evalutes to true on success, false on failure. +The macro takes 1 input parameter (ptr). +*/ +#if (OSCL_HAS_TLS_SUPPORT) && !(OSCL_TLS_IS_KEYED) && !defined(OSCL_TLS_STORE_FUNC) +#error "ERROR: OSCL_TLS_STORE_FUNC has to be defined" +#endif + +/** +When OSCL_TLS_IS_KEYED==0, +\def OSCL_TLS_GET_FUNC macro should be set to an expression that +returns the TLS value. +*/ +#if (OSCL_HAS_TLS_SUPPORT) && !(OSCL_TLS_IS_KEYED) && !defined(OSCL_TLS_GET_FUNC) +#error "ERROR: OSCL_TLS_GET_FUNC has to be defined" +#endif + +/** +OSCL_HAS_BASIC_LOCK should be set to 1 if the platform has basic lock support. +*/ +#if !defined(OSCL_HAS_BASIC_LOCK ) +#error "ERROR: OSCL_HAS_BASIC_LOCK must be defined to 0 or 1" +#endif + + +/** +When OSCL_HAS_BASIC_LOCK is 1, +type TOsclBasicLockObject should be defined as the type used as +a mutex object or handle on the target platform. It can +be either typedef'd as a C-compilable type or can be #defined. +Examples: +typedef pthread_mutex_t TOsclBasicLockObject; +#define TOsclBasicLockObject RMutex +*/ +#if (OSCL_HAS_BASIC_LOCK) && !defined(TOsclBasicLockObject) +typedef TOsclBasicLockObject __verify__TOsclBasicLockObject__defined__; +#endif + +/** +\def OSCL_HAS_PRAGMA_PACK macro should be set to 1 if the compiler supports +pragma pack, 0 if it does not. +*/ +#ifndef OSCL_HAS_PRAGMA_PACK +#error "ERROR: OSCL_HAS_PRAGMA_PACK must be defined to 0 or 1" +#endif + +/*! @} */ + +#endif // OSCLCONFIG_CHECK_H_INCLUDED + + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_compiler_warnings.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_compiler_warnings.h new file mode 100644 index 0000000000..28d741813f --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_compiler_warnings.h @@ -0,0 +1,44 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G _ C O M P I L E R _ W A R N I N G S + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig_compiler_warnings.h + * \brief This file contains the ability to turn off/on compiler warnings + * + */ + +// This macro enables the "#pragma GCC system_header" found in any header file that +// includes this config file. +// "#pragma GCC system_header" suppresses compiler warnings in the rest of that header +// file by treating the header as a system header file. +// For instance, foo.h has 30 lines, "#pragma GCC system_header" is inserted at line 10, +// from line 11 to the end of file, all compiler warnings are disabled. +// However, this does not affect any files that include foo.h. +// +#ifdef __GNUC__ +#define OSCL_DISABLE_GCC_WARNING_SYSTEM_HEADER +#endif + +#define OSCL_FUNCTION_PTR(x) (&x) + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_error.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_error.h new file mode 100644 index 0000000000..6cdf86c270 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_error.h @@ -0,0 +1,53 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G _ E R R O R + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig_error.h + * \brief This file contains the common typedefs and header files needed to compile osclerror + * + */ + + +#ifndef OSCLCONFIG_ERROR_H_INCLUDED +#define OSCLCONFIG_ERROR_H_INCLUDED + +#ifndef OSCLCONFIG_H_INCLUDED +#include "osclconfig.h" +#endif + +#define OSCL_HAS_EXCEPTIONS 1 +#define OSCL_HAS_ERRNO_H 1 +#define OSCL_HAS_SYMBIAN_ERRORTRAP 0 +#define OSCL_HAS_SETJMP_H 1 + +// system header files +#include <setjmp.h> +#include <errno.h> + + +// confirm that all definitions have been defined +#include "osclconfig_error_check.h" + +#endif // OSCLCONFIG_ERROR_H_INCLUDED + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_error_check.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_error_check.h new file mode 100644 index 0000000000..301181e89c --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_error_check.h @@ -0,0 +1,63 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#ifndef OSCLCONFIG_ERROR_CHECK_H_INCLUDED +#define OSCLCONFIG_ERROR_CHECK_H_INCLUDED + + +/** +OSCL_HAS_EXCEPTIONS macro should be set to 1 if +the target platform supports C++ exceptions (throw, catch). +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_EXCEPTIONS +#error "ERROR: OSCL_HAS_EXCEPTIONS has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_EXCEPTIONS macro should be set to 1 if +the target platform supports the POSIX-compliant errno.h header file. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_ERRNO_H +#error "ERROR: OSCL_HAS_ERRNO_H has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_SYMBIAN_ERRORTRAP macro should be set to 1 if +the target platform has Symbian leave, trap, and cleanup stack support. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_SYMBIAN_ERRORTRAP +#error "ERROR: OSCL_HAS_SYMBIAN_ERRORTRAP has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_SETJMP_H macro should be set to 1 if +the target platform supports the setjmp.h header file including +the setjmp and longjmp functions. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_SETJMP_H +#error "ERROR: OSCL_HAS_SETJMP_H has to be defined to either 1 or 0" +#endif + + +#endif //OSCLCONFIG_ERROR_CHECK_H_INCLUDED + + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_global_new_delete.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_global_new_delete.h new file mode 100644 index 0000000000..d3d0112007 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_global_new_delete.h @@ -0,0 +1,30 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +#ifndef OSCLCONFIG_GLOBAL_NEW_DELETE_H_INCLUDED +#define OSCLCONFIG_GLOBAL_NEW_DELETE_H_INCLUDED + +//This file contains overloads for the global new/delete operators +//for use in configurations without a native new/delete operator, +//or where it is desirable to overload the existing global new/delete +//operators. The implementation of the operators is in oscl_mem.cpp. + +void* operator new(size_t); +void operator delete(void*); + + +#endif diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_global_placement_new.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_global_placement_new.h new file mode 100644 index 0000000000..4ab19e7aa3 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_global_placement_new.h @@ -0,0 +1,31 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +#ifndef OSCLCONFIG_GLOBAL_PLACEMENT_NEW_H_INCLUDED +#define OSCLCONFIG_GLOBAL_PLACEMENT_NEW_H_INCLUDED + +//This file contains a definition of placement new operator +//for use in configurations without a native placement new +//operator definition. + +inline void* operator new(size_t, void* ptr) +{ + return ptr; +} + + +#endif diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_io.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_io.h new file mode 100644 index 0000000000..bca1245588 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_io.h @@ -0,0 +1,309 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2010 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G _ I O + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig_io.h + * \brief This file contains common typedefs based on the ANSI C limits.h header + * + * This header file should work for any ANSI C compiler to determine the + * proper native C types to use for OSCL integer types. + */ + + +#ifndef OSCLCONFIG_IO_H_INCLUDED +#define OSCLCONFIG_IO_H_INCLUDED + +#ifndef OSCLCONFIG_H_INCLUDED +#include "osclconfig.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <fcntl.h> +#include <signal.h> +#include <netdb.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <errno.h> +#include <sys/vfs.h> +#include <dirent.h> +//#include <glob.h> +#if (OSCL_HAS_ANSI_STDLIB_SUPPORT) +#if (OSCL_HAS_UNIX_SUPPORT) +#include <sys/stat.h> +#endif +#endif + +//For File I/O +#define OSCL_HAS_GLOB 0 +#define OSCL_HAS_ANSI_FILE_IO_SUPPORT 1 +#define OSCL_HAS_ANSI_64BIT_FILE_IO_SUPPORT 0 +#define OSCL_HAS_MSWIN_FILE_IO_SUPPORT 0 +#define OSCL_HAS_SYMBIAN_COMPATIBLE_IO_FUNCTION 0 +#define OSCL_HAS_NATIVE_FILE_CACHE_ENABLE 1 +#define OSCL_FILE_BUFFER_MAX_SIZE 32768 +#define OSCL_HAS_PV_FILE_CACHE 0 +#define OSCL_HAS_LARGE_FILE_SUPPORT 1 + +//For Sockets +#define OSCL_HAS_SYMBIAN_SOCKET_SERVER 0 +#define OSCL_HAS_SYMBIAN_DNS_SERVER 0 +#define OSCL_HAS_BERKELEY_SOCKETS 1 +#define OSCL_HAS_SOCKET_SUPPORT 1 + +//basic socket types +typedef int TOsclSocket; +typedef struct sockaddr_in TOsclSockAddr; +typedef socklen_t TOsclSockAddrLen; +typedef struct ip_mreq TIpMReq; + +//Init addr macro, inet_addr returns an uint32 +#define OsclValidInetAddr(addr) (inet_addr(addr)!=INADDR_NONE) + +//address conversion macro-- from string to network address. +#define OsclMakeSockAddr(sockaddr,port,addrstr,ok)\ + sockaddr.sin_family=OSCL_AF_INET;\ + sockaddr.sin_port=htons(port);\ + int32 result=inet_aton((const char*)addrstr,&sockaddr.sin_addr);\ + ok=(result!=0); + +//address conversion macro-- from network address to string +#define OsclUnMakeSockAddr(sockaddr,addrstr)\ + addrstr=inet_ntoa(sockaddr.sin_addr); +//address conversion macro-- from string to inaddr +#define OsclMakeInAddr(in_addr,addrstr,ok)\ + int32 result = inet_aton((const char*)addrstr, &in_addr);\ + ok=(result!=0); + +//address conversion macro-- from inaddr to string +#define OsclUnMakeInAddr(in_addr,addrstr)\ + addrstr=inet_ntoa(in_addr); + +//wrappers for berkeley socket calls +#define OsclSetRecvBufferSize(s,val,ok,err) \ + ok=(setsockopt(s,SOL_SOCKET,SO_RCVBUF,(char*)&val, sizeof(int)) !=-1);\ + if (!ok)err=errno + +#define OsclBind(s,addr,ok,err)\ + TOsclSockAddr* tmpadr = &addr;\ + sockaddr* sadr = OSCL_STATIC_CAST(sockaddr*, tmpadr);\ + ok=(bind(s,sadr,sizeof(addr))!=(-1));\ + if (!ok)err=errno + +#define OsclSetSockOpt(s,optLevel,optName,optVal,optLen,ok,err)\ + ok=(setsockopt(s,optLevel,optName,OSCL_STATIC_CAST(const char*,optVal),optLen) != (-1));\ + if (!ok)err=errno +#define OsclJoin(s,addr,ok,err)\ +{\ + struct ip_mreq mreq; \ + void* p = &addr; \ + ok=(bind(s,(sockaddr*)p,sizeof(addr))!=(-1));\ + mreq.imr_multiaddr.s_addr = addr.sin_addr.s_addr ; \ + mreq.imr_interface.s_addr = htonl(INADDR_ANY); \ + ok=(setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq))!=(-1)); \ + if (!ok)err=errno;\ +} + + +#define OsclListen(s,size,ok,err)\ + ok=(listen(iSocket,qSize)!=(-1));\ + if (!ok)err=errno + +#define OsclAccept(s,accept_s,ok,err,wouldblock)\ + accept_s=accept(s,NULL,NULL);\ + ok=(accept_s!=(-1));\ + if (!ok){err=errno;wouldblock=(err==EAGAIN||err==EWOULDBLOCK);} + +#define OsclSetNonBlocking(s,ok,err)\ + ok=(fcntl(s,F_SETFL,O_NONBLOCK)!=(-1));\ + if (!ok)err=errno + +#define OsclShutdown(s,how,ok,err)\ + ok=(shutdown(iSocket,how)!=(-1));\ + if (!ok)err=errno + +#define OsclSocket(s,fam,type,prot,ok,err)\ + s=socket(fam,type,prot);\ + ok=(s!=(-1));\ + if (!ok)err=errno + +#define OsclSendTo(s,buf,len,addr,ok,err,nbytes,wouldblock)\ + TOsclSockAddr* tmpadr = &addr;\ + sockaddr* sadr = OSCL_STATIC_CAST(sockaddr*, tmpadr);\ + nbytes=sendto(s,(const void*)(buf),(size_t)(len),0,sadr,(socklen_t)sizeof(addr));\ + ok=(nbytes!=(-1));\ + if (!ok){err=errno;wouldblock=(err==EAGAIN||err==EWOULDBLOCK);} + +#define OsclSend(s,buf,len,ok,err,nbytes,wouldblock)\ + nbytes=send(s,(const void*)(buf),(size_t)(len),0);\ + ok=(nbytes!=(-1));\ + if (!ok){err=errno;wouldblock=(err==EAGAIN||err==EWOULDBLOCK);} + +#define OsclCloseSocket(s,ok,err)\ + ok=(close(s)!=(-1));\ + if (!ok)err=errno + +#define OsclConnect(s,addr,ok,err,wouldblock)\ + TOsclSockAddr* tmpadr = &addr;\ + sockaddr* sadr = OSCL_STATIC_CAST(sockaddr*, tmpadr);\ + ok=(connect(s,sadr,sizeof(addr))!=(-1));\ + if (!ok){err=errno;wouldblock=(err==EINPROGRESS);} +#define OsclGetPeerName(s,name,namelen,ok,err)\ + ok=(getpeername(s,(sockaddr*)&name,(socklen_t*)&namelen) != (-1) );\ + if (!ok)err=errno + +#define OsclGetAsyncSockErr(s,ok,err)\ + int opterr;socklen_t optlen=sizeof(opterr);\ + ok=(getsockopt(s,SOL_SOCKET,SO_ERROR,(void *)&opterr,&optlen)!=(-1));\ + if(ok)err=opterr;else err=errno; + +#define OsclPipe(x) pipe(x) +#define OsclReadFD(fd,buf,cnt) read(fd,buf,cnt) +#define OsclWriteFD(fd,buf,cnt) write(fd,buf,cnt) + +//unix reports connect completion in write set in the getsockopt +//error. +#define OsclConnectComplete(s,wset,eset,success,fail,ok,err)\ + success=fail=false;\ + if (FD_ISSET(s,&eset))\ + {fail=true;OsclGetAsyncSockErr(s,ok,err);}\ + else if (FD_ISSET(s,&wset))\ + {OsclGetAsyncSockErr(s,ok,err);if (ok && err==0)success=true;else fail=true;} + +#define OsclRecv(s,buf,len,ok,err,nbytes,wouldblock)\ + nbytes=recv(s,(void *)(buf),(size_t)(len),0);\ + ok=(nbytes!=(-1));\ + if (!ok){err=errno;wouldblock=(err==EAGAIN);} + +#define OsclRecvFrom(s,buf,len,paddr,paddrlen,ok,err,nbytes,wouldblock)\ +{\ +void* p=paddr;\ +nbytes=recvfrom(s,(void*)(buf),(size_t)(len),0,(struct sockaddr*)p,paddrlen);\ + ok=(nbytes!=(-1));\ + if (!ok){err=errno;wouldblock=(err==EAGAIN);}\ +} + + +#define OsclSocketSelect(nfds,rd,wr,ex,timeout,ok,err,nhandles)\ + nhandles=select(nfds,&rd,&wr,&ex,&timeout);\ + ok=(nhandles!=(-1));\ + if (!ok)err=errno + +//there's not really any socket startup needed on unix, but +//you need to define a signal handler for SIGPIPE to avoid +//broken pipe crashes. +#define OsclSocketStartup(ok)\ + signal(SIGPIPE,SIG_IGN);\ + ok=true + +#define OsclSocketCleanup(ok)\ + signal(SIGPIPE,SIG_DFL);\ + ok=true + +//hostent type +typedef struct hostent TOsclHostent; + +//wrapper for gethostbyname +#define OsclGethostbyname(name,hostent,ok,err)\ + hostent=gethostbyname((const char*)name);\ + ok=(hostent!=NULL);\ + if (!ok)err=errno; + +//extract dotted address from a hostent +#define OsclGetDottedAddr(hostent,dottedaddr,ok)\ + long *_hostaddr=(long*)hostent->h_addr_list[0];\ + struct in_addr _inaddr;\ + _inaddr.s_addr=*_hostaddr;\ + dottedaddr=inet_ntoa(_inaddr);\ + ok=(dottedaddr!=NULL); + +//extract dotted address from a hostent into the vector of OsclNetworkAddress +#define OsclGetDottedAddrVector(hostent,dottedaddr,dottedaddrvect,ok)\ + if(dottedaddrvect)\ + {\ + long **_addrlist=(long**)hostent->h_addr_list;\ + for(int i = 0; _addrlist[i] != NULL; i++){\ + struct in_addr _inaddr;\ + _inaddr.s_addr=*_addrlist[i];\ + OsclNetworkAddress addr(inet_ntoa(_inaddr), 0);\ + dottedaddrvect->push_back(addr);\ + }\ + if (!dottedaddrvect->empty())\ + {dottedaddr->port = dottedaddrvect->front().port; dottedaddr->ipAddr.Set(dottedaddrvect->front().ipAddr.Str());}\ + ok=(!dottedaddrvect->empty() && (((*dottedaddrvect)[0]).ipAddr.Str() != NULL));\ + }\ + else\ + {\ + char *add;\ + OsclGetDottedAddr(hostent,add,ok);\ + if(ok) dottedaddr->ipAddr.Set(add);\ + } + +//socket shutdown codes +#define OSCL_SD_RECEIVE SHUT_RD +#define OSCL_SD_SEND SHUT_WR +#define OSCL_SD_BOTH SHUT_RDWR + +//address family codes +#define OSCL_AF_INET AF_INET + +//socket type codes +#define OSCL_SOCK_STREAM SOCK_STREAM +#define OSCL_SOCK_DATAGRAM SOCK_DGRAM + +//IP protocol codes +#define OSCL_IPPROTO_IP IPPROTO_IP +#define OSCL_IPPROTO_TCP IPPROTO_TCP +#define OSCL_IPPROTO_UDP IPPROTO_UDP + +//Socket option Levels +#define OSCL_SOL_SOCKET SOL_SOCKET +#define OSCL_SOL_IP IPPROTO_IP +#define OSCL_SOL_TCP IPPROTO_TCP +#define OSCL_SOL_UDP IPPROTO_UDP + +//Socket Option Values (level = IP) +#define OSCL_SOCKOPT_IP_MULTICAST_TTL IP_MULTICAST_TTL +#define OSCL_SOCKOPT_IP_ADDMEMBERSHIP IP_ADD_MEMBERSHIP +#define OSCL_SOCKOPT_IP_TOS IP_TOS + +//Socket Option Values (level = Socket) +#define OSCL_SOCKOPT_SOL_REUSEADDR SO_REUSEADDR +//End sockets + +// file IO support +#if (OSCL_HAS_LARGE_FILE_SUPPORT) +typedef off64_t TOsclFileOffset; +#else +typedef int32 TOsclFileOffset; +#endif + +#include "osclconfig_io_check.h" + +#endif + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_io_check.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_io_check.h new file mode 100644 index 0000000000..22ddebbd10 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_io_check.h @@ -0,0 +1,605 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +#ifndef OSCLCONFIG_IO_CHECK_H_INCLUDED +#define OSCLCONFIG_IO_CHECK_H_INCLUDED + +/** +OSCL_HAS_ANSI_FILE_IO_SUPPORT macro should be set to 1 if +the target platform supports the ANSI C file I/O functions (fopen, fread, etc). +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_ANSI_FILE_IO_SUPPORT +#error "ERROR: OSCL_HAS_ANSI_FILE_IO_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_ANSI_64BIT_FILE_IO_SUPPORT macro should be set to 1 if +the target platform supports the 64-bit ANSI C file I/O functions (fopen, fread, etc). +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_ANSI_64BIT_FILE_IO_SUPPORT +#error "ERROR: OSCL_HAS_ANSI_64BIT_FILE_IO_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_MSWIN_FILE_IO_SUPPORT macro should be set to 1 if +the target platform supports the ANSI C file I/O functions (fopen, fread, etc). +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_MSWIN_FILE_IO_SUPPORT +#error "ERROR: OSCL_HAS_MSWIN_FILE_IO_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_SYMBIAN_COMPATIBLE_IO_FUNCTION macro should be set to 1 if +the target platform supports the Symbian file I/O functions (RFile, RFs). +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_SYMBIAN_COMPATIBLE_IO_FUNCTION +#error "ERROR: OSCL_HAS_SYMBIAN_COMPATIBLE_IO_FUNCTION has to be defined to either 1 or 0" +#endif + +/** +On Symbian platforms only: +OSCL_HAS_NATIVE_DUPLICATE_FILE_HANDLE macro should be set to 1 if +the target platform supports the Symbian file I/O function RFile::Duplicate. +Otherwise it should be set to 0. +*/ +#if (OSCL_HAS_SYMBIAN_COMPATIBLE_IO_FUNCTION) +#ifndef OSCL_HAS_NATIVE_DUPLICATE_FILE_HANDLE +#error "ERROR: OSCL_HAS_NATIVE_DUPLICATE_FILE_HANDLE has to be defined to either 1 or 0" +#endif +#endif + + +/** +OSCL_HAS_NATIVE_FILE_CACHE_ENABLE macro should be set to 1 if +the target platform includes native file cache capability. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_NATIVE_FILE_CACHE_ENABLE +#error "ERROR: OSCL_HAS_NATIVE_FILE_CACHE_ENABLE has to be defined to either 1 or 0" +#endif + + +/** +OSCL_HAS_PV_FILE_CACHE macro should be set to 1 if +the target platform includes PV file cache capability. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_PV_FILE_CACHE +#error "ERROR: OSCL_HAS_PV_FILE_CACHE has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_LARGE_FILE_SUPPORT macro should be set to 1 if +the target platform supports more than 32bit file I/O capability. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_LARGE_FILE_SUPPORT +#error "ERROR: OSCL_HAS_LARGE_FILE_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +type TOsclFileOffset should be defined as the type used for file size +and offsets on the target platform. +Example: +typedef size_t TOsclFileOffset; +*/ +typedef TOsclFileOffset __verify__TOsclFileOffset__defined__; + + +/** +OSCL_FILE_BUFFER_MAX_SIZE macro should be set to +the desired size of the file I/O cache in bytes. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_FILE_BUFFER_MAX_SIZE +#error "ERROR: OSCL_FILE_BUFFER_MAX_SIZE has to be defined to a numeric value" +#endif + +/** +OSCL_HAS_SOCKET_SUPPORT macro should be set to 1 if +the target platform supports sockets of any type. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_SOCKET_SUPPORT +#error "ERROR: OSCL_HAS_SOCKET_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_SYMBIAN_SOCKET_SERVER macro should be set to +1 if the platform supports Symbian socket API (RSocket, RSocketServ). +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_SYMBIAN_SOCKET_SERVER +#error "ERROR: OSCL_HAS_SYMBIAN_SOCKET_SERVER has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_SYMBIAN_DNS_SERVER macro should be set to +1 if the platform supports Symbian Host Resolver API (RHostResolver). +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_SYMBIAN_DNS_SERVER +#error "ERROR: OSCL_HAS_SYMBIAN_DNS_SERVER has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_BERKELEY_SOCKETS macro should be set to +1 if the platform supports Berkeley style socket API, including +non-blocking I/O and a 'select' call. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_BERKELEY_SOCKETS +#error "ERROR: OSCL_HAS_BERKELEY_SOCKETS has to be defined to either 1 or 0" +#endif + +/** +For platforms with Berkeley type sockets, +TOsclSocket typedef should be set to platform native socket type. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +typedef TOsclSocket __TOsclSocketCheck___; +#endif + +/** +For platforms with Berkeley type sockets, +TOsclSockAddr typedef should be set to platform native socket address type. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +typedef TOsclSockAddr __TOsclSockAddrCheck___; +#endif + +/** +For platforms with Berkeley type sockets, +TOsclSockAddrLen typedef should be set to platform native socket address +length type. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +typedef TOsclSockAddrLen __TOsclSockAddrLenCheck___; +#endif + +/** +For platforms with Berkeley type sockets, +OsclBind(s,addr,ok,err) must be defined to +an expression that does a bind call. +'s' and 'addr' are the socket and address parameters +to the bind command. +On success, 'ok' must be set to true. +On failure, 'ok' must be set to false and 'err' must be set +to the bind error. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclBind +#error "ERROR: OsclBind(s,addr,ok,err) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclListen(s,size,ok,err) must be defined to +an expression that does a listen call and sets 'ok' and 'err' +to indicate the result. +'s' and 'size' are the socket and queue size args to the listen +call. +On success, 'ok' must be set to true. +On failure, 'ok' must be set to false and 'err' must be set +to the listen error. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclListen +#error "ERROR: OsclListen(s,size,ok,err) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclAccept(s,accept_s,ok,err,wouldblock) must be defined to +an expression that does an accept call and sets 'ok', 'err', +and 'wouldblock' to indicate the result. +'s' and 'accept_s' are the socket and accept socket args to the +accept call. +On success, 'ok' must be set to true. +On failure, 'ok' must be set to false and 'err' must be set +to the accept error. Additionally 'wouldblock' must be set to true +if the error code indicates that the socket is non-blocking and +would block, or to false otherwise. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclAccept +#error "ERROR: OsclAccept(s,accept_s,ok,err,wouldblock) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclSetNonBlocking(s,ok,err) must be defined to +an expression that sets socket 's' to non-blocking I/O mode +and sets 'ok' and 'err' to indicate the result. +On success, 'ok' must be set to true. +On failure, 'ok' must be set to false and 'err' must be set +to the error. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclSetNonBlocking +#error "ERROR: OsclSetNonBlocking(s,ok,err) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclShutdown(s,how,ok,err) must be defined to +an expression that does a shutdown call and sets 'ok' and 'err' +to indicate the result. +'s' and 'how' are the socket and shutdown type args to the +shutdown call. +On success, 'ok' must be set to true. +On failure, 'ok' must be set to false and 'err' must be set +to the shutdown error. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclShutdown +#error "ERROR: OsclShutdown(s,how,ok,err) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclSocket(s,fam,type,prot,ok,err) must be defined to +an expression that does a socket creation call and sets 'ok' +and 'err' to indicate the result. +'s', 'fam', 'type', and 'prot' are the socket, family, type, and +protocol args to the socket call. +On success, 'ok' must be set to true. +On failure, 'ok' must be set to false and 'err' must be set +to the socket error. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclSocket +#error "ERROR: OsclSocket(s,fam,type,prot,ok,err) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclSendTo(s,buf,len,addr,ok,err,nbytes,wouldblock) must be defined +to an expression that does a sendto call and sets 'ok, 'err', 'nbytes', +and 'wouldblock' to indicate the result. +'s', 'buf', 'len', 'flags' and 'addr' are the arguments to the sendto +call. +On success, 'ok' must be set to true, and 'nbytes' must be set to +the number of bytes sent. +On failure, 'ok' must be set to false 'err' must be set +to the socket error. Additionally 'wouldblock' must be set to true +if the error code indicates that the socket is non-blocking and +would block, or to false otherwise. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclSendTo +#error "ERROR: OsclSendTo(s,buf,len,flags,addr,ok,err,nbytes,wouldblock) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclSend(s,buf,len,ok,err,nbytes,wouldblock) must be defined to +an expression that does a send operation and sets 'ok, 'err', 'nbytes', +and 'wouldblock' to indicate the result. +'s', 'buf', and 'len' are the args to the send call. +On success, 'ok' must be set to true, and 'nbytes' must be set to +the number of bytes sent. +On failure, 'ok' must be set to false 'err' must be set +to the socket error. Additionally 'wouldblock' must be set to true +if the error code indicates that the socket is non-blocking and +would block, or to false otherwise. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclSend +#error "ERROR: OsclSend(s,buf,len,ok,err,nbytes,wouldblock) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclCloseSocket(s,ok,err) must be defined to +an expression that closes socket 's' and sets 'ok and 'err' +to indicate the result. +On success, 'ok' must be set to true. +On failure, 'ok' must be set to false and 'err' must be set +to the close error. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclCloseSocket +#error "ERROR: OsclCloseSocket(s,ok,err) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclConnect(s,addr,ok,err,wouldblock) must be defined to +an expression that does a connect call and sets 'ok', 'err', +and 'wouldblock' to indicate the result. +'s' and 'addr' are the socket and address args to the connect call. +On success, 'ok' must be set to true. +On failure, 'ok' must be set to false 'err' must be set +to the socket error. Additionally 'wouldblock' must be set to true +if the error code indicates that the socket is non-blocking and +would block, or to false otherwise. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclConnect +#error "ERROR: OsclConnect(s,addr,ok,err,wouldblock) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclConnectComplete(s,wset,eset,success,fail,ok,err) must be set +to an expression that checks for completion of a connect operation +on a non-blocking socket and sets 'success', 'fail', 'ok', and 'err' +to indicate the result. +'s' is the socket, 'wset' is the write set from the select call, +'eset' is the exception set from the select call. +If connect is not yet complete, 'success' and 'fail' must be +set false. +On connect success, 'success' must be set true. +On conneect failure, 'success' must be set false, 'fail' must be +set true. Additionally, the call attempts to retrieve the connect error. +If the connect error is obtained, 'ok' is set true and 'err' contains +the error. If the connect error is not obtained, 'ok' is set false +and 'err' is the error code from the attempt. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclConnectComplete +#error "ERROR: OsclConnectComplete(s,wset,eset,success,fail,ok,err) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclRecv(s,buf,len,ok,err,nbytes,wouldblock) must be defined to +an expression that does a recv call and sets 'ok', 'err', 'nbytes', +and 'wouldblock' to indicate the result. +'s', 'buf', and 'len' are the arguments to the recv call. +On success, 'ok' must be set to true, and 'nbytes' must be set to +the number of bytes received. +On failure, 'ok' must be set to false 'err' must be set +to the socket error. Additionally 'wouldblock' must be set to true +if the error code indicates that the socket is non-blocking and +would block, or to false otherwise. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclRecv +#error "ERROR: OsclRecv(s,buf,len,ok,err,nbytes,wouldblock) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclRecvFrom(s,buf,len,addr,addrlen,ok,err,nbytes,wouldblock) must be defined to +an expression that does a recvfrom call and sets 'ok', 'err', 'nbytes', +and 'wouldblock' to indicate the result. +'s', 'buf', 'len', 'paddr', and 'paddrlen' are the arguments to the recvfrom call. +On success, 'ok' must be set to true, 'nbytes' must be set to +the number of bytes received, and 'paddr' must be set to the source address. +On failure, 'ok' must be set to false 'err' must be set +to the socket error. Additionally 'wouldblock' must be set to true +if the error code indicates that the socket is non-blocking and +would block, or to false otherwise. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclRecvFrom +#error "ERROR: OsclRecvFrom(s,buf,len,paddr,paddrlen,ok,err,nbytes,wouldblock) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclSocketSelect(nfds,rd,wr,ex,timeout,ok,err,nhandles) must be defined to +an expression that does a select call and sets 'ok', 'err', and +'nhandles' to indicate the result. +'nfds', 'rd', 'wr', 'ex', and 'timeout' are the arguments to the +select call. +On success, 'ok' must be set to true, and 'nhandles' must be set to +the number of socket handles with activitiy detected. +On failure, 'ok' must be set to false 'err' must be set +to the select error. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclSocketSelect +#error "ERROR: OsclSocketSelect(nfds,rd,wr,ex,timeout,ok,err,nhandles) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclSocketStartup(ok) must be defined to +an expression that does any necessary startup of the socket system +and sets 'ok' to indicate the result. +On success, 'ok' must be set to true. +On failure, 'ok' must be set to false. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclSocketStartup +#error "ERROR: OsclSocketStartup(ok) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclSocketCleanup(ok) must be defined to +an expression that does any necessary cleanup of the socket system +and sets 'ok' to indicate the result. +On success, 'ok' must be set to true. +On failure, 'ok' must be set to false. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclSocketCleanup +#error "ERROR: OsclSocketCleanup(ok) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclGetAsyncSockErr(s,ok,err) must be defined to +an expression that does a getsockopt call to retrieve a socket error +and sets 'ok' and 'err' to indicate the result. +'s' is the socket argument to the getsockopt call. +On success, 'ok' must be set true and 'err' must be set to the +error retrieved. +On failure, 'ok' must be set false and 'err' must be set to the +error from the getsockopt call. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclGetAsyncSockErr +#error "ERROR: OsclGetAsyncSockErr(s,ok,err) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +TOsclHostent typedef should be set to platform native hostent type. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +typedef TOsclHostent __TOsclHostentCheck___; +#endif + +/** +For platforms with Berkeley type sockets, +OsclGethostbyname(name,hostent,ok,err) must be defined to +an expression that does a gethostbyname call on host 'name' +and sets 'hostent', 'ok' and 'err' to indicate the result. +'name' is the name argument to the gethostbyname call. +On success, 'ok' must be set true and 'hostent' must be set to +the TOsclHostent* retrieved. +On failure, 'ok' must be set false and 'err' must be set to the +error from the gethostbyname call. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclGethostbyname +#error "ERROR: OsclGethostbyname(name,hostent,ok,err) has to be defined" +#endif +#endif + +/** +For platforms with Berkeley type sockets, +OsclGetDottedAddr(hostent,dottedaddr,ok) must be defined to +an expression that does extracts an address in dotted decimal +notation from a hostent structure. +'hostent' is the TOsclHostent*, +'dottedaddr' is a char* output containing the dotted address, +and 'ok' is a bool that should be set true on success, false on failure. +*/ +#if OSCL_HAS_BERKELEY_SOCKETS +#ifndef OsclGetDottedAddr +#error "ERROR: OsclGetDottedAddr(hostent,dottedaddr,ok) has to be defined" +#endif +#endif + + +/** +For platforms in which file descriptors created with a pipe() command can be +used with the select() system call the following 3 macros must be defined +*/ + +#if OSCL_HAS_SELECTABLE_PIPES +#ifndef OsclPipe +#error "ERROR: OsclPipe(pipearray) has to be defined" +#endif +#endif + +#if OSCL_HAS_SELECTABLE_PIPES +#ifndef OsclReadFD +#error "ERROR: OsclReadFD(fd,buffer,cnt) has to be defined" +#endif +#endif + +#if OSCL_HAS_SELECTABLE_PIPES +#ifndef OsclWriteFD +#error "ERROR: OsclWriteFD(fd,buffer,cnt) has to be defined" +#endif +#endif + +#if OSCL_HAS_SOCKET_SUPPORT +/** +OsclValidInetAddr must be defined to a boolean expression to +evaluate whether an address is proper IP4 format. +'addr' is a char* containing the address string. +*/ +#ifndef OsclValidInetAddr +#error "ERROR: OsclValidInetAddr(addr) must be defined" +#endif +#endif + +#if OSCL_HAS_SOCKET_SUPPORT +/** +OSCL_SD_RECEIVE, OSCL_SD_SEND, and OSCL_SD_BOTH must be defined to +the platform-specific socket shutdown codes. +*/ +#ifndef OSCL_SD_RECEIVE +#error "ERROR: OSCL_SD_RECEIVE has to be defined" +#endif +#ifndef OSCL_SD_SEND +#error "ERROR: OSCL_SD_SEND has to be defined" +#endif +#ifndef OSCL_SD_BOTH +#error "ERROR: OSCL_SD_BOTH has to be defined" +#endif +#endif + +#if OSCL_HAS_SOCKET_SUPPORT +/** +OSCL_AF_INET must be defined to the platform-specific +network address family codes for INET. +*/ +#ifndef OSCL_AF_INET +#error "ERROR: OSCL_AF_INET has to be defined" +#endif +#endif + +#if OSCL_HAS_SOCKET_SUPPORT +/** +OSCL_SOCK_STREAM and OSCL_SOCK_DATAGRAM must be defined to +the platform-specific socket type codes. +*/ +#ifndef OSCL_SOCK_STREAM +#error "ERROR: OSCL_SOCK_STREAM has to be defined" +#endif +#ifndef OSCL_SOCK_DATAGRAM +#error "ERROR: OSCL_SOCK_DATAGRAM has to be defined" +#endif +#endif + +#if OSCL_HAS_SOCKET_SUPPORT +/** +OSCL_IPPROTO_TCP and OSCL_IPPROTO_UDP must be defined to +the platform-specific IP protocol codes. +*/ +#ifndef OSCL_IPPROTO_TCP +#error "ERROR: OSCL_IPPROTO_TCP has to be defined" +#endif +#ifndef OSCL_IPPROTO_UDP +#error "ERROR: OSCL_IPPROTO_UDP has to be defined" +#endif +#endif + + +#endif // OSCLCONFIG_IO_CHECK_H_INCLUDED + + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_ix86.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_ix86.h new file mode 100644 index 0000000000..87d7afb43f --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_ix86.h @@ -0,0 +1,41 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G ( P L A T F O R M C O N F I G I N F O ) + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig_ix86.h + * \brief This file contains configuration information for the ix86 processor family + * + */ + +#ifndef OSCLCONFIG_IX86_H_INCLUDED +#define OSCLCONFIG_IX86_H_INCLUDED + + +// Define macros for integer alignment and little endian byte order. +#define OSCL_INTEGERS_WORD_ALIGNED 1 +#define OSCL_BYTE_ORDER_BIG_ENDIAN 0 +#define OSCL_BYTE_ORDER_LITTLE_ENDIAN 1 + + +#endif diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_lib.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_lib.h new file mode 100644 index 0000000000..ee71a6ad52 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_lib.h @@ -0,0 +1,63 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2010 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G _ L I B ( P L A T F O R M C O N F I G I N F O ) + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig_lib.h + \brief This file contains configuration information for the ANSI build. + +*/ + +#ifndef OSCLCONFIG_LIB_H_INCLUDED +#define OSCLCONFIG_LIB_H_INCLUDED + + + +//Set this to 1 to indicate this platform has oscllib support +#define OSCL_HAS_RUNTIME_LIB_LOADING_SUPPORT 1 +#define PV_RUNTIME_LIB_FILENAME_EXTENSION "so" + +//Set this to 1 to enable looking for debug versions of libraries. +//Use #ifndef to allow the compiler setting to override this definition +#ifndef OSCL_LIB_READ_DEBUG_LIBS +#if (OSCL_RELEASE_BUILD) +#define OSCL_LIB_READ_DEBUG_LIBS 0 +#else +#define OSCL_LIB_READ_DEBUG_LIBS 1 +#endif +#endif + +// The path recursively from which the config files are picked up +#ifndef PV_DYNAMIC_LOADING_CONFIG_FILE_PATH +#ifdef ANDROID +#define PV_DYNAMIC_LOADING_CONFIG_FILE_PATH "/system/etc" +#else +#define PV_DYNAMIC_LOADING_CONFIG_FILE_PATH "./" +#endif +#endif + +// check all osclconfig required macros are defined +#include "osclconfig_lib_check.h" + +#endif // OSCLCONFIG_LIB_H_INCLUDED + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_lib_check.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_lib_check.h new file mode 100644 index 0000000000..e4f7479eab --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_lib_check.h @@ -0,0 +1,67 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#ifndef OSCLCONFIG_LIB_CHECK_H_INCLUDED +#define OSCLCONFIG_LIB_CHECK_H_INCLUDED + +/*! \addtogroup osclconfig OSCL config + * + * @{ + */ + + + +/** +OSCL_HAS_RUNTIME_LIB_LOADING_SUPPORT should be set to 1 if the platform has basic explicit runtime DLL loading support. +*/ +#if !defined(OSCL_HAS_RUNTIME_LIB_LOADING_SUPPORT ) +#error "ERROR: OSCL_HAS_RUNTIME_LIB_LOADING_SUPPORT must be defined to 0 or 1" +#endif + +#if(OSCL_HAS_RUNTIME_LIB_LOADING_SUPPORT) +/** +** When OSCL_HAS_RUNTIME_LIB_LOADING_SUPPORT is 1, +** OSCL_LIB_READ_DEBUG_LIBS should be set to 0 or 1. Set to 1 to enable loading +** debug versions of libs. +*/ +#if !defined(OSCL_LIB_READ_DEBUG_LIBS) +#error "ERROR: OSCL_LIB_READ_DEBUG_LIBS must be defined to 0 or 1" +#endif + +/* +** When OSCL_HAS_RUNTIME_LIB_LOADING_SUPPORT is 1, +** PV_DYNAMIC_LOADING_CONFIG_FILE_PATH should be set. +*/ +#if !defined(PV_DYNAMIC_LOADING_CONFIG_FILE_PATH) +#error "ERROR: PV_DYNAMIC_LOADING_CONFIG_FILE_PATH must be set to a path where the config files are expected to be present" +#endif + +/* +** When OSCL_HAS_RUNTIME_LIB_LOADING_SUPPORT is 1, +** PV_RUNTIME_LIB_FILENAME_EXTENSION should be set. +*/ +#if !defined(PV_RUNTIME_LIB_FILENAME_EXTENSION) +#error "ERROR: PV_RUNTIME_LIB_FILENAME_EXTENSION must be specified for use as the dynamic library file extension" +#endif +#endif // OSCL_HAS_RUNTIME_LIB_LOADING_SUPPORT + +/*! @} */ + +#endif // OSCLCONFIG_LIB_CHECK_H_INCLUDED + + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_limits_typedefs.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_limits_typedefs.h new file mode 100644 index 0000000000..4ce355dfa4 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_limits_typedefs.h @@ -0,0 +1,88 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G_ L I M I T S _ T Y P E D E F S + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig_limits_typedefs.h + * \brief This file contains common typedefs based on the ANSI C limits.h header + * + * This header file should work for any ANSI C compiler to determine the + * proper native C types to use for OSCL integer types. + */ + + +#ifndef OSCLCONFIG_LIMITS_TYPEDEFS_H_INCLUDED +#define OSCLCONFIG_LIMITS_TYPEDEFS_H_INCLUDED + + +#include <limits.h> + +// determine if char is signed or unsigned +#if ( CHAR_MIN == 0 ) +#define OSCL_CHAR_IS_UNSIGNED 1 +#define OSCL_CHAR_IS_SIGNED 0 +#elif ( CHAR_MIN == SCHAR_MIN ) +#define OSCL_CHAR_IS_UNSIGNED 0 +#define OSCL_CHAR_IS_SIGNED 1 +#else +#error "Cannot determine if char is signed or unsigned" +#endif + + +#if ( (CHAR_MAX == 255) || (CHAR_MAX == 127) ) +typedef signed char int8; +typedef unsigned char uint8; +#else +#error "Cannot determine an 8-bit interger type" +#endif + + +#if ( SHRT_MAX == 32767 ) +typedef short int16; +typedef unsigned short uint16; + +#elif ( INT_MAX == 32767 ) +typedef int int16; +typedef unsigned int uint16; + +#else +#error "Cannot determine 16-bit integer type" +#endif + + + +#if ( INT_MAX == 2147483647 ) +typedef int int32; +typedef unsigned int uint32; + +#elif ( LONG_MAX == 2147483647 ) +typedef long int32; +typedef unsigned long uint32; + +#else +#error "Cannot determine 32-bit integer type" +#endif + + + +#endif diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_memory.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_memory.h new file mode 100644 index 0000000000..b5c69d04ef --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_memory.h @@ -0,0 +1,91 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2010 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G _ M E M O R Y + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + + + +#ifndef OSCLCONFIG_MEMORY_H_INCLUDED +#define OSCLCONFIG_MEMORY_H_INCLUDED + + +#ifndef OSCLCONFIG_H_INCLUDED +#include "osclconfig.h" +#endif + +#ifndef OSCLCONFIG_ANSI_MEMORY_H_INCLUDED +#include "osclconfig_ansi_memory.h" +#endif + +/* OSCL_HAS_GLOBAL_NEW_DELETE - Enables or disables the definition of overloaded + * global memory operators in oscl_mem.h + * + * Release Mode: OSCL_HAS_GLOBAL_NEW_DELETE 0 + * Debug Mode: OSCL_HAS_GLOBAL_NEW_DELETE 1 + */ + + +#if (OSCL_RELEASE_BUILD) +#define OSCL_BYPASS_MEMMGT 1 +#define OSCL_HAS_GLOBAL_NEW_DELETE 0 +#else +#define OSCL_BYPASS_MEMMGT 1 //Temporarily disabling +#define OSCL_HAS_GLOBAL_NEW_DELETE 1 +#endif + +/* PVMEM_INST_LEVEL - Memory leak instrumentation level enables the compilation + * of detailed memory leak info (filename + line number). + * PVMEM_INST_LEVEL 0: Release mode. + * PVMEM_INST_LEVEL 1: Debug mode. + */ + +#if(OSCL_RELEASE_BUILD) +#define PVMEM_INST_LEVEL 0 +#else +#define PVMEM_INST_LEVEL 1 +#endif + +#if(OSCL_HAS_GLOBAL_NEW_DELETE) +//Detect if <new> or <new.h> is included anyplace to avoid a compile error. +#if defined(_INC_NEW) +#error Duplicate New Definition! +#endif //_INC_NEW +#if defined(_NEW_) +#error Duplicate New Definition! +#endif //_NEW_ +#endif //OSCL_HAS_GLOBAL_NEW_DELETE + +#ifdef __cplusplus +#include <new> //for placement new +#endif //__cplusplus + +//OSCL_HAS_HEAP_BASE_SUPPORT - Enables or disables overloaded memory operators in HeapBase class +#define OSCL_HAS_HEAP_BASE_SUPPORT 1 + +#define OSCL_HAS_SYMBIAN_MEMORY_FUNCS 0 + + +#include "osclconfig_memory_check.h" + + +#endif diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_memory_check.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_memory_check.h new file mode 100644 index 0000000000..8903111292 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_memory_check.h @@ -0,0 +1,72 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#ifndef OSCLCONFIG_MEMORY_CHECK_H_INCLUDED +#define OSCLCONFIG_MEMORY_CHECK_H_INCLUDED + + +/** +OSCL_BYPASS_MEMMGT macro should be set to 1 if +it is desirable to bypass the PV memory management system and just +use the native memory management. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_BYPASS_MEMMGT +#error "ERROR: OSCL_BYPASS_MEMMGT has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_ANSI_MEMORY_FUNCS macro should be set to 1 if +the target platform supports ANSI C memory functions (malloc, free, etc). +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_ANSI_MEMORY_FUNCS +#error "ERROR: OSCL_HAS_ANSI_MEMORY_FUNCS has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_SYMBIAN_MEMORY_FUNCS macro should be set to 1 if +the target platform supports Symbian memory functions User::Alloc, User::Free, etc. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_SYMBIAN_MEMORY_FUNCS +#error "ERROR: OSCL_HAS_SYMBIAN_MEMORY_FUNCS has to be defined to either 1 or 0" +#endif + +/* + * OSCL_HAS_HEAP_BASE_SUPPORT macro should be set to 1 for the + * platforms that allows inheritance from HeapBase class for + * overloading of new/delete operators. + */ + +#ifndef OSCL_HAS_HEAP_BASE_SUPPORT +#error "ERROR: OSCL_HAS_HEAP_BASE_SUPPORT has to be defined to either 1 or 0." +#endif + +/* + * OSCL_HAS_GLOBAL_NEW_DELETE macro should be set to 1 for the + * platforms that allows overloading of new/delete operators. + */ + +#ifndef OSCL_HAS_GLOBAL_NEW_DELETE +#error "ERROR: OSCL_HAS_GLOBAL_NEW_DELETE has to be defined to either 1 or 0." +#endif + +#endif // OSCLCONFIG_MEMORY_CHECK_H_INCLUDED + + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_no_os.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_no_os.h new file mode 100644 index 0000000000..c1a06e3316 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_no_os.h @@ -0,0 +1,71 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2010 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#ifndef OSCLCONFIG_NO_OS_H_INCLUDED +#define OSCLCONFIG_NO_OS_H_INCLUDED + +/*! \addtogroup osclconfig OSCL config + * + * @{ + */ + +//a file to turn off ALL os-specific switches. + +//osclconfig +#define OSCL_HAS_UNIX_SUPPORT 0 +#define OSCL_HAS_MSWIN_SUPPORT 0 +#define OSCL_HAS_MSWIN_PARTIAL_SUPPORT 0 +#define OSCL_HAS_SYMBIAN_SUPPORT 0 +#define OSCL_HAS_SAVAJE_SUPPORT 0 +#define OSCL_HAS_PV_C_OS_SUPPORT 0 +#define OSCL_HAS_ANDROID_SUPPORT 0 +#define OSCL_HAS_IPHONE_SUPPORT 0 + +//osclconfig_error +#define OSCL_HAS_SYMBIAN_ERRORTRAP 0 + +//osclconfig_memory +#define OSCL_HAS_SYMBIAN_MEMORY_FUNCS 0 +#define OSCL_HAS_PV_C_OS_API_MEMORY_FUNCS 0 + +//osclconfig_time +#define OSCL_HAS_PV_C_OS_TIME_FUNCS 0 +#define OSCL_HAS_UNIX_TIME_FUNCS 0 + +//osclconfig_util +#define OSCL_HAS_SYMBIAN_TIMERS 0 +#define OSCL_HAS_SYMBIAN_MATH 0 + +//osclconfig_proc +#define OSCL_HAS_SYMBIAN_SCHEDULER 0 +#define OSCL_HAS_SEM_TIMEDWAIT_SUPPORT 0 +#define OSCL_HAS_PTHREAD_SUPPORT 0 + +//osclconfig_io +#define OSCL_HAS_SYMBIAN_COMPATIBLE_IO_FUNCTION 0 +#define OSCL_HAS_SAVAJE_IO_SUPPORT 0 +#define OSCL_HAS_SYMBIAN_SOCKET_SERVER 0 +#define OSCL_HAS_SYMBIAN_DNS_SERVER 0 +#define OSCL_HAS_BERKELEY_SOCKETS 0 + + +/*! @} */ + +#endif // OSCLCONFIG_CHECK_H_INCLUDED + + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_proc.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_proc.h new file mode 100644 index 0000000000..9f4396549a --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_proc.h @@ -0,0 +1,43 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G _ P R O C ( P L A T F O R M C O N F I G I N F O ) + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig_proc.h + * \brief This file contains configuration information for the linux platform + * + */ + +#ifndef OSCLCONFIG_PROC_H_INCLUDED +#define OSCLCONFIG_PROC_H_INCLUDED + +#ifndef OSCLCONFIG_H_INCLUDED +#include "osclconfig.h" +#endif + +#include "osclconfig_proc_unix_android.h" + +#include "osclconfig_proc_check.h" + + +#endif diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_proc_check.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_proc_check.h new file mode 100644 index 0000000000..0cba8f2556 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_proc_check.h @@ -0,0 +1,157 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#ifndef OSCLCONFIG_PROC_CHECK_H_INCLUDED +#define OSCLCONFIG_PROC_CHECK_H_INCLUDED + +/** +OSCL_HAS_THREAD_SUPPORT macro should be set to 1 if +the target platform supports threads. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_THREAD_SUPPORT +#error "ERROR: OSCL_HAS_THREAD_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_NON_PREEMPTIVE_THREAD_SUPPORT macro should be set to 1 if +the target platform supports non-pre-emptive threads. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_NON_PREEMPTIVE_THREAD_SUPPORT +#error "ERROR: OSCL_HAS_NON_PREEMPTIVE_THREAD_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_SYMBIAN_SCHEDULER macro should be set to 1 if +the target platform supports Symbian active object scheduler. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_SYMBIAN_SCHEDULER +#error "ERROR: OSCL_HAS_SYMBIAN_SCHEDULER has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_SEM_TIMEDWAIT_SUPPORT macro should be set to 1 if +the target platform supports POSIX-compliant semaphores (semaphore.h) +with advanced realtime features including sem_timedwait. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_SEM_TIMEDWAIT_SUPPORT +#error "ERROR: OSCL_HAS_SEM_TIMEDWAIT_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_PTHREAD_SUPPORT macro should be set to 1 if +the target platform supports POSIX-compliand pthreads (pthread.h). +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_PTHREAD_SUPPORT +#error "ERROR: OSCL_HAS_PTHREAD_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +type TOsclThreadId should be defined as the type used as +a thread ID +on the target platform. +Example: +typedef DWORD TOsclThreadId; +*/ +typedef TOsclThreadId __verify__TOsclThreadId__defined__; + +/** +type TOsclThreadFuncRet should be defined as the type used as +a thread function return value +on the target platform. +Example: +typedef DWORD TOsclThreadFuncRet; +*/ +typedef TOsclThreadFuncRet __verify__TOsclThreadFuncRet__defined__; + +/** +type TOsclThreadFuncArg should be defined as the type used as +a thread function argument +on the target platform. +Example: +typedef LPVOID TOsclThreadFuncArg; +*/ +typedef TOsclThreadFuncArg __verify__TOsclThreadFuncArg__defined__; + +/** +OSCL_THREAD_DECL macro should be defined to the +necessary function declaration modifiers for thread routines, +or a null macro if no modifiers are needed. +Example: +#define OSCL_THREAD_DECL WINAPI +*/ +#ifndef OSCL_THREAD_DECL +#error "ERROR: OSCL_THREAD_DECL has to be defined." +#endif + +/** +Example of a declaration of a thread routine called MyThreadMain using +the Oscl definitions: + +static TOsclThreadFuncRet OSCL_THREAD_DECL MyThreadMain(TOsclThreadFuncArg arg); +*/ + +/** +type TOsclThreadObject should be defined as the type used as +a thread object or handle +on the target platform. +Example: +typedef pthread_t TOsclThreadObject; +*/ +typedef TOsclThreadObject __verify__TOsclThreadObject__defined__; + +/** +type TOsclMutexObject should be defined as the type used as +a mutex object or handle +on the target platform. +Example: +typedef pthread_mutex_t TOsclMutexObject; +*/ +typedef TOsclMutexObject __verify__TOsclMutexObject__defined__; + +/** +type TOsclSemaphoreObject should be defined as the type used as +a mutex object or handle +on the target platform. +Example: +typedef sem_t TOsclSemaphoreObject; +*/ +typedef TOsclSemaphoreObject __verify__TOsclSemaphoreObject__defined__; + +/** +type TOsclConditionObject should be defined as the type used as +a condition variable +on the target platform. +Example: +typedef pthread_cond_t TOsclConditionObject; + +Note: Condition variables are only used with certain semaphore implementations. +If the semaphore implementation does not require a condition variable, +then this type can be defined as 'int' as follows: +typedef int TOsclConditionObject; //not used +*/ +typedef TOsclConditionObject __verify__TOsclConditionObject__defined__; + + +#endif //OSCLCONFIG_PROC_CHECK_H_INCLUDED + + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_proc_unix_android.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_proc_unix_android.h new file mode 100644 index 0000000000..c5d05eb4ef --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_proc_unix_android.h @@ -0,0 +1,60 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G _ P R O C ( P L A T F O R M C O N F I G I N F O ) + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig_proc.h + * \brief This file contains configuration information for the linux platform + * + */ + +#ifndef OSCLCONFIG_PROC_UNIX_ANDROID_H_INCLUDED +#define OSCLCONFIG_PROC_UNIX_ANDROID_H_INCLUDED + +#define OSCL_HAS_SYMBIAN_SCHEDULER 0 + +#define OSCL_HAS_THREAD_SUPPORT 1 +#define OSCL_HAS_NON_PREEMPTIVE_THREAD_SUPPORT 0 + +//semaphore with advanced realtime features incl. timed wait. +#define OSCL_HAS_SEM_TIMEDWAIT_SUPPORT 0 +//#include <time.h> +//#include <semaphore.h> + +//pthreads +#define OSCL_HAS_PTHREAD_SUPPORT 1 +#include <pthread.h> +#include <errno.h> +#include <signal.h> + +// threads, mutex, semaphores +typedef pthread_t TOsclThreadId; +typedef void* TOsclThreadFuncArg; +typedef void* TOsclThreadFuncRet; +#define OSCL_THREAD_DECL +typedef pthread_t TOsclThreadObject; +typedef pthread_mutex_t TOsclMutexObject; +typedef int TOsclSemaphoreObject; +typedef pthread_cond_t TOsclConditionObject; + +#endif diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_proc_unix_common.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_proc_unix_common.h new file mode 100644 index 0000000000..104a2ccafe --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_proc_unix_common.h @@ -0,0 +1,59 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G _ P R O C ( P L A T F O R M C O N F I G I N F O ) + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig_proc.h + * \brief This file contains configuration information for the linux platform + * + */ + +#ifndef OSCLCONFIG_PROC_UNIX_COMMON_H_INCLUDED +#define OSCLCONFIG_PROC_UNIX_COMMON_H_INCLUDED + +#define OSCL_HAS_SYMBIAN_SCHEDULER 0 + +#define OSCL_HAS_THREAD_SUPPORT 1 +#define OSCL_HAS_NON_PREEMPTIVE_THREAD_SUPPORT 0 + +//semaphore with advanced realtime features incl. timed wait. +#define OSCL_HAS_SEM_TIMEDWAIT_SUPPORT 1 +#include <time.h> +#include <semaphore.h> + +//pthreads +#define OSCL_HAS_PTHREAD_SUPPORT 1 +#include <pthread.h> +#include <errno.h> + +// threads, mutex, semaphores +typedef pthread_t TOsclThreadId; +typedef void* TOsclThreadFuncArg; +typedef void* TOsclThreadFuncRet; +#define OSCL_THREAD_DECL +typedef pthread_t TOsclThreadObject; +typedef pthread_mutex_t TOsclMutexObject; +typedef sem_t TOsclSemaphoreObject; +typedef pthread_cond_t TOsclConditionObject; + +#endif diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_time.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_time.h new file mode 100644 index 0000000000..cb5365906c --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_time.h @@ -0,0 +1,50 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2010 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G _ T I M E ( T I M E - D E F I N I T I O N S ) + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + + + +#ifndef OSCLCONFIG_TIME_H_INCLUDED +#define OSCLCONFIG_TIME_H_INCLUDED + + +#ifndef OSCLCONFIG_H_INCLUDED +#include "osclconfig.h" +#endif + +// system header files +#include <time.h> // timeval +#include <sys/time.h> // timercmp +#include <unistd.h> + + + +#define OSCL_HAS_UNIX_TIME_FUNCS 1 + +typedef struct timeval OsclBasicTimeStruct; +typedef tm OsclBasicDateTimeStruct; + +#include "osclconfig_time_check.h" + +#endif diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_time_check.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_time_check.h new file mode 100644 index 0000000000..0243d5c1f6 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_time_check.h @@ -0,0 +1,47 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2010 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +//osclconfig: this build configuration file is for win32 +#ifndef OSCLCONFIG_TIME_CHECK_H_INCLUDED +#define OSCLCONFIG_TIME_CHECK_H_INCLUDED + + +/** +OSCL_HAS_UNIX_TIME_FUNCS macro should be set to 1 if +the target platform supports unix time of day functions. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_UNIX_TIME_FUNCS +#error "ERROR: OSCL_HAS_UNIX_TIME_FUNCS has to be defined to either 1 or 0" +#endif + +/** +OsclBasicTimeStruct type should be defined to the platform-specific +time of day type. +*/ +typedef OsclBasicTimeStruct __Validate__BasicTimeStruct__; + +/** +OsclBasicDateTimeStruct type should be defined to the platform-specific +date + time type. +*/ +typedef OsclBasicDateTimeStruct __Validate__BasicTimeDateStruct__; + +#endif //OSCLCONFIG_TIME_CHECK_H_INCLUDED + + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_unix_android.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_unix_android.h new file mode 100644 index 0000000000..f4508ac48d --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_unix_android.h @@ -0,0 +1,105 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2010 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G _ U N I X _ C O M M O N + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig_limits_typedefs.h + * \brief This file contains common typedefs based on the ANSI C limits.h header + * + * This header file should work for any ANSI C compiler to determine the + * proper native C types to use for OSCL integer types. + */ + + +#ifndef OSCLCONFIG_UNIX_ANDROID_H_INCLUDED +#define OSCLCONFIG_UNIX_ANDROID_H_INCLUDED + + +// system header files +#include <stdlib.h> // abort +#include <stdarg.h> // va_list +#include <sys/types.h> +#include <stdio.h> +//#include <wchar.h> +#include <string.h> +#include <unistd.h> //for sleep +#include <pthread.h> +#include <ctype.h> // for tolower and toupper +#ifdef __cplusplus +#include <new> //for placement new +#endif +#include <math.h> + +#define OSCL_DISABLE_INLINES 0 + +#define OSCL_HAS_ANSI_STDLIB_SUPPORT 1 +#define OSCL_HAS_ANSI_MATH_SUPPORT 1 +#define OSCL_HAS_GLOBAL_VARIABLE_SUPPORT 1 +#define OSCL_HAS_ANSI_STRING_SUPPORT 1 +#define OSCL_HAS_ANSI_WIDE_STRING_SUPPORT 0 +#define OSCL_HAS_ANSI_STDIO_SUPPORT 1 + +#define OSCL_MEMFRAG_PTR_BEFORE_LEN 1 + +#define OSCL_HAS_UNIX_SUPPORT 1 +#define OSCL_HAS_MSWIN_SUPPORT 0 +#define OSCL_HAS_MSWIN_PARTIAL_SUPPORT 0 +#define OSCL_HAS_SYMBIAN_SUPPORT 0 +#define OSCL_HAS_IPHONE_SUPPORT 0 + + +// 64-bit int +#define OSCL_NATIVE_INT64_TYPE int64_t +#define OSCL_NATIVE_UINT64_TYPE uint64_t +#define INT64(x) x##LL +#define UINT64(x) x##ULL +#define INT64_HILO(high,low) ((((high##LL))<<32)|low) +#define UINT64_HILO(high,low) ((((high##ULL))<<32)|low) + +// character set. +#define OSCL_HAS_UNICODE_SUPPORT 1 +#define OSCL_NATIVE_WCHAR_TYPE wchar_t +#if (OSCL_HAS_UNICODE_SUPPORT) +#define _STRLIT(x) L ## x +#else +#define _STRLIT(x) x +#endif +#define _STRLIT_CHAR(x) x +#define _STRLIT_WCHAR(x) L ## x + +// Thread-local storage. Unix has keyed TLS. +#define OSCL_HAS_TLS_SUPPORT 1 +#define OSCL_TLS_IS_KEYED 1 +typedef pthread_key_t TOsclTlsKey ; +#define OSCL_TLS_KEY_CREATE_FUNC(key) (pthread_key_create(&key,NULL)==0) +#define OSCL_TLS_KEY_DELETE_FUNC(key) pthread_key_delete(key) +#define OSCL_TLS_STORE_FUNC(key,ptr) (pthread_setspecific(key,(const void*)ptr)==0) +#define OSCL_TLS_GET_FUNC(key) pthread_getspecific(key) + +//Basic lock +#define OSCL_HAS_BASIC_LOCK 1 +#include <pthread.h> +typedef pthread_mutex_t TOsclBasicLockObject; + +#endif // OSCLCONFIG_UNIX_COMMON_H_INCLUDED + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_unix_common.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_unix_common.h new file mode 100644 index 0000000000..d795c497cb --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_unix_common.h @@ -0,0 +1,103 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2010 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +// -*- c++ -*- +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// O S C L C O N F I G _ U N I X _ C O M M O N + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +/*! \file osclconfig_limits_typedefs.h + * \brief This file contains common typedefs based on the ANSI C limits.h header + * + * This header file should work for any ANSI C compiler to determine the + * proper native C types to use for OSCL integer types. + */ + + +#ifndef OSCLCONFIG_UNIX_COMMON_H_INCLUDED +#define OSCLCONFIG_UNIX_COMMON_H_INCLUDED + + +// system header files +#include <stdlib.h> // abort +#include <stdarg.h> // va_list +#include <sys/types.h> +#include <stdio.h> +#include <wchar.h> +#include <string.h> +#include <unistd.h> //for sleep +#include <pthread.h> +#include <ctype.h> // for tolower and toupper +#ifdef __cplusplus +#include <new> //for placement new +#endif +#include <math.h> + +#define OSCL_DISABLE_INLINES 0 + +#define OSCL_HAS_ANSI_STDLIB_SUPPORT 1 +#define OSCL_HAS_ANSI_MATH_SUPPORT 1 +#define OSCL_HAS_GLOBAL_VARIABLE_SUPPORT 1 +#define OSCL_HAS_ANSI_STRING_SUPPORT 1 +#define OSCL_HAS_ANSI_WIDE_STRING_SUPPORT 1 +#define OSCL_HAS_ANSI_STDIO_SUPPORT 1 + +#define OSCL_MEMFRAG_PTR_BEFORE_LEN 1 + +#define OSCL_HAS_UNIX_SUPPORT 1 +#define OSCL_HAS_MSWIN_SUPPORT 0 +#define OSCL_HAS_MSWIN_PARTIAL_SUPPORT 0 +#define OSCL_HAS_SYMBIAN_SUPPORT 0 + +// 64-bit int +#define OSCL_NATIVE_INT64_TYPE int64_t +#define OSCL_NATIVE_UINT64_TYPE uint64_t +#define INT64(x) x##LL +#define UINT64(x) x##ULL +#define INT64_HILO(high,low) ((((high##LL))<<32)|low) +#define UINT64_HILO(high,low) ((((high##ULL))<<32)|low) + +// character set. +#define OSCL_HAS_UNICODE_SUPPORT 1 +#define OSCL_NATIVE_WCHAR_TYPE wchar_t +#if (OSCL_HAS_UNICODE_SUPPORT) +#define _STRLIT(x) L ## x +#else +#define _STRLIT(x) x +#endif +#define _STRLIT_CHAR(x) x +#define _STRLIT_WCHAR(x) L ## x + +// Thread-local storage. Unix has keyed TLS. +#define OSCL_HAS_TLS_SUPPORT 1 +#define OSCL_TLS_IS_KEYED 1 +typedef pthread_key_t TOsclTlsKey ; +#define OSCL_TLS_KEY_CREATE_FUNC(key) (pthread_key_create(&key,NULL)==0) +#define OSCL_TLS_KEY_DELETE_FUNC(key) pthread_key_delete(key) +#define OSCL_TLS_STORE_FUNC(key,ptr) (pthread_setspecific(key,(const void*)ptr)==0) +#define OSCL_TLS_GET_FUNC(key) pthread_getspecific(key) + +//Basic lock +#define OSCL_HAS_BASIC_LOCK 1 +#include <pthread.h> +typedef pthread_mutex_t TOsclBasicLockObject; + +#endif // OSCLCONFIG_UNIX_COMMON_H_INCLUDED + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_util.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_util.h new file mode 100644 index 0000000000..a169848541 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_util.h @@ -0,0 +1,43 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +#ifndef OSCLCONFIG_UTIL_H_INCLUDED +#define OSCLCONFIG_UTIL_H_INCLUDED + +#ifndef OSCLCONFIG_H_INCLUDED +#include "osclconfig.h" +#endif + +#include <stdio.h> //sprintf +#include <time.h> // OSCL clock +#include <sys/time.h> // timeval + +#define OSCL_CLOCK_HAS_DRIFT_CORRECTION 0 +#define OSCL_HAS_SYMBIAN_TIMERS 0 +#define OSCL_HAS_SYMBIAN_MATH 0 + +#define OSCL_RAND_MAX RAND_MAX + +//Define system sleep call for the tick count test here. +#include <unistd.h> +#define SLEEP_ONE_SEC sleep(1) + + +#include "osclconfig_util_check.h" + +#endif + diff --git a/tools/android/depends/libomxil-bellagio/oscl/osclconfig_util_check.h b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_util_check.h new file mode 100644 index 0000000000..f615c4a164 --- /dev/null +++ b/tools/android/depends/libomxil-bellagio/oscl/osclconfig_util_check.h @@ -0,0 +1,58 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +#ifndef OSCLCONFIG_UTIL_CHECK_H_INCLUDED +#define OSCLCONFIG_UTIL_CHECK_H_INCLUDED + +/** +OSCL_HAS_SYMBIAN_TIMERS macro should be set to 1 if +the target platform supports Symbian timers (RTimer). +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_SYMBIAN_TIMERS +#error "ERROR: OSCL_HAS_SYMBIAN_TIMERS has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_SYMBIAN_MATH macro should be set to 1 if +the target platform supports Symbian <e32math.h> features. +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_SYMBIAN_MATH +#error "ERROR: OSCL_HAS_SYMBIAN_MATH has to be defined to either 1 or 0" +#endif + +/** +OSCL_HAS_ANSI_MATH_SUPPORT macro should be set to 1 if +the target platform supports the ANSI C math functions (math.h) +Otherwise it should be set to 0. +*/ +#ifndef OSCL_HAS_ANSI_MATH_SUPPORT +#error "ERROR: OSCL_HAS_ANSI_MATH_SUPPORT has to be defined to either 1 or 0" +#endif + +/** +OSCL_CLOCK_HAS_DRIFT_CORRECTION macro should be set to 1 if the target platform +has drift correction Otherwise it should be set to 0. +*/ +#ifndef OSCL_CLOCK_HAS_DRIFT_CORRECTION +#error "ERROR: OSCL_CLOCK_HAS_DRIFT_CORRECTION has to be defined to either 1 or 0" +#endif + +#endif // OSCLCONFIG_UTIL_CHECK_H_INCLUDED + + diff --git a/tools/android/depends/libplist/0001-dontbuildswig.patch b/tools/android/depends/libplist/0001-dontbuildswig.patch new file mode 100644 index 0000000000..7ff491df8d --- /dev/null +++ b/tools/android/depends/libplist/0001-dontbuildswig.patch @@ -0,0 +1,11 @@ +--- a/CMakeLists.txt 2011-08-18 21:45:33.000000000 +0200 ++++ b/CMakeLists.txt 2011-08-18 21:45:16.000000000 +0200 +@@ -36,7 +36,7 @@ + ADD_SUBDIRECTORY( test ) + + IF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND ) +- ADD_SUBDIRECTORY( swig ) ++# ADD_SUBDIRECTORY( swig ) + ENDIF ( SWIG_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND ) + + # add uninstall target diff --git a/tools/android/depends/libplist/0002-missing-libs.patch b/tools/android/depends/libplist/0002-missing-libs.patch new file mode 100644 index 0000000000..5d2bf7fdbe --- /dev/null +++ b/tools/android/depends/libplist/0002-missing-libs.patch @@ -0,0 +1,12 @@ +diff -ruN armeabi-v7a/src/CMakeLists.txt armeabi-v7a.good//src/CMakeLists.txt +--- src/CMakeLists.txt 2011-06-24 21:00:48.000000000 -0400 ++++ src/CMakeLists.txt 2012-06-08 13:52:14.934096496 -0400 +@@ -35,7 +35,7 @@ + SET_SOURCE_FILES_PROPERTIES(${libcnary_object_files} PROPERTIES EXTERNAL_OBJECT true GENERATED true) + + ADD_LIBRARY( plist SHARED ${libplist_SRC} ${libcnary_object_files} ) +-TARGET_LINK_LIBRARIES( plist ${LIBXML2_LIBRARIES} ) ++TARGET_LINK_LIBRARIES( plist m z iconv ${LIBXML2_LIBRARIES} ) + SET_TARGET_PROPERTIES( plist PROPERTIES VERSION ${LIBPLIST_LIBVERSION} ) + SET_TARGET_PROPERTIES( plist PROPERTIES SOVERSION ${LIBPLIST_SOVERSION} ) + if(APPLE) diff --git a/tools/android/depends/libplist/0003-no-so-version.patch b/tools/android/depends/libplist/0003-no-so-version.patch new file mode 100644 index 0000000000..5474b29796 --- /dev/null +++ b/tools/android/depends/libplist/0003-no-so-version.patch @@ -0,0 +1,23 @@ +--- src/CMakeLists.txt.orig 2012-06-23 03:33:46.000000000 +0200 ++++ src/CMakeLists.txt 2012-06-23 03:34:24.000000000 +0200 +@@ -36,16 +36,16 @@ + + ADD_LIBRARY( plist SHARED ${libplist_SRC} ${libcnary_object_files} ) + TARGET_LINK_LIBRARIES( plist m z iconv ${LIBXML2_LIBRARIES} ) +-SET_TARGET_PROPERTIES( plist PROPERTIES VERSION ${LIBPLIST_LIBVERSION} ) +-SET_TARGET_PROPERTIES( plist PROPERTIES SOVERSION ${LIBPLIST_SOVERSION} ) ++#SET_TARGET_PROPERTIES( plist PROPERTIES VERSION ${LIBPLIST_LIBVERSION} ) ++#SET_TARGET_PROPERTIES( plist PROPERTIES SOVERSION ${LIBPLIST_SOVERSION} ) + if(APPLE) + SET_TARGET_PROPERTIES( plist PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib") + endif() + + ADD_LIBRARY( plist++ SHARED ${libplist++_SRC} ) + TARGET_LINK_LIBRARIES( plist++ plist ) +-SET_TARGET_PROPERTIES( plist++ PROPERTIES VERSION ${LIBPLIST_LIBVERSION} ) +-SET_TARGET_PROPERTIES( plist++ PROPERTIES SOVERSION ${LIBPLIST_SOVERSION} ) ++#SET_TARGET_PROPERTIES( plist++ PROPERTIES VERSION ${LIBPLIST_LIBVERSION} ) ++#SET_TARGET_PROPERTIES( plist++ PROPERTIES SOVERSION ${LIBPLIST_SOVERSION} ) + if(APPLE) + SET_TARGET_PROPERTIES( plist++ PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib") + endif() diff --git a/tools/android/depends/libplist/Makefile b/tools/android/depends/libplist/Makefile new file mode 100644 index 0000000000..104f51c73a --- /dev/null +++ b/tools/android/depends/libplist/Makefile @@ -0,0 +1,54 @@ +include ../Makefile.include +DEPS= ../Makefile.include 0001-dontbuildswig.patch 0002-missing-libs.patch \ + 0003-no-so-version.patch Makefile + +# lib name, version +LIBNAME=libplist +VERSION=1.6 +SOURCE=$(LIBNAME)-$(VERSION) +FILENAME=v$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +LIBDYLIB=$(PLATFORM)/build/src/libplist++.so + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 < ../0001-dontbuildswig.patch + cd $(PLATFORM); patch -p0 < ../0002-missing-libs.patch + cd $(PLATFORM); patch -p0 < ../0003-no-so-version.patch + cd $(PLATFORM); rm -rf build; mkdir -p build + cd $(PLATFORM)/build; CC=$(CC) CXX=$(CXX) cmake \ + -DCMAKE_C_FLAGS:STRING="$(CPPFLAGS) $(CFLAGS)" \ + -DCMAKE_CXX_FLAGS:STRING="$(CPPFLAGS) $(CXXFLAGS)" \ + -DCMAKE_INCLUDE_PATH=$(PREFIX)/include \ + -DCMAKE_LIBRARY_PATH=$(PREFIX)/lib \ + -DCMAKE_INSTALL_NAME_DIR=$(PREFIX)/lib \ + -DCMAKE_INSTALL_PREFIX=$(PREFIX) \ + -DCMAKE_SYSTEM_NAME=Linux \ + -DCMAKE_FIND_ROOT_PATH=$(platform_sdk_path) .. + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -j 1 -C $(PLATFORM)/build + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM)/build install + + rm -f $(PREFIX)/lib/libplist.la + -$(READELF) --dynamic $(PREFIX)/lib/libplist.so | grep ibrary + + rm -f $(PREFIX)/lib/libplist++.la + -$(READELF) --dynamic $(PREFIX)/lib/libplist++.so | grep ibrary + touch $@ + +clean: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libpng-native/Makefile b/tools/android/depends/libpng-native/Makefile new file mode 100644 index 0000000000..e220ae1864 --- /dev/null +++ b/tools/android/depends/libpng-native/Makefile @@ -0,0 +1,42 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libpng +#VERSION=1.4.4 +VERSION=1.2.38 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) + +LIBDYLIB=$(PLATFORM)/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/libpng/Makefile b/tools/android/depends/libpng/Makefile new file mode 100644 index 0000000000..9990124e44 --- /dev/null +++ b/tools/android/depends/libpng/Makefile @@ -0,0 +1,41 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libpng +#VERSION=1.4.4 +VERSION=1.2.38 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared + +LIBDYLIB=$(PLATFORM)/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/librtmp/Makefile b/tools/android/depends/librtmp/Makefile new file mode 100644 index 0000000000..02a8ea2e3a --- /dev/null +++ b/tools/android/depends/librtmp/Makefile @@ -0,0 +1,43 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile prefix.patch + +# lib name, version +LIBNAME=rtmpdump +VERSION=2.3 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tgz + +# configuration settings + +LIBDYLIB=$(PLATFORM)/librtmp/librtmp.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p0 < ../prefix.patch + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM)/librtmp CROSS_COMPILE=$(CROSSTOOLS) PREFIX=$(PREFIX) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM)/librtmp install PREFIX=$(PREFIX) + rm -f $(PREFIX)/lib/librtmp.la $(PREFIX)/lib/librtmp.so + mv -f $(PREFIX)/lib/librtmp.so.0 $(PREFIX)/lib/librtmp.so + $(RPL) -e "librtmp.so.0" "librtmp.so\x00\x00" $(PREFIX)/lib/librtmp.so + -$(READELF) --dynamic $(PREFIX)/lib/librtmp.so | grep ibrary + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/librtmp/prefix.patch b/tools/android/depends/librtmp/prefix.patch new file mode 100644 index 0000000000..198a85cf79 --- /dev/null +++ b/tools/android/depends/librtmp/prefix.patch @@ -0,0 +1,10 @@ +--- librtmp/Makefile 2010-06-30 15:58:35.000000000 -0400 ++++ librtmp/Makefile.2 2011-03-31 16:19:52.813884882 -0400 +@@ -1,6 +1,6 @@ + VERSION=v2.3 + +-prefix=/usr/local ++prefix=$(PREFIX) + + CC=$(CROSS_COMPILE)gcc + LD=$(CROSS_COMPILE)ld diff --git a/tools/android/depends/libsamplerate/Makefile b/tools/android/depends/libsamplerate/Makefile new file mode 100644 index 0000000000..ef3b0925fe --- /dev/null +++ b/tools/android/depends/libsamplerate/Makefile @@ -0,0 +1,42 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libsamplerate +VERSION=0.1.7 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + cp -f $(CONFIG_SUB) $(CONFIG_GUESS) Cfg; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-sndfile --disable-fftw --disable-shared + +LIBDYLIB=$(PLATFORM)/src/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libsdl/01-SDL_SetWidthHeight.patch b/tools/android/depends/libsdl/01-SDL_SetWidthHeight.patch new file mode 100644 index 0000000000..0e26023554 --- /dev/null +++ b/tools/android/depends/libsdl/01-SDL_SetWidthHeight.patch @@ -0,0 +1,33 @@ +Index: include/SDL_video.h +=================================================================== +--- include/SDL_video.h (revision 4116) ++++ include/SDL_video.h (working copy) +@@ -324,6 +324,11 @@ + extern DECLSPEC SDL_Rect ** SDLCALL SDL_ListModes(SDL_PixelFormat *format, Uint32 flags); + + /** ++* Alter the width and height of the current surface to the given sizes. ++*/ ++extern DECLSPEC void SDLCALL SDL_SetWidthHeight(int width, int height); ++ ++/** + * Set up a video mode with the specified width, height and bits-per-pixel. + * + * If 'bpp' is 0, it is treated as the current display bits per pixel. + +Index: src/video/SDL_video.c +=================================================================== +--- src/video/SDL_video.c (revision 4116) ++++ src/video/SDL_video.c (working copy) +@@ -1956,3 +1956,11 @@ + return(0); + } + } ++ ++void SDL_SetWidthHeight(int width, int height) ++{ ++ if (current_video != NULL && current_video->screen != NULL) { ++ current_video->screen->w = width; ++ current_video->screen->h = height; ++ } ++} diff --git a/tools/android/depends/libsdl/02-mmx.patch b/tools/android/depends/libsdl/02-mmx.patch new file mode 100644 index 0000000000..82f51aa787 --- /dev/null +++ b/tools/android/depends/libsdl/02-mmx.patch @@ -0,0 +1,12 @@ +--- src/video/mmx.h Mon Feb 06 08:28:51 2006 +0000 ++++ src/video/mmx.h Sun Jan 30 13:38:57 2011 -0800 +@@ -355,7 +355,7 @@ + + #define mmx_r2m(op, reg, mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ +- : "=X" (mem) \ ++ : "=m" (mem) \ + : /* nothing */ ) + + #define mmx_r2r(op, regs, regd) \ + diff --git a/tools/android/depends/libsdl/Makefile b/tools/android/depends/libsdl/Makefile new file mode 100644 index 0000000000..4dab88b76c --- /dev/null +++ b/tools/android/depends/libsdl/Makefile @@ -0,0 +1,43 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include 01-SDL_SetWidthHeight.patch 02-mmx.patch Makefile + +# lib name, version +LIBNAME=SDL +VERSION=1.2.14 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) \ + --without-x --disable-video-x11 --disable-video-directfb + +LIBDYLIB=$(PLATFORM)/build/.libs/lib$(LIBNAME).so + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + echo $(ARCHIVE) > .gitignore + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + echo $(PLATFORM) > .gitignore + cd $(PLATFORM); patch -p0 < ../01-SDL_SetWidthHeight.patch + cd $(PLATFORM); patch -p0 < ../02-mmx.patch + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -j 1 -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/libsdl_image/Makefile b/tools/android/depends/libsdl_image/Makefile new file mode 100644 index 0000000000..22bde73ecc --- /dev/null +++ b/tools/android/depends/libsdl_image/Makefile @@ -0,0 +1,40 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS=Makefile + +# lib name, version +LIBNAME=SDL_image +VERSION=1.2.7 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) \ + --disable-jpg-shared --disable-png-shared --disable-tif-shared --disable-sdltest + +LIBDYLIB=$(PLATFORM)/.libs/lib$(LIBNAME).so + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + echo $(PLATFORM) > .gitignore + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/libshairport/001_add_ao.patch b/tools/android/depends/libshairport/001_add_ao.patch new file mode 100644 index 0000000000..995f7b78ee --- /dev/null +++ b/tools/android/depends/libshairport/001_add_ao.patch @@ -0,0 +1,270 @@ +diff -uP libshairport-1.2.0.20310_lib/src/ao.h ../../../../../libshairport-1.2.0.20310_lib/src/ao.h +--- src/ao.h 1970-01-01 01:00:00.000000000 +0100 ++++ src/ao.h 2011-09-25 20:36:36.000000000 +0200 +@@ -0,0 +1,156 @@ ++/* ++ * ++ * ao.h ++ * ++ * Original Copyright (C) Aaron Holtzman - May 1999 ++ * Modifications Copyright (C) Stan Seibert - July 2000, July 2001 ++ * More Modifications Copyright (C) Jack Moffitt - October 2000 ++ * ++ * This file is part of libao, a cross-platform audio outputlibrary. See ++ * README for a history of this source code. ++ * ++ * libao is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * libao 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GNU Make; see the file COPYING. If not, write to ++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++#ifndef __AO_H__ ++#define __AO_H__ ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif /* __cplusplus */ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <stdint.h> ++#include <errno.h> ++ ++/* --- Constants ---*/ ++ ++#define AO_TYPE_LIVE 1 ++#define AO_TYPE_FILE 2 ++ ++ ++#define AO_ENODRIVER 1 ++#define AO_ENOTFILE 2 ++#define AO_ENOTLIVE 3 ++#define AO_EBADOPTION 4 ++#define AO_EOPENDEVICE 5 ++#define AO_EOPENFILE 6 ++#define AO_EFILEEXISTS 7 ++#define AO_EBADFORMAT 8 ++ ++#define AO_EFAIL 100 ++ ++ ++#define AO_FMT_LITTLE 1 ++#define AO_FMT_BIG 2 ++#define AO_FMT_NATIVE 4 ++ ++/* --- Structures --- */ ++ ++typedef struct ao_info { ++ int type; /* live output or file output? */ ++ char *name; /* full name of driver */ ++ char *short_name; /* short name of driver */ ++ char *author; /* driver author */ ++ char *comment; /* driver comment */ ++ int preferred_byte_format; ++ int priority; ++ char **options; ++ int option_count; ++} ao_info; ++ ++typedef struct ao_functions ao_functions; ++typedef struct ao_device ao_device; ++ ++typedef struct ao_sample_format { ++ int bits; /* bits per sample */ ++ int rate; /* samples per second (in a single channel) */ ++ int channels; /* number of audio channels */ ++ int byte_format; /* Byte ordering in sample, see constants below */ ++ char *matrix; /* input channel location/ordering */ ++} ao_sample_format; ++ ++typedef struct ao_option { ++ char *key; ++ char *value; ++ struct ao_option *next; ++} ao_option; ++ ++#if defined(AO_BUILDING_LIBAO) ++#include "ao_private.h" ++#endif ++ ++/* --- Functions --- */ ++ ++/* library setup/teardown */ ++void ao_initialize(void); ++void ao_shutdown(void); ++ ++/* device setup/playback/teardown */ ++int ao_append_global_option(const char *key, ++ const char *value); ++int ao_append_option(ao_option **options, ++ const char *key, ++ const char *value); ++void ao_free_options(ao_option *options); ++ ++char* ao_get_option(ao_option *options, const char* key); ++ ++ao_device* ao_open_live(int driver_id, ++ ao_sample_format *format, ++ ao_option *option); ++ao_device* ao_open_file(int driver_id, ++ const char *filename, ++ int overwrite, ++ ao_sample_format *format, ++ ao_option *option); ++ ++int ao_play(ao_device *device, ++ char *output_samples, ++ uint32_t num_bytes); ++int ao_close(ao_device *device); ++ ++/* driver information */ ++int ao_driver_id(const char *short_name); ++int ao_default_driver_id(void); ++ao_info *ao_driver_info(int driver_id); ++ao_info **ao_driver_info_list(int *driver_count); ++char *ao_file_extension(int driver_id); ++ ++/* miscellaneous */ ++int ao_is_big_endian(void); ++ ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif /* __AO_H__ */ ++ ++extern struct AudioOutput g_ao; ++struct AudioOutput ++ { ++ void (*ao_initialize)(void); ++ int (*ao_play)(ao_device *, char *, uint32_t); ++ int (*ao_default_driver_id)(void); ++ ao_device* (*ao_open_live)( int, ao_sample_format *, ao_option *); ++ int (*ao_close)(ao_device *); ++ /* -- Device Setup/Playback/Teardown -- */ ++ int (*ao_append_option)(ao_option **, const char *, const char *); ++ void (*ao_free_options)(ao_option *); ++ char* (*ao_get_option)(ao_option *, const char* ); ++ }; +diff -uP libshairport-1.2.0.20310_lib/src/hairtunes.c ../../../../../libshairport-1.2.0.20310_lib/src/hairtunes.c +--- src/hairtunes.c 2011-09-23 21:55:48.000000000 +0200 ++++ src/hairtunes.c 2011-09-25 20:37:49.000000000 +0200 +@@ -25,7 +25,7 @@ + */ + + #define XBMC +-//#defined HAS_AO ++#define HAS_AO + + #include <stdio.h> + #include <stdlib.h> +@@ -45,7 +45,7 @@ + #include <sys/signal.h> + #include <fcntl.h> + #ifdef HAS_AO +-#include <ao/ao.h> ++#include "ao.h" + #endif + + #ifdef FANCY_RESAMPLING +@@ -881,7 +881,7 @@ + } + #ifdef HAS_AO + } else { +- ao_play(dev, (char *)outbuf, play_samples*4); ++ g_ao.ao_play(dev, (char *)outbuf, play_samples*4); + #endif + } + } +@@ -906,7 +906,7 @@ + ao_device *dev; + + void* init_ao() { +- ao_initialize(); ++ g_ao.ao_initialize(); + + int driver; + #ifndef XBMC +@@ -921,7 +921,7 @@ + #endif + { + // otherwise choose the default +- driver = ao_default_driver_id(); ++ driver = g_ao.ao_default_driver_id(); + } + + ao_sample_format fmt; +@@ -944,9 +944,9 @@ + } + #endif + +- ao_append_option(&ao_opts, "name", "Streaming..."); ++ g_ao.ao_append_option(&ao_opts, "name", "Streaming..."); + +- dev = ao_open_live(driver, &fmt, ao_opts); ++ dev = g_ao.ao_open_live(driver, &fmt, ao_opts); + if (dev == NULL) { + die("Could not open ao device"); + } +@@ -985,7 +985,7 @@ + audio_running = 0; + pthread_join(audio_thread, NULL); + #ifdef HAS_AO +- ao_close(dev); ++ g_ao.ao_close(dev); + #endif + } + +diff -uP libshairport-1.2.0.20310_lib/src/shairport.c ../../../../../libshairport-1.2.0.20310_lib/src/shairport.c +--- src/shairport.c 2011-08-21 01:57:56.000000000 +0200 ++++ src/shairport.c 2011-09-25 20:44:40.000000000 +0200 +@@ -92,6 +92,14 @@ + static char tPassword[56] = ""; + static char tHWID[HWID_SIZE] = {0,51,52,53,54,55}; + ++#ifdef XBMC ++struct AudioOutput g_ao; ++void shairport_set_ao(struct AudioOutput *ao) ++{ ++ g_ao=*ao; ++} ++#endif ++ + #ifndef XBMC + int main(int argc, char **argv) + #else +diff -uP libshairport-1.2.0.20310_lib/src/shairport.h ../../../../../libshairport-1.2.0.20310_lib/src/shairport.h +--- src/shairport.h 2011-08-21 01:58:11.000000000 +0200 ++++ src/shairport.h 2011-09-25 20:36:43.000000000 +0200 +@@ -11,6 +11,7 @@ + #include <regex.h> + #include <sys/types.h> + #include <regex.h> ++#include "ao.h" + + + #define HWID_SIZE 6 +@@ -62,9 +63,11 @@ + void shairport_exit(void); + int shairport_loop(void); + int shairport_is_running(void); ++void shairport_set_ao(struct AudioOutput *ao); + + #ifdef __cplusplus + } + #endif /* __cplusplus */ + + #endif ++ diff --git a/tools/android/depends/libshairport/002_fix_install_header.patch b/tools/android/depends/libshairport/002_fix_install_header.patch new file mode 100644 index 0000000000..495b97346c --- /dev/null +++ b/tools/android/depends/libshairport/002_fix_install_header.patch @@ -0,0 +1,12 @@ +--- src/Makefile.am.old 2011-09-23 23:14:39.000000000 +0200 ++++ src/Makefile.am 2011-09-25 21:38:08.000000000 +0200 +@@ -1,7 +1,7 @@ + lib_LTLIBRARIES=libshairport.la + +-library_includedir=$(includedir) +-library_include_HEADERS = shairport.h ++library_includedir=$(includedir)/shairport ++library_include_HEADERS = shairport.h ao.h socketlib.h + + libshairport_la_SOURCES=shairport.c hairtunes.c socketlib.c alac.c + libshairport_la_LDFLAGS=-dynamiclib diff --git a/tools/android/depends/libshairport/003_fix_deadlock.patch b/tools/android/depends/libshairport/003_fix_deadlock.patch new file mode 100644 index 0000000000..c05970e138 --- /dev/null +++ b/tools/android/depends/libshairport/003_fix_deadlock.patch @@ -0,0 +1,10 @@ +--- src/hairtunes.c.orig 2011-09-25 21:58:08.000000000 +0200 ++++ src/hairtunes.c 2011-09-25 21:58:12.000000000 +0200 +@@ -991,6 +991,7 @@ + + void hairtunes_cleanup(void) + { ++ pthread_cond_signal(&ab_buffer_ready); + clean_output(); + clean_rtp(); + clean_buffer(); diff --git a/tools/android/depends/libshairport/004_fix_bad_access.patch b/tools/android/depends/libshairport/004_fix_bad_access.patch new file mode 100644 index 0000000000..1976904c4d --- /dev/null +++ b/tools/android/depends/libshairport/004_fix_bad_access.patch @@ -0,0 +1,22 @@ +--- src/hairtunes.c.orig 2011-09-25 23:26:56.000000000 +0200 ++++ src/hairtunes.c 2011-09-25 23:29:27.000000000 +0200 +@@ -89,7 +89,6 @@ + // maximal resampling shift - conservative + #define OUTFRAME_BYTES (4*(frame_size+3)) + +- + alac_file *decoder_info; + + #ifdef FANCY_RESAMPLING +@@ -849,6 +848,11 @@ + inbuf = buffer_get_frame(); + } while (!inbuf && audio_running); + ++ if(!audio_running) ++ { ++ return 0; //don't access inbuf if audio stopped ++ } ++ + #ifdef FANCY_RESAMPLING + if (fancy_resampling) { + int i; diff --git a/tools/android/depends/libshairport/005_fix_shutdown.patch b/tools/android/depends/libshairport/005_fix_shutdown.patch new file mode 100644 index 0000000000..32bd282719 --- /dev/null +++ b/tools/android/depends/libshairport/005_fix_shutdown.patch @@ -0,0 +1,10 @@ +--- src/shairport.c 2011-09-25 23:58:06.000000000 +0200 ++++ src/shairport.c.new 2011-09-25 23:57:54.000000000 +0200 +@@ -368,6 +368,7 @@ + void shairport_exit(void) + { + m_running = 0; ++ close(tServerSock); + } + + int shairport_is_running(void) diff --git a/tools/android/depends/libshairport/006_no_printf.patch b/tools/android/depends/libshairport/006_no_printf.patch new file mode 100644 index 0000000000..eb69d42b74 --- /dev/null +++ b/tools/android/depends/libshairport/006_no_printf.patch @@ -0,0 +1,843 @@ +--- src/alac.c 2011-08-21 00:06:21.000000000 +0200 ++++ src/alac.c 2011-10-01 04:12:09.000000000 +0200 +@@ -804,7 +804,7 @@ + } + else + { +- fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type); ++ xprintf("FIXME: unhandled predicition type: %i\n", prediction_type); + /* i think the only other prediction type (or perhaps this is just a + * boolean?) runs adaptive fir twice.. like: + * predictor_decompress_fir_adapt(predictor_error, tempout, ...) +@@ -885,7 +885,7 @@ + } + case 20: + case 32: +- fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size); ++ xprintf("FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size); + break; + default: + break; +@@ -1004,7 +1004,7 @@ + } + else + { /* see mono case */ +- fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_a); ++ xprintf("FIXME: unhandled predicition type: %i\n", prediction_type_a); + } + + /* channel 2 */ +@@ -1029,7 +1029,7 @@ + } + else + { +- fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_b); ++ xprintf("FIXME: unhandled predicition type: %i\n", prediction_type_b); + } + } + else +@@ -1106,7 +1106,7 @@ + } + case 20: + case 32: +- fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size); ++ xprintf("FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size); + break; + default: + break; +--- src/hairtunes.c 2011-10-01 17:45:08.000000000 +0200 ++++ src/hairtunes.c 2011-10-01 17:42:07.000000000 +0200 +@@ -121,8 +121,8 @@ + pthread_cond_t ab_buffer_ready; + + static void die(char *why) { +- fprintf(stderr, "FATAL: %s\n", why); +- exit(1); ++ xprintf("FATAL: %s\n", why); ++ //exit(1); + } + + static int hex2bin(unsigned char *buf, char *hex) { +@@ -245,13 +245,13 @@ + continue; + } + if (!strcmp(line, "exit\n")) { +- exit(0); ++ ;//exit(0); + } + if (!strcmp(line, "flush\n")) { + hairtunes_flush(); + } + } +- fprintf(stderr, "bye!\n"); ++ xprintf("bye!\n"); + fflush(stderr); + #endif + +@@ -262,7 +262,7 @@ + { + assert(f<=0); + if (debug) +- fprintf(stderr, "VOL: %lf\n", f); ++ xprintf("VOL: %lf\n", f); + volume = pow(10.0,0.05*f); + fix_volume = 65536.0 * volume; + } +@@ -273,7 +273,7 @@ + ab_resync(); + pthread_mutex_unlock(&ab_mutex); + if (debug) +- fprintf(stderr, "FLUSH\n"); ++ xprintf("FLUSH\n"); + } + + #ifdef HAIRTUNES_STANDALONE +@@ -423,7 +423,7 @@ + } else if (seq_order(ab_read, seqno)) { // late but not yet played + abuf = audio_buffer + BUFIDX(seqno); + } else { // too late. +- fprintf(stderr, "\nlate packet %04X (%04X:%04X)\n", seqno, ab_read, ab_write); ++ xprintf("\nlate packet %04X (%04X:%04X)\n", seqno, ab_read, ab_write); + } + buf_fill = ab_write - ab_read; + pthread_mutex_unlock(&ab_mutex); +@@ -520,7 +520,7 @@ + if (seq_order(last, first)) + return; + +- fprintf(stderr, "requesting resend on %d packets (port %d)\n", last-first+1, controlport); ++ xprintf("requesting resend on %d packets (port %d)\n", last-first+1, controlport); + + char req[8]; // *not* a standard RTCP NACK + req[0] = 0x80; +@@ -604,8 +604,8 @@ + port += 3; + } + +- printf("port: %d\n", port); // let our handler know where we end up listening +- printf("cport: %d\n", port+1); ++ xprintf("port: %d\n", port); // let our handler know where we end up listening ++ xprintf("cport: %d\n", port+1); + + rtp_sockets[0] = sock; + rtp_sockets[1] = csock; +@@ -708,7 +708,7 @@ + bf_est_drift = biquad_filt(&bf_drift_lpf, CONTROL_B*(bf_est_err*CONTROL_A + err_deriv) + bf_est_drift); + + if (debug) +- fprintf(stderr, "bf %d err %f drift %f desiring %f ed %f estd %f\r", fill, bf_est_err, bf_est_drift, desired_fill, err_deriv, err_deriv + CONTROL_A*bf_est_err); ++ xprintf("bf %d err %f drift %f desiring %f ed %f estd %f\r", fill, bf_est_err, bf_est_drift, desired_fill, err_deriv, err_deriv + CONTROL_A*bf_est_err); + bf_playback_rate = 1.0 + CONTROL_A*bf_est_err + bf_est_drift; + + bf_last_err = bf_est_err; +@@ -724,7 +724,7 @@ + buf_fill = ab_write - ab_read; + if (buf_fill < 1 || !ab_synced || ab_buffering) { // init or underrun. stop and wait + if (ab_synced) +- fprintf(stderr, "\nunderrun\n"); ++ xprintf("\nunderrun\n"); + + ab_buffering = 1; + pthread_cond_wait(&ab_buffer_ready, &ab_mutex); +@@ -736,7 +736,7 @@ + return 0; + } + if (buf_fill >= BUFFER_FRAMES) { // overrunning! uh-oh. restart at a sane distance +- fprintf(stderr, "\noverrun.\n"); ++ xprintf("\noverrun.\n"); + ab_read = ab_write - START_FILL; + } + read = ab_read; +@@ -748,7 +748,7 @@ + + volatile abuf_t *curframe = audio_buffer + BUFIDX(read); + if (!curframe->ready) { +- fprintf(stderr, "\nmissing frame.\n"); ++ xprintf("\nmissing frame.\n"); + memset(curframe->data, 0, FRAME_BYTES); + } + curframe->ready = 0; +@@ -775,13 +775,13 @@ + if (stuff) { + if (stuff==1) { + if (debug) +- fprintf(stderr, "+++++++++\n"); ++ xprintf("+++++++++\n"); + // interpolate one sample + *outptr++ = dithered_vol(((long)inptr[-2] + (long)inptr[0]) >> 1); + *outptr++ = dithered_vol(((long)inptr[-1] + (long)inptr[1]) >> 1); + } else if (stuff==-1) { + if (debug) +- fprintf(stderr, "---------\n"); ++ xprintf("---------\n"); + inptr++; + inptr++; + } +--- src/shairport.c 2011-10-01 17:45:08.000000000 +0200 ++++ src/shairport.c 2011-10-01 17:41:04.000000000 +0200 +@@ -31,6 +31,27 @@ + #include "shairport.h" + #include "hairtunes.h" + ++static struct printfPtr g_printf={NULL}; ++ ++int xprintf(const char *format, ...) ++{ ++ char dbg[2048]; ++ va_list args; ++ va_start(args, format); ++ vsnprintf(dbg, sizeof(dbg), format, args); ++ va_end(args); ++ if(g_printf.extprintf) ++ { ++ g_printf.extprintf(dbg, sizeof(dbg)); ++ } ++ else ++ { ++ printf(dbg); ++ } ++ ++ return 1; ++} ++ + #ifndef TRUE + #define TRUE (-1) + #endif +@@ -98,6 +119,11 @@ + { + g_ao=*ao; + } ++ ++void shairport_set_printf(struct printfPtr *funcPtr) ++{ ++ g_printf = *funcPtr; ++} + #endif + + #ifndef XBMC +@@ -106,7 +132,7 @@ + int shairport_main(int argc, char **argv) + #endif + { +- printf("initializing shairport\n"); ++ xprintf("initializing shairport\n",NULL); + char tHWID_Hex[HWID_SIZE * 2 + 1]; + char tKnownHwid[32]; + +@@ -185,22 +211,22 @@ + } + else if(!strcmp(arg, "-h") || !strcmp(arg, "--help")) + { +- slog(LOG_INFO, "ShairPort version 0.05 C port - Airport Express emulator\n"); +- slog(LOG_INFO, "Usage:\nshairport [OPTION...]\n\nOptions:\n"); +- slog(LOG_INFO, " -a, --apname=AirPort Sets Airport name\n"); +- slog(LOG_INFO, " -p, --password=secret Sets Password (not working)\n"); +- slog(LOG_INFO, " -o, --server_port=5000 Sets Port for Avahi/dns-sd\n"); +- slog(LOG_INFO, " -b, --buffer=282 Sets Number of frames to buffer before beginning playback\n"); +- slog(LOG_INFO, " -d Daemon mode\n"); +- slog(LOG_INFO, " -q, --quiet Supresses all output.\n"); +- slog(LOG_INFO, " -v,-v2,-v3,-vv Various debugging levels\n"); +- slog(LOG_INFO, "\n"); ++ xprintf("ShairPort version 0.05 C port - Airport Express emulator\n"); ++ xprintf("Usage:\nshairport [OPTION...]\n\nOptions:\n"); ++ xprintf(" -a, --apname=AirPort Sets Airport name\n"); ++ xprintf(" -p, --password=secret Sets Password (not working)\n"); ++ xprintf(" -o, --server_port=5000 Sets Port for Avahi/dns-sd\n"); ++ xprintf(" -b, --buffer=282 Sets Number of frames to buffer before beginning playback\n"); ++ xprintf(" -d Daemon mode\n"); ++ xprintf(" -q, --quiet Supresses all output.\n"); ++ xprintf(" -v,-v2,-v3,-vv Various debugging levels\n"); ++ xprintf("\n"); + return 0; + } + } + + if ( buffer_start_fill < 30 || buffer_start_fill > BUFFER_FRAMES ) { +- fprintf(stderr, "buffer value must be > 30 and < %d\n", BUFFER_FRAMES); ++ xprintf("buffer value must be > 30 and < %d\n", BUFFER_FRAMES); + return(0); + } + +@@ -209,11 +235,11 @@ + int tPid = fork(); + if(tPid < 0) + { +- exit(1); // Error on fork ++ //exit(1); // Error on fork + } + else if(tPid > 0) + { +- exit(0); ++ //exit(0); + } + else + { +@@ -254,10 +280,10 @@ + sscanf(tHWID_Hex, "%02X%02X%02X%02X%02X%02X", &tHWID[0], &tHWID[1], &tHWID[2], &tHWID[3], &tHWID[4], &tHWID[5]); + } + +- slog(LOG_INFO, "LogLevel: %d\n", kCurrentLogLevel); +- slog(LOG_INFO, "AirName: %s\n", tServerName); +- slog(LOG_INFO, "HWID: %.*s\n", HWID_SIZE, tHWID+1); +- slog(LOG_INFO, "HWID_Hex(%d): %s\n", strlen(tHWID_Hex), tHWID_Hex); ++ xprintf("LogLevel: %d\n", kCurrentLogLevel); ++ xprintf("AirName: %s\n", tServerName); ++ xprintf("HWID: %.*s\n", HWID_SIZE, tHWID+1); ++ xprintf("HWID_Hex(%d): %s\n", strlen(tHWID_Hex), tHWID_Hex); + + if(tSimLevel >= 1) + { +@@ -271,12 +297,12 @@ + #ifndef XBMC + startAvahi(tHWID_Hex, tServerName, tPort); + #endif +- slog(LOG_DEBUG_V, "Starting connection server: specified server port: %d\n", tPort); ++ xprintf("Starting connection server: specified server port: %d\n", tPort); + tServerSock = setupListenServer(&tAddrInfo, tPort); + if(tServerSock < 0) + { + freeaddrinfo(tAddrInfo); +- slog(LOG_INFO, "Error setting up server socket on port %d, try specifying a different port\n", tPort); ++ xprintf("Error setting up server socket on port %d, try specifying a different port\n", tPort); + return 0; + } + +@@ -303,7 +329,7 @@ + + int readsock; + +- slog(LOG_DEBUG_V, "Waiting for clients to connect\n"); ++ xprintf("Waiting for clients to connect\n"); + + while(m_running) + { +@@ -335,7 +361,7 @@ + { + freeaddrinfo(tAddrInfo); + tAddrInfo = NULL; +- slog(LOG_DEBUG, "...Accepted Client Connection..\n"); ++ xprintf("...Accepted Client Connection..\n"); + close(tServerSock); + handleClient(tClientSock, tPassword, tHWID); + //close(tClientSock); +@@ -343,11 +369,11 @@ + } + else + { +- slog(LOG_DEBUG_VV, "Child now busy handling new client\n"); ++ xprintf("Child now busy handling new client\n"); + close(tClientSock); + } + #else +- slog(LOG_DEBUG, "...Accepted Client Connection..\n"); ++ xprintf("...Accepted Client Connection..\n"); + handleClient(tClientSock, tPassword, tHWID); + #endif + } +@@ -357,7 +383,7 @@ + } + } + +- slog(LOG_DEBUG_VV, "Finished\n"); ++ xprintf("Finished\n"); + if(tAddrInfo != NULL) + { + freeaddrinfo(tAddrInfo); +@@ -416,7 +442,7 @@ + + void handleClient(int pSock, char *pPassword, char *pHWADDR) + { +- slog(LOG_DEBUG_VV, "In Handle Client\n"); ++ xprintf("In Handle Client\n"); + fflush(stdout); + + socklen_t len; +@@ -435,7 +461,7 @@ + + // deal with both IPv4 and IPv6: + if (addr.ss_family == AF_INET) { +- slog(LOG_DEBUG_V, "Constructing ipv4 address\n"); ++ xprintf("Constructing ipv4 address\n"); + struct sockaddr_in *s = (struct sockaddr_in *)&addr; + port = ntohs(s->sin_port); + inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr); +@@ -455,20 +481,20 @@ + if(memcmp(&addr.bin[0], "\x00\x00\x00\x00" "\x00\x00\x00\x00" "\x00\x00\xff\xff", 12) == 0) + { + // its ipv4... +- slog(LOG_DEBUG_V, "Constructing ipv4 from ipv6 address\n"); ++ xprintf("Constructing ipv4 from ipv6 address\n"); + memcpy(ipbin, &addr.bin[12], 4); + ipbinlen = 4; + } + else + { +- slog(LOG_DEBUG_V, "Constructing ipv6 address\n"); ++ xprintf("Constructing ipv6 address\n"); + memcpy(ipbin, &s->sin6_addr, 16); + ipbinlen = 16; + } + } + +- slog(LOG_DEBUG_V, "Peer IP address: %s\n", ipstr); +- slog(LOG_DEBUG_V, "Peer port : %d\n", port); ++ xprintf("Peer IP address: %s\n", ipstr); ++ xprintf("Peer port : %d\n", port); + + int tMoreDataNeeded = 1; + struct keyring tKeys; +@@ -489,16 +515,16 @@ + tError = readDataFromClient(pSock, &(tConn.recv)); + if(!tError && strlen(tConn.recv.data) > 0) + { +- slog(LOG_DEBUG_VV, "Finished Reading some data from client\n"); ++ xprintf("Finished Reading some data from client\n"); + // parse client request + tMoreDataNeeded = parseMessage(&tConn, ipbin, ipbinlen, pHWADDR); + if(1 == tMoreDataNeeded) + { +- slog(LOG_DEBUG_VV, "\n\nNeed to read more data\n"); ++ xprintf("\n\nNeed to read more data\n"); + } + else if(-1 == tMoreDataNeeded) // Forked process down below ended. + { +- slog(LOG_DEBUG_V, "Forked Process ended...cleaning up\n"); ++ xprintf("Forked Process ended...cleaning up\n"); + cleanup(&tConn); + // pSock was already closed + return; +@@ -507,13 +533,13 @@ + } + else + { +- slog(LOG_DEBUG, "Error reading from socket, closing client\n"); ++ xprintf("Error reading from socket, closing client\n"); + // Error reading data....quit. + cleanup(&tConn); + return; + } + } +- slog(LOG_DEBUG_VV, "Writing: %d chars to socket\n", tConn.resp.current); ++ xprintf("Writing: %d chars to socket\n", tConn.resp.current); + //tConn->resp.data[tConn->resp.current-1] = '\0'; + writeDataToClient(pSock, &(tConn.resp)); + // Finished reading one message... +@@ -526,9 +552,9 @@ + + void writeDataToClient(int pSock, struct shairbuffer *pResponse) + { +- slog(LOG_DEBUG_VV, "\n----Beg Send Response Header----\n%.*s\n", pResponse->current, pResponse->data); ++ xprintf("\n----Beg Send Response Header----\n%.*s\n", pResponse->current, pResponse->data); + send(pSock, pResponse->data, pResponse->current,0); +- slog(LOG_DEBUG_VV, "----Send Response Header----\n"); ++ xprintf("----Send Response Header----\n"); + } + + int readDataFromClient(int pSock, struct shairbuffer *pClientBuffer) +@@ -541,7 +567,7 @@ + while(tRetval > 0 && tEnd < 0) + { + // Read from socket until \n\n, \r\n\r\n, or \r\r is found +- slog(LOG_DEBUG_V, "Waiting To Read...\n"); ++ xprintf("Waiting To Read...\n"); + fflush(stdout); + tRetval = read(pSock, tReadBuf, MAX_SIZE); + // if new buffer contains the end of request string, only copy partial buffer? +@@ -552,40 +578,40 @@ + { + pClientBuffer->marker = tEnd+1; // Marks start of content + } +- slog(SOCKET_LOG_LEVEL, "Found end of http request at: %d\n", tEnd); ++ xprintf("Found end of http request at: %d\n", tEnd); + fflush(stdout); + } + else + { + tEnd = MAX_SIZE; +- slog(SOCKET_LOG_LEVEL, "Read %d of data so far\n%s\n", tRetval, tReadBuf); ++ xprintf("Read %d of data so far\n%s\n", tRetval, tReadBuf); + fflush(stdout); + } + if(tRetval > 0) + { + // Copy read data into tReceive; +- slog(SOCKET_LOG_LEVEL, "Read %d data, using %d of it\n", tRetval, tEnd); ++ xprintf("Read %d data, using %d of it\n", tRetval, tEnd); + addNToShairBuffer(pClientBuffer, tReadBuf, tRetval); +- slog(LOG_DEBUG_VV, "Finished copying data\n"); ++ xprintf("Finished copying data\n"); + } + else + { +- slog(LOG_DEBUG, "Error reading data from socket, got: %d bytes", tRetval); ++ xprintf("Error reading data from socket, got: %d bytes", tRetval); + return tRetval; + } + } + if(tEnd + 1 != tRetval) + { +- slog(SOCKET_LOG_LEVEL, "Read more data after end of http request. %d instead of %d\n", tRetval, tEnd+1); ++ xprintf("Read more data after end of http request. %d instead of %d\n", tRetval, tEnd+1); + } +- slog(SOCKET_LOG_LEVEL, "Finished Reading Data:\n%s\nEndOfData\n", pClientBuffer->data); ++ xprintf("Finished Reading Data:\n%s\nEndOfData\n", pClientBuffer->data); + fflush(stdout); + return 0; + } + + char *getFromBuffer(char *pBufferPtr, const char *pField, int pLenAfterField, int *pReturnSize, char *pDelims) + { +- slog(LOG_DEBUG_V, "GettingFromBuffer: %s\n", pField); ++ xprintf("GettingFromBuffer: %s\n", pField); + char* tFound = strstr(pBufferPtr, pField); + int tSize = 0; + if(tFound != NULL) +@@ -606,7 +632,7 @@ + } + + tSize = (int) (tShortest - tFound); +- slog(LOG_DEBUG_VV, "Found %.*s length: %d\n", tSize, tFound, tSize); ++ xprintf("Found %.*s length: %d\n", tSize, tFound, tSize); + if(pReturnSize != NULL) + { + *pReturnSize = tSize; +@@ -614,7 +640,7 @@ + } + else + { +- slog(LOG_DEBUG_V, "Not Found\n"); ++ xprintf("Not Found\n"); + } + return tFound; + } +@@ -648,10 +674,10 @@ + { + char tTrim[tFoundSize + 2]; + getTrimmed(tFound, tFoundSize, TRUE, TRUE, tTrim); +- slog(LOG_DEBUG_VV, "HeaderChallenge: [%s] len: %d sizeFound: %d\n", tTrim, strlen(tTrim), tFoundSize); ++ xprintf("HeaderChallenge: [%s] len: %d sizeFound: %d\n", tTrim, strlen(tTrim), tFoundSize); + int tChallengeDecodeSize = 16; + char *tChallenge = decode_base64((unsigned char *)tTrim, tFoundSize, &tChallengeDecodeSize); +- slog(LOG_DEBUG_VV, "Challenge Decode size: %d expected 16\n", tChallengeDecodeSize); ++ xprintf("Challenge Decode size: %d expected 16\n", tChallengeDecodeSize); + + int tCurSize = 0; + unsigned char tChalResp[38]; +@@ -673,7 +699,7 @@ + } + + char *tTmp = encode_base64((unsigned char *)tChalResp, tCurSize); +- slog(LOG_DEBUG_VV, "Full sig: %s\n", tTmp); ++ xprintf("Full sig: %s\n", tTmp); + free(tTmp); + + // RSA Encrypt +@@ -722,10 +748,10 @@ + { + if(isLogEnabledFor(HEADER_LOG_LEVEL)) + { +- slog(HEADER_LOG_LEVEL, "Content-Length: %s value -> %d\n", tContent, tContentSize); ++ xprintf("Content-Length: %s value -> %d\n", tContent, tContentSize); + if(pConn->recv.marker != 0) + { +- slog(HEADER_LOG_LEVEL, "ContentPtr has %d, but needs %d\n", ++ xprintf("ContentPtr has %d, but needs %d\n", + strlen(pConn->recv.data+pConn->recv.marker), tContentSize); + } + } +@@ -735,7 +761,7 @@ + } + else + { +- slog(LOG_DEBUG_VV, "No content, header only\n"); ++ xprintf("No content, header only\n"); + } + + // "Creates" a new Response Header for our response message +@@ -748,7 +774,7 @@ + { + tLen = 20; + } +- slog(LOG_INFO, "********** RECV %.*s **********\n", tLen, pConn->recv.data); ++ xprintf("********** RECV %.*s **********\n", tLen, pConn->recv.data); + } + + if(pConn->password != NULL) +@@ -758,7 +784,7 @@ + + if(buildAppleResponse(pConn, pIpBin, pIpBinLen, pHWID)) // need to free sig + { +- slog(LOG_DEBUG_V, "Added AppleResponse to Apple-Challenge request\n"); ++ xprintf("Added AppleResponse to Apple-Challenge request\n"); + } + + // Find option, then based on option, do different actions. +@@ -778,14 +804,14 @@ + int tKeySize = 0; + char tEncodedAesIV[tSize + 2]; + getTrimmed(tHeaderVal, tSize, TRUE, TRUE, tEncodedAesIV); +- slog(LOG_DEBUG_VV, "AESIV: [%.*s] Size: %d Strlen: %d\n", tSize, tEncodedAesIV, tSize, strlen(tEncodedAesIV)); ++ xprintf("AESIV: [%.*s] Size: %d Strlen: %d\n", tSize, tEncodedAesIV, tSize, strlen(tEncodedAesIV)); + char *tDecodedIV = decode_base64((unsigned char*) tEncodedAesIV, tSize, &tSize); + + // grab the key, copy it out of the receive buffer + tHeaderVal = getFromContent(tContent, "a=rsaaeskey", &tKeySize); + char tEncodedAesKey[tKeySize + 2]; // +1 for nl, +1 for \0 + getTrimmed(tHeaderVal, tKeySize, TRUE, TRUE, tEncodedAesKey); +- slog(LOG_DEBUG_VV, "AES KEY: [%s] Size: %d Strlen: %d\n", tEncodedAesKey, tKeySize, strlen(tEncodedAesKey)); ++ xprintf("AES KEY: [%s] Size: %d Strlen: %d\n", tEncodedAesKey, tKeySize, strlen(tEncodedAesKey)); + // remove base64 coding from key + char *tDecodedAesKey = decode_base64((unsigned char*) tEncodedAesKey, + tKeySize, &tKeySize); // Need to free DecodedAesKey +@@ -794,7 +820,7 @@ + int tFmtpSize = 0; + char *tFmtp = getFromContent(tContent, "a=fmtp", &tFmtpSize); // Don't need to free + tFmtp = getTrimmedMalloc(tFmtp, tFmtpSize, TRUE, FALSE); // will need to free +- slog(LOG_DEBUG_VV, "Format: %s\n", tFmtp); ++ xprintf("Format: %s\n", tFmtp); + + RSA *rsa = loadKey(); + // Decrypt the binary aes key +@@ -803,11 +829,11 @@ + if(RSA_private_decrypt(tKeySize, (unsigned char *)tDecodedAesKey, + (unsigned char*) tDecryptedKey, rsa, RSA_PKCS1_OAEP_PADDING) >= 0) + { +- slog(LOG_DEBUG, "Decrypted AES key from RSA Successfully\n"); ++ xprintf("Decrypted AES key from RSA Successfully\n"); + } + else + { +- slog(LOG_INFO, "Error Decrypting AES key from RSA\n"); ++ xprintf("Error Decrypting AES key from RSA\n"); + } + free(tDecodedAesKey); + RSA_free(rsa); +@@ -823,13 +849,13 @@ + // struct comms *tComms = pConn->hairtunes; + // if (! (pipe(tComms->in) == 0 && pipe(tComms->out) == 0)) + // { +-// slog(LOG_INFO, "Error setting up hairtunes communications...some things probably wont work very well.\n"); ++// xprintf("Error setting up hairtunes communications...some things probably wont work very well.\n"); + // } + + // Setup fork + char tPort[8] = "6000"; // get this from dup()'d stdout of child pid + +- printf("******** SETUP!!!!!\n"); ++ xprintf("******** SETUP!!!!!\n",NULL); + #ifndef XBMC + int tPid = fork(); + if(tPid == 0) +@@ -845,11 +871,11 @@ + tFound = getFromSetup(pConn->recv.data, "timing_port", &tSize); + getTrimmed(tFound, tSize, 1, 0, tTPortStr); + +- slog(LOG_DEBUG_VV, "converting %s and %s from str->int\n", tCPortStr, tTPortStr); ++ xprintf("converting %s and %s from str->int\n", tCPortStr, tTPortStr); + int tControlport = atoi(tCPortStr); + int tTimingport = atoi(tTPortStr); + +- slog(LOG_DEBUG_V, "Got %d for CPort and %d for TPort\n", tControlport, tTimingport); ++ xprintf("Got %d for CPort and %d for TPort\n", tControlport, tTimingport); + char *tRtp = NULL; + char *tPipe = NULL; + char *tAoDriver = NULL; +@@ -884,7 +910,7 @@ + tDataport, tRtp, tPipe, tAoDriver, tAoDeviceName, tAoDeviceId); + #ifndef XBMC + // Quit when finished. +- slog(LOG_DEBUG, "Returned from hairtunes init....returning -1, should close out this whole side of the fork\n"); ++ xprintf("Returned from hairtunes init....returning -1, should close out this whole side of the fork\n"); + return -1; + } + else if(tPid >0) +@@ -897,7 +923,7 @@ + int tRead = read(tComms->out[0], tFromHairtunes, 80); + if(tRead <= 0) + { +- slog(LOG_INFO, "Error reading port from hairtunes function, assuming default port: %d\n", tPort); ++ xprintf("Error reading port from hairtunes function, assuming default port: %d\n", tPort); + } + else + { +@@ -909,7 +935,7 @@ + } + else + { +- slog(LOG_INFO, "Read %d bytes, Error translating %s into a port\n", tRead, tFromHairtunes); ++ xprintf("Read %d bytes, Error translating %s into a port\n", tRead, tFromHairtunes); + } + } + +@@ -930,7 +956,7 @@ + } + else + { +- slog(LOG_INFO, "Error forking process....dere' be errors round here.\n"); ++ xprintf("Error forking process....dere' be errors round here.\n"); + return -1; + } + #endif +@@ -942,7 +968,7 @@ + propogateCSeq(pConn); + #ifndef XBMC + close(pConn->hairtunes->in[1]); +- slog(LOG_DEBUG, "Tearing down connection, closing pipes\n"); ++ xprintf("Tearing down connection, closing pipes\n"); + #else + hairtunes_cleanup(); + #endif +@@ -964,7 +990,7 @@ + propogateCSeq(pConn); + int tSize = 0; + char *tVol = getFromHeader(pConn->recv.data, "volume", &tSize); +- slog(LOG_DEBUG_VV, "About to write [vol: %.*s] data to hairtunes\n", tSize, tVol); ++ xprintf("About to write [vol: %.*s] data to hairtunes\n", tSize, tVol); + // TBD VOLUME + #ifndef XBMC + write(pConn->hairtunes->in[1], "vol: ", 5); +@@ -973,11 +999,11 @@ + #else + hairtunes_setvolume(atof(tVol)); + #endif +- slog(LOG_DEBUG_VV, "Finished writing data write data to hairtunes\n"); ++ xprintf("Finished writing data write data to hairtunes\n"); + } + else + { +- slog(LOG_DEBUG, "\n\nUn-Handled recv: %s\n", pConn->recv.data); ++ xprintf("\n\nUn-Handled recv: %s\n", pConn->recv.data); + propogateCSeq(pConn); + } + addToShairBuffer(&(pConn->resp), "\r\n"); +@@ -1056,7 +1082,7 @@ + char tName[100 + HWID_SIZE + 3]; + if(strlen(pServerName) > tMaxServerName) + { +- slog(LOG_INFO,"Hey dog, we see you like long server names, " ++ xprintf("Hey dog, we see you like long server names, " + "so we put a strncat in our command so we don't buffer overflow, while you listen to your flow.\n" + "We just used the first %d characters. Pick something shorter if you want\n", tMaxServerName); + } +@@ -1067,7 +1093,7 @@ + strcat(tName, pHWStr); + strcat(tName, "@"); + strncat(tName, pServerName, tMaxServerName); +- slog(AVAHI_LOG_LEVEL, "Avahi/DNS-SD Name: %s\n", tName); ++ xprintf("Avahi/DNS-SD Name: %s\n", tName); + + execlp("avahi-publish-service", "avahi-publish-service", tName, + "_raop._tcp", tPort, "tp=UDP","sm=false","sv=false","ek=1","et=0,1", +@@ -1079,12 +1105,12 @@ + perror("error"); + } + +- slog(LOG_INFO, "Bad error... couldn't find or failed to run: avahi-publish-service OR dns-sd\n"); +- exit(1); ++ xprintf("Bad error... couldn't find or failed to run: avahi-publish-service OR dns-sd\n"); ++ //exit(1); + } + else + { +- slog(LOG_DEBUG_VV, "Avahi/DNS-SD started on PID: %d\n", tPid); ++ xprintf("Avahi/DNS-SD started on PID: %d\n", tPid); + } + return tPid; + } +@@ -1092,7 +1118,7 @@ + + void printBufferInfo(struct shairbuffer *pBuf, int pLevel) + { +- slog(pLevel, "Buffer: [%s] size: %d maxchars:%d\n", pBuf->data, pBuf->current, pBuf->maxsize/sizeof(char)); ++ xprintf("Buffer: [%s] size: %d maxchars:%d\n", pBuf->data, pBuf->current, pBuf->maxsize/sizeof(char)); + } + + int getAvailChars(struct shairbuffer *pBuf) +@@ -1173,7 +1199,8 @@ + { + va_list argp; + va_start(argp, pFormat); +- vprintf(pFormat, argp); ++ xprintf(pFormat, argp); ++ //vprintf(pFormat, argp); + va_end(argp); + } + //#endif +@@ -1227,9 +1254,9 @@ + { + if(pBuf->data != NULL) + { +- slog(LOG_DEBUG_VV, "Hrm, buffer wasn't cleaned up....trying to free\n"); ++ xprintf("Hrm, buffer wasn't cleaned up....trying to free\n"); + free(pBuf->data); +- slog(LOG_DEBUG_VV, "Free didn't seem to seg fault....huzzah\n"); ++ xprintf("Free didn't seem to seg fault....huzzah\n"); + } + pBuf->current = 0; + pBuf->marker = 0; +@@ -1287,6 +1314,6 @@ + BIO *tBio = BIO_new_mem_buf(AIRPORT_PRIVATE_KEY, -1); + RSA *rsa = PEM_read_bio_RSAPrivateKey(tBio, NULL, NULL, NULL); //NULL, NULL, NULL); + BIO_free(tBio); +- slog(RSA_LOG_LEVEL, "RSA Key: %d\n", RSA_check_key(rsa)); ++ xprintf("RSA Key: %d\n", RSA_check_key(rsa)); + return rsa; + } +--- src/shairport.h 2011-10-01 17:45:08.000000000 +0200 ++++ src/shairport.h 2011-10-01 17:19:43.000000000 +0200 +@@ -59,11 +59,17 @@ + { + #endif /* __cplusplus */ + ++struct printfPtr ++{ ++ int (*extprintf)(const char* msg, size_t msgSize); ++}; ++ + int shairport_main(int argc, char **argv); + void shairport_exit(void); + int shairport_loop(void); + int shairport_is_running(void); + void shairport_set_ao(struct AudioOutput *ao); ++void shairport_set_printf(struct printfPtr *funcPtr); + + #ifdef __cplusplus + } +--- src/socketlib.c 2011-09-23 22:00:48.000000000 +0200 ++++ src/socketlib.c 2011-10-01 17:42:39.000000000 +0200 +@@ -82,7 +82,7 @@ + delay(RETRY_DELAY, &tRes); + } + } +- printf("%d Retry attempts exceeded\n", RETRY_COUNT); ++ xprintf("%d Retry attempts exceeded\n", RETRY_COUNT); + return ERROR; + } + +@@ -102,7 +102,7 @@ + tError = getaddrinfo(pHostname, pService, &hints, pAddrInfo); + if(tError != 0) + { +- printf("Error getting address info\n"); ++ xprintf("Error getting address info\n"); + } + return tError; + } +@@ -200,7 +200,7 @@ + else + { + // Invalid encoded data, no other cases are possible. +- printf("Unrecoverable error....base64 values are incorrectly encoded\n"); ++ xprintf("Unrecoverable error....base64 values are incorrectly encoded\n"); + return pSize; + } + } +@@ -226,7 +226,7 @@ + memset(input, 0, length); + memcpy(input, pInput, pLength); + memset(input+pLength, '=', length-pLength); +- printf("Fixed value: [%.*s]\n", length, input); ++ xprintf("Fixed value: [%.*s]\n", length, input); + } + char *buffer = (char *)malloc(length); + memset(buffer, 0, length); diff --git a/tools/android/depends/libshairport/007_fix_syslog_defines.patch b/tools/android/depends/libshairport/007_fix_syslog_defines.patch new file mode 100644 index 0000000000..4d9b834f9c --- /dev/null +++ b/tools/android/depends/libshairport/007_fix_syslog_defines.patch @@ -0,0 +1,24 @@ +--- src/shairport.h 2011-10-01 04:09:16.000000000 +0200 ++++ src/shairport.h 2011-11-07 18:05:05.000000000 +0100 +@@ -16,10 +16,17 @@ + + #define HWID_SIZE 6 + #define SHAIRPORT_LOG 1 +-#define LOG_INFO 1 +-#define LOG_DEBUG 5 +-#define LOG_DEBUG_V 6 +-#define LOG_DEBUG_VV 7 ++ ++#ifndef LOG_INFO ++#define LOG_INFO 5 ++#endif ++ ++#ifndef LOG_DEBUG ++#define LOG_DEBUG 6 ++#endif ++ ++#define LOG_DEBUG_V 7 ++#define LOG_DEBUG_VV 8 + + struct shairbuffer + { diff --git a/tools/android/depends/libshairport/008-add-missing-libs.patch b/tools/android/depends/libshairport/008-add-missing-libs.patch new file mode 100644 index 0000000000..6efd30222a --- /dev/null +++ b/tools/android/depends/libshairport/008-add-missing-libs.patch @@ -0,0 +1,21 @@ +--- configure.in-org 2011-11-08 11:53:42.802419355 -0500 ++++ configure.in 2011-11-08 11:55:38.082419413 -0500 +@@ -11,8 +11,9 @@ AC_PROG_LIBTOOL + + # Checks for libraries. + #AC_CHECK_LIB([c], [main]) +-#AC_CHECK_LIB([m], [main]) ++AC_CHECK_LIB([m], [main]) + AC_CHECK_LIB([ssl], [main],, AC_MSG_ERROR($missing_library)) ++AC_CHECK_LIB([crypto], [main],, AC_MSG_ERROR($missing_library)) + AC_CHECK_LIB([pthread], [main],, AC_MSG_ERROR($missing_library)) + + OUTPUT_FILES="Makefile" +@@ -21,4 +22,4 @@ LIBDIR=$PREFIX + + AC_CONFIG_FILES([${OUTPUT_FILES}]) + AC_OUTPUT(Makefile src/Makefile) +-AC_OUTPUT +\ No newline at end of file ++AC_OUTPUT + diff --git a/tools/android/depends/libshairport/009_fix_ipv6.patch b/tools/android/depends/libshairport/009_fix_ipv6.patch new file mode 100644 index 0000000000..01ff026d07 --- /dev/null +++ b/tools/android/depends/libshairport/009_fix_ipv6.patch @@ -0,0 +1,22 @@ +--- src/socketlib.c 2012-01-04 20:41:05.000000000 +0100 ++++ src/socketlib.c 2012-01-04 20:35:53.000000000 +0100 +@@ -48,7 +48,7 @@ + if((tSock==-1) && (pAddrInfo->ai_family == AF_INET6) && (errno == EAFNOSUPPORT)) + { + //Fallback to ipv4 +- perror("Failed to create ipv6 socket. Trying ipv4"); ++ xprintf("Failed to create ipv6 socket. Trying ipv4"); + pAddrInfo->ai_family = AF_INET; + tSock = socket(pAddrInfo->ai_family, pAddrInfo->ai_socktype, 0); + } +@@ -158,8 +158,8 @@ + sprintf(tService, "%d", pPort); // copies port to string + int tFamily = AF_INET; + #ifdef AF_INET6 +- //printf("Listening on IPv6 Socket\n"); +- //tFamily = AF_INET6; ++ xprintf("Listening on IPv6 Socket\n"); ++ tFamily = AF_INET6; + #else + //printf("Listening on IPv4 Socket"); + #endif diff --git a/tools/android/depends/libshairport/010_handle_metadata.patch b/tools/android/depends/libshairport/010_handle_metadata.patch new file mode 100644 index 0000000000..a48782ed08 --- /dev/null +++ b/tools/android/depends/libshairport/010_handle_metadata.patch @@ -0,0 +1,154 @@ +diff -ruP src/ao.h libshairport.new/src/ao.h +--- src/ao.h 2012-05-07 22:26:53.000000000 +0200 ++++ src/ao.h 2012-05-08 18:46:42.000000000 +0200 +@@ -152,5 +152,7 @@ + /* -- Device Setup/Playback/Teardown -- */ + int (*ao_append_option)(ao_option **, const char *, const char *); + void (*ao_free_options)(ao_option *); +- char* (*ao_get_option)(ao_option *, const char* ); ++ char* (*ao_get_option)(ao_option *, const char* ); ++ void (*ao_set_metadata)(const char *buffer, unsigned int size); ++ void (*ao_set_metadata_coverart)(const char *buffer, unsigned int size); + }; +diff -ruP src/hairtunes.c src/hairtunes.c +--- src/hairtunes.c 2012-05-07 22:26:53.000000000 +0200 ++++ src/hairtunes.c 2012-05-08 18:45:51.000000000 +0200 +@@ -267,6 +267,16 @@ + fix_volume = 65536.0 * volume; + } + ++void hairtunes_set_metadata(const char *buffer, unsigned int size) ++{ ++ g_ao.ao_set_metadata(buffer, size); ++} ++ ++void hairtunes_set_metadata_coverart(const char *buffer, unsigned int size) ++{ ++ g_ao.ao_set_metadata_coverart(buffer, size); ++} ++ + void hairtunes_flush(void) + { + pthread_mutex_lock(&ab_mutex); +diff -ruP src/hairtunes.h src/hairtunes.h +--- src/hairtunes.h 2011-08-21 00:06:21.000000000 +0200 ++++ src/hairtunes.h 2012-05-08 18:46:00.000000000 +0200 +@@ -4,6 +4,8 @@ + int hairtunes_init(char *pAeskey, char *pAesiv, char *pFmtpstr, int pCtrlPort, int pTimingPort, + int pDataPort, char *pRtpHost, char*pPipeName, char *pLibaoDriver, char *pLibaoDeviceName, char *pLibaoDeviceId); + void hairtunes_setvolume(float vol); ++void hairtunes_set_metadata(const char *buffer, unsigned int size); ++void hairtunes_set_metadata_coverart(const char *buffer, unsigned int size); + void hairtunes_flush(void); + void hairtunes_cleanup(void); + +diff -ruP src/shairport.c src/shairport.c +--- src/shairport.c 2012-05-07 22:26:53.000000000 +0200 ++++ src/shairport.c 2012-05-08 18:45:30.000000000 +0200 +@@ -513,7 +513,8 @@ + while(1 == tMoreDataNeeded) + { + tError = readDataFromClient(pSock, &(tConn.recv)); +- if(!tError && strlen(tConn.recv.data) > 0) ++ //if(!tError && strlen(tConn.recv.data) > 0) ++ if(!tError && tConn.recv.current > 0) + { + xprintf("Finished Reading some data from client\n"); + // parse client request +@@ -632,7 +633,7 @@ + } + + tSize = (int) (tShortest - tFound); +- xprintf("Found %.*s length: %d\n", tSize, tFound, tSize); ++ xprintf("Found %s length: %d\n",tFound, tSize); + if(pReturnSize != NULL) + { + *pReturnSize = tSize; +@@ -744,7 +745,7 @@ + if(tContent != NULL) + { + int tContentSize = atoi(tContent); +- if(pConn->recv.marker == 0 || strlen(pConn->recv.data+pConn->recv.marker) != tContentSize) ++ if(pConn->recv.marker == 0 || pConn->recv.current-pConn->recv.marker != tContentSize) + { + if(isLogEnabledFor(HEADER_LOG_LEVEL)) + { +@@ -752,7 +753,7 @@ + if(pConn->recv.marker != 0) + { + xprintf("ContentPtr has %d, but needs %d\n", +- strlen(pConn->recv.data+pConn->recv.marker), tContentSize); ++ (pConn->recv.current-pConn->recv.marker), tContentSize); + } + } + // check if value in tContent > 2nd read from client. +@@ -989,15 +990,67 @@ + { + propogateCSeq(pConn); + int tSize = 0; ++ char *buffer = NULL; ++ char *contentType = getFromHeader(pConn->recv.data, "Content-Type", &tSize); ++ char *tContent = getFromHeader(pConn->recv.data, "Content-Length", NULL); ++ int iContentSize = 0; ++ int isJpg = 0; ++ ++ if(tContent != NULL) ++ { ++ iContentSize = atoi(tContent); ++ } ++ ++ if( tSize > 1 && ++ (strncmp(contentType, "application/x-dmap-tagged", tSize) == 0) || ++ (strncmp(contentType, "image/jpeg", tSize) == 0) ) ++ { ++ if( (pConn->recv.current - pConn->recv.marker) == iContentSize && pConn->recv.marker != 0) ++ { ++ if(strncmp(contentType, "image/jpeg", tSize) == 0) ++ { ++ isJpg = 1; ++ } ++ buffer = (char *)malloc(iContentSize * sizeof(char)); ++ memcpy(buffer, pConn->recv.data + pConn->recv.marker, iContentSize); ++ } ++ else ++ { ++ iContentSize = 0; ++ } ++ } ++ else ++ { ++ iContentSize = 0; ++ } + char *tVol = getFromHeader(pConn->recv.data, "volume", &tSize); +- xprintf("About to write [vol: %.*s] data to hairtunes\n", tSize, tVol); ++ if( tVol) ++ { ++ xprintf("About to write [vol: %.*s] data to hairtunes\n", tSize, tVol); ++ } + // TBD VOLUME + #ifndef XBMC + write(pConn->hairtunes->in[1], "vol: ", 5); + write(pConn->hairtunes->in[1], tVol, tSize); + write(pConn->hairtunes->in[1], "\n", 1); + #else +- hairtunes_setvolume(atof(tVol)); ++ if(tVol) ++ { ++ hairtunes_setvolume(atof(tVol)); ++ } ++ ++ if(iContentSize) ++ { ++ if(isJpg) ++ { ++ hairtunes_set_metadata_coverart(buffer, iContentSize); ++ } ++ else ++ { ++ hairtunes_set_metadata(buffer, iContentSize); ++ } ++ free(buffer); ++ } + #endif + xprintf("Finished writing data write data to hairtunes\n"); + } diff --git a/tools/android/depends/libshairport/Makefile b/tools/android/depends/libshairport/Makefile new file mode 100644 index 0000000000..f730d6fbf7 --- /dev/null +++ b/tools/android/depends/libshairport/Makefile @@ -0,0 +1,57 @@ +include ../Makefile.include +DEPS= ../Makefile.include 001_add_ao.patch 002_fix_install_header.patch 003_fix_deadlock.patch \ + 004_fix_bad_access.patch 005_fix_shutdown.patch 006_no_printf.patch \ + 007_fix_syslog_defines.patch 008-add-missing-libs.patch \ + 009_fix_ipv6.patch 010_handle_metadata.patch android.patch Makefile + +# lib name, version +LIBNAME=libshairport +VERSION=1.2.0.20310_lib +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) --host=$(HOST) + + +LIBDYLIB=$(PLATFORM)/src/.libs/libshairport.so.0.0.0 + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p0 < ../001_add_ao.patch + cd $(PLATFORM); patch -p0 < ../002_fix_install_header.patch + cd $(PLATFORM); patch -p0 < ../003_fix_deadlock.patch + cd $(PLATFORM); patch -p0 < ../004_fix_bad_access.patch + cd $(PLATFORM); patch -p0 < ../005_fix_shutdown.patch + cd $(PLATFORM); patch -p0 < ../006_no_printf.patch + cd $(PLATFORM); patch -p0 < ../007_fix_syslog_defines.patch + cd $(PLATFORM); patch -p0 < ../008-add-missing-libs.patch + cd $(PLATFORM); patch -p0 < ../009_fix_ipv6.patch + cd $(PLATFORM); patch -p0 < ../010_handle_metadata.patch + cd $(PLATFORM); patch -p0 < ../android.patch + cd $(PLATFORM); $(AUTORECONF) -vif + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -j 1 -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libshairport.la $(PREFIX)/lib/libshairport.so $(PREFIX)/lib/libshairport.so.0 + mv -f $(PREFIX)/lib/libshairport.so.0.0.0 $(PREFIX)/lib/libshairport.so + $(RPL) -e "libshairport.so.0" "libshairport.so\x00\x00" $(PREFIX)/lib/libshairport.so + -$(READELF) --dynamic $(PREFIX)/lib/libshairport.so | grep ibrary + touch $@ + +clean: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libshairport/android.patch b/tools/android/depends/libshairport/android.patch new file mode 100644 index 0000000000..673cfeb7da --- /dev/null +++ b/tools/android/depends/libshairport/android.patch @@ -0,0 +1,21 @@ +--- configure.in 2012-06-03 23:09:30.024347827 -0400 ++++ configure.in 2012-06-03 23:11:37.494347747 -0400 +@@ -14,7 +14,7 @@ + AC_CHECK_LIB([m], [main]) + AC_CHECK_LIB([ssl], [main],, AC_MSG_ERROR($missing_library)) + AC_CHECK_LIB([crypto], [main],, AC_MSG_ERROR($missing_library)) +-AC_CHECK_LIB([pthread], [main],, AC_MSG_ERROR($missing_library)) ++#AC_CHECK_LIB([pthread], [main],, AC_MSG_ERROR($missing_library)) + + OUTPUT_FILES="Makefile" + +--- src/hairtunes.c 2012-06-03 23:15:47.944347589 -0400 ++++ src/hairtunes.c 2012-06-03 23:16:23.044347567 -0400 +@@ -42,7 +42,6 @@ + #include <sys/stat.h> + + #include "hairtunes.h" +-#include <sys/signal.h> + #include <fcntl.h> + #ifdef HAS_AO + #include "ao.h" diff --git a/tools/android/depends/libssh/Makefile b/tools/android/depends/libssh/Makefile new file mode 100644 index 0000000000..8848ef3af2 --- /dev/null +++ b/tools/android/depends/libssh/Makefile @@ -0,0 +1,46 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile removelegacy.patch android.patch + +# lib name, version +LIBNAME=libssh +VERSION=0.5.0 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +LIBDYLIB=$(PLATFORM)/build/src/$(LIBNAME).so.4.2.0 + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); rm -rf build; mkdir -p build + cd $(PLATFORM); patch -p0 < ../removelegacy.patch + cd $(PLATFORM); patch -p0 < ../android.patch + cd $(PLATFORM); patch -p0 < ../md5.patch + sed -ie "s|-fstack-protector|-fnostack-protector|" "$(PLATFORM)/cmake/Modules/DefineCompilerFlags.cmake" + sed -ie "s|add_subdirectory(examples)||" "$(PLATFORM)/CMakeLists.txt" + cd $(PLATFORM)/build; CC=$(CC) CXX=$(CXX) cmake \ + -DCMAKE_C_FLAGS:STRING="$(CPPFLAGS) $(CFLAGS)" \ + -DCMAKE_CXX_FLAGS:STRING="$(CPPFLAGS) $(CXXFLAGS)" \ + -DCMAKE_INSTALL_NAME_DIR=$(PREFIX)/lib \ + -DCMAKE_INSTALL_PREFIX=$(PREFIX) \ + -DCMAKE_SYSTEM_NAME=Linux \ + -DWITH_STATIC_LIB=1 \ + -DCMAKE_FIND_ROOT_PATH="$(TOOLCHAIN)/sysroot/usr;$(PREFIX)" .. +$(LIBDYLIB): $(PLATFORM) + make -j 1 -C $(PLATFORM)/build + +.installed-$(PLATFORM): $(LIBDYLIB) + make -C $(PLATFORM)/build install + rm -f $(PREFIX)/lib/libssh.so $(PREFIX)/lib/libssh.so.4.2.0 $(PREFIX)/lib/libssh.so.4 + touch $@ + +clean: + rm -rf $(PLATFORM) .installed + +distclean:: + rm -rf $(PLATFORM) .installed diff --git a/tools/android/depends/libssh/android.patch b/tools/android/depends/libssh/android.patch new file mode 100644 index 0000000000..c76e648f7f --- /dev/null +++ b/tools/android/depends/libssh/android.patch @@ -0,0 +1,49 @@ +--- src/connect.c 2011-05-31 10:29:52.000000000 -0400 ++++ src/connect.c 2012-07-25 23:15:22.281514489 -0400 +@@ -159,7 +159,7 @@ + int timeout_ms; + ssh_pollfd_t fds; + int rc = 0; +- unsigned int len = sizeof(rc); ++ socklen_t len = sizeof(rc); + + enter_function(); + +--- src/misc.c 2011-05-31 10:29:52.000000000 -0400 ++++ src/misc.c 2012-07-25 23:24:46.611514133 -0400 +@@ -207,6 +207,9 @@ + #endif /* NSS_BUFLEN_PASSWD */ + + char *ssh_get_user_home_dir(void) { ++#if defined(__ANDROID__) ++ return NULL; ++#else + char *szPath = NULL; + struct passwd pwd; + struct passwd *pwdbuf; +@@ -221,6 +224,7 @@ + szPath = strdup(pwd.pw_dir); + + return szPath; ++#endif + } + + /* we have read access on file */ +@@ -233,6 +237,9 @@ + } + + char *ssh_get_local_username(ssh_session session) { ++#if defined(__ANDROID__) ++ return NULL; ++#else + struct passwd pwd; + struct passwd *pwdbuf; + char buf[NSS_BUFLEN_PASSWD]; +@@ -254,6 +261,7 @@ + } + + return name; ++#endif + } + + int ssh_is_ipaddr_v4(const char *str) { diff --git a/tools/android/depends/libssh/md5.patch b/tools/android/depends/libssh/md5.patch new file mode 100644 index 0000000000..b5985f0be8 --- /dev/null +++ b/tools/android/depends/libssh/md5.patch @@ -0,0 +1,72 @@ +diff -ruN include/libssh/wrapper.h include/libssh/wrapper.h +--- include/libssh/wrapper.h 2011-05-31 10:29:52.000000000 -0400 ++++ include/libssh/wrapper.h 2012-07-26 00:21:16.021511996 -0400 +@@ -26,7 +26,7 @@ + #include "libssh/libcrypto.h" + #include "libssh/libgcrypt.h" + +-MD5CTX md5_init(void); ++MD5CTX ssh_md5_init(void); + void md5_update(MD5CTX c, const void *data, unsigned long len); + void md5_final(unsigned char *md,MD5CTX c); + SHACTX sha1_init(void); +diff -ruN src/dh.c src/dh.c +--- src/dh.c 2011-05-31 10:29:52.000000000 -0400 ++++ src/dh.c 2012-07-26 00:19:52.961512049 -0400 +@@ -854,7 +854,7 @@ + return SSH_ERROR; + } + +- ctx = md5_init(); ++ ctx = ssh_md5_init(); + if (ctx == NULL) { + SAFE_FREE(h); + return SSH_ERROR; +diff -ruN src/kex.c src/kex.c +--- src/kex.c 2011-05-31 10:29:52.000000000 -0400 ++++ src/kex.c 2012-07-26 00:20:37.671512021 -0400 +@@ -509,7 +509,7 @@ + ssh_string hostn) { + MD5CTX md5 = NULL; + +- md5 = md5_init(); ++ md5 = ssh_md5_init(); + if (md5 == NULL) { + return -1; + } +diff -ruN src/keyfiles.c src/keyfiles.c +--- src/keyfiles.c 2011-05-31 10:29:52.000000000 -0400 ++++ src/keyfiles.c 2012-07-26 00:20:51.801512011 -0400 +@@ -223,7 +223,7 @@ + unsigned int md_not_empty; + + for (j = 0, md_not_empty = 0; j < keylen; ) { +- md = md5_init(); ++ md = ssh_md5_init(); + if (md == NULL) { + return -1; + } +diff -ruN src/libcrypto.c src/libcrypto.c +--- src/libcrypto.c 2011-05-31 10:29:52.000000000 -0400 ++++ src/libcrypto.c 2012-07-26 00:20:07.061512022 -0400 +@@ -89,7 +89,7 @@ + SHA1(digest, len, hash); + } + +-MD5CTX md5_init(void) { ++MD5CTX ssh_md5_init(void) { + MD5CTX c = malloc(sizeof(*c)); + if (c == NULL) { + return NULL; +diff -ruN src/libgcrypt.c src/libgcrypt.c +--- src/libgcrypt.c 2011-05-31 10:29:52.000000000 -0400 ++++ src/libgcrypt.c 2012-07-26 00:20:19.401512036 -0400 +@@ -62,7 +62,7 @@ + gcry_md_hash_buffer(GCRY_MD_SHA1, hash, digest, len); + } + +-MD5CTX md5_init(void) { ++MD5CTX ssh_md5_init(void) { + MD5CTX c = NULL; + gcry_md_open(&c, GCRY_MD_MD5, 0); + diff --git a/tools/android/depends/libssh/removelegacy.patch b/tools/android/depends/libssh/removelegacy.patch new file mode 100644 index 0000000000..69683cb869 --- /dev/null +++ b/tools/android/depends/libssh/removelegacy.patch @@ -0,0 +1,10 @@ +--- src/CMakeLists.txt 2011-06-16 19:04:44.000000000 +0200 ++++ src/CMakeLists.txt 2011-06-16 19:03:40.000000000 +0200 +@@ -94,7 +94,6 @@ + keyfiles.c + keys.c + known_hosts.c +- legacy.c + libcrypto.c + libgcrypt.c + log.c diff --git a/tools/android/depends/libssh2/Makefile b/tools/android/depends/libssh2/Makefile new file mode 100644 index 0000000000..352f129e5a --- /dev/null +++ b/tools/android/depends/libssh2/Makefile @@ -0,0 +1,48 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libssh2 +VERSION=1.2.7 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --with-openssl + +SHELL := /bin/bash +RM := rm -rf + +LIBDYLIB=$(PLATFORM)/src/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libssh2.la $(PREFIX)/lib/libssh2.so $(PREFIX)/lib/libssh2.so.1 + mv -f $(PREFIX)/lib/libssh2.so.1.0.1 $(PREFIX)/lib/libssh2.so + $(RPL) -e "libssh2.so.1" "libssh2.so\x00\x00" $(PREFIX)/lib/libssh2.so + -$(READELF) --dynamic $(PREFIX)/lib/libssh2.so | grep ibrary + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libtool/Makefile b/tools/android/depends/libtool/Makefile new file mode 100644 index 0000000000..ccaa0047f4 --- /dev/null +++ b/tools/android/depends/libtool/Makefile @@ -0,0 +1,42 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libtool +VERSION=2.2.6 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE)a.tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) \ + --disable-shared + +LIBDYLIB=$(PLATFORM)/libtool + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -rf $(PREFIX)/lib/libltdl.a $(PREFIX)/lib/libltdl.la + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/libvorbis/Makefile b/tools/android/depends/libvorbis/Makefile new file mode 100644 index 0000000000..6e5e190f94 --- /dev/null +++ b/tools/android/depends/libvorbis/Makefile @@ -0,0 +1,63 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libvorbis +VERSION=1.2.3 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +export LIBS=-lm +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-oggtest --disable-docs --disable-examples + +LIBDYLIB=$(PLATFORM)/lib/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + sed -ie "s|SUBDIRS = m4 include vq lib examples test doc|SUBDIRS = m4 include lib|" "$(PLATFORM)/Makefile.in" + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libvorbis.la $(PREFIX)/lib/libvorbis.so $(PREFIX)/lib/libvorbis.so.0 + mv -f $(PREFIX)/lib/libvorbis.so.0.4.3 $(PREFIX)/lib/libxbvorbis.so + ln -sf $(PREFIX)/lib/libxbvorbis.so $(PREFIX)/lib/libvorbis.so + $(RPL) -e "libvorbis.so.0" "libxbvorbis.so" $(PREFIX)/lib/libxbvorbis.so + -$(READELF) --dynamic $(PREFIX)/lib/libxbvorbis.so | grep ibrary + # + rm -f $(PREFIX)/lib/libvorbisfile.la $(PREFIX)/lib/libvorbisfile.so $(PREFIX)/lib/libvorbisfile.so.3 + mv -f $(PREFIX)/lib/libvorbisfile.so.3.3.2 $(PREFIX)/lib/libxbvorbisfile.so + ln -sf $(PREFIX)/lib/libxbvorbisfile.so $(PREFIX)/lib/libvorbisfile.so + $(RPL) -e "libvorbisfile.so.3" "libxbvorbisfile.so" $(PREFIX)/lib/libxbvorbisfile.so + $(RPL) -e "libvorbis.so.0" "libxbvorbis.so" $(PREFIX)/lib/libxbvorbisfile.so + -$(READELF) --dynamic $(PREFIX)/lib/libxbvorbisfile.so | grep ibrary + # + rm -f $(PREFIX)/lib/libvorbisenc.la $(PREFIX)/lib/libvorbisenc.so $(PREFIX)/lib/libvorbisenc.so.2 + mv -f $(PREFIX)/lib/libvorbisenc.so.2.0.6 $(PREFIX)/lib/libxbvorbisenc.so + ln -sf $(PREFIX)/lib/libxbvorbisenc.so $(PREFIX)/lib/libvorbisenc.so + $(RPL) -e "libvorbisenc.so.2" "libxbvorbisenc.so" $(PREFIX)/lib/libxbvorbisenc.so + $(RPL) -e "libvorbis.so.0" "libxbvorbis.so" $(PREFIX)/lib/libxbvorbisenc.so + -$(READELF) --dynamic $(PREFIX)/lib/libxbvorbisenc.so | grep ibrary + # + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libxml2/Makefile b/tools/android/depends/libxml2/Makefile new file mode 100644 index 0000000000..61215314d7 --- /dev/null +++ b/tools/android/depends/libxml2/Makefile @@ -0,0 +1,43 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libxml2 +VERSION=2.7.6 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --without-python --disable-shared + +LIBDYLIB=$(PLATFORM)/.libs/$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + sed -ie "s|runtest$$(EXEEXT)||" "$(PLATFORM)/Makefile.in" + sed -ie "s|testrecurse$$(EXEEXT)||" "$(PLATFORM)/Makefile.in" + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/libzip/Makefile b/tools/android/depends/libzip/Makefile new file mode 100644 index 0000000000..d578770798 --- /dev/null +++ b/tools/android/depends/libzip/Makefile @@ -0,0 +1,39 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=libzip +VERSION=0.10 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared + +LIBDYLIB=$(PLATFORM)/lib/.libs/$(LIBNAME).a + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + rm -f $(PREFIX)/lib/libzip.la $(PREFIX)/lib/libzip*.so* + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/mysql/01-mysqlclient-cross-compile.patch b/tools/android/depends/mysql/01-mysqlclient-cross-compile.patch new file mode 100644 index 0000000000..12b22b7e0d --- /dev/null +++ b/tools/android/depends/mysql/01-mysqlclient-cross-compile.patch @@ -0,0 +1,170 @@ +diff -ruN mysql-5.1.55.org/configure.in mysql-5.1.55/configure.in +--- mysql-5.1.55.org/configure.in 2011-01-25 16:04:35.000000000 +0100 ++++ mysql-5.1.55/configure.in 2011-05-19 20:14:38.000000000 +0200 +@@ -1571,13 +1571,6 @@ + esac + + +-# System characteristics +-case $SYSTEM_TYPE in +- *netware*) ;; +- *) +-AC_SYS_RESTARTABLE_SYSCALLS +- ;; +-esac + + # Build optimized or debug version ? + # First check for gcc and g++ +diff -ruN mysql-5.1.55.org/storage/innodb_plugin/plug.in mysql-5.1.55/storage/innodb_plugin/plug.in +--- mysql-5.1.55.org/storage/innodb_plugin/plug.in 2011-01-25 16:04:35.000000000 +0100 ++++ mysql-5.1.55/storage/innodb_plugin/plug.in 2011-05-19 21:59:28.000000000 +0200 +@@ -56,149 +56,6 @@ + esac + AC_SUBST(INNODB_DYNAMIC_CFLAGS) + +- AC_MSG_CHECKING(whether GCC atomic builtins are available) +- # either define HAVE_IB_GCC_ATOMIC_BUILTINS or not +- AC_TRY_RUN( +- [ +- int main() +- { +- long x; +- long y; +- long res; +- char c; +- +- x = 10; +- y = 123; +- res = __sync_bool_compare_and_swap(&x, x, y); +- if (!res || x != y) { +- return(1); +- } +- +- x = 10; +- y = 123; +- res = __sync_bool_compare_and_swap(&x, x + 1, y); +- if (res || x != 10) { +- return(1); +- } +- +- x = 10; +- y = 123; +- res = __sync_add_and_fetch(&x, y); +- if (res != 123 + 10 || x != 123 + 10) { +- return(1); +- } +- +- c = 10; +- res = __sync_lock_test_and_set(&c, 123); +- if (res != 10 || c != 123) { +- return(1); +- } +- +- return(0); +- } +- ], +- [ +- AC_DEFINE([HAVE_IB_GCC_ATOMIC_BUILTINS], [1], +- [GCC atomic builtins are available]) +- AC_MSG_RESULT(yes) +- ], +- [ +- AC_MSG_RESULT(no) +- ] +- ) +- +- AC_MSG_CHECKING(whether pthread_t can be used by GCC atomic builtins) +- # either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not +- AC_TRY_RUN( +- [ +- #include <pthread.h> +- #include <string.h> +- +- int main(int argc, char** argv) { +- pthread_t x1; +- pthread_t x2; +- pthread_t x3; +- +- memset(&x1, 0x0, sizeof(x1)); +- memset(&x2, 0x0, sizeof(x2)); +- memset(&x3, 0x0, sizeof(x3)); +- +- __sync_bool_compare_and_swap(&x1, x2, x3); +- +- return(0); +- } +- ], +- [ +- AC_DEFINE([HAVE_IB_ATOMIC_PTHREAD_T_GCC], [1], +- [pthread_t can be used by GCC atomic builtins]) +- AC_MSG_RESULT(yes) +- ], +- [ +- AC_MSG_RESULT(no) +- ] +- ) +- +- AC_MSG_CHECKING(whether Solaris libc atomic functions are available) +- # Define HAVE_IB_SOLARIS_ATOMICS if _all_ of the following +- # functions are present. +- AC_CHECK_FUNCS(atomic_add_long_nv \ +- atomic_cas_32 \ +- atomic_cas_64 \ +- atomic_cas_ulong \ +- atomic_swap_uchar) +- +- if test "${ac_cv_func_atomic_add_long_nv}" = "yes" -a \ +- "${ac_cv_func_atomic_cas_32}" = "yes" -a \ +- "${ac_cv_func_atomic_cas_64}" = "yes" -a \ +- "${ac_cv_func_atomic_cas_ulong}" = "yes" -a \ +- "${ac_cv_func_atomic_swap_uchar}" = "yes" ; then +- +- AC_DEFINE([HAVE_IB_SOLARIS_ATOMICS], [1], +- [Define to 1 if Solaris libc atomic functions are available] +- ) +- fi +- +- AC_MSG_CHECKING(whether pthread_t can be used by Solaris libc atomic functions) +- # either define HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS or not +- AC_TRY_RUN( +- [ +- #include <pthread.h> +- #include <string.h> +- +- int main(int argc, char** argv) { +- pthread_t x1; +- pthread_t x2; +- pthread_t x3; +- +- memset(&x1, 0x0, sizeof(x1)); +- memset(&x2, 0x0, sizeof(x2)); +- memset(&x3, 0x0, sizeof(x3)); +- +- if (sizeof(pthread_t) == 4) { +- +- atomic_cas_32(&x1, x2, x3); +- +- } else if (sizeof(pthread_t) == 8) { +- +- atomic_cas_64(&x1, x2, x3); +- +- } else { +- +- return(1); +- } +- +- return(0); +- } +- ], +- [ +- AC_DEFINE([HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS], [1], +- [pthread_t can be used by solaris atomics]) +- AC_MSG_RESULT(yes) +- ], +- [ +- AC_MSG_RESULT(no) +- ] +- ) + + # this is needed to know which one of atomic_cas_32() or atomic_cas_64() + # to use in the source diff --git a/tools/android/depends/mysql/02-mysqlclient-ios.patch b/tools/android/depends/mysql/02-mysqlclient-ios.patch new file mode 100644 index 0000000000..3945b48f55 --- /dev/null +++ b/tools/android/depends/mysql/02-mysqlclient-ios.patch @@ -0,0 +1,27 @@ +diff -ruN mysql-5.1.55.org/include/my_global.h mysql-5.1.55/include/my_global.h +--- mysql-5.1.55.org/include/my_global.h 2011-01-25 16:04:37.000000000 +0100 ++++ mysql-5.1.55/include/my_global.h 2011-05-19 22:12:13.000000000 +0200 +@@ -132,7 +132,7 @@ + # define SIZEOF_INT 4 + # define SIZEOF_LONG_LONG 8 + # define SIZEOF_OFF_T 8 +-# if defined(__i386__) || defined(__ppc__) ++# if defined(__i386__) || defined(__ppc__) || defined(__arm__) + # define SIZEOF_CHARP 4 + # define SIZEOF_LONG 4 + # elif defined(__x86_64__) || defined(__ppc64__) +diff -ruN mysql-5.1.55.org/include/my_net.h mysql-5.1.55/include/my_net.h +--- mysql-5.1.55.org/include/my_net.h 2011-01-25 16:04:48.000000000 +0100 ++++ mysql-5.1.55/include/my_net.h 2011-05-19 22:13:39.000000000 +0200 +@@ -44,9 +44,9 @@ + #endif + + #if !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__) && !defined(__NETWARE__) +-#include <netinet/in_systm.h> ++/* #include <netinet/in_systm.h> */ + #include <netinet/in.h> +-#include <netinet/ip.h> ++/* #include <netinet/ip.h> */ + #if !defined(alpha_linux_port) + #include <netinet/tcp.h> + #endif diff --git a/tools/android/depends/mysql/03-mysqlclient-android.patch b/tools/android/depends/mysql/03-mysqlclient-android.patch new file mode 100644 index 0000000000..2993fdda49 --- /dev/null +++ b/tools/android/depends/mysql/03-mysqlclient-android.patch @@ -0,0 +1,93 @@ +diff -ru mysql-5.1.55.org/client/mysql.cc mysql-5.1.55/client/mysql.cc +--- mysql-5.1.55.org/client/mysql.cc 2011-01-25 16:04:37.000000000 +0100 ++++ mysql-5.1.55/client/mysql.cc 2011-11-15 20:17:00.000000000 +0100 +@@ -97,6 +97,7 @@ + #include <conio.h> + #elif !defined(__NETWARE__) + #include <readline/readline.h> ++#include <readline/history.h> + #define HAVE_READLINE + #endif + //int vidattr(long unsigned int attrs); // Was missing in sun curses +@@ -1045,14 +1046,16 @@ + } HIST_ENTRY; + #endif + ++#if !defined(__ANDROID__) + extern "C" int add_history(const char *command); /* From readline directory */ + extern "C" int read_history(const char *command); + extern "C" int write_history(const char *command); + extern "C" HIST_ENTRY *history_get(int num); + extern "C" int history_length; ++static void fix_history(String *final_command); ++#endif + static int not_in_history(const char *line); + static void initialize_readline (char *name); +-static void fix_history(String *final_command); + #endif + + static COMMANDS *find_command(char *name,char cmd_name); +Only in mysql-5.1.55/client: mysql.cc~ +diff -ru mysql-5.1.55.org/config/ac-macros/readline.m4 mysql-5.1.55/config/ac-macros/readline.m4 +--- mysql-5.1.55.org/config/ac-macros/readline.m4 2011-01-25 16:04:51.000000000 +0100 ++++ mysql-5.1.55/config/ac-macros/readline.m4 2011-11-15 20:17:54.000000000 +0100 +@@ -4,6 +4,7 @@ + [ + #include "stdio.h" + #include "readline/readline.h" ++ #include "readline/history.h" + ], + [ + HIST_ENTRY entry; +Only in mysql-5.1.55/config/ac-macros: readline.m4~ +diff -ru mysql-5.1.55.org/include/my_dir.h mysql-5.1.55/include/my_dir.h +--- mysql-5.1.55.org/include/my_dir.h 2011-01-25 16:04:48.000000000 +0100 ++++ mysql-5.1.55/include/my_dir.h 2011-11-15 20:15:46.000000000 +0100 +@@ -35,9 +35,15 @@ + #define MY_S_ISUID S_ISUID /* set user id on execution */ + #define MY_S_ISGID S_ISGID /* set group id on execution */ + #define MY_S_ISVTX S_ISVTX /* save swapped text even after use */ ++#if defined(__ANDROID__) ++#define MY_S_IREAD S_IRUSR /* read permission, owner */ ++#define MY_S_IWRITE S_IWUSR /* write permission, owner */ ++#define MY_S_IEXEC S_IEXEC /* execute/search permission, owner */ ++#else + #define MY_S_IREAD S_IREAD /* read permission, owner */ + #define MY_S_IWRITE S_IWRITE /* write permission, owner */ + #define MY_S_IEXEC S_IEXEC /* execute/search permission, owner */ ++#endif + + #define MY_S_ISDIR(m) (((m) & MY_S_IFMT) == MY_S_IFDIR) + #define MY_S_ISCHR(m) (((m) & MY_S_IFMT) == MY_S_IFCHR) +Only in mysql-5.1.55/include: my_dir.h~ +diff -ru mysql-5.1.55.org/include/my_global.h mysql-5.1.55/include/my_global.h +--- mysql-5.1.55.org/include/my_global.h 2011-11-15 20:14:37.000000000 +0100 ++++ mysql-5.1.55/include/my_global.h 2011-11-15 20:15:13.000000000 +0100 +@@ -979,6 +979,10 @@ + typedef unsigned char uchar; /* Short for unsigned char */ + #endif + ++#ifndef HAVE_USHORT ++typedef unsigned short ushort; ++#endif ++ + #ifndef HAVE_INT8 + typedef signed char int8; /* Signed integer >= 8 bits */ + #endif +Only in mysql-5.1.55/include: my_global.h~ +diff -ru mysql-5.1.55.org/mysys/my_gethwaddr.c mysql-5.1.55/mysys/my_gethwaddr.c +--- mysql-5.1.55.org/mysys/my_gethwaddr.c 2011-01-25 16:04:35.000000000 +0100 ++++ mysql-5.1.55/mysys/my_gethwaddr.c 2011-11-15 20:19:11.000000000 +0100 +@@ -66,7 +66,11 @@ + + #include <net/if.h> + #include <sys/ioctl.h> ++#ifdef __ANDROID__ ++#include <net/if_ether.h> ++#else + #include <net/ethernet.h> ++#endif + + my_bool my_gethwaddr(uchar *to) + { +Only in mysql-5.1.55/mysys: my_gethwaddr.c~ diff --git a/tools/android/depends/mysql/Makefile b/tools/android/depends/mysql/Makefile new file mode 100644 index 0000000000..34cf040e82 --- /dev/null +++ b/tools/android/depends/mysql/Makefile @@ -0,0 +1,52 @@ +include ../Makefile.include +DEPS= ../Makefile.include 01-mysqlclient-cross-compile.patch 02-mysqlclient-ios.patch 03-mysqlclient-android.patch Makefile + +# lib name, version +LIBNAME=mysql +VERSION=5.1.55 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --build=$(BUILD) \ + --enable-thread-safe-client --with-extra-charsets=complex \ + --with-named-thread-libs=-lc --with-named-curses-libs=-lncurses \ + --without-readline --without-libedit \ + --without-server --without-bench --without-docs --without-man --disable-shared + +LIBDYLIB=$(PLATFORM)/lib$(LIBNAME)/.libs/lib$(LIBNAME)client.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -Np1 -i ../01-mysqlclient-cross-compile.patch + cd $(PLATFORM); patch -Np1 -i ../02-mysqlclient-ios.patch + cd $(PLATFORM); patch -Np1 -i ../03-mysqlclient-android.patch + cd $(PLATFORM); autoconf + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM)/include + $(MAKE) -C $(PLATFORM)/libmysql + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM)/libmysql install + $(MAKE) -C $(PLATFORM)/scripts/ install-binSCRIPTS + $(MAKE) -C $(PLATFORM)/include/ install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/ncurses/Makefile b/tools/android/depends/ncurses/Makefile new file mode 100644 index 0000000000..34ae2a20d1 --- /dev/null +++ b/tools/android/depends/ncurses/Makefile @@ -0,0 +1,41 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=ncurses +VERSION=5.9 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) --host=$(HOST) --build=$(BUILD) --without-cxx-binding --without-progs --without-tests --without-manpages --disable-shared --without-ada + +LIBDYLIB=$(PLATFORM)/lib/lib$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) http://ftp.gnu.org/gnu/ncurses/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) +# cd $(PLATFORM); patch -Np1 -i ../01-ncurses-locale.patch + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/openssl/Makefile b/tools/android/depends/openssl/Makefile new file mode 100644 index 0000000000..d951c38742 --- /dev/null +++ b/tools/android/depends/openssl/Makefile @@ -0,0 +1,45 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=openssl +VERSION=0.9.8r +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=MACHINE=$(HOST) ./config no-shared zlib no-shared --openssldir=$(PREFIX) + +LIBDYLIB=$(PLATFORM)/libssl.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + #when compiled on darwin it just won't realise that we do crosscompiling + #so it would stick in -arch i386 or -arch x86_64 into the cflags + #that would break the cross compile so we have to get rid of these + sed -ie 's/-arch i386//' $(PLATFORM)/Configure + sed -ie 's/-arch x86_64//' $(PLATFORM)/Configure + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -j 1 -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install_sw + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/pcre/Makefile b/tools/android/depends/pcre/Makefile new file mode 100644 index 0000000000..039904d743 --- /dev/null +++ b/tools/android/depends/pcre/Makefile @@ -0,0 +1,39 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=pcre +VERSION=7.9 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-stack-for-recursion --disable-shared + + +LIBDYLIB=$(PLATFORM)/.libs/lib$(LIBNAME).a +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/pkg-config/Makefile b/tools/android/depends/pkg-config/Makefile new file mode 100644 index 0000000000..4eeed4c63e --- /dev/null +++ b/tools/android/depends/pkg-config/Makefile @@ -0,0 +1,41 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +# lib name, version +LIBNAME=pkg-config +VERSION=0.23 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) --enable-indirect-deps --with-pc-path=$(PREFIX)/lib/pkgconfig:$(PREFIX)/share/pkgconfig + +LIBDYLIB=$(PLATFORM)/pkg-config + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/python26-native/Makefile b/tools/android/depends/python26-native/Makefile new file mode 100644 index 0000000000..c1c6579620 --- /dev/null +++ b/tools/android/depends/python26-native/Makefile @@ -0,0 +1,38 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=Python +VERSION=2.6.5 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.bz2 +CWD=$(shell pwd) +HOSTPYTHONDIR=$(CWD)/$(PLATFORM)/hostpython + +CONFIGURE=./configure --prefix=$(PREFIX) --disable-shared --disable-toolbox-glue --disable-framework + +LIBDYLIB=$(PLATFORM)/python + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + cd $(PLATFORM); $(MAKE) + +.installed-$(PLATFORM): $(LIBDYLIB) + cd $(PLATFORM); make install + touch $@ + +clean: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/python26-native/cpython-2.6.5-multiarch.patch b/tools/android/depends/python26-native/cpython-2.6.5-multiarch.patch new file mode 100644 index 0000000000..e1f756ce0d --- /dev/null +++ b/tools/android/depends/python26-native/cpython-2.6.5-multiarch.patch @@ -0,0 +1,36 @@ +diff -rupN setup.py setup.py +--- setup.py 2010-03-08 08:08:25.000000000 +0100 ++++ setup.py 2012-07-13 11:15:27.000000000 +0200 +@@ -308,10 +308,32 @@ class PyBuildExt(build_ext): + return platform + return sys.platform + ++ def add_multiarch_paths(self): ++ # Debian/Ubuntu multiarch support. ++ # https://wiki.ubuntu.com/MultiarchSpec ++ # self.build_temp ++ tmpfile = os.path.join(self.build_temp, 'multiarch') ++ if not os.path.exists(self.build_temp): ++ os.makedirs(self.build_temp) ++ ret = os.system('dpkg-architecture -qDEB_HOST_MULTIARCH > %s' % ++ tmpfile) ++ try: ++ if ret >> 8 == 0: ++ with open(tmpfile) as fp: ++ multiarch_path_component = fp.readline().strip() ++ add_dir_to_list(self.compiler.library_dirs, ++ '/usr/lib/' + multiarch_path_component) ++ add_dir_to_list(self.compiler.include_dirs, ++ '/usr/include/' + multiarch_path_component) ++ finally: ++ os.unlink(tmpfile) ++ ++ + def detect_modules(self): + # Ensure that /usr/local is always used + add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') + add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') ++ self.add_multiarch_paths() + + # Add paths specified in the environment variables LDFLAGS and + # CPPFLAGS for header and library files. diff --git a/tools/android/depends/python26-native/cpython-2.6.5-nosslv2.patch b/tools/android/depends/python26-native/cpython-2.6.5-nosslv2.patch new file mode 100644 index 0000000000..087fc895c7 --- /dev/null +++ b/tools/android/depends/python26-native/cpython-2.6.5-nosslv2.patch @@ -0,0 +1,127 @@ +diff -rupN Doc/library/ssl.rst Doc/library/ssl.rst +--- Doc/library/ssl.rst 2009-10-27 15:50:20.000000000 +0100 ++++ Doc/library/ssl.rst 2012-07-13 11:23:12.000000000 +0200 +@@ -113,7 +113,6 @@ Functions, Constants, and Exceptions + ======================== ========= ========= ========== ========= + *client* / **server** **SSLv2** **SSLv3** **SSLv23** **TLSv1** + ------------------------ --------- --------- ---------- --------- +- *SSLv2* yes no yes* no + *SSLv3* yes yes yes no + *SSLv23* yes no yes no + *TLSv1* no no yes yes +@@ -218,10 +217,6 @@ Functions, Constants, and Exceptions + Note that use of this setting requires a valid certificate validation file + also be passed as a value of the ``ca_certs`` parameter. + +-.. data:: PROTOCOL_SSLv2 +- +- Selects SSL version 2 as the channel encryption protocol. +- + .. data:: PROTOCOL_SSLv23 + + Selects SSL version 2 or 3 as the channel encryption protocol. This is a +diff -rupN Lib/ssl.py Lib/ssl.py +--- Lib/ssl.py 2010-01-18 10:12:06.000000000 +0100 ++++ Lib/ssl.py 2012-07-13 11:27:10.000000000 +0200 +@@ -49,7 +49,6 @@ CERT_REQUIRED - certificates are require + + The following constants identify various SSL protocol variants: + +-PROTOCOL_SSLv2 + PROTOCOL_SSLv3 + PROTOCOL_SSLv23 + PROTOCOL_TLSv1 +@@ -61,7 +60,7 @@ import _ssl # if we can't im + + from _ssl import SSLError + from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED +-from _ssl import PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 ++from _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 + from _ssl import RAND_status, RAND_egd, RAND_add + from _ssl import \ + SSL_ERROR_ZERO_RETURN, \ +@@ -418,8 +417,6 @@ def get_protocol_name(protocol_code): + return "TLSv1" + elif protocol_code == PROTOCOL_SSLv23: + return "SSLv23" +- elif protocol_code == PROTOCOL_SSLv2: +- return "SSLv2" + elif protocol_code == PROTOCOL_SSLv3: + return "SSLv3" + else: +diff -rupN Lib/test/test_ssl.py Lib/test/test_ssl.py +--- Lib/test/test_ssl.py 2008-09-29 20:56:38.000000000 +0200 ++++ Lib/test/test_ssl.py 2012-07-13 11:26:29.000000000 +0200 +@@ -74,7 +74,6 @@ class BasicTests(unittest.TestCase): + s.close() + + def testCrucialConstants(self): +- ssl.PROTOCOL_SSLv2 + ssl.PROTOCOL_SSLv23 + ssl.PROTOCOL_SSLv3 + ssl.PROTOCOL_TLSv1 +@@ -834,27 +833,9 @@ else: + badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir, + "badkey.pem")) + +- def testProtocolSSL2(self): +- if test_support.verbose: +- sys.stdout.write("\n") +- tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True) +- tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL) +- tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED) +- tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True) +- tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False) +- tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False) +- + def testProtocolSSL23(self): + if test_support.verbose: + sys.stdout.write("\n") +- try: +- tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True) +- except test_support.TestFailed, x: +- # this fails on some older versions of OpenSSL (0.9.7l, for instance) +- if test_support.verbose: +- sys.stdout.write( +- " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n" +- % str(x)) + tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True) + tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True) + tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True) +@@ -873,7 +854,6 @@ else: + tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True) + tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) + tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) +- tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) + tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False) + tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) + +@@ -883,7 +863,6 @@ else: + tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True) + tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) + tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) +- tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) + tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False) + tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False) + +diff -rupN Modules/_ssl.c Modules/_ssl.c +--- Modules/_ssl.c 2010-03-03 13:34:43.000000000 +0100 ++++ Modules/_ssl.c 2012-07-13 11:26:52.000000000 +0200 +@@ -300,8 +300,6 @@ newPySSLObject(PySocketSockObject *Sock, + self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ + else if (proto_version == PY_SSL_VERSION_SSL3) + self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ +- else if (proto_version == PY_SSL_VERSION_SSL2) +- self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ + else if (proto_version == PY_SSL_VERSION_SSL23) + self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ + PySSL_END_ALLOW_THREADS +@@ -1627,8 +1625,6 @@ init_ssl(void) + PY_SSL_CERT_REQUIRED); + + /* protocol versions */ +- PyModule_AddIntConstant(m, "PROTOCOL_SSLv2", +- PY_SSL_VERSION_SSL2); + PyModule_AddIntConstant(m, "PROTOCOL_SSLv3", + PY_SSL_VERSION_SSL3); + PyModule_AddIntConstant(m, "PROTOCOL_SSLv23", diff --git a/tools/android/depends/python26/Makefile b/tools/android/depends/python26/Makefile new file mode 100644 index 0000000000..51a7db1b1d --- /dev/null +++ b/tools/android/depends/python26/Makefile @@ -0,0 +1,53 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile Python-2.6.2-android.patch \ + Python-2.6.5-xcompile.patch Python-2.6-ctypes.patch \ + Python-no-modules.patch Python-no-export-path.patch modules.setup + +# lib name, version +LIBNAME=Python +VERSION=2.6.5 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.bz2 + +# configuration settings +CONFIGURE=OPT=-Os \ + LIBS=-lm \ + ./configure --prefix=$(PREFIX) --host=$(HOST) \ + --disable-toolbox-glue --disable-framework --with-system-ffi \ + ac_cv_func_gethostbyname_r=no ac_cv_header_sys_un_h=yes + +LIBDYLIB=$(PLATFORM)/libpython2.6.a + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + echo $(NATIVEPREFIX) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -Np1 -i ../Python-2.6.5-xcompile.patch + cd $(PLATFORM); patch -Np1 -i ../Python-2.6.2-android.patch + cd $(PLATFORM); patch -p0 < ../Python-no-modules.patch + cd $(PLATFORM); patch -p0 < ../Python-no-export-path.patch + cp modules.setup $(PLATFORM)/Modules/Setup.dist + cd $(PLATFORM); sed -ie 's|-framework CoreFoundation||' configure.in + cd $(PLATFORM); $(AUTORECONF) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) HOSTPYTHON=$(NATIVEPREFIX)/bin/python HOSTPGEN=$(NATIVEPREFIX)/bin/pgen CROSS_COMPILE_TARGET=yes libpython2.6.a + +.installed-$(PLATFORM): $(LIBDYLIB) + make -C $(PLATFORM) HOSTPYTHON=$(NATIVEPREFIX)/bin/python HOSTPGEN=$(NATIVEPREFIX)/bin/pgen CROSS_COMPILE_TARGET=yes install + find $(PREFIX)/lib/python2.6 -type f -name "*.py" -delete + find $(PREFIX)/lib/python2.6 -type f -name "*.pyc" -delete + # + touch $@ + +clean: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/python26/Python-2.6-ctypes.patch b/tools/android/depends/python26/Python-2.6-ctypes.patch new file mode 100644 index 0000000000..647dca800b --- /dev/null +++ b/tools/android/depends/python26/Python-2.6-ctypes.patch @@ -0,0 +1,45 @@ +--- a/Modules/_ctypes/_ctypes.c (revision 74955) ++++ b/Modules/_ctypes/_ctypes.c (working copy) +@@ -5521,36 +5521,42 @@ + Struct_Type.tp_base = &CData_Type; + if (PyType_Ready(&Struct_Type) < 0) + return; ++ Py_INCREF(&Struct_Type); + PyModule_AddObject(m, "Structure", (PyObject *)&Struct_Type); + + Py_TYPE(&Union_Type) = &UnionType_Type; + Union_Type.tp_base = &CData_Type; + if (PyType_Ready(&Union_Type) < 0) + return; ++ Py_INCREF(&Union_Type); + PyModule_AddObject(m, "Union", (PyObject *)&Union_Type); + + Py_TYPE(&Pointer_Type) = &PointerType_Type; + Pointer_Type.tp_base = &CData_Type; + if (PyType_Ready(&Pointer_Type) < 0) + return; ++ Py_INCREF(&Pointer_Type); + PyModule_AddObject(m, "_Pointer", (PyObject *)&Pointer_Type); + + Py_TYPE(&Array_Type) = &ArrayType_Type; + Array_Type.tp_base = &CData_Type; + if (PyType_Ready(&Array_Type) < 0) + return; ++ Py_INCREF(&Array_Type); + PyModule_AddObject(m, "Array", (PyObject *)&Array_Type); + + Py_TYPE(&Simple_Type) = &SimpleType_Type; + Simple_Type.tp_base = &CData_Type; + if (PyType_Ready(&Simple_Type) < 0) + return; ++ Py_INCREF(&Simple_Type); + PyModule_AddObject(m, "_SimpleCData", (PyObject *)&Simple_Type); + + Py_TYPE(&CFuncPtr_Type) = &CFuncPtrType_Type; + CFuncPtr_Type.tp_base = &CData_Type; + if (PyType_Ready(&CFuncPtr_Type) < 0) + return; ++ Py_INCREF(&CFuncPtr_Type); + PyModule_AddObject(m, "CFuncPtr", (PyObject *)&CFuncPtr_Type); + + /************************************************* diff --git a/tools/android/depends/python26/Python-2.6.2-android.patch b/tools/android/depends/python26/Python-2.6.2-android.patch new file mode 100644 index 0000000000..78ad30008a --- /dev/null +++ b/tools/android/depends/python26/Python-2.6.2-android.patch @@ -0,0 +1,61 @@ +diff --ignore-file-name-case -wuprN Python-2.6.2/Modules/pwdmodule.c python-src//Modules/pwdmodule.c +--- Python-2.6.2/Modules/pwdmodule.c 2008-06-09 01:58:54.000000000 -0300 ++++ python-src//Modules/pwdmodule.c 2011-01-05 17:09:37.000000000 -0300 +@@ -68,14 +68,14 @@ mkpwent(struct passwd *p) + #define SETS(i,val) sets(v, i, val) + + SETS(setIndex++, p->pw_name); +-#ifdef __VMS ++#if defined(__VMS) || defined(ANDROID) + SETS(setIndex++, ""); + #else + SETS(setIndex++, p->pw_passwd); + #endif + SETI(setIndex++, p->pw_uid); + SETI(setIndex++, p->pw_gid); +-#ifdef __VMS ++#if defined(__VMS) || defined(ANDROID) + SETS(setIndex++, ""); + #else + SETS(setIndex++, p->pw_gecos); +diff --ignore-file-name-case -wuprN Python-2.6.2/Modules/termios.c python-src//Modules/termios.c +--- Python-2.6.2/Modules/termios.c 2008-06-09 01:58:54.000000000 -0300 ++++ python-src//Modules/termios.c 2011-01-05 17:09:37.000000000 -0300 +@@ -227,6 +227,7 @@ termios_tcsendbreak(PyObject *self, PyOb + return Py_None; + } + ++#if 0 // No tcdrain defined for Android. + PyDoc_STRVAR(termios_tcdrain__doc__, + "tcdrain(fd) -> None\n\ + \n\ +@@ -246,6 +247,7 @@ termios_tcdrain(PyObject *self, PyObject + Py_INCREF(Py_None); + return Py_None; + } ++#endif + + PyDoc_STRVAR(termios_tcflush__doc__, + "tcflush(fd, queue) -> None\n\ +@@ -301,8 +303,8 @@ static PyMethodDef termios_methods[] = + METH_VARARGS, termios_tcsetattr__doc__}, + {"tcsendbreak", termios_tcsendbreak, + METH_VARARGS, termios_tcsendbreak__doc__}, +- {"tcdrain", termios_tcdrain, +- METH_VARARGS, termios_tcdrain__doc__}, ++ // {"tcdrain", termios_tcdrain, ++ // METH_VARARGS, termios_tcdrain__doc__}, + {"tcflush", termios_tcflush, + METH_VARARGS, termios_tcflush__doc__}, + {"tcflow", termios_tcflow, +--- Python-2.6.2/Modules/posixmodule.c 2012-06-20 14:20:07.833441645 -0400 ++++ Python-2.6.2/Modules/posixmodule.c 2012-06-20 14:23:03.023441535 -0400 +@@ -3761,7 +3761,7 @@ + slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ + if (slave_fd < 0) + return posix_error(); +-#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC) ++#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC) && !defined(ANDROID) + ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ + ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ + #ifndef __hpux diff --git a/tools/android/depends/python26/Python-2.6.5-xcompile.patch b/tools/android/depends/python26/Python-2.6.5-xcompile.patch new file mode 100644 index 0000000000..51df2d347d --- /dev/null +++ b/tools/android/depends/python26/Python-2.6.5-xcompile.patch @@ -0,0 +1,301 @@ +diff -uN Python-2.6.2/configure Python-2.6.2POld/configure +--- Python-2.6.2/configure 2009-03-31 03:56:14.000000000 +1000 + +@@ -24326,14 +24326,14 @@ + + { echo "$as_me:$LINENO: checking for %zd printf() format support" >&5 + echo $ECHO_N "checking for %zd printf() format support... $ECHO_C" >&6; } +-if test "$cross_compiling" = yes; then +- { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +-See \`config.log' for more details." >&5 +-echo "$as_me: error: cannot run test program while cross compiling +-See \`config.log' for more details." >&2;} +- { (exit 1); exit 1; }; } +-else +- cat >conftest.$ac_ext <<_ACEOF ++#if test "$cross_compiling" = yes; then ++# { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling ++#See \`config.log' for more details." >&5 ++#echo "$as_me: error: cannot run test program while cross compiling ++#See \`config.log' for more details." >&2;} ++# { (exit 1); exit 1; }; } ++#else ++cat >conftest.$ac_ext <<_ACEOF + /* confdefs.h. */ + _ACEOF + cat confdefs.h >>conftest.$ac_ext +@@ -24411,7 +24411,7 @@ + echo "${ECHO_T}no" >&6; } + fi + rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +-fi ++#fi + + + +diff -uN Python-2.6.2/configure.in Python-2.6.2POld/configure.in +--- Python-2.6.2/configure.in 2009-03-31 03:56:14.000000000 +1000 ++++ Python-2.6.2POld/configure.in 2009-08-17 12:19:15.000000000 +1000 +@@ -3656,48 +3656,48 @@ + AC_MSG_RESULT(no) + fi + +-AC_MSG_CHECKING(for %zd printf() format support) +-AC_TRY_RUN([#include <stdio.h> +-#include <stddef.h> +-#include <string.h> +- +-#ifdef HAVE_SYS_TYPES_H +-#include <sys/types.h> +-#endif +- +-#ifdef HAVE_SSIZE_T +-typedef ssize_t Py_ssize_t; +-#elif SIZEOF_VOID_P == SIZEOF_LONG +-typedef long Py_ssize_t; +-#else +-typedef int Py_ssize_t; +-#endif +- +-int main() +-{ +- char buffer[256]; +- +- if(sprintf(buffer, "%zd", (size_t)123) < 0) +- return 1; +- +- if (strcmp(buffer, "123")) +- return 1; +- +- if (sprintf(buffer, "%zd", (Py_ssize_t)-123) < 0) +- return 1; +- +- if (strcmp(buffer, "-123")) +- return 1; +- +- return 0; +-}], +-[AC_MSG_RESULT(yes) +- AC_DEFINE(PY_FORMAT_SIZE_T, "z", [Define to printf format modifier for Py_ssize_t])], +- AC_MSG_RESULT(no)) ++#AC_MSG_CHECKING(for %zd printf() format support) ++#AC_TRY_RUN([#include <stdio.h> ++##include <stddef.h> ++##include <string.h> ++ ++##ifdef HAVE_SYS_TYPES_H ++##include <sys/types.h> ++##endif ++ ++##ifdef HAVE_SSIZE_T ++#typedef ssize_t Py_ssize_t; ++##elif SIZEOF_VOID_P == SIZEOF_LONG ++#typedef long Py_ssize_t; ++##else ++#typedef int Py_ssize_t; ++##endif ++# ++#int main() ++#{ ++# char buffer[256]; ++# ++# if(sprintf(buffer, "%zd", (size_t)123) < 0) ++# return 1;# ++# ++# if (strcmp(buffer, "123")) ++# return 1; ++# ++# if (sprintf(buffer, "%zd", (Py_ssize_t)-123) < 0) ++# return 1; ++# ++# if (strcmp(buffer, "-123")) ++# return 1; ++# ++# return 0; ++#}], ++#[AC_MSG_RESULT(yes) ++# AC_DEFINE(PY_FORMAT_SIZE_T, "z", [Define to printf format modifier for Py_ssize_t])], ++# AC_MSG_RESULT(no)) + + AC_CHECK_TYPE(socklen_t,, + AC_DEFINE(socklen_t,int, +- Define to `int' if <sys/socket.h> does not define.),[ ++ Define to 'int' if <sys/socket.h> does not define.),[ + #ifdef HAVE_SYS_TYPES_H + #include <sys/types.h> + #endif +diff -uN Python-2.6.2/Makefile.pre.in Python-2.6.2POld/Makefile.pre.in +--- Python-2.6.2/Makefile.pre.in 2009-02-24 21:07:44.000000000 +1000 ++++ Python-2.6.2POld/Makefile.pre.in 2009-08-17 12:19:15.000000000 +1000 +@@ -175,6 +175,7 @@ + + PYTHON= python$(EXE) + BUILDPYTHON= python$(BUILDEXE) ++HOSTPYTHON= ./$(BUILDPYTHON) + + # The task to run while instrument when building the profile-opt target + PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck +@@ -206,6 +207,8 @@ + # Parser + PGEN= Parser/pgen$(EXE) + ++HOSTPGEN= $(PGEN) ++ + POBJS= \ + Parser/acceler.o \ + Parser/grammar1.o \ +@@ -394,8 +397,8 @@ + # Build the shared modules + sharedmods: $(BUILDPYTHON) + @case $$MAKEFLAGS in \ +- *s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py -q build;; \ +- *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py build;; \ ++ *s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' $(HOSTPYTHON) -E $(srcdir)/setup.py -q build;; \ ++ *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' $(HOSTPYTHON) -E $(srcdir)/setup.py build;; \ + esac + + # Build static library +@@ -517,7 +520,7 @@ + + $(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT) + -@$(INSTALL) -d Include +- -$(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) ++ -$(HOSTPGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) + + $(PGEN): $(PGENOBJS) + $(CC) $(OPT) $(LDFLAGS) $(PGENOBJS) $(LIBS) -o $(PGEN) +@@ -886,24 +889,24 @@ + done; \ + done + $(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt +- PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- ./$(BUILDPYTHON) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \ ++ -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ ++ $(HOSTPYTHON) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST) -f \ + -x 'bad_coding|badsyntax|site-packages' $(DESTDIR)$(LIBDEST) +- PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- ./$(BUILDPYTHON) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ ++ -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ ++ $(HOSTPYTHON) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST) -f \ + -x 'bad_coding|badsyntax|site-packages' $(DESTDIR)$(LIBDEST) + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- ./$(BUILDPYTHON) -Wi -t $(DESTDIR)$(LIBDEST)/compileall.py \ ++ $(HOSTPYTHON) -Wi -t $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST)/site-packages -f \ + -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- ./$(BUILDPYTHON) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \ ++ $(HOSTPYTHON) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST)/site-packages -f \ + -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- ./$(BUILDPYTHON) -Wi -t -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" ++ $(HOSTPYTHON) -Wi -t -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" + + # Create the PLATDIR source directory, if one wasn't distributed.. + $(srcdir)/Lib/$(PLATDIR): +@@ -1001,7 +1004,8 @@ + # Install the dynamically loadable modules + # This goes into $(exec_prefix) + sharedinstall: +- $(RUNSHARED) ./$(BUILDPYTHON) -E $(srcdir)/setup.py install \ ++ CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' CROSS_COMPILE='$(CROSS_COMPILE)' \ ++ $(RUNSHARED) $(HOSTPYTHON) -E $(srcdir)/setup.py install \ + --prefix=$(prefix) \ + --install-scripts=$(BINDIR) \ + --install-platlib=$(DESTSHARED) \ +diff -uN Python-2.6.2/setup.py Python-2.6.2POld/setup.py +--- Python-2.6.2/setup.py 2009-04-01 04:20:48.000000000 +1000 ++++ Python-2.6.2POld/setup.py 2009-08-17 12:19:15.000000000 +1000 +@@ -17,7 +17,7 @@ + from distutils.command.install_lib import install_lib + + # This global variable is used to hold the list of modules to be disabled. +-disabled_module_list = [] ++disabled_module_list = ['_ctypes', '_curses', '_curses_panel', '_cursesmodule', '_tkinter', 'syslogmodule', 'nismodule'] + + def add_dir_to_list(dirlist, dir): + """Add the directory 'dir' to the list 'dirlist' (at the front) if +@@ -267,33 +267,40 @@ + self.announce('WARNING: skipping import check for Cygwin-based "%s"' + % ext.name) + return ++ if os.environ.get('CROSS_COMPILE_TARGET') == 'yes': ++ return ++ + ext_filename = os.path.join( + self.build_lib, + self.get_ext_filename(self.get_ext_fullname(ext.name))) + try: + imp.load_dynamic(ext.name, ext_filename) + except ImportError, why: +- self.failed.append(ext.name) +- self.announce('*** WARNING: renaming "%s" since importing it' +- ' failed: %s' % (ext.name, why), level=3) +- assert not self.inplace +- basename, tail = os.path.splitext(ext_filename) +- newname = basename + "_failed" + tail +- if os.path.exists(newname): +- os.remove(newname) +- os.rename(ext_filename, newname) +- +- # XXX -- This relies on a Vile HACK in +- # distutils.command.build_ext.build_extension(). The +- # _built_objects attribute is stored there strictly for +- # use here. +- # If there is a failure, _built_objects may not be there, +- # so catch the AttributeError and move on. +- try: +- for filename in self._built_objects: +- os.remove(filename) +- except AttributeError: +- self.announce('unable to remove files (ignored)') ++ if os.environ.get('CROSS_COMPILE_TARGET') != "yes": ++ self.announce('*** WARNING: renaming "%s" since importing it' ++ ' failed: %s' % (ext.name, why), level=3) ++ assert not self.inplace ++ basename, tail = os.path.splitext(ext_filename) ++ newname = basename + "_failed" + tail ++ if os.path.exists(newname): ++ os.remove(newname) ++ os.rename(ext_filename, newname) ++ ++ # XXX -- This relies on a Vile HACK in ++ # distutils.command.build_ext.build_extension(). The ++ # _built_objects attribute is stored there strictly for ++ # use here. ++ # If there is a failure, _built_objects may not be there, ++ # so catch the AttributeError and move on. ++ try: ++ for filename in self._built_objects: ++ os.remove(filename) ++ except AttributeError: ++ self.announce('unable to remove files (ignored)') ++ else: ++ self.announce('WARNING: "%s" failed importing, but we leave it ' ++ 'because we are cross-compiling' % ++ ext.name) + except: + exc_type, why, tb = sys.exc_info() + self.announce('*** WARNING: importing extension "%s" ' +@@ -665,7 +672,7 @@ + + if (ssl_incs is not None and + ssl_libs is not None and +- openssl_ver >= 0x00907000): ++ openssl_ver >= 0x00907000 and False): + # The _hashlib module wraps optimized implementations + # of hash functions from the OpenSSL library. + exts.append( Extension('_hashlib', ['_hashopenssl.c'], +@@ -685,7 +692,7 @@ + depends = ['md5.h']) ) + missing.append('_hashlib') + +- if (openssl_ver < 0x00908000): ++ if (True or openssl_ver < 0x00908000): + # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash + exts.append( Extension('_sha256', ['sha256module.c']) ) + exts.append( Extension('_sha512', ['sha512module.c']) ) + diff --git a/tools/android/depends/python26/Python-no-export-path.patch b/tools/android/depends/python26/Python-no-export-path.patch new file mode 100644 index 0000000000..6753baa9c8 --- /dev/null +++ b/tools/android/depends/python26/Python-no-export-path.patch @@ -0,0 +1,12 @@ +diff -ruN Makefile.pre.in Makefile.pre.in +--- Makefile.pre.in 2012-07-12 17:52:37.072234980 -0400 ++++ Makefile.pre.in 2012-07-13 15:45:36.522185303 -0400 +@@ -912,8 +912,6 @@ + $(srcdir)/Lib/$(PLATDIR): + mkdir $(srcdir)/Lib/$(PLATDIR) + cp $(srcdir)/Lib/plat-generic/regen $(srcdir)/Lib/$(PLATDIR)/regen +- export PATH; PATH="`pwd`:$$PATH"; \ +- export PYTHONPATH; PYTHONPATH="`pwd`/Lib"; \ + export DYLD_FRAMEWORK_PATH; DYLD_FRAMEWORK_PATH="`pwd`"; \ + export EXE; EXE="$(BUILDEXE)"; \ + cd $(srcdir)/Lib/$(PLATDIR); $(RUNSHARED) ./regen
\ No newline at end of file diff --git a/tools/android/depends/python26/Python-no-modules.patch b/tools/android/depends/python26/Python-no-modules.patch new file mode 100644 index 0000000000..f65683799f --- /dev/null +++ b/tools/android/depends/python26/Python-no-modules.patch @@ -0,0 +1,12 @@ +diff -ruN setup.py /setup.py +--- setup.py 2012-06-22 19:56:02.633319969 -0400 ++++ setup.py 2012-06-22 19:56:49.403319941 -0400 +@@ -98,7 +98,7 @@ + self.failed = [] + + def build_extensions(self): +- ++ return + # Detect which modules should be compiled + missing = self.detect_modules() + diff --git a/tools/android/depends/python26/modules.setup b/tools/android/depends/python26/modules.setup new file mode 100644 index 0000000000..7af2e85f83 --- /dev/null +++ b/tools/android/depends/python26/modules.setup @@ -0,0 +1,519 @@ +# -*- makefile -*- +# The file Setup is used by the makesetup script to construct the files +# Makefile and config.c, from Makefile.pre and config.c.in, +# respectively. The file Setup itself is initially copied from +# Setup.dist; once it exists it will not be overwritten, so you can edit +# Setup to your heart's content. Note that Makefile.pre is created +# from Makefile.pre.in by the toplevel configure script. + +# (VPATH notes: Setup and Makefile.pre are in the build directory, as +# are Makefile and config.c; the *.in and *.dist files are in the source +# directory.) + +# Each line in this file describes one or more optional modules. +# Modules enabled here will not be compiled by the setup.py script, +# so the file can be used to override setup.py's behavior. + +# Lines have the following structure: +# +# <module> ... [<sourcefile> ...] [<cpparg> ...] [<library> ...] +# +# <sourcefile> is anything ending in .c (.C, .cc, .c++ are C++ files) +# <cpparg> is anything starting with -I, -D, -U or -C +# <library> is anything ending in .a or beginning with -l or -L +# <module> is anything else but should be a valid Python +# identifier (letters, digits, underscores, beginning with non-digit) +# +# (As the makesetup script changes, it may recognize some other +# arguments as well, e.g. *.so and *.sl as libraries. See the big +# case statement in the makesetup script.) +# +# Lines can also have the form +# +# <name> = <value> +# +# which defines a Make variable definition inserted into Makefile.in +# +# Finally, if a line contains just the word "*shared*" (without the +# quotes but with the stars), then the following modules will not be +# built statically. The build process works like this: +# +# 1. Build all modules that are declared as static in Modules/Setup, +# combine them into libpythonxy.a, combine that into python. +# 2. Build all modules that are listed as shared in Modules/Setup. +# 3. Invoke setup.py. That builds all modules that +# a) are not builtin, and +# b) are not listed in Modules/Setup, and +# c) can be build on the target +# +# Therefore, modules declared to be shared will not be +# included in the config.c file, nor in the list of objects to be +# added to the library archive, and their linker options won't be +# added to the linker options. Rules to create their .o files and +# their shared libraries will still be added to the Makefile, and +# their names will be collected in the Make variable SHAREDMODS. This +# is used to build modules as shared libraries. (They can be +# installed using "make sharedinstall", which is implied by the +# toplevel "make install" target.) (For compatibility, +# *noconfig* has the same effect as *shared*.) +# +# In addition, *static* explicitly declares the following modules to +# be static. Lines containing "*static*" and "*shared*" may thus +# alternate throughout this file. + +# NOTE: As a standard policy, as many modules as can be supported by a +# platform should be present. The distribution comes with all modules +# enabled that are supported by most platforms and don't require you +# to ftp sources from elsewhere. +*static* + +# Some special rules to define PYTHONPATH. +# Edit the definitions below to indicate which options you are using. +# Don't add any whitespace or comments! + +# Directories where library files get installed. +# DESTLIB is for Python modules; MACHDESTLIB for shared libraries. +DESTLIB=$(LIBDEST) +MACHDESTLIB=$(BINLIBDEST) + +# NOTE: all the paths are now relative to the prefix that is computed +# at run time! + +# Standard path -- don't edit. +# No leading colon since this is the first entry. +# Empty since this is now just the runtime prefix. +DESTPATH= + +# Site specific path components -- should begin with : if non-empty +SITEPATH= + +# Standard path components for test modules +TESTPATH= + +# Path components for machine- or system-dependent modules and shared libraries +MACHDEPPATH=:plat-$(MACHDEP) +EXTRAMACHDEPPATH= + +# Path component for the Tkinter-related modules +# The TKPATH variable is always enabled, to save you the effort. +TKPATH=:lib-tk + +# Path component for old modules. +OLDPATH=:lib-old + +COREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(TESTPATH)$(MACHDEPPATH)$(EXTRAMACHDEPPATH)$(TKPATH)$(OLDPATH) +PYTHONPATH=$(COREPYTHONPATH) + + +# The modules listed here can't be built as shared libraries for +# various reasons; therefore they are listed here instead of in the +# normal order. + +# This only contains the minimal set of modules required to run the +# setup.py script in the root of the Python source tree. + +posix posixmodule.c # posix (UNIX) system calls +errno errnomodule.c # posix (UNIX) errno values +pwd pwdmodule.c # this is needed to find out the user's home dir + # if $HOME is not set +_sre _sre.c # Fredrik Lundh's new regular expressions +_codecs _codecsmodule.c # access to the builtin codecs and codec registry + +# The zipimport module is always imported at startup. Having it as a +# builtin module avoids some bootstrapping problems and reduces overhead. +zipimport zipimport.c + +# The rest of the modules listed in this file are all commented out by +# default. Usually they can be detected and built as dynamically +# loaded modules by the new setup.py script added in Python 2.1. If +# you're on a platform that doesn't support dynamic loading, want to +# compile modules statically into the Python binary, or need to +# specify some odd set of compiler switches, you can uncomment the +# appropriate lines below. + +# ====================================================================== + +# The Python symtable module depends on .h files that setup.py doesn't track +_symtable symtablemodule.c + +# The SGI specific GL module: + +GLHACK=-Dclear=__GLclear +#gl glmodule.c cgensupport.c -I$(srcdir) $(GLHACK) -lgl -lX11 + +# Pure module. Cannot be linked dynamically. +# -DWITH_QUANTIFY, -DWITH_PURIFY, or -DWITH_ALL_PURE +#WHICH_PURE_PRODUCTS=-DWITH_ALL_PURE +#PURE_INCLS=-I/usr/local/include +#PURE_STUBLIBS=-L/usr/local/lib -lpurify_stubs -lquantify_stubs +#pure puremodule.c $(WHICH_PURE_PRODUCTS) $(PURE_INCLS) $(PURE_STUBLIBS) + +# Uncommenting the following line tells makesetup that all following +# modules are to be built as shared libraries (see above for more +# detail; also note that *static* reverses this effect): + +#*shared* + +# GNU readline. Unlike previous Python incarnations, GNU readline is +# now incorporated in an optional module, configured in the Setup file +# instead of by a configure script switch. You may have to insert a +# -L option pointing to the directory where libreadline.* lives, +# and you may have to change -ltermcap to -ltermlib or perhaps remove +# it, depending on your system -- see the GNU readline instructions. +# It's okay for this to be a shared library, too. + +#readline readline.c -lreadline -lncurses + + +# Modules that should always be present (non UNIX dependent): + +array arraymodule.c # array objects +cmath cmathmodule.c # -lm # complex math library functions +math mathmodule.c # -lm # math library functions, e.g. sin() +_struct _struct.c # binary structure packing/unpacking +time timemodule.c # -lm # time operations and variables +operator operator.c # operator.add() and similar goodies +_weakref _weakref.c # basic weak reference support +_testcapi _testcapimodule.c # Python C API test module +_random _randommodule.c # Random number generator +_collections _collectionsmodule.c # Container types +itertools itertoolsmodule.c # Functions creating iterators for efficient looping +strop stropmodule.c # String manipulations +_functools _functoolsmodule.c # Tools for working with functions and callable objects + +EXPATDEFINES='-DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI' +_elementtree -I$(srcdir)/Modules/expat $(EXPATDEFINES) _elementtree.c # elementtree accelerator +#_pickle _pickle.c # pickle accelerator +datetime datetimemodule.c # date/time type +_bisect _bisectmodule.c # Bisection algorithms + +unicodedata unicodedata.c # static Unicode character database + +# access to ISO C locale support +_locale _localemodule.c -lintl -liconv + + +# Modules with some UNIX dependencies -- on by default: +# (If you have a really backward UNIX, select and socket may not be +# supported...) +# +fcntl fcntlmodule.c # fcntl(2) and ioctl(2) +#spwd spwdmodule.c # spwd(3) +#grp grpmodule.c # grp(3) +select selectmodule.c # select(2); not on ancient System V + +# Memory-mapped files (also works on Win32). +mmap mmapmodule.c + +# CSV file helper +_csv _csv.c + +# Socket module helper for socket(2) +_socket socketmodule.c + +# Socket module helper for SSL support; you must comment out the other +# socket line above, and possibly edit the SSL variable: +SSLDEFINES='-DUSE_SSL' +_ssl _ssl.c \ + $(SSLDEFINES) -I$(prefix)/include -I$(prefix)/include/openssl \ + -L$(prefix)/lib -lssl -lcrypto + +_hashlib _hashopenssl.c \ + $(SSLDEFINES) -I$(prefix)/include -I$(prefix)/include/openssl \ + -L$(prefix)/lib -lssl -lcrypto + +# The crypt module is now disabled by default because it breaks builds +# on many systems (where -lcrypt is needed), e.g. Linux (I believe). +# +# First, look at Setup.config; configure may have set this for you. + +#crypt cryptmodule.c -lcrypt # crypt(3); needs -lcrypt on some systems + +# Some more UNIX dependent modules -- off by default, since these +# are not supported by all UNIX systems: + +#nis nismodule.c -lnsl # Sun yellow pages -- not everywhere +termios termios.c # Steen Lumholt's termios module +resource resource.c # Jeremy Hylton's rlimit interface + + +# Multimedia modules -- off by default. +# These don't work for 64-bit platforms!!! +# #993173 says audioop works on 64-bit platforms, though. +# These represent audio samples or images as strings: + +#audioop audioop.c # Operations on audio samples +#imageop imageop.c # Operations on images + + +# Note that the _md5 and _sha modules are normally only built if the +# system does not have the OpenSSL libs containing an optimized version. + +# The _md5 module implements the RSA Data Security, Inc. MD5 +# Message-Digest Algorithm, described in RFC 1321. The necessary files +# md5.c and md5.h are included here. + +_md5 md5module.c md5.c + + +# The _sha module implements the SHA checksum algorithms. +# (NIST's Secure Hash Algorithms.) +_sha shamodule.c +_sha256 sha256module.c +_sha512 sha512module.c + + +# SGI IRIX specific modules -- off by default. + +# These module work on any SGI machine: + +# *** gl must be enabled higher up in this file *** +#fm fmmodule.c $(GLHACK) -lfm -lgl # Font Manager +#sgi sgimodule.c # sgi.nap() and a few more + +# This module requires the header file +# /usr/people/4Dgifts/iristools/include/izoom.h: +#imgfile imgfile.c -limage -lgutil -lgl -lm # Image Processing Utilities + + +# These modules require the Multimedia Development Option (I think): + +#al almodule.c -laudio # Audio Library +#cd cdmodule.c -lcdaudio -lds -lmediad # CD Audio Library +#cl clmodule.c -lcl -lawareaudio # Compression Library +#sv svmodule.c yuvconvert.c -lsvideo -lXext -lX11 # Starter Video + + +# The FORMS library, by Mark Overmars, implements user interface +# components such as dialogs and buttons using SGI's GL and FM +# libraries. You must ftp the FORMS library separately from +# ftp://ftp.cs.ruu.nl/pub/SGI/FORMS. It was tested with FORMS 2.2a. +# NOTE: if you want to be able to use FORMS and curses simultaneously +# (or both link them statically into the same binary), you must +# compile all of FORMS with the cc option "-Dclear=__GLclear". + +# The FORMS variable must point to the FORMS subdirectory of the forms +# toplevel directory: + +#FORMS=/ufs/guido/src/forms/FORMS +#fl flmodule.c -I$(FORMS) $(GLHACK) $(FORMS)/libforms.a -lfm -lgl + + +# SunOS specific modules -- off by default: + +#sunaudiodev sunaudiodev.c + + +# A Linux specific module -- off by default; this may also work on +# some *BSDs. + +#linuxaudiodev linuxaudiodev.c + + +# George Neville-Neil's timing module: + +timing timingmodule.c + + +# The _tkinter module. +# +# The command for _tkinter is long and site specific. Please +# uncomment and/or edit those parts as indicated. If you don't have a +# specific extension (e.g. Tix or BLT), leave the corresponding line +# commented out. (Leave the trailing backslashes in! If you +# experience strange errors, you may want to join all uncommented +# lines and remove the backslashes -- the backslash interpretation is +# done by the shell's "read" command and it may not be implemented on +# every system. + +# *** Always uncomment this (leave the leading underscore in!): +# _tkinter _tkinter.c tkappinit.c -DWITH_APPINIT \ +# *** Uncomment and edit to reflect where your Tcl/Tk libraries are: +# -L/usr/local/lib \ +# *** Uncomment and edit to reflect where your Tcl/Tk headers are: +# -I/usr/local/include \ +# *** Uncomment and edit to reflect where your X11 header files are: +# -I/usr/X11R6/include \ +# *** Or uncomment this for Solaris: +# -I/usr/openwin/include \ +# *** Uncomment and edit for Tix extension only: +# -DWITH_TIX -ltix8.1.8.2 \ +# *** Uncomment and edit for BLT extension only: +# -DWITH_BLT -I/usr/local/blt/blt8.0-unoff/include -lBLT8.0 \ +# *** Uncomment and edit for PIL (TkImaging) extension only: +# (See http://www.pythonware.com/products/pil/ for more info) +# -DWITH_PIL -I../Extensions/Imaging/libImaging tkImaging.c \ +# *** Uncomment and edit for TOGL extension only: +# -DWITH_TOGL togl.c \ +# *** Uncomment and edit to reflect your Tcl/Tk versions: +# -ltk8.2 -ltcl8.2 \ +# *** Uncomment and edit to reflect where your X11 libraries are: +# -L/usr/X11R6/lib \ +# *** Or uncomment this for Solaris: +# -L/usr/openwin/lib \ +# *** Uncomment these for TOGL extension only: +# -lGL -lGLU -lXext -lXmu \ +# *** Uncomment for AIX: +# -lld \ +# *** Always uncomment this; X11 libraries to link with: +# -lX11 + +# Lance Ellinghaus's syslog module +syslog syslogmodule.c # syslog daemon interface + + +# Curses support, requring the System V version of curses, often +# provided by the ncurses library. e.g. on Linux, link with -lncurses +# instead of -lcurses). +# +# First, look at Setup.config; configure may have set this for you. + +#_curses _cursesmodule.c -lcurses -ltermcap +# Wrapper for the panel library that's part of ncurses and SYSV curses. +#_curses_panel _curses_panel.c -lpanel -lncurses + + +# Generic (SunOS / SVR4) dynamic loading module. +# This is not needed for dynamic loading of Python modules -- +# it is a highly experimental and dangerous device for calling +# *arbitrary* C functions in *arbitrary* shared libraries: + +#dl dlmodule.c + + +# Modules that provide persistent dictionary-like semantics. You will +# probably want to arrange for at least one of them to be available on +# your machine, though none are defined by default because of library +# dependencies. The Python module anydbm.py provides an +# implementation independent wrapper for these; dumbdbm.py provides +# similar functionality (but slower of course) implemented in Python. + +# The standard Unix dbm module has been moved to Setup.config so that +# it will be compiled as a shared library by default. Compiling it as +# a built-in module causes conflicts with the pybsddb3 module since it +# creates a static dependency on an out-of-date version of db.so. +# +# First, look at Setup.config; configure may have set this for you. + +#dbm -I$(prefix)/include -L$(prefix)/lib dbmmodule.c # dbm(3) may require -lndbm or similar + +# Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: +# +# First, look at Setup.config; configure may have set this for you. + +#gdbm gdbmmodule.c -I$(prefix)/include -L$(prefix)/lib -lgdbm + + +# Sleepycat Berkeley DB interface. +# +# This requires the Sleepycat DB code, see http://www.sleepycat.com/ +# The earliest supported version of that library is 3.0, the latest +# supported version is 4.0 (4.1 is specifically not supported, as that +# changes the semantics of transactional databases). A list of available +# releases can be found at +# +# http://www.sleepycat.com/update/index.html +# +# Edit the variables DB and DBLIBVERto point to the db top directory +# and the subdirectory of PORT where you built it. +#DB=/usr/local/BerkeleyDB.4.0 +#DBLIBVER=4.0 +#DBINC=$(DB)/include +#DBLIB=$(DB)/lib +#_bsddb _bsddb.c -I$(DBINC) -L$(DBLIB) -ldb-$(DBLIBVER) + +# Historical Berkeley DB 1.85 +# +# This module is deprecated; the 1.85 version of the Berkeley DB library has +# bugs that can cause data corruption. If you can, use later versions of the +# library instead, available from <http://www.sleepycat.com/>. + +#DB=/depot/sundry/src/berkeley-db/db.1.85 +#DBPORT=$(DB)/PORT/irix.5.3 +#bsddb185 bsddbmodule.c -I$(DBPORT)/include -I$(DBPORT) $(DBPORT)/libdb.a + + + +# Helper module for various ascii-encoders +binascii binascii.c + +# Fred Drake's interface to the Python parser +parser parsermodule.c + +# cStringIO and cPickle +cStringIO cStringIO.c +cPickle cPickle.c + + +# Lee Busby's SIGFPE modules. +# The library to link fpectl with is platform specific. +# Choose *one* of the options below for fpectl: + +# For SGI IRIX (tested on 5.3): +#fpectl fpectlmodule.c -lfpe + +# For Solaris with SunPro compiler (tested on Solaris 2.5 with SunPro C 4.2): +# (Without the compiler you don't have -lsunmath.) +#fpectl fpectlmodule.c -R/opt/SUNWspro/lib -lsunmath -lm + +# For other systems: see instructions in fpectlmodule.c. +#fpectl fpectlmodule.c ... + +# Test module for fpectl. No extra libraries needed. +#fpetest fpetestmodule.c + +# Andrew Kuchling's zlib module. +# This require zlib 1.1.3 (or later). +# See http://www.gzip.org/zlib/ +zlib zlibmodule.c -I$(prefix)/include -L$(prefix)/lib -lz + +# Interface to the Expat XML parser +# +# Expat was written by James Clark and is now maintained by a group of +# developers on SourceForge; see www.libexpat.org for more +# information. The pyexpat module was written by Paul Prescod after a +# prototype by Jack Jansen. Source of Expat 1.95.2 is included in +# Modules/expat/. Usage of a system shared libexpat.so/expat.dll is +# not advised. +# +# More information on Expat can be found at www.libexpat.org. +# +pyexpat expat/xmlparse.c expat/xmlrole.c expat/xmltok.c pyexpat.c -I$(srcdir)/Modules/expat $(EXPATDEFINES) -I$(prefix)/include -L$(prefix)/lib -lexpat + + +# Hye-Shik Chang's CJKCodecs + +# multibytecodec is required for all the other CJK codec modules +_multibytecodec cjkcodecs/multibytecodec.c + +_codecs_cn cjkcodecs/_codecs_cn.c +_codecs_hk cjkcodecs/_codecs_hk.c +_codecs_iso2022 cjkcodecs/_codecs_iso2022.c +_codecs_jp cjkcodecs/_codecs_jp.c +_codecs_kr cjkcodecs/_codecs_kr.c +_codecs_tw cjkcodecs/_codecs_tw.c + +# Example -- included for reference only: +# xx xxmodule.c + +# Another example -- the 'xxsubtype' module shows C-level subtyping in action +xxsubtype xxsubtype.c + +_lsprof _lsprof.c rotatingtree.c +_json _json.c +_fileio _fileio.c +_heapq _heapqmodule.c +_hotshot _hotshot.c +future_builtins future_builtins.c + +SQLITEDEFINES='-DMODULE_NAME="sqlite3"' +_sqlite3 _sqlite/connection.c \ + _sqlite/cursor.c _sqlite/microprotocols.c _sqlite/prepare_protocol.c \ + _sqlite/row.c _sqlite/statement.c _sqlite/module.c _sqlite/util.c _sqlite/cache.c \ + -I$(prefix)/include -L$(prefix)/lib -lsqlite3 $(SQLITEDEFINES) + +_ctypes _ctypes/callbacks.c _ctypes/callproc.c _ctypes/cfield.c _ctypes/_ctypes.c \ + _ctypes/_ctypes_test.c _ctypes/malloc_closure.c _ctypes/stgdict.c \ + -I$(prefix)/include/ffi -L$(prefix)/lib -lffi + +#bz2 bz2module.c -I$(prefix)/include -L$(prefix)/lib -lbz2 diff --git a/tools/android/depends/readline/01-readline-setpwent.patch b/tools/android/depends/readline/01-readline-setpwent.patch new file mode 100644 index 0000000000..3d04de77c9 --- /dev/null +++ b/tools/android/depends/readline/01-readline-setpwent.patch @@ -0,0 +1,20 @@ +--- readline-6.0/complete.c 2011-01-16 21:32:57.000000000 +0100 ++++ readline-6.0.orig/complete.c 2011-10-15 22:45:29.000000000 +0200 +@@ -2029,6 +2029,9 @@ + static int namelen, first_char, first_char_loc; + char *value; + ++#if defined(__ANDROID__) ++ return (char*)NULL; ++#else + if (state == 0) + { + FREE (username); +@@ -2040,6 +2043,7 @@ + namelen = strlen (username); + setpwent (); + } ++#endif; + + #if defined (HAVE_GETPWENT) + while (entry = getpwent ()) diff --git a/tools/android/depends/readline/Makefile b/tools/android/depends/readline/Makefile new file mode 100644 index 0000000000..33e3d01be9 --- /dev/null +++ b/tools/android/depends/readline/Makefile @@ -0,0 +1,41 @@ +include ../Makefile.include +DEPS= ../Makefile.include 01-readline-setpwent.patch Makefile + +# lib name, version +LIBNAME=readline +VERSION=6.0 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) support/; ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared + +LIBDYLIB=$(PLATFORM)/lib$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -Np1 -i ../01-readline-setpwent.patch + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/rpl/Makefile b/tools/android/depends/rpl/Makefile new file mode 100644 index 0000000000..a401bb5757 --- /dev/null +++ b/tools/android/depends/rpl/Makefile @@ -0,0 +1,14 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile rpl + +all: .installed-$(PLATFORM) + +.installed-$(PLATFORM): $(DEPS) + mkdir -p $(PREFIX)/bin + cp rpl $(PREFIX)/bin + touch $@ + +clean: + +distclean:: diff --git a/tools/android/depends/rpl/rpl b/tools/android/depends/rpl/rpl new file mode 100755 index 0000000000..d528850571 --- /dev/null +++ b/tools/android/depends/rpl/rpl @@ -0,0 +1,310 @@ +#!/usr/bin/python + +import optparse, sys, os, tempfile, re +try: import readline +except ImportError: pass +from stat import * + +def show_license(*eat): + print """rpl - replace strings in files +Copyright (C) 2004-2005 Goran Weinholt <weinholt@debian.org> +Copyright (C) 2004 Christian Haggstrom <chm@c00.info> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +""" + sys.exit(0) + +def get_files(filenames, recurse, suffixen, verbose, hidden_files): + new_files = [] + for filename in filenames: + try: + perms = os.lstat(filename) + except OSError, e: + sys.stderr.write("\nrpl: Unable to read permissions of %s." + % filename) + sys.stderr.write("\nrpl: Error: %s" % e) + sys.stderr.write("\nrpl: SKIPPING %s\n\n" % filename) + continue + + if S_ISDIR(perms.st_mode): + if recurse: + if verbose: + sys.stderr.write("Scanning Directory: %s\n" % filename) + for f in os.listdir(filename): + if not hidden_files and f.startswith('.'): + if verbose: + sys.stderr.write("Skipping: %s (hidden)\n" + % os.path.join(filename, f)) + continue + new_files += get_files([os.path.join(filename, f)], + recurse, suffixen, verbose, + hidden_files) + else: + if verbose: + sys.stderr.write("Directory: %s skipped.\n" % filename) + continue + elif S_ISREG(perms.st_mode): + if suffixen != [] and \ + not True in [ filename.endswith(s) for s in suffixen ]: + sys.stderr.write("Skipping: %s (suffix not in list)\n" + % filename) + continue + new_files += [(filename, perms)] + else: + sys.stderr.write("Skipping: %s (not a regular file)\n" + % filename) + return new_files + +def unescape(s): + regex = re.compile(r'\\([0-7]{1,3}|x[0-9a-fA-F]{2}|[nrtvafb\\])') + return regex.sub(lambda match: eval('"%s"' % match.group()), s) + +def blockrepl(instream, outstream, regex, before, after, blocksize=None): + patlen = len(before) + sum = 0 + if not blocksize: blocksize = 2*patlen + tonext = '' + while 1: + block = instream.read(blocksize) + if not block: break + parts = regex.split(tonext+block) + sum += len(parts)-1 + lastpart = parts[-1] + if lastpart: + tonext = lastpart[-patlen:] + parts[-1] = lastpart[:-len(tonext)] + else: + tonext = '' + outstream.write(after.join(parts)) + outstream.write(tonext) + return sum + +def main(): + # First we parse the command line arguments... + usage = "usage: %prog [options] old_string new_string target_file(s)" + parser = optparse.OptionParser(usage, version="%prog 1.5.2") + parser.add_option("-L", "--license", action="callback", + callback=show_license, help="show the software license") + parser.add_option("-x", metavar="SUFFIX", + action="append", dest="suffixen", default=[], + help="specify file suffix to match") + parser.add_option("-i", "--ignore-case", + action="store_true", dest="ignore_case", default=False, + help="do a case insensitive match") + parser.add_option("-w", "--whole-words", + action="store_true", dest="whole_words", default=False, + help="whole words (old_string matches on word boundaries only)") + parser.add_option("-b", "--backup", + action="store_true", dest="do_backup", default=False, + help="make a backup before overwriting files") + parser.add_option("-q", "--quiet", + action="store_true", dest="quiet", default=False, + help="quiet mode") + parser.add_option("-v", "--verbose", + action="store_true", dest="verbose", default=False, + help="verbose mode") + parser.add_option("-s", "--dry-run", + action="store_true", dest="dry_run", default=False, + help="simulation mode") + parser.add_option("-R", "--recursive", + action="store_true", dest="recurse", default=False, + help="recurse into subdirectories") + parser.add_option("-e", "--escape", + action="store_true", dest="escapes", default=False, + help="expand escapes in old_string and new_string") + parser.add_option("-p", "--prompt", + action="store_true", dest="prompt", default=False, + help="prompt before modifying each file") + parser.add_option("-f", "--force", + action="store_true", dest="force", default=False, + help="ignore errors when trying to preserve permissions") + parser.add_option("-d", "--keep-times", + action="store_true", dest="keep_times", default=False, + help="keep the modification times on modified files") + parser.add_option("-t", "--use-tmpdir", + action="store_true", dest="use_tmpdir", default=False, + help="use $TMPDIR for storing temporary files") + parser.add_option("-a", "--all", + action="store_true", dest="hidden_files", default=False, + help="do not ignore files and directories starting with .") + (opts, args) = parser.parse_args() + + # args should now contain old_str, new_str and a list of files/dirs + if len(args) < 3: + parser.error("must have at least three arguments") + if args[0] == "": + parser.error("must have something to replace") + + old_str = args[0] + new_str = args[1] + files = args[2:] + + # See if all the files actually exist + for file in files: + if not os.path.exists(file): + sys.stderr.write("\nrpl: File \"%s\" not found.\n" % file) + sys.exit(os.EX_DATAERR) + + if new_str == "" and not opts.quiet: + sys.stderr.write("Really DELETE all occurences of %s " % old_str) + if opts.ignore_case: + sys.stderr.write("(ignoring case)? (Y/[N]) ") + else: + sys.stderr.write("(case sensitive)? (Y/[N]) ") + line = raw_input() + if line != "" and line[0] in "nN": + sys.stderr.write("\nrpl: User cancelled operation.\n") + sys.exit(os.EX_TEMPFAIL) + + # Tell the user what is going to happen + if opts.dry_run: + sys.stderr.write("Simulating replacement of \"%s\" with \"%s\" " + % (old_str, new_str)) + else: + sys.stderr.write("Replacing \"%s\" with \"%s\" " % (old_str, new_str)) + if opts.ignore_case: sys.stderr.write("(ignoring case) ") + else: sys.stderr.write("(case sensitive) ") + if opts.whole_words: sys.stderr.write("(whole words only)\n") + else: sys.stderr.write("(partial words matched)\n") + if opts.dry_run and not opts.quiet: + sys.stderr.write("The files listed below would be modified in a replace operation.\n") + + if opts.escapes: + old_str = unescape(old_str) + new_str = unescape(new_str) + if opts.whole_words: + regex = re.compile(r"(?:(?<=\s)|^)" + re.escape(old_str) + r"(?=\s|$)", + opts.ignore_case and re.I or 0) + else: + regex = re.compile(re.escape(old_str), opts.ignore_case and re.I or 0) + + total_matches = 0 + files = get_files(files, opts.recurse, opts.suffixen, opts.verbose, opts.hidden_files) + for filename, perms in files: + # Open the input file + try: f = open(filename, "rb") + except IOError, e: + sys.stderr.write("\nrpl: Unable to open %s for reading." % fn) + sys.stderr.write("\nrpl: Error: %s" % e) + sys.stderr.write("\nrpl: SKIPPING %s\n\n" % fn) + continue + + # Find out where we should put the temporary file + if opts.use_tmpdir: tempfile.tempdir = None + else: tempfile.tempdir = os.path.dirname(filename) + + # Create the output file + try: + o, tmp_path = tempfile.mkstemp("", ".tmp.") + o = os.fdopen(o, "wb") + except OSError, e: + sys.stderr.write("\nrpl: Unable to create temp file.") + sys.stderr.write("\nrpl: Error: %s" % e) + sys.stderr.write("\nrpl: (Type \"rpl -h\" and consider \"-t\" to specify temp file location.)") + sys.stderr.write("\nrpl: SKIPPING %s\n\n" % filename) + continue + + # Set permissions and owner + try: + os.chown(tmp_path, perms.st_uid, perms.st_gid) + os.chmod(tmp_path, perms.st_mode) + except OSError, e: + sys.stderr.write("\nrpl: Unable to set owner/group/perms of %s" + % filename) + sys.stderr.write("\nrpl: Error: %s" % e) + if opts.force: + sys.stderr.write("\nrpl: WARNING: New owner/group/perms may not match!\n\n") + else: + sys.stderr.write("\nrpl: SKIPPING %s!\n\n" % filename) + os.unlink(tmp_path) + continue + + if opts.verbose and not opts.dry_run: + sys.stderr.write("Processing: %s\n" % filename) + elif not opts.quiet and not opts.dry_run: + sys.stderr.write(".") + sys.stderr.flush() + + # Do the actual work now + matches = blockrepl(f, o, regex, old_str, new_str, 1024) + + f.close() + o.close() + + if matches == 0: + os.unlink(tmp_path) + continue + + if opts.dry_run: + try: + fn = os.path.realpath(filename) + except OSError, e: + fn = filename + if not opts.quiet: sys.stderr.write(" %s\n" % fn) + os.unlink(tmp_path) + total_matches += matches + continue + + if opts.prompt: + sys.stderr.write("\nSave '%s' ? ([Y]/N) " % filename) + line = "" + while line == "" or line[0] not in "Yy\nnN": + line = raw_input() + if line[0] in "nN": + sys.stderr.write("Not Saved.\n") + os.unlink(tmp_path) + continue + sys.stderr.write("Saved.\n") + + if opts.do_backup: + try: os.rename(filename, filename + "~") + except OSError, e: + sys.stderr.write("rpl: An error occured renaming %s to %s." % (filename, filename + "~")) + sys.stderr.write("\nrpl: Error: %s" % e) + continue + + # Rename the file + try: os.rename(tmp_path, filename) + except OSError, e: + sys.stderr.write("rpl: An error occured replacing %s with %s." + % (tmp_path, filename)) + sys.stderr.write("\nrpl: Error: %s" % e) + os.unlink(tmp_path) + continue + + # Restore the times + if opts.keep_times: + try: os.utime(filename, (perms.st_atime, perms.st_mtime)) + except OSError, e: + sys.stderr.write("\nrpl: An error occured setting the access time and mod time of the file %s.", filename) + sys.stderr.write("\nrpl: Error: %s" % e) + total_matches += matches + + # We're about to exit, give a summary + if not opts.quiet: + if opts.dry_run: + sys.stderr.write("\nA Total of %lu matches found in %lu file%s searched." + % (total_matches, + len(files), + len(files) != 1 and "s" or "")) + sys.stderr.write("\nNone replaced (simulation mode).\n") + else: + sys.stderr.write("\nA Total of %lu matches replaced in %lu file%s searched.\n" + % (total_matches, + len(files), + len(files) != 1 and "s" or "")) + +if __name__ == "__main__": + main() diff --git a/tools/android/depends/samba/Makefile b/tools/android/depends/samba/Makefile new file mode 100644 index 0000000000..29b53d2db9 --- /dev/null +++ b/tools/android/depends/samba/Makefile @@ -0,0 +1,101 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile samba30-3.0.37-configure.in.patch \ + samba30-3.0.37-CVE-2010-2063.patch \ + samba30-3.0.37-silence-receive-warning.patch \ + samba30-3.0.37-vfs_default.c.patch samba30-3.0.37-wle-fix.patch \ + samba_android.patch + +# lib name, version +LIBNAME=samba +VERSION=3.0.37 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +# android does not really support LFS but we can force it +# in libsmbclient by defining off_t to off64_t and changing +# libsmbclient.h to match. Defining _OFF_T_DEFINED_ allows +# us to change the typedef of off_t in android's sys/type.h. +# Then xbmc will correctly access smb shares with LFS enabled +# using the altered libsmbclient.h. +export CFLAGS+=-D_FILE_OFFSET_BITS=64 -D_OFF_T_DEFINED_ -Doff_t=off64_t -Dlseek=lseek64 +CONFIGURE= cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) \ + SMB_BUILD_CC_NEGATIVE_ENUM_VALUES=yes \ + libreplace_cv_READDIR_GETDIRENTRIES=no \ + libreplace_cv_READDIR_GETDENTS=no \ + linux_getgrouplist_ok=no \ + samba_cv_REPLACE_READDIR=no \ + samba_cv_HAVE_WRFILE_KEYTAB=yes \ + samba_cv_HAVE_GETTIMEOFDAY_TZ=yes \ + samba_cv_USE_SETREUID=yes \ + samba_cv_HAVE_KERNEL_OPLOCKS_LINUX=yes \ + samba_cv_HAVE_IFACE_IFCONF=yes \ + samba_cv_HAVE_MMAP=yes \ + samba_cv_HAVE_FCNTL_LOCK=yes \ + samba_cv_HAVE_SECURE_MKSTEMP=yes \ + samba_cv_CC_NEGATIVE_ENUM_VALUES=yes \ + samba_cv_fpie=no \ + samba_cv_have_longlong=yes \ + samba_cv_HAVE_OFF64_T=yes \ + samba_cv_HAVE_UT_UT_TYPE=no \ + ac_cv_func_srand=yes \ + ac_cv_func_rand=yes \ + --disable-cups \ + --enable-static \ + --disable-shared \ + --disable-pie \ + --disable-iprint \ + --disable-fam \ + --without-cluster-support \ + --without-cifsupcall \ + --without-ads \ + --without-ldap \ + --with-included-popt \ + --with-included-iniparser \ + --without-sys-quotas \ + --without-krb5 \ + --without-automount \ + --without-sendfile-support \ + --with-libiconv=$(STAGING_DIR) \ + --without-cifsmount \ + --without-winbind \ + +LIBDYLIB=$(PLATFORM)/source/bin/libsmbclient.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); patch -p1 < ../samba30-3.0.37-configure.in.patch + cd $(PLATFORM); patch -p1 < ../samba30-3.0.37-CVE-2010-2063.patch + cd $(PLATFORM); patch -p1 < ../samba30-3.0.37-silence-receive-warning.patch + cd $(PLATFORM); patch -p1 < ../samba30-3.0.37-vfs_default.c.patch + cd $(PLATFORM); patch -p1 < ../samba30-3.0.37-wle-fix.patch + cd $(PLATFORM); patch -p0 < ../samba_android.patch + sed -ie "s|off_t|off64_t|g" "$(PLATFORM)/source/include/libsmbclient.h" + cd $(PLATFORM)/source && ./autogen.sh + cd $(PLATFORM)/source; $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM)/source headers + mkdir -p $(PLATFORM)/source/bin + $(MAKE) -C $(PLATFORM)/source libsmbclient + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM)/source installclientlib + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/samba/samba30-3.0.37-CVE-2010-2063.patch b/tools/android/depends/samba/samba30-3.0.37-CVE-2010-2063.patch new file mode 100644 index 0000000000..b4657de2c0 --- /dev/null +++ b/tools/android/depends/samba/samba30-3.0.37-CVE-2010-2063.patch @@ -0,0 +1,38 @@ +diff --git a/source/smbd/process.c b/source/smbd/process.c +index e861e16..6499bc7 100644 +--- a/source/smbd/process.c ++++ b/source/smbd/process.c +@@ -1159,6 +1159,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) + { + static char *orig_inbuf; + static char *orig_outbuf; ++ static int orig_size; + int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); + unsigned smb_off2 = SVAL(inbuf,smb_vwv1); + char *inbuf2, *outbuf2; +@@ -1178,6 +1179,13 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) + /* this is the first part of the chain */ + orig_inbuf = inbuf; + orig_outbuf = outbuf; ++ orig_size = size; ++ } ++ ++ /* Validate smb_off2 */ ++ if ((smb_off2 < smb_wct - 4) || orig_size < (smb_off2 + 4 - smb_wct)) { ++ exit_server_cleanly("Bad chained packet"); ++ return -1; + } + + /* +@@ -1192,6 +1200,11 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) + SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); + SCVAL(outbuf,smb_vwv0,smb_com2); + ++ if (outsize <= smb_wct) { ++ exit_server_cleanly("Bad chained packet"); ++ return -1; ++ } ++ + /* remember how much the caller added to the chain, only counting stuff + after the parameter words */ + chain_size += outsize - smb_wct; diff --git a/tools/android/depends/samba/samba30-3.0.37-configure.in.patch b/tools/android/depends/samba/samba30-3.0.37-configure.in.patch new file mode 100644 index 0000000000..3af1e125fc --- /dev/null +++ b/tools/android/depends/samba/samba30-3.0.37-configure.in.patch @@ -0,0 +1,64 @@ +--- samba-3.0.25borig/source/configure.in 2007-05-23 08:29:20.000000000 -0700 ++++ samba3025bfinal/source/configure.in 2007-07-24 12:15:13.000000000 -0700 +@@ -1374,31 +1374,40 @@ + # + case "$host_os" in + *linux*) +- # glibc <= 2.3.2 has a broken getgrouplist +- AC_TRY_RUN([ ++ ++AC_CACHE_CHECK([for a broken Linux getgrouplist API], ++ linux_getgrouplist_ok, ++ [ ++ AC_TRY_RUN([ + #include <unistd.h> + #include <sys/utsname.h> +-main() { +- /* glibc up to 2.3 has a broken getgrouplist */ ++ ++ int main() { ++ /* glibc up to 2.3 has a broken ++getgrouplist */ + #if defined(__GLIBC__) && defined(__GLIBC_MINOR__) +- int libc_major = __GLIBC__; +- int libc_minor = __GLIBC_MINOR__; ++ int libc_major = __GLIBC__; ++ int libc_minor = __GLIBC_MINOR__; ++ ++ if (libc_major < 2) ++ return 1; ++ if ((libc_major == 2) && (libc_minor <= 3)) ++ return 1; ++#endif ++ return 0; ++ } ++ ++ ], ++ [linux_getgrouplist_ok=yes], ++ [linux_getgrouplist_ok=no], ++ [linux_getgrouplist_ok=cross]) ++ ]) ++ ++ if test x"$linux_getgrouplist_ok" = x"yes"; then ++ AC_DEFINE(HAVE_GETGROUPLIST, 1, [Have good getgrouplist]) ++ fi ++ + +- if (libc_major < 2) +- exit(1); +- if ((libc_major == 2) && (libc_minor <= 3)) +- exit(1); +-#endif +- exit(0); +-} +-], [linux_getgrouplist_ok=yes], [linux_getgrouplist_ok=no]) +- if test x"$linux_getgrouplist_ok" = x"yes"; then +- AC_DEFINE(HAVE_GETGROUPLIST, 1, [Have good getgrouplist]) +- fi +- ;; +- *) +- AC_CHECK_FUNCS(getgrouplist) +- ;; + esac + + # diff --git a/tools/android/depends/samba/samba30-3.0.37-silence-receive-warning.patch b/tools/android/depends/samba/samba30-3.0.37-silence-receive-warning.patch new file mode 100644 index 0000000000..92b84336c8 --- /dev/null +++ b/tools/android/depends/samba/samba30-3.0.37-silence-receive-warning.patch @@ -0,0 +1,11 @@ +--- samba-3.0.37-clean/source/libsmb/clientgen.c 2009-09-30 05:21:56.000000000 -0700 ++++ samba-3.0.37/source/libsmb/clientgen.c 2010-11-18 21:56:06.874516928 -0800 +@@ -108,7 +108,7 @@ + + /* If the server is not responding, note that now */ + if (!ret) { +- DEBUG(0, ("Receiving SMB: Server stopped responding\n")); ++ DEBUG(1, ("Receiving SMB: Server stopped responding\n")); + cli->smb_rw_error = smb_read_error; + close(cli->fd); + cli->fd = -1; diff --git a/tools/android/depends/samba/samba30-3.0.37-vfs_default.c.patch b/tools/android/depends/samba/samba30-3.0.37-vfs_default.c.patch new file mode 100644 index 0000000000..7a640ecb85 --- /dev/null +++ b/tools/android/depends/samba/samba30-3.0.37-vfs_default.c.patch @@ -0,0 +1,16 @@ +--- samba-3.0.25borig/source/modules/vfs_default.c 2007-04-09 10:30:58.000000000 -0700 ++++ samba3025bfinal/source/modules/vfs_default.c 2007-07-24 12:18:07.000000000 -0700 +@@ -813,10 +813,11 @@ + + START_PROFILE(syscall_linux_setlease); + +-#ifdef LINUX ++#ifdef HAVE_KERNEL_OPLOCKS_LINUX + /* first set the signal handler */ +- if(linux_set_lease_sighandler(fd) == -1) ++ if(linux_set_lease_sighandler(fd) == -1) { + return -1; ++ } + + result = linux_setlease(fd, leasetype); + #else diff --git a/tools/android/depends/samba/samba30-3.0.37-wle-fix.patch b/tools/android/depends/samba/samba30-3.0.37-wle-fix.patch new file mode 100644 index 0000000000..8a41f455a3 --- /dev/null +++ b/tools/android/depends/samba/samba30-3.0.37-wle-fix.patch @@ -0,0 +1,101 @@ +diff -r -u samba-3.0.37-clean/source/libsmb/asn1.c samba-3.0.37/source/libsmb/asn1.c +--- samba-3.0.37-clean/source/libsmb/asn1.c 2009-09-30 05:21:56.000000000 -0700 ++++ samba-3.0.37/source/libsmb/asn1.c 2010-11-18 12:40:06.981517350 -0800 +@@ -261,6 +261,36 @@ + return asn1_read(data, v, 1); + } + ++/* peek to see if a tag is present */ ++/* this was not ported from samba and may not be identical to libsmb mainline */ ++BOOL asn1_peek_tag(ASN1_DATA *data, uint8 tag) ++{ ++ uint8 curtag; ++ ++ if (data->has_error) ++ return False; ++ ++ // overflow checking ++ if (data->ofs + 1 < data->ofs || data->ofs + 1 < 1) { ++ return False; ++ } ++ ++ // boundary checking ++ if (data->ofs + 1 > data->length) { ++ return False; ++ } ++ ++ memcpy( (void*)&curtag, data->data + data->ofs, 1); ++ ++ // don't move cursor ++ // don't set error ++ ++ if( tag != curtag ) ++ return False; ++ ++ return True; ++} ++ + /* start reading a nested asn1 structure */ + BOOL asn1_start_tag(ASN1_DATA *data, uint8 tag) + { +diff -r -u samba-3.0.37-clean/source/libsmb/clispnego.c samba-3.0.37/source/libsmb/clispnego.c +--- samba-3.0.37-clean/source/libsmb/clispnego.c 2009-09-30 05:21:56.000000000 -0700 ++++ samba-3.0.37/source/libsmb/clispnego.c 2010-11-18 12:52:54.833518134 -0800 +@@ -135,9 +135,16 @@ + + asn1_start_tag(&data,ASN1_APPLICATION(0)); + asn1_check_OID(&data,OID_SPNEGO); ++ ++ /* negTokenInit [0] NegTokenInit */ + asn1_start_tag(&data,ASN1_CONTEXT(0)); + asn1_start_tag(&data,ASN1_SEQUENCE(0)); + ++ /* mechTypes [0] MechTypeList OPTIONAL */ ++ ++ /* Not really optional, we depend on this to decide ++ * what mechanisms we have to work with. */ ++ + asn1_start_tag(&data,ASN1_CONTEXT(0)); + asn1_start_tag(&data,ASN1_SEQUENCE(0)); + for (i=0; asn1_tag_remaining(&data) > 0 && i < ASN1_MAX_OIDS-1; i++) { +@@ -150,7 +157,39 @@ + asn1_end_tag(&data); + + *principal = NULL; +- if (asn1_tag_remaining(&data) > 0) { ++ ++ /* ++ Win7 + Live Sign-in Assistant attaches a mechToken ++ ASN1_CONTEXT(2) to the negTokenInit packet ++ which breaks our negotiation if we just assume ++ the next tag is ASN1_CONTEXT(3). ++ */ ++ ++ if (asn1_peek_tag(&data, ASN1_CONTEXT(1))) { ++ uint8 flags; ++ ++ /* reqFlags [1] ContextFlags OPTIONAL */ ++ asn1_start_tag(&data, ASN1_CONTEXT(1)); ++ asn1_start_tag(&data, ASN1_BITFIELD); ++ while (asn1_tag_remaining(&data) > 0) { ++ asn1_read_uint8(&data, &flags); ++ } ++ asn1_end_tag(&data); ++ asn1_end_tag(&data); ++ } ++ ++ if (asn1_peek_tag(&data, ASN1_CONTEXT(2))) { ++ /* mechToken [2] OCTET STRING OPTIONAL */ ++ DATA_BLOB token; ++ asn1_start_tag(&data, ASN1_CONTEXT(2)); ++ asn1_read_OctetString(&data, &token); ++ asn1_end_tag(&data); ++ /* Throw away the token - not used. */ ++ data_blob_free(&token); ++ } ++ ++ if (asn1_peek_tag(&data, ASN1_CONTEXT(3))) { ++ /* mechListMIC [3] OCTET STRING OPTIONAL */ + asn1_start_tag(&data, ASN1_CONTEXT(3)); + asn1_start_tag(&data, ASN1_SEQUENCE(0)); + asn1_start_tag(&data, ASN1_CONTEXT(0)); diff --git a/tools/android/depends/samba/samba_android.patch b/tools/android/depends/samba/samba_android.patch new file mode 100644 index 0000000000..b48c0e7631 --- /dev/null +++ b/tools/android/depends/samba/samba_android.patch @@ -0,0 +1,220 @@ +--- source/lib/fault.c 2009-09-30 08:21:56.000000000 -0400 ++++ source/lib/fault.c 2012-05-11 00:55:11.115651420 -0400 +@@ -136,7 +136,7 @@ + #endif + #endif + +-#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) ++#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) && !defined(ANDROID) + /* On Linux we lose the ability to dump core when we change our user + * ID. We know how to dump core safely, so let's make sure we have our + * dumpable flag set. +--- source/lib/system.c 2009-09-30 08:21:56.000000000 -0400 ++++ source/lib/system.c 2012-05-11 00:56:25.965651373 -0400 +@@ -1065,7 +1065,7 @@ + new_pwd.pw_passwd = SMB_STRDUP("x"); + new_pwd.pw_uid = uid; + new_pwd.pw_gid = 100; +- new_pwd.pw_gecos = SMB_STRDUP("faked user"); ++// new_pwd.pw_gecos = SMB_STRDUP("faked user"); + new_pwd.pw_dir = SMB_STRDUP("/nodir"); + new_pwd.pw_shell = SMB_STRDUP("/bin/false"); + +@@ -1241,7 +1241,7 @@ + retval.pw_passwd = pwret->pw_passwd; + retval.pw_uid = pwret->pw_uid; + retval.pw_gid = pwret->pw_gid; +- unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos)); ++// unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos)); + unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir)); + unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell)); + +@@ -1264,7 +1264,7 @@ + retval.pw_passwd = pwret->pw_passwd; + retval.pw_uid = pwret->pw_uid; + retval.pw_gid = pwret->pw_gid; +- unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos)); ++// unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos)); + unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir)); + unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell)); + +--- source/lib/util_pw.c 2009-09-30 08:21:56.000000000 -0400 ++++ source/lib/util_pw.c 2012-05-11 00:55:43.485651400 -0400 +@@ -32,7 +32,7 @@ + ret->pw_passwd = talloc_strdup(ret, from->pw_passwd); + ret->pw_uid = from->pw_uid; + ret->pw_gid = from->pw_gid; +- ret->pw_gecos = talloc_strdup(ret, from->pw_gecos); ++// ret->pw_gecos = talloc_strdup(ret, from->pw_gecos); + ret->pw_dir = talloc_strdup(ret, from->pw_dir); + ret->pw_shell = talloc_strdup(ret, from->pw_shell); + return ret; +--- source/libads/dns.c 2009-09-30 08:21:56.000000000 -0400 ++++ source/libads/dns.c 2012-05-11 01:05:46.485651020 -0400 +@@ -38,6 +38,11 @@ + + #define MAX_DNS_PACKET_SIZE 0xffff + ++# define C_IN 1 ++# define T_A 1 ++# define T_NS 2 ++# define NS_HFIXEDSZ 12 ++# define NS_PACKETSZ 512 + #ifdef NS_HFIXEDSZ /* Bind 8/9 interface */ + #if !defined(C_IN) /* AIX 5.3 already defines C_IN */ + # define C_IN ns_c_in +@@ -45,18 +50,18 @@ + #if !defined(T_A) /* AIX 5.3 already defines T_A */ + # define T_A ns_t_a + #endif +-# define T_SRV ns_t_srv ++# define T_SRV 33 + #if !defined(T_NS) /* AIX 5.3 already defines T_NS */ +-# define T_NS ns_t_ns ++# define T_NS 2 + #endif + #else +-# ifdef HFIXEDSZ +-# define NS_HFIXEDSZ HFIXEDSZ +-# else +-# define NS_HFIXEDSZ sizeof(HEADER) +-# endif /* HFIXEDSZ */ ++//# ifdef HFIXEDSZ ++//# define NS_HFIXEDSZ HFIXEDSZ ++//# else ++//# define NS_HFIXEDSZ sizeof(HEADER) ++//# endif /* HFIXEDSZ */ + # ifdef PACKETSZ +-# define NS_PACKETSZ PACKETSZ ++# define NS_PACKETSZ 512 + # else /* 512 is usually the default */ + # define NS_PACKETSZ 512 + # endif /* PACKETSZ */ +--- source/passdb/passdb.c 2009-09-30 08:21:56.000000000 -0400 ++++ source/passdb/passdb.c 2012-05-11 00:57:08.295651347 -0400 +@@ -143,7 +143,7 @@ + /* Basic properties based upon the Unix account information */ + + pdb_set_username(user, pwd->pw_name, PDB_SET); +- pdb_set_fullname(user, pwd->pw_gecos, PDB_SET); ++// pdb_set_fullname(user, pwd->pw_gecos, PDB_SET); + pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT); + #if 0 + /* This can lead to a primary group of S-1-22-2-XX which +diff -ruN source/lib/iconv.c source/lib/iconv.c +--- source/lib/iconv.c 2009-09-30 08:21:56.000000000 -0400 ++++ source/lib/iconv.c 2012-05-11 02:13:02.365648475 -0400 +@@ -20,6 +20,8 @@ + */ + + #include "includes.h" ++//#include <stdint.h> ++//#include <asm/byteorder.h> + + /* + * We have to use strcasecmp here as the character conversions +@@ -489,6 +491,21 @@ + return 0; + } + ++#include <stdint.h> ++#include <asm/byteorder.h> ++ ++void swab(const void *from, void*to, ssize_t n) ++{ ++ ssize_t i; ++ ++ if (n < 0) ++ return; ++ ++ for (i = 0; i < (n/2)*2; i += 2) ++ *((uint16_t*)to+i) = __arch__swab16(*((uint16_t*)from+i)); ++} ++ ++ + static size_t iconv_swab(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) + { +diff -ruN source/lib/replace/system/passwd.h source/lib/replace/system/passwd.h +--- source/lib/replace/system/passwd.h 2009-09-30 08:21:56.000000000 -0400 ++++ source/lib/replace/system/passwd.h 2012-05-11 02:19:27.025648232 -0400 +@@ -60,8 +60,8 @@ + #include <compat.h> + #endif + +-#ifdef REPLACE_GETPASS +-#define getpass(prompt) getsmbpass((prompt)) ++#ifndef REPLACE_GETPASS ++#define getpass(prompt) NULL + #endif + + #ifndef NGROUPS_MAX +diff -ruN source/lib/system.c source/lib/system.c +--- source/lib/system.c 2012-05-11 00:56:25.965651373 -0400 ++++ source/lib/system.c 2012-05-11 02:22:37.945648112 -0400 +@@ -476,7 +476,8 @@ + #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64) + seekdir64(dirp, offset); + #else +- seekdir(dirp, offset); ++// seekdir64(dirp, offset); ++ return; + #endif + } + +@@ -489,7 +490,8 @@ + #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64) + return (long)telldir64(dirp); + #else +- return (long)telldir(dirp); ++// return (long)telldir(dirp); ++ return(0); + #endif + } + +@@ -985,17 +987,19 @@ + + void sys_setpwent(void) + { +- setpwent(); ++// setpwent(); + } + + struct passwd *sys_getpwent(void) + { +- return getpwent(); ++// return getpwent(); ++ return NULL; ++ + } + + void sys_endpwent(void) + { +- endpwent(); ++// endpwent(); + } + + /************************************************************************** +diff -ruN source/passdb/pdb_interface.c source/passdb/pdb_interface.c +--- source/passdb/pdb_interface.c 2009-09-30 08:21:56.000000000 -0400 ++++ source/passdb/pdb_interface.c 2012-05-11 02:22:29.085648117 -0400 +@@ -1380,8 +1380,8 @@ + } + + /* Primary group members */ +- setpwent(); +- while ((pwd = getpwent()) != NULL) { ++ sys_setpwent(); ++ while ((pwd = sys_getpwent()) != NULL) { + if (pwd->pw_gid == gid) { + if (!add_uid_to_array_unique(mem_ctx, pwd->pw_uid, + pp_uids, p_num)) { +@@ -1389,7 +1389,7 @@ + } + } + } +- endpwent(); ++ sys_endpwent(); + + /* Secondary group members */ + for (gr = grp->gr_mem; (*gr != NULL) && ((*gr)[0] != '\0'); gr += 1) { diff --git a/tools/android/depends/sqlite3/Makefile b/tools/android/depends/sqlite3/Makefile new file mode 100644 index 0000000000..f8208cd99d --- /dev/null +++ b/tools/android/depends/sqlite3/Makefile @@ -0,0 +1,45 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=sqlite +VERSION=3071000 +SOURCE=$(LIBNAME)-autoconf-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +export CXXFLAGS+=-DSQLITE_ENABLE_COLUMN_METADATA=1 +export CFLAGS+=-DSQLITE_TEMP_STORE=3 +export TCLLIBDIR=/dev/null +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared \ + --enable-threadsafe --disable-tcl --disable-readline \ + +LIBDYLIB=$(PLATFORM)/.libs/lib$(LIBNAME)3.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/tiff-native/Makefile b/tools/android/depends/tiff-native/Makefile new file mode 100644 index 0000000000..cabf30f2ae --- /dev/null +++ b/tools/android/depends/tiff-native/Makefile @@ -0,0 +1,42 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=tiff +VERSION=3.8.2 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) config/; \ + ./configure --prefix=$(PREFIX) + +LIBDYLIB=$(PLATFORM)/libtiff/.libs/lib$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/tiff/Makefile b/tools/android/depends/tiff/Makefile new file mode 100644 index 0000000000..2f02c9bb40 --- /dev/null +++ b/tools/android/depends/tiff/Makefile @@ -0,0 +1,41 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=tiff +VERSION=3.8.2 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) config/; \ + ./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared + +LIBDYLIB=$(PLATFORM)/libtiff/.libs/lib$(LIBNAME).a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/tinyxml/Makefile b/tools/android/depends/tinyxml/Makefile new file mode 100644 index 0000000000..19239a69b3 --- /dev/null +++ b/tools/android/depends/tinyxml/Makefile @@ -0,0 +1,39 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +# lib name, version +LIBNAME=tinyxml +VERSION=2.6.2_2 +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) --host=$(HOST) --disable-shared + + +LIBDYLIB=$(PLATFORM)/src/.libs/libtinyxml.a + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(AUTORECONF) -vif + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -j 1 -C $(PLATFORM)/src + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM)/src install + touch $@ + +clean: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/depends/xbmc/Makefile b/tools/android/depends/xbmc/Makefile new file mode 100644 index 0000000000..38ca256899 --- /dev/null +++ b/tools/android/depends/xbmc/Makefile @@ -0,0 +1,39 @@ +-include ../Makefile.include + +SOURCE=../../../../ + +export PYTHON_VERSION=2.6 +export PYTHON_LDFLAGS=-L$(PREFIX)/lib -lpython$(PYTHON_VERSION) -lc -ldl -lm -lexpat -lffi -lintl +export PYTHON_CPPFLAGS=-I$(PREFIX)/include/python$(PYTHON_VERSION) +export PYTHON_SITE_PKG=$(PREFIX)/lib/python$(PYTHON_VERSION)/site-packages +export PYTHON_NOVERSIONCHECK=no-check +export USE_TEXTUREPACKER_NATIVE_ROOT=$(NATIVEPREFIX) +export MYSQL_CONFIG=$(PREFIX)/bin/mysql_config +export LIBS+=-lcrystax + +# configuration settings +CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) build-aux/ ;\ + ./configure --prefix=$(PREFIX) --host=$(HOST) \ + --enable-neon --enable-gles --enable-debug \ + --disable-sdl --disable-x11 --disable-xrandr \ + --disable-optical-drive --disable-joystick --disable-optimizations \ + --enable-shared-lib --disable-alsa + + +all: $(SOURCE)/libxbmc.so + + +$(SOURCE)/libxbmc.so: + cd $(SOURCE); ./bootstrap + cd $(SOURCE); $(CONFIGURE) + cd $(SOURCE); $(MAKE) + cd $(SOURCE); $(MAKE) apk + +../Makefile.include: + $(error Please run edit and run setup-sdk.sh) + +clean: + cd $(SOURCE); $(MAKE) clean + +distclean: + cd $(SOURCE); $(MAKE) clean diff --git a/tools/android/depends/yajl/Makefile b/tools/android/depends/yajl/Makefile new file mode 100644 index 0000000000..03965dc68b --- /dev/null +++ b/tools/android/depends/yajl/Makefile @@ -0,0 +1,52 @@ +include ../Makefile.include +DEPS= ../Makefile.include Makefile static.patch + +# lib name, version +LIBNAME=yajl +VERSION=2.0.1 +SOURCE=lloyd-$(LIBNAME)-f4b2b1a +ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +CMAKE=$(PREFIX)/bin/cmake +# configuration settings +LIBDYLIB=$(PLATFORM)/build/$(LIBNAME)-$(VERSION)/lib/libyajl.a + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + sed -ie "s|ADD_CUSTOM_TARGET|#ADD_CUSTOM_TARGET|g" "$(PLATFORM)/CMakeLists.txt" + sed -ie "s|./run_tests.sh|#./run_tests.sh|g" "$(PLATFORM)/CMakeLists.txt" + sed -ie "s|WORKING_DIRECTORY|#WORKING_DIRECTORY|g" "$(PLATFORM)/CMakeLists.txt" + sed -ie "s|ADD_SUBDIRECTORY(reformatter)|#ADD_SUBDIRECTORY(reformatter)|g" "$(PLATFORM)/CMakeLists.txt" + cd $(PLATFORM); patch -p0 < ../static.patch + cd $(PLATFORM); patch -p0 < ../shared.patch + cd $(PLATFORM); rm -rf build; mkdir -p build + cd $(PLATFORM)/build; CC=$(CC) CXX=$(CXX) cmake \ + -DCMAKE_C_FLAGS:STRING="$(CPPFLAGS) $(CFLAGS)" \ + -DCMAKE_CXX_FLAGS:STRING="$(CPPFLAGS) $(CXXFLAGS)" \ + -DCMAKE_INCLUDE_PATH=$(PREFIX)/include \ + -DCMAKE_LIBRARY_PATH=$(PREFIX)/lib \ + -DCMAKE_INSTALL_NAME_DIR=$(PREFIX)/lib \ + -DCMAKE_INSTALL_PREFIX=$(PREFIX) \ + -DCMAKE_SYSTEM_NAME=Linux \ + -DCMAKE_FIND_ROOT_PATH=$(platform_sdk_path) .. + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -C $(PLATFORM)/build + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM)/build install + touch $@ + +clean: + $(MAKE) -C $(PLATFORM)/build clean + rm -f .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) diff --git a/tools/android/depends/yajl/shared.patch b/tools/android/depends/yajl/shared.patch new file mode 100644 index 0000000000..13ea0c7464 --- /dev/null +++ b/tools/android/depends/yajl/shared.patch @@ -0,0 +1,20 @@ +--- src/CMakeLists.txt.orig 2012-06-22 21:09:34.000000000 +0200 ++++ src/CMakeLists.txt 2012-06-22 21:11:49.000000000 +0200 +@@ -40,6 +40,8 @@ + + TARGET_LINK_LIBRARIES(yajl_s m) + ++TARGET_LINK_LIBRARIES(yajl m) ++ + #### setup shared library version number + SET_TARGET_PROPERTIES(yajl PROPERTIES + DEFINE_SYMBOL YAJL_SHARED +@@ -79,7 +79,7 @@ + IF(NOT WIN32) + # at build time you may specify the cmake variable LIB_SUFFIX to handle + # 64-bit systems which use 'lib64' +- INSTALL(TARGETS yajl LIBRARY DESTINATION lib${LIB_SUFFIX}) ++# INSTALL(TARGETS yajl LIBRARY DESTINATION lib${LIB_SUFFIX}) + INSTALL(TARGETS yajl_s ARCHIVE DESTINATION lib${LIB_SUFFIX}) + INSTALL(FILES ${PUB_HDRS} DESTINATION include/yajl) + INSTALL(FILES ${incDir}/yajl_version.h DESTINATION include/yajl) diff --git a/tools/android/depends/yajl/static.patch b/tools/android/depends/yajl/static.patch new file mode 100644 index 0000000000..ca1a9433ef --- /dev/null +++ b/tools/android/depends/yajl/static.patch @@ -0,0 +1,19 @@ +--- src/CMakeLists.txt.orig 2011-04-28 04:48:41.000000000 +0200 ++++ src/CMakeLists.txt 2012-06-22 21:07:59.000000000 +0200 +@@ -38,12 +38,16 @@ + + ADD_LIBRARY(yajl SHARED ${SRCS} ${HDRS} ${PUB_HDRS}) + ++TARGET_LINK_LIBRARIES(yajl_s m) ++ + #### setup shared library version number + SET_TARGET_PROPERTIES(yajl PROPERTIES + DEFINE_SYMBOL YAJL_SHARED + SOVERSION ${YAJL_MAJOR} + VERSION ${YAJL_MAJOR}.${YAJL_MINOR}.${YAJL_MICRO}) + ++SET_TARGET_PROPERTIES(yajl_s PROPERTIES OUTPUT_NAME yajl) ++ + #### ensure a .dylib has correct absolute installation paths upon installation + IF(APPLE) + MESSAGE("INSTALL_NAME_DIR: ${CMAKE_INSTALL_PREFIX}/lib") diff --git a/tools/android/depends/yasm/Makefile b/tools/android/depends/yasm/Makefile new file mode 100644 index 0000000000..eb4c4e0e5e --- /dev/null +++ b/tools/android/depends/yasm/Makefile @@ -0,0 +1,41 @@ +NATIVE_BUILD=1 +include ../Makefile.include +DEPS= ../Makefile.include Makefile + +APPNAME=yasm +VERSION=1.1.0 +SOURCE=$(APPNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.gz + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) + +APP=$(PLATFORM)/$(APPNAME) + +CLEAN_FILES=$(ARCHIVE) $(PLATFORM) + +all: .installed-$(PLATFORM) + +$(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) + -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) + cd $(PLATFORM); $(CONFIGURE) + +$(APP): $(PLATFORM) + $(MAKE) -C $(PLATFORM) + +.installed-$(PLATFORM): $(APP) + $(MAKE) -C $(PLATFORM) install + rm -rf $(PREFIX)/lib/libyasm.a + touch $@ + +clean: + $(MAKE) -C $(PLATFORM) clean + rm .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/android/packaging/.gitignore b/tools/android/packaging/.gitignore new file mode 100644 index 0000000000..7132ab579f --- /dev/null +++ b/tools/android/packaging/.gitignore @@ -0,0 +1,8 @@ +/images/* +xbmc/assets/* +xbmc/lib/* +xbmc/libs/* +xbmc/obj/* +xbmc/src/org/xbmc/xbmc/*.class +xbmc/classes.dex +tmp/* diff --git a/tools/android/packaging/Makefile b/tools/android/packaging/Makefile new file mode 100644 index 0000000000..0ba5893955 --- /dev/null +++ b/tools/android/packaging/Makefile @@ -0,0 +1,93 @@ +include ../depends/Makefile.include + +OBJS = libcurl.so \ + librtmp.so libmad.so \ + libafpclient.so \ + libshairport.so libplist.so \ + libxbogg.so libxbvorbis.so libxbvorbisfile.so libxbFLAC.so libxbmpeg2.so \ + libxbmpeg2convert.so + +PLATFORM_OBJS = + +XBMCROOT = $(shell cd $(CURDIR)/../../..; pwd) +COPYDIRS = system addons language media +AAPT = $(SDKROOT)/platform-tools/aapt +DX = $(SDKROOT)/platform-tools/dx +GCC_VERSION=$(shell $(CC) -dumpversion) + +X86OVERRIDES=XBMC_OVERRIDE_HOST=i686-android-linux XBMC_OVERRIDE_TOOLCHAIN=$(XBMC_X86_TOOLCHAIN) +ARMOVERRIDES=XBMC_OVERRIDE_HOST=arm-linux-androideabi XBMC_OVERRIDE_TOOLCHAIN=$(XBMC_ARM_TOOLCHAIN) + +#this fixes a android ndk fuckup where the pathes to +#prebuilt stuff follow different name shemes for +#arm and x86 +ifeq ($(findstring x86,$(PLATFORM)),x86) +GDBPATH=$(NDKROOT)/toolchains/$(PLATFORM)-$(GCC_VERSION)/prebuilt/gdbserver +else +GDBPATH=$(NDKROOT)/toolchains/$(HOST)-$(GCC_VERSION)/prebuilt/gdbserver +endif + +all: package +SRCLIBS = $(addprefix $(PREFIX)/lib/,$(OBJS)) $(addprefix $(PREFIX)/lib/$(SDK_PLATFORM)/,$(PLATFORM_OBJS)) +DSTLIBS = $(PLATFORM)/lib/libxbmc.so $(addprefix $(PLATFORM)/lib/,$(OBJS)) $(addprefix $(PLATFORM)/lib/,$(PLATFORM_OBJS)) +libs= $(DSTLIBS) + +multi: x86 arm + @cp images/xbmcapp-debug-skeleton.apk images/xbmcapp-debug-multi-unaligned.apk + @cd xbmc; zip -r -q ../images/xbmcapp-debug-multi-unaligned.apk lib/ assets + @jarsigner -keystore ~/.android/debug.keystore -storepass android images/xbmcapp-debug-multi-unaligned.apk androiddebugkey + @$(SDKROOT)/tools/zipalign -f 4 images/xbmcapp-debug-multi-unaligned.apk $(XBMCROOT)/xbmcapp-multi-debug.apk + @rm images/xbmcapp-debug-multi-unaligned.apk + @echo "$(XBMCROOT)/xbmcapp-multi-debug.apk created" + +package: extras + @cp images/xbmcapp-debug-skeleton.apk images/xbmcapp-debug-$(PLATFORM)-unaligned.apk + @javac xbmc/src/org/xbmc/xbmc/xbmc.java + @$(DX) --dex --output=xbmc/classes.dex xbmc/src/org/xbmc/xbmc/ + @cd xbmc; zip -r -q ../images/xbmcapp-debug-$(PLATFORM)-unaligned.apk lib/$(PLATFORM) assets classes.dex + @jarsigner -keystore ~/.android/debug.keystore -storepass android images/xbmcapp-debug-$(PLATFORM)-unaligned.apk androiddebugkey + @$(SDKROOT)/tools/zipalign -f 4 images/xbmcapp-debug-$(PLATFORM)-unaligned.apk $(XBMCROOT)/xbmcapp-$(PLATFORM)-debug.apk + @rm images/xbmcapp-debug-$(PLATFORM)-unaligned.apk + @echo "$(XBMCROOT)/xbmcapp-$(PLATFORM)-debug.apk created" + +extras: libs + rm -rf xbmc/assets/python2.6/lib/ + mkdir -p xbmc/assets xbmc/res xbmc/assets/python2.6/lib/ + cp -rfp $(PREFIX)/share/xbmc/* ./xbmc/assets + find `pwd`/xbmc/assets/system/ -name "*.so" -exec rm {} \; + find `pwd`/xbmc/assets/addons/skin.*/media/* -not -iname "Textures.xbt" -exec rm {} \; + cp -rfp $(PREFIX)/lib/python2.6 xbmc/assets/python2.6/lib/ + cd xbmc/assets/python2.6/lib/python2.6/; rm -rf test config lib-dynload + mkdir -p tmp/res; $(AAPT) c -S xbmc/res -C tmp/res; cp -r -n xbmc/res tmp/ || true + $(AAPT) p -f -I $(SDKROOT)/platforms/android-10/android.jar -S tmp/res/ -M xbmc/AndroidManifest.xml -F images/xbmcapp-debug-skeleton.apk + @rm -rf tmp/ + +libs: $(PREFIX)/lib/xbmc/libxbmc.so + rm -rf xbmc/lib/$(PLATFORM) xbmc/libs/$(PLATFORM) xbmc/obj/local/$(PLATFORM) + mkdir -p xbmc/lib/$(PLATFORM) images xbmc/assets/python2.6/lib/ xbmc/libs/$(PLATFORM) xbmc/obj/local/$(PLATFORM) + cp -fp $(SRCLIBS) xbmc/obj/local/$(PLATFORM)/ + cp -fp $(PREFIX)/lib/xbmc/libxbmc.so xbmc/obj/local/$(PLATFORM)/ + find $(PREFIX)/lib/xbmc/system -name "*.so" -exec cp -fp {} xbmc/obj/local/$(PLATFORM)/ \; + cd xbmc/obj/local/$(PLATFORM)/; find . -name "*.so" -not -name "lib*.so" | sed "s/\.\///" | xargs -I@ mv @ lib@ + cp -fp xbmc/obj/local/$(PLATFORM)/*.so xbmc/lib/$(PLATFORM)/ + $(STRIP) --strip-unneeded xbmc/lib/$(PLATFORM)/*.so + install -p $(GDBPATH) ./xbmc/libs/$(PLATFORM)/gdbserver + echo "set solib-search-path ./obj/local/$(PLATFORM)" > ./xbmc/libs/$(PLATFORM)/gdb.setup + echo "directory $(TOOLCHAIN)/sysroot/usr/include $(NDKROOT)/sources/android/native_app_glue" \ + "$(NDKROOT)/sources/cxx-stl/gnu-libstdc++/include/$(GCC_VERSION) $(XBMCROOT) $(PREFIX)/include jni" >> ./xbmc/libs/$(PLATFORM)/gdb.setup + cp -fp xbmc/libs/$(PLATFORM)/* xbmc/lib/$(PLATFORM) + +$(PREFIX)/lib/xbmc/libxbmc.so: $(SRCLIBS) + $(MAKE) -C ../depends/xbmc + +$(SRCLIBS): + +arm: armeabi-v7a + +armeabi-v7a: $(XBMC_ARM_TOOLCHAIN) force + XBMC_OVERRIDE_PLATFORM=$@ $(ARMOVERRIDES) $(MAKE) package + +x86: $(XBMC_X86_TOOLCHAIN) force + XBMC_OVERRIDE_PLATFORM=$@ $(X86OVERRIDES) $(MAKE) package + +.PHONY: arm armeabi-v7a x86 force extras libs diff --git a/tools/android/packaging/xbmc/AndroidManifest.xml b/tools/android/packaging/xbmc/AndroidManifest.xml new file mode 100644 index 0000000000..e85a63d950 --- /dev/null +++ b/tools/android/packaging/xbmc/AndroidManifest.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- BEGIN_INCLUDE(manifest) --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.xbmc.xbmc" + android:versionCode="1" + android:versionName="1.0"> + + <!-- This is the platform API where NativeActivity was introduced. --> + <uses-sdk android:minSdkVersion="10" /> + + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.WAKE_LOCK" /> + + <application android:icon="@drawable/ic_launcher" android:debuggable="true" android:label="@string/app_name" android:hasCode="true"> + + <!-- Our activity is the built-in NativeActivity framework class. + This will take care of integrating with our NDK code. --> + <activity android:name="android.app.NativeActivity" + android:label="XBMC" + android:configChanges="orientation|keyboardHidden" + android:theme="@android:style/Theme.NoTitleBar.Fullscreen" + android:screenOrientation="landscape" + android:finishOnTaskLaunch="true" + android:launchMode="singleInstance"> + <!-- Tell NativeActivity the name of or .so --> + <meta-data android:name="android.app.lib_name" + android:value="xbmc" /> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest> +<!-- END_INCLUDE(manifest) --> + diff --git a/tools/android/packaging/xbmc/jni/Android.mk b/tools/android/packaging/xbmc/jni/Android.mk new file mode 100644 index 0000000000..a11b30a6ec --- /dev/null +++ b/tools/android/packaging/xbmc/jni/Android.mk @@ -0,0 +1,3 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE := xbmc diff --git a/tools/android/packaging/xbmc/jni/Application.mk b/tools/android/packaging/xbmc/jni/Application.mk new file mode 100644 index 0000000000..b528a661be --- /dev/null +++ b/tools/android/packaging/xbmc/jni/Application.mk @@ -0,0 +1,5 @@ +APP_PLATFORM := android-9 +APP_OPTIM = debug +APP_ABI := armeabi-v7a +# This would support both ARVMv5TE and ARMv7 +#APP_ABI := armeabi armeabi-v7a diff --git a/tools/android/packaging/xbmc/res/drawable-hdpi/ic_launcher.png b/tools/android/packaging/xbmc/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000000..d7f7e958cc --- /dev/null +++ b/tools/android/packaging/xbmc/res/drawable-hdpi/ic_launcher.png diff --git a/tools/android/packaging/xbmc/res/drawable-ldpi/ic_launcher.png b/tools/android/packaging/xbmc/res/drawable-ldpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000000..4a6e213e40 --- /dev/null +++ b/tools/android/packaging/xbmc/res/drawable-ldpi/ic_launcher.png diff --git a/tools/android/packaging/xbmc/res/drawable-mdpi/ic_launcher.png b/tools/android/packaging/xbmc/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000000..7eaa3dae63 --- /dev/null +++ b/tools/android/packaging/xbmc/res/drawable-mdpi/ic_launcher.png diff --git a/tools/android/packaging/xbmc/res/layout/main.xml b/tools/android/packaging/xbmc/res/layout/main.xml new file mode 100644 index 0000000000..bc12cd8231 --- /dev/null +++ b/tools/android/packaging/xbmc/res/layout/main.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" > + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/hello" /> + +</LinearLayout>
\ No newline at end of file diff --git a/tools/android/packaging/xbmc/res/values/strings.xml b/tools/android/packaging/xbmc/res/values/strings.xml new file mode 100644 index 0000000000..f938cf354d --- /dev/null +++ b/tools/android/packaging/xbmc/res/values/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + + <string name="hello">bruhahaha</string> + <string name="app_name">XBMC</string> + +</resources>
\ No newline at end of file diff --git a/tools/android/packaging/xbmc/src/org/xbmc/xbmc/xbmc.java b/tools/android/packaging/xbmc/src/org/xbmc/xbmc/xbmc.java new file mode 100644 index 0000000000..c086394556 --- /dev/null +++ b/tools/android/packaging/xbmc/src/org/xbmc/xbmc/xbmc.java @@ -0,0 +1 @@ +class xbmc{}
\ No newline at end of file diff --git a/tools/darwin/depends/configure.in b/tools/darwin/depends/configure.in index 4fdc4bb242..26bae84760 100644 --- a/tools/darwin/depends/configure.in +++ b/tools/darwin/depends/configure.in @@ -36,10 +36,13 @@ case $use_darwin in if test "$use_arch" = "armv7"; then AC_MSG_ERROR(error in configure of --with-arch=$use_arch) fi - found_sdk_version=[`$use_xcodebuild -showsdks | grep macosx | sort | tail -n 1 | awk '{ print $4}'`] + found_sdk_version=[`$use_xcodebuild -showsdks | grep macosx | sort | tail -n 1 | grep -oE 'macosx[0-9.0-9]+' | cut -c 7-$NF`] use_sdk="${use_sdk:-$found_sdk_version}" case $use_sdk in - 10.*);; + 10.5);; + 10.6);; + 10.7);; + 10.8) use_sdk=10.7;; *) AC_MSG_ERROR(error in configure of --with-sdk=$use_sdk) esac diff --git a/tools/darwin/packaging/xbmc-atv2/mkdeb-xbmc-atv2.sh b/tools/darwin/packaging/xbmc-atv2/mkdeb-xbmc-atv2.sh index b3953e35e7..c5fd74ed0d 100755 --- a/tools/darwin/packaging/xbmc-atv2/mkdeb-xbmc-atv2.sh +++ b/tools/darwin/packaging/xbmc-atv2/mkdeb-xbmc-atv2.sh @@ -45,7 +45,7 @@ fi PACKAGE=org.xbmc.xbmc-atv2 VERSION=12.0 -REVISION=0~alpha4 +REVISION=0~alpha5 ARCHIVE=${PACKAGE}_${VERSION}-${REVISION}_iphoneos-arm.deb echo Creating $PACKAGE package version $VERSION revision $REVISION diff --git a/tools/darwin/packaging/xbmc-ios/mkdeb-xbmc-ios.sh b/tools/darwin/packaging/xbmc-ios/mkdeb-xbmc-ios.sh index 808158d540..34a0f8b7d7 100755 --- a/tools/darwin/packaging/xbmc-ios/mkdeb-xbmc-ios.sh +++ b/tools/darwin/packaging/xbmc-ios/mkdeb-xbmc-ios.sh @@ -46,7 +46,7 @@ fi PACKAGE=org.xbmc.xbmc-ios VERSION=12.0 -REVISION=0~alpha4 +REVISION=0~alpha5 ARCHIVE=${PACKAGE}_${VERSION}-${REVISION}_iphoneos-arm.deb echo Creating $PACKAGE package version $VERSION revision $REVISION diff --git a/xbmc-xrandr.c b/xbmc-xrandr.c index b54b253845..3c686e2059 100644 --- a/xbmc-xrandr.c +++ b/xbmc-xrandr.c @@ -909,7 +909,6 @@ crtc_can_use_transform (crtc_t *crtc, XTransform *transform) return True; return False; } -#endif /* * Report only rotations that are supported by all crtcs @@ -936,6 +935,7 @@ output_rotations (output_t *output) } return rotation; } +#endif static Bool output_can_use_rotation (output_t *output, Rotation rotation) @@ -2999,7 +2999,7 @@ main (int argc, char **argv) Atom *props; int j, k, nprop; Bool *mode_shown; - Rotation rotations = output_rotations (output); +// Rotation rotations = output_rotations (output); printf (" <output name=\"%s\" connected=\"%s\"", output_info->name, connection[output_info->connection]); if (mode) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index df84f8a5bf..a330c3e34a 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -25,9 +25,9 @@ #include "interfaces/Builtins.h" #include "utils/Variant.h" #include "utils/Splash.h" -#include "input/KeyboardLayoutConfiguration.h" #include "LangInfo.h" #include "Util.h" +#include "URL.h" #include "guilib/TextureManager.h" #include "cores/dvdplayer/DVDFileInfo.h" #include "cores/AudioEngine/AEFactory.h" @@ -142,9 +142,7 @@ #include "music/karaoke/GUIDialogKaraokeSongSelector.h" #include "music/karaoke/GUIWindowKaraokeLyrics.h" #endif -#include "guilib/GUIFontTTF.h" #include "network/Network.h" -#include "storage/IoSupport.h" #include "network/Zeroconf.h" #include "network/ZeroconfBrowser.h" #ifndef _LINUX @@ -235,7 +233,7 @@ #include "settings/GUIDialogContentSettings.h" #include "video/dialogs/GUIDialogVideoScan.h" #include "dialogs/GUIDialogBusy.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "dialogs/GUIDialogKeyboardGeneric.h" #include "dialogs/GUIDialogYesNo.h" #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogProgress.h" @@ -457,7 +455,7 @@ bool CApplication::OnEvent(XBMC_Event& newEvent) { case XBMC_QUIT: if (!g_application.m_bStop) - g_application.getApplicationMessenger().Quit(); + CApplicationMessenger::Get().Quit(); break; case XBMC_KEYDOWN: g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym)); @@ -501,7 +499,7 @@ bool CApplication::OnEvent(XBMC_Event& newEvent) } break; case XBMC_USEREVENT: - g_application.getApplicationMessenger().UserEvent(newEvent.user.code); + CApplicationMessenger::Get().UserEvent(newEvent.user.code); break; case XBMC_APPCOMMAND: return g_application.OnAppCommand(newEvent.appcommand.action); @@ -509,14 +507,6 @@ bool CApplication::OnEvent(XBMC_Event& newEvent) return true; } -// This function does not return! -void CApplication::FatalErrorHandler(bool WindowSystemInitialized, bool MapDrives, bool InitNetwork) -{ - fprintf(stderr, "Fatal error encountered, aborting\n"); - fprintf(stderr, "Error log at %sxbmc.log\n", g_settings.m_logFolder.c_str()); - abort(); -} - extern "C" void __stdcall init_emu_environ(); extern "C" void __stdcall update_emu_environ(); @@ -613,6 +603,12 @@ bool CApplication::Create() CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Linux (%s, %s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetLinuxDistro().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__); #elif defined(_WIN32) CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: %s. Built on %s (compiler %i)", g_infoManager.GetVersion().c_str(), g_sysinfo.GetKernelVersion().c_str(), __DATE__, _MSC_VER); +#if defined(__arm__) + if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON) + CLog::Log(LOGNOTICE, "ARM Features: Neon enabled"); + else + CLog::Log(LOGNOTICE, "ARM Features: Neon disabled"); +#endif CLog::Log(LOGNOTICE, g_cpuInfo.getCPUModel().c_str()); CLog::Log(LOGNOTICE, CWIN32Util::GetResInfoString()); CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted"); @@ -662,7 +658,7 @@ bool CApplication::Create() if (!CAEFactory::LoadEngine()) { CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine"); - FatalErrorHandler(true, true, true); + return false; } CLog::Log(LOGNOTICE, "load settings..."); @@ -670,7 +666,10 @@ bool CApplication::Create() g_guiSettings.Initialize(); // Initialize default Settings - don't move g_powerManager.SetDefaults(); if (!g_settings.Load()) - FatalErrorHandler(true, true, true); + { + CLog::Log(LOGFATAL, "%s: Failed to reset settings", __FUNCTION__); + return false; + } CLog::Log(LOGINFO, "creating subdirectories"); CLog::Log(LOGINFO, "userdata folder: %s", g_settings.GetProfileUserDataFolder().c_str()); @@ -699,13 +698,16 @@ bool CApplication::Create() CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str()); if (!g_localizeStrings.Load(strLanguagePath, strLanguage)) - FatalErrorHandler(false, false, true); + { + CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str()); + return false; + } // start the AudioEngine if (!CAEFactory::StartEngine()) { CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine"); - FatalErrorHandler(true, true, true); + return false; } // restore AE's previous volume state @@ -721,7 +723,7 @@ bool CApplication::Create() if (!CAddonMgr::Get().Init()) { CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr"); - FatalErrorHandler(true, true, true); + return false; } g_peripherals.Initialise(); @@ -853,7 +855,7 @@ bool CApplication::CreateGUI() // The key mappings may already have been loaded by a peripheral CLog::Log(LOGINFO, "load keymapping"); if (!CButtonTranslator::GetInstance().Load()) - FatalErrorHandler(false, false, true); + return false; int iResolution = g_graphicsContext.GetVideoResolution(); CLog::Log(LOGINFO, "GUI format %ix%i %s", @@ -967,7 +969,10 @@ bool CApplication::InitDirectoriesLinux() CSpecialProtocol::SetHomePath(userHome + "/.xbmc"); CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata"); - CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp"); + CStdString strTempPath = userHome; + strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp"); + if (getenv("XBMC_TEMP")) + strTempPath = getenv("XBMC_TEMP"); CSpecialProtocol::SetTempPath(strTempPath); URIUtils::AddSlashAtEnd(strTempPath); @@ -986,7 +991,10 @@ bool CApplication::InitDirectoriesLinux() CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data")); CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata")); - CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp"); + CStdString strTempPath = xbmcPath; + strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp"); + if (getenv("XBMC_TEMP")) + strTempPath = getenv("XBMC_TEMP"); CSpecialProtocol::SetTempPath(strTempPath); CreateUserDirs(); @@ -1024,7 +1032,7 @@ bool CApplication::InitDirectoriesOSX() fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf"; setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0); #endif - + // setup path to our internal dylibs so loader can find them CStdString frameworksPath = CUtil::GetFrameworksPath(); CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath); @@ -1206,12 +1214,12 @@ bool CApplication::Initialize() g_windowManager.Add(new CGUIWindowLoginScreen); // window id = 29 g_windowManager.Add(new CGUIWindowSettingsProfile); // window id = 34 g_windowManager.Add(new CGUIWindowAddonBrowser); // window id = 40 - g_windowManager.Add(new CGUIWindowScreensaverDim); // window id = 97 + g_windowManager.Add(new CGUIWindowScreensaverDim); // window id = 97 g_windowManager.Add(new CGUIWindowDebugInfo); // window id = 98 g_windowManager.Add(new CGUIWindowPointer); // window id = 99 g_windowManager.Add(new CGUIDialogYesNo); // window id = 100 g_windowManager.Add(new CGUIDialogProgress); // window id = 101 - g_windowManager.Add(new CGUIDialogKeyboard); // window id = 103 + g_windowManager.Add(new CGUIDialogKeyboardGeneric); // window id = 103 g_windowManager.Add(new CGUIDialogVolumeBar); // window id = 104 g_windowManager.Add(new CGUIDialogSeekBar); // window id = 115 g_windowManager.Add(new CGUIDialogSubMenu); // window id = 105 @@ -1290,7 +1298,7 @@ bool CApplication::Initialize() if (!LoadSkin(g_guiSettings.GetString("lookandfeel.skin")) && !LoadSkin(DEFAULT_SKIN)) { CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", DEFAULT_SKIN); - FatalErrorHandler(true, true, true); + return false; } if (g_advancedSettings.m_splashImage) @@ -1329,7 +1337,7 @@ bool CApplication::Initialize() CLog::Log(LOGINFO, "removing tempfiles"); CUtil::RemoveTempFiles(); - // if the user shutoff the xbox during music scan + // if the user shutoff the system during music scan // restore the settings if (g_settings.m_bMyMusicIsScanning) { @@ -1367,6 +1375,100 @@ bool CApplication::Initialize() return true; } +bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/) +{ + bool ret = true; + bool oldSetting = false; + + switch(eServer) + { + case ES_WEBSERVER: + oldSetting = g_guiSettings.GetBool("services.webserver"); + g_guiSettings.SetBool("services.webserver", bStart); + + if (bStart) + ret = StartWebServer(); + else + StopWebServer(); + + if (!ret) + { + g_guiSettings.SetBool("services.webserver", oldSetting); + } + break; + case ES_AIRPLAYSERVER: + oldSetting = g_guiSettings.GetBool("services.esenabled"); + g_guiSettings.SetBool("services.airplay", bStart); + + if (bStart) + ret = StartAirplayServer(); + else + StopAirplayServer(bWait); + + if (!ret) + { + g_guiSettings.SetBool("services.esenabled", oldSetting); + } + break; + case ES_JSONRPCSERVER: + oldSetting = g_guiSettings.GetBool("services.esenabled"); + g_guiSettings.SetBool("services.esenabled", bStart); + + if (bStart) + ret = StartJSONRPCServer(); + else + StopJSONRPCServer(bWait); + + if (!ret) + { + g_guiSettings.SetBool("services.esenabled", oldSetting); + } + break; + case ES_UPNPSERVER: + g_guiSettings.SetBool("services.upnpserver", bStart); + if (bStart) + StartUPnPServer(); + else + StopUPnPServer(); + break; + case ES_UPNPRENDERER: + g_guiSettings.SetBool("services.upnprenderer", bStart); + if (bStart) + StartUPnPRenderer(); + else + StopUPnPRenderer(); + break; + case ES_EVENTSERVER: + oldSetting = g_guiSettings.GetBool("services.esenabled"); + g_guiSettings.SetBool("services.esenabled", bStart); + + if (bStart) + ret = StartEventServer(); + else + StopEventServer(bWait, false); + + if (!ret) + { + g_guiSettings.SetBool("services.esenabled", oldSetting); + } + + break; + case ES_ZEROCONF: + g_guiSettings.SetBool("services.zeroconf", bStart); + if (bStart) + StartZeroconf(); + else + StopZeroconf(); + break; + default: + ret = false; + break; + } + g_settings.Save(); + + return ret; +} + bool CApplication::StartWebServer() { #ifdef HAS_WEB_SERVER @@ -1385,7 +1487,7 @@ bool CApplication::StartWebServer() bool started = false; if (m_WebServer.Start(webPort, g_guiSettings.GetString("services.webserverusername"), g_guiSettings.GetString("services.webserverpassword"))) { - std::map<std::string, std::string> txt; + std::map<std::string, std::string> txt; started = true; // publish web frontend and API services #ifdef HAS_WEB_INTERFACE @@ -1400,7 +1502,7 @@ bool CApplication::StartWebServer() } #ifdef HAS_HTTPAPI if (g_settings.m_HttpApiBroadcastLevel >= 1) - getApplicationMessenger().HttpApi("broadcastlevel; StartUp;1"); + CApplicationMessenger::Get().HttpApi("broadcastlevel; StartUp;1"); #endif return started; @@ -1429,15 +1531,16 @@ void CApplication::StopWebServer() #endif } -void CApplication::StartAirplayServer() +bool CApplication::StartAirplayServer() { + bool ret = false; #ifdef HAS_AIRPLAY if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable()) { int listenPort = g_advancedSettings.m_airPlayPort; CStdString password = g_guiSettings.GetString("services.airplaypassword"); bool usePassword = g_guiSettings.GetBool("services.useairplaypassword"); - + if (CAirPlayServer::StartServer(listenPort, true)) { CAirPlayServer::SetCredentials(usePassword, password); @@ -1455,22 +1558,28 @@ void CApplication::StartAirplayServer() txt["model"] = "AppleTV2,1"; txt["srcvers"] = AIRPLAY_SERVER_VERSION_STR; CZeroconf::GetInstance()->PublishService("servers.airplay", "_airplay._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), listenPort, txt); + ret = true; } } + if (ret) #endif + { #ifdef HAS_AIRTUNES - if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable()) - { - int listenPort = g_advancedSettings.m_airTunesPort; - CStdString password = g_guiSettings.GetString("services.airplaypassword"); - bool usePassword = g_guiSettings.GetBool("services.useairplaypassword"); - - if (!CAirTunesServer::StartServer(listenPort, true, usePassword, password)) + if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable()) { - CLog::Log(LOGERROR, "Failed to start AirTunes Server"); + int listenPort = g_advancedSettings.m_airTunesPort; + CStdString password = g_guiSettings.GetString("services.airplaypassword"); + bool usePassword = g_guiSettings.GetBool("services.useairplaypassword"); + + if (!CAirTunesServer::StartServer(listenPort, true, usePassword, password)) + { + CLog::Log(LOGERROR, "Failed to start AirTunes Server"); + } + ret = true; } - } #endif + } + return ret; } void CApplication::StopAirplayServer(bool bWait) @@ -1491,7 +1600,7 @@ bool CApplication::StartJSONRPCServer() { if (CTCPServer::StartServer(g_advancedSettings.m_jsonTcpPort, g_guiSettings.GetBool("services.esallinterfaces"))) { - std::map<std::string, std::string> txt; + std::map<std::string, std::string> txt; CZeroconf::GetInstance()->PublishService("servers.jsonrpc-tpc", "_xbmc-jsonrpc._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), g_advancedSettings.m_jsonTcpPort, txt); return true; } @@ -1799,7 +1908,7 @@ void CApplication::LoadSkin(const SkinPtr& skin) UnloadSkin(); - CLog::Log(LOGINFO, " load skin from: %s", skin->Path().c_str()); + CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str()); g_SkinInfo = skin; g_SkinInfo->Start(); @@ -2118,9 +2227,9 @@ void CApplication::Render() { // Less fps in DPMS - bool lowfps = m_dpmsIsActive; + bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter(); // Whether externalplayer is playing and we're unfocused - bool extPlayerActive = m_eCurrentPlayer >= EPC_EXTPLAYER && IsPlaying() && !m_AppFocused; + bool extPlayerActive = m_eCurrentPlayer == EPC_EXTPLAYER && IsPlaying() && !m_AppFocused; m_bPresentFrame = false; if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused()) @@ -2379,10 +2488,23 @@ bool CApplication::OnKey(const CKey& key) if (!key.IsAnalogButton()) CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str()); - // Play a sound based on the action - g_audioManager.PlayActionSound(action); + bool bResult = false; + + // play sound before the action unless the button is held, + // where we execute after the action as held actions aren't fired every time. + if(action.GetHoldTime()) + { + bResult = OnAction(action); + if(bResult) + g_audioManager.PlayActionSound(action); + } + else + { + g_audioManager.PlayActionSound(action); + bResult = OnAction(action); + } - return OnAction(action); + return bResult; } // OnAppCommand is called in response to a XBMC_APPCOMMAND event. @@ -2428,7 +2550,7 @@ bool CApplication::OnAction(const CAction &action) { CStdString tmp; tmp.Format("%i",action.GetID()); - getApplicationMessenger().HttpApi("broadcastlevel; OnAction:"+tmp+";2"); + CApplicationMessenger::Get().HttpApi("broadcastlevel; OnAction:"+tmp+";2"); } #endif @@ -2472,7 +2594,7 @@ bool CApplication::OnAction(const CAction &action) m_navigationTimer.StartZero(); return true; } - } + } // handle extra global presses @@ -2574,7 +2696,7 @@ bool CApplication::OnAction(const CAction &action) { if (IsPlaying() && m_pPlayer->SkipNext()) return true; - + if (IsPaused()) m_pPlayer->Pause(); @@ -2989,11 +3111,11 @@ bool CApplication::ProcessMouse() return OnAction(mouseaction); // This is a mouse action so we need to record the mouse position - return OnAction(CAction(mouseaction.GetID(), - g_Mouse.GetHold(MOUSE_LEFT_BUTTON), - (float)g_Mouse.GetX(), - (float)g_Mouse.GetY(), - (float)g_Mouse.GetDX(), + return OnAction(CAction(mouseaction.GetID(), + g_Mouse.GetHold(MOUSE_LEFT_BUTTON), + (float)g_Mouse.GetX(), + (float)g_Mouse.GetY(), + (float)g_Mouse.GetDX(), (float)g_Mouse.GetDY(), mouseaction.GetName())); } @@ -3011,7 +3133,7 @@ void CApplication::CheckForTitleChange() CStdString msg=m_pXbmcHttp->GetOpenTag()+"MovieTitle:"+tagVal->m_strTitle+m_pXbmcHttp->GetCloseTag(); if (m_prevMedia!=msg && g_settings.m_HttpApiBroadcastLevel>=1) { - getApplicationMessenger().HttpApi("broadcastlevel; MediaChanged:"+msg+";1"); + CApplicationMessenger::Get().HttpApi("broadcastlevel; MediaChanged:"+msg+";1"); m_prevMedia=msg; } } @@ -3028,7 +3150,7 @@ void CApplication::CheckForTitleChange() msg+=m_pXbmcHttp->GetOpenTag()+"AudioArtist:"+StringUtils::Join(tagVal->GetArtist(), g_advancedSettings.m_musicItemSeparator)+m_pXbmcHttp->GetCloseTag(); if (m_prevMedia!=msg) { - getApplicationMessenger().HttpApi("broadcastlevel; MediaChanged:"+msg+";1"); + CApplicationMessenger::Get().HttpApi("broadcastlevel; MediaChanged:"+msg+";1"); m_prevMedia=msg; } } @@ -3209,8 +3331,23 @@ bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKe if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, actionID, actionName, fullRange)) { CAction action(actionID, fAmount, 0.0f, actionName, holdTime); - g_audioManager.PlayActionSound(action); - return OnAction(action); + bool bResult = false; + + // play sound before the action unless the button is held, + // where we execute after the action as held actions aren't fired every time. + if(action.GetHoldTime()) + { + bResult = OnAction(action); + if(bResult) + g_audioManager.PlayActionSound(action); + } + else + { + g_audioManager.PlayActionSound(action); + bResult = OnAction(action); + } + + return bResult; } else { @@ -3370,7 +3507,10 @@ bool CApplication::Cleanup() #ifdef _LINUX CXHandle::DumpObjectTracker(); #endif - +#if defined(TARGET_ANDROID) + // enable for all platforms once it's safe + g_sectionLoader.UnloadAll(); +#endif #ifdef _CRTDBG_MAP_ALLOC _CrtDumpMemoryLeaks(); while(1); // execution ends @@ -3402,7 +3542,7 @@ void CApplication::Stop(int exitCode) if (m_pXbmcHttp) { if (g_settings.m_HttpApiBroadcastLevel >= 1) - getApplicationMessenger().HttpApi("broadcastlevel; ShutDown;1"); + CApplicationMessenger::Get().HttpApi("broadcastlevel; ShutDown;1"); m_pXbmcHttp->shuttingDown = true; } @@ -3436,7 +3576,7 @@ void CApplication::Stop(int exitCode) if (m_videoInfoScanner->IsScanning()) m_videoInfoScanner->Stop(); - m_applicationMessenger.Cleanup(); + CApplicationMessenger::Get().Cleanup(); StopServices(); //Sleep(5000); @@ -3539,7 +3679,7 @@ void CApplication::Stop(int exitCode) // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here. Destroy(); - // + // Sleep(200); } @@ -3722,7 +3862,7 @@ bool CApplication::PlayStack(const CFileItem& item, bool bRestart) } dbs.Close(); } - } + } *m_itemCurrentFile = item; m_currentStackPosition = 0; @@ -3777,7 +3917,7 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) if (CGUIDialogPlayEject::ShowAndGetInput(item)) // PlayDiscAskResume takes path to disc. No parameter means default DVD drive. // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway - return MEDIA_DETECT::CAutorun::PlayDiscAskResume(); + return MEDIA_DETECT::CAutorun::PlayDiscAskResume(); #endif return true; } @@ -3836,7 +3976,7 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) } CPlayerOptions options; - + if( item.HasProperty("StartPercent") ) { double fallback = 0.0f; @@ -3844,7 +3984,7 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str()); options.startpercent = item.GetProperty("StartPercent").asDouble(fallback); } - + PLAYERCOREID eNewCore = EPC_NONE; if( bRestart ) { @@ -3876,7 +4016,7 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) options.starttime = 0.0f; CBookmark bookmark; CStdString path = item.GetPath(); - if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_strFileNameAndPath.Find("removable://") == 0) + if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_strFileNameAndPath.Find("removable://") == 0) path = item.GetVideoInfoTag()->m_strFileNameAndPath; else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString())) path = item.GetProperty("original_listitem_url").asString(); @@ -3885,6 +4025,14 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) options.starttime = bookmark.timeInSeconds; options.state = bookmark.playerState; } + /* + override with information from the actual item if available. We do this as the VFS (eg plugins) + may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that, + should the playerState be required, it is fetched from the database. + See the note in CGUIWindowVideoBase::ShowResumeMenu. + */ + if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet()) + options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds; } else if (item.HasVideoInfoTag()) { @@ -4065,7 +4213,7 @@ void CApplication::OnPlayBackEnded() #ifdef HAS_HTTPAPI // Let's tell the outside world as well if (g_settings.m_HttpApiBroadcastLevel>=1) - getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackEnded;1"); + CApplicationMessenger::Get().HttpApi("broadcastlevel; OnPlayBackEnded;1"); #endif CVariant data(CVariant::VariantTypeObject); @@ -4099,7 +4247,7 @@ void CApplication::OnPlayBackStarted() #ifdef HAS_HTTPAPI // Let's tell the outside world as well if (g_settings.m_HttpApiBroadcastLevel>=1) - getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackStarted;1"); + CApplicationMessenger::Get().HttpApi("broadcastlevel; OnPlayBackStarted;1"); #endif CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0); @@ -4117,7 +4265,7 @@ void CApplication::OnQueueNextItem() #ifdef HAS_HTTPAPI // Let's tell the outside world as well if (g_settings.m_HttpApiBroadcastLevel>=1) - getApplicationMessenger().HttpApi("broadcastlevel; OnQueueNextItem;1"); + CApplicationMessenger::Get().HttpApi("broadcastlevel; OnQueueNextItem;1"); #endif if(IsPlayingAudio()) @@ -4147,7 +4295,7 @@ void CApplication::OnPlayBackStopped() #ifdef HAS_HTTPAPI // Let's tell the outside world as well if (g_settings.m_HttpApiBroadcastLevel>=1) - getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackStopped;1"); + CApplicationMessenger::Get().HttpApi("broadcastlevel; OnPlayBackStopped;1"); #endif CVariant data(CVariant::VariantTypeObject); @@ -4170,7 +4318,7 @@ void CApplication::OnPlayBackPaused() #ifdef HAS_HTTPAPI // Let's tell the outside world as well if (g_settings.m_HttpApiBroadcastLevel>=1) - getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackPaused;1"); + CApplicationMessenger::Get().HttpApi("broadcastlevel; OnPlayBackPaused;1"); #endif CVariant param; @@ -4188,7 +4336,7 @@ void CApplication::OnPlayBackResumed() #ifdef HAS_HTTPAPI // Let's tell the outside world as well if (g_settings.m_HttpApiBroadcastLevel>=1) - getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackResumed;1"); + CApplicationMessenger::Get().HttpApi("broadcastlevel; OnPlayBackResumed;1"); #endif CVariant param; @@ -4209,7 +4357,7 @@ void CApplication::OnPlayBackSpeedChanged(int iSpeed) { CStdString tmp; tmp.Format("broadcastlevel; OnPlayBackSpeedChanged:%i;1",iSpeed); - getApplicationMessenger().HttpApi(tmp); + CApplicationMessenger::Get().HttpApi(tmp); } #endif @@ -4231,7 +4379,7 @@ void CApplication::OnPlayBackSeek(int iTime, int seekOffset) { CStdString tmp; tmp.Format("broadcastlevel; OnPlayBackSeek:%i;1",iTime); - getApplicationMessenger().HttpApi(tmp); + CApplicationMessenger::Get().HttpApi(tmp); } #endif @@ -4256,7 +4404,7 @@ void CApplication::OnPlayBackSeekChapter(int iChapter) { CStdString tmp; tmp.Format("broadcastlevel; OnPlayBackSkeekChapter:%i;1",iChapter); - getApplicationMessenger().HttpApi(tmp); + CApplicationMessenger::Get().HttpApi(tmp); } #endif } @@ -4372,7 +4520,7 @@ void CApplication::UpdateFileState() if (m_progressTrackingItem->IsVideo()) { - if ((m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) && m_pPlayer->GetTotalTime() > 15*60) + if ((m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) && m_pPlayer->GetTotalTime() > 15*60*1000) { m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.Reset(); m_pPlayer->GetStreamDetails(m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails); @@ -4546,7 +4694,7 @@ bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */) if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER) g_windowManager.PreviousWindow(); // show the previous window if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) - g_application.getApplicationMessenger().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW); + CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW); } return true; } @@ -4585,7 +4733,7 @@ void CApplication::CheckScreenSaverAndDPMS() // * Are we playing a video and it is not paused? if ((IsPlayingVideo() && !m_pPlayer->IsPaused()) // * Are we playing some music in fullscreen vis? - || (IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION + || (IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty())) { ResetScreenSaverTimer(); @@ -4659,7 +4807,7 @@ void CApplication::ActivateScreenSaver(bool forceType /*= false */) path = "special://profile/Thumbnails/Video/Fanart"; if (type == "1") path = "special://profile/Thumbnails/Music/Fanart"; - m_applicationMessenger.PictureSlideShow(path, true, type != "2"); + CApplicationMessenger::Get().PictureSlideShow(path, true, type != "2"); } else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim") return; @@ -4697,7 +4845,7 @@ void CApplication::CheckShutdown() m_shutdownTimer.Stop(); // Sleep the box - getApplicationMessenger().Shutdown(); + CApplicationMessenger::Get().Shutdown(); } } @@ -4830,7 +4978,7 @@ bool CApplication::OnMessage(CGUIMessage& message) return true; } } - + // In case playback ended due to user eg. skipping over the end, clear // our resume bookmark here if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0) @@ -4867,9 +5015,18 @@ bool CApplication::OnMessage(CGUIMessage& message) DimLCDOnPlayback(false); } - if (!IsPlayingVideo() && g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO) + if (!IsPlayingVideo()) { - g_windowManager.PreviousWindow(); + if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO) + { + g_windowManager.PreviousWindow(); + } + else + { + CSingleLock lock(g_graphicsContext); + // resets to res_desktop or look&feel resolution (including refreshrate) + g_graphicsContext.SetFullScreenVideo(false); + } } if (!IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) @@ -4888,7 +5045,8 @@ bool CApplication::OnMessage(CGUIMessage& message) g_windowManager.PreviousWindow(); } - if (IsEnableTestMode()) g_application.getApplicationMessenger().Quit(); + if (IsEnableTestMode()) + CApplicationMessenger::Get().Quit(); return true; } break; @@ -4914,42 +5072,42 @@ bool CApplication::OnMessage(CGUIMessage& message) } bool CApplication::ExecuteXBMCAction(std::string actionStr) +{ + // see if it is a user set string + CLog::Log(LOGDEBUG,"%s : Translating %s", __FUNCTION__, actionStr.c_str()); + CGUIInfoLabel info(actionStr, ""); + actionStr = info.GetLabel(0); + CLog::Log(LOGDEBUG,"%s : To %s", __FUNCTION__, actionStr.c_str()); + + // user has asked for something to be executed + if (CBuiltins::HasCommand(actionStr)) + CBuiltins::Execute(actionStr); + else + { + // try translating the action from our ButtonTranslator + int actionID; + if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID)) { - // see if it is a user set string - CLog::Log(LOGDEBUG,"%s : Translating %s", __FUNCTION__, actionStr.c_str()); - CGUIInfoLabel info(actionStr, ""); - actionStr = info.GetLabel(0); - CLog::Log(LOGDEBUG,"%s : To %s", __FUNCTION__, actionStr.c_str()); - - // user has asked for something to be executed - if (CBuiltins::HasCommand(actionStr)) - CBuiltins::Execute(actionStr); - else - { - // try translating the action from our ButtonTranslator - int actionID; - if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID)) - { - OnAction(CAction(actionID)); - return true; - } - CFileItem item(actionStr, false); + OnAction(CAction(actionID)); + return true; + } + CFileItem item(actionStr, false); #ifdef HAS_PYTHON - if (item.IsPythonScript()) - { // a python script - g_pythonParser.evalFile(item.GetPath().c_str(),ADDON::AddonPtr()); - } - else + if (item.IsPythonScript()) + { // a python script + g_pythonParser.evalFile(item.GetPath().c_str(),ADDON::AddonPtr()); + } + else #endif - if (item.IsAudio() || item.IsVideo()) - { // an audio or video file - PlayFile(item); - } - else - return false; - } - return true; + if (item.IsAudio() || item.IsVideo()) + { // an audio or video file + PlayFile(item); } + else + return false; + } + return true; +} void CApplication::Process() { @@ -4960,7 +5118,7 @@ void CApplication::Process() // process messages which have to be send to the gui // (this can only be done after g_windowManager.Render()) - m_applicationMessenger.ProcessWindowMessages(); + CApplicationMessenger::Get().ProcessWindowMessages(); #ifdef HAS_PYTHON // process any Python scripts @@ -4968,7 +5126,7 @@ void CApplication::Process() #endif // process messages, even if a movie is playing - m_applicationMessenger.ProcessMessages(); + CApplicationMessenger::Get().ProcessMessages(); if (g_application.m_bStop) return; //we're done, everything has been unloaded // check how far we are through playing the current item @@ -5077,7 +5235,7 @@ void CApplication::ProcessSlow() #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB) smb.CheckIfIdle(); #endif - + #ifdef HAS_FILESYSTEM_NFS gNfsConnection.CheckIfIdle(); #endif @@ -5108,7 +5266,7 @@ void CApplication::ProcessSlow() } } #endif - + if (!IsPlayingVideo()) CAddonInstaller::Get().UpdateRepos(); @@ -5349,7 +5507,7 @@ double CApplication::GetTotalTime() const if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0) rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset; else - rc = m_pPlayer->GetTotalTime(); + rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f); } return rc; @@ -5422,7 +5580,7 @@ void CApplication::SeekTime( double dTime ) item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0); // don't just call "PlayFile" here, as we are quite likely called from the // player thread, so we won't be able to delete ourselves. - m_applicationMessenger.PlayFile(item, true); + CApplicationMessenger::Get().PlayFile(item, true); } return; } @@ -5445,7 +5603,11 @@ float CApplication::GetPercentage() const } if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0) - return (float)(GetTime() / GetTotalTime() * 100); + { + double totalTime = GetTotalTime(); + if (totalTime > 0.0f) + return (float)(GetTime() / totalTime * 100); + } else return m_pPlayer->GetPercentage(); } @@ -5455,8 +5617,18 @@ float CApplication::GetPercentage() const float CApplication::GetCachePercentage() const { if (IsPlaying() && m_pPlayer) - return m_pPlayer->GetCachePercentage(); - + { + // Note that the player returns a relative cache percentage and we want an absolute percentage + if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0) + { + float stackedTotalTime = (float) GetTotalTime(); + // We need to take into account the stack's total time vs. currently playing file's total time + if (stackedTotalTime > 0.0f) + return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) ); + } + else + return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() ); + } return 0.0f; } @@ -5761,11 +5933,6 @@ bool CApplication::AlwaysProcess(const CAction& action) return false; } -CApplicationMessenger& CApplication::getApplicationMessenger() -{ - return m_applicationMessenger; -} - bool CApplication::IsCurrentThread() const { return CThread::IsCurrentThread(m_threadID); diff --git a/xbmc/Application.h b/xbmc/Application.h index 7fe9b380c8..36425f7f2c 100644 --- a/xbmc/Application.h +++ b/xbmc/Application.h @@ -25,6 +25,7 @@ #include "XBApplicationEx.h" #include "guilib/IMsgTargetCallback.h" +#include "guilib/Key.h" #include "threads/Condition.h" #include <map> @@ -53,7 +54,6 @@ namespace MEDIA_DETECT #include "win32/WIN32Util.h" #endif #include "utils/Stopwatch.h" -#include "ApplicationMessenger.h" #include "network/Network.h" #include "utils/CharsetConverter.h" #ifdef HAS_PERFORMANCE_SAMPLE @@ -65,7 +65,6 @@ namespace MEDIA_DETECT class CSeekHandler; class CKaraokeLyricsManager; class CInertialScrollingHandler; -class CApplicationMessenger; class DPMSSupport; class CSplash; class CBookmark; @@ -109,6 +108,18 @@ protected: class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMsgTargetCallback { public: + + enum ESERVERS + { + ES_WEBSERVER = 1, + ES_AIRPLAYSERVER, + ES_JSONRPCSERVER, + ES_UPNPRENDERER, + ES_UPNPSERVER, + ES_EVENTSERVER, + ES_ZEROCONF + }; + CApplication(void); virtual ~CApplication(void); virtual bool Initialize(); @@ -124,10 +135,13 @@ public: bool DestroyWindow(); void StartServices(); void StopServices(); + + bool StartServer(enum ESERVERS eServer, bool bStart, bool bWait = false); + bool StartWebServer(); void StopWebServer(); - void StartAirplayServer(); - void StopAirplayServer(bool bWait); + bool StartAirplayServer(); + void StopAirplayServer(bool bWait); bool StartJSONRPCServer(); void StopJSONRPCServer(bool bWait); void StartUPnP(); @@ -207,7 +221,17 @@ public: // Wakes up from the screensaver and / or DPMS. Returns true if woken up. bool WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed = false); bool WakeUpScreenSaver(bool bPowerOffKeyPressed = false); + /*! + \brief Returns the total time in fractional seconds of the currently playing media + + Beware that this method returns fractional seconds whereas IPlayer::GetTotalTime() returns milliseconds. + */ double GetTotalTime() const; + /*! + \brief Returns the current time in fractional seconds of the currently playing media + + Beware that this method returns fractional seconds whereas IPlayer::GetTime() returns milliseconds. + */ double GetTime() const; float GetPercentage() const; @@ -242,7 +266,6 @@ public: static bool OnEvent(XBMC_Event& newEvent); - CApplicationMessenger& getApplicationMessenger(); #if defined(HAS_LINUX_NETWORK) CNetworkLinux& getNetwork(); #elif defined(HAS_WIN32_NETWORK) @@ -344,13 +367,16 @@ public: \sa CSeekHandler */ const CSeekHandler *GetSeekHandler() const { return m_seekHandler; }; + + bool SwitchToFullScreen(); + + CSplash* GetSplash() { return m_splash; } protected: bool LoadSkin(const CStdString& skinID); void LoadSkin(const boost::shared_ptr<ADDON::CSkinInfo>& skin); bool m_skinReloading; // if true we disallow LoadSkin until ReloadSkin is called - friend class CApplicationMessenger; #if defined(TARGET_DARWIN_IOS) friend class CWinEventsIOS; #endif @@ -404,7 +430,7 @@ protected: bool m_bEnableLegacyRes; bool m_bTestMode; bool m_bSystemScreenSaverEnable; - + int m_frameCount; CCriticalSection m_frameMutex; XbmcThreads::ConditionVariable m_frameCond; @@ -417,12 +443,10 @@ protected: void SetHardwareVolume(float hardwareVolume); void UpdateLCD(); - void FatalErrorHandler(bool WindowSystemInitialized, bool MapDrives, bool InitNetwork); void VolumeChanged() const; bool PlayStack(const CFileItem& item, bool bRestart); - bool SwitchToFullScreen(); bool ProcessMouse(); bool ProcessRemote(float frameTime); bool ProcessGamepad(float frameTime); @@ -445,7 +469,6 @@ protected: CSeekHandler *m_seekHandler; CInertialScrollingHandler *m_pInertialScrollingHandler; - CApplicationMessenger m_applicationMessenger; #if defined(HAS_LINUX_NETWORK) CNetworkLinux m_network; #elif defined(HAS_WIN32_NETWORK) diff --git a/xbmc/ApplicationMessenger.cpp b/xbmc/ApplicationMessenger.cpp index 23c2b93c93..8acd3eea10 100644 --- a/xbmc/ApplicationMessenger.cpp +++ b/xbmc/ApplicationMessenger.cpp @@ -23,7 +23,6 @@ #include "ApplicationMessenger.h" #include "Application.h" -#include "guilib/TextureManager.h" #include "PlayListPlayer.h" #include "Util.h" #ifdef HAS_PYTHON @@ -39,10 +38,10 @@ #include "settings/GUISettings.h" #include "FileItem.h" #include "guilib/GUIDialog.h" -#include "windowing/WindowingFactory.h" #include "GUIInfoManager.h" #include "utils/Splash.h" #include "cores/VideoRenderers/RenderManager.h" +#include "music/tags/MusicInfoTag.h" #include "powermanagement/PowerManager.h" @@ -67,11 +66,10 @@ #include "playlists/PlayList.h" #include "FileItem.h" -#include "utils/JobManager.h" -#include "storage/DetectDVDType.h" #include "ThumbLoader.h" using namespace std; +using namespace MUSIC_INFO; CDelayedMessage::CDelayedMessage(ThreadMessage& msg, unsigned int delay) : CThread("CDelayedMessage") { @@ -91,7 +89,17 @@ void CDelayedMessage::Process() Sleep(m_delay); if (!m_bStop) - g_application.getApplicationMessenger().SendMessage(m_msg, false); + CApplicationMessenger::Get().SendMessage(m_msg, false); +} + +CApplicationMessenger& CApplicationMessenger::Get() +{ + static CApplicationMessenger s_messenger; + return s_messenger; +} + +CApplicationMessenger::CApplicationMessenger() +{ } CApplicationMessenger::~CApplicationMessenger() @@ -279,10 +287,9 @@ case TMSG_POWERDOWN: case TMSG_RESTARTAPP: { -#ifdef _WIN32 +#if defined(TARGET_WINDOWS) || defined(TARGET_LINUX) g_application.Stop(EXITCODE_RESTARTAPP); #endif - // TODO } break; @@ -521,23 +528,23 @@ case TMSG_POWERDOWN: switch (m_pXbmcHttp->xbmcCommand(pMsg->strParam)) { case 1: - g_application.getApplicationMessenger().Restart(); + Restart(); break; case 2: - g_application.getApplicationMessenger().Shutdown(); + Shutdown(); break; case 3: - g_application.getApplicationMessenger().Quit(); + Quit(); break; case 4: - g_application.getApplicationMessenger().Reset(); + Reset(); break; case 5: - g_application.getApplicationMessenger().RestartApp(); + RestartApp(); break; } #endif @@ -761,10 +768,38 @@ case TMSG_POWERDOWN: case TMSG_SPLASH_MESSAGE: { - if (g_application.m_splash) - g_application.m_splash->Show(pMsg->strParam); + if (g_application.GetSplash()) + g_application.GetSplash()->Show(pMsg->strParam); } break; + + case TMSG_DISPLAY_SETUP: + { + *((bool*)pMsg->lpVoid) = g_application.InitWindow(); + g_application.ReloadSkin(); + } + break; + + case TMSG_DISPLAY_DESTROY: + { + *((bool*)pMsg->lpVoid) = g_application.DestroyWindow(); + } + break; + + case TMSG_UPDATE_CURRENT_ITEM: + { + CFileItem* item = (CFileItem*)pMsg->lpVoid; + if (!item) + return; + if (pMsg->dwParam1 == 1 && item->HasMusicInfoTag()) // only grab music tag + g_infoManager.SetCurrentSongTag(*item->GetMusicInfoTag()); + else if (pMsg->dwParam1 == 2 && item->HasVideoInfoTag()) // only grab video tag + g_infoManager.SetCurrentVideoTag(*item->GetVideoInfoTag()); + else + g_infoManager.SetCurrentItem(*item); + delete item; + break; + } } } @@ -1136,7 +1171,7 @@ void CApplicationMessenger::Show(CGUIDialog *pDialog) void CApplicationMessenger::Close(CGUIWindow *window, bool forceClose, bool waitResult /*= true*/, int nextWindowID /*= 0*/, bool enableSound /*= true*/) { ThreadMessage tMsg = {TMSG_GUI_WINDOW_CLOSE, nextWindowID}; - tMsg.dwParam2 = (DWORD)(forceClose ? 0x01 : 0 | enableSound ? 0x02 : 0); + tMsg.dwParam2 = (DWORD)((forceClose ? 0x01 : 0) | (enableSound ? 0x02 : 0)); tMsg.lpVoid = window; SendMessage(tMsg, waitResult); } @@ -1204,3 +1239,51 @@ void CApplicationMessenger::SetSplashMessage(int stringID) { SetSplashMessage(g_localizeStrings.Get(stringID)); } + +bool CApplicationMessenger::SetupDisplay() +{ + bool result; + + ThreadMessage tMsg = {TMSG_DISPLAY_SETUP}; + tMsg.lpVoid = (void*)&result; + SendMessage(tMsg, true); + + return result; +} + +bool CApplicationMessenger::DestroyDisplay() +{ + bool result; + + ThreadMessage tMsg = {TMSG_DISPLAY_DESTROY}; + tMsg.lpVoid = (void*)&result; + SendMessage(tMsg, true); + + return result; +} + +void CApplicationMessenger::SetCurrentSongTag(const CMusicInfoTag& tag) +{ + CFileItem* item = new CFileItem(tag); + ThreadMessage tMsg = {TMSG_UPDATE_CURRENT_ITEM}; + tMsg.dwParam1 = 1; + tMsg.lpVoid = (void*)item; + SendMessage(tMsg, false); +} + +void CApplicationMessenger::SetCurrentVideoTag(const CVideoInfoTag& tag) +{ + CFileItem* item = new CFileItem(tag); + ThreadMessage tMsg = {TMSG_UPDATE_CURRENT_ITEM}; + tMsg.dwParam1 = 2; + tMsg.lpVoid = (void*)item; + SendMessage(tMsg, false); +} + +void CApplicationMessenger::SetCurrentItem(const CFileItem& item) +{ + CFileItem* item2 = new CFileItem(item); + ThreadMessage tMsg = {TMSG_UPDATE_CURRENT_ITEM}; + tMsg.lpVoid = (void*)item2; + SendMessage(tMsg, false); +} diff --git a/xbmc/ApplicationMessenger.h b/xbmc/ApplicationMessenger.h index 393ee4d4f5..0a3b6b6de6 100644 --- a/xbmc/ApplicationMessenger.h +++ b/xbmc/ApplicationMessenger.h @@ -28,6 +28,8 @@ #include "threads/Event.h" #include <boost/shared_ptr.hpp> +#include "PlatformDefs.h" + #include <queue> class CFileItem; @@ -35,6 +37,12 @@ class CFileItemList; class CGUIDialog; class CGUIWindow; class CGUIMessage; +class CVideoInfoTag; + +namespace MUSIC_INFO +{ + class CMusicInfoTag; +} // defines here #define TMSG_DIALOG_DOMODAL 100 @@ -60,6 +68,7 @@ class CGUIMessage; #define TMSG_PLAYLISTPLAYER_REMOVE 219 #define TMSG_PLAYLISTPLAYER_SWAP 223 #define TMSG_PLAYLISTPLAYER_REPEAT 224 +#define TMSG_UPDATE_CURRENT_ITEM 225 #define TMSG_PICTURE_SHOW 220 #define TMSG_PICTURE_SLIDESHOW 221 @@ -98,6 +107,9 @@ class CGUIMessage; #define TMSG_VOLUME_SHOW 900 #define TMSG_SPLASH_MESSAGE 901 +#define TMSG_DISPLAY_SETUP 1000 +#define TMSG_DISPLAY_DESTROY 1001 + typedef struct { DWORD dwMessage; @@ -129,9 +141,12 @@ struct ThreadMessageCallback class CApplicationMessenger { - public: - ~CApplicationMessenger(); + /*! + \brief The only way through which the global instance of the CApplicationMessenger should be accessed. + \return the global instance. + */ + static CApplicationMessenger& Get(); void Cleanup(); // if a message has to be send to the gui, use MSG_TYPE_WINDOW instead @@ -180,6 +195,12 @@ public: void Minimize(bool wait = false); void ExecOS(const CStdString command, bool waitExit = false); void UserEvent(int code); + //! \brief Set the tag for the currently playing song + void SetCurrentSongTag(const MUSIC_INFO::CMusicInfoTag& tag); + //! \brief Set the tag for the currently playing video + void SetCurrentVideoTag(const CVideoInfoTag& tag); + //! \brief Set the currently currently item + void SetCurrentItem(const CFileItem& item); CStdString GetResponse(); int SetResponse(CStdString response); @@ -209,15 +230,21 @@ public: void SetSplashMessage(const CStdString& message); void SetSplashMessage(int stringID); + + bool SetupDisplay(); + bool DestroyDisplay(); private: + // private construction, and no assignements; use the provided singleton methods + CApplicationMessenger(); + CApplicationMessenger(const CApplicationMessenger&); + CApplicationMessenger const& operator=(CApplicationMessenger const&); + virtual ~CApplicationMessenger(); void ProcessMessage(ThreadMessage *pMsg); - std::queue<ThreadMessage*> m_vecMessages; std::queue<ThreadMessage*> m_vecWindowMessages; CCriticalSection m_critSection; CCriticalSection m_critBuffer; CStdString bufferResponse; - }; diff --git a/xbmc/AutoSwitch.cpp b/xbmc/AutoSwitch.cpp index 6ee8127694..c9ce88d382 100644 --- a/xbmc/AutoSwitch.cpp +++ b/xbmc/AutoSwitch.cpp @@ -20,7 +20,6 @@ */ #include "AutoSwitch.h" -#include "guilib/GUIBaseContainer.h" // for VIEW_TYPE_* #include "settings/Settings.h" #include "settings/GUISettings.h" #include "guilib/GUIWindowManager.h" diff --git a/xbmc/Autorun.cpp b/xbmc/Autorun.cpp index a29a869420..36a10a8c40 100644 --- a/xbmc/Autorun.cpp +++ b/xbmc/Autorun.cpp @@ -25,7 +25,6 @@ #include "Autorun.h" #include "Application.h" -#include "Util.h" #include "GUIPassword.h" #include "GUIUserMessages.h" #include "PlayListPlayer.h" @@ -34,7 +33,6 @@ #include "filesystem/DirectoryFactory.h" #include "filesystem/File.h" #include "settings/GUISettings.h" -#include "settings/AdvancedSettings.h" #include "settings/Settings.h" #include "playlists/PlayList.h" #include "guilib/GUIWindowManager.h" diff --git a/xbmc/DbUrl.cpp b/xbmc/DbUrl.cpp new file mode 100644 index 0000000000..51a94e442c --- /dev/null +++ b/xbmc/DbUrl.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <sstream> + +#include "DbUrl.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" + +using namespace std; + +CDbUrl::CDbUrl() +{ + Reset(); +} + +CDbUrl::~CDbUrl() +{ } + +void CDbUrl::Reset() +{ + m_valid = false; + m_type.clear(); + m_url.Reset(); + m_options.clear(); +} + +std::string CDbUrl::ToString() const +{ + if (!m_valid) + return ""; + + return m_url.Get(); +} + +bool CDbUrl::FromString(const std::string &dbUrl) +{ + Reset(); + + m_url.Parse(dbUrl); + m_valid = parse(); + + if (!m_valid) + Reset(); + + return m_valid; +} + +void CDbUrl::AppendPath(const std::string &subPath) +{ + if (!m_valid || subPath.empty()) + return; + + m_url.SetFileName(URIUtils::AddFileToFolder(m_url.GetFileName(), subPath)); +} + +void CDbUrl::updateOptions() +{ + // Update the options string in the CURL object + string options = GetOptionsString(); + if (!options.empty()) + options = "?" + options; + + m_url.SetOptions(options); +} diff --git a/xbmc/DbUrl.h b/xbmc/DbUrl.h new file mode 100644 index 0000000000..4a70e59e21 --- /dev/null +++ b/xbmc/DbUrl.h @@ -0,0 +1,59 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <map> +#include <string> + +#include "URL.h" +#include "utils/UrlOptions.h" + +class CDbUrl : public CUrlOptions +{ +public: + CDbUrl(); + virtual ~CDbUrl(); + + bool IsValid() const { return m_valid; } + void Reset(); + + std::string ToString() const; + bool FromString(const std::string &dbUrl); + + const std::string& GetType() const { return m_type; } + void AppendPath(const std::string &subPath); + + virtual void AddOption(const std::string &key, const std::string &value) { CUrlOptions::AddOption(key, value); updateOptions(); } + virtual void AddOption(const std::string &key, int value) { CUrlOptions::AddOption(key, value); updateOptions(); } + virtual void AddOption(const std::string &key, float value) { CUrlOptions::AddOption(key, value); updateOptions(); } + virtual void AddOption(const std::string &key, double value) { CUrlOptions::AddOption(key, value); updateOptions(); } + virtual void AddOption(const std::string &key, bool value) { CUrlOptions::AddOption(key, value); updateOptions(); } + virtual void AddOptions(const std::string &options) { CUrlOptions::AddOptions(options); updateOptions(); } + +protected: + virtual bool parse() = 0; + + CURL m_url; + std::string m_type; + +private: + void updateOptions(); + + bool m_valid; +}; diff --git a/xbmc/DllPaths.h b/xbmc/DllPaths.h index 02d9f2a388..ba1d195551 100644 --- a/xbmc/DllPaths.h +++ b/xbmc/DllPaths.h @@ -24,6 +24,8 @@ #ifdef _WIN32 #include "DllPaths_win32.h" +#elif defined (__ANDROID__) +#include "DllPaths_generated_android.h" #else #include "DllPaths_generated.h" #endif diff --git a/xbmc/DllPaths_generated_android.h.in b/xbmc/DllPaths_generated_android.h.in new file mode 100644 index 0000000000..21299ab36b --- /dev/null +++ b/xbmc/DllPaths_generated_android.h.in @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2005-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ +#pragma once +/* libraries */ + +//Android rules: +// - All solibs must be in the form ^lib*.so$ +// - All solibs must be in the same dir +// - Arch need not be specified, each arch will get its own lib dir. +// We only keep @ARCH@ here to retain the same structure as *nix. +// * foo.so will be renamed libfoo.so in the packaging stage + +#define DLL_PATH_CPLUFF "libcpluff-@ARCH@.so" +#define DLL_PATH_IMAGELIB "libImageLib-@ARCH@.so" +#define DLL_PATH_LIBEXIF "libexif-@ARCH@.so" +#define DLL_PATH_LIBID3TAG "libid3tag-@ARCH@.so" +#define DLL_PATH_LIBHDHOMERUN "libhdhomerun-@ARCH@.so" +#define DLL_PATH_MEDIAINFO "libmediainfo-@ARCH@.so" +#define DLL_PATH_LIBCMYTH "libcmyth-@ARCH@.so" + +#define DLL_PATH_LIBRTMP "@RTMP_SONAME@" +#define DLL_PATH_LIBNFS "@NFS_SONAME@" +#define DLL_PATH_LIBAFP "@AFPCLIENT_SONAME@" +#define DLL_PATH_LIBPLIST "@PLIST_SONAME@" +#define DLL_PATH_LIBSHAIRPORT "@SHAIRPORT_SONAME@" +#define DLL_PATH_LIBCEC "@LIBCEC_SONAME@" + +#ifndef DLL_PATH_LIBCURL +#define DLL_PATH_LIBCURL "@CURL_SONAME@" +#endif + +/* paplayer */ +#define DLL_PATH_AAC_CODEC "libAACCodec-@ARCH@.so" +#define DLL_PATH_ADPCM_CODEC "libadpcm-@ARCH@.so" +#define DLL_PATH_ADPLUG_CODEC "libadplug-@ARCH@.so" +#define DLL_PATH_APE_CODEC "libMACDll-@ARCH@.so" +#define DLL_PATH_ASAP_CODEC "libxbmc_asap-@ARCH@.so" +#define DLL_PATH_DCA_CODEC "libdcacodec-@ARCH@.so" +#define DLL_PATH_GYM_CODEC "libgensapu-@ARCH@.so" +#define DLL_PATH_MID_CODEC "libtimidity-@ARCH@.so" +#define DLL_PATH_MODULE_CODEC "libdumb-@ARCH@.so" +#define DLL_PATH_MPC_CODEC "libmpcdec-@ARCH@.so" +#define DLL_PATH_NSF_CODEC "libnosefart-@ARCH@.so" +#define DLL_PATH_SID_CODEC "libsidplay2-@ARCH@.so" +#define DLL_PATH_SPC_CODEC "libSNESAPU-@ARCH@.so" +#define DLL_PATH_VGM_CODEC "libvgmstream-@ARCH@.so" +#define DLL_PATH_WAVPACK_CODEC "@WAVPACK_SONAME@" +#define DLL_PATH_YM_CODEC "libstsoundlibrary-@ARCH@.so" + +#define DLL_PATH_FLAC_CODEC "@FLAC_SONAME@" +#define DLL_PATH_MODPLUG_CODEC "@MODPLUG_SONAME@" +#define DLL_PATH_OGG_CODEC "@VORBISFILE_SONAME@" + +/* dvdplayer */ +#define DLL_PATH_LIBASS "@ASS_SONAME@" +#define DLL_PATH_LIBDVDNAV "libdvdnav-@ARCH@.so" +#define DLL_PATH_LIBMPEG2 "@MPEG2_SONAME@" +#define DLL_PATH_LIBMAD "@MAD_SONAME@" + +/* ffmpeg */ +#define DLL_PATH_LIBAVCODEC "libavcodec-53-@ARCH@.so" +#define DLL_PATH_LIBAVFORMAT "libavformat-53-@ARCH@.so" +#define DLL_PATH_LIBAVUTIL "libavutil-51-@ARCH@.so" +#define DLL_PATH_LIBPOSTPROC "libpostproc-52-@ARCH@.so" +#define DLL_PATH_LIBSWSCALE "libswscale-2-@ARCH@.so" +#define DLL_PATH_LIBAVFILTER "libavfilter-2-@ARCH@.so" +#define DLL_PATH_LIBSWRESAMPLE "libswresample-0-@ARCH@.so" + +/* cdrip */ +#define DLL_PATH_LAME_ENC "@LAMEENC_SONAME@" +#define DLL_PATH_OGG "@OGG_SONAME@" +#define DLL_PATH_VORBIS_ENC "@VORBISENC_SONAME@" +#define DLL_PATH_VORBIS "@VORBIS_SONAME@" + +/* libbluray */ +#define DLL_PATH_LIBBLURAY "@BLURAY_SONAME@" + +/* Android's libui for gralloc */ +#define DLL_PATH_LIBUI "libui.so" diff --git a/xbmc/Favourites.cpp b/xbmc/Favourites.cpp index 9f5abf588d..752079e951 100644 --- a/xbmc/Favourites.cpp +++ b/xbmc/Favourites.cpp @@ -22,7 +22,6 @@ #include "Favourites.h" #include "filesystem/File.h" #include "Util.h" -#include "guilib/Key.h" #include "settings/Settings.h" #include "FileItem.h" #include "utils/XBMCTinyXML.h" diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp index b4d6344361..f35fed45bd 100644 --- a/xbmc/FileItem.cpp +++ b/xbmc/FileItem.cpp @@ -26,18 +26,16 @@ #include "Util.h" #include "playlists/PlayListFactory.h" #include "utils/Crc32.h" -#include "filesystem/DirectoryCache.h" +#include "filesystem/Directory.h" #include "filesystem/StackDirectory.h" #include "filesystem/CurlFile.h" #include "filesystem/MultiPathDirectory.h" #include "filesystem/MusicDatabaseDirectory.h" #include "filesystem/VideoDatabaseDirectory.h" -#include "filesystem/DirectoryFactory.h" #include "music/tags/MusicInfoTagLoaderFactory.h" #include "CueDocument.h" #include "video/VideoDatabase.h" #include "music/MusicDatabase.h" -#include "SortFileItem.h" #include "utils/TuxBoxUtil.h" #include "video/VideoInfoTag.h" #include "threads/SingleLock.h" @@ -55,7 +53,6 @@ #include "utils/Variant.h" #include "music/karaoke/karaokelyricsfactory.h" #include "utils/Mime.h" -#include "utils/CharsetConverter.h" using namespace std; using namespace XFILE; @@ -560,6 +557,12 @@ bool CFileItem::IsVideo() const bool CFileItem::IsDiscStub() const { + if (IsVideoDb() && HasVideoInfoTag()) + { + CFileItem dbItem(m_bIsFolder ? GetVideoInfoTag()->m_strPath : GetVideoInfoTag()->m_strFileNameAndPath, m_bIsFolder); + return dbItem.IsDiscStub(); + } + CStdString strExtension; URIUtils::GetExtension(m_strPath, strExtension); @@ -652,6 +655,7 @@ bool CFileItem::IsFileFolder() const return ( IsSmartPlayList() || (IsPlayList() && g_advancedSettings.m_playlistAsFolders) || + IsAPK() || IsZIP() || IsRAR() || IsRSS() || @@ -734,6 +738,11 @@ bool CFileItem::IsRAR() const return URIUtils::IsRAR(m_strPath); } +bool CFileItem::IsAPK() const +{ + return URIUtils::IsAPK(m_strPath); +} + bool CFileItem::IsZIP() const { return URIUtils::IsZIP(m_strPath); @@ -758,6 +767,11 @@ bool CFileItem::IsRSS() const || GetMimeType() == "application/rss+xml"; } +bool CFileItem::IsAndroidApp() const +{ + return URIUtils::IsAndroidApp(m_strPath); +} + bool CFileItem::IsStack() const { return URIUtils::IsStack(m_strPath); @@ -1223,8 +1237,7 @@ void CFileItemList::SetFastLookup(bool fastLookup) for (unsigned int i=0; i < m_items.size(); i++) { CFileItemPtr pItem = m_items[i]; - CStdString path(pItem->GetPath()); path.ToLower(); - m_map.insert(MAPFILEITEMSPAIR(path, pItem)); + m_map.insert(MAPFILEITEMSPAIR(pItem->GetPath(), pItem)); } } if (!fastLookup && m_fastLookup) @@ -1236,15 +1249,14 @@ bool CFileItemList::Contains(const CStdString& fileName) const { CSingleLock lock(m_lock); - // checks case insensitive - CStdString checkPath(fileName); checkPath.ToLower(); if (m_fastLookup) - return m_map.find(checkPath) != m_map.end(); + return m_map.find(fileName) != m_map.end(); + // slow method... for (unsigned int i = 0; i < m_items.size(); i++) { const CFileItemPtr pItem = m_items[i]; - if (pItem->GetPath().Equals(checkPath)) + if (pItem->GetPath().Equals(fileName)) return true; } return false; @@ -1285,9 +1297,7 @@ void CFileItemList::Add(const CFileItemPtr &pItem) m_items.push_back(pItem); if (m_fastLookup) { - CStdString path(pItem->GetPath()); - path.ToLower(); - m_map.insert(MAPFILEITEMSPAIR(path, pItem)); + m_map.insert(MAPFILEITEMSPAIR(pItem->GetPath(), pItem)); } } @@ -1305,8 +1315,7 @@ void CFileItemList::AddFront(const CFileItemPtr &pItem, int itemPosition) } if (m_fastLookup) { - CStdString path(pItem->GetPath()); path.ToLower(); - m_map.insert(MAPFILEITEMSPAIR(path, pItem)); + m_map.insert(MAPFILEITEMSPAIR(pItem->GetPath(), pItem)); } } @@ -1321,8 +1330,7 @@ void CFileItemList::Remove(CFileItem* pItem) m_items.erase(it); if (m_fastLookup) { - CStdString path(pItem->GetPath()); path.ToLower(); - m_map.erase(path); + m_map.erase(pItem->GetPath()); } break; } @@ -1338,8 +1346,7 @@ void CFileItemList::Remove(int iItem) CFileItemPtr pItem = *(m_items.begin() + iItem); if (m_fastLookup) { - CStdString path(pItem->GetPath()); path.ToLower(); - m_map.erase(path); + m_map.erase(pItem->GetPath()); } m_items.erase(m_items.begin() + iItem); } @@ -1417,11 +1424,9 @@ CFileItemPtr CFileItemList::Get(const CStdString& strPath) { CSingleLock lock(m_lock); - CStdString pathToCheck(strPath); pathToCheck.ToLower(); - if (m_fastLookup) { - IMAPFILEITEMS it=m_map.find(pathToCheck); + IMAPFILEITEMS it=m_map.find(strPath); if (it != m_map.end()) return it->second; @@ -1431,7 +1436,7 @@ CFileItemPtr CFileItemList::Get(const CStdString& strPath) for (unsigned int i = 0; i < m_items.size(); i++) { CFileItemPtr pItem = m_items[i]; - if (pItem->GetPath().Equals(pathToCheck)) + if (pItem->GetPath().Equals(strPath)) return pItem; } @@ -1441,12 +1446,10 @@ CFileItemPtr CFileItemList::Get(const CStdString& strPath) const CFileItemPtr CFileItemList::Get(const CStdString& strPath) const { CSingleLock lock(m_lock); - - CStdString pathToCheck(strPath); pathToCheck.ToLower(); - + if (m_fastLookup) { - map<CStdString, CFileItemPtr>::const_iterator it=m_map.find(pathToCheck); + map<CStdString, CFileItemPtr>::const_iterator it=m_map.find(strPath); if (it != m_map.end()) return it->second; @@ -1456,7 +1459,7 @@ const CFileItemPtr CFileItemList::Get(const CStdString& strPath) const for (unsigned int i = 0; i < m_items.size(); i++) { CFileItemPtr pItem = m_items[i]; - if (pItem->GetPath().Equals(pathToCheck)) + if (pItem->GetPath().Equals(strPath)) return pItem; } diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h index 3ef2ef61d1..f32429ff49 100644 --- a/xbmc/FileItem.h +++ b/xbmc/FileItem.h @@ -113,6 +113,7 @@ public: bool IsDVDFile(bool bVobs = true, bool bIfos = true) const; bool IsBDFile() const; bool IsRAR() const; + bool IsAPK() const; bool IsZIP() const; bool IsCBZ() const; bool IsCBR() const; @@ -147,6 +148,7 @@ public: bool IsVTP() const; bool IsLiveTV() const; bool IsRSS() const; + bool IsAndroidApp() const; void RemoveExtension(); void CleanString(); diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp index d0cc2c900d..fbcf8be131 100644 --- a/xbmc/GUIInfoManager.cpp +++ b/xbmc/GUIInfoManager.cpp @@ -20,9 +20,8 @@ */ #include "system.h" +#include "GUIInfoManager.h" #include "windows/GUIMediaWindow.h" -#include "dialogs/GUIDialogFileBrowser.h" -#include "settings/GUIDialogContentSettings.h" #include "dialogs/GUIDialogProgress.h" #include "Application.h" #include "Util.h" @@ -36,17 +35,14 @@ #ifdef HAS_LCD #include "utils/LCD.h" #endif -#include "GUIPassword.h" #include "LangInfo.h" #include "utils/SystemInfo.h" #include "guilib/GUITextBox.h" -#include "GUIInfoManager.h" #include "pictures/GUIWindowSlideShow.h" #include "music/LastFmManager.h" #include "pictures/PictureInfoTag.h" #include "music/tags/MusicInfoTag.h" #include "guilib/GUIWindowManager.h" -#include "filesystem/File.h" #include "playlists/PlayList.h" #include "utils/TuxBoxUtil.h" #include "windowing/WindowingFactory.h" @@ -58,11 +54,10 @@ #include "utils/StringUtils.h" #include "utils/MathUtils.h" #include "utils/SeekHandler.h" +#include "URL.h" // stuff for current song -#include "music/tags/MusicInfoTagLoaderFactory.h" #include "music/MusicInfoLoader.h" -#include "utils/LabelFormatter.h" #include "GUIUserMessages.h" #include "video/dialogs/GUIDialogVideoInfo.h" @@ -74,7 +69,6 @@ #include "addons/AddonManager.h" #include "interfaces/info/InfoBool.h" -#include "TextureCache.h" #include "ThumbLoader.h" #include "cores/AudioEngine/Utils/AEUtil.h" @@ -538,6 +532,7 @@ const infomap slideshow[] = {{ "ispaused", SLIDESHOW_ISPAUSED }, { "israndom", SLIDESHOW_ISRANDOM }}; const int picture_slide_map[] = {/* LISTITEM_PICTURE_RESOLUTION => */ SLIDE_RESOLUTION, + /* LISTITEM_PICTURE_DATE => */ SLIDE_EXIF_DATE, /* LISTITEM_PICTURE_DATETIME => */ SLIDE_EXIF_DATE_TIME, /* LISTITEM_PICTURE_COMMENT => */ SLIDE_COMMENT, /* LISTITEM_PICTURE_CAPTION => */ SLIDE_IPTC_CAPTION, @@ -1028,6 +1023,7 @@ int CGUIInfoManager::TranslateSingleString(const CStdString &strCondition) else if (platform == "osx") return SYSTEM_PLATFORM_DARWIN_OSX; else if (platform == "ios") return SYSTEM_PLATFORM_DARWIN_IOS; else if (platform == "atv2") return SYSTEM_PLATFORM_DARWIN_ATV2; + else if (platform == "android") return SYSTEM_PLATFORM_ANDROID; } if (info[0].name == "musicplayer") { // TODO: these two don't allow duration(foo) and also don't allow more than this number of levels... @@ -1852,7 +1848,7 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI if (item && condition >= LISTITEM_START && condition < LISTITEM_END) bReturn = GetItemBool(item, condition); // Ethernet Link state checking - // Will check if the Xbox has a Ethernet Link connection! [Cable in!] + // Will check if system has a Ethernet Link connection! [Cable in!] // This can used for the skinner to switch off Network or Inter required functions else if ( condition == SYSTEM_ALWAYS_TRUE) bReturn = true; @@ -1885,7 +1881,7 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI bReturn = g_application.IsMusicScanning(); } else if (condition == SYSTEM_PLATFORM_LINUX) -#if defined(_LINUX) && !defined(TARGET_DARWIN) +#if defined(_LINUX) && !defined(TARGET_DARWIN) && !defined(TARGET_ANDROID) bReturn = true; #else bReturn = false; @@ -1920,6 +1916,12 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI #else bReturn = false; #endif + else if (condition == SYSTEM_PLATFORM_ANDROID) +#if defined(TARGET_ANDROID) + bReturn = true; +#else + bReturn = false; +#endif else if (condition == SYSTEM_MEDIA_DVD) bReturn = g_mediaManager.IsDiscInDrive(); #ifdef HAS_DVD_DRIVE @@ -3240,7 +3242,7 @@ CStdString CGUIInfoManager::GetMusicLabel(int item) CStdString strSampleRate = ""; if (g_application.m_pPlayer->GetSampleRate() > 0) { - strSampleRate.Format("%i",g_application.m_pPlayer->GetSampleRate()/1000); + strSampleRate.Format("%.5g", ((double)g_application.m_pPlayer->GetSampleRate() / 1000.0)); } return strSampleRate; } @@ -3627,7 +3629,7 @@ string CGUIInfoManager::GetSystemHeatInfo(int info) { // update our variables m_lastSysHeatInfoTime = CTimeUtils::GetFrameTime(); #if defined(_LINUX) - m_cpuTemp = g_cpuInfo.getTemperature(); + g_cpuInfo.getTemperature(m_cpuTemp); m_gpuTemp = GetGPUTemperature(); #endif } @@ -3828,7 +3830,7 @@ bool CGUIInfoManager::GetItemInt(int &value, const CGUIListItem *item, int info) switch (info) { case LISTITEM_PERCENT_PLAYED: - if (item->IsFileItem() && ((const CFileItem *)item)->HasVideoInfoTag() && ((const CFileItem *)item)->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds > 0 && ((const CFileItem *)item)->GetVideoInfoTag()->m_resumePoint.timeInSeconds > 0) + if (item->IsFileItem() && ((const CFileItem *)item)->HasVideoInfoTag() && ((const CFileItem *)item)->GetVideoInfoTag()->m_resumePoint.IsPartWay()) value = (int)(100 * ((const CFileItem *)item)->GetVideoInfoTag()->m_resumePoint.timeInSeconds / ((const CFileItem *)item)->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds); else value = 0; diff --git a/xbmc/GUIInfoManager.h b/xbmc/GUIInfoManager.h index dab3970ff4..3e05423af5 100644 --- a/xbmc/GUIInfoManager.h +++ b/xbmc/GUIInfoManager.h @@ -391,6 +391,7 @@ namespace INFO #define SYSTEM_PLATFORM_DARWIN_OSX 744 #define SYSTEM_PLATFORM_DARWIN_IOS 745 #define SYSTEM_PLATFORM_DARWIN_ATV2 746 +#define SYSTEM_PLATFORM_ANDROID 747 #define SYSTEM_CAN_POWERDOWN 750 #define SYSTEM_CAN_SUSPEND 751 @@ -425,7 +426,7 @@ namespace INFO #define VERSION_MAJOR 12 #define VERSION_MINOR 0 -#define VERSION_TAG "-ALPHA4" +#define VERSION_TAG "-ALPHA5" #define LISTITEM_START 35000 #define LISTITEM_THUMB (LISTITEM_START) @@ -461,57 +462,58 @@ namespace INFO // the ordering of LISTITEM_PICTURE_* is important as they're mapped to SLIDE_* items in GUIInfoManager.cpp #define LISTITEM_PICTURE_START (LISTITEM_START + 30) #define LISTITEM_PICTURE_RESOLUTION (LISTITEM_PICTURE_START) // => SLIDE_RESOLUTION -#define LISTITEM_PICTURE_DATETIME (LISTITEM_START + 31) // => SLIDE_EXIF_DATE_TIME -#define LISTITEM_PICTURE_COMMENT (LISTITEM_START + 32) // => SLIDE_COMMENT -#define LISTITEM_PICTURE_CAPTION (LISTITEM_START + 33) // => SLIDE_IPTC_CAPTION -#define LISTITEM_PICTURE_DESC (LISTITEM_START + 34) // => SLIDE_EXIF_DESCRIPTION -#define LISTITEM_PICTURE_KEYWORDS (LISTITEM_START + 35) // => SLIDE_IPTC_KEYWORDS -#define LISTITEM_PICTURE_CAM_MAKE (LISTITEM_START + 36) // => SLIDE_EXIF_CAMERA_MAKE -#define LISTITEM_PICTURE_CAM_MODEL (LISTITEM_START + 37) // => SLIDE_EXIF_CAMERA_MODEL -#define LISTITEM_PICTURE_APERTURE (LISTITEM_START + 38) // => SLIDE_EXIF_APERTURE -#define LISTITEM_PICTURE_FOCAL_LEN (LISTITEM_START + 39) // => SLIDE_EXIF_FOCAL_LENGTH -#define LISTITEM_PICTURE_FOCUS_DIST (LISTITEM_START + 40) // => SLIDE_EXIF_FOCUS_DIST -#define LISTITEM_PICTURE_EXP_MODE (LISTITEM_START + 41) // => SLIDE_EXIF_EXPOSURE_MODE -#define LISTITEM_PICTURE_EXP_TIME (LISTITEM_START + 42) // => SLIDE_EXIF_EXPOSURE_TIME -#define LISTITEM_PICTURE_ISO (LISTITEM_START + 43) // => SLIDE_EXIF_ISO_EQUIV -#define LISTITEM_PICTURE_GPS_LAT (LISTITEM_START + 44) // => SLIDE_EXIF_GPS_LATITUDE -#define LISTITEM_PICTURE_GPS_LON (LISTITEM_START + 45) // => SLIDE_EXIF_GPS_LONGITUDE -#define LISTITEM_PICTURE_GPS_ALT (LISTITEM_START + 46) // => SLIDE_EXIF_GPS_ALTITUDE +#define LISTITEM_PICTURE_DATE (LISTITEM_START + 31) // => SLIDE_EXIF_DATE +#define LISTITEM_PICTURE_DATETIME (LISTITEM_START + 32) // => SLIDE_EXIF_DATE_TIME +#define LISTITEM_PICTURE_COMMENT (LISTITEM_START + 33) // => SLIDE_COMMENT +#define LISTITEM_PICTURE_CAPTION (LISTITEM_START + 34) // => SLIDE_IPTC_CAPTION +#define LISTITEM_PICTURE_DESC (LISTITEM_START + 35) // => SLIDE_EXIF_DESCRIPTION +#define LISTITEM_PICTURE_KEYWORDS (LISTITEM_START + 36) // => SLIDE_IPTC_KEYWORDS +#define LISTITEM_PICTURE_CAM_MAKE (LISTITEM_START + 37) // => SLIDE_EXIF_CAMERA_MAKE +#define LISTITEM_PICTURE_CAM_MODEL (LISTITEM_START + 38) // => SLIDE_EXIF_CAMERA_MODEL +#define LISTITEM_PICTURE_APERTURE (LISTITEM_START + 39) // => SLIDE_EXIF_APERTURE +#define LISTITEM_PICTURE_FOCAL_LEN (LISTITEM_START + 40) // => SLIDE_EXIF_FOCAL_LENGTH +#define LISTITEM_PICTURE_FOCUS_DIST (LISTITEM_START + 41) // => SLIDE_EXIF_FOCUS_DIST +#define LISTITEM_PICTURE_EXP_MODE (LISTITEM_START + 42) // => SLIDE_EXIF_EXPOSURE_MODE +#define LISTITEM_PICTURE_EXP_TIME (LISTITEM_START + 43) // => SLIDE_EXIF_EXPOSURE_TIME +#define LISTITEM_PICTURE_ISO (LISTITEM_START + 44) // => SLIDE_EXIF_ISO_EQUIV +#define LISTITEM_PICTURE_GPS_LAT (LISTITEM_START + 45) // => SLIDE_EXIF_GPS_LATITUDE +#define LISTITEM_PICTURE_GPS_LON (LISTITEM_START + 46) // => SLIDE_EXIF_GPS_LONGITUDE +#define LISTITEM_PICTURE_GPS_ALT (LISTITEM_START + 47) // => SLIDE_EXIF_GPS_ALTITUDE #define LISTITEM_PICTURE_END (LISTITEM_PICTURE_GPS_ALT) -#define LISTITEM_STUDIO (LISTITEM_START + 47) -#define LISTITEM_MPAA (LISTITEM_START + 48) -#define LISTITEM_CAST (LISTITEM_START + 49) -#define LISTITEM_CAST_AND_ROLE (LISTITEM_START + 50) -#define LISTITEM_WRITER (LISTITEM_START + 51) -#define LISTITEM_TAGLINE (LISTITEM_START + 52) -#define LISTITEM_TOP250 (LISTITEM_START + 53) -#define LISTITEM_RATING_AND_VOTES (LISTITEM_START + 54) -#define LISTITEM_TRAILER (LISTITEM_START + 55) -#define LISTITEM_STAR_RATING (LISTITEM_START + 56) -#define LISTITEM_FILENAME_AND_PATH (LISTITEM_START + 57) -#define LISTITEM_SORT_LETTER (LISTITEM_START + 58) -#define LISTITEM_ALBUM_ARTIST (LISTITEM_START + 59) -#define LISTITEM_FOLDERNAME (LISTITEM_START + 60) -#define LISTITEM_VIDEO_CODEC (LISTITEM_START + 61) -#define LISTITEM_VIDEO_RESOLUTION (LISTITEM_START + 62) -#define LISTITEM_VIDEO_ASPECT (LISTITEM_START + 63) -#define LISTITEM_AUDIO_CODEC (LISTITEM_START + 64) -#define LISTITEM_AUDIO_CHANNELS (LISTITEM_START + 65) -#define LISTITEM_AUDIO_LANGUAGE (LISTITEM_START + 66) -#define LISTITEM_SUBTITLE_LANGUAGE (LISTITEM_START + 67) -#define LISTITEM_IS_FOLDER (LISTITEM_START + 68) -#define LISTITEM_ORIGINALTITLE (LISTITEM_START + 69) -#define LISTITEM_COUNTRY (LISTITEM_START + 70) -#define LISTITEM_PLAYCOUNT (LISTITEM_START + 71) -#define LISTITEM_LASTPLAYED (LISTITEM_START + 72) -#define LISTITEM_FOLDERPATH (LISTITEM_START + 73) -#define LISTITEM_DISC_NUMBER (LISTITEM_START + 74) -#define LISTITEM_FILE_EXTENSION (LISTITEM_START + 75) -#define LISTITEM_IS_RESUMABLE (LISTITEM_START + 76) -#define LISTITEM_PERCENT_PLAYED (LISTITEM_START + 77) -#define LISTITEM_DATE_ADDED (LISTITEM_START + 78) -#define LISTITEM_DBTYPE (LISTITEM_START + 79) -#define LISTITEM_DBID (LISTITEM_START + 80) +#define LISTITEM_STUDIO (LISTITEM_START + 48) +#define LISTITEM_MPAA (LISTITEM_START + 49) +#define LISTITEM_CAST (LISTITEM_START + 50) +#define LISTITEM_CAST_AND_ROLE (LISTITEM_START + 51) +#define LISTITEM_WRITER (LISTITEM_START + 52) +#define LISTITEM_TAGLINE (LISTITEM_START + 53) +#define LISTITEM_TOP250 (LISTITEM_START + 54) +#define LISTITEM_RATING_AND_VOTES (LISTITEM_START + 55) +#define LISTITEM_TRAILER (LISTITEM_START + 56) +#define LISTITEM_STAR_RATING (LISTITEM_START + 57) +#define LISTITEM_FILENAME_AND_PATH (LISTITEM_START + 58) +#define LISTITEM_SORT_LETTER (LISTITEM_START + 59) +#define LISTITEM_ALBUM_ARTIST (LISTITEM_START + 60) +#define LISTITEM_FOLDERNAME (LISTITEM_START + 61) +#define LISTITEM_VIDEO_CODEC (LISTITEM_START + 62) +#define LISTITEM_VIDEO_RESOLUTION (LISTITEM_START + 63) +#define LISTITEM_VIDEO_ASPECT (LISTITEM_START + 64) +#define LISTITEM_AUDIO_CODEC (LISTITEM_START + 65) +#define LISTITEM_AUDIO_CHANNELS (LISTITEM_START + 66) +#define LISTITEM_AUDIO_LANGUAGE (LISTITEM_START + 67) +#define LISTITEM_SUBTITLE_LANGUAGE (LISTITEM_START + 68) +#define LISTITEM_IS_FOLDER (LISTITEM_START + 69) +#define LISTITEM_ORIGINALTITLE (LISTITEM_START + 70) +#define LISTITEM_COUNTRY (LISTITEM_START + 71) +#define LISTITEM_PLAYCOUNT (LISTITEM_START + 72) +#define LISTITEM_LASTPLAYED (LISTITEM_START + 73) +#define LISTITEM_FOLDERPATH (LISTITEM_START + 74) +#define LISTITEM_DISC_NUMBER (LISTITEM_START + 75) +#define LISTITEM_FILE_EXTENSION (LISTITEM_START + 76) +#define LISTITEM_IS_RESUMABLE (LISTITEM_START + 77) +#define LISTITEM_PERCENT_PLAYED (LISTITEM_START + 78) +#define LISTITEM_DATE_ADDED (LISTITEM_START + 79) +#define LISTITEM_DBTYPE (LISTITEM_START + 80) +#define LISTITEM_DBID (LISTITEM_START + 81) #define LISTITEM_PROPERTY_START (LISTITEM_START + 200) #define LISTITEM_PROPERTY_END (LISTITEM_PROPERTY_START + 1000) diff --git a/xbmc/GUILargeTextureManager.cpp b/xbmc/GUILargeTextureManager.cpp index 60e5a84f47..89d7d7e1a2 100644 --- a/xbmc/GUILargeTextureManager.cpp +++ b/xbmc/GUILargeTextureManager.cpp @@ -22,7 +22,6 @@ #include "threads/SystemClock.h" #include "GUILargeTextureManager.h" #include "settings/GUISettings.h" -#include "FileItem.h" #include "guilib/Texture.h" #include "threads/SingleLock.h" #include "utils/TimeUtils.h" @@ -30,7 +29,6 @@ #include "guilib/GraphicContext.h" #include "utils/log.h" #include "TextureCache.h" -#include "TextureCacheJob.h" using namespace std; diff --git a/xbmc/GUIPassword.cpp b/xbmc/GUIPassword.cpp index 34b1e3a29a..cc57148849 100644 --- a/xbmc/GUIPassword.cpp +++ b/xbmc/GUIPassword.cpp @@ -21,15 +21,14 @@ #include "GUIPassword.h" #include "GUIUserMessages.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "dialogs/GUIDialogGamepad.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "dialogs/GUIDialogNumeric.h" #include "dialogs/GUIDialogOK.h" #include "settings/GUIDialogLockSettings.h" #include "settings/GUIDialogProfileSettings.h" #include "Util.h" -#include "URL.h" #include "settings/Settings.h" #include "settings/GUISettings.h" #include "guilib/GUIWindowManager.h" @@ -157,7 +156,7 @@ bool CGUIPassword::CheckStartUpLock() } else { - g_application.getApplicationMessenger().Shutdown(); // Turn off the box + CApplicationMessenger::Get().Shutdown(); // Turn off the box return false; } } @@ -467,7 +466,7 @@ int CGUIPassword::VerifyPassword(LockType btnType, const CStdString& strPassword iVerifyPasswordResult = CGUIDialogGamepad::ShowAndVerifyPassword(const_cast<CStdString&>(strPassword), strHeading, 0); break; case LOCK_MODE_QWERTY: - iVerifyPasswordResult = CGUIDialogKeyboard::ShowAndVerifyPassword(const_cast<CStdString&>(strPassword), strHeading, 0); + iVerifyPasswordResult = CGUIKeyboardFactory::ShowAndVerifyPassword(const_cast<CStdString&>(strPassword), strHeading, 0); break; default: // must not be supported, treat as unlocked iVerifyPasswordResult = 0; diff --git a/xbmc/GUIViewState.cpp b/xbmc/GUIViewState.cpp index ed86717eb4..a4d8203900 100644 --- a/xbmc/GUIViewState.cpp +++ b/xbmc/GUIViewState.cpp @@ -29,7 +29,6 @@ #include "utils/URIUtils.h" #include "URL.h" #include "GUIPassword.h" -#include "guilib/GUIBaseContainer.h" // for VIEW_TYPE_* #include "ViewDatabase.h" #include "AutoSwitch.h" #include "guilib/GUIWindowManager.h" @@ -45,6 +44,9 @@ #include "filesystem/AddonsDirectory.h" #include "guilib/TextureManager.h" +#if defined(TARGET_ANDROID) +#include "filesystem/AndroidAppDirectory.h" +#endif using namespace std; using namespace ADDON; @@ -102,6 +104,9 @@ CGUIViewState* CGUIViewState::GetViewState(int windowId, const CFileItemList& it if (items.GetPath() == "special://musicplaylists/") return new CGUIViewStateWindowMusicSongs(items); + if (url.GetProtocol() == "androidapp") + return new CGUIViewStateWindowPrograms(items); + if (windowId==WINDOW_MUSIC_NAV) return new CGUIViewStateWindowMusicNav(items); @@ -371,6 +376,25 @@ void CGUIViewState::AddAddonsSource(const CStdString &content, const CStdString } } +#if defined(TARGET_ANDROID) +void CGUIViewState::AddAndroidSource(const CStdString &content, const CStdString &label, const CStdString &thumb) +{ + CFileItemList items; + XFILE::CAndroidAppDirectory apps; + if (apps.GetDirectory(content, items)) + { + CMediaSource source; + source.strPath = "androidapp://sources/" + content + "/"; + source.strName = label; + if (!thumb.IsEmpty() && g_TextureManager.HasTexture(thumb)) + source.m_strThumbnailImage = thumb; + source.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL; + source.m_ignore = true; + m_sources.push_back(source); + } +} +#endif + void CGUIViewState::AddLiveTVSources() { VECSOURCES *sources = g_settings.GetSourcesFromType("video"); diff --git a/xbmc/GUIViewState.h b/xbmc/GUIViewState.h index 928e059a68..07b968bf17 100644 --- a/xbmc/GUIViewState.h +++ b/xbmc/GUIViewState.h @@ -23,7 +23,6 @@ #include "utils/LabelFormatter.h" #include "SortFileItem.h" -#include "guilib/GUIBaseContainer.h" #include "MediaSource.h" class CViewState; // forward @@ -73,6 +72,9 @@ protected: \param thumb the skin image to use as the icon */ void AddAddonsSource(const CStdString &content, const CStdString &label, const CStdString& thumb); +#if defined(TARGET_ANDROID) + void AddAndroidSource(const CStdString &content, const CStdString &label, const CStdString& thumb); +#endif void AddLiveTVSources(); void AddSortMethod(SORT_METHOD sortMethod, int buttonLabel, LABEL_MASKS labelmasks); diff --git a/xbmc/Makefile.in b/xbmc/Makefile.in index 4db5f0db7a..f0d2bae73e 100644 --- a/xbmc/Makefile.in +++ b/xbmc/Makefile.in @@ -5,6 +5,7 @@ SRCS=Application.cpp \ BackgroundInfoLoader.cpp \ CueDocument.cpp \ DatabaseManager.cpp \ + DbUrl.cpp \ DynamicDll.cpp \ Favourites.cpp \ FileItem.cpp \ diff --git a/xbmc/NfoFile.cpp b/xbmc/NfoFile.cpp index e55570b4eb..813948e118 100644 --- a/xbmc/NfoFile.cpp +++ b/xbmc/NfoFile.cpp @@ -27,12 +27,10 @@ #include "addons/AddonManager.h" #include "filesystem/File.h" #include "settings/GUISettings.h" -#include "Util.h" #include "FileItem.h" #include "music/Album.h" #include "music/Artist.h" #include "settings/GUISettings.h" -#include "LangInfo.h" #include "utils/log.h" #include <vector> diff --git a/xbmc/PartyModeManager.cpp b/xbmc/PartyModeManager.cpp index 8ebfa30805..964dcf1495 100644 --- a/xbmc/PartyModeManager.cpp +++ b/xbmc/PartyModeManager.cpp @@ -113,11 +113,7 @@ bool CPartyModeManager::Enable(PartyModeContext context /*= PARTYMODECONTEXT_MUS { set<CStdString> playlists; if ( playlistLoaded ) - { m_strCurrentFilterMusic = playlist.GetWhereClause(db, playlists); - if (!m_strCurrentFilterMusic.empty()) - m_strCurrentFilterMusic = "WHERE " + m_strCurrentFilterMusic; - } CLog::Log(LOGINFO, "PARTY MODE MANAGER: Registering filter:[%s]", m_strCurrentFilterMusic.c_str()); m_iMatchingSongs = (int)db.GetSongIDs(m_strCurrentFilterMusic, songIDs); @@ -146,11 +142,7 @@ bool CPartyModeManager::Enable(PartyModeContext context /*= PARTYMODECONTEXT_MUS { set<CStdString> playlists; if ( playlistLoaded ) - { m_strCurrentFilterVideo = playlist.GetWhereClause(db, playlists); - if (!m_strCurrentFilterVideo.empty()) - m_strCurrentFilterVideo = "WHERE " + m_strCurrentFilterVideo; - } CLog::Log(LOGINFO, "PARTY MODE MANAGER: Registering filter:[%s]", m_strCurrentFilterVideo.c_str()); m_iMatchingSongs += (int)db.GetMusicVideoIDs(m_strCurrentFilterVideo, songIDs2); @@ -594,8 +586,8 @@ bool CPartyModeManager::AddInitialSongs(vector<pair<int,int> > &songIDs) vector<pair<int,int> > chosenSongIDs; GetRandomSelection(songIDs, iMissingSongs, chosenSongIDs); - CStdString sqlWhereMusic = "where songview.idSong in ("; - CStdString sqlWhereVideo = "idMVideo in ("; + CStdString sqlWhereMusic = "songview.idSong IN ("; + CStdString sqlWhereVideo = "idMVideo IN ("; for (vector< pair<int,int> >::iterator it = chosenSongIDs.begin(); it != chosenSongIDs.end(); it++) { @@ -614,7 +606,7 @@ bool CPartyModeManager::AddInitialSongs(vector<pair<int,int> > &songIDs) sqlWhereMusic[sqlWhereMusic.size() - 1] = ')'; // replace the last comma with closing bracket CMusicDatabase database; database.Open(); - database.GetSongsByWhere("", sqlWhereMusic, items); + database.GetSongsByWhere("musicdb://4/", sqlWhereMusic, items); } if (sqlWhereVideo.size() > 19) { @@ -644,7 +636,7 @@ pair<CStdString,CStdString> CPartyModeManager::GetWhereClauseWithHistory() const if (m_history.size()) { if (m_strCurrentFilterMusic.IsEmpty()) - historyWhereMusic = "where songview.idSong not in ("; + historyWhereMusic = "songview.idSong not in ("; else historyWhereMusic = m_strCurrentFilterMusic + " and songview.idSong not in ("; if (m_strCurrentFilterVideo.IsEmpty()) @@ -673,7 +665,7 @@ void CPartyModeManager::AddToHistory(int type, int songID) { while (m_history.size() >= m_songsInHistory && m_songsInHistory) m_history.erase(m_history.begin()); - m_history.push_back(make_pair<int,int>(type,songID)); + m_history.push_back(make_pair(type,songID)); } void CPartyModeManager::GetRandomSelection(vector< pair<int,int> >& in, unsigned int number, vector< pair<int,int> >& out) diff --git a/xbmc/PasswordManager.cpp b/xbmc/PasswordManager.cpp index 5c7cfcbe11..63e10bcb95 100644 --- a/xbmc/PasswordManager.cpp +++ b/xbmc/PasswordManager.cpp @@ -85,6 +85,10 @@ bool CPasswordManager::PromptToAuthenticateURL(CURL &url) void CPasswordManager::SaveAuthenticatedURL(const CURL &url, bool saveToProfile) { + // don't store/save authenticated url if it doesn't contain username + if (url.GetUserName().IsEmpty()) + return; + CSingleLock lock(m_critSection); CStdString path = GetLookupPath(url); diff --git a/xbmc/SectionLoader.h b/xbmc/SectionLoader.h index 0b0d7ad3b7..b738fcd041 100644 --- a/xbmc/SectionLoader.h +++ b/xbmc/SectionLoader.h @@ -45,12 +45,12 @@ public: static LibraryLoader* LoadDLL(const CStdString& strSection, bool bDelayUnload=true, bool bLoadSymbols=false); static void UnloadDLL(const CStdString& strSection); static void UnloadDelayed(); + void UnloadAll(); + protected: std::vector<CDll> m_vecLoadedDLLs; CCriticalSection m_critSection; -private: - void UnloadAll(); }; XBMC_GLOBAL_REF(CSectionLoader,g_sectionLoader); diff --git a/xbmc/TextureCache.cpp b/xbmc/TextureCache.cpp index 9d63405039..8288c2daa1 100644 --- a/xbmc/TextureCache.cpp +++ b/xbmc/TextureCache.cpp @@ -28,6 +28,7 @@ #include "settings/AdvancedSettings.h" #include "utils/log.h" #include "utils/URIUtils.h" +#include "URL.h" using namespace XFILE; @@ -64,6 +65,7 @@ bool CTextureCache::IsCachedImage(const CStdString &url) const if (url != "-" && !CURL::IsFullPath(url)) return true; if (URIUtils::IsInPath(url, "special://skin/") || + URIUtils::IsInPath(url, "androidapp://") || URIUtils::IsInPath(url, g_settings.GetThumbnailsFolder())) return true; return false; @@ -72,7 +74,8 @@ bool CTextureCache::IsCachedImage(const CStdString &url) const bool CTextureCache::HasCachedImage(const CStdString &url) { CStdString cachedHash; - return !GetCachedImage(url, cachedHash).IsEmpty(); + CStdString cachedImage(GetCachedImage(url, cachedHash)); + return (!cachedImage.IsEmpty() && cachedImage != url); } CStdString CTextureCache::GetCachedImage(const CStdString &image, CStdString &cachedHash, bool trackUsage) diff --git a/xbmc/TextureCache.h b/xbmc/TextureCache.h index 22a51be273..0a2733e305 100644 --- a/xbmc/TextureCache.h +++ b/xbmc/TextureCache.h @@ -92,7 +92,8 @@ public: */ CStdString CacheImage(const CStdString &url, CBaseTexture **texture = NULL); - /*! \brief Check whether an image is cached + /*! \brief Check whether an image is in the cache + Note: If the image url won't normally be cached (eg a skin image) this function will return false. \param image url of the image \return true if the image is cached, false otherwise \sa ClearCachedImage diff --git a/xbmc/TextureCacheJob.cpp b/xbmc/TextureCacheJob.cpp index 0fe6de10c6..cd12ee85be 100644 --- a/xbmc/TextureCacheJob.cpp +++ b/xbmc/TextureCacheJob.cpp @@ -180,7 +180,7 @@ CBaseTexture *CTextureCacheJob::LoadImage(const CStdString &image, unsigned int // Validate file URL to see if it is an image CFileItem file(image, false); if (!(file.IsPicture() && !(file.IsZIP() || file.IsRAR() || file.IsCBR() || file.IsCBZ() )) - && !file.GetMimeType().Left(6).Equals("image/")) // ignore non-pictures + && !file.GetMimeType().Left(6).Equals("image/") && !file.GetMimeType().Equals("application/octet-stream")) // ignore non-pictures return NULL; CBaseTexture *texture = CBaseTexture::LoadFromFile(image, width, height, g_guiSettings.GetBool("pictures.useexifrotation")); diff --git a/xbmc/ThumbLoader.cpp b/xbmc/ThumbLoader.cpp index 14f60f9d25..80c324251a 100644 --- a/xbmc/ThumbLoader.cpp +++ b/xbmc/ThumbLoader.cpp @@ -109,6 +109,7 @@ bool CThumbExtractor::DoWork() || m_item.IsDVDImage() || m_item.IsDVDFile(false, true) || m_item.IsInternetStream() + || m_item.IsDiscStub() || m_item.IsPlayList()) return false; @@ -197,14 +198,6 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem) m_database->Open(); - // resume point - if (pItem->HasVideoInfoTag() && - pItem->GetVideoInfoTag()->m_resumePoint.type != CBookmark::RESUME && pItem->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds == 0) - { - if (m_database->GetResumePoint(*pItem->GetVideoInfoTag())) - pItem->SetInvalid(); - } - if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->HasStreamDetails() && (pItem->GetVideoInfoTag()->m_type == "movie" || pItem->GetVideoInfoTag()->m_type == "episode" || pItem->GetVideoInfoTag()->m_type == "musicvideo")) { diff --git a/xbmc/URL.cpp b/xbmc/URL.cpp index 031051e61d..a1e8085c84 100644 --- a/xbmc/URL.cpp +++ b/xbmc/URL.cpp @@ -97,9 +97,14 @@ void CURL::Parse(const CStdString& strURL1) // example: filename /foo/bar.zip/alice.rar/bob.avi // This should turn into zip://rar:///foo/bar.zip/alice.rar/bob.avi iPos = 0; + bool is_apk = (strURL.Find(".apk/", iPos) > 0); while (1) { - iPos = strURL.Find(".zip/", iPos); + if (is_apk) + iPos = strURL.Find(".apk/", iPos); + else + iPos = strURL.Find(".zip/", iPos); + int extLen = 3; if (iPos < 0) { @@ -119,8 +124,16 @@ void CURL::Parse(const CStdString& strURL1) #endif { Encode(archiveName); - CURL c((CStdString)"zip" + "://" + archiveName + '/' + strURL.Right(strURL.size() - iPos - 1)); - *this = c; + if (is_apk) + { + CURL c((CStdString)"apk" + "://" + archiveName + '/' + strURL.Right(strURL.size() - iPos - 1)); + *this = c; + } + else + { + CURL c((CStdString)"zip" + "://" + archiveName + '/' + strURL.Right(strURL.size() - iPos - 1)); + *this = c; + } return; } } @@ -161,7 +174,10 @@ void CURL::Parse(const CStdString& strURL1) if(m_strProtocol.Equals("rss") || m_strProtocol.Equals("rar") || m_strProtocol.Equals("addons") || - m_strProtocol.Equals("image")) + m_strProtocol.Equals("image") || + m_strProtocol.Equals("videodb") || + m_strProtocol.Equals("musicdb") || + m_strProtocol.Equals("androidapp")) sep = "?"; else if(strProtocol2.Equals("http") @@ -169,6 +185,7 @@ void CURL::Parse(const CStdString& strURL1) || strProtocol2.Equals("plugin") || strProtocol2.Equals("hdhomerun") || strProtocol2.Equals("rtsp") + || strProtocol2.Equals("apk") || strProtocol2.Equals("zip")) sep = "?;#|"; else if(strProtocol2.Equals("ftp") @@ -454,7 +471,10 @@ const CStdString& CURL::GetProtocolOptions() const const CStdString CURL::GetFileNameWithoutPath() const { // *.zip and *.rar store the actual zip/rar path in the hostname of the url - if ((m_strProtocol == "rar" || m_strProtocol == "zip") && m_strFileName.IsEmpty()) + if ((m_strProtocol == "rar" || + m_strProtocol == "zip" || + m_strProtocol == "apk") && + m_strFileName.IsEmpty()) return URIUtils::GetFileName(m_strHostName); // otherwise, we've already got the filepath, so just grab the filename portion @@ -707,6 +727,20 @@ void CURL::Encode(CStdString& strURLData) strURLData = strResult; } +std::string CURL::Decode(const std::string& strURLData) +{ + CStdString url = strURLData; + Decode(url); + return url; +} + +std::string CURL::Encode(const std::string& strURLData) +{ + CStdString url = strURLData; + Encode(url); + return url; +} + CStdString CURL::TranslateProtocol(const CStdString& prot) { if (prot == "shout" diff --git a/xbmc/URL.h b/xbmc/URL.h index 2807e5a06a..ed2f7eeeda 100644 --- a/xbmc/URL.h +++ b/xbmc/URL.h @@ -71,6 +71,8 @@ public: static bool IsFullPath(const CStdString &url); ///< return true if the url includes the full path static void Decode(CStdString& strURLData); static void Encode(CStdString& strURLData); + static std::string Decode(const std::string& strURLData); + static std::string Encode(const std::string& strURLData); static CStdString TranslateProtocol(const CStdString& prot); protected: diff --git a/xbmc/Util.cpp b/xbmc/Util.cpp index f1e5983492..11b0077f86 100644 --- a/xbmc/Util.cpp +++ b/xbmc/Util.cpp @@ -39,13 +39,11 @@ #endif #include "Application.h" -#include "utils/AutoPtrHandle.h" #include "Util.h" #include "addons/Addon.h" -#include "storage/IoSupport.h" +#include "filesystem/Directory.h" #include "filesystem/StackDirectory.h" #include "filesystem/MultiPathDirectory.h" -#include "filesystem/DirectoryCache.h" #include "filesystem/SpecialProtocol.h" #include "filesystem/RSSDirectory.h" #ifdef HAS_FILESYSTEM_RAR @@ -63,9 +61,6 @@ #include "guilib/TextureManager.h" #include "utils/fstrcmp.h" #include "storage/MediaManager.h" -#include "guilib/DirectXGraphics.h" -#include "network/DNSNameCache.h" -#include "guilib/GUIWindowManager.h" #ifdef _WIN32 #include <shlobj.h> #include "WIN32Util.h" @@ -75,7 +70,6 @@ #endif #include "GUIUserMessages.h" #include "filesystem/File.h" -#include "utils/Crc32.h" #include "settings/Settings.h" #include "utils/StringUtils.h" #include "settings/AdvancedSettings.h" @@ -92,7 +86,7 @@ #include "cores/dvdplayer/DVDSubtitles/DVDSubtitleTagSami.h" #include "cores/dvdplayer/DVDSubtitles/DVDSubtitleStream.h" #include "windowing/WindowingFactory.h" -#include "video/VideoInfoTag.h" +#include "URL.h" #ifdef HAVE_LIBCAP #include <sys/capability.h> #endif @@ -104,7 +98,6 @@ using namespace XFILE; static const int64_t SECS_BETWEEN_EPOCHS = 11644473600LL; static const int64_t SECS_TO_100NS = 10000000; -using namespace AUTOPTR; using namespace XFILE; using namespace PLAYLIST; @@ -1237,6 +1230,7 @@ CStdString CUtil::ValidatePath(const CStdString &path, bool bFixDoubleSlashes /* // recurse and crash XBMC if (URIUtils::IsURL(path) && (path.Find('%') >= 0 || + path.Left(4).Equals("apk:") || path.Left(4).Equals("zip:") || path.Left(4).Equals("rar:") || path.Left(6).Equals("stack:") || diff --git a/xbmc/XBApplicationEx.cpp b/xbmc/XBApplicationEx.cpp index eda90027c7..0a73343a3e 100644 --- a/xbmc/XBApplicationEx.cpp +++ b/xbmc/XBApplicationEx.cpp @@ -73,14 +73,14 @@ INT CXBApplicationEx::Run(bool renderGUI) { CLog::Log(LOGNOTICE, "Running the application..." ); - BYTE processExceptionCount = 0; - BYTE frameMoveExceptionCount = 0; - BYTE renderExceptionCount = 0; unsigned int lastFrameTime = 0; unsigned int frameTime = 0; const unsigned int noRenderFrameTime = 15; // Simulates ~66fps #ifndef _DEBUG + BYTE processExceptionCount = 0; + BYTE frameMoveExceptionCount = 0; + BYTE renderExceptionCount = 0; const BYTE MAX_EXCEPTION_COUNT = 10; #endif @@ -100,9 +100,8 @@ INT CXBApplicationEx::Run(bool renderGUI) lastFrameTime = XbmcThreads::SystemClockMillis(); Process(); //reset exception count - processExceptionCount = 0; - #ifndef _DEBUG + processExceptionCount = 0; } catch (...) @@ -124,9 +123,8 @@ INT CXBApplicationEx::Run(bool renderGUI) #endif if (!m_bStop) FrameMove(true, renderGUI); //reset exception count - frameMoveExceptionCount = 0; - #ifndef _DEBUG + frameMoveExceptionCount = 0; } catch (...) @@ -154,12 +152,10 @@ INT CXBApplicationEx::Run(bool renderGUI) if(frameTime < noRenderFrameTime) Sleep(noRenderFrameTime - frameTime); } - +#ifndef _DEBUG //reset exception count renderExceptionCount = 0; -#ifndef _DEBUG - } catch (...) { diff --git a/xbmc/addons/Addon.cpp b/xbmc/addons/Addon.cpp index ed26edfe33..ddb28c0e9f 100644 --- a/xbmc/addons/Addon.cpp +++ b/xbmc/addons/Addon.cpp @@ -34,6 +34,7 @@ #endif #include "utils/log.h" #include "utils/URIUtils.h" +#include "URL.h" #include <vector> #include <string.h> #include <ostream> diff --git a/xbmc/addons/Addon.h b/xbmc/addons/Addon.h index fabc1ce33b..553a0c880f 100644 --- a/xbmc/addons/Addon.h +++ b/xbmc/addons/Addon.h @@ -23,11 +23,8 @@ #include "IAddon.h" #include "addons/AddonVersion.h" #include "utils/XBMCTinyXML.h" -#include "Util.h" -#include "URL.h" #include "guilib/LocalizeStrings.h" -class CURL; class TiXmlElement; typedef struct cp_plugin_info_t cp_plugin_info_t; diff --git a/xbmc/addons/AddonDatabase.cpp b/xbmc/addons/AddonDatabase.cpp index fa13a3a7d7..743e7ac4bb 100644 --- a/xbmc/addons/AddonDatabase.cpp +++ b/xbmc/addons/AddonDatabase.cpp @@ -268,7 +268,7 @@ bool CAddonDatabase::GetAddon(int id, AddonPtr& addon) m_pDS2->query(sql.c_str()); while (!m_pDS2->eof()) { - props.dependencies.insert(make_pair(m_pDS2->fv(0).get_asString(), make_pair(m_pDS2->fv(1).get_asString(), m_pDS2->fv(2).get_asBool()))); + props.dependencies.insert(make_pair(m_pDS2->fv(0).get_asString(), make_pair(AddonVersion(m_pDS2->fv(1).get_asString()), m_pDS2->fv(2).get_asBool()))); m_pDS2->next(); } diff --git a/xbmc/addons/AddonDll.h b/xbmc/addons/AddonDll.h index e7451e8f87..42d002f394 100644 --- a/xbmc/addons/AddonDll.h +++ b/xbmc/addons/AddonDll.h @@ -81,9 +81,12 @@ template<class TheDll, typename TheStruct, typename TheProps> CAddonDll<TheDll, TheStruct, TheProps>::CAddonDll(const cp_extension_t *ext) : CAddon(ext) { - if (ext) + // if library attribute isn't present, look for a system-dependent one + if (ext && m_strLibName.IsEmpty()) { -#if defined(_LINUX) && !defined(TARGET_DARWIN) +#if defined(TARGET_ANDROID) + m_strLibName = CAddonMgr::Get().GetExtValue(ext->configuration, "@library_android"); +#elif defined(_LINUX) && !defined(TARGET_DARWIN) m_strLibName = CAddonMgr::Get().GetExtValue(ext->configuration, "@library_linux"); #elif defined(_WIN32) && defined(HAS_SDL_OPENGL) m_strLibName = CAddonMgr::Get().GetExtValue(ext->configuration, "@library_wingl"); @@ -147,6 +150,15 @@ bool CAddonDll<TheDll, TheStruct, TheProps>::LoadDll() } /* Check if lib being loaded exists, else check in XBMC binary location */ +#if defined(TARGET_ANDROID) + // Android libs MUST live in this path, else multi-arch will break. + // The usual soname requirements apply. no subdirs, and filename is ^lib.*\.so$ + if (!CFile::Exists(strFileName)) + { + CStdString tempbin = getenv("XBMC_ANDROID_LIBS"); + strFileName = tempbin + "/" + m_strLibName; + } +#endif if (!CFile::Exists(strFileName)) { CStdString temp = CSpecialProtocol::TranslatePath("special://xbmc/"); @@ -228,18 +240,25 @@ void CAddonDll<TheDll, TheStruct, TheProps>::Stop() { strcpy(str_id, "###GetSavedSettings"); sprintf (str_value, "%i", i); - m_pDll->SetSetting((const char*)&str_id, (void*)&str_value); + ADDON_STATUS status = m_pDll->SetSetting((const char*)&str_id, (void*)&str_value); + + if (status == ADDON_STATUS_UNKNOWN) + break; + if (strcmp(str_id,"###End") != 0) UpdateSetting(str_id, str_value); } CAddon::SaveSettings(); } - if (m_pDll) m_pDll->Stop(); + if (m_pDll) + { + m_pDll->Stop(); + CLog::Log(LOGINFO, "ADDON: Dll Stopped - %s", Name().c_str()); + } } catch (std::exception &e) { HandleException(e, "m_pDll->Stop"); } - CLog::Log(LOGINFO, "ADDON: Dll Stopped - %s", Name().c_str()); } template<class TheDll, typename TheStruct, typename TheProps> @@ -260,10 +279,13 @@ void CAddonDll<TheDll, TheStruct, TheProps>::Destroy() } free(m_pStruct); m_pStruct = NULL; - delete m_pDll; - m_pDll = NULL; + if (m_pDll) + { + delete m_pDll; + m_pDll = NULL; + CLog::Log(LOGINFO, "ADDON: Dll Destroyed - %s", Name().c_str()); + } m_initialized = false; - CLog::Log(LOGINFO, "ADDON: Dll Destroyed - %s", Name().c_str()); } template<class TheDll, typename TheStruct, typename TheProps> diff --git a/xbmc/addons/AddonInstaller.cpp b/xbmc/addons/AddonInstaller.cpp index 52ce0bb76d..82736732c8 100644 --- a/xbmc/addons/AddonInstaller.cpp +++ b/xbmc/addons/AddonInstaller.cpp @@ -28,7 +28,7 @@ #include "filesystem/Directory.h" #include "settings/GUISettings.h" #include "settings/Settings.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "Favourites.h" #include "utils/JobManager.h" #include "dialogs/GUIDialogYesNo.h" @@ -39,6 +39,7 @@ #include "utils/StringUtils.h" #include "dialogs/GUIDialogKaiToast.h" #include "dialogs/GUIDialogProgress.h" +#include "URL.h" using namespace std; using namespace XFILE; @@ -467,7 +468,7 @@ bool CAddonInstallJob::OnPreInstall() // check whether this is an active skin - we need to unload it if so if (g_guiSettings.GetString("lookandfeel.skin") == m_addon->ID()) { - g_application.getApplicationMessenger().ExecBuiltIn("UnloadSkin", true); + CApplicationMessenger::Get().ExecBuiltIn("UnloadSkin", true); return true; } @@ -572,7 +573,7 @@ void CAddonInstallJob::OnPostInstall(bool reloadAddon) toast->ResetTimer(); toast->Close(true); } - g_application.getApplicationMessenger().ExecBuiltIn("ReloadSkin"); + CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin"); } } diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp index c796469f68..3ab9e9f2e4 100644 --- a/xbmc/addons/AddonManager.cpp +++ b/xbmc/addons/AddonManager.cpp @@ -31,7 +31,6 @@ #include "settings/AdvancedSettings.h" #include "utils/log.h" #include "utils/XBMCTinyXML.h" -#include "dialogs/GUIDialogYesNo.h" #ifdef HAS_VISUALISATION #include "Visualisation.h" #endif @@ -45,6 +44,7 @@ #include "Repository.h" #include "Skin.h" #include "Service.h" +#include "Util.h" using namespace std; @@ -116,7 +116,16 @@ AddonPtr CAddonMgr::Factory(const cp_extension_t *props) { // built in screensaver return AddonPtr(new CAddon(props)); } -#if defined(_LINUX) && !defined(TARGET_DARWIN) + if (type == ADDON_SCREENSAVER) + { // Python screensaver + CStdString library = CAddonMgr::Get().GetExtValue(props->configuration, "@library"); + if (URIUtils::GetExtension(library).Equals(".py", false)) + return AddonPtr(new CScreenSaver(props)); + } +#if defined(TARGET_ANDROID) + if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_android")) && value.empty()) + break; + #elif defined(_LINUX) && !defined(TARGET_DARWIN) if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_linux")) && value.empty()) break; #elif defined(_WIN32) && defined(HAS_SDL_OPENGL) @@ -580,7 +589,9 @@ bool CAddonMgr::PlatformSupportsAddon(const cp_plugin_info_t *plugin) const { if (platforms[i] == "all") return true; -#if defined(_LINUX) && !defined(TARGET_DARWIN) +#if defined(TARGET_ANDROID) + if (platforms[i] == "android") +#elif defined(_LINUX) && !defined(TARGET_DARWIN) if (platforms[i] == "linux") #elif defined(_WIN32) && defined(HAS_SDL_OPENGL) if (platforms[i] == "wingl") diff --git a/xbmc/addons/AddonStatusHandler.cpp b/xbmc/addons/AddonStatusHandler.cpp index f7397f95c3..032d620ed4 100644 --- a/xbmc/addons/AddonStatusHandler.cpp +++ b/xbmc/addons/AddonStatusHandler.cpp @@ -21,7 +21,7 @@ #include "AddonStatusHandler.h" #include "AddonManager.h" #include "threads/SingleLock.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "guilib/GUIWindowManager.h" #include "GUIDialogAddonSettings.h" #include "dialogs/GUIDialogYesNo.h" @@ -95,7 +95,7 @@ void CAddonStatusHandler::Process() //send message and wait for user input ThreadMessage tMsg = {TMSG_DIALOG_DOMODAL, WINDOW_DIALOG_YES_NO, g_windowManager.GetActiveWindow()}; - g_application.getApplicationMessenger().SendMessage(tMsg, true); + CApplicationMessenger::Get().SendMessage(tMsg, true); if (pDialog->IsConfirmed()) CAddonMgr::Get().GetCallbackForType(m_addon->Type())->RequestRestart(m_addon, false); @@ -111,7 +111,7 @@ void CAddonStatusHandler::Process() //send message and wait for user input ThreadMessage tMsg = {TMSG_DIALOG_DOMODAL, WINDOW_DIALOG_OK, g_windowManager.GetActiveWindow()}; - g_application.getApplicationMessenger().SendMessage(tMsg, true); + CApplicationMessenger::Get().SendMessage(tMsg, true); CAddonMgr::Get().GetCallbackForType(m_addon->Type())->RequestRestart(m_addon, true); } @@ -128,7 +128,7 @@ void CAddonStatusHandler::Process() //send message and wait for user input ThreadMessage tMsg = {TMSG_DIALOG_DOMODAL, WINDOW_DIALOG_YES_NO, g_windowManager.GetActiveWindow()}; - g_application.getApplicationMessenger().SendMessage(tMsg, true); + CApplicationMessenger::Get().SendMessage(tMsg, true); if (!pDialogYesNo->IsConfirmed()) return; @@ -156,7 +156,7 @@ void CAddonStatusHandler::Process() //send message and wait for user input ThreadMessage tMsg = {TMSG_DIALOG_DOMODAL, WINDOW_DIALOG_OK, g_windowManager.GetActiveWindow()}; - g_application.getApplicationMessenger().SendMessage(tMsg, true); + CApplicationMessenger::Get().SendMessage(tMsg, true); } } diff --git a/xbmc/addons/GUIDialogAddonSettings.cpp b/xbmc/addons/GUIDialogAddonSettings.cpp index e2a5aa2d04..8286d49949 100644 --- a/xbmc/addons/GUIDialogAddonSettings.cpp +++ b/xbmc/addons/GUIDialogAddonSettings.cpp @@ -39,8 +39,8 @@ #include "video/VideoInfoScanner.h" #include "addons/Scraper.h" #include "guilib/GUIWindowManager.h" -#include "Application.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "ApplicationMessenger.h" +#include "guilib/GUIKeyboardFactory.h" #include "FileItem.h" #include "settings/Settings.h" #include "GUIInfoManager.h" @@ -48,6 +48,8 @@ #include "dialogs/GUIDialogSelect.h" #include "GUIWindowAddonBrowser.h" #include "utils/log.h" +#include "Util.h" +#include "URL.h" using namespace std; using namespace ADDON; @@ -98,7 +100,7 @@ bool CGUIDialogAddonSettings::OnMessage(CGUIMessage& message) bool bCloseDialog = false; if (iControl == ID_BUTTON_DEFAULT) - SetDefaults(); + SetDefaultSettings(); else if (iControl != ID_BUTTON_OK) bCloseDialog = ShowVirtualKeyboard(iControl); @@ -249,7 +251,7 @@ bool CGUIDialogAddonSettings::ShowVirtualKeyboard(int iControl) if (bEncoded) CURL::Decode(value); - if (CGUIDialogKeyboard::ShowAndGetInput(value, label, true, bHidden)) + if (CGUIKeyboardFactory::ShowAndGetInput(value, label, true, bHidden)) { // if hidden hide input if (bHidden) @@ -408,7 +410,7 @@ bool CGUIDialogAddonSettings::ShowVirtualKeyboard(int iControl) action.Replace("$ID", m_addon->ID()); if (option) bCloseDialog = (strcmpi(option, "close") == 0); - g_application.getApplicationMessenger().ExecBuiltIn(action); + CApplicationMessenger::Get().ExecBuiltIn(action); } } else if (strcmp(type, "date") == 0) @@ -1079,7 +1081,7 @@ CStdString CGUIDialogAddonSettings::GetString(const char *value, bool subSetting } // Go over all the settings and set their default values -void CGUIDialogAddonSettings::SetDefaults() +void CGUIDialogAddonSettings::SetDefaultSettings() { if(!m_addon) return; diff --git a/xbmc/addons/GUIDialogAddonSettings.h b/xbmc/addons/GUIDialogAddonSettings.h index 4483e9ce8b..4939c7c651 100644 --- a/xbmc/addons/GUIDialogAddonSettings.h +++ b/xbmc/addons/GUIDialogAddonSettings.h @@ -70,7 +70,7 @@ private: void FreeControls(); void UpdateFromControls(); void EnableControls(); - void SetDefaults(); + void SetDefaultSettings(); bool GetCondition(const CStdString &condition, const int controlId); void SaveSettings(void); diff --git a/xbmc/addons/GUIWindowAddonBrowser.cpp b/xbmc/addons/GUIWindowAddonBrowser.cpp index de34c94ab7..8ce8991db9 100644 --- a/xbmc/addons/GUIWindowAddonBrowser.cpp +++ b/xbmc/addons/GUIWindowAddonBrowser.cpp @@ -22,10 +22,8 @@ #include "GUIWindowAddonBrowser.h" #include "addons/AddonManager.h" #include "addons/Repository.h" -#include "dialogs/GUIDialogContextMenu.h" #include "GUIDialogAddonInfo.h" #include "GUIDialogAddonSettings.h" -#include "dialogs/GUIDialogKeyboard.h" #include "dialogs/GUIDialogYesNo.h" #include "dialogs/GUIDialogSelect.h" #include "dialogs/GUIDialogFileBrowser.h" diff --git a/xbmc/addons/PluginSource.h b/xbmc/addons/PluginSource.h index b5fea263dd..75cce2b07b 100644 --- a/xbmc/addons/PluginSource.h +++ b/xbmc/addons/PluginSource.h @@ -35,8 +35,15 @@ public: CPluginSource(const AddonProps &props); virtual ~CPluginSource() {} virtual bool IsType(TYPE type) const; - bool Provides(const Content& content) const { - return content == UNKNOWN ? false : m_providedContent.count(content) > 0; } + bool Provides(const Content& content) const + { + return content == UNKNOWN ? false : m_providedContent.count(content) > 0; + } + + bool ProvidesSeveral() const + { + return m_providedContent.size() > 1; + } static Content Translate(const CStdString &content); private: diff --git a/xbmc/addons/Repository.cpp b/xbmc/addons/Repository.cpp index 1957394db1..1083b60cb5 100644 --- a/xbmc/addons/Repository.cpp +++ b/xbmc/addons/Repository.cpp @@ -32,6 +32,7 @@ #include "dialogs/GUIDialogYesNo.h" #include "dialogs/GUIDialogKaiToast.h" #include "TextureDatabase.h" +#include "URL.h" using namespace XFILE; using namespace ADDON; @@ -92,19 +93,21 @@ CStdString CRepository::FetchChecksum(const CStdString& url) CSingleLock lock(m_critSection); CFile file; file.Open(url); - CStdString checksum; try { - char* temp = new char[(size_t)file.GetLength()+1]; - file.Read(temp,file.GetLength()); - temp[file.GetLength()] = 0; - checksum = temp; - delete[] temp; + // we intentionally avoid using file.GetLength() for + // Transfer-Encoding: chunked servers. + std::stringstream str; + char temp[1024]; + int read; + while ((read=file.Read(temp, sizeof(temp))) > 0) + str.write(temp, read); + return str.str(); } catch (...) { + return ""; } - return checksum; } CStdString CRepository::GetAddonHash(const AddonPtr& addon) diff --git a/xbmc/addons/Repository.h b/xbmc/addons/Repository.h index ca0775da5e..741b58c0f7 100644 --- a/xbmc/addons/Repository.h +++ b/xbmc/addons/Repository.h @@ -23,7 +23,6 @@ #include "Addon.h" #include "AddonManager.h" #include "XBDateTime.h" -#include "URL.h" #include "utils/Job.h" #include "threads/CriticalSection.h" #include "threads/SingleLock.h" diff --git a/xbmc/addons/Scraper.cpp b/xbmc/addons/Scraper.cpp index 15f23401d5..310f738985 100644 --- a/xbmc/addons/Scraper.cpp +++ b/xbmc/addons/Scraper.cpp @@ -39,6 +39,9 @@ #include "video/VideoDatabase.h" #include "music/Album.h" #include "music/Artist.h" +#include "Util.h" +#include "URL.h" + #include <sstream> using namespace std; diff --git a/xbmc/addons/ScreenSaver.cpp b/xbmc/addons/ScreenSaver.cpp index 1da9caa238..dce9ce8e38 100644 --- a/xbmc/addons/ScreenSaver.cpp +++ b/xbmc/addons/ScreenSaver.cpp @@ -22,6 +22,16 @@ #include "settings/Settings.h" #include "windowing/WindowingFactory.h" +#ifdef HAS_PYTHON +#include "interfaces/python/XBPython.h" +#include "utils/AlarmClock.h" + +// What sound does a python screensaver make? +#define PYTHON_ALARM "sssssscreensaver" + +#define PYTHON_SCRIPT_TIMEOUT 5 // seconds +#endif + namespace ADDON { @@ -32,6 +42,17 @@ namespace ADDON bool CScreenSaver::CreateScreenSaver() { +#ifdef HAS_PYTHON + if (URIUtils::GetExtension(LibPath()).Equals(".py", false)) + { + // Don't allow a previously-scheduled alarm to kill our new screensaver + g_alarmClock.Stop(PYTHON_ALARM); + + if (!g_pythonParser.StopScript(LibPath())) + g_pythonParser.evalFile(LibPath(), AddonPtr(new CScreenSaver(Props()))); + return true; + } +#endif // pass it the screen width,height // and the name of the screensaver int iWidth = g_graphicsContext.GetWidth(); @@ -78,6 +99,13 @@ void CScreenSaver::GetInfo(SCR_INFO *info) void CScreenSaver::Destroy() { +#ifdef HAS_PYTHON + if (URIUtils::GetExtension(LibPath()).Equals(".py", false)) + { + g_alarmClock.Start(PYTHON_ALARM, PYTHON_SCRIPT_TIMEOUT, "StopScript(" + LibPath() + ")", true, false); + return; + } +#endif // Release what was allocated in method CScreenSaver::CreateScreenSaver. if (m_pInfo) { diff --git a/xbmc/android/activity/AndroidFeatures.cpp b/xbmc/android/activity/AndroidFeatures.cpp new file mode 100644 index 0000000000..71db527591 --- /dev/null +++ b/xbmc/android/activity/AndroidFeatures.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "AndroidFeatures.h" +#include "XBMCApp.h" +#include "utils/log.h" + +#include <cpu-features.h> + +bool CAndroidFeatures::HasNeon() +{ + if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM) + return ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0); + return false; +} + +int CAndroidFeatures::GetVersion() +{ + static int version = -1; + + if (version == -1) + { + version = 0; + + JNIEnv *jenv = NULL; + CXBMCApp::AttachCurrentThread(&jenv, NULL); + + jclass jcOsBuild = jenv->FindClass("android/os/Build$VERSION"); + if (jcOsBuild == NULL) + { + CLog::Log(LOGERROR, "%s: Error getting class android.os.Build.VERSION", __PRETTY_FUNCTION__); + return version; + } + + jint iSdkVersion = jenv->GetStaticIntField(jcOsBuild, jenv->GetStaticFieldID(jcOsBuild, "SDK_INT", "I")); + CLog::Log(LOGDEBUG, "%s: android.os.Build.VERSION %d", __PRETTY_FUNCTION__, (int)iSdkVersion); + + // <= 10 Gingerbread + // <= 13 Honeycomb + // <= 15 IceCreamSandwich + // JellyBean + version = iSdkVersion; + + jenv->DeleteLocalRef(jcOsBuild); + CXBMCApp::DetachCurrentThread(); + } + return version; +} + +std::string CAndroidFeatures::GetLibiomxName() +{ + std::string strOMXLibName; + int version = GetVersion(); + + // Gingerbread + if (version <= 10) + strOMXLibName = "libiomx-10.so"; + // Honeycomb + else if (version <= 13) + strOMXLibName = "libiomx-13.so"; + // IceCreamSandwich + else if (version <= 15) + strOMXLibName = "libiomx-14.so"; + else + strOMXLibName = "unknown"; + + return strOMXLibName; +} + diff --git a/xbmc/android/activity/AndroidFeatures.h b/xbmc/android/activity/AndroidFeatures.h new file mode 100644 index 0000000000..fbbbddd6e5 --- /dev/null +++ b/xbmc/android/activity/AndroidFeatures.h @@ -0,0 +1,31 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <string> + +class CAndroidFeatures +{ + public: + + static bool HasNeon(); + static int GetVersion(); + static std::string GetLibiomxName(); +};
\ No newline at end of file diff --git a/xbmc/android/activity/AndroidKey.cpp b/xbmc/android/activity/AndroidKey.cpp new file mode 100644 index 0000000000..fe07d8c213 --- /dev/null +++ b/xbmc/android/activity/AndroidKey.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "AndroidKey.h" +#include "XBMCApp.h" +#include "guilib/Key.h" +#include "windowing/WinEvents.h" + +static KeyMap keyMap[] = { + { AKEYCODE_UNKNOWN , XBMCK_LAST }, + { AKEYCODE_SOFT_LEFT , XBMCK_LEFT }, + { AKEYCODE_SOFT_RIGHT , XBMCK_RIGHT }, + { AKEYCODE_HOME , XBMCK_HOME }, + { AKEYCODE_BACK , XBMCK_BACKSPACE }, + { AKEYCODE_CALL , XBMCK_LAST }, + { AKEYCODE_ENDCALL , XBMCK_LAST }, + { AKEYCODE_0 , XBMCK_0 }, + { AKEYCODE_1 , XBMCK_1 }, + { AKEYCODE_2 , XBMCK_2 }, + { AKEYCODE_3 , XBMCK_3 }, + { AKEYCODE_4 , XBMCK_4 }, + { AKEYCODE_5 , XBMCK_5 }, + { AKEYCODE_6 , XBMCK_6 }, + { AKEYCODE_7 , XBMCK_7 }, + { AKEYCODE_8 , XBMCK_8 }, + { AKEYCODE_9 , XBMCK_9 }, + { AKEYCODE_STAR , XBMCK_ASTERISK }, + { AKEYCODE_POUND , XBMCK_HASH }, + { AKEYCODE_DPAD_UP , XBMCK_UP }, + { AKEYCODE_DPAD_DOWN , XBMCK_DOWN }, + { AKEYCODE_DPAD_LEFT , XBMCK_LEFT }, + { AKEYCODE_DPAD_RIGHT , XBMCK_RIGHT }, + { AKEYCODE_DPAD_CENTER , XBMCK_RETURN }, + { AKEYCODE_VOLUME_UP , XBMCK_PLUS }, + { AKEYCODE_VOLUME_DOWN , XBMCK_MINUS }, + { AKEYCODE_POWER , XBMCK_POWER }, + { AKEYCODE_CAMERA , XBMCK_LAST }, + { AKEYCODE_CLEAR , XBMCK_LAST }, + { AKEYCODE_A , XBMCK_a }, + { AKEYCODE_B , XBMCK_b }, + { AKEYCODE_C , XBMCK_c }, + { AKEYCODE_D , XBMCK_d }, + { AKEYCODE_E , XBMCK_e }, + { AKEYCODE_F , XBMCK_f }, + { AKEYCODE_G , XBMCK_g }, + { AKEYCODE_H , XBMCK_h }, + { AKEYCODE_I , XBMCK_i }, + { AKEYCODE_J , XBMCK_j }, + { AKEYCODE_K , XBMCK_k }, + { AKEYCODE_L , XBMCK_l }, + { AKEYCODE_M , XBMCK_m }, + { AKEYCODE_N , XBMCK_n }, + { AKEYCODE_O , XBMCK_o }, + { AKEYCODE_P , XBMCK_p }, + { AKEYCODE_Q , XBMCK_q }, + { AKEYCODE_R , XBMCK_r }, + { AKEYCODE_S , XBMCK_s }, + { AKEYCODE_T , XBMCK_t }, + { AKEYCODE_U , XBMCK_u }, + { AKEYCODE_V , XBMCK_v }, + { AKEYCODE_W , XBMCK_w }, + { AKEYCODE_X , XBMCK_x }, + { AKEYCODE_Y , XBMCK_y }, + { AKEYCODE_Z , XBMCK_z }, + { AKEYCODE_COMMA , XBMCK_COMMA }, + { AKEYCODE_PERIOD , XBMCK_PERIOD }, + { AKEYCODE_ALT_LEFT , XBMCK_LEFT }, + { AKEYCODE_ALT_RIGHT , XBMCK_RIGHT }, + { AKEYCODE_SHIFT_LEFT , XBMCK_LEFT }, + { AKEYCODE_SHIFT_RIGHT , XBMCK_RIGHT }, + { AKEYCODE_TAB , XBMCK_TAB }, + { AKEYCODE_SPACE , XBMCK_SPACE }, + { AKEYCODE_SYM , XBMCK_LAST }, + { AKEYCODE_EXPLORER , XBMCK_LAST }, + { AKEYCODE_ENVELOPE , XBMCK_LAST }, + { AKEYCODE_ENTER , XBMCK_RETURN }, + { AKEYCODE_DEL , XBMCK_DELETE }, + { AKEYCODE_GRAVE , XBMCK_BACKQUOTE }, + { AKEYCODE_MINUS , XBMCK_MINUS }, + { AKEYCODE_EQUALS , XBMCK_EQUALS }, + { AKEYCODE_LEFT_BRACKET , XBMCK_LEFTBRACKET }, + { AKEYCODE_RIGHT_BRACKET , XBMCK_RIGHTBRACKET }, + { AKEYCODE_BACKSLASH , XBMCK_BACKSLASH }, + { AKEYCODE_SEMICOLON , XBMCK_SEMICOLON }, + { AKEYCODE_APOSTROPHE , XBMCK_QUOTE }, + { AKEYCODE_SLASH , XBMCK_SLASH }, + { AKEYCODE_AT , XBMCK_AT }, + { AKEYCODE_NUM , XBMCK_NUMLOCK }, + { AKEYCODE_HEADSETHOOK , XBMCK_LAST }, + { AKEYCODE_FOCUS , XBMCK_LAST }, // *Camera* focus + { AKEYCODE_PLUS , XBMCK_PLUS }, + { AKEYCODE_MENU , XBMCK_MENU }, + { AKEYCODE_NOTIFICATION , XBMCK_LAST }, + { AKEYCODE_SEARCH , XBMCK_LAST }, + { AKEYCODE_MEDIA_PLAY_PAUSE, XBMCK_MEDIA_PLAY_PAUSE }, + { AKEYCODE_MEDIA_STOP , XBMCK_MEDIA_STOP }, + { AKEYCODE_MEDIA_NEXT , XBMCK_MEDIA_NEXT_TRACK }, + { AKEYCODE_MEDIA_PREVIOUS , XBMCK_MEDIA_PREV_TRACK }, + { AKEYCODE_MEDIA_REWIND , XBMCK_REWIND }, + { AKEYCODE_MEDIA_FAST_FORWARD , XBMCK_FASTFORWARD }, + { AKEYCODE_MUTE , XBMCK_VOLUME_MUTE }, + { AKEYCODE_PAGE_UP , XBMCK_PAGEUP }, + { AKEYCODE_PAGE_DOWN , XBMCK_PAGEDOWN }, + { AKEYCODE_PICTSYMBOLS , XBMCK_LAST }, + { AKEYCODE_SWITCH_CHARSET , XBMCK_LAST }, + { AKEYCODE_BUTTON_A , XBMCK_LAST }, + { AKEYCODE_BUTTON_B , XBMCK_LAST }, + { AKEYCODE_BUTTON_C , XBMCK_LAST }, + { AKEYCODE_BUTTON_X , XBMCK_LAST }, + { AKEYCODE_BUTTON_Y , XBMCK_LAST }, + { AKEYCODE_BUTTON_Z , XBMCK_LAST }, + { AKEYCODE_BUTTON_L1 , XBMCK_LAST }, + { AKEYCODE_BUTTON_R1 , XBMCK_LAST }, + { AKEYCODE_BUTTON_L2 , XBMCK_LAST }, + { AKEYCODE_BUTTON_R2 , XBMCK_LAST }, + { AKEYCODE_BUTTON_THUMBL , XBMCK_LAST }, + { AKEYCODE_BUTTON_THUMBR , XBMCK_LAST }, + { AKEYCODE_BUTTON_START , XBMCK_LAST }, + { AKEYCODE_BUTTON_SELECT , XBMCK_LAST }, + { AKEYCODE_BUTTON_MODE , XBMCK_LAST } +}; + +bool CAndroidKey::onKeyboardEvent(AInputEvent* event) +{ + CXBMCApp::android_printf("%s", __PRETTY_FUNCTION__); + if (event == NULL) + return false; + + int32_t keycode = AKeyEvent_getKeyCode(event); + int32_t flags = AKeyEvent_getFlags(event); + int32_t state = AKeyEvent_getMetaState(event); + int32_t repeatCount = AKeyEvent_getRepeatCount(event); + + // Check if we got some special key + uint16_t sym = XBMCK_UNKNOWN; + for (unsigned int index = 0; index < sizeof(keyMap) / sizeof(KeyMap); index++) + { + if (keycode == keyMap[index].nativeKey) + { + sym = keyMap[index].xbmcKey; + break; + } + } + + // check if this is a key we don't want to handle + if (sym == XBMCK_LAST) + return false; + + uint16_t modifiers = 0; + if (state & AMETA_ALT_LEFT_ON) + modifiers |= XBMCKMOD_LALT; + if (state & AMETA_ALT_RIGHT_ON) + modifiers |= XBMCKMOD_RALT; + if (state & AMETA_SHIFT_LEFT_ON) + modifiers |= XBMCKMOD_LSHIFT; + if (state & AMETA_SHIFT_RIGHT_ON) + modifiers |= XBMCKMOD_RSHIFT; + /* TODO: + if (state & AMETA_SYM_ON) + modifiers |= 0x000?;*/ + + switch (AKeyEvent_getAction(event)) + { + case AKEY_EVENT_ACTION_DOWN: + CXBMCApp::android_printf("CXBMCApp: key down (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)", + keycode, repeatCount, flags, + (state & AMETA_ALT_ON) ? "yes" : "no", + (state & AMETA_SHIFT_ON) ? "yes" : "no", + (state & AMETA_SYM_ON) ? "yes" : "no"); + XBMC_Key((uint8_t)keycode, sym, modifiers, false); + return true; + + case AKEY_EVENT_ACTION_UP: + CXBMCApp::android_printf("CXBMCApp: key up (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)", + keycode, repeatCount, flags, + (state & AMETA_ALT_ON) ? "yes" : "no", + (state & AMETA_SHIFT_ON) ? "yes" : "no", + (state & AMETA_SYM_ON) ? "yes" : "no"); + XBMC_Key((uint8_t)keycode, sym, modifiers, true); + return true; + + case AKEY_EVENT_ACTION_MULTIPLE: + CXBMCApp::android_printf("CXBMCApp: key multiple (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)", + keycode, repeatCount, flags, + (state & AMETA_ALT_ON) ? "yes" : "no", + (state & AMETA_SHIFT_ON) ? "yes" : "no", + (state & AMETA_SYM_ON) ? "yes" : "no"); + break; + + default: + CXBMCApp::android_printf("CXBMCApp: unknown key (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)", + keycode, repeatCount, flags, + (state & AMETA_ALT_ON) ? "yes" : "no", + (state & AMETA_SHIFT_ON) ? "yes" : "no", + (state & AMETA_SYM_ON) ? "yes" : "no"); + break; + } + + return false; +} + +void CAndroidKey::XBMC_Key(uint8_t code, uint16_t key, uint16_t modifiers, bool up) +{ + XBMC_Event newEvent; + memset(&newEvent, 0, sizeof(newEvent)); + + unsigned char type = up ? XBMC_KEYUP : XBMC_KEYDOWN; + newEvent.type = type; + newEvent.key.type = type; + newEvent.key.keysym.scancode = code; + newEvent.key.keysym.sym = (XBMCKey)key; + newEvent.key.keysym.unicode = key; + newEvent.key.keysym.mod = (XBMCMod)modifiers; + + CXBMCApp::android_printf("XBMC_Key(%u, %u, 0x%04X, %d)", code, key, modifiers, up); + CWinEvents::MessagePush(&newEvent); +}
\ No newline at end of file diff --git a/xbmc/android/activity/AndroidKey.h b/xbmc/android/activity/AndroidKey.h new file mode 100644 index 0000000000..579e32ab9c --- /dev/null +++ b/xbmc/android/activity/AndroidKey.h @@ -0,0 +1,37 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <stdint.h> +#include <android/input.h> + +typedef struct { + int32_t nativeKey; + int16_t xbmcKey; +} KeyMap; + +class CAndroidKey +{ +public: + CAndroidKey(){}; + ~CAndroidKey(){}; + void XBMC_Key(uint8_t code, uint16_t key, uint16_t modifiers, bool up); + bool onKeyboardEvent(AInputEvent* event); +};
\ No newline at end of file diff --git a/xbmc/android/activity/AndroidMouse.cpp b/xbmc/android/activity/AndroidMouse.cpp new file mode 100644 index 0000000000..483a1fbf3c --- /dev/null +++ b/xbmc/android/activity/AndroidMouse.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "AndroidMouse.h" +#include "XBMCApp.h" +#include "Application.h" +#include "guilib/GUIWindowManager.h" +#include "windowing/WinEvents.h" + +CAndroidMouse::CAndroidMouse() +{ +} + +CAndroidMouse::~CAndroidMouse() +{ +} + +bool CAndroidMouse::onMouseEvent(AInputEvent* event) +{ + if (event == NULL) + return false; + + int32_t eventAction = AMotionEvent_getAction(event); + int8_t mouseAction = eventAction & AMOTION_EVENT_ACTION_MASK; + size_t mousePointer = eventAction >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + + CXBMCApp::android_printf("%s pointer:%i", __PRETTY_FUNCTION__, mousePointer); + float x = AMotionEvent_getX(event, mousePointer); + float y = AMotionEvent_getY(event, mousePointer); + + switch (mouseAction) + { + case AMOTION_EVENT_ACTION_UP: + case AMOTION_EVENT_ACTION_DOWN: + MouseButton(x,y,mouseAction); + return true; + default: + MouseMove(x,y); + return true; + } + return false; +} + +void CAndroidMouse::MouseMove(float x, float y) +{ + CXBMCApp::android_printf("%s: x:%f, y:%f", __PRETTY_FUNCTION__, x, y); + XBMC_Event newEvent; + + memset(&newEvent, 0, sizeof(newEvent)); + + newEvent.type = XBMC_MOUSEMOTION; + newEvent.motion.type = XBMC_MOUSEMOTION; + newEvent.motion.which = 0; + newEvent.motion.state = 0; + newEvent.motion.x = x; + newEvent.motion.y = y; + newEvent.motion.xrel = 0; + newEvent.motion.yrel = 0; + CWinEventsAndroid::MessagePush(&newEvent); +} + +void CAndroidMouse::MouseButton(float x, float y, int32_t action) +{ + CXBMCApp::android_printf("%s: x:%f, y:%f, action:%i", __PRETTY_FUNCTION__, x, y, action); + XBMC_Event newEvent; + + memset(&newEvent, 0, sizeof(newEvent)); + + newEvent.type = (action == AMOTION_EVENT_ACTION_DOWN) ? XBMC_MOUSEBUTTONDOWN : XBMC_MOUSEBUTTONUP; + newEvent.button.state = (action == AMOTION_EVENT_ACTION_DOWN) ? XBMC_PRESSED : XBMC_RELEASED; + newEvent.button.type = newEvent.type; + newEvent.button.x = x; + newEvent.button.y = y; + newEvent.button.button = XBMC_BUTTON_LEFT; + CWinEventsAndroid::MessagePush(&newEvent); +} diff --git a/xbmc/android/activity/AndroidMouse.h b/xbmc/android/activity/AndroidMouse.h new file mode 100644 index 0000000000..d0009b86f5 --- /dev/null +++ b/xbmc/android/activity/AndroidMouse.h @@ -0,0 +1,36 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ +#include <android/input.h> + +class CAndroidMouse +{ + +public: + CAndroidMouse(); + virtual ~CAndroidMouse(); + bool onMouseEvent(AInputEvent* event); + +protected: + +private: + void MouseMove(float x, float y); + void MouseButton(float x, float y, int32_t type); +}; diff --git a/xbmc/android/activity/AndroidTouch.cpp b/xbmc/android/activity/AndroidTouch.cpp new file mode 100644 index 0000000000..d84ffa50bd --- /dev/null +++ b/xbmc/android/activity/AndroidTouch.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "AndroidTouch.h" +#include "XBMCApp.h" +#include "guilib/GUIWindowManager.h" +#include "windowing/WinEvents.h" +#include "ApplicationMessenger.h" + +CAndroidTouch::CAndroidTouch() +{ + CTouchInput::Get().RegisterHandler(this); +} + +CAndroidTouch::~CAndroidTouch() +{ + CTouchInput::Get().UnregisterHandler(); +} + +bool CAndroidTouch::onTouchEvent(AInputEvent* event) +{ + CXBMCApp::android_printf("%s", __PRETTY_FUNCTION__); + if (event == NULL) + return false; + + size_t numPointers = AMotionEvent_getPointerCount(event); + if (numPointers <= 0) + { + CXBMCApp::android_printf(" => aborting touch event because there are no active pointers"); + return false; + } + + if (numPointers > TOUCH_MAX_POINTERS) + numPointers = TOUCH_MAX_POINTERS; + + int32_t eventAction = AMotionEvent_getAction(event); + int8_t touchAction = eventAction & AMOTION_EVENT_ACTION_MASK; + size_t touchPointer = eventAction >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + + CTouchInput::TouchEvent touchEvent = CTouchInput::TouchEventAbort; + switch (touchAction) + { + case AMOTION_EVENT_ACTION_DOWN: + case AMOTION_EVENT_ACTION_POINTER_DOWN: + touchEvent = CTouchInput::TouchEventDown; + break; + + case AMOTION_EVENT_ACTION_UP: + case AMOTION_EVENT_ACTION_POINTER_UP: + touchEvent = CTouchInput::TouchEventUp; + break; + + case AMOTION_EVENT_ACTION_MOVE: + touchEvent = CTouchInput::TouchEventMove; + break; + + case AMOTION_EVENT_ACTION_OUTSIDE: + case AMOTION_EVENT_ACTION_CANCEL: + default: + break; + } + + float x = AMotionEvent_getX(event, touchPointer); + float y = AMotionEvent_getY(event, touchPointer); + float size = AMotionEvent_getTouchMinor(event, touchPointer); + int64_t time = AMotionEvent_getEventTime(event); + + // first update all touch pointers + for (unsigned int pointer = 0; pointer < numPointers; pointer++) + CTouchInput::Get().Update(pointer, AMotionEvent_getX(event, pointer), AMotionEvent_getY(event, pointer), + AMotionEvent_getEventTime(event), AMotionEvent_getTouchMinor(event, pointer)); + + // now send the event + return CTouchInput::Get().Handle(touchEvent, x, y, time, touchPointer, size); +} + +bool CAndroidTouch::OnSingleTouchStart(float x, float y) +{ + // Send a mouse motion event for getting the current guiitem selected + XBMC_Touch(XBMC_MOUSEMOTION, 0, (uint16_t)x, (uint16_t)y); + + return true; +} + +bool CAndroidTouch::OnTouchGesturePanStart(float x, float y) +{ + XBMC_TouchGesture(ACTION_GESTURE_BEGIN, x, y, 0.0f, 0.0f); + + return true; +} + +bool CAndroidTouch::OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY) +{ + XBMC_TouchGesture(ACTION_GESTURE_PAN, x, y, offsetX, offsetY); + + return true; +} + +bool CAndroidTouch::OnTouchGesturePanEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY) +{ + XBMC_TouchGesture(ACTION_GESTURE_END, velocityX, velocityY, x, y); + + // unfocus the focused GUI item + g_windowManager.SendMessage(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0); + + return true; +} + +void CAndroidTouch::OnSingleTap(float x, float y) +{ + XBMC_Touch(XBMC_MOUSEBUTTONDOWN, XBMC_BUTTON_LEFT, (uint16_t)x, (uint16_t)y); + XBMC_Touch(XBMC_MOUSEBUTTONUP, XBMC_BUTTON_LEFT, (uint16_t)x, (uint16_t)y); +} + +void CAndroidTouch::OnSingleLongPress(float x, float y) +{ + // we send a right-click for this + XBMC_Touch(XBMC_MOUSEBUTTONDOWN, XBMC_BUTTON_RIGHT, (uint16_t)x, (uint16_t)y); + XBMC_Touch(XBMC_MOUSEBUTTONUP, XBMC_BUTTON_RIGHT, (uint16_t)x, (uint16_t)y); +} + +void CAndroidTouch::OnZoomPinch(float centerX, float centerY, float zoomFactor) +{ + XBMC_TouchGesture(ACTION_GESTURE_ZOOM, centerX, centerY, zoomFactor, 0); +} + +void CAndroidTouch::XBMC_Touch(uint8_t type, uint8_t button, uint16_t x, uint16_t y) +{ + XBMC_Event newEvent; + memset(&newEvent, 0, sizeof(newEvent)); + + newEvent.type = type; + newEvent.button.type = type; + newEvent.button.button = button; + newEvent.button.x = x; + newEvent.button.y = y; + + CXBMCApp::android_printf("XBMC_Touch(%u, %u, %u, %u)", type, button, x, y); + CWinEvents::MessagePush(&newEvent); +} + +void CAndroidTouch::XBMC_TouchGesture(int32_t action, float posX, float posY, float offsetX, float offsetY) +{ + CXBMCApp::android_printf("XBMC_TouchGesture(%d, %f, %f, %f, %f)", action, posX, posY, offsetX, offsetY); + if (action == ACTION_GESTURE_BEGIN) + CApplicationMessenger::Get().SendAction(CAction(action, 0, posX, posY, 0, 0), WINDOW_INVALID, false); + else if (action == ACTION_GESTURE_PAN) + CApplicationMessenger::Get().SendAction(CAction(action, 0, posX, posY, offsetX, offsetY), WINDOW_INVALID, false); + else if (action == ACTION_GESTURE_END) + CApplicationMessenger::Get().SendAction(CAction(action, 0, posX, posY, offsetX, offsetY), WINDOW_INVALID, false); + else if (action == ACTION_GESTURE_ZOOM) + CApplicationMessenger::Get().SendAction(CAction(action, 0, posX, posY, offsetX, 0), WINDOW_INVALID, false); +} diff --git a/xbmc/android/activity/AndroidTouch.h b/xbmc/android/activity/AndroidTouch.h new file mode 100644 index 0000000000..f8bf51e401 --- /dev/null +++ b/xbmc/android/activity/AndroidTouch.h @@ -0,0 +1,48 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ +#include <android/input.h> +#include <math.h> + +#include "input/TouchInput.h" + +class CAndroidTouch : protected ITouchHandler +{ + +public: + CAndroidTouch(); + virtual ~CAndroidTouch(); + bool onTouchEvent(AInputEvent* event); + +protected: + virtual bool OnSingleTouchStart(float x, float y); + + virtual bool OnTouchGesturePanStart(float x, float y); + virtual bool OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY); + virtual bool OnTouchGesturePanEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY); + + virtual void OnSingleTap(float x, float y); + virtual void OnSingleLongPress(float x, float y); + virtual void OnZoomPinch(float centerX, float centerY, float zoomFactor); + +private: + void XBMC_Touch(uint8_t type, uint8_t button, uint16_t x, uint16_t y); + void XBMC_TouchGesture(int32_t action, float posX, float posY, float offsetX, float offsetY); +}; diff --git a/xbmc/android/activity/DllGraphicBuffer.h b/xbmc/android/activity/DllGraphicBuffer.h new file mode 100644 index 0000000000..ff5b309bb7 --- /dev/null +++ b/xbmc/android/activity/DllGraphicBuffer.h @@ -0,0 +1,57 @@ +#pragma once + +/* + * Copyright (C) 2005-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#if (defined HAVE_CONFIG_H) && (!defined WIN32) + #include "config.h" +#endif +#include "DynamicDll.h" +#include "GraphicBuffer.h" +class DllGraphicBufferInterface +{ +public: + virtual ~DllGraphicBufferInterface() {} + virtual void GraphicBufferCtor(void *, uint32_t w, uint32_t h, uint32_t format, gfxImageUsage usage)=0; + virtual void GraphicBufferDtor(void *)=0; + virtual int GraphicBufferLock(void*, uint32_t usage, void **addr)=0; + virtual int GraphicBufferUnlock(void*)=0; + virtual int GraphicBufferGetNativeBuffer(void*)=0; +}; + +class DllGraphicBuffer : public DllDynamic, DllGraphicBufferInterface +{ + DECLARE_DLL_WRAPPER(DllGraphicBuffer, DLL_PATH_LIBUI) + + DEFINE_METHOD5(void, GraphicBufferCtor, (void *p1, uint32_t p2, uint32_t p3, uint32_t p4, gfxImageUsage p5)) + DEFINE_METHOD1(void, GraphicBufferDtor, (void* p1)) + DEFINE_METHOD3(int, GraphicBufferLock, (void *p1, uint32_t p2, void** p3)) + DEFINE_METHOD1(int, GraphicBufferUnlock,(void* p1)) + DEFINE_METHOD1(int, GraphicBufferGetNativeBuffer,(void* p1)) + + BEGIN_METHOD_RESOLVE() + RESOLVE_METHOD_RENAME(_ZN7android13GraphicBufferC1Ejjij, GraphicBufferCtor) + RESOLVE_METHOD_RENAME(_ZN7android13GraphicBufferD1Ev, GraphicBufferDtor) + RESOLVE_METHOD_RENAME(_ZN7android13GraphicBuffer4lockEjPPv, GraphicBufferLock) + RESOLVE_METHOD_RENAME(_ZN7android13GraphicBuffer6unlockEv, GraphicBufferUnlock) + RESOLVE_METHOD_RENAME(_ZNK7android13GraphicBuffer15getNativeBufferEv, GraphicBufferGetNativeBuffer) + END_METHOD_RESOLVE() +};
\ No newline at end of file diff --git a/xbmc/android/activity/EventLoop.cpp b/xbmc/android/activity/EventLoop.cpp new file mode 100644 index 0000000000..467ccddc8d --- /dev/null +++ b/xbmc/android/activity/EventLoop.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "EventLoop.h" +#include "XBMCApp.h" + +CEventLoop::CEventLoop(android_app* application) + : m_enabled(false), + m_application(application), + m_activityHandler(NULL), m_inputHandler(NULL) +{ + if (m_application == NULL) + return; + + m_application->userData = this; + m_application->onAppCmd = activityCallback; + m_application->onInputEvent = inputCallback; +} + +void CEventLoop::run(IActivityHandler &activityHandler, IInputHandler &inputHandler) +{ + int ident; + int events; + struct android_poll_source* source; + + m_activityHandler = &activityHandler; + m_inputHandler = &inputHandler; + + CXBMCApp::android_printf("CEventLoop: starting event loop"); + while (1) + { + // We will block forever waiting for events. + while ((ident = ALooper_pollAll(-1, NULL, &events, (void**)&source)) >= 0) + { + // Process this event. + if (source != NULL) + source->process(m_application, source); + + // Check if we are exiting. + if (m_application->destroyRequested) + { + CXBMCApp::android_printf("CEventLoop: we are being destroyed"); + return; + } + } + } +} + +void CEventLoop::activate() +{ + if (m_enabled || m_application->window == NULL) + return; + + m_enabled = true; + if (m_activityHandler->onActivate() != ActivityOK) + { + CXBMCApp::android_printf("CEventLoop: IActivityHandler::onActivate() failed"); + ANativeActivity_finish(m_application->activity); + } +} + +void CEventLoop::deactivate() +{ + if (!m_enabled) + return; + + m_activityHandler->onDeactivate(); + m_enabled = false; +} + +void CEventLoop::processActivity(int32_t command) +{ + switch (command) + { + case APP_CMD_CONFIG_CHANGED: + m_activityHandler->onConfigurationChanged(); + break; + + case APP_CMD_INIT_WINDOW: + // The window is being shown, get it ready. + m_activityHandler->onCreateWindow(m_application->window); + break; + + case APP_CMD_WINDOW_RESIZED: + // The window has been resized + m_activityHandler->onResizeWindow(); + break; + + case APP_CMD_TERM_WINDOW: + // The window is being hidden or closed, clean it up. + m_activityHandler->onDestroyWindow(); + deactivate(); + break; + + case APP_CMD_GAINED_FOCUS: + activate(); + m_activityHandler->onGainFocus(); + break; + + case APP_CMD_LOST_FOCUS: + m_activityHandler->onLostFocus(); + deactivate(); + break; + + case APP_CMD_LOW_MEMORY: + m_activityHandler->onLowMemory(); + break; + + case APP_CMD_START: + m_activityHandler->onStart(); + break; + + case APP_CMD_RESUME: + m_activityHandler->onResume(); + break; + + case APP_CMD_SAVE_STATE: + // The system has asked us to save our current state. Do so. + m_activityHandler->onSaveState(&m_application->savedState, &m_application->savedStateSize); + break; + + case APP_CMD_PAUSE: + m_activityHandler->onPause(); + deactivate(); + break; + + case APP_CMD_STOP: + m_activityHandler->onStop(); + break; + + case APP_CMD_DESTROY: + m_activityHandler->onDestroy(); + break; + + default: + break; + } +} + +int32_t CEventLoop::processInput(AInputEvent* event) +{ + int32_t type = AInputEvent_getType(event); + switch (type) + { + case AINPUT_EVENT_TYPE_MOTION: + switch (AInputEvent_getSource(event)) + { + case AINPUT_SOURCE_TOUCHSCREEN: + return m_inputHandler->onTouchEvent(event); + case AINPUT_SOURCE_MOUSE: + return m_inputHandler->onMouseEvent(event); + } + break; + + case AINPUT_EVENT_TYPE_KEY: + return m_inputHandler->onKeyboardEvent(event); + } + + return 0; +} + +void CEventLoop::activityCallback(android_app* application, int32_t command) +{ + if (application == NULL || application->userData == NULL) + return; + + CEventLoop& eventLoop = *((CEventLoop*)application->userData); + eventLoop.processActivity(command); +} + +int32_t CEventLoop::inputCallback(android_app* application, AInputEvent* event) +{ + if (application == NULL || application->userData == NULL || + event == NULL) + return 0; + + CEventLoop& eventLoop = *((CEventLoop*)application->userData); + return eventLoop.processInput(event); +} + diff --git a/xbmc/android/activity/EventLoop.h b/xbmc/android/activity/EventLoop.h new file mode 100644 index 0000000000..f5f42784f4 --- /dev/null +++ b/xbmc/android/activity/EventLoop.h @@ -0,0 +1,50 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <android_native_app_glue.h> + +#include "IActivityHandler.h" +#include "IInputHandler.h" + +class CEventLoop +{ +public: + CEventLoop(android_app* application); + + void run(IActivityHandler &activityHandler, IInputHandler &inputHandler); + +protected: + void activate(); + void deactivate(); + + void processActivity(int32_t command); + int32_t processInput(AInputEvent* event); + +private: + static void activityCallback(android_app* application, int32_t command); + static int32_t inputCallback(android_app* application, AInputEvent* event); + + bool m_enabled; + android_app* m_application; + IActivityHandler* m_activityHandler; + IInputHandler* m_inputHandler; +}; + diff --git a/xbmc/android/activity/GraphicBuffer.cpp b/xbmc/android/activity/GraphicBuffer.cpp new file mode 100644 index 0000000000..4ffcdd45c3 --- /dev/null +++ b/xbmc/android/activity/GraphicBuffer.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2005-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * James Willcox <jwillcox@mozilla.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "DllGraphicBuffer.h" +#include "GraphicBuffer.h" +#include "XBMCApp.h" +#include "utils/log.h" + +DllGraphicBuffer *CGraphicBuffer::m_dll = NULL; + +/* Yanked from Android's hardware.h */ +enum +{ + HAL_PIXEL_FORMAT_RGBA_8888 = 1, + HAL_PIXEL_FORMAT_RGBX_8888 = 2, + HAL_PIXEL_FORMAT_RGB_888 = 3, + HAL_PIXEL_FORMAT_RGB_565 = 4, + HAL_PIXEL_FORMAT_BGRA_8888 = 5, + HAL_PIXEL_FORMAT_RGBA_5551 = 6, + HAL_PIXEL_FORMAT_RGBA_4444 = 7, + + /* + * Android YUV format: + * + * This format is exposed outside of the HAL to software + * decoders and applications. + * EGLImageKHR must support it in conjunction with the + * OES_EGL_image_external extension. + * + * YV12 is 4:2:0 YCrCb planar format comprised of a WxH Y plane followed + * by (W/2) x (H/2) Cr and Cb planes. + * + * This format assumes + * - an even width + * - an even height + * - a horizontal stride multiple of 16 pixels + * - a vertical stride equal to the height + * + * y_size = stride * height + * c_size = ALIGN(stride/2, 16) * height/2 + * size = y_size + c_size * 2 + * cr_offset = y_size + * cb_offset = y_size + c_size + * + */ + HAL_PIXEL_FORMAT_YV12 = 0x32315659, // YCrCb 4:2:0 Planar +}; + +CGraphicBuffer::CGraphicBuffer(uint32_t width, uint32_t height, uint32_t format, gfxImageUsage usage): + m_width(width), m_height(height), m_usage(usage), m_format(format), m_handle(0) +{ + CLog::Log(LOGDEBUG, "CGraphicBuffer::CGraphicBuffer"); + if (!m_dll) + { + // m_dll is static, there can be only one. + m_dll = new DllGraphicBuffer; + m_dll->Load(); + m_dll->EnableDelayedUnload(false); + } + + m_handle = malloc(4096 * 4); + if (m_dll) + m_dll->GraphicBufferCtor(m_handle, width, height, GetAndroidFormat(format), usage); +} + +CGraphicBuffer::~CGraphicBuffer() +{ + if (m_handle) + { + if (m_dll) + m_dll->GraphicBufferDtor(m_handle); + free(m_handle); + } +} + +bool CGraphicBuffer::Lock(gfxImageUsage aUsage, void **addr) +{ + if (m_dll) + return m_dll->GraphicBufferLock(m_handle, aUsage, addr) == 0; + return false; +} + +uint32_t CGraphicBuffer::GetNativeBuffer() +{ + if (m_dll) + return m_dll->GraphicBufferGetNativeBuffer(m_handle); + return false; +} + +bool CGraphicBuffer::Unlock() +{ + if (m_dll) + return m_dll->GraphicBufferUnlock(m_handle) == 0; + return false; +} + +uint32_t CGraphicBuffer::GetAndroidFormat(uint32_t format) +{ + switch (format) + { + case XB_FMT_A8R8G8B8: + return HAL_PIXEL_FORMAT_BGRA_8888; + case XB_FMT_RGBA8: + return HAL_PIXEL_FORMAT_RGBA_8888; + case XB_FMT_RGB8: + return HAL_PIXEL_FORMAT_RGB_888; + } + return 0; +}
\ No newline at end of file diff --git a/xbmc/android/activity/GraphicBuffer.h b/xbmc/android/activity/GraphicBuffer.h new file mode 100644 index 0000000000..48c0d9cf29 --- /dev/null +++ b/xbmc/android/activity/GraphicBuffer.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2005-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * James Willcox <jwillcox@mozilla.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#pragma once +#include <stdint.h> +#include "guilib/XBTF.h" + +class DllGraphicBuffer; + +/* Copied from Android's gralloc.h */ +enum gfxImageUsage { + /* buffer is never read in software */ + GRALLOC_USAGE_SW_READ_NEVER = 0x00000000, + /* buffer is rarely read in software */ + GRALLOC_USAGE_SW_READ_RARELY = 0x00000002, + /* buffer is often read in software */ + GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003, + /* mask for the software read values */ + GRALLOC_USAGE_SW_READ_MASK = 0x0000000F, + + /* buffer is never written in software */ + GRALLOC_USAGE_SW_WRITE_NEVER = 0x00000000, + /* buffer is never written in software */ + GRALLOC_USAGE_SW_WRITE_RARELY = 0x00000020, + /* buffer is never written in software */ + GRALLOC_USAGE_SW_WRITE_OFTEN = 0x00000030, + /* mask for the software write values */ + GRALLOC_USAGE_SW_WRITE_MASK = 0x000000F0, + + /* buffer will be used as an OpenGL ES texture */ + GRALLOC_USAGE_HW_TEXTURE = 0x00000100, + /* buffer will be used as an OpenGL ES render target */ + GRALLOC_USAGE_HW_RENDER = 0x00000200, + /* buffer will be used by the 2D hardware blitter */ + GRALLOC_USAGE_HW_2D = 0x00000400, + /* buffer will be used with the framebuffer device */ + GRALLOC_USAGE_HW_FB = 0x00001000, + /* mask for the software usage bit-mask */ + GRALLOC_USAGE_HW_MASK = 0x00001F00, + + /* implementation-specific private usage flags */ + GRALLOC_USAGE_PRIVATE_0 = 0x10000000, + GRALLOC_USAGE_PRIVATE_1 = 0x20000000, + GRALLOC_USAGE_PRIVATE_2 = 0x40000000, + GRALLOC_USAGE_PRIVATE_3 = 0x80000000, + GRALLOC_USAGE_PRIVATE_MASK = 0xF0000000, +}; + +class CGraphicBuffer +{ +public: + CGraphicBuffer(uint32_t width, uint32_t height, uint32_t format, gfxImageUsage usage); + virtual ~CGraphicBuffer(); + + bool Lock(gfxImageUsage usage, void **addr); + bool Unlock(); + uint32_t GetNativeBuffer(); + +private: + uint32_t m_width; + uint32_t m_height; + gfxImageUsage m_usage; + uint32_t m_format; + + uint32_t GetAndroidFormat(uint32_t format); + + void *m_handle; + static DllGraphicBuffer *m_dll; +}; diff --git a/xbmc/android/activity/IActivityHandler.h b/xbmc/android/activity/IActivityHandler.h new file mode 100644 index 0000000000..d887d35e27 --- /dev/null +++ b/xbmc/android/activity/IActivityHandler.h @@ -0,0 +1,57 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <stdint.h> + +struct ANativeWindow; +typedef struct ANativeWindow ANativeWindow; + +typedef enum +{ + ActivityOK = 0, + ActivityExit = -1, + ActivityError = -2, + ActivityUnknown = 1 +} ActivityResult; + +class IActivityHandler +{ +public: + virtual ActivityResult onActivate() = 0; + virtual void onDeactivate() = 0; + + virtual void onStart() {} + virtual void onResume() {} + virtual void onPause() {} + virtual void onStop() {} + virtual void onDestroy() {} + + virtual void onSaveState(void **data, size_t *size) {} + virtual void onConfigurationChanged() {} + virtual void onLowMemory() {} + + virtual void onCreateWindow(ANativeWindow* window) {} + virtual void onResizeWindow() {} + virtual void onDestroyWindow() {} + virtual void onGainFocus() {} + virtual void onLostFocus() {} +}; + diff --git a/xbmc/android/activity/IInputHandler.h b/xbmc/android/activity/IInputHandler.h new file mode 100644 index 0000000000..a1bd9485ee --- /dev/null +++ b/xbmc/android/activity/IInputHandler.h @@ -0,0 +1,27 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "AndroidTouch.h" +#include "AndroidKey.h" +#include "AndroidMouse.h" + +class IInputHandler : public CAndroidTouch, public CAndroidKey, public CAndroidMouse +{}; diff --git a/xbmc/android/activity/Makefile.in b/xbmc/android/activity/Makefile.in new file mode 100644 index 0000000000..280c892063 --- /dev/null +++ b/xbmc/android/activity/Makefile.in @@ -0,0 +1,34 @@ +include @abs_top_srcdir@/tools/android/depends/Makefile.include + +GLUEPATH = $(NDKROOT)/sources/android/native_app_glue +APP_GLUE = android_native_app_glue.o + +CPUPATH = $(NDKROOT)/sources/android/cpufeatures +CPU_OBJ = cpu-features.o + +INCLUDES += -I$(GLUEPATH) -I$(CPUPATH) + +SRCS = android_main.cpp +SRCS += AndroidFeatures.cpp +SRCS += AndroidKey.cpp +SRCS += AndroidTouch.cpp +SRCS += AndroidMouse.cpp +SRCS += GraphicBuffer.cpp +SRCS += EventLoop.cpp +SRCS += unzip.cpp +SRCS += XBMCApp.cpp + +OBJS += $(APP_GLUE) $(CPU_OBJ) + +LIB = activity.a + +$(LIB): $(OBJS) + +$(APP_GLUE): + $(CC) -c -I$(GLUEPATH) -o $@ $(GLUEPATH)/$(APP_GLUE:.o=.c) + +$(CPU_OBJ): + $(CC) -c -I$(CPUPATH) -o $@ $(CPUPATH)/$(CPU_OBJ:.o=.c) + +include @abs_top_srcdir@/Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/android/activity/XBMCApp.cpp b/xbmc/android/activity/XBMCApp.cpp new file mode 100644 index 0000000000..300e927d77 --- /dev/null +++ b/xbmc/android/activity/XBMCApp.cpp @@ -0,0 +1,961 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <sstream> + +#include <unistd.h> +#include <stdlib.h> +#include <dlfcn.h> +#include <string.h> + +#include <android/native_window.h> +#include <jni.h> + +#include "XBMCApp.h" + +#include "input/MouseStat.h" +#include "input/XBMC_keysym.h" +#include "guilib/Key.h" +#include "windowing/XBMC_events.h" +#include <android/log.h> + +#include "Application.h" +#include "settings/AdvancedSettings.h" +#include "xbmc.h" +#include "windowing/WinEvents.h" +#include "guilib/GUIWindowManager.h" +#include "utils/log.h" +#include "ApplicationMessenger.h" + +#define GIGABYTES 1073741824 + +using namespace std; + +template<class T, void(T::*fn)()> +void* thread_run(void* obj) +{ + (static_cast<T*>(obj)->*fn)(); + return NULL; +} + +ANativeActivity *CXBMCApp::m_activity = NULL; +ANativeWindow* CXBMCApp::m_window = NULL; + +CXBMCApp::CXBMCApp(ANativeActivity *nativeActivity) + : m_wakeLock(NULL) +{ + m_activity = nativeActivity; + + if (m_activity == NULL) + { + android_printf("CXBMCApp: invalid ANativeActivity instance"); + exit(1); + return; + } + + m_state.appState = Uninitialized; + + if (pthread_mutex_init(&m_state.mutex, NULL) != 0) + { + android_printf("CXBMCApp: pthread_mutex_init() failed"); + m_state.appState = Error; + exit(1); + return; + } + +} + +CXBMCApp::~CXBMCApp() +{ + stop(); + + pthread_mutex_destroy(&m_state.mutex); +} + +ActivityResult CXBMCApp::onActivate() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + + switch (m_state.appState) + { + case Uninitialized: + acquireWakeLock(); + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + pthread_create(&m_state.thread, &attr, thread_run<CXBMCApp, &CXBMCApp::run>, this); + pthread_attr_destroy(&attr); + break; + + case Unfocused: + XBMC_Pause(false); + setAppState(Rendering); + break; + + case Paused: + acquireWakeLock(); + + XBMC_SetupDisplay(); + XBMC_Pause(false); + setAppState(Rendering); + break; + + case Initialized: + case Rendering: + case Stopping: + case Stopped: + case Error: + default: + break; + } + + return ActivityOK; +} + +void CXBMCApp::onDeactivate() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + // this is called on pause, stop and window destroy which + // require specific (and different) actions +} + +void CXBMCApp::onStart() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + // wait for onCreateWindow() and onGainFocus() +} + +void CXBMCApp::onResume() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + // wait for onCreateWindow() and onGainFocus() +} + +void CXBMCApp::onPause() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + // wait for onDestroyWindow() and/or onLostFocus() +} + +void CXBMCApp::onStop() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + // everything has been handled in onLostFocus() so wait + // if onDestroy() is called +} + +void CXBMCApp::onDestroy() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + stop(); +} + +void CXBMCApp::onSaveState(void **data, size_t *size) +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + // no need to save anything as XBMC is running in its own thread +} + +void CXBMCApp::onConfigurationChanged() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + // ignore any configuration changes like screen rotation etc +} + +void CXBMCApp::onLowMemory() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + // can't do much as we don't want to close completely +} + +void CXBMCApp::onCreateWindow(ANativeWindow* window) +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + if (window == NULL) + { + android_printf(" => invalid ANativeWindow object"); + return; + } + m_window = window; +} + +void CXBMCApp::onResizeWindow() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + // no need to do anything because we are fixed in fullscreen landscape mode +} + +void CXBMCApp::onDestroyWindow() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + + if (m_state.appState < Paused) + { + XBMC_DestroyDisplay(); + setAppState(Paused); + releaseWakeLock(); + } +} + +void CXBMCApp::onGainFocus() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + // everything is handled in onActivate() +} + +void CXBMCApp::onLostFocus() +{ + android_printf("%s: %d", __PRETTY_FUNCTION__, m_state.appState); + switch (m_state.appState) + { + case Initialized: + case Rendering: + XBMC_Pause(true); + setAppState(Unfocused); + break; + + default: + break; + } +} + +bool CXBMCApp::getWakeLock(JNIEnv *env) +{ + android_printf("%s", __PRETTY_FUNCTION__); + if (m_activity == NULL) + { + android_printf(" missing activity => unable to use WakeLocks"); + return false; + } + + if (env == NULL) + return false; + + if (m_wakeLock == NULL) + { + jobject oActivity = m_activity->clazz; + jclass cActivity = env->GetObjectClass(oActivity); + + // get the wake lock + jmethodID midActivityGetSystemService = env->GetMethodID(cActivity, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"); + jstring sPowerService = env->NewStringUTF("power"); // POWER_SERVICE + jobject oPowerManager = env->CallObjectMethod(oActivity, midActivityGetSystemService, sPowerService); + + jclass cPowerManager = env->GetObjectClass(oPowerManager); + jmethodID midNewWakeLock = env->GetMethodID(cPowerManager, "newWakeLock", "(ILjava/lang/String;)Landroid/os/PowerManager$WakeLock;"); + jstring sXbmcPackage = env->NewStringUTF("org.xbmc.xbmc"); + jobject oWakeLock = env->CallObjectMethod(oPowerManager, midNewWakeLock, (jint)0x1a /* FULL_WAKE_LOCK */, sXbmcPackage); + m_wakeLock = env->NewGlobalRef(oWakeLock); + + env->DeleteLocalRef(oWakeLock); + env->DeleteLocalRef(cPowerManager); + env->DeleteLocalRef(oPowerManager); + env->DeleteLocalRef(sPowerService); + env->DeleteLocalRef(sXbmcPackage); + env->DeleteLocalRef(cActivity); + } + + return m_wakeLock != NULL; +} + +void CXBMCApp::acquireWakeLock() +{ + if (m_activity == NULL) + return; + + JNIEnv *env = NULL; + AttachCurrentThread(&env); + + if (!getWakeLock(env)) + { + android_printf("%s: unable to acquire a WakeLock"); + return; + } + + jclass cWakeLock = env->GetObjectClass(m_wakeLock); + jmethodID midWakeLockAcquire = env->GetMethodID(cWakeLock, "acquire", "()V"); + env->CallVoidMethod(m_wakeLock, midWakeLockAcquire); + env->DeleteLocalRef(cWakeLock); + + DetachCurrentThread(); +} + +void CXBMCApp::releaseWakeLock() +{ + if (m_activity == NULL) + return; + + JNIEnv *env = NULL; + AttachCurrentThread(&env); + + if (!getWakeLock(env)) + { + android_printf("%s: unable to release a WakeLock"); + return; + } + + jclass cWakeLock = env->GetObjectClass(m_wakeLock); + jmethodID midWakeLockRelease = env->GetMethodID(cWakeLock, "release", "()V"); + env->CallVoidMethod(m_wakeLock, midWakeLockRelease); + env->DeleteLocalRef(cWakeLock); + + DetachCurrentThread(); +} + +void CXBMCApp::run() +{ + int status = 0; + setAppState(Initialized); + + android_printf(" => running XBMC_Run..."); + try + { + setAppState(Rendering); + status = XBMC_Run(true); + android_printf(" => XBMC_Run finished with %d", status); + } + catch(...) + { + android_printf("ERROR: Exception caught on main loop. Exiting"); + setAppState(Error); + } + + bool finishActivity = false; + pthread_mutex_lock(&m_state.mutex); + finishActivity = m_state.appState != Stopping; + m_state.appState = Stopped; + pthread_mutex_unlock(&m_state.mutex); + + if (finishActivity) + { + android_printf(" => calling ANativeActivity_finish()"); + ANativeActivity_finish(m_activity); + } +} + +void CXBMCApp::stop() +{ + android_printf("%s", __PRETTY_FUNCTION__); + + pthread_mutex_lock(&m_state.mutex); + if (m_state.appState < Stopped) + { + m_state.appState = Stopping; + pthread_mutex_unlock(&m_state.mutex); + + android_printf(" => executing XBMC_Stop"); + XBMC_Stop(); + android_printf(" => waiting for XBMC to finish"); + pthread_join(m_state.thread, NULL); + android_printf(" => XBMC finished"); + } + else + pthread_mutex_unlock(&m_state.mutex); + + if (m_wakeLock != NULL && m_activity != NULL) + { + JNIEnv *env = NULL; + m_activity->vm->AttachCurrentThread(&env, NULL); + + env->DeleteGlobalRef(m_wakeLock); + m_wakeLock = NULL; + } +} + +void CXBMCApp::setAppState(AppState state) +{ + pthread_mutex_lock(&m_state.mutex); + m_state.appState = state; + pthread_mutex_unlock(&m_state.mutex); +} + +void CXBMCApp::XBMC_Pause(bool pause) +{ + android_printf("XBMC_Pause(%s)", pause ? "true" : "false"); + // Only send the PAUSE action if we are pausing XBMC and something is currently playing + if (pause && g_application.IsPlaying() && !g_application.IsPaused()) + CApplicationMessenger::Get().SendAction(CAction(ACTION_PAUSE), WINDOW_INVALID, true); + + g_application.m_AppActive = g_application.m_AppFocused = !pause; +} + +void CXBMCApp::XBMC_Stop() +{ + CApplicationMessenger::Get().Quit(); +} + +bool CXBMCApp::XBMC_SetupDisplay() +{ + android_printf("XBMC_SetupDisplay()"); + return CApplicationMessenger::Get().SetupDisplay(); +} + +bool CXBMCApp::XBMC_DestroyDisplay() +{ + android_printf("XBMC_DestroyDisplay()"); + return CApplicationMessenger::Get().DestroyDisplay(); +} + +int CXBMCApp::AttachCurrentThread(JNIEnv** p_env, void* thr_args /* = NULL */) +{ + // Until a thread is attached, it has no JNIEnv, and cannot make JNI calls. + // The JNIEnv is used for thread-local storage. For this reason, + // you cannot share a JNIEnv between threads. + // If a thread is attached to JNIEnv and garbage collection is in progress, + // or the debugger has issued a suspend request, Android will + // pause the thread the next time it makes a JNI call. + return m_activity->vm->AttachCurrentThread(p_env, thr_args); +} + +int CXBMCApp::DetachCurrentThread() +{ + // Threads attached through JNIEnv must + // call DetachCurrentThread before they exit + return m_activity->vm->DetachCurrentThread(); +} + +int CXBMCApp::SetBuffersGeometry(int width, int height, int format) +{ + return ANativeWindow_setBuffersGeometry(m_window, width, height, format); +} + +int CXBMCApp::android_printf(const char *format, ...) +{ + // For use before CLog is setup by XBMC_Run() + va_list args; + va_start(args, format); + int result = __android_log_vprint(ANDROID_LOG_VERBOSE, "XBMC", format, args); + va_end(args); + return result; +} + +bool CXBMCApp::ListApplications(vector<androidPackage> *applications) +{ + if (!m_activity) + return false; + + JNIEnv *env = NULL; + AttachCurrentThread(&env); + jobject oActivity = m_activity->clazz; + jclass cActivity = env->GetObjectClass(oActivity); + + // oPackageManager = new PackageManager(); + jmethodID mgetPackageManager = env->GetMethodID(cActivity, "getPackageManager", "()Landroid/content/pm/PackageManager;"); + jobject oPackageManager = (jobject)env->CallObjectMethod(oActivity, mgetPackageManager); + env->DeleteLocalRef(cActivity); + + // adata[] = oPackageManager.getInstalledApplications(0); + jclass cPackageManager = env->GetObjectClass(oPackageManager); + jmethodID mgetInstalledApplications = env->GetMethodID(cPackageManager, "getInstalledApplications", "(I)Ljava/util/List;"); + jmethodID mgetApplicationLabel = env->GetMethodID(cPackageManager, "getApplicationLabel", "(Landroid/content/pm/ApplicationInfo;)Ljava/lang/CharSequence;"); + jobject odata = env->CallObjectMethod(oPackageManager, mgetInstalledApplications, 0); + jclass cdata = env->GetObjectClass(odata); + jmethodID mtoArray = env->GetMethodID(cdata, "toArray", "()[Ljava/lang/Object;"); + jobjectArray adata = (jobjectArray)env->CallObjectMethod(odata, mtoArray); + env->DeleteLocalRef(cdata); + env->DeleteLocalRef(odata); + env->DeleteLocalRef(cPackageManager); + + int size = env->GetArrayLength(adata); + for (int i = 0; i < size; i++) + { + // oApplicationInfo = adata[i]; + jobject oApplicationInfo = env->GetObjectArrayElement(adata, i); + jclass cApplicationInfo = env->GetObjectClass(oApplicationInfo); + jfieldID mclassName = env->GetFieldID(cApplicationInfo, "packageName", "Ljava/lang/String;"); + jstring sapplication = (jstring)env->GetObjectField(oApplicationInfo, mclassName); + + if (!sapplication) + { + env->DeleteLocalRef(cApplicationInfo); + env->DeleteLocalRef(oApplicationInfo); + continue; + } + // cname = oApplicationInfo.packageName; + const char* cname = env->GetStringUTFChars(sapplication, NULL); + androidPackage desc; + desc.packageName = cname; + env->ReleaseStringUTFChars(sapplication, cname); + env->DeleteLocalRef(sapplication); + env->DeleteLocalRef(cApplicationInfo); + + jstring spackageLabel = (jstring) env->CallObjectMethod(oPackageManager, mgetApplicationLabel, oApplicationInfo); + if (!spackageLabel) + { + env->DeleteLocalRef(oApplicationInfo); + continue; + } + // cname = opackageManager.getApplicationLabel(oApplicationInfo); + const char* cpackageLabel = env->GetStringUTFChars(spackageLabel, NULL); + desc.packageLabel = cpackageLabel; + env->ReleaseStringUTFChars(spackageLabel, cpackageLabel); + env->DeleteLocalRef(spackageLabel); + env->DeleteLocalRef(oApplicationInfo); + + if (!HasLaunchIntent(desc.packageName)) + continue; + + applications->push_back(desc); + } + env->DeleteLocalRef(oPackageManager); + DetachCurrentThread(); + return true; +} + +bool CXBMCApp::GetIconSize(const string &packageName, int *width, int *height) +{ + if (!m_activity) + return false; + + jthrowable exc; + JNIEnv *env = NULL; + AttachCurrentThread(&env); + + jobject oActivity = m_activity->clazz; + jclass cActivity = env->GetObjectClass(oActivity); + + // oPackageManager = new PackageManager(); + jmethodID mgetPackageManager = env->GetMethodID(cActivity, "getPackageManager", "()Landroid/content/pm/PackageManager;"); + jobject oPackageManager = (jobject)env->CallObjectMethod(oActivity, mgetPackageManager); + env->DeleteLocalRef(cActivity); + + jclass cPackageManager = env->GetObjectClass(oPackageManager); + jmethodID mgetApplicationIcon = env->GetMethodID(cPackageManager, "getApplicationIcon", "(Ljava/lang/String;)Landroid/graphics/drawable/Drawable;"); + env->DeleteLocalRef(cPackageManager); + + jclass cBitmapDrawable = env->FindClass("android/graphics/drawable/BitmapDrawable"); + jmethodID mBitmapDrawableCtor = env->GetMethodID(cBitmapDrawable, "<init>", "()V"); + jmethodID mgetBitmap = env->GetMethodID(cBitmapDrawable, "getBitmap", "()Landroid/graphics/Bitmap;"); + + // BitmapDrawable oBitmapDrawable; + jobject oBitmapDrawable = env->NewObject(cBitmapDrawable, mBitmapDrawableCtor); + jstring sPackageName = env->NewStringUTF(packageName.c_str()); + + // oBitmapDrawable = oPackageManager.getApplicationIcon(sPackageName) + oBitmapDrawable = env->CallObjectMethod(oPackageManager, mgetApplicationIcon, sPackageName); + jobject oBitmap = env->CallObjectMethod(oBitmapDrawable, mgetBitmap); + env->DeleteLocalRef(sPackageName); + env->DeleteLocalRef(cBitmapDrawable); + env->DeleteLocalRef(oBitmapDrawable); + env->DeleteLocalRef(oPackageManager); + exc = env->ExceptionOccurred(); + if (exc) + { + CLog::Log(LOGERROR, "CXBMCApp::GetIconSize Error getting icon size for %s. Exception follows:", packageName.c_str()); + env->ExceptionDescribe(); + env->ExceptionClear(); + env->DeleteLocalRef(oBitmap); + DetachCurrentThread(); + return false; + } + jclass cBitmap = env->GetObjectClass(oBitmap); + jmethodID mgetWidth = env->GetMethodID(cBitmap, "getWidth", "()I"); + jmethodID mgetHeight = env->GetMethodID(cBitmap, "getHeight", "()I"); + env->DeleteLocalRef(cBitmap); + + // width = oBitmap.getWidth; + *width = (int)env->CallIntMethod(oBitmap, mgetWidth); + + exc = env->ExceptionOccurred(); + if (exc) + { + CLog::Log(LOGERROR, "CXBMCApp::GetIconSize Error getting icon width for %s. Exception follows:", packageName.c_str()); + env->ExceptionDescribe(); + env->ExceptionClear(); + env->DeleteLocalRef(oBitmap); + DetachCurrentThread(); + return false; + } + // height = oBitmap.getHeight; + *height = (int)env->CallIntMethod(oBitmap, mgetHeight); + env->DeleteLocalRef(oBitmap); + + exc = env->ExceptionOccurred(); + if (exc) + { + CLog::Log(LOGERROR, "CXBMCApp::GetIconSize Error getting icon height for %s. Exception follows:", packageName.c_str()); + env->ExceptionDescribe(); + env->ExceptionClear(); + DetachCurrentThread(); + return false; + } + + DetachCurrentThread(); + return true; +} + +bool CXBMCApp::GetIcon(const string &packageName, void* buffer, unsigned int bufSize) +{ + if (!m_activity) + return false; + + jthrowable exc; + JNIEnv *env = NULL; + AttachCurrentThread(&env); + + CLog::Log(LOGERROR, "CXBMCApp::GetIconSize Looking for: %s", packageName.c_str()); + + jobject oActivity = m_activity->clazz; + jclass cActivity = env->GetObjectClass(oActivity); + + // oPackageManager = new PackageManager(); + jmethodID mgetPackageManager = env->GetMethodID(cActivity, "getPackageManager", "()Landroid/content/pm/PackageManager;"); + jobject oPackageManager = (jobject)env->CallObjectMethod(oActivity, mgetPackageManager); + env->DeleteLocalRef(cActivity); + + jclass cPackageManager = env->GetObjectClass(oPackageManager); + jmethodID mgetApplicationIcon = env->GetMethodID(cPackageManager, "getApplicationIcon", "(Ljava/lang/String;)Landroid/graphics/drawable/Drawable;"); + env->DeleteLocalRef(cPackageManager); + + jclass cBitmapDrawable = env->FindClass("android/graphics/drawable/BitmapDrawable"); + jmethodID mBitmapDrawableCtor = env->GetMethodID(cBitmapDrawable, "<init>", "()V"); + jmethodID mgetBitmap = env->GetMethodID(cBitmapDrawable, "getBitmap", "()Landroid/graphics/Bitmap;"); + + // BitmapDrawable oBitmapDrawable; + jobject oBitmapDrawable = env->NewObject(cBitmapDrawable, mBitmapDrawableCtor); + jstring sPackageName = env->NewStringUTF(packageName.c_str()); + + // oBitmapDrawable = oPackageManager.getApplicationIcon(sPackageName) + oBitmapDrawable = env->CallObjectMethod(oPackageManager, mgetApplicationIcon, sPackageName); + env->DeleteLocalRef(sPackageName); + env->DeleteLocalRef(cBitmapDrawable); + env->DeleteLocalRef(oPackageManager); + exc = env->ExceptionOccurred(); + if (exc) + { + CLog::Log(LOGERROR, "CXBMCApp::GetIcon Error getting icon for %s. Exception follows:", packageName.c_str()); + env->ExceptionDescribe(); + env->ExceptionClear(); + DetachCurrentThread(); + return false; + } + jobject oBitmap = env->CallObjectMethod(oBitmapDrawable, mgetBitmap); + env->DeleteLocalRef(oBitmapDrawable); + jclass cBitmap = env->GetObjectClass(oBitmap); + jmethodID mcopyPixelsToBuffer = env->GetMethodID(cBitmap, "copyPixelsToBuffer", "(Ljava/nio/Buffer;)V"); + jobject oPixels = env->NewDirectByteBuffer(buffer,bufSize); + env->DeleteLocalRef(cBitmap); + + // memcpy(buffer,oPixels,bufSize); + env->CallVoidMethod(oBitmap, mcopyPixelsToBuffer, oPixels); + env->DeleteLocalRef(oPixels); + env->DeleteLocalRef(oBitmap); + exc = env->ExceptionOccurred(); + if (exc) + { + CLog::Log(LOGERROR, "CXBMCApp::GetIcon Error copying icon for %s. Exception follows:", packageName.c_str()); + env->ExceptionDescribe(); + env->ExceptionClear(); + DetachCurrentThread(); + return false; + } + DetachCurrentThread(); + return true; +} + + +bool CXBMCApp::HasLaunchIntent(const string &package) +{ + if (!m_activity) + return false; + + JNIEnv *env = NULL; + AttachCurrentThread(&env); + + jthrowable exc; + jobject oActivity = m_activity->clazz; + jclass cActivity = env->GetObjectClass(oActivity); + + // oPackageManager = new PackageManager(); + jmethodID mgetPackageManager = env->GetMethodID(cActivity, "getPackageManager", "()Landroid/content/pm/PackageManager;"); + jobject oPackageManager = (jobject)env->CallObjectMethod(oActivity, mgetPackageManager); + + // oPackageIntent = oPackageManager.getLaunchIntentForPackage(package); + jclass cPackageManager = env->GetObjectClass(oPackageManager); + jmethodID mgetLaunchIntentForPackage = env->GetMethodID(cPackageManager, "getLaunchIntentForPackage", "(Ljava/lang/String;)Landroid/content/Intent;"); + jstring sPackageName = env->NewStringUTF(package.c_str()); + jobject oPackageIntent = env->CallObjectMethod(oPackageManager, mgetLaunchIntentForPackage, sPackageName); + env->DeleteLocalRef(sPackageName); + env->DeleteLocalRef(cPackageManager); + env->DeleteLocalRef(oPackageManager); + + exc = env->ExceptionOccurred(); + if (exc) + { + CLog::Log(LOGERROR, "CXBMCApp::HasLaunchIntent Error checking for Launch Intent for %s. Exception follows:", package.c_str()); + env->ExceptionDescribe(); + env->ExceptionClear(); + return false; + } + if (!oPackageIntent) + { + return false; + } + + env->DeleteLocalRef(oPackageIntent); + return true; +} + +bool CXBMCApp::StartActivity(const string &package) +{ + if (!m_activity || !package.size()) + return false; + + jthrowable exc; + JNIEnv *env = NULL; + AttachCurrentThread(&env); + jobject oActivity = m_activity->clazz; + jclass cActivity = env->GetObjectClass(oActivity); + + // oPackageManager = new PackageManager(); + jmethodID mgetPackageManager = env->GetMethodID(cActivity, "getPackageManager", "()Landroid/content/pm/PackageManager;"); + jobject oPackageManager = (jobject)env->CallObjectMethod(oActivity, mgetPackageManager); + + // oPackageIntent = oPackageManager.getLaunchIntentForPackage(package); + jclass cPackageManager = env->GetObjectClass(oPackageManager); + jmethodID mgetLaunchIntentForPackage = env->GetMethodID(cPackageManager, "getLaunchIntentForPackage", "(Ljava/lang/String;)Landroid/content/Intent;"); + jstring sPackageName = env->NewStringUTF(package.c_str()); + jobject oPackageIntent = env->CallObjectMethod(oPackageManager, mgetLaunchIntentForPackage, sPackageName); + env->DeleteLocalRef(cPackageManager); + env->DeleteLocalRef(sPackageName); + env->DeleteLocalRef(oPackageManager); + + exc = env->ExceptionOccurred(); + if (exc) + { + CLog::Log(LOGERROR, "CXBMCApp::StartActivity Failed to load %s. Exception follows:", package.c_str()); + env->ExceptionDescribe(); + env->ExceptionClear(); + env->DeleteLocalRef(cActivity); + DetachCurrentThread(); + return false; + } + if (!oPackageIntent) + { + CLog::Log(LOGERROR, "CXBMCApp::StartActivity %s has no Launch Intent", package.c_str()); + env->DeleteLocalRef(cActivity); + DetachCurrentThread(); + return false; + } + // startActivity(oIntent); + jmethodID mStartActivity = env->GetMethodID(cActivity, "startActivity", "(Landroid/content/Intent;)V"); + env->CallVoidMethod(oActivity, mStartActivity, oPackageIntent); + env->DeleteLocalRef(cActivity); + env->DeleteLocalRef(oPackageIntent); + + exc = env->ExceptionOccurred(); + if (exc) + { + CLog::Log(LOGERROR, "CXBMCApp::StartActivity Failed to load %s. Exception follows:", package.c_str()); + env->ExceptionDescribe(); + env->ExceptionClear(); + DetachCurrentThread(); + return false; + } + + DetachCurrentThread(); + return true; +} + +int CXBMCApp::GetBatteryLevel() +{ + if (m_activity == NULL) + return -1; + + JNIEnv *env = NULL; + AttachCurrentThread(&env); + jobject oActivity = m_activity->clazz; + + // IntentFilter oIntentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + jclass cIntentFilter = env->FindClass("android/content/IntentFilter"); + jmethodID midIntentFilterCtor = env->GetMethodID(cIntentFilter, "<init>", "(Ljava/lang/String;)V"); + jstring sIntentBatteryChanged = env->NewStringUTF("android.intent.action.BATTERY_CHANGED"); // Intent.ACTION_BATTERY_CHANGED + jobject oIntentFilter = env->NewObject(cIntentFilter, midIntentFilterCtor, sIntentBatteryChanged); + env->DeleteLocalRef(cIntentFilter); + env->DeleteLocalRef(sIntentBatteryChanged); + + // Intent oBatteryStatus = activity.registerReceiver(null, oIntentFilter); + jclass cActivity = env->GetObjectClass(oActivity); + jmethodID midActivityRegisterReceiver = env->GetMethodID(cActivity, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;"); + env->DeleteLocalRef(cActivity); + jobject oBatteryStatus = env->CallObjectMethod(oActivity, midActivityRegisterReceiver, NULL, oIntentFilter); + + jclass cIntent = env->GetObjectClass(oBatteryStatus); + jmethodID midIntentGetIntExtra = env->GetMethodID(cIntent, "getIntExtra", "(Ljava/lang/String;I)I"); + env->DeleteLocalRef(cIntent); + + // int iLevel = oBatteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); + jstring sBatteryManagerExtraLevel = env->NewStringUTF("level"); // BatteryManager.EXTRA_LEVEL + jint iLevel = env->CallIntMethod(oBatteryStatus, midIntentGetIntExtra, sBatteryManagerExtraLevel, (jint)-1); + env->DeleteLocalRef(sBatteryManagerExtraLevel); + // int iScale = oBatteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1); + jstring sBatteryManagerExtraScale = env->NewStringUTF("scale"); // BatteryManager.EXTRA_SCALE + jint iScale = env->CallIntMethod(oBatteryStatus, midIntentGetIntExtra, sBatteryManagerExtraScale, (jint)-1); + env->DeleteLocalRef(sBatteryManagerExtraScale); + env->DeleteLocalRef(oBatteryStatus); + env->DeleteLocalRef(oIntentFilter); + + DetachCurrentThread(); + + if (iLevel <= 0 || iScale < 0) + return iLevel; + + return ((int)iLevel * 100) / (int)iScale; +} + +bool CXBMCApp::GetExternalStorage(std::string &path, const std::string &type /* = "" */) +{ + if (m_activity == NULL) + return false; + + JNIEnv *env = NULL; + AttachCurrentThread(&env); + + // check if external storage is available + // String sStorageState = android.os.Environment.getExternalStorageState(); + jclass cEnvironment = env->FindClass("android/os/Environment"); + jmethodID midEnvironmentGetExternalStorageState = env->GetStaticMethodID(cEnvironment, "getExternalStorageState", "()Ljava/lang/String;"); + jstring sStorageState = (jstring)env->CallStaticObjectMethod(cEnvironment, midEnvironmentGetExternalStorageState); + // if (sStorageState != Environment.MEDIA_MOUNTED && sStorageState != Environment.MEDIA_MOUNTED_READ_ONLY) return false; + const char* storageState = env->GetStringUTFChars(sStorageState, NULL); + bool mounted = strcmp(storageState, "mounted") == 0 || strcmp(storageState, "mounted_ro") == 0; + env->ReleaseStringUTFChars(sStorageState, storageState); + env->DeleteLocalRef(sStorageState); + + if (mounted) + { + jobject oExternalStorageDirectory = NULL; + if (type.empty() || type == "files") + { + // File oExternalStorageDirectory = Environment.getExternalStorageDirectory(); + jmethodID midEnvironmentGetExternalStorageDirectory = env->GetStaticMethodID(cEnvironment, "getExternalStorageDirectory", "()Ljava/io/File;"); + oExternalStorageDirectory = env->CallStaticObjectMethod(cEnvironment, midEnvironmentGetExternalStorageDirectory); + } + else if (type == "music" || type == "videos" || type == "pictures" || type == "photos" || type == "downloads") + { + jstring sType = NULL; + if (type == "music") + sType = env->NewStringUTF("Music"); // Environment.DIRECTORY_MUSIC + else if (type == "videos") + sType = env->NewStringUTF("Movies"); // Environment.DIRECTORY_MOVIES + else if (type == "pictures") + sType = env->NewStringUTF("Pictures"); // Environment.DIRECTORY_PICTURES + else if (type == "photos") + sType = env->NewStringUTF("DCIM"); // Environment.DIRECTORY_DCIM + else if (type == "downloads") + sType = env->NewStringUTF("Download"); // Environment.DIRECTORY_DOWNLOADS + + // File oExternalStorageDirectory = Environment.getExternalStoragePublicDirectory(sType); + jmethodID midEnvironmentGetExternalStoragePublicDirectory = env->GetStaticMethodID(cEnvironment, "getExternalStoragePublicDirectory", "(Ljava/lang/String;)Ljava/io/File;"); + oExternalStorageDirectory = env->CallStaticObjectMethod(cEnvironment, midEnvironmentGetExternalStoragePublicDirectory, sType); + env->DeleteLocalRef(sType); + } + + if (oExternalStorageDirectory != NULL) + { + // path = oExternalStorageDirectory.getAbsolutePath(); + jclass cFile = env->GetObjectClass(oExternalStorageDirectory); + jmethodID midFileGetAbsolutePath = env->GetMethodID(cFile, "getAbsolutePath", "()Ljava/lang/String;"); + env->DeleteLocalRef(cFile); + jstring sPath = (jstring)env->CallObjectMethod(oExternalStorageDirectory, midFileGetAbsolutePath); + const char* cPath = env->GetStringUTFChars(sPath, NULL); + path = cPath; + env->ReleaseStringUTFChars(sPath, cPath); + env->DeleteLocalRef(sPath); + env->DeleteLocalRef(oExternalStorageDirectory); + } + else + mounted = false; + } + + env->DeleteLocalRef(cEnvironment); + + DetachCurrentThread(); + + return mounted && !path.empty(); +} + +bool CXBMCApp::GetStorageUsage(const std::string &path, std::string &usage) +{ + if (m_activity == NULL) + return false; + + if (path.empty()) + { + ostringstream fmt; + fmt.width(24); fmt << left << "Filesystem"; + fmt.width(12); fmt << right << "Size"; + fmt.width(12); fmt << "Used"; + fmt.width(12); fmt << "Avail"; + fmt.width(12); fmt << "Use %"; + + usage = fmt.str(); + return false; + } + + JNIEnv *env = NULL; + AttachCurrentThread(&env); + + // android.os.StatFs oStats = new android.os.StatFs(sPath); + jclass cStatFs = env->FindClass("android/os/StatFs"); + jmethodID midStatFsCtor = env->GetMethodID(cStatFs, "<init>", "(Ljava/lang/String;)V"); + jstring sPath = env->NewStringUTF(path.c_str()); + jobject oStats = env->NewObject(cStatFs, midStatFsCtor, sPath); + env->DeleteLocalRef(sPath); + + // int iBlockSize = oStats.getBlockSize(); + jmethodID midStatFsGetBlockSize = env->GetMethodID(cStatFs, "getBlockSize", "()I"); + jint iBlockSize = env->CallIntMethod(oStats, midStatFsGetBlockSize); + + // int iBlocksTotal = oStats.getBlockCount(); + jmethodID midStatFsGetBlockCount = env->GetMethodID(cStatFs, "getBlockCount", "()I"); + jint iBlocksTotal = env->CallIntMethod(oStats, midStatFsGetBlockCount); + + // int iBlocksFree = oStats.getFreeBlocks(); + jmethodID midStatFsGetFreeBlocks = env->GetMethodID(cStatFs, "getFreeBlocks", "()I"); + jint iBlocksFree = env->CallIntMethod(oStats, midStatFsGetFreeBlocks); + + env->DeleteLocalRef(oStats); + env->DeleteLocalRef(cStatFs); + + DetachCurrentThread(); + + if (iBlockSize <= 0 || iBlocksTotal <= 0 || iBlocksFree < 0) + return false; + + float totalSize = (float)iBlockSize * iBlocksTotal / GIGABYTES; + float freeSize = (float)iBlockSize * iBlocksFree / GIGABYTES; + float usedSize = totalSize - freeSize; + float usedPercentage = usedSize / totalSize * 100; + + ostringstream fmt; + fmt << fixed; + fmt.precision(1); + fmt.width(24); fmt << left << path; + fmt.width(12); fmt << right << totalSize << "G"; // size in GB + fmt.width(12); fmt << usedSize << "G"; // used in GB + fmt.width(12); fmt << freeSize << "G"; // free + fmt.precision(0); + fmt.width(12); fmt << usedPercentage << "%"; // percentage used + + usage = fmt.str(); + return true; +} diff --git a/xbmc/android/activity/XBMCApp.h b/xbmc/android/activity/XBMCApp.h new file mode 100644 index 0000000000..9220c98816 --- /dev/null +++ b/xbmc/android/activity/XBMCApp.h @@ -0,0 +1,156 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <math.h> +#include <pthread.h> +#include <string> +#include <vector> + +#include <android/native_activity.h> + +#include "IActivityHandler.h" +#include "IInputHandler.h" + +#include "xbmc.h" + + +// forward delares +class CAESinkAUDIOTRACK; +typedef struct _JNIEnv JNIEnv; + +struct androidIcon +{ + unsigned int width; + unsigned int height; + void *pixels; +}; + +struct androidPackage +{ + std::string packageName; + std::string packageLabel; +}; + + +class CXBMCApp : public IActivityHandler +{ +public: + CXBMCApp(ANativeActivity *nativeActivity); + virtual ~CXBMCApp(); + + bool isValid() { return m_activity != NULL; } + + ActivityResult onActivate(); + void onDeactivate(); + + void onStart(); + void onResume(); + void onPause(); + void onStop(); + void onDestroy(); + + void onSaveState(void **data, size_t *size); + void onConfigurationChanged(); + void onLowMemory(); + + void onCreateWindow(ANativeWindow* window); + void onResizeWindow(); + void onDestroyWindow(); + void onGainFocus(); + void onLostFocus(); + + + static ANativeWindow* GetNativeWindow() { return m_window; }; + static int SetBuffersGeometry(int width, int height, int format); + static int android_printf(const char *format, ...); + + static int GetBatteryLevel(); + static bool StartActivity(const std::string &package); + static bool ListApplications(std::vector <androidPackage> *applications); + static bool GetIconSize(const std::string &packageName, int *width, int *height); + static bool GetIcon(const std::string &packageName, void* buffer, unsigned int bufSize); + /*! + * \brief If external storage is available, it returns the path for the external storage (for the specified type) + * \param path will contain the path of the external storage (for the specified type) + * \param type optional type. Possible values are "", "files", "music", "videos", "pictures", "photos, "downloads" + * \return true if external storage is available and a valid path has been stored in the path parameter + */ + static bool GetExternalStorage(std::string &path, const std::string &type = ""); + static bool GetStorageUsage(const std::string &path, std::string &usage); + +protected: + // limit who can access AttachCurrentThread/DetachCurrentThread + friend class CAESinkAUDIOTRACK; + friend class CAndroidFeatures; + friend class CFileAndroidApp; + + static int AttachCurrentThread(JNIEnv** p_env, void* thr_args = NULL); + static int DetachCurrentThread(); + +private: + static bool HasLaunchIntent(const std::string &package); + bool getWakeLock(JNIEnv *env); + void acquireWakeLock(); + void releaseWakeLock(); + void run(); + void stop(); + + static ANativeActivity *m_activity; + jobject m_wakeLock; + + typedef enum { + // XBMC_Initialize hasn't been executed yet + Uninitialized, + // XBMC_Initialize has been successfully executed + Initialized, + // XBMC is currently rendering + Rendering, + // XBMC has stopped rendering because it has lost focus + // but it still has an EGLContext + Unfocused, + // XBMC has been paused/stopped and does not have an + // EGLContext + Paused, + // XBMC is being stopped + Stopping, + // XBMC has stopped + Stopped, + // An error has occured + Error + } AppState; + + typedef struct { + pthread_t thread; + pthread_mutex_t mutex; + AppState appState; + } State; + + State m_state; + + void setAppState(AppState state); + + static ANativeWindow* m_window; + + void XBMC_Pause(bool pause); + void XBMC_Stop(); + bool XBMC_DestroyDisplay(); + bool XBMC_SetupDisplay(); +}; diff --git a/xbmc/android/activity/android_main.cpp b/xbmc/android/activity/android_main.cpp new file mode 100644 index 0000000000..b74fc873ee --- /dev/null +++ b/xbmc/android/activity/android_main.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <dlfcn.h> + +#include <android_native_app_glue.h> +#include <jni.h> + +#include "EventLoop.h" +#include "XBMCApp.h" +#include "unzip.h" + +void setup_env(struct android_app* state) +{ + JavaVM* vm = state->activity->vm; + JNIEnv* env = state->activity->env; + const char* temp; + + vm->AttachCurrentThread(&env, NULL); + jobject oActivity = state->activity->clazz; + jclass cActivity = env->GetObjectClass(oActivity); + + // get the path to the android system libraries + jclass cSystem = env->FindClass("java/lang/System"); + jmethodID midSystemGetProperty = env->GetStaticMethodID(cSystem, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;"); + jstring sJavaLibraryPath = env->NewStringUTF("java.library.path"); + jstring sSystemLibraryPath = (jstring)env->CallStaticObjectMethod(cSystem, midSystemGetProperty, sJavaLibraryPath); + temp = env->GetStringUTFChars(sSystemLibraryPath, NULL); + setenv("XBMC_ANDROID_SYSTEM_LIBS", temp, 0); + env->ReleaseStringUTFChars(sSystemLibraryPath, temp); + env->DeleteLocalRef(sJavaLibraryPath); + env->DeleteLocalRef(sSystemLibraryPath); + env->DeleteLocalRef(cSystem); + + // get the path to XBMC's data directory (usually /data/data/<app-name>) + jmethodID midActivityGetApplicationInfo = env->GetMethodID(cActivity, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;"); + jobject oApplicationInfo = env->CallObjectMethod(oActivity, midActivityGetApplicationInfo); + jclass cApplicationInfo = env->GetObjectClass(oApplicationInfo); + jfieldID fidApplicationInfoDataDir = env->GetFieldID(cApplicationInfo, "dataDir", "Ljava/lang/String;"); + jstring sDataDir = (jstring)env->GetObjectField(oApplicationInfo, fidApplicationInfoDataDir); + temp = env->GetStringUTFChars(sDataDir, NULL); + setenv("XBMC_ANDROID_DATA", temp, 0); + env->ReleaseStringUTFChars(sDataDir, temp); + env->DeleteLocalRef(sDataDir); + + // get the path to where android extracts native libraries to + jfieldID fidApplicationInfoNativeLibraryDir = env->GetFieldID(cApplicationInfo, "nativeLibraryDir", "Ljava/lang/String;"); + jstring sNativeLibraryDir = (jstring)env->GetObjectField(oApplicationInfo, fidApplicationInfoNativeLibraryDir); + temp = env->GetStringUTFChars(sNativeLibraryDir, NULL); + setenv("XBMC_ANDROID_LIBS", temp, 0); + env->ReleaseStringUTFChars(sNativeLibraryDir, temp); + env->DeleteLocalRef(sNativeLibraryDir); + env->DeleteLocalRef(oApplicationInfo); + env->DeleteLocalRef(cApplicationInfo); + + // get the path to the APK + char apkPath[PATH_MAX] = {0}; + jmethodID midActivityGetPackageResourcePath = env->GetMethodID(cActivity, "getPackageResourcePath", "()Ljava/lang/String;"); + jstring sApkPath = (jstring)env->CallObjectMethod(oActivity, midActivityGetPackageResourcePath); + temp = env->GetStringUTFChars(sApkPath, NULL); + strcpy(apkPath, temp); + setenv("XBMC_ANDROID_APK", apkPath, 0); + env->ReleaseStringUTFChars(sApkPath, temp); + env->DeleteLocalRef(sApkPath); + + // Get the path to the temp/cache directory + char cacheDir[PATH_MAX] = {0}; + char tempDir[PATH_MAX] = {0}; + jmethodID midActivityGetCacheDir = env->GetMethodID(cActivity, "getCacheDir", "()Ljava/io/File;"); + jobject oCacheDir = env->CallObjectMethod(oActivity, midActivityGetCacheDir); + + jclass cFile = env->GetObjectClass(oCacheDir); + jmethodID midFileGetAbsolutePath = env->GetMethodID(cFile, "getAbsolutePath", "()Ljava/lang/String;"); + env->DeleteLocalRef(cFile); + + jstring sCachePath = (jstring)env->CallObjectMethod(oCacheDir, midFileGetAbsolutePath); + temp = env->GetStringUTFChars(sCachePath, NULL); + strcpy(cacheDir, temp); + strcpy(tempDir, temp); + env->ReleaseStringUTFChars(sCachePath, temp); + env->DeleteLocalRef(sCachePath); + env->DeleteLocalRef(oCacheDir); + + strcat(tempDir, "/temp"); + setenv("XBMC_TEMP", tempDir, 0); + + strcat(cacheDir, "/apk"); + + //cache assets from the apk + extract_to_cache(apkPath, cacheDir); + + strcat(cacheDir, "/assets"); + setenv("XBMC_BIN_HOME", cacheDir, 0); + setenv("XBMC_HOME" , cacheDir, 0); + + // Get the path to the external storage + // The path would actually be available from state->activity->externalDataPath (apart from a (known) bug in Android 2.3.x) + // but calling getExternalFilesDir() will automatically create the necessary directories for us. + // There might NOT be external storage present so check it before trying to setup. + char storagePath[PATH_MAX] = {0}; + jmethodID midActivityGetExternalFilesDir = env->GetMethodID(cActivity, "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;"); + jobject oExternalDir = env->CallObjectMethod(oActivity, midActivityGetExternalFilesDir, (jstring)NULL); + if (oExternalDir) + { + jstring sExternalPath = (jstring)env->CallObjectMethod(oExternalDir, midFileGetAbsolutePath); + temp = env->GetStringUTFChars(sExternalPath, NULL); + strcpy(storagePath, temp); + env->ReleaseStringUTFChars(sExternalPath, temp); + env->DeleteLocalRef(sExternalPath); + env->DeleteLocalRef(oExternalDir); + } + + // Check if we don't have a valid path yet + if (strlen(storagePath) <= 0) + { + // Get the path to the internal storage + // For more details see the comment on getting the path to the external storage + jstring sXbmcName = env->NewStringUTF("org.xbmc.xbmc"); + jmethodID midActivityGetDir = env->GetMethodID(cActivity, "getDir", "(Ljava/lang/String;I)Ljava/io/File;"); + jobject oInternalDir = env->CallObjectMethod(oActivity, midActivityGetDir, sXbmcName, 1 /* MODE_WORLD_READABLE */); + env->DeleteLocalRef(sXbmcName); + + jstring sInternalPath = (jstring)env->CallObjectMethod(oInternalDir, midFileGetAbsolutePath); + temp = env->GetStringUTFChars(sInternalPath, NULL); + strcpy(storagePath, temp); + env->ReleaseStringUTFChars(sInternalPath, temp); + env->DeleteLocalRef(sInternalPath); + env->DeleteLocalRef(oInternalDir); + } + + env->DeleteLocalRef(cActivity); + + // Check if we have a valid home path + if (strlen(storagePath) > 0) + setenv("HOME", storagePath, 0); + else + setenv("HOME", getenv("XBMC_TEMP"), 0); + + state->activity->vm->DetachCurrentThread(); +} + +extern void android_main(struct android_app* state) +{ + // make sure that the linker doesn't strip out our glue + app_dummy(); + + setup_env(state); + CEventLoop eventLoop(state); + CXBMCApp xbmcApp(state->activity); + IInputHandler inputHandler; + if (xbmcApp.isValid()) + eventLoop.run(xbmcApp, inputHandler); + else + CXBMCApp::android_printf("android_main: setup failed"); + + CXBMCApp::android_printf("android_main: Exiting"); + // We need to call exit() so that all loaded libraries are properly unloaded + // otherwise on the next start of the Activity android will simple re-use + // those loaded libs in the state they were in when we quit XBMC last time + // which will lead to crashes because of global/static classes that haven't + // been properly uninitialized + exit(0); +} diff --git a/xbmc/android/activity/unzip.cpp b/xbmc/android/activity/unzip.cpp new file mode 100644 index 0000000000..d07d185b76 --- /dev/null +++ b/xbmc/android/activity/unzip.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <errno.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <utime.h> +#include <zip.h> +#include "XBMCApp.h" + +typedef struct stat Stat; + +static int do_mkdir(const char *path) +{ + Stat st; + int status = 0; + + if (stat(path, &st) != 0) + { + /* Directory does not exist */ + if (mkdir(path, 0755) != 0) + status = -1; + } + else if (!S_ISDIR(st.st_mode)) + { + errno = ENOTDIR; + status = -1; + } + + return(status); +} + +int mkpath(const char *path) +{ + char *pp; + char *sp; + int status; + char *copypath = strdup(path); + + status = 0; + pp = copypath; + while (status == 0 && (sp = strchr(pp, '/')) != 0) + { + if (sp != pp) + { + /* Neither root nor double slash in path */ + *sp = '\0'; + status = do_mkdir(copypath); + *sp = '/'; + } + pp = sp + 1; + } + if (status == 0) + status = do_mkdir(path); + free(copypath); + return (status); +} + +int extract_to_cache(const char *archive, const char *cache_path) +{ + struct zip *ziparchive; + struct zip_file *zipfile; + struct zip_stat zipstat; + char buf[4096]; + int err; + int len; + int fd; + int dirname_len; + uint64_t sum; + char *full_path; + char *dir_name; + Stat localfile; + utimbuf modified; + CXBMCApp::android_printf("unzip: Preparing to cache. This could take a while..."); + + if ((ziparchive = zip_open(archive, 0, &err)) == NULL) + { + zip_error_to_str(buf, sizeof(buf), err, errno); + CXBMCApp::android_printf("unzip error: can't open archive %s/n",archive); + return 1; + } + + mkpath(cache_path); + + for (size_t i = 0; i < zip_get_num_entries(ziparchive, 0); i++) + { + if (zip_stat_index(ziparchive, i, 0, &zipstat) != 0) + { + CXBMCApp::android_printf("unzip error: can't open entry: %i/n",i); + continue; + } + + if(strncmp (zipstat.name,"assets/",7) != 0) + continue; + + if(strncmp (zipstat.name,"assets/python2.6",16) == 0) + continue; + + modified.modtime = modified.actime = zipstat.mtime; + + full_path = (char*)malloc( sizeof(char*) * (strlen(cache_path) + 1 + strlen(zipstat.name) + 1)); + sprintf(full_path, "%s/%s",cache_path,zipstat.name); + + if (zipstat.name[strlen(zipstat.name) - 1] == '/') + { + mkpath(full_path); + free(full_path); + continue; + } + + zipfile = zip_fopen_index(ziparchive, i, 0); + if (!zipfile) + { + CXBMCApp::android_printf("unzip error: can't open index"); + free(full_path); + continue; + } + + if (stat(full_path, &localfile) != 0) + { + dirname_len = strrchr(zipstat.name,'/') - zipstat.name; + dir_name = (char*)malloc( sizeof(char*) * (strlen(cache_path) + 1 + dirname_len + 1)); + strncpy(dir_name, full_path, strlen(cache_path) + dirname_len + 1); + dir_name[strlen(cache_path) + dirname_len + 1] = '\0'; + mkpath(dir_name); + free(dir_name); + } + // watch this compare, zipstat.mtime is time_t which is a signed long + else if (localfile.st_mtime == (unsigned long)zipstat.mtime) + { + free(full_path); + continue; + } + + fd = open(full_path, O_RDWR | O_TRUNC | O_CREAT, 0644); + if(fd < 0) + { + CXBMCApp::android_printf("unzip error: could not open %s",full_path); + free(full_path); + continue; + } + + sum = 0; + while (sum != zipstat.size) + { + len = zip_fread(zipfile, buf, 4096); + if (len < 0) + { + CXBMCApp::android_printf("unzip error: no data in %s",full_path); + free(full_path); + continue; + } + write(fd, buf, len); + sum += len; + } + close(fd); + zip_fclose(zipfile); + + if (stat(full_path, &localfile) == 0) + { + // save the zip time. this way we know for certain if we need to refresh. + utime(full_path, &modified); + } + else + { + CXBMCApp::android_printf("unzip error: failed to extract %s",full_path); + } + + free(full_path); + } + + if (zip_close(ziparchive) == -1) + CXBMCApp::android_printf("unzip error: can't close zip archive `%s'/n", archive); + + return 0; +} diff --git a/xbmc/android/activity/unzip.h b/xbmc/android/activity/unzip.h new file mode 100644 index 0000000000..f531c00930 --- /dev/null +++ b/xbmc/android/activity/unzip.h @@ -0,0 +1,22 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +int extract_to_cache(const char*, const char*); diff --git a/xbmc/android/loader/AndroidDyload.cpp b/xbmc/android/loader/AndroidDyload.cpp new file mode 100644 index 0000000000..db8017d239 --- /dev/null +++ b/xbmc/android/loader/AndroidDyload.cpp @@ -0,0 +1,332 @@ +#include <sys/stat.h> +#include <stdlib.h> +#include <string> +#include <elf.h> +#include <errno.h> +#include <vector> +#include <dlfcn.h> +#include <fcntl.h> +#include "android/activity/XBMCApp.h" +#include "AndroidDyload.h" +using namespace std; + +//#define DEBUG_SPEW + +std::list<recursivelib> CAndroidDyload::m_recursivelibs; +solib CAndroidDyload::m_libs; + +bool CAndroidDyload::IsSystemLib(const string &filename) +{ + { + CSingleLock lock(m_libLock); + for ( solibit i = m_libs.begin() ; i != m_libs.end(); i++ ) + { + if (i->first == filename) + return i->second.system; + } + } + + string result = FindLib(filename, false); + if (result.size() > 0) + return false; + result = FindLib(filename, true); + return result.size() > 0; +} + +string CAndroidDyload::FindLib(const string &filename, bool checkSystem) +{ + struct stat st; + string path; + strings searchpaths; + string systemLibs = (getenv("XBMC_ANDROID_SYSTEM_LIBS")); + string localLibs = getenv("XBMC_ANDROID_LIBS"); + string dirname = filename.substr(0,filename.find_last_of('/')); + + while (true) + { + size_t pos = systemLibs.find(":"); + searchpaths.push_back(systemLibs.substr(0, pos)); + + if (pos != string::npos) + systemLibs.erase(0, pos + 1); + else + break; + } + + // Check xbmc package libs + path = (localLibs+"/"+filename.substr(filename.find_last_of('/') +1)); + if (stat((path).c_str(), &st) == 0) + return(path); + + // Check system libs. If we're not looking in system libs, bail. + // Note that we also bail if the explicit path happens to itself be a system + // lib and checkSystem == false. + for (strings::iterator j = searchpaths.begin(); j != searchpaths.end(); ++j) + { + path = (*j+"/"+filename.substr(filename.find_last_of('/') +1)); + if (stat((path).c_str(), &st) == 0) + { + if (checkSystem) + return(path); + else + { + if (dirname == *j) + return ""; + } + } + } + + // Nothing found yet, try the full given path. + if (stat((filename).c_str(), &st) == 0) + return(filename); + + return ""; +} + +void* CAndroidDyload::Find(const string &filename) +{ + CSingleLock lock(m_libLock); + solibit i = m_libs.find(filename); + return i == m_libs.end() ? NULL : i->second.handle; +} + +string CAndroidDyload::Find(void *handle) +{ + CSingleLock lock(m_libLock); + for ( solibit i = m_libs.begin() ; i != m_libs.end(); i++ ) + { + if (i->second.handle == handle) + return i->first; + } + return ""; +} + +void *CAndroidDyload::FindInDeps(const string &filename) +{ + CSingleLock lock(m_depsLock); + for (std::list<recursivelibdep>::iterator k = m_lib.deps.begin(); k != m_lib.deps.end(); k++) + { + if (k->filename == filename) + return k->handle; + } + return NULL; +} + +int CAndroidDyload::AddRef(const string &filename) +{ + CSingleLock lock(m_libLock); + if (m_libs.find(filename) == m_libs.end()) + return -1; + return (++(m_libs[filename].refcount)); +} + +int CAndroidDyload::DecRef(const string &filename) +{ + CSingleLock lock(m_libLock); + if (m_libs.find(filename) == m_libs.end()) + return -1; + return (--(m_libs[filename].refcount)); +} + +void CAndroidDyload::GetDeps(string filename, strings *results) +{ + Elf32_Ehdr header; + char *data = NULL; + int fd, i; + + fd = open(filename.c_str(), O_RDONLY); + if(fd < 0) + { + CXBMCApp::android_printf("Cannot open %s: %s\n", filename.c_str(), strerror(errno)); + return; + } + + if(read(fd, &header, sizeof(header)) < 0) + { + CXBMCApp::android_printf("Cannot read elf header: %s\n", strerror(errno)); + return; + } + + lseek(fd, header.e_shoff, SEEK_SET); + + for(i = 0; i < header.e_shnum; i++) + { + Elf32_Shdr sheader; + + lseek(fd, header.e_shoff + (i * header.e_shentsize), SEEK_SET); + read(fd, &sheader, sizeof(sheader)); + + if(sheader.sh_type == SHT_DYNSYM) + { + Elf32_Shdr symheader; + lseek(fd, header.e_shoff + (sheader.sh_link * header.e_shentsize), SEEK_SET); + read(fd, &symheader, sizeof(Elf32_Shdr)); + lseek(fd, symheader.sh_offset, SEEK_SET); + data = (char*)malloc(symheader.sh_size); + read(fd, data, symheader.sh_size); + break; + } + } + + if(!data) + return; + + for(i = 0; i < header.e_shnum; i++) + { + Elf32_Shdr sheader; + + lseek(fd, header.e_shoff + (i * header.e_shentsize), SEEK_SET); + read(fd, &sheader, sizeof(Elf32_Shdr)); + + if (sheader.sh_type == SHT_DYNAMIC) + { + unsigned int j; + + lseek(fd, sheader.sh_offset, SEEK_SET); + for(j = 0; j < sheader.sh_size / sizeof(Elf32_Dyn); j++) + { + Elf32_Dyn cur; + read(fd, &cur, sizeof(Elf32_Dyn)); + if(cur.d_tag == DT_NEEDED) + { + char *final = data + cur.d_un.d_val; + results->push_back(final); + } + } + } + } + return; +} + +void* CAndroidDyload::Open(const char * path) +{ + string filename = path; + filename = filename.substr(filename.find_last_of('/') +1); + void *handle = NULL; + m_lib.deps.clear(); + handle = Find(filename); + if (handle) + { + AddRef(filename); + return handle; + } + bool checkSystem = IsSystemLib(path); + handle = Open_Internal(filename, checkSystem); + if (handle != NULL) + { + CSingleLock lock(m_depsLock); + m_lib.handle = handle; + m_lib.filename = filename; + m_recursivelibs.push_back(m_lib); +#if defined(DEBUG_SPEW) + CXBMCApp::android_printf("xb_dlopen: opening lib: %s", filename.c_str()); + Dump(); +#endif + } + return handle; +} + +void* CAndroidDyload::Open_Internal(string filename, bool checkSystem) +{ + strings deps; + string deppath; + libdata lib; + void *handle = NULL; + + string path = FindLib(filename, checkSystem); + if (!path.size()) + return NULL; + + GetDeps(path, &deps); + + for (strings::iterator j = deps.begin(); j != deps.end(); ++j) + { + // Don't traverse into libxbmc's deps, they're guaranteed to be loaded. + if (*j == "libxbmc.so") + continue; + + if (FindInDeps(*j)) + continue; + + handle = Find(*j); + if (handle) + { + if (IsSystemLib(*j) && !checkSystem) + continue; + recursivelibdep dep; + dep.handle = handle; + dep.filename = *j; + m_lib.deps.push_back(dep); + AddRef(*j); + continue; + } + + Open_Internal(*j, checkSystem); + } + + handle = dlopen(path.c_str(), RTLD_LOCAL); + + if (handle == NULL) + CXBMCApp::android_printf("xb_dlopen: Error from dlopen(%s): %s", path.c_str(), dlerror()); + + recursivelibdep dep; + dep.handle = handle; + dep.filename = filename; + m_lib.deps.push_back(dep); + + lib.refcount = 1; + lib.handle = handle; + lib.system = checkSystem; + + CSingleLock lock(m_libLock); + m_libs[filename] = lib; + + return handle; +} + +int CAndroidDyload::Close(void *handle) +{ + CSingleLock lock(m_depsLock); + for (std::list<recursivelib>::iterator i = m_recursivelibs.begin(); i != m_recursivelibs.end(); i++) + { + if (i->handle == handle) + { + for (std::list<recursivelibdep>::iterator j = i->deps.begin(); j != i->deps.end(); j++) + { + if (DecRef(j->filename) == 0) + { + if (dlclose(j->handle)) + CXBMCApp::android_printf("xb_dlopen: Error from dlopen(%s): %s", j->filename.c_str(), dlerror()); + + CSingleLock lock(m_libLock); + m_libs.erase(j->filename); + } + } + m_recursivelibs.erase(i); +#if defined(DEBUG_SPEW) + Dump(); +#endif + return 0; + } + } + return 1; +} + +void CAndroidDyload::Dump() +{ + CSingleLock liblock(m_libLock); + for ( solibit i = m_libs.begin() ; i != m_libs.end(); i++ ) + { + CXBMCApp::android_printf("lib: %s. refcount: %i",i->first.c_str(), i->second.refcount); + } + + CSingleLock depslock(m_depsLock); + for (std::list<recursivelib>::iterator i = m_recursivelibs.begin(); i != m_recursivelibs.end(); i++) + { + CXBMCApp::android_printf("xb_dlopen: recursive dep: %s", i->filename.c_str()); + for (std::list<recursivelibdep>::iterator j = i->deps.begin(); j != i->deps.end(); j++) + { + CXBMCApp::android_printf("xb_dlopen: recursive dep: \\-- %s", j->filename.c_str()); + } + } +} diff --git a/xbmc/android/loader/AndroidDyload.h b/xbmc/android/loader/AndroidDyload.h new file mode 100644 index 0000000000..6dc2ef9f9f --- /dev/null +++ b/xbmc/android/loader/AndroidDyload.h @@ -0,0 +1,57 @@ +#pragma once +#include <stdlib.h> +#include <string> +#include <list> +#include <map> +#include "threads/SingleLock.h" + +struct recursivelibdep +{ + void* handle; + std::string filename; +}; + +struct recursivelib +{ + void* handle; + std::string filename; + std::list<recursivelibdep> deps; +}; + +struct libdata +{ + void *handle; + int refcount; + bool system; +}; + +typedef std::map<std::string, libdata> solib; +typedef std::map<std::string, libdata>::iterator solibit; + +typedef std::list<std::string> strings; +typedef std::list<void *> handles; + +class CAndroidDyload +{ +public: + void* Open(const char *path); + int Close(void* handle); + +private: + void *Open_Internal(std::string filename, bool checkSystem); + void* Find(const std::string &filename); + bool IsSystemLib(const std::string &filename); + std::string Find(void *handle); + std::string FindLib(const std::string &filename, bool checkSystem); + void* FindInDeps(const std::string &filename); + int AddRef(const std::string &filename); + int DecRef(const std::string &filename); + void GetDeps(std::string filename, strings *results); + void Dump(); + + recursivelib m_lib; + static std::list<recursivelib> m_recursivelibs; + static solib m_libs; + CCriticalSection m_libLock; + CCriticalSection m_depsLock; +};
\ No newline at end of file diff --git a/xbmc/android/loader/Makefile.in b/xbmc/android/loader/Makefile.in new file mode 100644 index 0000000000..d2cf65f08b --- /dev/null +++ b/xbmc/android/loader/Makefile.in @@ -0,0 +1,5 @@ +SRCS = AndroidDyload.cpp +LIB = AndroidDyload.a + +include @abs_top_srcdir@/Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS)))
\ No newline at end of file diff --git a/xbmc/cdrip/CDDARipper.cpp b/xbmc/cdrip/CDDARipper.cpp index 3b00144ee5..25a68420ef 100644 --- a/xbmc/cdrip/CDDARipper.cpp +++ b/xbmc/cdrip/CDDARipper.cpp @@ -34,8 +34,6 @@ #include "music/tags/MusicInfoTag.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogOK.h" -#include "dialogs/GUIDialogProgress.h" -#include "dialogs/GUIDialogKeyboard.h" #include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" #include "FileItem.h" diff --git a/xbmc/cores/AudioEngine/AESinkFactory.cpp b/xbmc/cores/AudioEngine/AESinkFactory.cpp index 810d4fe97b..797a63dd09 100644 --- a/xbmc/cores/AudioEngine/AESinkFactory.cpp +++ b/xbmc/cores/AudioEngine/AESinkFactory.cpp @@ -21,13 +21,11 @@ #include "AESinkFactory.h" #include "Interfaces/AESink.h" -#include "utils/SystemInfo.h" -#include "utils/log.h" -#include "settings/AdvancedSettings.h" - #if defined(TARGET_WINDOWS) #include "Sinks/AESinkWASAPI.h" #include "Sinks/AESinkDirectSound.h" +#elif defined(TARGET_ANDROID) + #include "Sinks/AESinkAUDIOTRACK.h" #elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD) #if defined(HAS_ALSA) #include "Sinks/AESinkALSA.h" @@ -39,6 +37,10 @@ #include "Sinks/AESinkProfiler.h" #include "Sinks/AESinkNULL.h" +#include "settings/AdvancedSettings.h" +#include "utils/SystemInfo.h" +#include "utils/log.h" + void CAESinkFactory::ParseDevice(std::string &device, std::string &driver) { int pos = device.find_first_of(':'); @@ -47,19 +49,20 @@ void CAESinkFactory::ParseDevice(std::string &device, std::string &driver) driver = device.substr(0, pos); std::transform(driver.begin(), driver.end(), driver.begin(), ::toupper); - /* check that it is a valid driver name */ + // check that it is a valid driver name if ( -#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) +#if defined(TARGET_WINDOWS) + driver == "WASAPI" || + driver == "DIRECTSOUND" || +#elif defined(TARGET_ANDROID) + driver == "AUDIOTRACK" || +#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD) #if defined(HAS_ALSA) driver == "ALSA" || #endif driver == "OSS" || -#elif defined(TARGET_WINDOWS) - driver == "WASAPI" || - driver == "DIRECTSOUND" || #endif - driver == "PROFILER" - ) + driver == "PROFILER") device = device.substr(pos + 1, device.length() - pos - 1); else driver.clear(); @@ -85,9 +88,7 @@ void CAESinkFactory::ParseDevice(std::string &device, std::string &driver) IAESink *CAESinkFactory::Create(std::string &device, AEAudioFormat &desiredFormat, bool rawPassthrough) { -#if !defined(TARGET_DARWIN) - - /* extract the driver from the device string if it exists */ + // extract the driver from the device string if it exists std::string driver; ParseDevice(device, driver); @@ -100,41 +101,30 @@ IAESink *CAESinkFactory::Create(std::string &device, AEAudioFormat &desiredForma #if defined(TARGET_WINDOWS) - - if ((driver.empty() && g_sysinfo.IsVistaOrHigher() || driver == "WASAPI") && !g_advancedSettings.m_audioForceDirectSound) + if ((driver.empty() && g_sysinfo.IsVistaOrHigher() || + driver == "WASAPI") && !g_advancedSettings.m_audioForceDirectSound) TRY_SINK(WASAPI) else - TRY_SINK(DirectSound) /* Always fall back to DirectSound */ + TRY_SINK(DirectSound) // always fall back to DirectSound -#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD) +#elif defined(TARGET_ANDROID) + if (driver.empty() || driver == "AUDIOTRACK") + TRY_SINK(AUDIOTRACK) +#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD) #if defined(HAS_ALSA) if (driver.empty() || driver == "ALSA") TRY_SINK(ALSA) #endif - if (driver.empty() || driver == "OSS") - TRY_SINK(OSS) - - /* no need to try others as both will have been attempted if driver is empty */ - if (driver.empty()) - TRY_SINK(NULL); - /* if we failed to get a sink, try to open one of the others */ - #if defined(HAS_ALSA) - if (driver != "ALSA") - TRY_SINK(ALSA) - #endif - if (driver != "OSS") + if (driver.empty() || driver == "OSS") TRY_SINK(OSS) +#endif -#endif /* defined TARGET_WINDOWS || defined TARGET_LINUX || defined TARGET_FREEBSD */ - - //Complete failure. + // complete failure. TRY_SINK(NULL); -#endif /* defined TARGET_DARWIN */ - - /* should never get here */ + // should never get here ASSERT(false); return NULL; } @@ -149,19 +139,18 @@ IAESink *CAESinkFactory::Create(std::string &device, AEAudioFormat &desiredForma void CAESinkFactory::EnumerateEx(AESinkInfoList &list) { - -#if defined(HAS_ALSA) - ENUMERATE_SINK(ALSA); -#endif - -#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) - ENUMERATE_SINK(OSS); -#endif - #if defined(TARGET_WINDOWS) if (g_sysinfo.IsVistaOrHigher() && !g_advancedSettings.m_audioForceDirectSound) ENUMERATE_SINK(WASAPI); - ENUMERATE_SINK(DirectSound); +#elif defined(TARGET_ANDROID) + ENUMERATE_SINK(AUDIOTRACK); +#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD) + #if defined(HAS_ALSA) + ENUMERATE_SINK(ALSA); + #endif + + ENUMERATE_SINK(OSS); #endif + } diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp index b5e121d7bc..cccd02617d 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp @@ -91,7 +91,7 @@ bool CCoreAudioAE::Initialize() Deinitialize(); - bool ret = OpenCoreAudio(); + bool ret = OpenCoreAudio(44100, false, AE_FMT_FLOAT); Start(); @@ -155,6 +155,9 @@ bool CCoreAudioAE::OpenCoreAudio(unsigned int sampleRate, bool forceRaw, case 10: m_stdChLayout = AE_CH_LAYOUT_7_1; break; } #endif + // force optical/coax to 2.0 output channels + if (!m_rawPassthrough && g_guiSettings.GetInt("audiooutput.mode") == AUDIO_IEC958) + m_stdChLayout = AE_CH_LAYOUT_2_0; // setup the desired format m_format.m_channelLayout = CAEChannelInfo(m_stdChLayout); @@ -211,7 +214,7 @@ bool CCoreAudioAE::OpenCoreAudio(unsigned int sampleRate, bool forceRaw, AEAudioFormat initformat = m_format; // initialize audio hardware - m_Initialized = HAL->Initialize(this, m_rawPassthrough, initformat, rawDataFormat, m_outputDevice); + m_Initialized = HAL->Initialize(this, m_rawPassthrough, initformat, rawDataFormat, m_outputDevice, m_volume); unsigned int bps = CAEUtil::DataFormatToBits(m_format.m_dataFormat); m_chLayoutCount = m_format.m_channelLayout.Count(); @@ -363,7 +366,7 @@ void CCoreAudioAE::SetVolume(float volume) // we need this because m_volume is init'ed via // SetVolume and need to also init m_volumeBeforeMute. if (!m_muted) - m_volumeBeforeMute = volume; + m_volumeBeforeMute = volume; HAL->SetVolume(m_volume); } @@ -373,7 +376,7 @@ void CCoreAudioAE::SetMute(const bool enabled) m_muted = enabled; if(m_muted) { - m_volumeBeforeMute = m_volume; + m_volumeBeforeMute = m_volume; SetVolume(VOLUME_MINIMUM); } else @@ -390,10 +393,10 @@ bool CCoreAudioAE::IsMuted() void CCoreAudioAE::SetSoundMode(const int mode) { m_soundMode = mode; - + /* stop all currently playing sounds if they are being turned off */ if (mode == AE_SOUND_OFF || (mode == AE_SOUND_IDLE && m_streamsPlaying)) - StopAllSounds(); + StopAllSounds(); } bool CCoreAudioAE::SupportsRaw() @@ -421,15 +424,10 @@ IAEStream* CCoreAudioAE::MakeStream(enum AEDataFormat dataFormat, Stop(); - if (COREAUDIO_IS_RAW(dataFormat)) + if (m_Initialized) { Deinitialize(); - m_Initialized = OpenCoreAudio(sampleRate, true, dataFormat); - } - else if (/* wasEmpty || */ m_rawPassthrough) - { - Deinitialize(); - m_Initialized = OpenCoreAudio(sampleRate); + m_Initialized = OpenCoreAudio(sampleRate, COREAUDIO_IS_RAW(dataFormat), dataFormat); } /* if the stream was not initialized, do it now */ @@ -438,7 +436,7 @@ IAEStream* CCoreAudioAE::MakeStream(enum AEDataFormat dataFormat, Start(); - m_streamsPlaying = true; + m_streamsPlaying = true; return stream; } @@ -469,7 +467,7 @@ IAEStream* CCoreAudioAE::FreeStream(IAEStream *stream) m_streamsPlaying = !m_streams.empty(); streamLock.Leave(); - + // When we have been in passthrough mode, reinit the hardware to come back to anlog out if (/*m_streams.empty() || */ m_rawPassthrough) { @@ -635,7 +633,7 @@ OSStatus CCoreAudioAE::OnRender(AudioUnitRenderActionFlags *actionFlags, //int size = frames * HAL->m_BytesPerFrame; for (UInt32 i = 0; i < ioData->mNumberBuffers; i++) - bzero(ioData->mBuffers[i].mData, ioData->mBuffers[i].mDataByteSize); + bzero(ioData->mBuffers[i].mData, ioData->mBuffers[i].mDataByteSize); if (!m_Initialized) { diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.h index 887f335338..027f987258 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.h +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.h @@ -68,7 +68,7 @@ protected: // Give the HAL access to the engine friend class CCoreAudioAEHAL; CCoreAudioAEHAL *HAL; - + public: virtual void Shutdown(); @@ -88,19 +88,19 @@ public: virtual void SetMute(const bool enabled); virtual bool IsMuted(); virtual void SetSoundMode(const int mode); - + virtual bool SupportsRaw(); - + CCoreAudioAEHAL* GetHAL(); - + // returns a new stream for data in the specified format - virtual IAEStream* MakeStream(enum AEDataFormat dataFormat, + virtual IAEStream* MakeStream(enum AEDataFormat dataFormat, unsigned int sampleRate,unsigned int encodedSamplerate, CAEChannelInfo channelLayout, unsigned int options = 0); - + virtual IAEStream* FreeStream(IAEStream *stream); - + // returns a new sound object virtual IAESound* MakeSound(const std::string& file); void StopAllSounds(); @@ -114,17 +114,17 @@ public: virtual void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough); - virtual OSStatus Render(AudioUnitRenderActionFlags* actionFlags, - const AudioTimeStamp* pTimeStamp, UInt32 busNumber, + virtual OSStatus Render(AudioUnitRenderActionFlags* actionFlags, + const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pBufList); - + private: CCriticalSection m_callbackLock; CCriticalSection m_streamLock; CCriticalSection m_soundLock; CCriticalSection m_soundSampleLock; - + // currently playing sounds typedef struct { CCoreAudioAESound *owner; @@ -139,30 +139,29 @@ private: StreamList m_streams; SoundList m_sounds; SoundStateList m_playing_sounds; - + // Prevent multiple init/deinit bool m_Initialized; bool m_callbackRunning; - + AEAudioFormat m_format; unsigned int m_chLayoutCount; bool m_rawPassthrough; enum AEStdChLayout m_stdChLayout; - - bool OpenCoreAudio(unsigned int sampleRate = 44100, bool forceRaw = false, - enum AEDataFormat rawDataFormat = AE_FMT_AC3); + + bool OpenCoreAudio(unsigned int sampleRate, bool forceRaw, enum AEDataFormat rawDataFormat); void Deinitialize(); void Start(); void Stop(); - OSStatus OnRender(AudioUnitRenderActionFlags *actionFlags, - const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, + OSStatus OnRender(AudioUnitRenderActionFlags *actionFlags, + const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); float m_volume; - float m_volumeBeforeMute; + float m_volumeBeforeMute; bool m_muted; int m_soundMode; - bool m_streamsPlaying; + bool m_streamsPlaying; }; diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.cpp index 94050a3655..4505a30089 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.cpp +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.cpp @@ -575,7 +575,7 @@ bool CAUMultiChannelMixer::SetCurrentVolume(Float32 vol) if (!m_audioUnit) return false; - OSStatus ret = AudioUnitSetParameter(m_audioUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, kInputBus, vol, 0); + OSStatus ret = AudioUnitSetParameter(m_audioUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, kOutputBus, vol, 0); if (ret) { CLog::Log(LOGERROR, "CAUMultiChannelMixer::SetCurrentVolume: Unable to set Mixer volume. Error = %s", GetError(ret).c_str()); @@ -607,7 +607,7 @@ CCoreAudioGraph::~CCoreAudioGraph() Close(); } -bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing) +bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing, float initVolume) { OSStatus ret; @@ -777,6 +777,8 @@ bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format, boo return false; } + SetCurrentVolume(initVolume); + UInt32 bufferFrames = m_audioUnit->GetBufferFrameSize(); m_audioUnit->SetMaxFramesPerSlice(bufferFrames); @@ -1100,6 +1102,7 @@ m_Initialized (false ), m_Passthrough (false ), m_allowMixing (false ), m_encoded (false ), +m_initVolume (1.0f ), m_NumLatencyFrames (0 ), m_OutputBufferIndex (0 ) { @@ -1125,7 +1128,7 @@ bool CCoreAudioAEHALIOS::InitializePCM(ICoreAudioSource *pSource, AEAudioFormat if (!m_audioGraph) return false; - if (!m_audioGraph->Open(pSource, format, allowMixing)) + if (!m_audioGraph->Open(pSource, format, allowMixing, m_initVolume)) { CLog::Log(LOGDEBUG, "CCoreAudioAEHALIOS::Initialize: Unable to initialize audio due a missconfiguration. Try 2.0 speaker configuration."); return false; @@ -1146,7 +1149,7 @@ bool CCoreAudioAEHALIOS::InitializePCMEncoded(ICoreAudioSource *pSource, AEAudio return true; } -bool CCoreAudioAEHALIOS::Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device) +bool CCoreAudioAEHALIOS::Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device, float initVolume) { m_ae = (CCoreAudioAE *)ae; @@ -1158,6 +1161,7 @@ bool CCoreAudioAEHALIOS::Initialize(ICoreAudioSource *ae, bool passThrough, AEAu m_encoded = false; m_OutputBufferIndex = 0; m_rawDataFormat = rawDataFormat; + m_initVolume = initVolume; if (format.m_channelLayout.Count() == 0) { diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.h index 5123158cba..9cf3559799 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.h +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.h @@ -61,13 +61,13 @@ class CCoreAudioUnit public: CCoreAudioUnit(); virtual ~CCoreAudioUnit(); - + virtual bool Open(AUGraph audioGraph, AudioComponentDescription desc); virtual bool Open(AUGraph audioGraph, OSType type, OSType subType, OSType manufacturer); virtual void Close(); virtual bool SetInputSource(ICoreAudioSource* pSource); virtual bool IsInitialized() {return m_Initialized;} - virtual bool GetFormat(AudioStreamBasicDescription* pDesc, AudioUnitScope scope, AudioUnitElement bus); + virtual bool GetFormat(AudioStreamBasicDescription* pDesc, AudioUnitScope scope, AudioUnitElement bus); virtual bool SetFormat(AudioStreamBasicDescription* pDesc, AudioUnitScope scope, AudioUnitElement bus); virtual bool SetMaxFramesPerSlice(UInt32 maxFrames); virtual void GetFormatDesc(AEAudioFormat format, AudioStreamBasicDescription *streamDesc); @@ -83,11 +83,11 @@ public: protected: bool SetRenderProc(); bool RemoveRenderProc(); - static OSStatus RenderCallback(void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, + static OSStatus RenderCallback(void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, AudioBufferList *ioData); ICoreAudioSource* m_pSource; AudioUnit m_audioUnit; @@ -104,7 +104,7 @@ public: CAUOutputDevice(); virtual ~CAUOutputDevice(); UInt32 GetBufferFrameSize(); - + /* Float32 GetCurrentVolume(); bool SetCurrentVolume(Float32 vol); @@ -117,13 +117,13 @@ class CAUMultiChannelMixer : public CAUOutputDevice public: CAUMultiChannelMixer(); virtual ~CAUMultiChannelMixer(); - + UInt32 GetInputBusCount(); bool SetInputBusFormat(UInt32 busCount, AudioStreamBasicDescription *pFormat); bool SetInputBusCount(UInt32 busCount); UInt32 GetOutputBusCount(); bool SetOutputBusCount(UInt32 busCount); - + Float32 GetCurrentVolume(); bool SetCurrentVolume(Float32 vol); }; @@ -132,23 +132,23 @@ class CCoreAudioGraph { private: AUGraph m_audioGraph; - + CAUOutputDevice *m_audioUnit; CAUMultiChannelMixer *m_mixerUnit; CAUOutputDevice *m_inputUnit; - + int m_reservedBusNumber[MAX_CONNECTION_LIMIT]; bool m_initialized; bool m_allowMixing; - + typedef std::list<CAUOutputDevice*> AUUnitList; AUUnitList m_auUnitList; - + public: CCoreAudioGraph(); ~CCoreAudioGraph(); - - bool Open(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing); + + bool Open(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing, float initVolume); bool Close(); bool Start(); bool Stop(); @@ -174,17 +174,18 @@ protected: bool m_allowMixing; bool m_encoded; AEDataFormat m_rawDataFormat; + float m_initVolume; public: unsigned int m_NumLatencyFrames; unsigned int m_OutputBufferIndex; CCoreAudioAE *m_ae; - + CCoreAudioAEHALIOS(); virtual ~CCoreAudioAEHALIOS(); - + virtual bool InitializePCM(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing); virtual bool InitializePCMEncoded(ICoreAudioSource *pSource, AEAudioFormat &format); - virtual bool Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device); + virtual bool Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device, float initVolume); virtual void Deinitialize(); virtual void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough); virtual void SetDirectInput(ICoreAudioSource *pSource, AEAudioFormat &format); diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.cpp index 43d292d503..258b27c33b 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.cpp +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.cpp @@ -44,6 +44,7 @@ CCoreAudioAEHALOSX::CCoreAudioAEHALOSX() : m_Passthrough (false ), m_allowMixing (false ), m_encoded (false ), + m_initVolume (1.0f ), m_NumLatencyFrames (0 ), m_OutputBufferIndex (0 ) { @@ -92,7 +93,12 @@ bool CCoreAudioAEHALOSX::InitializePCM(ICoreAudioSource *pSource, AEAudioFormat if (!m_audioGraph) return false; - if (!m_audioGraph->Open(pSource, format, outputDevice, allowMixing, g_LayoutMap[ g_guiSettings.GetInt("audiooutput.channellayout") ] )) + AudioChannelLayoutTag layout = g_LayoutMap[ g_guiSettings.GetInt("audiooutput.channellayout") ]; + // force optical/coax to 2.0 output channels + if (!m_Passthrough && g_guiSettings.GetInt("audiooutput.mode") == AUDIO_IEC958) + layout = g_LayoutMap[1]; + + if (!m_audioGraph->Open(pSource, format, outputDevice, allowMixing, layout, m_initVolume )) { CLog::Log(LOGDEBUG, "CCoreAudioAEHALOSX::Initialize: " "Unable to initialize audio due a missconfiguration. Try 2.0 speaker configuration."); @@ -159,7 +165,7 @@ bool CCoreAudioAEHALOSX::InitializeEncoded(AudioDeviceID outputDevice, AEAudioFo { // check pcm output formats unsigned int bps = CAEUtil::DataFormatToBits(AE_FMT_S16NE); - if (desc.mFormat.mChannelsPerFrame == m_initformat.m_channelLayout.Count() && + if (desc.mFormat.mChannelsPerFrame == m_initformat.m_channelLayout.Count() && desc.mFormat.mBitsPerChannel == bps && desc.mFormat.mSampleRate == m_initformat.m_sampleRate ) { @@ -174,7 +180,7 @@ bool CCoreAudioAEHALOSX::InitializeEncoded(AudioDeviceID outputDevice, AEAudioFo // check encoded formats if (desc.mFormat.mFormatID == kAudioFormat60958AC3 || desc.mFormat.mFormatID == 'IAC3') { - if (desc.mFormat.mChannelsPerFrame == m_initformat.m_channelLayout.Count() && + if (desc.mFormat.mChannelsPerFrame == m_initformat.m_channelLayout.Count() && desc.mFormat.mSampleRate == m_initformat.m_sampleRate ) { outputFormat = desc.mFormat; // Select this format @@ -201,7 +207,7 @@ bool CCoreAudioAEHALOSX::InitializeEncoded(AudioDeviceID outputDevice, AEAudioFo } CLog::Log(LOGDEBUG, "CCoreAudioAEHALOSX::InitializeEncoded: " - "Selected stream[%u] - id: 0x%04X, Physical Format: %s", + "Selected stream[%u] - id: 0x%04X, Physical Format: %s", m_OutputBufferIndex, (uint)outputStream, StreamDescriptionToString(outputFormat, formatString)); // TODO: Auto hogging sets this for us. Figure out how/when to turn it off or use it @@ -257,7 +263,7 @@ bool CCoreAudioAEHALOSX::InitializeEncoded(AudioDeviceID outputDevice, AEAudioFo return true; } -bool CCoreAudioAEHALOSX::Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device) +bool CCoreAudioAEHALOSX::Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device, float initVolume) { // Reset all the devices to a default 'non-hog' and mixable format. // If we don't do this we may be unable to find the Default Output device. @@ -274,6 +280,7 @@ bool CCoreAudioAEHALOSX::Initialize(ICoreAudioSource *ae, bool passThrough, AEAu m_Passthrough = passThrough; m_encoded = false; m_OutputBufferIndex = 0; + m_initVolume = initVolume; if (format.m_channelLayout.Count() == 0) { @@ -298,6 +305,8 @@ bool CCoreAudioAEHALOSX::Initialize(ICoreAudioSource *ae, bool passThrough, AEAu // Attach our output object to the device m_AudioDevice->Open(outputDevice); + m_AudioDevice->SetHogStatus(false); + m_AudioDevice->SetMixingSupport(true); // If this is a passthrough (AC3/DTS) stream, attempt to handle it natively if (m_Passthrough) diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.h index 01ba02e4d9..f26069192a 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.h +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.h @@ -47,6 +47,7 @@ protected: bool m_allowMixing; bool m_encoded; AEDataFormat m_rawDataFormat; + float m_initVolume; public: unsigned int m_NumLatencyFrames; unsigned int m_OutputBufferIndex; @@ -58,7 +59,7 @@ public: virtual bool InitializePCM(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing, AudioDeviceID outputDevice); virtual bool InitializePCMEncoded(ICoreAudioSource *pSource, AEAudioFormat &format, AudioDeviceID outputDevice); virtual bool InitializeEncoded(AudioDeviceID outputDevice, AEAudioFormat &format); - virtual bool Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device); + virtual bool Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device, float initVolume); virtual void Deinitialize(); virtual void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough); virtual void SetDirectInput(ICoreAudioSource *pSource, AEAudioFormat &format); diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAESound.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAESound.h index 26b52a961a..54175e1a11 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAESound.h +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAESound.h @@ -22,7 +22,7 @@ #include "Interfaces/AESound.h" #include "threads/CriticalSection.h" -#include "utils/AEWAVLoader.h" +#include "Utils/AEWAVLoader.h" class CCoreAudioAESound : public IAESound { diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.cpp index 3b9f0b75c8..e88ee78a7e 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.cpp +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.cpp @@ -144,12 +144,12 @@ CCoreAudioAEStream::~CCoreAudioAEStream() InternalFlush(); - _aligned_free(m_convertBuffer); - //_aligned_free(m_resampleBuffer); - _aligned_free(m_remapBuffer); - _aligned_free(m_vizRemapBuffer); + _aligned_free(m_convertBuffer); m_convertBuffer = NULL; + //_aligned_free(m_resampleBuffer); m_resampleBuffer = NULL; + _aligned_free(m_remapBuffer); m_remapBuffer = NULL; + _aligned_free(m_vizRemapBuffer); m_vizRemapBuffer = NULL; - delete m_Buffer; + delete m_Buffer; m_Buffer = NULL; /* if (m_resample) @@ -402,7 +402,7 @@ unsigned int CCoreAudioAEStream::AddData(void *data, unsigned int size) adddata = (uint8_t *)m_remapBuffer; channelsInBuffer = m_OutputFormat.m_channelLayout.Count(); } - + // upmix the ouput to output channels if ( (!m_isRaw || m_rawDataFormat == AE_FMT_LPCM) && (m_chLayoutCountOutput > channelsInBuffer) ) { @@ -416,7 +416,7 @@ unsigned int CCoreAudioAEStream::AddData(void *data, unsigned int size) unsigned int total_ms_sleep = 0; unsigned int room = m_Buffer->GetWriteSize(); - while (addsize > room && !m_paused && total_ms_sleep < 200) + while (addsize > room && !m_paused && total_ms_sleep < 100) { // we got deleted if (!m_valid || !m_Buffer || m_draining ) @@ -453,11 +453,11 @@ unsigned int CCoreAudioAEStream::GetFrames(uint8_t *buffer, unsigned int size) if (!m_isRaw) { float *floatBuffer = (float *)buffer; - unsigned int samples = readsize / m_OutputBytesPerSample; + unsigned int samples = readsize / m_OutputBytesPerSample; // we have a frame, if we have a viz we need to hand the data to it. - // Keep in mind that our buffer is already in output format. - // So we remap output format to viz format !!! + // Keep in mind that our buffer is already in output format. + // So we remap output format to viz format !!! if (m_OutputFormat.m_dataFormat == AE_FMT_FLOAT) { // TODO : Why the hell is vizdata limited ? @@ -751,7 +751,7 @@ OSStatus CCoreAudioAEStream::OnRender(AudioUnitRenderActionFlags *ioActionFlags, if (!m_valid || m_delete || !m_Buffer || m_firstInput || m_paused) { for (UInt32 i = 0; i < ioData->mNumberBuffers; i++) - bzero(ioData->mBuffers[i].mData, ioData->mBuffers[i].mDataByteSize); + bzero(ioData->mBuffers[i].mData, ioData->mBuffers[i].mDataByteSize); if (ioActionFlags) *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence; m_firstInput = false; diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.cpp index 9b3b07c628..6725db5db9 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.cpp +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.cpp @@ -22,12 +22,9 @@ #include "CoreAudioDevice.h" #include "CoreAudioAEHAL.h" #include "CoreAudioChannelLayout.h" +#include "CoreAudioHardware.h" #include "utils/log.h" -// AudioHardwareGetProperty and friends are deprecated, -// turn off the warning spew. -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // CCoreAudioDevice ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -41,7 +38,8 @@ CCoreAudioDevice::CCoreAudioDevice() : m_SampleRateRestore (0.0f ), m_HogPid (-1 ), m_frameSize (0 ), - m_OutputBufferIndex (0 ) + m_OutputBufferIndex (0 ), + m_BufferSizeRestore (0 ) { } @@ -55,7 +53,8 @@ CCoreAudioDevice::CCoreAudioDevice(AudioDeviceID deviceId) : m_SampleRateRestore (0.0f ), m_HogPid (-1 ), m_frameSize (0 ), - m_OutputBufferIndex (0 ) + m_OutputBufferIndex (0 ), + m_BufferSizeRestore (0 ) { } @@ -67,8 +66,9 @@ CCoreAudioDevice::~CCoreAudioDevice() bool CCoreAudioDevice::Open(AudioDeviceID deviceId) { m_DeviceId = deviceId; - return true; + m_BufferSizeRestore = GetBufferSize(); CLog::Log(LOGDEBUG, "CCoreAudioDevice::Open: Opened device 0x%04x", (uint)m_DeviceId); + return true; } void CCoreAudioDevice::Close() @@ -84,6 +84,8 @@ void CCoreAudioDevice::Close() SetInputSource(NULL, 0, 0); SetHogStatus(false); + CCoreAudioHardware::SetAutoHogMode(false); + if (m_MixerRestore > -1) // We changed the mixer status SetMixingSupport((m_MixerRestore ? true : false)); m_MixerRestore = -1; @@ -94,6 +96,12 @@ void CCoreAudioDevice::Close() SetNominalSampleRate(m_SampleRateRestore); } + if (m_BufferSizeRestore && m_BufferSizeRestore != GetBufferSize()) + { + SetBufferSize(m_BufferSizeRestore); + m_BufferSizeRestore = 0; + } + CLog::Log(LOGDEBUG, "CCoreAudioDevice::Close: Closed device 0x%04x", (uint)m_DeviceId); m_IoProc = NULL; m_pSource = NULL; @@ -231,48 +239,70 @@ std::string CCoreAudioDevice::GetName() if (!m_DeviceId) return NULL; - UInt32 size = 0; - // TODO: Change to kAudioObjectPropertyObjectName - AudioDeviceGetPropertyInfo(m_DeviceId,0, false, - kAudioDevicePropertyDeviceName, &size, NULL); - char *buff = new char[size]; - OSStatus ret = AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertyDeviceName, &size, buff); - - std::string name; - name.assign(buff, size-1); - delete [] buff; - if (ret) + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyDeviceName; + + UInt32 propertySize; + OSStatus ret = AudioObjectGetPropertyDataSize(m_DeviceId, &propertyAddress, 0, NULL, &propertySize); + if (ret != noErr) + return NULL; + + std::string name = ""; + char *buff = new char[propertySize + 1]; + buff[propertySize] = 0x00; + ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, buff); + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioDevice::GetName: " "Unable to get device name - id: 0x%04x. Error = %s", (uint)m_DeviceId, GetError(ret).c_str()); - return NULL; } + else + { + name = buff; + } + delete buff; + + return name; } UInt32 CCoreAudioDevice::GetTotalOutputChannels() { + UInt32 channels = 0; + if (!m_DeviceId) - return 0; + return channels; + + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyStreamConfiguration; UInt32 size = 0; - UInt32 channels = 0; - AudioDeviceGetPropertyInfo(m_DeviceId, 0, false, - kAudioDevicePropertyStreamConfiguration, &size, NULL); + OSStatus ret = AudioObjectGetPropertyDataSize(m_DeviceId, &propertyAddress, 0, NULL, &size); + if (ret != noErr) + return channels; + AudioBufferList* pList = (AudioBufferList*)malloc(size); - OSStatus ret = AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertyStreamConfiguration, &size, pList); - if (!ret) + ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &size, pList); + if (ret == noErr) + { for(UInt32 buffer = 0; buffer < pList->mNumberBuffers; ++buffer) channels += pList->mBuffers[buffer].mNumberChannels; + } else + { CLog::Log(LOGERROR, "CCoreAudioDevice::GetTotalOutputChannels: " "Unable to get total device output channels - id: 0x%04x. Error = %s", (uint)m_DeviceId, GetError(ret).c_str()); + } + CLog::Log(LOGDEBUG, "CCoreAudioDevice::GetTotalOutputChannels: " "Found %u channels in %u buffers", (uint)channels, (uint)pList->mNumberBuffers); free(pList); + return channels; } @@ -281,35 +311,44 @@ bool CCoreAudioDevice::GetStreams(AudioStreamIdList* pList) if (!pList || !m_DeviceId) return false; - Boolean writable = false; + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyStreams; + UInt32 propertySize = 0; - OSStatus ret = AudioDeviceGetPropertyInfo(m_DeviceId, 0, false, - kAudioDevicePropertyStreams, &propertySize, &writable); - if (ret) + OSStatus ret = AudioObjectGetPropertyDataSize(m_DeviceId, &propertyAddress, 0, NULL, &propertySize); + if (ret != noErr) return false; + UInt32 streamCount = propertySize / sizeof(AudioStreamID); AudioStreamID* pStreamList = new AudioStreamID[streamCount]; - ret = AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertyStreams, &propertySize, pStreamList); - if (!ret) + ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, pStreamList); + if (ret == noErr) { for (UInt32 stream = 0; stream < streamCount; stream++) pList->push_back(pStreamList[stream]); } delete[] pStreamList; - return (ret == noErr); + + return ret == noErr; } bool CCoreAudioDevice::IsRunning() { - UInt32 isRunning = false; - UInt32 size = sizeof(isRunning); - OSStatus ret = AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertyDeviceIsRunning, &size, &isRunning); - if (ret) + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyDeviceIsRunning; + + UInt32 isRunning = 0; + UInt32 propertySize = sizeof(isRunning); + OSStatus ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, &isRunning); + if (ret != noErr) return false; - return (isRunning != 0); + + return isRunning != 0; } bool CCoreAudioDevice::SetHogStatus(bool hog) @@ -320,6 +359,11 @@ bool CCoreAudioDevice::SetHogStatus(bool hog) if (!m_DeviceId) return false; + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyHogMode; + if (hog) { // Not already set @@ -327,8 +371,7 @@ bool CCoreAudioDevice::SetHogStatus(bool hog) { CLog::Log(LOGDEBUG, "CCoreAudioDevice::SetHogStatus: " "Setting 'hog' status on device 0x%04x", (unsigned int)m_DeviceId); - OSStatus ret = AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, - kAudioDevicePropertyHogMode, sizeof(m_HogPid), &m_HogPid); + OSStatus ret = AudioObjectSetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, sizeof(m_HogPid), &m_HogPid); if (ret || m_HogPid != getpid()) { CLog::Log(LOGERROR, "CCoreAudioDevice::SetHogStatus: " @@ -347,8 +390,7 @@ bool CCoreAudioDevice::SetHogStatus(bool hog) CLog::Log(LOGDEBUG, "CCoreAudioDevice::SetHogStatus: " "Releasing 'hog' status on device 0x%04x", (unsigned int)m_DeviceId); pid_t hogPid = -1; - OSStatus ret = AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, - kAudioDevicePropertyHogMode, sizeof(hogPid), &hogPid); + OSStatus ret = AudioObjectSetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, sizeof(hogPid), &hogPid); if (ret || hogPid == getpid()) { CLog::Log(LOGERROR, "CCoreAudioDevice::SetHogStatus: " @@ -367,9 +409,14 @@ pid_t CCoreAudioDevice::GetHogStatus() if (!m_DeviceId) return false; + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyHogMode; + pid_t hogPid = -1; UInt32 size = sizeof(hogPid); - AudioDeviceGetProperty(m_DeviceId, 0, false, kAudioDevicePropertyHogMode, &size, &hogPid); + AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &size, &hogPid); return hogPid; } @@ -388,12 +435,17 @@ bool CCoreAudioDevice::SetMixingSupport(UInt32 mix) // This is our first change to this setting. Store the original setting for restore restore = (GetMixingSupport() ? 1 : 0); } + + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertySupportsMixing; + UInt32 mixEnable = mix ? 1 : 0; CLog::Log(LOGDEBUG, "CCoreAudioDevice::SetMixingSupport: " "%sabling mixing for device 0x%04x", mix ? "En" : "Dis", (unsigned int)m_DeviceId); - OSStatus ret = AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, - kAudioDevicePropertySupportsMixing, sizeof(mixEnable), &mixEnable); - if (ret) + OSStatus ret = AudioObjectSetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, sizeof(mixEnable), &mixEnable); + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioDevice::SetMixingSupport: " "Unable to set MixingSupport to %s. Error = %s", mix ? "'On'" : "'Off'", GetError(ret).c_str()); @@ -409,14 +461,16 @@ bool CCoreAudioDevice::GetMixingSupport() if (!m_DeviceId) return false; - OSStatus ret; UInt32 size; UInt32 mix = 0; Boolean writable = false; - size = sizeof(writable); - ret = AudioDeviceGetPropertyInfo(m_DeviceId, 0, FALSE, - kAudioDevicePropertySupportsMixing, &size, &writable); + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertySupportsMixing; + + OSStatus ret = AudioObjectIsPropertySettable(m_DeviceId, &propertyAddress, &writable); if (ret) { CLog::Log(LOGERROR, "CCoreAudioDevice::SupportsMixing: " @@ -427,9 +481,8 @@ bool CCoreAudioDevice::GetMixingSupport() if (writable) { size = sizeof(mix); - ret = AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertySupportsMixing, &size, &mix); - if (ret) + ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &size, &mix); + if (ret != noErr) mix = 0; } @@ -444,9 +497,13 @@ bool CCoreAudioDevice::SetCurrentVolume(Float32 vol) if (!m_DeviceId) return false; - OSStatus ret = AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, - kHALOutputParam_Volume, sizeof(Float32), &vol); - if (ret) + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kHALOutputParam_Volume; + + OSStatus ret = AudioObjectSetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, sizeof(Float32), &vol); + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioDevice::SetCurrentVolume: " "Unable to set AudioUnit volume. Error = %s", GetError(ret).c_str()); @@ -460,17 +517,19 @@ bool CCoreAudioDevice::GetPreferredChannelLayout(CCoreAudioChannelLayout& layout if (!m_DeviceId) return false; + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyPreferredChannelLayout; + UInt32 propertySize = 0; - Boolean writable = false; - OSStatus ret = AudioDeviceGetPropertyInfo(m_DeviceId, 0, false, - kAudioDevicePropertyPreferredChannelLayout, &propertySize, &writable); + OSStatus ret = AudioObjectGetPropertyDataSize(m_DeviceId, &propertyAddress, 0, NULL, &propertySize); if (ret) return false; void* pBuf = malloc(propertySize); - ret = AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertyPreferredChannelLayout, &propertySize, pBuf); - if (ret) + ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, pBuf); + if (ret != noErr) CLog::Log(LOGERROR, "CCoreAudioDevice::GetPreferredChannelLayout: " "Unable to retrieve preferred channel layout. Error = %s", GetError(ret).c_str()); else @@ -487,19 +546,24 @@ bool CCoreAudioDevice::GetDataSources(CoreAudioDataSourceList* pList) if (!pList || !m_DeviceId) return false; + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyDataSources; + UInt32 propertySize = 0; - Boolean writable = false; - OSStatus ret = AudioDeviceGetPropertyInfo(m_DeviceId, 0, false, - kAudioDevicePropertyDataSources, &propertySize, &writable); - if (ret) + OSStatus ret = AudioObjectGetPropertyDataSize(m_DeviceId, &propertyAddress, 0, NULL, &propertySize); + if (ret != noErr) return false; - UInt32 sources = propertySize / sizeof(UInt32); + + UInt32 sources = propertySize / sizeof(UInt32); UInt32* pSources = new UInt32[sources]; - ret = AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertyDataSources, &propertySize, pSources); - if (!ret) + ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, pSources); + if (ret == noErr) + { for (UInt32 i = 0; i < sources; i++) - pList->push_back(pSources[i]);; + pList->push_back(pSources[i]); + } delete[] pSources; return (!ret); } @@ -509,11 +573,15 @@ Float64 CCoreAudioDevice::GetNominalSampleRate() if (!m_DeviceId) return 0.0f; + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyNominalSampleRate; + Float64 sampleRate = 0.0f; - UInt32 size = sizeof(Float64); - OSStatus ret = AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertyNominalSampleRate, &size, &sampleRate); - if (ret) + UInt32 propertySize = sizeof(Float64); + OSStatus ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, &sampleRate); + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioDevice::GetNominalSampleRate: " "Unable to retrieve current device sample rate. Error = %s", GetError(ret).c_str()); @@ -531,10 +599,13 @@ bool CCoreAudioDevice::SetNominalSampleRate(Float64 sampleRate) if (currentRate == sampleRate) return true; //No need to change - UInt32 size = sizeof(Float64); - OSStatus ret = AudioDeviceSetProperty(m_DeviceId, - NULL, 0, false, kAudioDevicePropertyNominalSampleRate, size, &sampleRate); - if (ret) + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyNominalSampleRate; + + OSStatus ret = AudioObjectSetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, sizeof(Float64), &sampleRate); + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioDevice::SetNominalSampleRate: " "Unable to set current device sample rate to %0.0f. Error = %s", @@ -552,32 +623,33 @@ bool CCoreAudioDevice::SetNominalSampleRate(Float64 sampleRate) UInt32 CCoreAudioDevice::GetNumLatencyFrames() { - UInt32 i_param, i_param_size, num_latency_frames = 0; + UInt32 num_latency_frames = 0; if (!m_DeviceId) return 0; - i_param_size = sizeof(uint32_t); - // number of frames of latency in the AudioDevice - if (noErr == AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertyLatency, &i_param_size, &i_param)) - { + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyLatency; + + UInt32 i_param = 0; + UInt32 i_param_size = sizeof(uint32_t); + OSStatus ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &i_param_size, &i_param); + if (ret == noErr) num_latency_frames += i_param; - } // number of frames in the IO buffers - if (noErr == AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertyBufferFrameSize, &i_param_size, &i_param)) - { + propertyAddress.mSelector = kAudioDevicePropertyBufferFrameSize; + ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &i_param_size, &i_param); + if (ret == noErr) num_latency_frames += i_param; - } // number for frames in ahead the current hardware position that is safe to do IO - if (noErr == AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertySafetyOffset, &i_param_size, &i_param)) - { + propertyAddress.mSelector = kAudioDevicePropertySafetyOffset; + ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &i_param_size, &i_param); + if (ret == noErr) num_latency_frames += i_param; - } return (num_latency_frames); } @@ -587,11 +659,15 @@ UInt32 CCoreAudioDevice::GetBufferSize() if (!m_DeviceId) return false; + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyBufferFrameSize; + UInt32 size = 0; UInt32 propertySize = sizeof(size); - OSStatus ret = AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertyBufferFrameSize, &propertySize, &size); - if (ret) + OSStatus ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, &size); + if (ret != noErr) CLog::Log(LOGERROR, "CCoreAudioDevice::GetBufferSize: " "Unable to retrieve buffer size. Error = %s", GetError(ret).c_str()); return size; @@ -602,12 +678,18 @@ bool CCoreAudioDevice::SetBufferSize(UInt32 size) if (!m_DeviceId) return false; + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyBufferFrameSize; + UInt32 propertySize = sizeof(size); - OSStatus ret = AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, - kAudioDevicePropertyBufferFrameSize, propertySize, &size); - if (ret) + OSStatus ret = AudioObjectSetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, propertySize, &size); + if (ret != noErr) + { CLog::Log(LOGERROR, "CCoreAudioDevice::SetBufferSize: " "Unable to set buffer size. Error = %s", GetError(ret).c_str()); + } if (GetBufferSize() != size) CLog::Log(LOGERROR, "CCoreAudioDevice::SetBufferSize: Buffer size change not applied."); diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.h index 131b2ee0b4..7bac2ef33f 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.h +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.h @@ -89,6 +89,7 @@ protected: pid_t m_HogPid; unsigned int m_frameSize; unsigned int m_OutputBufferIndex; + unsigned int m_BufferSizeRestore; }; -#endif
\ No newline at end of file +#endif diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.cpp index b2c011efc5..d02d3c4f76 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.cpp +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.cpp @@ -52,11 +52,11 @@ CCoreAudioGraph::~CCoreAudioGraph() } bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format, - AudioDeviceID deviceId, bool allowMixing, AudioChannelLayoutTag layoutTag) + AudioDeviceID deviceId, bool allowMixing, AudioChannelLayoutTag layoutTag, float initVolume) { - AudioStreamBasicDescription fmt; - AudioStreamBasicDescription inputFormat; - AudioStreamBasicDescription outputFormat; + AudioStreamBasicDescription fmt = {0}; + AudioStreamBasicDescription inputFormat = {0}; + AudioStreamBasicDescription outputFormat = {0}; m_deviceId = deviceId; m_allowMixing = allowMixing; @@ -88,6 +88,7 @@ bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format, if (!m_audioUnit->Open(m_audioGraph, kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple)) return false; + m_audioUnit->SetBus(GetFreeBus()); m_audioUnit->GetFormatDesc(format, &inputFormat, &fmt); @@ -97,6 +98,8 @@ bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format, if (!m_audioUnit->SetCurrentDevice(deviceId)) return false; + SetCurrentVolume(initVolume); + if (allowMixing) { delete m_mixMap; @@ -236,18 +239,6 @@ bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format, } } -/* -// WTF is this an why is it in CoreAudioAEHALOSX ? -#ifdef TAGRGET_IOS - if (!m_audioUnit->SetFormat(&inputFormat, kAudioUnitScope_Output, kInputBus)) - { - CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " - "Error setting Device Output Stream Format %s", - StreamDescriptionToString(inputFormat, formatString)); - } -#endif -*/ - ret = AUGraphUpdate(m_audioGraph, NULL); if (ret) { @@ -315,6 +306,7 @@ bool CCoreAudioGraph::Close() CAUOutputDevice *d = m_auUnitList.front(); m_auUnitList.pop_front(); ReleaseBus(d->GetBus()); + d->SetInputSource(NULL); d->Close(); delete d; } @@ -488,9 +480,9 @@ CAUOutputDevice *CCoreAudioGraph::CreateUnit(AEAudioFormat &format) if (!m_audioUnit || !m_mixerUnit) return NULL; - AudioStreamBasicDescription fmt; - AudioStreamBasicDescription inputFormat; - AudioStreamBasicDescription outputFormat; + AudioStreamBasicDescription fmt = {0}; + AudioStreamBasicDescription inputFormat = {0}; + AudioStreamBasicDescription outputFormat = {0}; int busNumber = GetFreeBus(); if (busNumber == INVALID_BUS) @@ -578,7 +570,7 @@ int CCoreAudioGraph::GetMixerChannelOffset(int busNumber) return 0; int offset = 0; - AudioStreamBasicDescription fmt; + AudioStreamBasicDescription fmt = {0}; for (int i = 0; i < busNumber; i++) { diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.h index cdebe9afc0..c4aa6d2dc9 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.h +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.h @@ -41,9 +41,9 @@ class CCoreAudioGraph public: CCoreAudioGraph(); ~CCoreAudioGraph(); - + bool Open(ICoreAudioSource *pSource, AEAudioFormat &format, AudioDeviceID deviceId, - bool allowMixing, AudioChannelLayoutTag layoutTag); + bool allowMixing, AudioChannelLayoutTag layoutTag, float initVolume); bool Close(); bool Start(); bool Stop(); @@ -59,11 +59,11 @@ public: private: AUGraph m_audioGraph; - + CAUOutputDevice *m_inputUnit; CAUOutputDevice *m_audioUnit; CAUMatrixMixer *m_mixerUnit; - + int m_reservedBusNumber[MAX_CONNECTION_LIMIT]; bool m_initialized; AudioDeviceID m_deviceId; diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.cpp index ba3ad8ab87..f5204b2def 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.cpp +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.cpp @@ -24,16 +24,17 @@ #include "CoreAudioAEHAL.h" #include "utils/log.h" -// AudioHardwareGetProperty and friends are deprecated, -// turn off the warning spew. -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - bool CCoreAudioHardware::GetAutoHogMode() { + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioHardwarePropertyHogModeIsAllowed; + UInt32 val = 0; UInt32 size = sizeof(val); - OSStatus ret = AudioHardwareGetProperty(kAudioHardwarePropertyHogModeIsAllowed, &size, &val); - if (ret) + OSStatus ret = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &size, &val); + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioHardware::GetAutoHogMode: " "Unable to get auto 'hog' mode. Error = %s", GetError(ret).c_str()); @@ -44,22 +45,30 @@ bool CCoreAudioHardware::GetAutoHogMode() void CCoreAudioHardware::SetAutoHogMode(bool enable) { + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioHardwarePropertyHogModeIsAllowed; + UInt32 val = enable ? 1 : 0; - OSStatus ret = AudioHardwareSetProperty(kAudioHardwarePropertyHogModeIsAllowed, sizeof(val), &val); - if (ret) + UInt32 size = sizeof(val); + OSStatus ret = AudioObjectSetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, size, &val); + if (ret != noErr) CLog::Log(LOGERROR, "CCoreAudioHardware::SetAutoHogMode: " "Unable to set auto 'hog' mode. Error = %s", GetError(ret).c_str()); } AudioStreamBasicDescription* CCoreAudioHardware::FormatsList(AudioStreamID stream) { - // This is deprecated for kAudioStreamPropertyAvailablePhysicalFormats, - // but compiling on 10.3 requires the older constant - AudioDevicePropertyID p = kAudioStreamPropertyPhysicalFormats; - - UInt32 listSize; // Retrieve all the stream formats supported by this output stream - OSStatus ret = AudioStreamGetPropertyInfo(stream, 0, p, &listSize, NULL); + + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioStreamPropertyPhysicalFormats; + + UInt32 listSize = 0; + OSStatus ret = AudioObjectGetPropertyDataSize(stream, &propertyAddress, 0, NULL, &listSize); if (ret != noErr) { CLog::Log(LOGDEBUG, "CCoreAudioHardware::FormatsList: " @@ -76,7 +85,7 @@ AudioStreamBasicDescription* CCoreAudioHardware::FormatsList(AudioStreamID strea return NULL; } - ret = AudioStreamGetProperty(stream, 0, p, &listSize, list); + ret = AudioObjectGetPropertyData(stream, &propertyAddress, 0, NULL, &listSize, list); if (ret != noErr) { CLog::Log(LOGDEBUG, "CCoreAudioHardware::FormatsList: " @@ -94,9 +103,13 @@ AudioStreamBasicDescription* CCoreAudioHardware::FormatsList(AudioStreamID strea AudioStreamID* CCoreAudioHardware::StreamsList(AudioDeviceID device) { // Get a list of all the streams on this device + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioDevicePropertyStreams; + UInt32 listSize; - OSStatus ret = AudioDeviceGetPropertyInfo(device, 0, FALSE, - kAudioDevicePropertyStreams, &listSize, NULL); + OSStatus ret = AudioObjectGetPropertyDataSize(device, &propertyAddress, 0, NULL, &listSize); if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioHardware::StreamsList: " @@ -113,10 +126,7 @@ AudioStreamID* CCoreAudioHardware::StreamsList(AudioDeviceID device) return NULL; } - AudioObjectPropertyAddress propertyAddress; - propertyAddress.mScope = kAudioDevicePropertyScopeInput; - propertyAddress.mElement = kAudioObjectPropertyElementMaster; - propertyAddress.mSelector = kAudioDevicePropertyStreams; + propertyAddress.mScope = kAudioDevicePropertyScopeInput; ret = AudioObjectGetPropertyData(device, &propertyAddress, 0, NULL, &listSize, list); if (ret != noErr) { @@ -135,8 +145,19 @@ void CCoreAudioHardware::ResetAudioDevices() { // Reset any devices with an AC3 stream back to a Linear PCM // so that they can become a default output device + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioHardwarePropertyDevices; + UInt32 size; - AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, NULL); + OSStatus ret = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &size); + if (ret != noErr) + { + CLog::Log(LOGERROR, "CCoreAudioHardware::ResetAudioDevices: ResetAudioDevices - unknown size"); + return; + } + AudioDeviceID *devices = (AudioDeviceID*)malloc(size); if (!devices) { @@ -144,17 +165,22 @@ void CCoreAudioHardware::ResetAudioDevices() return; } int numDevices = size / sizeof(AudioDeviceID); - AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices); + ret = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &size, devices); + if (ret != noErr) + { + CLog::Log(LOGERROR, "CCoreAudioHardware::ResetAudioDevices: ResetAudioDevices - cannot get device list"); + return; + } for (int i = 0; i < numDevices; i++) { - AudioStreamID *streams; - - streams = StreamsList(devices[i]); - for (int j = 0; streams[j] != kAudioHardwareBadStreamError; j++) - ResetStream(streams[j]); - - free(streams); + AudioStreamID *streams = StreamsList(devices[i]); + if (streams) + { + for (int j = 0; streams[j] != kAudioHardwareBadStreamError; j++) + ResetStream(streams[j]); + free(streams); + } } free(devices); } @@ -162,10 +188,16 @@ void CCoreAudioHardware::ResetAudioDevices() void CCoreAudioHardware::ResetStream(AudioStreamID stream) { // Find the streams current physical format + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioStreamPropertyPhysicalFormat; + AudioStreamBasicDescription currentFormat; UInt32 paramSize = sizeof(currentFormat); - AudioStreamGetProperty(stream, 0, kAudioStreamPropertyPhysicalFormat, - ¶mSize, ¤tFormat); + OSStatus ret = AudioObjectGetPropertyData(stream, &propertyAddress, 0, NULL, ¶mSize, ¤tFormat); + if (ret != noErr) + return; // If it's currently AC-3/SPDIF then reset it to some mixable format if (currentFormat.mFormatID == 'IAC3' || @@ -181,7 +213,7 @@ void CCoreAudioHardware::ResetStream(AudioStreamID stream) { if (formats[i].mFormatID == kAudioFormatLinearPCM) { - OSStatus ret = AudioStreamSetProperty(stream, NULL, 0, kAudioStreamPropertyPhysicalFormat, sizeof(formats[i]), &(formats[i])); + ret = AudioObjectSetPropertyData(stream, &propertyAddress, 0, NULL, sizeof(formats[i]), &(formats[i])); if (ret != noErr) { CLog::Log(LOGDEBUG, "CCoreAudioHardware::ResetStream: " @@ -219,12 +251,24 @@ AudioDeviceID CCoreAudioHardware::FindAudioDevice(const std::string &searchName) "Searching for device - %s.", searchName.c_str()); // Obtain a list of all available audio devices + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioHardwarePropertyDevices; + UInt32 size = 0; - AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, NULL); + OSStatus ret = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &size); + if (ret != noErr) + { + CLog::Log(LOGERROR, "CCoreAudioHardware::FindAudioDevice: " + "Unable to retrieve the size of the list of available devices. Error = %s", GetError(ret).c_str()); + return 0; + } + size_t deviceCount = size / sizeof(AudioDeviceID); AudioDeviceID* pDevices = new AudioDeviceID[deviceCount]; - OSStatus ret = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, pDevices); - if (ret) + ret = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &size, pDevices); + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioHardware::FindAudioDevice: " "Unable to retrieve the list of available devices. Error = %s", GetError(ret).c_str()); @@ -262,17 +306,17 @@ AudioDeviceID CCoreAudioHardware::FindAudioDevice(const std::string &searchName) AudioDeviceID CCoreAudioHardware::GetDefaultOutputDevice() { - UInt32 size = sizeof(AudioDeviceID); - AudioDeviceID deviceId = 0; AudioObjectPropertyAddress propertyAddress; propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; propertyAddress.mElement = kAudioObjectPropertyElementMaster; propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice; - OSStatus ret = AudioObjectGetPropertyData(kAudioObjectSystemObject, - &propertyAddress, 0, NULL, &size, &deviceId); + + AudioDeviceID deviceId = 0; + UInt32 size = sizeof(AudioDeviceID); + OSStatus ret = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &size, &deviceId); // outputDevice is set to 0 if there is no audio device available // or if the default device is set to an encoded format - if (ret || !deviceId) + if (ret != noErr || !deviceId) { CLog::Log(LOGERROR, "CCoreAudioHardware::GetDefaultOutputDevice:" " Unable to identify default output device. Error = %s", GetError(ret).c_str()); @@ -284,31 +328,26 @@ AudioDeviceID CCoreAudioHardware::GetDefaultOutputDevice() void CCoreAudioHardware::GetOutputDeviceName(std::string& name) { + name = "Default"; AudioDeviceID deviceId = GetDefaultOutputDevice(); - if(deviceId) - { - UInt32 size = 0; - // TODO: Change to kAudioObjectPropertyObjectName - AudioDeviceGetPropertyInfo(deviceId,0, false, - kAudioDevicePropertyDeviceName, &size, NULL); - char *m_buffer = (char*)malloc(size); - - OSStatus ret = AudioDeviceGetProperty(deviceId, 0, false, - kAudioDevicePropertyDeviceName, &size, m_buffer); - if (ret && !m_buffer) - { - name ="Default"; - } - else - { - name = m_buffer; - free(m_buffer); - } - } - else + if (deviceId) { - name = "Default"; + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioObjectPropertyName; + + CFStringRef theDeviceName = NULL; + UInt32 propertySize = sizeof(CFStringRef); + OSStatus ret = AudioObjectGetPropertyData(deviceId, &propertyAddress, 0, NULL, &propertySize, &theDeviceName); + if (ret != noErr) + return; + + const char *cstr = CFStringGetCStringPtr(theDeviceName, kCFStringEncodingUTF8); + if (cstr) + name = cstr; + CFRelease(theDeviceName); } } @@ -319,18 +358,24 @@ UInt32 CCoreAudioHardware::GetOutputDevices(CoreAudioDeviceList *pList) return found; // Obtain a list of all available audio devices + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioHardwarePropertyDevices; + UInt32 size = 0; - AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, NULL); + OSStatus ret = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &size); + if (ret != noErr) + { + CLog::Log(LOGERROR, "CCoreAudioHardware::GetOutputDevices:" + " Unable to retrieve the size of the list of available devices. Error = %s", GetError(ret).c_str()); + return found; + } + size_t deviceCount = size / sizeof(AudioDeviceID); AudioDeviceID* pDevices = new AudioDeviceID[deviceCount]; - - AudioObjectPropertyAddress propertyAddress; - propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; - propertyAddress.mElement = kAudioObjectPropertyElementMaster; - propertyAddress.mSelector = kAudioHardwarePropertyDevices; - OSStatus ret = AudioObjectGetPropertyData(kAudioObjectSystemObject, - &propertyAddress, 0, NULL, &size, pDevices); - if (ret) + ret = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &size, pDevices); + if (ret != noErr) CLog::Log(LOGERROR, "CCoreAudioHardware::GetOutputDevices:" " Unable to retrieve the list of available devices. Error = %s", GetError(ret).c_str()); else diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioRingBuffer.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioRingBuffer.h index 8b4b427765..0c45882c46 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioRingBuffer.h +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioRingBuffer.h @@ -233,7 +233,7 @@ public: */ unsigned int GetReadSize() { - return m_iWritten - m_iRead; + return m_iWritten > m_iRead ? m_iWritten - m_iRead : 0; } /** diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioStream.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioStream.cpp index daba9bf44d..26fd9bc18a 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioStream.cpp +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioStream.cpp @@ -25,10 +25,6 @@ #include "utils/log.h" #include "utils/StdString.h" -// AudioHardwareGetProperty and friends are deprecated, -// turn off the warning spew. -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - CCoreAudioStream::CCoreAudioStream() : m_StreamId (0 ) { @@ -119,9 +115,16 @@ UInt32 CCoreAudioStream::GetDirection() UInt32 val = 0; UInt32 size = sizeof(UInt32); - OSStatus ret = AudioStreamGetProperty(m_StreamId, 0, kAudioStreamPropertyDirection, &size, &val); + + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioStreamPropertyDirection; + + OSStatus ret = AudioObjectGetPropertyData(m_StreamId, &propertyAddress, 0, NULL, &size, &val); if (ret) return 0; + return val; } @@ -132,7 +135,13 @@ UInt32 CCoreAudioStream::GetTerminalType() UInt32 val = 0; UInt32 size = sizeof(UInt32); - OSStatus ret = AudioStreamGetProperty(m_StreamId, 0, kAudioStreamPropertyTerminalType, &size, &val); + + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioStreamPropertyTerminalType; + + OSStatus ret = AudioObjectGetPropertyData(m_StreamId, &propertyAddress, 0, NULL, &size, &val); if (ret) return 0; return val; @@ -146,13 +155,19 @@ UInt32 CCoreAudioStream::GetNumLatencyFrames() UInt32 i_param_size = sizeof(uint32_t); UInt32 i_param, num_latency_frames = 0; + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioStreamPropertyLatency; + // number of frames of latency in the AudioStream - if (noErr == AudioStreamGetProperty(m_StreamId, 0, kAudioStreamPropertyLatency, &i_param_size, &i_param)) + OSStatus ret = AudioObjectGetPropertyData(m_StreamId, &propertyAddress, 0, NULL, &i_param_size, &i_param); + if (ret == noErr) { num_latency_frames += i_param; } - return (num_latency_frames); + return num_latency_frames; } bool CCoreAudioStream::GetVirtualFormat(AudioStreamBasicDescription* pDesc) @@ -161,7 +176,16 @@ bool CCoreAudioStream::GetVirtualFormat(AudioStreamBasicDescription* pDesc) return false; UInt32 size = sizeof(AudioStreamBasicDescription); - OSStatus ret = AudioStreamGetProperty(m_StreamId, 0, kAudioStreamPropertyVirtualFormat, &size, pDesc); + + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioStreamPropertyVirtualFormat; + OSStatus ret = AudioObjectGetPropertyDataSize(m_StreamId, &propertyAddress, 0, NULL, &size); + if (ret) + return false; + + ret = AudioObjectGetPropertyData(m_StreamId, &propertyAddress, 0, NULL, &size, pDesc); if (ret) return false; return true; @@ -185,8 +209,14 @@ bool CCoreAudioStream::SetVirtualFormat(AudioStreamBasicDescription* pDesc) } } m_virtual_format_event.Reset(); - OSStatus ret = AudioStreamSetProperty(m_StreamId, - NULL, 0, kAudioStreamPropertyVirtualFormat, sizeof(AudioStreamBasicDescription), pDesc); + + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioStreamPropertyVirtualFormat; + + UInt32 propertySize = sizeof(AudioStreamBasicDescription); + OSStatus ret = AudioObjectSetPropertyData(m_StreamId, &propertyAddress, 0, NULL, propertySize, pDesc); if (ret) { CLog::Log(LOGERROR, "CCoreAudioStream::SetVirtualFormat: " @@ -229,7 +259,13 @@ bool CCoreAudioStream::GetPhysicalFormat(AudioStreamBasicDescription* pDesc) return false; UInt32 size = sizeof(AudioStreamBasicDescription); - OSStatus ret = AudioStreamGetProperty(m_StreamId, 0, kAudioStreamPropertyPhysicalFormat, &size, pDesc); + + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioStreamPropertyPhysicalFormat; + + OSStatus ret = AudioObjectGetPropertyData(m_StreamId, &propertyAddress, 0, NULL, &size, pDesc); if (ret) return false; return true; @@ -253,8 +289,14 @@ bool CCoreAudioStream::SetPhysicalFormat(AudioStreamBasicDescription* pDesc) } } m_physical_format_event.Reset(); - OSStatus ret = AudioStreamSetProperty(m_StreamId, - NULL, 0, kAudioStreamPropertyPhysicalFormat, sizeof(AudioStreamBasicDescription), pDesc); + + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioStreamPropertyPhysicalFormat; + + UInt32 propertySize = sizeof(AudioStreamBasicDescription); + OSStatus ret = AudioObjectSetPropertyData(m_StreamId, &propertyAddress, 0, NULL, propertySize, pDesc); if (ret) { CLog::Log(LOGERROR, "CCoreAudioStream::SetPhysicalFormat: " @@ -297,17 +339,19 @@ bool CCoreAudioStream::GetAvailableVirtualFormats(StreamFormatList* pList) if (!pList || !m_StreamId) return false; + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioStreamPropertyAvailableVirtualFormats; + UInt32 propertySize = 0; - Boolean writable = false; - OSStatus ret = AudioStreamGetPropertyInfo(m_StreamId, 0, - kAudioStreamPropertyAvailableVirtualFormats, &propertySize, &writable); + OSStatus ret = AudioObjectGetPropertyDataSize(m_StreamId, &propertyAddress, 0, NULL, &propertySize); if (ret) return false; UInt32 formatCount = propertySize / sizeof(AudioStreamRangedDescription); - AudioStreamRangedDescription* pFormatList = new AudioStreamRangedDescription[formatCount]; - ret = AudioStreamGetProperty(m_StreamId, 0, - kAudioStreamPropertyAvailableVirtualFormats, &propertySize, pFormatList); + AudioStreamRangedDescription *pFormatList = new AudioStreamRangedDescription[formatCount]; + ret = AudioObjectGetPropertyData(m_StreamId, &propertyAddress, 0, NULL, &propertySize, pFormatList); if (!ret) { for (UInt32 format = 0; format < formatCount; format++) @@ -322,17 +366,19 @@ bool CCoreAudioStream::GetAvailablePhysicalFormats(StreamFormatList* pList) if (!pList || !m_StreamId) return false; + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + propertyAddress.mSelector = kAudioStreamPropertyAvailablePhysicalFormats; + UInt32 propertySize = 0; - Boolean writable = false; - OSStatus ret = AudioStreamGetPropertyInfo(m_StreamId, 0, - kAudioStreamPropertyAvailablePhysicalFormats, &propertySize, &writable); + OSStatus ret = AudioObjectGetPropertyDataSize(m_StreamId, &propertyAddress, 0, NULL, &propertySize); if (ret) return false; UInt32 formatCount = propertySize / sizeof(AudioStreamRangedDescription); - AudioStreamRangedDescription* pFormatList = new AudioStreamRangedDescription[formatCount]; - ret = AudioStreamGetProperty(m_StreamId, 0, - kAudioStreamPropertyAvailablePhysicalFormats, &propertySize, pFormatList); + AudioStreamRangedDescription *pFormatList = new AudioStreamRangedDescription[formatCount]; + ret = AudioObjectGetPropertyData(m_StreamId, &propertyAddress, 0, NULL, &propertySize, pFormatList); if (!ret) { for (UInt32 format = 0; format < formatCount; format++) diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.cpp index 82a985803b..ce5d7c149b 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.cpp +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.cpp @@ -27,10 +27,6 @@ #include <AudioToolbox/AUGraph.h> -// AudioHardwareGetProperty and friends are deprecated, -// turn off the warning spew. -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - CCoreAudioUnit::CCoreAudioUnit() : m_pSource (NULL ), m_audioUnit (NULL ), @@ -47,7 +43,7 @@ CCoreAudioUnit::~CCoreAudioUnit() Close(); } -bool CCoreAudioUnit::Open(AUGraph audioGraph, ComponentDescription desc) +bool CCoreAudioUnit::Open(AUGraph audioGraph, AudioComponentDescription desc) { if (m_audioUnit) Close(); @@ -56,7 +52,7 @@ bool CCoreAudioUnit::Open(AUGraph audioGraph, ComponentDescription desc) m_Initialized = false; - ret = AUGraphNewNode(audioGraph, &desc, 0, NULL, &m_audioNode); + ret = AUGraphAddNode(audioGraph, &desc, &m_audioNode); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " @@ -64,7 +60,7 @@ bool CCoreAudioUnit::Open(AUGraph audioGraph, ComponentDescription desc) return false; } - ret = AUGraphGetNodeInfo(audioGraph, m_audioNode, 0, 0, 0, &m_audioUnit); + ret = AUGraphNodeInfo(audioGraph, m_audioNode, 0, &m_audioUnit); if (ret) { CLog::Log(LOGERROR, "CCoreAudioGraph::Open: " @@ -80,12 +76,10 @@ bool CCoreAudioUnit::Open(AUGraph audioGraph, ComponentDescription desc) bool CCoreAudioUnit::Open(AUGraph audioGraph, OSType type, OSType subType, OSType manufacturer) { - ComponentDescription desc; + AudioComponentDescription desc = {0}; desc.componentType = type; desc.componentSubType = subType; desc.componentManufacturer = manufacturer; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; return Open(audioGraph, desc); } @@ -99,7 +93,7 @@ void CCoreAudioUnit::Close() SetInputSource(NULL); Stop(); - + if (m_busNumber != INVALID_BUS) { OSStatus ret = AUGraphDisconnectNodeInput(m_audioGraph, m_audioNode, m_busNumber); @@ -110,7 +104,7 @@ void CCoreAudioUnit::Close() } ret = AUGraphRemoveNode(m_audioGraph, m_audioNode); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::Close: " "Unable to remove AudioUnit. Error = %s", GetError(ret).c_str()); @@ -133,7 +127,7 @@ bool CCoreAudioUnit::GetFormat(AudioStreamBasicDescription* pDesc, AudioUnitScop UInt32 size = sizeof(AudioStreamBasicDescription); OSStatus ret = AudioUnitGetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, scope, bus, pDesc, &size); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::GetFormat: " "Unable to get AudioUnit format. Bus : %d Scope : %d : Error = %s", @@ -150,7 +144,7 @@ bool CCoreAudioUnit::SetFormat(AudioStreamBasicDescription* pDesc, AudioUnitScop OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, scope, bus, pDesc, sizeof(AudioStreamBasicDescription)); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::SetFormat: " "Unable to set AudioUnit format. Bus : %d Scope : %d : Error = %s", @@ -167,7 +161,7 @@ bool CCoreAudioUnit::SetMaxFramesPerSlice(UInt32 maxFrames) OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFrames, sizeof(UInt32)); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::SetMaxFramesPerSlice: " "Unable to set AudioUnit max frames per slice. Error = %s", GetError(ret).c_str()); @@ -185,7 +179,7 @@ bool CCoreAudioUnit::GetSupportedChannelLayouts(AudioChannelLayoutList* pLayouts Boolean writable = false; OSStatus ret = AudioUnitGetPropertyInfo(m_audioUnit, kAudioUnitProperty_SupportedChannelLayoutTags, kAudioUnitScope_Input, 0, &propSize, &writable); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::GetSupportedChannelLayouts: " "Unable to retrieve supported channel layout property info. Error = %s", GetError(ret).c_str()); @@ -195,7 +189,7 @@ bool CCoreAudioUnit::GetSupportedChannelLayouts(AudioChannelLayoutList* pLayouts AudioChannelLayoutTag* pSuppLayouts = new AudioChannelLayoutTag[layoutCount]; ret = AudioUnitGetProperty(m_audioUnit, kAudioUnitProperty_SupportedChannelLayoutTags, kAudioUnitScope_Output, 0, pSuppLayouts, &propSize); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::GetSupportedChannelLayouts: " "Unable to retrieve supported channel layouts. Error = %s", GetError(ret).c_str()); @@ -226,7 +220,7 @@ bool CCoreAudioUnit::SetRenderProc() callbackInfo.inputProcRefCon = this; // Pointer to be returned in the callback proc OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callbackInfo, sizeof(AURenderCallbackStruct)); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::SetRenderProc: " "Unable to set AudioUnit render callback. Error = %s", GetError(ret).c_str()); @@ -246,12 +240,14 @@ bool CCoreAudioUnit::RemoveRenderProc() if (!m_audioUnit || !m_renderProc) return false; + AudioUnitInitialize(m_audioUnit); + AURenderCallbackStruct callbackInfo; callbackInfo.inputProc = nil; callbackInfo.inputProcRefCon = nil; OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callbackInfo, sizeof(AURenderCallbackStruct)); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::RemoveRenderProc: " "Unable to remove AudioUnit render callback. Error = %s", GetError(ret).c_str()); @@ -367,7 +363,7 @@ float CCoreAudioUnit::GetLatency() OSStatus ret = AudioUnitGetProperty(m_audioUnit, kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0, &latency, &size); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::GetLatency: " "Unable to set AudioUnit latency. Error = %s", GetError(ret).c_str()); @@ -416,7 +412,7 @@ bool CAUOutputDevice::SetCurrentDevice(AudioDeviceID deviceId) OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, kOutputBus, &deviceId, sizeof(AudioDeviceID)); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::SetCurrentDevice: " "Unable to set current device. Error = %s", GetError(ret).c_str()); @@ -445,7 +441,7 @@ bool CAUOutputDevice::GetChannelMap(CoreAudioChannelList* pChannelMap) SInt32* pMap = new SInt32[channels]; OSStatus ret = AudioUnitGetProperty(m_audioUnit, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Input, 0, pMap, &size); - if (ret) + if (ret != noErr) CLog::Log(LOGERROR, "CCoreAudioUnit::GetInputChannelMap: " "Unable to retrieve AudioUnit input channel map. Error = %s", GetError(ret).c_str()); else @@ -470,7 +466,7 @@ bool CAUOutputDevice::SetChannelMap(CoreAudioChannelList* pChannelMap) OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Input, 0, pMap, size); - if (ret) + if (ret != noErr) CLog::Log(LOGERROR, "CCoreAudioUnit::GetBufferFrameSize: " "Unable to get current device's buffer size. Error = %s", GetError(ret).c_str()); delete[] pMap; @@ -485,7 +481,7 @@ Float32 CAUOutputDevice::GetCurrentVolume() Float32 volPct = 0.0f; OSStatus ret = AudioUnitGetParameter(m_audioUnit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, &volPct); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::GetCurrentVolume: " "Unable to get AudioUnit volume. Error = %s", GetError(ret).c_str()); @@ -501,7 +497,7 @@ bool CAUOutputDevice::SetCurrentVolume(Float32 vol) OSStatus ret = AudioUnitSetParameter(m_audioUnit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, vol, 0); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::SetCurrentVolume: " "Unable to set AudioUnit volume. Error = %s", GetError(ret).c_str()); @@ -520,7 +516,7 @@ UInt32 CAUOutputDevice::GetBufferFrameSize() OSStatus ret = AudioUnitGetProperty(m_audioUnit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Input, 0, &bufferSize, &size); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CCoreAudioUnit::GetBufferFrameSize: " "Unable to get current device's buffer size. Error = %s", GetError(ret).c_str()); @@ -545,7 +541,7 @@ bool CAUOutputDevice::EnableInputOuput() enable = 1; ret = AudioUnitSetProperty(m_audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &enable, sizeof(enable)); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CAUOutputDevice::EnableInputOuput:: " "Unable to enable input on bus 1. Error = %s", GetError(ret).c_str()); @@ -555,7 +551,7 @@ bool CAUOutputDevice::EnableInputOuput() enable = 1; ret = AudioUnitSetProperty(m_audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &enable, sizeof(enable)); - if (ret) + if (ret != noErr) { CLog::Log(LOGERROR, "CAUOutputDevice::EnableInputOuput:: " "Unable to disable output on bus 0. Error = %s", GetError(ret).c_str()); @@ -571,17 +567,22 @@ bool CAUOutputDevice::GetPreferredChannelLayout(CCoreAudioChannelLayout& layout) if (!m_DeviceId) return false; - UInt32 propertySize = 0; - Boolean writable = false; - OSStatus ret = AudioDeviceGetPropertyInfo(m_DeviceId, 0, false, - kAudioDevicePropertyPreferredChannelLayout, &propertySize, &writable); - if (ret) + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyPreferredChannelLayout; + if (!AudioObjectHasProperty(m_DeviceId, &propertyAddress)) return false; - void* pBuf = malloc(propertySize); - ret = AudioDeviceGetProperty(m_DeviceId, 0, false, - kAudioDevicePropertyPreferredChannelLayout, &propertySize, pBuf); - if (ret) + UInt32 propertySize = 0; + OSStatus ret = AudioObjectGetPropertyDataSize(m_DeviceId, &propertyAddress, 0, NULL, &propertySize); + if (ret != noErr) + CLog::Log(LOGERROR, "CAUOutputDevice::GetPreferredChannelLayout: " + "Unable to retrieve preferred channel layout size. Error = %s", GetError(ret).c_str()); + + void *pBuf = malloc(propertySize); + ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, pBuf); + if (ret != noErr) CLog::Log(LOGERROR, "CAUOutputDevice::GetPreferredChannelLayout: " "Unable to retrieve preferred channel layout. Error = %s", GetError(ret).c_str()); else diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.h index 562e1b779a..6875db8ad6 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.h +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.h @@ -41,7 +41,7 @@ public: CCoreAudioUnit(); virtual ~CCoreAudioUnit(); - virtual bool Open(AUGraph audioGraph, ComponentDescription desc); + virtual bool Open(AUGraph audioGraph, AudioComponentDescription desc); virtual bool Open(AUGraph audioGraph, OSType type, OSType subType, OSType manufacturer); virtual void Close(); virtual bool SetInputSource(ICoreAudioSource *pSource); diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/ICoreAudioAEHAL.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/ICoreAudioAEHAL.h index 3463d02e0e..1053f8885c 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/ICoreAudioAEHAL.h +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/ICoreAudioAEHAL.h @@ -32,12 +32,12 @@ class CAUOutputDevice; */ class ICoreAudioAEHAL { -protected: +protected: ICoreAudioAEHAL() {} virtual ~ICoreAudioAEHAL() {} public: - virtual bool Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device) = 0; + virtual bool Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device, float initVolume) = 0; virtual void Deinitialize() = 0; virtual void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough) = 0; //virtual CAUOutputDevice *DestroyUnit(CAUOutputDevice *outputUnit); diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp index 563fd3d4df..bd01a674a1 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp @@ -162,6 +162,7 @@ void CSoftAE::OpenSink() m_reOpenEvent.Reset(); m_reOpen = true; m_reOpenEvent.Wait(); + m_wake.Set(); } /* this must NEVER be called from outside the main thread or Initialization */ @@ -322,6 +323,10 @@ void CSoftAE::InternalOpenSink() m_sinkFormatSampleRateMul = 1.0 / (float)newFormat.m_sampleRate; m_sinkFormatFrameSizeMul = 1.0 / (float)newFormat.m_frameSize; m_sinkBlockSize = newFormat.m_frames * newFormat.m_frameSize; + // check if sink controls volume, if so, init the volume. + m_sinkHandlesVolume = m_sink->HasVolume(); + if (m_sinkHandlesVolume) + m_sink->SetVolume(m_volume); /* invalidate the buffer */ m_buffer.Empty(); @@ -425,6 +430,7 @@ void CSoftAE::InternalOpenSink() /* notify any event listeners that we are done */ m_reOpen = false; m_reOpenEvent.Set(); + m_wake.Set(); } void CSoftAE::ResetEncoder() @@ -666,6 +672,7 @@ void CSoftAE::ResumeStream(CSoftAEStream *stream) void CSoftAE::Stop() { m_running = false; + m_wake.Set(); /* wait for the thread to stop */ CSingleLock lock(m_runningLock); @@ -732,6 +739,7 @@ void CSoftAE::PlaySound(IAESound *sound) ((CSoftAESound*)sound)->GetSampleCount() }; m_playing_sounds.push_back(ss); + m_wake.Set(); } void CSoftAE::FreeSound(IAESound *sound) @@ -795,34 +803,34 @@ IAEStream *CSoftAE::FreeStream(IAEStream *stream) double CSoftAE::GetDelay() { + double delay = (double)m_buffer.Used() * m_sinkFormatFrameSizeMul *m_sinkFormatSampleRateMul; CSharedLock sinkLock(m_sinkLock); + if (m_sink) + delay += m_sink->GetDelay(); + sinkLock.Leave(); - double delay = m_sink->GetDelay(); if (m_transcode && m_encoder && !m_rawPassthrough) delay += m_encoder->GetDelay((double)m_encodedBuffer.Used() * m_encoderFrameSizeMul); - double buffered = (double)m_buffer.Used() * m_sinkFormatFrameSizeMul; - return delay + (buffered * m_sinkFormatSampleRateMul); + return delay; } double CSoftAE::GetCacheTime() { + double time = (double)m_buffer.Used() * m_sinkFormatFrameSizeMul * m_sinkFormatSampleRateMul; CSharedLock sinkLock(m_sinkLock); - - double time; - time = (double)m_buffer.Used() * m_sinkFormatFrameSizeMul * m_sinkFormatSampleRateMul; - time += m_sink->GetCacheTime(); + if (m_sink) + time += m_sink->GetCacheTime(); return time; } double CSoftAE::GetCacheTotal() { + double total = (double)m_buffer.Size() * m_sinkFormatFrameSizeMul * m_sinkFormatSampleRateMul; CSharedLock sinkLock(m_sinkLock); - - double total; - total = (double)m_buffer.Size() * m_sinkFormatFrameSizeMul * m_sinkFormatSampleRateMul; - total += m_sink->GetCacheTotal(); + if (m_sink) + total += m_sink->GetCacheTotal(); return total; } @@ -835,6 +843,12 @@ float CSoftAE::GetVolume() void CSoftAE::SetVolume(float volume) { m_volume = volume; + if (!m_sinkHandlesVolume) + return; + + CSharedLock sinkLock(m_sinkLock); + if (m_sink) + m_sink->SetVolume(m_volume); } void CSoftAE::StopAllSounds() @@ -885,10 +899,19 @@ void CSoftAE::Run() CLog::Log(LOGDEBUG, "CSoftAE::Run - Sink restart flagged"); InternalOpenSink(); } +#if defined(TARGET_ANDROID) + else if (m_playingStreams.empty() && m_playing_sounds.empty()) + { + // if we have nothing to do, take a dirt nap. + // we do not have to take a lock just to check empty. + // this keeps AE from sucking CPU if nothing is going on. + m_wake.WaitMSec(100); + } +#endif } } -void CSoftAE::AllocateConvIfNeeded(size_t convertedSize) +void CSoftAE::AllocateConvIfNeeded(size_t convertedSize, bool prezero) { if (m_convertedSize < convertedSize) { @@ -896,10 +919,17 @@ void CSoftAE::AllocateConvIfNeeded(size_t convertedSize) m_converted = (uint8_t *)_aligned_malloc(convertedSize, 16); m_convertedSize = convertedSize; } + if (prezero) + memset(m_converted, 0x00, convertedSize); } unsigned int CSoftAE::MixSounds(float *buffer, unsigned int samples) { + // no point doing anything if we have no sounds, + // we do not have to take a lock just to check empty + if (m_playing_sounds.empty()) + return 0; + SoundStateList::iterator itt; unsigned int mixed = 0; @@ -922,8 +952,9 @@ unsigned int CSoftAE::MixSounds(float *buffer, unsigned int samples) #ifdef __SSE__ CAEUtil::SSEMulAddArray(buffer, ss->samples, volume, mixSamples); #else + float *sample_buffer = ss->samples; for (unsigned int i = 0; i < mixSamples; ++i) - buffer[i] = (buffer[i] + (ss->samples[i] * volume)); + *buffer++ = *sample_buffer++ * volume; #endif ss->sampleCount -= mixSamples; @@ -951,34 +982,27 @@ bool CSoftAE::FinalizeSamples(float *buffer, unsigned int samples, bool hasAudio } /* deamplify */ - bool clamp = false; - if (m_volume < 1.0) + if (!m_sinkHandlesVolume && m_volume < 1.0) { #ifdef __SSE__ CAEUtil::SSEMulArray(buffer, m_volume, samples); - for (unsigned int i = 0; i < samples; ++i) - if (buffer[i] < -1.0f || buffer[i] > 1.0f) - { - clamp = true; - break; - } #else - for (unsigned int i = 0; i < samples; ++i) - { - buffer[i] *= m_volume; - if (!clamp && (buffer[i] < -1.0f || buffer[i] > 1.0f)) - clamp = true; - } + float *fbuffer = buffer; + for (unsigned int i = 0; i < samples; i++) + *fbuffer++ *= m_volume; #endif } - else + + /* check if we need to clamp */ + bool clamp = false; + float *fbuffer = buffer; + for (unsigned int i = 0; i < samples; i++, fbuffer++) { - for (unsigned int i = 0; i < samples; ++i) - if (buffer[i] < -1.0f || buffer[i] > 1.0f) - { - clamp = true; - break; - } + if (*fbuffer < -1.0f || *fbuffer > 1.0f) + { + clamp = true; + break; + } } /* if there were no samples outside of the range, dont clamp the buffer */ @@ -1004,8 +1028,9 @@ int CSoftAE::RunOutputStage(bool hasAudio) if (m_convertFn) { const unsigned int convertedBytes = m_sinkFormat.m_frames * m_sinkFormat.m_frameSize; - AllocateConvIfNeeded(convertedBytes); - m_convertFn((float*)data, needSamples, m_converted); + AllocateConvIfNeeded(convertedBytes, !hasAudio); + if (hasAudio) + m_convertFn((float*)data, needSamples, m_converted); data = m_converted; } @@ -1042,8 +1067,9 @@ int CSoftAE::RunRawOutputStage(bool hasAudio) * tell it the needed format from here, so do it here for now (better than * nothing)... */ - AllocateConvIfNeeded(m_sinkBlockSize); - Endian_Swap16_buf((uint16_t *)m_converted, (uint16_t *)data, m_sinkBlockSize / 2); + AllocateConvIfNeeded(m_sinkBlockSize, !hasAudio); + if (hasAudio) + Endian_Swap16_buf((uint16_t *)m_converted, (uint16_t *)data, m_sinkBlockSize / 2); data = m_converted; } @@ -1076,17 +1102,10 @@ int CSoftAE::RunTranscodeStage(bool hasAudio) if (m_convertFn) { unsigned int newsize = m_encoderFormat.m_frames * m_encoderFormat.m_frameSize; - if (m_convertedSize < newsize) - { - _aligned_free(m_converted); - m_converted = (uint8_t *)_aligned_malloc(newsize, 16); - m_convertedSize = newsize; - } - m_convertFn( - (float*)m_buffer.Raw(block), - m_encoderFormat.m_frames * m_encoderFormat.m_channelLayout.Count(), - m_converted - ); + AllocateConvIfNeeded(newsize, !hasAudio); + if (hasAudio) + m_convertFn((float*)m_buffer.Raw(block), + m_encoderFormat.m_frames * m_encoderFormat.m_channelLayout.Count(), m_converted); buffer = m_converted; } else @@ -1169,16 +1188,17 @@ unsigned int CSoftAE::RunRawStreamStage(unsigned int channelCount, void *out, bo unsigned int CSoftAE::RunStreamStage(unsigned int channelCount, void *out, bool &restart) { + // no point doing anything if we have no streams, + // we do not have to take a lock just to check empty + if (m_playingStreams.empty()) + return 0; + float *dst = (float*)out; unsigned int mixed = 0; /* identify the master stream */ CSingleLock streamLock(m_streamLock); - /* no point doing anything if we have no streams */ - if (m_playingStreams.empty()) - return mixed; - /* mix in any running streams */ StreamList resumeStreams; for (StreamList::iterator itt = m_playingStreams.begin(); itt != m_playingStreams.end(); ++itt) @@ -1199,23 +1219,8 @@ unsigned int CSoftAE::RunStreamStage(unsigned int channelCount, void *out, bool else #endif { - /* unrolled loop for performance */ - unsigned int blocks = channelCount & ~0x3; - unsigned int i = 0; - for (i = 0; i < blocks; i += 4) - { - dst[i+0] += frame[i+0] * volume; - dst[i+1] += frame[i+1] * volume; - dst[i+2] += frame[i+2] * volume; - dst[i+3] += frame[i+3] * volume; - } - - switch (channelCount & 0x3) - { - case 3: dst[i] += frame[i] * volume; ++i; - case 2: dst[i] += frame[i] * volume; ++i; - case 1: dst[i] += frame[i] * volume; - } + for (unsigned int i = 0; i < channelCount; ++i) + *dst++ += *frame++ * volume; } ++mixed; diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h index 11501efd9a..b70ea21093 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h @@ -130,6 +130,7 @@ private: /* internal vars */ bool m_running, m_reOpen; CEvent m_reOpenEvent; + CEvent m_wake; CCriticalSection m_runningLock; /* released when the thread exits */ CCriticalSection m_streamLock; /* m_streams lock */ @@ -150,6 +151,7 @@ private: float m_sinkFormatSampleRateMul; float m_sinkFormatFrameSizeMul; unsigned int m_sinkBlockSize; + bool m_sinkHandlesVolume; AEAudioFormat m_encoderFormat; float m_encoderFrameSizeMul; unsigned int m_bytesPerSample; @@ -186,7 +188,7 @@ private: uint8_t *m_converted; size_t m_convertedSize; - void AllocateConvIfNeeded(size_t convertedSize); + void AllocateConvIfNeeded(size_t convertedSize, bool prezero = false); /* thread run stages */ diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp index 33f282a138..106b3da284 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp @@ -136,7 +136,9 @@ void CSoftAEStream::Initialize() m_aeChannelLayout = AE.GetChannelLayout(); m_aeBytesPerFrame = AE_IS_RAW(m_initDataFormat) ? m_bytesPerFrame : (m_samplesPerFrame * sizeof(float)); - m_waterLevel = AE.GetSampleRate() / 2; + // set the waterlevel to 75 percent of the number of frames per second. + // this lets us drain the main buffer down futher before flagging an underrun. + m_waterLevel = AE.GetSampleRate() - (AE.GetSampleRate() / 4); m_refillBuffer = m_waterLevel; m_format.m_dataFormat = useDataFormat; @@ -192,8 +194,8 @@ void CSoftAEStream::Initialize() m_ssrcData.data_in = m_convertBuffer; m_internalRatio = (double)AE.GetSampleRate() / (double)m_initSampleRate; m_ssrcData.src_ratio = m_internalRatio; - m_ssrcData.data_out = (float*)_aligned_malloc(m_format.m_frameSamples * std::ceil(m_ssrcData.src_ratio) * sizeof(float), 16); - m_ssrcData.output_frames = m_format.m_frames * std::ceil(m_ssrcData.src_ratio); + m_ssrcData.data_out = (float*)_aligned_malloc(m_format.m_frameSamples * (int)std::ceil(m_ssrcData.src_ratio) * sizeof(float), 16); + m_ssrcData.output_frames = m_format.m_frames * (long)std::ceil(m_ssrcData.src_ratio); m_ssrcData.end_of_input = 0; } @@ -576,6 +578,7 @@ void CSoftAEStream::InternalFlush() /* reset our counts */ m_framesBuffered = 0; m_refillBuffer = m_waterLevel; + m_draining = false; } double CSoftAEStream::GetResampleRatio() @@ -594,7 +597,7 @@ bool CSoftAEStream::SetResampleRatio(double ratio) CSharedLock lock(m_lock); - int oldRatioInt = std::ceil(m_ssrcData.src_ratio); + int oldRatioInt = (int)std::ceil(m_ssrcData.src_ratio); m_resampleRatio = ratio; @@ -605,8 +608,8 @@ bool CSoftAEStream::SetResampleRatio(double ratio) if (oldRatioInt < std::ceil(m_ssrcData.src_ratio)) { _aligned_free(m_ssrcData.data_out); - m_ssrcData.data_out = (float*)_aligned_malloc(m_format.m_frameSamples * std::ceil(m_ssrcData.src_ratio) * sizeof(float), 16); - m_ssrcData.output_frames = m_format.m_frames * std::ceil(m_ssrcData.src_ratio); + m_ssrcData.data_out = (float*)_aligned_malloc(m_format.m_frameSamples * (int)std::ceil(m_ssrcData.src_ratio) * sizeof(float), 16); + m_ssrcData.output_frames = m_format.m_frames * (long)std::ceil(m_ssrcData.src_ratio); } return true; } diff --git a/xbmc/cores/AudioEngine/Interfaces/AESink.h b/xbmc/cores/AudioEngine/Interfaces/AESink.h index 7083d08b98..0b620388d3 100644 --- a/xbmc/cores/AudioEngine/Interfaces/AESink.h +++ b/xbmc/cores/AudioEngine/Interfaces/AESink.h @@ -78,5 +78,15 @@ public: Drain the sink */ virtual void Drain() {}; + + /* + Indicates if sink can handle volume control. + */ + virtual bool HasVolume() {return false;}; + + /* + This method sets the volume control, volume ranges from 0.0 to 1.0. + */ + virtual void SetVolume(float volume) {}; }; diff --git a/xbmc/cores/AudioEngine/Makefile.in b/xbmc/cores/AudioEngine/Makefile.in index 1acb2bd552..7749502ca2 100644 --- a/xbmc/cores/AudioEngine/Makefile.in +++ b/xbmc/cores/AudioEngine/Makefile.in @@ -35,18 +35,22 @@ SRCS += Engines/CoreAudio/CoreAudioMixMap.cpp SRCS += Engines/CoreAudio/CoreAudioStream.cpp SRCS += Engines/CoreAudio/CoreAudioUnit.cpp else -SRCS += Sinks/AESinkALSA.cpp -SRCS += Sinks/AESinkOSS.cpp SRCS += Sinks/AESinkProfiler.cpp SRCS += Engines/SoftAE/SoftAE.cpp SRCS += Engines/SoftAE/SoftAEStream.cpp SRCS += Engines/SoftAE/SoftAESound.cpp +ifeq (@USE_ANDROID@,1) +SRCS += Sinks/AESinkAUDIOTRACK.cpp +else +SRCS += Sinks/AESinkALSA.cpp +SRCS += Sinks/AESinkOSS.cpp SRCS += Engines/PulseAE/PulseAE.cpp SRCS += Engines/PulseAE/PulseAEStream.cpp SRCS += Engines/PulseAE/PulseAESound.cpp endif +endif SRCS += Utils/AEChannelInfo.cpp SRCS += Utils/AEBuffer.cpp diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index 8a1eba44ba..f37c9a9fac 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -151,10 +151,12 @@ bool CAESinkALSA::Initialize(AEAudioFormat &format, std::string &device) format.m_channelLayout = m_channelLayout; + AEDeviceType devType = AEDeviceTypeFromName(device); + std::string AESParams; /* digital interfaces should have AESx set, though in practice most * receivers don't care */ - if (m_passthrough || device.substr(0, 6) == "iec958" || device.substr(0, 4) == "hdmi") + if (m_passthrough || devType == AE_DEVTYPE_HDMI || devType == AE_DEVTYPE_IEC958) GetAESParams(format, AESParams); CLog::Log(LOGINFO, "CAESinkALSA::Initialize - Attempting to open device \"%s\"", device.c_str()); @@ -172,7 +174,7 @@ bool CAESinkALSA::Initialize(AEAudioFormat &format, std::string &device) /* Prefer dmix for non-passthrough stereo when sample rate matches */ - if (!OpenPCMDevice(device, AESParams, m_channelLayout.Count(), &m_pcm, config, format.m_sampleRate == dmixRate && !m_passthrough)) + if (!OpenPCMDevice(device, AESParams, m_channelLayout.Count(), &m_pcm, config, format.m_sampleRate == (unsigned int) dmixRate && !m_passthrough)) { CLog::Log(LOGERROR, "CAESinkALSA::Initialize - failed to initialize device \"%s\"", device.c_str()); snd_config_delete(config); @@ -718,17 +720,31 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list) if (strcmp(name, "front") != 0) EnumerateDevice(list, std::string("@") + (name+5), desc ? desc : name, config); } + + /* Do not enumerate "default", it is already enumerated above. */ + /* Do not enumerate the sysdefault or surroundXX devices, those are * always accompanied with a "front" device and it is handled above * as "@". The below devices will be automatically used if available * for a "@" device. */ + + /* Ubuntu has patched their alsa-lib so that "defaults.namehint.extended" + * defaults to "on" instead of upstream "off", causing lots of unwanted + * extra devices (many of which are not actually routed properly) to be + * found by the enumeration process. Skip them as well ("hw", "dmix", + * "plughw", "dsnoop"). */ + else if (baseName != "default" && baseName != "sysdefault" && baseName != "surround40" && baseName != "surround41" && baseName != "surround50" && baseName != "surround51" - && baseName != "surround71") + && baseName != "surround71" + && baseName != "hw" + && baseName != "dmix" + && baseName != "plughw" + && baseName != "dsnoop") { EnumerateDevice(list, name, desc ? desc : name, config); } @@ -768,10 +784,8 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list) && it1->m_displayNameExtra == it2->m_displayNameExtra) { /* something needs to be done */ - std::string cardString1; - std::string cardString2; - GetParamFromName(it1->m_deviceName, "CARD", cardString1); - GetParamFromName(it2->m_deviceName, "CARD", cardString2); + std::string cardString1 = GetParamFromName(it1->m_deviceName, "CARD"); + std::string cardString2 = GetParamFromName(it2->m_deviceName, "CARD"); if (cardString1 != cardString2) { @@ -781,10 +795,8 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list) continue; } - std::string devString1; - std::string devString2; - GetParamFromName(it1->m_deviceName, "DEV", devString1); - GetParamFromName(it2->m_deviceName, "DEV", devString2); + std::string devString1 = GetParamFromName(it1->m_deviceName, "DEV"); + std::string devString2 = GetParamFromName(it2->m_deviceName, "DEV"); if (devString1 != devString2) { @@ -794,9 +806,9 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list) continue; } - /* if we got here, the configuration is really weird, just give up */ - it1->m_displayName = it1->m_deviceName; - it2->m_displayName = it2->m_deviceName; + /* if we got here, the configuration is really weird, just append the whole device string */ + it1->m_displayName += " (" + it1->m_deviceName + ")"; + it2->m_displayName += " (" + it2->m_deviceName + ")"; } } } @@ -806,8 +818,7 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list) { for (AEDeviceInfoList::iterator itl = list.begin(); itl != list.end(); ++itl) { - std::string cardString; - GetParamFromName(itl->m_deviceName, "CARD", cardString); + std::string cardString = GetParamFromName(itl->m_deviceName, "CARD"); if (cardString == *it) /* "HDA NVidia (NVidia)", "HDA NVidia (NVidia_2)", ... */ itl->m_displayName += " (" + cardString + ")"; @@ -820,12 +831,10 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list) for (AEDeviceInfoList::iterator itl = list.begin(); itl != list.end(); ++itl) { std::string baseName = itl->m_deviceName.substr(0, itl->m_deviceName.find(':')); - std::string cardString; - GetParamFromName(itl->m_deviceName, "CARD", cardString); + std::string cardString = GetParamFromName(itl->m_deviceName, "CARD"); if (baseName == it->first && cardString == it->second) { - std::string devString; - GetParamFromName(itl->m_deviceName, "DEV", devString); + std::string devString = GetParamFromName(itl->m_deviceName, "DEV"); /* "HDMI #0", "HDMI #1" ... */ itl->m_displayNameExtra += " #" + devString; } @@ -833,19 +842,27 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list) } } -void CAESinkALSA::GetParamFromName(const std::string &name, const std::string ¶m, std::string &value) +AEDeviceType CAESinkALSA::AEDeviceTypeFromName(const std::string &name) +{ + if (name.substr(0, 4) == "hdmi") + return AE_DEVTYPE_HDMI; + else if (name.substr(0, 6) == "iec958" || name.substr(0, 5) == "spdif") + return AE_DEVTYPE_IEC958; + + return AE_DEVTYPE_PCM; +} + +std::string CAESinkALSA::GetParamFromName(const std::string &name, const std::string ¶m) { - /* name = "hdmi:CARD=x,DEV=y" param = "CARD" => value = "x" */ + /* name = "hdmi:CARD=x,DEV=y" param = "CARD" => return "x" */ size_t parPos = name.find(param + '='); if (parPos != std::string::npos) { parPos += param.size() + 1; - value = name.substr(parPos, name.find_first_of(",'\"", parPos)-parPos); - } - else - { - value = ""; + return name.substr(parPos, name.find_first_of(",'\"", parPos)-parPos); } + + return ""; } void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &device, const std::string &description, snd_config_t *config) @@ -869,16 +886,7 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev CAEDeviceInfo info; info.m_deviceName = device; - - bool isHDMI = (device.substr(0, 4) == "hdmi"); - bool isSPDIF = (device.substr(0, 6) == "iec958"); - - if (isHDMI) - info.m_deviceType = AE_DEVTYPE_HDMI; - else if (isSPDIF) - info.m_deviceType = AE_DEVTYPE_IEC958; - else - info.m_deviceType = AE_DEVTYPE_PCM; + info.m_deviceType = AEDeviceTypeFromName(device); if (cardNr >= 0) { @@ -887,7 +895,7 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev if (snd_card_get_name(cardNr, &cardName) == 0) info.m_displayName = cardName; - if (isHDMI && info.m_displayName.size() > 5 && + if (info.m_deviceType == AE_DEVTYPE_HDMI && info.m_displayName.size() > 5 && info.m_displayName.substr(info.m_displayName.size()-5) == " HDMI") { /* We already know this is HDMI, strip it */ @@ -904,7 +912,7 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev if (pcminfoName != "USB Audio") info.m_displayNameExtra = pcminfoName; - if (isHDMI) + if (info.m_deviceType == AE_DEVTYPE_HDMI) { /* replace, this was likely "HDMI 0" */ info.m_displayNameExtra = "HDMI"; @@ -936,10 +944,20 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev if (badHDMI) { - /* unconnected HDMI port */ - CLog::Log(LOGDEBUG, "CAESinkALSA - Skipping HDMI device \"%s\" as it has no ELD data", device.c_str()); - snd_pcm_close(pcmhandle); - return; + /* only trust badHDMI (= unconnected or non-existent port) on Intel + * and NVIDIA where it has been confirmed to work, show the empty + * port on other systems */ + if (info.m_displayName.compare(0, 9, "HDA Intel") == 0 || info.m_displayName.compare(0, 10, "HDA NVidia") == 0) + { + /* unconnected HDMI port */ + CLog::Log(LOGDEBUG, "CAESinkALSA - Skipping HDMI device \"%s\" as it has no ELD data", device.c_str()); + snd_pcm_close(pcmhandle); + return; + } + else + { + CLog::Log(LOGDEBUG, "CAESinkALSA - HDMI device \"%s\" may be unconnected (no ELD data)", device.c_str()); + } } } else @@ -949,7 +967,7 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev } } } - else if (isSPDIF) + else if (info.m_deviceType == AE_DEVTYPE_IEC958) { /* append instead of replace, pcminfoName is useful for S/PDIF */ if (!info.m_displayNameExtra.empty()) @@ -1091,7 +1109,8 @@ bool CAESinkALSA::GetELD(snd_hctl_t *hctl, int device, CAEDeviceInfo& info, bool return false; int dataLength = snd_ctl_elem_info_get_count(einfo); - /* if there is no ELD data, then its a bad HDMI device, either nothing attached OR an invalid nVidia HDMI device */ + /* if there is no ELD data, then its a bad HDMI device, either nothing attached OR an invalid nVidia HDMI device + * OR the driver doesn't properly support ELD (notably ATI/AMD, 2012-05) */ if (!dataLength) badHDMI = true; else diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h index 53cb479b7d..5b33deafe9 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h @@ -78,7 +78,8 @@ private: static bool TryDeviceWithParams(const std::string &name, const std::string ¶ms, snd_pcm_t **pcmp, snd_config_t *lconf); static bool OpenPCMDevice(const std::string &name, const std::string ¶ms, int channels, snd_pcm_t **pcmp, snd_config_t *lconf, bool preferDmixStereo = false); - static void GetParamFromName(const std::string &name, const std::string ¶m, std::string &value); + static AEDeviceType AEDeviceTypeFromName(const std::string &name); + static std::string GetParamFromName(const std::string &name, const std::string ¶m); static void EnumerateDevice(AEDeviceInfoList &list, const std::string &device, const std::string &description, snd_config_t *config); static bool SoundDeviceExists(const std::string& device); static bool GetELD(snd_hctl_t *hctl, int device, CAEDeviceInfo& info, bool& badHDMI); diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp new file mode 100644 index 0000000000..e79f282be4 --- /dev/null +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp @@ -0,0 +1,452 @@ + /* + * Copyright (C) 2010-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "AESinkAUDIOTRACK.h" +#include "Utils/AEUtil.h" +#include "Utils/AERingBuffer.h" +#include "android/activity/XBMCApp.h" +#include "utils/log.h" + +#include <jni.h> + +#if defined(__ARM_NEON__) +#include <arm_neon.h> +#include "utils/CPUInfo.h" +// LGPLv2 from PulseAudio +// float values from AE are pre-clamped so we do not need to clamp again here +static void pa_sconv_s16le_from_f32ne_neon(unsigned n, const float32_t *a, int16_t *b) +{ + unsigned int i; + + const float32x4_t half4 = vdupq_n_f32(0.5f); + const float32x4_t scale4 = vdupq_n_f32(32767.0f); + const uint32x4_t mask4 = vdupq_n_u32(0x80000000); + + for (i = 0; i < (n & ~3); i += 4) + { + const float32x4_t v4 = vmulq_f32(vld1q_f32(&a[i]), scale4); + const float32x4_t w4 = vreinterpretq_f32_u32( + vorrq_u32(vandq_u32(vreinterpretq_u32_f32(v4), mask4), vreinterpretq_u32_f32(half4))); + vst1_s16(&b[i], vmovn_s32(vcvtq_s32_f32(vaddq_f32(v4, w4)))); + } + // leftovers + for ( ; i < n; i++) + b[i] = (int16_t) lrintf(a[i] * 0x7FFF); +} +#endif + +#if defined(HAS_AMLPLAYER) +// yes this is nasty here but there is really no place else to do it. +static void aml_cpufreq_limit(bool limit) +{ + static int audiotrack_cputype = -1; + + if (audiotrack_cputype == -1) + { + // defualt to m1 SoC + audiotrack_cputype = 1; + + FILE *cpuinfo_fd = fopen("/proc/cpuinfo", "r"); + if (cpuinfo_fd) + { + char buffer[512]; + while (fgets(buffer, sizeof(buffer), cpuinfo_fd)) + { + std::string stdbuffer(buffer); + if (stdbuffer.find("MESON-M3") != std::string::npos) + { + audiotrack_cputype = 3; + CLog::Log(LOGDEBUG, "CAMLPlayer::GetCpuType is AMLOGIC MESON-M3"); + break; + } + } + fclose(cpuinfo_fd); + } + } + // On M1 SoCs, when playing hw decoded audio, we cannot drop below 600MHz + // or risk hw audio dropouts. AML code does a 2X scaling based off + // /sys/class/audiodsp/codec_mips but tests show that this is + // seems risky so we just clamp to 600Mhz to be safe. + if (audiotrack_cputype == 3) + return; + + int cpufreq; + if (limit) + cpufreq = 600000; + else + cpufreq = 300000; + + int fd = open("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", O_CREAT | O_RDWR | O_TRUNC, 0644); + if (fd >= 0) + { + char bcmd[16]; + sprintf(bcmd, "%d", cpufreq); + write(fd, bcmd, strlen(bcmd)); + close(fd); + } +} +#endif + +static jint GetStaticIntField(JNIEnv *jenv, std::string class_name, std::string field_name) +{ + class_name.insert(0, "android/media/"); + jclass cls = jenv->FindClass(class_name.c_str()); + jfieldID field = jenv->GetStaticFieldID(cls, field_name.c_str(), "I"); + jint int_field = jenv->GetStaticIntField(cls, field); + jenv->DeleteLocalRef(cls); + return int_field; +} + +CAEDeviceInfo CAESinkAUDIOTRACK::m_info; +//////////////////////////////////////////////////////////////////////////////////////////// +CAESinkAUDIOTRACK::CAESinkAUDIOTRACK() + : CThread("audiotrack") +{ + m_sinkbuffer = NULL; + m_alignedS16LE = NULL; +#if defined(HAS_AMLPLAYER) + aml_cpufreq_limit(true); +#endif +} + +CAESinkAUDIOTRACK::~CAESinkAUDIOTRACK() +{ +#if defined(HAS_AMLPLAYER) + aml_cpufreq_limit(false); +#endif +} + +bool CAESinkAUDIOTRACK::Initialize(AEAudioFormat &format, std::string &device) +{ + m_format = format; + + // default to 44100, all android devices support it. + // then check if we can support the requested rate. + unsigned int sampleRate = 44100; + for (size_t i = 0; i < m_info.m_sampleRates.size(); i++) + { + if (m_format.m_sampleRate == m_info.m_sampleRates[i]) + { + sampleRate = m_format.m_sampleRate; + break; + } + } + m_format.m_sampleRate = sampleRate; + + // default to AE_FMT_S16LE, + // then check if we can support the requested format. + AEDataFormat dataFormat = AE_FMT_S16LE; + for (size_t i = 0; i < m_info.m_dataFormats.size(); i++) + { + if (m_format.m_dataFormat == m_info.m_dataFormats[i]) + { + dataFormat = m_format.m_dataFormat; + break; + } + } + m_format.m_dataFormat = dataFormat; + + m_format.m_channelLayout = m_info.m_channels; + m_format.m_frameSize = format.m_channelLayout.Count() * (CAEUtil::DataFormatToBits(m_format.m_dataFormat) >> 3); + + m_draining = false; + m_volume_changed = false; + // launch the process thread and wait for the + // AutoTrack jni object to get created and setup. + m_wake.Reset(); + m_inited.Reset(); + Create(); + if(!m_inited.WaitMSec(100)) + { + while(!m_inited.WaitMSec(1)) + Sleep(10); + } + + // m_min_frames is volatile and has been setup by Process() + m_format.m_frames = m_min_frames; + m_format.m_frameSamples = m_format.m_frames * m_format.m_channelLayout.Count(); + format = m_format; + + return true; +} + +void CAESinkAUDIOTRACK::Deinitialize() +{ + // force m_bStop and set m_wake, if might be sleeping. + m_bStop = true; + m_wake.Set(); + StopThread(); + delete m_sinkbuffer, m_sinkbuffer = NULL; + if (m_alignedS16LE) + _aligned_free(m_alignedS16LE), m_alignedS16LE = NULL; +} + +bool CAESinkAUDIOTRACK::IsCompatible(const AEAudioFormat format, const std::string device) +{ + return ((m_format.m_sampleRate == format.m_sampleRate) && + (m_format.m_dataFormat == format.m_dataFormat) && + (m_format.m_channelLayout == format.m_channelLayout)); +} + +double CAESinkAUDIOTRACK::GetDelay() +{ + // this includes any latency due to AudioTrack buffer, + // AudioMixer (if any) and audio hardware driver. + + double sinkbuffer_seconds_to_empty = m_sinkbuffer_sec_per_byte * (double)m_sinkbuffer->GetReadSize(); + return sinkbuffer_seconds_to_empty + m_audiotrack_empty_sec; +} + +double CAESinkAUDIOTRACK::GetCacheTime() +{ + // returns the time in seconds that it will take + // to underrun the buffer if no sample is added. + + double sinkbuffer_seconds_to_empty = m_sinkbuffer_sec_per_byte * (double)m_sinkbuffer->GetReadSize(); + return sinkbuffer_seconds_to_empty + m_audiotrack_empty_sec; +} + +double CAESinkAUDIOTRACK::GetCacheTotal() +{ + // total amount that the audio sink can buffer in units of seconds + + return m_sinkbuffer_sec + m_audiotrackbuffer_sec; +} + +unsigned int CAESinkAUDIOTRACK::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio) +{ + // write as many frames of audio as we can fit into our internal buffer. + + // our internal sink buffer is always AE_FMT_S16LE + unsigned int write_frames = (m_sinkbuffer->GetWriteSize() / m_sink_frameSize) % frames; + if (hasAudio && write_frames) + { + switch(m_format.m_dataFormat) + { + case AE_FMT_S16LE: + m_sinkbuffer->Write(data, write_frames * m_sink_frameSize); + m_wake.Set(); + break; +#if defined(__ARM_NEON__) + case AE_FMT_FLOAT: + if (!m_alignedS16LE) + m_alignedS16LE = (int16_t*)_aligned_malloc(m_format.m_frames * m_sink_frameSize, 16); + // neon convert AE_FMT_S16LE to AE_FMT_FLOAT + pa_sconv_s16le_from_f32ne_neon(write_frames * m_format.m_channelLayout.Count(), (const float32_t *)data, m_alignedS16LE); + m_sinkbuffer->Write((unsigned char*)m_alignedS16LE, write_frames * m_sink_frameSize); + m_wake.Set(); + break; +#endif + default: + break; + } + } + // AddPackets runs under a non-idled AE thread we must block or sleep. + // Trying to calc the optimal sleep is tricky so just a minimal sleep. + Sleep(10); + + return hasAudio ? write_frames:frames; +} + +void CAESinkAUDIOTRACK::Drain() +{ + CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::Drain"); + m_draining = true; + m_wake.Set(); +} + +bool CAESinkAUDIOTRACK::HasVolume() +{ + return true; +} + +void CAESinkAUDIOTRACK::SetVolume(float volume) +{ + m_volume = volume; + m_volume_changed = true; +} + +void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list) +{ + m_info.m_channels.Reset(); + m_info.m_dataFormats.clear(); + m_info.m_sampleRates.clear(); + + m_info.m_deviceType = AE_DEVTYPE_PCM; + m_info.m_deviceName = "AudioTrack"; + m_info.m_displayName = "android"; + m_info.m_displayNameExtra = "audiotrack"; + m_info.m_channels += AE_CH_FL; + m_info.m_channels += AE_CH_FR; + m_info.m_sampleRates.push_back(44100); + m_info.m_sampleRates.push_back(48000); + m_info.m_dataFormats.push_back(AE_FMT_S16LE); +#if defined(__ARM_NEON__) + if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON) + m_info.m_dataFormats.push_back(AE_FMT_FLOAT); +#endif + + list.push_back(m_info); +} + +void CAESinkAUDIOTRACK::Process() +{ + CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::Process"); + + JNIEnv *jenv = NULL; + CXBMCApp::AttachCurrentThread(&jenv, NULL); + + jclass jcAudioTrack = jenv->FindClass("android/media/AudioTrack"); + + jmethodID jmInit = jenv->GetMethodID(jcAudioTrack, "<init>", "(IIIIII)V"); + jmethodID jmPlay = jenv->GetMethodID(jcAudioTrack, "play", "()V"); + jmethodID jmStop = jenv->GetMethodID(jcAudioTrack, "stop", "()V"); + jmethodID jmFlush = jenv->GetMethodID(jcAudioTrack, "flush", "()V"); + jmethodID jmRelease = jenv->GetMethodID(jcAudioTrack, "release", "()V"); + jmethodID jmWrite = jenv->GetMethodID(jcAudioTrack, "write", "([BII)I"); + jmethodID jmPlayState = jenv->GetMethodID(jcAudioTrack, "getPlayState", "()I"); + jmethodID jmSetStereoVolume = jenv->GetMethodID(jcAudioTrack, "setStereoVolume", "(FF)I"); + jmethodID jmPlayHeadPosition = jenv->GetMethodID(jcAudioTrack, "getPlaybackHeadPosition", "()I"); + jmethodID jmGetMinBufferSize = jenv->GetStaticMethodID(jcAudioTrack, "getMinBufferSize", "(III)I"); + + jint audioFormat = GetStaticIntField(jenv, "AudioFormat", "ENCODING_PCM_16BIT"); + jint channelConfig = GetStaticIntField(jenv, "AudioFormat", "CHANNEL_OUT_STEREO"); + + jint min_buffer_size = jenv->CallStaticIntMethod(jcAudioTrack, jmGetMinBufferSize, + m_format.m_sampleRate, channelConfig, audioFormat); + + m_sink_frameSize = m_format.m_channelLayout.Count() * CAEUtil::DataFormatToBits(AE_FMT_S16LE) >> 3; + m_min_frames = min_buffer_size / m_sink_frameSize; + + m_audiotrackbuffer_sec = (double)m_min_frames / (double)m_format.m_sampleRate; + m_audiotrack_empty_sec = 0.0; + + // setup a 1/4 second internal sink lockless ring buffer + m_sinkbuffer = new AERingBuffer(m_sink_frameSize * m_format.m_sampleRate / 4); + m_sinkbuffer_sec_per_byte = 1.0 / (double)(m_sink_frameSize * m_format.m_sampleRate); + m_sinkbuffer_sec = (double)m_sinkbuffer_sec_per_byte * m_sinkbuffer->GetMaxSize(); + + jobject joAudioTrack = jenv->NewObject(jcAudioTrack, jmInit, + GetStaticIntField(jenv, "AudioManager", "STREAM_MUSIC"), + m_format.m_sampleRate, + channelConfig, + audioFormat, + min_buffer_size, + GetStaticIntField(jenv, "AudioTrack", "MODE_STREAM")); + + // The AudioTrack object has been created and waiting to play, + m_inited.Set(); + // yield to give other threads a chance to do some work. + sched_yield(); + + // cache the playing int value. + jint playing = GetStaticIntField(jenv, "AudioTrack", "PLAYSTATE_PLAYING"); + + // create a java byte buffer for writing pcm data to AudioTrack. + jarray jbuffer = jenv->NewByteArray(min_buffer_size); + + int64_t frames_written = 0; + int64_t frame_position = 0; + + while (!m_bStop) + { + if (m_volume_changed) + { + // check of volume changes and make them, + // do it here to keep jni calls local to this thread. + jfloat jvolume = m_volume; + jenv->CallIntMethod(joAudioTrack, jmSetStereoVolume, jvolume, jvolume); + m_volume_changed = false; + } + if (m_draining) + { + unsigned char byte_drain[1024]; + unsigned int byte_drain_size = m_sinkbuffer->GetReadSize() % 1024; + while (byte_drain_size) + { + m_sinkbuffer->Read(byte_drain, byte_drain_size); + byte_drain_size = m_sinkbuffer->GetReadSize() % 1024; + } + jenv->CallVoidMethod(joAudioTrack, jmStop); + jenv->CallVoidMethod(joAudioTrack, jmFlush); + } + + unsigned int read_bytes = m_sinkbuffer->GetReadSize() % min_buffer_size; + if (read_bytes > 0) + { + // android will auto pause the playstate when it senses idle, + // check it and set playing if it does this. Do this before + // writing into its buffer. + if (jenv->CallIntMethod(joAudioTrack, jmPlayState) != playing) + jenv->CallVoidMethod(joAudioTrack, jmPlay); + + // Write a buffer of audio data to Java AudioTrack. + // Warning, no other JNI function can be called after + // GetPrimitiveArrayCritical until ReleasePrimitiveArrayCritical. + void *pBuffer = jenv->GetPrimitiveArrayCritical(jbuffer, NULL); + if (pBuffer) + { + m_sinkbuffer->Read((unsigned char*)pBuffer, read_bytes); + jenv->ReleasePrimitiveArrayCritical(jbuffer, pBuffer, 0); + // jmWrite is blocking and returns when the data has been transferred + // from the Java layer and queued for playback. + jenv->CallIntMethod(joAudioTrack, jmWrite, jbuffer, 0, read_bytes); + } + } + // calc the number of seconds until audiotrack buffer is empty. + frame_position = jenv->CallIntMethod(joAudioTrack, jmPlayHeadPosition); + if (frame_position == 0) + frames_written = 0; + frames_written += read_bytes / m_sink_frameSize; + m_audiotrack_empty_sec = (double)(frames_written - frame_position) / m_format.m_sampleRate; + // some times, we can get frame_position + // ahead of frames_written, not a clue why. clamp it. + if (m_audiotrack_empty_sec < 0.0f) + m_audiotrack_empty_sec = 0.0f; + + if (m_sinkbuffer->GetReadSize() == 0) + { + // the sink buffer is empty, stop playback. + // Audiotrack will playout any written contents. + jenv->CallVoidMethod(joAudioTrack, jmStop); + // sleep this audio thread, we will get woken when we have audio data. + m_wake.WaitMSec(250); + } + } + + jenv->CallVoidMethod(joAudioTrack, jmStop); + jenv->CallVoidMethod(joAudioTrack, jmFlush); + jenv->CallVoidMethod(joAudioTrack, jmRelease); + + // might toss an exception on jmRelease so catch it. + jthrowable exception = jenv->ExceptionOccurred(); + if (exception) + { + jenv->ExceptionDescribe(); + jenv->ExceptionClear(); + } + + jenv->DeleteLocalRef(jbuffer); + jenv->DeleteLocalRef(joAudioTrack); + jenv->DeleteLocalRef(jcAudioTrack); + + CXBMCApp::DetachCurrentThread(); +} diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h new file mode 100644 index 0000000000..bde98a2fb5 --- /dev/null +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h @@ -0,0 +1,68 @@ +#pragma once +/* + * Copyright (C) 2010-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Interfaces/AESink.h" +#include "Utils/AEDeviceInfo.h" + +class AERingBuffer; + +class CAESinkAUDIOTRACK : public CThread, public IAESink +{ +public: + virtual const char *GetName() { return "AUDIOTRACK"; } + + CAESinkAUDIOTRACK(); + virtual ~CAESinkAUDIOTRACK(); + + virtual bool Initialize(AEAudioFormat &format, std::string &device); + virtual void Deinitialize(); + virtual bool IsCompatible(const AEAudioFormat format, const std::string device); + + virtual double GetDelay (); + virtual double GetCacheTime (); + virtual double GetCacheTotal (); + virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); + virtual void Drain (); + virtual bool HasVolume (); + virtual void SetVolume (float volume); + static void EnumerateDevicesEx(AEDeviceInfoList &list); + +private: + virtual void Process(); + + static CAEDeviceInfo m_info; + AEAudioFormat m_format; + double m_volume; + bool m_volume_changed; + volatile int m_min_frames; + int16_t *m_alignedS16LE; + AERingBuffer *m_sinkbuffer; + unsigned int m_sink_frameSize; + double m_sinkbuffer_sec; + double m_sinkbuffer_sec_per_byte; + + CEvent m_wake; + CEvent m_inited; + volatile bool m_draining; + double m_audiotrackbuffer_sec; + double m_audiotrack_empty_sec; +}; diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp index e38d20cc3d..e9a6495b53 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp @@ -130,7 +130,7 @@ bool CAESinkDirectSound::Initialize(AEAudioFormat &format, std::string &device) LPGUID deviceGUID = NULL; RPC_CSTR wszUuid = NULL; - HRESULT hr; + HRESULT hr = E_FAIL; std::list<DSDevice> DSDeviceList; std::string deviceFriendlyName; DirectSoundEnumerate(DSEnumCallback, &DSDeviceList); @@ -588,13 +588,13 @@ void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) IAudioClient *pClient; hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pClient); if (FAILED(hr)) - { - CLog::Log(LOGERROR, __FUNCTION__": Activate device failed (%s)", WASAPIErrToStr(hr)); - } + { + CLog::Log(LOGERROR, __FUNCTION__": Activate device failed (%s)", WASAPIErrToStr(hr)); + } //hr = pClient->GetMixFormat(&pwfxex); hr = pProperty->GetValue(PKEY_AudioEngine_DeviceFormat, &varName); - if (SUCCEEDED(hr)) + if (SUCCEEDED(hr) && varName.blob.cbSize > 0) { WAVEFORMATEX* smpwfxex = (WAVEFORMATEX*)varName.blob.pBlobData; deviceInfo.m_channels = layoutsByChCount[std::min(smpwfxex->nChannels, (WORD) 2)]; @@ -604,7 +604,7 @@ void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) } else { - CLog::Log(LOGERROR, __FUNCTION__": GetMixFormat failed (%s)", WASAPIErrToStr(hr)); + CLog::Log(LOGERROR, __FUNCTION__": Getting DeviceFormat failed (%s)", WASAPIErrToStr(hr)); } pClient->Release(); @@ -644,8 +644,9 @@ void CAESinkDirectSound::CheckPlayStatus() if (!(status & DSBSTATUS_PLAYING) && m_CacheLen != 0) // If we have some data, see if we can start playback { HRESULT hr = m_pBuffer->Play(0, 0, DSBPLAY_LOOPING); - dserr2str(hr); CLog::Log(LOGDEBUG,__FUNCTION__ ": Resuming Playback"); + if (FAILED(hr)) + CLog::Log(LOGERROR, __FUNCTION__": Failed to play the DirectSound buffer: %s", dserr2str(hr)); } } diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkNULL.h b/xbmc/cores/AudioEngine/Sinks/AESinkNULL.h index 20b7cc5582..a012593c80 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkNULL.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkNULL.h @@ -42,6 +42,7 @@ public: virtual double GetCacheTotal () { return 0.0; } virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); virtual void Drain (); + static void EnumerateDevices(AEDeviceList &devices, bool passthrough); private: int64_t m_ts; diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp index b94e6e8794..c45ceedc7a 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp @@ -332,22 +332,26 @@ bool CAESinkWASAPI::IsCompatible(const AEAudioFormat format, const std::string d double CAESinkWASAPI::GetDelay() { - return GetCacheTime(); + if (!m_initialized) + return 0.0; + + return m_sinkLatency; } double CAESinkWASAPI::GetCacheTime() { + /* This function deviates from the defined usage due to the event-driven */ + /* mode of WASAPI utilizing twin buffers which are written to in single */ + /* buffer chunks. Therefore the buffers are either 100% full or 50% full */ + /* At 50% issues arise with water levels in the stream and player. For */ + /* this reason the cache is shown as 100% full at all times, and control */ + /* of the buffer filling is assumed in AddPackets() and by the WASAPI */ + /* implementation of the WaitforSingleObject event indicating one of the */ + /* buffers is ready for filling via AddPackets */ if (!m_initialized) return 0.0; - unsigned int numPaddingFrames; - HRESULT hr = m_pAudioClient->GetCurrentPadding(&numPaddingFrames); - if (FAILED(hr)) - { - CLog::Log(LOGERROR, __FUNCTION__": GetCurrentPadding Failed : %s", WASAPIErrToStr(hr)); - return 0.0; - } - return (double)numPaddingFrames / (double)m_format.m_sampleRate; + return m_sinkLatency; } double CAESinkWASAPI::GetCacheTotal() @@ -355,11 +359,7 @@ double CAESinkWASAPI::GetCacheTotal() if (!m_initialized) return 0.0; - REFERENCE_TIME hnsLatency; - HRESULT hr = m_pAudioClient->GetStreamLatency(&hnsLatency); - - /** returns buffer duration in seconds */ - return hnsLatency / 10.0; + return m_sinkLatency; } unsigned int CAESinkWASAPI::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio) @@ -1084,7 +1084,15 @@ initialize: CLog::Log(LOGERROR, __FUNCTION__": Unable to initialize WASAPI in exclusive mode %d - (%s).", HRESULT(hr), WASAPIErrToStr(hr)); return false; } + + /* Latency of WASAPI buffers in event-driven mode is equal to the returned value */ + /* of GetStreamLatency converted from 100ns intervals to seconds then multiplied */ + /* by two as there are two equally-sized buffers and playback starts when the */ + /* second buffer is filled. Multiplying the returned 100ns intervals by 0.0000002*/ + /* is handles both the unit conversion and twin buffers. */ hr = m_pAudioClient->GetStreamLatency(&hnsLatency); + m_sinkLatency = hnsLatency * 0.0000002; + CLog::Log(LOGDEBUG, __FUNCTION__": Requested Duration of Buffer : %fmsec", hnsLatency / 10000.0); CLog::Log(LOGNOTICE, __FUNCTION__": WASAPI Exclusive Mode Sink Initialized Successfully!!!"); return true; diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h index 3f046027a2..19efd0f14e 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h @@ -75,4 +75,5 @@ private: unsigned int m_uiBufferLen; /* wasapi endpoint buffer size, in frames */ double m_avgTimeWaiting; /* time between next buffer of data from SoftAE and driver call for data */ + double m_sinkLatency; /* time in seconds of total duration of the two WASAPI buffers */ };
\ No newline at end of file diff --git a/xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.cpp b/xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.cpp index 17b94404a1..13043cae56 100644 --- a/xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.cpp @@ -58,6 +58,7 @@ void CAEBitstreamPacker::Pack(CAEStreamInfo &info, uint8_t* data, int size) PackDTSHD (info, data, size); break; + case CAEStreamInfo::STREAM_TYPE_DTSHD_CORE: case CAEStreamInfo::STREAM_TYPE_DTS_512: m_dataSize = CAEPackIEC61937::PackDTS_512(data, size, m_packedBuffer, info.IsLittleEndian()); break; diff --git a/xbmc/cores/AudioEngine/Utils/AEBuffer.h b/xbmc/cores/AudioEngine/Utils/AEBuffer.h index 6f22db6027..8c1d3f39e1 100644 --- a/xbmc/cores/AudioEngine/Utils/AEBuffer.h +++ b/xbmc/cores/AudioEngine/Utils/AEBuffer.h @@ -132,7 +132,10 @@ public: #endif if (dst) memcpy(dst, m_buffer, size); - memmove(m_buffer, m_buffer + size, m_bufferSize - size); + // we can just reset m_bufferPos + // if there is nothing else inside. + if (m_bufferPos != size) + memmove(m_buffer, m_buffer + size, m_bufferSize - size); m_bufferPos -= size; } diff --git a/xbmc/cores/AudioEngine/Utils/AEConvert.cpp b/xbmc/cores/AudioEngine/Utils/AEConvert.cpp index 980f2b94e3..21724435a9 100644 --- a/xbmc/cores/AudioEngine/Utils/AEConvert.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEConvert.cpp @@ -89,8 +89,13 @@ CAEConvert::AEConvertToFn CAEConvert::ToFloat(enum AEDataFormat dataFormat) case AE_FMT_S24BE4: return &S24BE4_Float; case AE_FMT_S24LE3: return &S24LE3_Float; case AE_FMT_S24BE3: return &S24BE3_Float; +#if defined(__ARM_NEON__) + case AE_FMT_S32LE : return &S32LE_Float_Neon; + case AE_FMT_S32BE : return &S32BE_Float_Neon; +#else case AE_FMT_S32LE : return &S32LE_Float; case AE_FMT_S32BE : return &S32BE_Float; +#endif case AE_FMT_DOUBLE: return &DOUBLE_Float; default: return NULL; @@ -114,8 +119,13 @@ CAEConvert::AEConvertFrFn CAEConvert::FrFloat(enum AEDataFormat dataFormat) case AE_FMT_S16BE : return &Float_S16BE; case AE_FMT_S24NE4: return &Float_S24NE4; case AE_FMT_S24NE3: return &Float_S24NE3; +#if defined(__ARM_NEON__) + case AE_FMT_S32LE : return &Float_S32LE_Neon; + case AE_FMT_S32BE : return &Float_S32BE_Neon; +#else case AE_FMT_S32LE : return &Float_S32LE; case AE_FMT_S32BE : return &Float_S32BE; +#endif case AE_FMT_DOUBLE: return &Float_DOUBLE; default: return NULL; @@ -126,8 +136,8 @@ unsigned int CAEConvert::U8_Float(uint8_t *data, const unsigned int samples, flo { const float mul = 2.0f / UINT8_MAX; - for (unsigned int i = 0; i < samples; ++i, ++data, ++dest) - *dest = *(uint8_t*)data * mul - 1.0f; + for (unsigned int i = 0; i < samples; ++i) + *dest++ = *data++ * mul - 1.0f; return samples; } @@ -136,8 +146,8 @@ unsigned int CAEConvert::S8_Float(uint8_t *data, const unsigned int samples, flo { const float mul = 1.0f / (INT8_MAX + 0.5f); - for (unsigned int i = 0; i < samples; ++i, ++data, ++dest) - *dest = *(int8_t*)data * mul; + for (unsigned int i = 0; i < samples; ++i) + *dest++ = *data++ * mul; return samples; } @@ -147,7 +157,7 @@ unsigned int CAEConvert::S16LE_Float(uint8_t* data, const unsigned int samples, static const float mul = 1.0f / (INT16_MAX + 0.5f); #ifdef __arm__ - for (int i = 0; i < samples; i++) + for (unsigned int i = 0; i < samples; i++) { __asm__ __volatile__ ( "ldrsh r1,[%[in]] \n\t" // Read a halfword from the source address @@ -166,8 +176,8 @@ unsigned int CAEConvert::S16LE_Float(uint8_t* data, const unsigned int samples, dest++; } #else - for (unsigned int i = 0; i < samples; ++i, data += 2, ++dest) - *dest = Endian_SwapLE16(*(int16_t*)data) * mul; + for (unsigned int i = 0; i < samples; ++i, data += 2) + *dest++ = Endian_SwapLE16(*(int16_t*)data) * mul; #endif return samples; @@ -178,7 +188,7 @@ unsigned int CAEConvert::S16BE_Float(uint8_t* data, const unsigned int samples, static const float mul = 1.0f / (INT16_MAX + 0.5f); #ifdef __arm__ - for (int i = 0; i < samples; i++) + for (unsigned int i = 0; i < samples; i++) { __asm__ __volatile__ ( "ldrsh r1,[%[in]] \n\t" // Read a halfword from the source address @@ -197,8 +207,8 @@ unsigned int CAEConvert::S16BE_Float(uint8_t* data, const unsigned int samples, dest++; } #else - for (unsigned int i = 0; i < samples; ++i, data += 2, ++dest) - *dest = Endian_SwapBE16(*(int16_t*)data) * mul; + for (unsigned int i = 0; i < samples; ++i, data += 2) + *dest++ = Endian_SwapBE16(*(int16_t*)data) * mul; #endif return samples; @@ -206,40 +216,40 @@ unsigned int CAEConvert::S16BE_Float(uint8_t* data, const unsigned int samples, unsigned int CAEConvert::S24LE4_Float(uint8_t *data, const unsigned int samples, float *dest) { - for (unsigned int i = 0; i < samples; ++i, ++dest, data += 4) + for (unsigned int i = 0; i < samples; ++i, data += 4) { int s = (data[2] << 24) | (data[1] << 16) | (data[0] << 8); - *dest = (float)s * INT32_SCALE; + *dest++ = (float)s * INT32_SCALE; } return samples; } unsigned int CAEConvert::S24BE4_Float(uint8_t *data, const unsigned int samples, float *dest) { - for (unsigned int i = 0; i < samples; ++i, ++dest, data += 4) + for (unsigned int i = 0; i < samples; ++i, data += 4) { int s = (data[0] << 24) | (data[1] << 16) | (data[2] << 8); - *dest = (float)s * INT32_SCALE; + *dest++ = (float)s * INT32_SCALE; } return samples; } unsigned int CAEConvert::S24LE3_Float(uint8_t *data, const unsigned int samples, float *dest) { - for (unsigned int i = 0; i < samples; ++i, ++dest, data += 3) + for (unsigned int i = 0; i < samples; ++i, data += 3) { int s = (data[2] << 24) | (data[1] << 16) | (data[0] << 8); - *dest = (float)s * INT32_SCALE; + *dest++ = (float)s * INT32_SCALE; } return samples; } unsigned int CAEConvert::S24BE3_Float(uint8_t *data, const unsigned int samples, float *dest) { - for (unsigned int i = 0; i < samples; ++i, ++dest, data += 3) + for (unsigned int i = 0; i < samples; ++i, data += 3) { int s = (data[1] << 24) | (data[2] << 16) | (data[3] << 8); - *dest = (float)s * INT32_SCALE; + *dest++ = (float)s * INT32_SCALE; } return samples; } @@ -249,7 +259,27 @@ unsigned int CAEConvert::S32LE_Float(uint8_t *data, const unsigned int samples, static const float factor = 1.0f / (float)INT32_MAX; int32_t *src = (int32_t*)data; + /* do this in groups of 4 to give the compiler a better chance of optimizing this */ + for (float *end = dest + (samples & ~0x3); dest < end;) + { + *dest++ = (float)Endian_SwapLE32(*src++) * factor; + *dest++ = (float)Endian_SwapLE32(*src++) * factor; + *dest++ = (float)Endian_SwapLE32(*src++) * factor; + *dest++ = (float)Endian_SwapLE32(*src++) * factor; + } + + /* process any remaining samples */ + for (float *end = dest + (samples & 0x3); dest < end;) + *dest++ = (float)Endian_SwapLE32(*src++) * factor; + + return samples; +} + +unsigned int CAEConvert::S32LE_Float_Neon(uint8_t *data, const unsigned int samples, float *dest) +{ #if defined(__ARM_NEON__) + static const float factor = 1.0f / (float)INT32_MAX; + int32_t *src = (int32_t*)data; /* groups of 4 samples */ for (float *end = dest + (samples & ~0x3); dest < end; src += 4, dest += 4) @@ -259,7 +289,7 @@ unsigned int CAEConvert::S32LE_Float(uint8_t *data, const unsigned int samples, val = vrev64q_s32(val); #endif float32x4_t ret = vmulq_n_f32(vcvtq_f32_s32(val), factor); - vst1q_f32((float32_t *)dest, ret); + vst1q_f32((float32_t*)dest, ret); } /* if there are >= 2 remaining samples */ @@ -279,33 +309,37 @@ unsigned int CAEConvert::S32LE_Float(uint8_t *data, const unsigned int samples, if (samples & 0x1) dest[0] = (float)src[0] * factor; -#else /* !defined(__ARM_NEON__) */ +#endif /* !defined(__ARM_NEON__) */ + return samples; +} + +unsigned int CAEConvert::S32BE_Float(uint8_t *data, const unsigned int samples, float *dest) +{ + static const float factor = 1.0f / (float)INT32_MAX; + int32_t *src = (int32_t*)data; /* do this in groups of 4 to give the compiler a better chance of optimizing this */ - for (float *end = dest + (samples & ~0x3); dest < end; src += 4, dest += 4) + for (float *end = dest + (samples & ~0x3); dest < end;) { - dest[0] = (float)Endian_SwapLE32(src[0]) * factor; - dest[1] = (float)Endian_SwapLE32(src[1]) * factor; - dest[2] = (float)Endian_SwapLE32(src[2]) * factor; - dest[3] = (float)Endian_SwapLE32(src[3]) * factor; + *dest++ = (float)Endian_SwapBE32(*src++) * factor; + *dest++ = (float)Endian_SwapBE32(*src++) * factor; + *dest++ = (float)Endian_SwapBE32(*src++) * factor; + *dest++ = (float)Endian_SwapBE32(*src++) * factor; } /* process any remaining samples */ - for (float *end = dest + (samples & 0x3); dest < end; ++src, ++dest) - dest[0] = (float)Endian_SwapLE32(src[0]) * factor; - -#endif + for (float *end = dest + (samples & 0x3); dest < end;) + *dest++ = (float)Endian_SwapBE32(*src++) * factor; return samples; } -unsigned int CAEConvert::S32BE_Float(uint8_t *data, const unsigned int samples, float *dest) +unsigned int CAEConvert::S32BE_Float_Neon(uint8_t *data, const unsigned int samples, float *dest) { +#if defined(__ARM_NEON__) static const float factor = 1.0f / (float)INT32_MAX; int32_t *src = (int32_t*)data; -#if defined(__ARM_NEON__) - /* groups of 4 samples */ for (float *end = dest + (samples & ~0x3); dest < end; src += 4, dest += 4) { @@ -334,31 +368,15 @@ unsigned int CAEConvert::S32BE_Float(uint8_t *data, const unsigned int samples, if (samples & 0x1) dest[0] = (float)src[0] * factor; -#else /* !defined(__ARM_NEON__) */ - - /* do this in groups of 4 to give the compiler a better chance of optimizing this */ - for (float *end = dest + (samples & ~0x3); dest < end; src += 4, dest += 4) - { - dest[0] = (float)Endian_SwapBE32(src[0]) * factor; - dest[1] = (float)Endian_SwapBE32(src[1]) * factor; - dest[2] = (float)Endian_SwapBE32(src[2]) * factor; - dest[3] = (float)Endian_SwapBE32(src[3]) * factor; - } - - /* process any remaining samples */ - for (float *end = dest + (samples & 0x3); dest < end; ++src, ++dest) - dest[0] = (float)Endian_SwapBE32(src[0]) * factor; - -#endif - +#endif /* !defined(__ARM_NEON__) */ return samples; } unsigned int CAEConvert::DOUBLE_Float(uint8_t *data, const unsigned int samples, float *dest) { double *src = (double*)data; - for (unsigned int i = 0; i < samples; ++i, ++src, ++dest) - *dest = CLAMP(*src / (float)INT32_MAX); + for (unsigned int i = 0; i < samples; ++i) + *dest++ = CLAMP(*src++ / (float)INT32_MAX); return samples; } @@ -380,17 +398,17 @@ unsigned int CAEConvert::Float_U8(float *data, const unsigned int samples, uint8 } const uint32_t even = count & ~0x3; - for (uint32_t i = 0; i < even; i += 4, data += 4, dest += 4) + for (uint32_t i = 0; i < even; i += 4, data += 4) { __m128 in = _mm_mul_ps(_mm_add_ps(_mm_load_ps(data), add), mul); __m64 con = _mm_cvtps_pi16(in); int16_t temp[4]; memcpy(temp, &con, sizeof(temp)); - dest[0] = (uint8_t)temp[0]; - dest[1] = (uint8_t)temp[1]; - dest[2] = (uint8_t)temp[2]; - dest[3] = (uint8_t)temp[3]; + *dest++ = (uint8_t)temp[0]; + *dest++ = (uint8_t)temp[1]; + *dest++ = (uint8_t)temp[2]; + *dest++ = (uint8_t)temp[3]; } if (count != even) @@ -431,8 +449,8 @@ unsigned int CAEConvert::Float_U8(float *data, const unsigned int samples, uint8 } _mm_empty(); #else /* no SSE */ - for (uint32_t i = 0; i < samples; ++i, ++data, ++dest) - dest[0] = safeRound((data[0] + 1.0f) * ((float)INT8_MAX+.5f)); + for (uint32_t i = 0; i < samples; ++i) + *dest++ = safeRound((*data++ + 1.0f) * ((float)INT8_MAX+.5f)); #endif return samples; @@ -490,8 +508,8 @@ unsigned int CAEConvert::Float_S8(float *data, const unsigned int samples, uint8 } _mm_empty(); #else /* no SSE */ - for (uint32_t i = 0; i < samples; ++i, ++data, ++dest) - dest[0] = safeRound(data[0] * ((float)INT8_MAX+.5f)); + for (uint32_t i = 0; i < samples; ++i) + *dest++ = safeRound(*data++ * ((float)INT8_MAX+.5f)); #endif return samples; @@ -611,20 +629,20 @@ unsigned int CAEConvert::Float_S16LE(float *data, const unsigned int samples, ui uint32_t i = 0; uint32_t even = samples & ~0x3; - for(; i < even; i += 4, data += 4, dst += 4) + for(; i < even; i += 4) { /* random round to dither */ float rand[4]; CAEUtil::FloatRand4(-0.5f, 0.5f, rand); - dst[0] = Endian_SwapLE16(safeRound(data[0] * ((float)INT16_MAX + rand[0]))); - dst[1] = Endian_SwapLE16(safeRound(data[1] * ((float)INT16_MAX + rand[1]))); - dst[2] = Endian_SwapLE16(safeRound(data[2] * ((float)INT16_MAX + rand[2]))); - dst[3] = Endian_SwapLE16(safeRound(data[3] * ((float)INT16_MAX + rand[3]))); + *dst++ = Endian_SwapLE16(safeRound(*data++ * ((float)INT16_MAX + rand[0]))); + *dst++ = Endian_SwapLE16(safeRound(*data++ * ((float)INT16_MAX + rand[1]))); + *dst++ = Endian_SwapLE16(safeRound(*data++ * ((float)INT16_MAX + rand[2]))); + *dst++ = Endian_SwapLE16(safeRound(*data++ * ((float)INT16_MAX + rand[3]))); } - for(; i < samples; ++i, ++data, ++dst) - dst[0] = Endian_SwapLE16(safeRound(data[0] * ((float)INT16_MAX + CAEUtil::FloatRand1(-0.5f, 0.5f)))); + for(; i < samples; ++i) + *dst++ = Endian_SwapLE16(safeRound(*data++ * ((float)INT16_MAX + CAEUtil::FloatRand1(-0.5f, 0.5f)))); #endif @@ -745,20 +763,20 @@ unsigned int CAEConvert::Float_S16BE(float *data, const unsigned int samples, ui uint32_t i = 0; uint32_t even = samples & ~0x3; - for(; i < even; i += 4, data += 4, dst += 4) + for(; i < even; i += 4) { /* random round to dither */ float rand[4]; CAEUtil::FloatRand4(-0.5f, 0.5f, rand); - dst[0] = Endian_SwapBE16(safeRound(data[0] * ((float)INT16_MAX + rand[0]))); - dst[1] = Endian_SwapBE16(safeRound(data[1] * ((float)INT16_MAX + rand[1]))); - dst[2] = Endian_SwapBE16(safeRound(data[2] * ((float)INT16_MAX + rand[2]))); - dst[3] = Endian_SwapBE16(safeRound(data[3] * ((float)INT16_MAX + rand[3]))); + *dst++ = Endian_SwapBE16(safeRound(*data++ * ((float)INT16_MAX + rand[0]))); + *dst++ = Endian_SwapBE16(safeRound(*data++ * ((float)INT16_MAX + rand[1]))); + *dst++ = Endian_SwapBE16(safeRound(*data++ * ((float)INT16_MAX + rand[2]))); + *dst++ = Endian_SwapBE16(safeRound(*data++ * ((float)INT16_MAX + rand[3]))); } - for(; i < samples; ++i, ++data, ++dst) - dst[0] = Endian_SwapBE16(safeRound(data[0] * ((float)INT16_MAX + CAEUtil::FloatRand1(-0.5f, 0.5f)))); + for(; i < samples; ++i, data++, dst++) + *dst++ = Endian_SwapBE16(safeRound(*data++ * ((float)INT16_MAX + CAEUtil::FloatRand1(-0.5f, 0.5f)))); #endif @@ -819,8 +837,8 @@ unsigned int CAEConvert::Float_S24NE4(float *data, const unsigned int samples, u } _mm_empty(); #else /* no SSE */ - for (uint32_t i = 0; i < samples; ++i, ++data, ++dst) - *dst = (safeRound(*data * ((float)INT24_MAX+.5f)) & 0xFFFFFF) << 8; + for (uint32_t i = 0; i < samples; ++i) + *dst++ = (safeRound(*data++ * ((float)INT24_MAX+.5f)) & 0xFFFFFF) << 8; #endif return samples << 2; @@ -966,9 +984,23 @@ unsigned int CAEConvert::Float_S32LE(float *data, const unsigned int samples, ui } } _mm_empty(); + #else + + /* no SIMD */ + for (uint32_t i = 0; i < samples; ++i, ++data, ++dst) + { + dst[0] = safeRound(data[0] * (float)INT32_MAX); + dst[0] = Endian_SwapLE32(dst[0]); + } + #endif + return samples << 2; +} - #elif defined(__ARM_NEON__) +unsigned int CAEConvert::Float_S32LE_Neon(float *data, const unsigned int samples, uint8_t *dest) +{ +#if defined(__ARM_NEON__) + int32_t *dst = (int32_t*)dest; for (float *end = data + (samples & ~0x3); data < end; data += 4, dst += 4) { float32x4_t val = vmulq_n_f32(vld1q_f32((const float32_t *)data), INT32_MAX); @@ -996,17 +1028,7 @@ unsigned int CAEConvert::Float_S32LE(float *data, const unsigned int samples, ui dst[0] = safeRound(data[0] * (float)INT32_MAX); dst[0] = Endian_SwapLE32(dst[0]); } - - #else - - /* no SIMD */ - for (uint32_t i = 0; i < samples; ++i, ++data, ++dst) - { - dst[0] = safeRound(data[0] * (float)INT32_MAX); - dst[0] = Endian_SwapLE32(dst[0]); - } - #endif - +#endif return samples << 2; } @@ -1071,9 +1093,22 @@ unsigned int CAEConvert::Float_S32BE(float *data, const unsigned int samples, ui } } _mm_empty(); + #else + /* no SIMD */ + for (uint32_t i = 0; i < samples; ++i, ++data, ++dst) + { + dst[0] = safeRound(data[0] * (float)INT32_MAX); + dst[0] = Endian_SwapBE32(dst[0]); + } + #endif - #elif defined(__ARM_NEON__) + return samples << 2; +} +unsigned int CAEConvert::Float_S32BE_Neon(float *data, const unsigned int samples, uint8_t *dest) +{ +#if defined(__ARM_NEON__) + int32_t *dst = (int32_t*)dest; for (float *end = data + (samples & ~0x3); data < end; data += 4, dst += 4) { float32x4_t val = vmulq_n_f32(vld1q_f32((const float32_t *)data), INT32_MAX); @@ -1101,25 +1136,15 @@ unsigned int CAEConvert::Float_S32BE(float *data, const unsigned int samples, ui dst[0] = safeRound(data[0] * (float)INT32_MAX); dst[0] = Endian_SwapBE32(dst[0]); } - - #else - - /* no SIMD */ - for (uint32_t i = 0; i < samples; ++i, ++data, ++dst) - { - dst[0] = safeRound(data[0] * (float)INT32_MAX); - dst[0] = Endian_SwapBE32(dst[0]); - } - #endif - +#endif return samples << 2; } unsigned int CAEConvert::Float_DOUBLE(float *data, const unsigned int samples, uint8_t *dest) { double *dst = (double*)dest; - for (unsigned int i = 0; i < samples; ++i, ++data, ++dst) - *dst = *data; + for (unsigned int i = 0; i < samples; ++i) + *dst++ = *data++; return samples * sizeof(double); } diff --git a/xbmc/cores/AudioEngine/Utils/AEConvert.h b/xbmc/cores/AudioEngine/Utils/AEConvert.h index 49fd6b8bfe..6cb231fc7f 100644 --- a/xbmc/cores/AudioEngine/Utils/AEConvert.h +++ b/xbmc/cores/AudioEngine/Utils/AEConvert.h @@ -46,6 +46,12 @@ private: static unsigned int Float_S32LE (float *data, const unsigned int samples, uint8_t *dest); static unsigned int Float_S32BE (float *data, const unsigned int samples, uint8_t *dest); static unsigned int Float_DOUBLE(float *data, const unsigned int samples, uint8_t *dest); + + static unsigned int S32LE_Float_Neon (uint8_t *data, const unsigned int samples, float *dest); + static unsigned int S32BE_Float_Neon (uint8_t *data, const unsigned int samples, float *dest); + static unsigned int Float_S32LE_Neon (float *data, const unsigned int samples, uint8_t *dest); + static unsigned int Float_S32BE_Neon (float *data, const unsigned int samples, uint8_t *dest); + public: typedef unsigned int (*AEConvertToFn)(uint8_t *data, const unsigned int samples, float *dest); typedef unsigned int (*AEConvertFrFn)(float *data, const unsigned int samples, uint8_t *dest); diff --git a/xbmc/cores/AudioEngine/Utils/AEPackIEC61937.h b/xbmc/cores/AudioEngine/Utils/AEPackIEC61937.h index b6041276aa..181975c116 100644 --- a/xbmc/cores/AudioEngine/Utils/AEPackIEC61937.h +++ b/xbmc/cores/AudioEngine/Utils/AEPackIEC61937.h @@ -23,14 +23,6 @@ #include <stdint.h> #include <list> -#ifdef __GNUC__ - #define S_PACK __attribute__((__packed__)) - #define E_PACK -#else - #define S_PACK __pragma(pack(push, 1)) - #define E_PACK __pragma(pack(pop)) -#endif - #define MAX_IEC61937_PACKET 61440 #define IEC61937_DATA_OFFSET 8 @@ -74,8 +66,12 @@ private: IEC61937_TYPE_TRUEHD = 0x16 }; - S_PACK +#ifdef __GNUC__ + struct __attribute__((__packed__)) IEC61937Packet +#else + __pragma(pack(push, 1)) struct IEC61937Packet +#endif { uint16_t m_preamble1; uint16_t m_preamble2; @@ -83,6 +79,8 @@ private: uint16_t m_length; uint8_t m_data[MAX_IEC61937_PACKET - IEC61937_DATA_OFFSET]; }; - E_PACK +#ifndef __GNUC__ + __pragma(pack(pop)) +#endif }; diff --git a/xbmc/cores/AudioEngine/Utils/AERemap.cpp b/xbmc/cores/AudioEngine/Utils/AERemap.cpp index d6b7f277df..d3732face7 100644 --- a/xbmc/cores/AudioEngine/Utils/AERemap.cpp +++ b/xbmc/cores/AudioEngine/Utils/AERemap.cpp @@ -290,19 +290,20 @@ void CAERemap::Remap(float * const in, float * const out, const unsigned int fra if (!info->in_dst) { unsigned int f = 0; + unsigned int odx = 0; for(; f < frameBlocks; f += 4) { - out[((f + 0) * m_outChannels) + o] = 0.0f; - out[((f + 1) * m_outChannels) + o] = 0.0f; - out[((f + 2) * m_outChannels) + o] = 0.0f; - out[((f + 3) * m_outChannels) + o] = 0.0f; + out[odx + o] = 0.0f, odx += m_outChannels; + out[odx + o] = 0.0f, odx += m_outChannels; + out[odx + o] = 0.0f, odx += m_outChannels; + out[odx + o] = 0.0f, odx += m_outChannels; } switch (frames & 0x3) { - case 3: out[(f * m_outChannels) + o] = 0.0f; ++f; - case 2: out[(f * m_outChannels) + o] = 0.0f; ++f; - case 1: out[(f * m_outChannels) + o] = 0.0f; + case 3: out[odx + o] = 0.0f, odx += m_outChannels; + case 2: out[odx + o] = 0.0f, odx += m_outChannels; + case 1: out[odx + o] = 0.0f; } continue; } @@ -311,20 +312,23 @@ void CAERemap::Remap(float * const in, float * const out, const unsigned int fra if (info->srcCount == 1) { unsigned int f = 0; + unsigned int idx = 0; + unsigned int odx = 0; + unsigned int srcIndex = info->srcIndex[0].index; /* the compiler has a better chance of optimizing this if it is done in parallel */ for (; f < frameBlocks; f += 4) { - out[((f + 0) * m_outChannels) + o] = in[((f + 0) * m_inChannels) + info->srcIndex[0].index]; - out[((f + 1) * m_outChannels) + o] = in[((f + 1) * m_inChannels) + info->srcIndex[0].index]; - out[((f + 2) * m_outChannels) + o] = in[((f + 2) * m_inChannels) + info->srcIndex[0].index]; - out[((f + 3) * m_outChannels) + o] = in[((f + 3) * m_inChannels) + info->srcIndex[0].index]; + out[odx + o] = in[idx + srcIndex], idx += m_inChannels, odx += m_outChannels; + out[odx + o] = in[idx + srcIndex], idx += m_inChannels, odx += m_outChannels; + out[odx + o] = in[idx + srcIndex], idx += m_inChannels, odx += m_outChannels; + out[odx + o] = in[idx + srcIndex], idx += m_inChannels, odx += m_outChannels; } switch (frames & 0x3) { - case 3: out[(f * m_outChannels) + o] = in[(f * m_inChannels) + info->srcIndex[0].index]; ++f; - case 2: out[(f * m_outChannels) + o] = in[(f * m_inChannels) + info->srcIndex[0].index]; ++f; - case 1: out[(f * m_outChannels) + o] = in[(f * m_inChannels) + info->srcIndex[0].index]; + case 3: out[odx + o] = in[idx + srcIndex], idx += m_inChannels, odx += m_outChannels; + case 2: out[odx + o] = in[idx + srcIndex], idx += m_inChannels, odx += m_outChannels; + case 1: out[odx + o] = in[idx + srcIndex]; } } else @@ -341,17 +345,17 @@ void CAERemap::Remap(float * const in, float * const out, const unsigned int fra int i = 0; for (; i < blocks; i += 4) { - *outOffset += inOffset[info->srcIndex[i + 0].index] * info->srcIndex[i + 0].level; - *outOffset += inOffset[info->srcIndex[i + 1].index] * info->srcIndex[i + 1].level; - *outOffset += inOffset[info->srcIndex[i + 2].index] * info->srcIndex[i + 2].level; - *outOffset += inOffset[info->srcIndex[i + 3].index] * info->srcIndex[i + 3].level; + *outOffset += inOffset[info->srcIndex[i].index] * info->srcIndex[i].level, i++; + *outOffset += inOffset[info->srcIndex[i].index] * info->srcIndex[i].level, i++; + *outOffset += inOffset[info->srcIndex[i].index] * info->srcIndex[i].level, i++; + *outOffset += inOffset[info->srcIndex[i].index] * info->srcIndex[i].level, i++; } /* unrolled loop for higher performance */ switch (info->srcCount & 0x3) { - case 3: *outOffset += inOffset[info->srcIndex[i].index] * info->srcIndex[i].level; ++i; - case 2: *outOffset += inOffset[info->srcIndex[i].index] * info->srcIndex[i].level; ++i; + case 3: *outOffset += inOffset[info->srcIndex[i].index] * info->srcIndex[i].level, i++; + case 2: *outOffset += inOffset[info->srcIndex[i].index] * info->srcIndex[i].level, i++; case 1: *outOffset += inOffset[info->srcIndex[i].index] * info->srcIndex[i].level; } } diff --git a/xbmc/cores/AudioEngine/Utils/AERingBuffer.h b/xbmc/cores/AudioEngine/Utils/AERingBuffer.h new file mode 100644 index 0000000000..14db166c25 --- /dev/null +++ b/xbmc/cores/AudioEngine/Utils/AERingBuffer.h @@ -0,0 +1,254 @@ +#pragma once +/* + * Copyright (C) 2010-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#define AE_RING_BUFFER_OK 0; +#define AE_RING_BUFFER_EMPTY 1; +#define AE_RING_BUFFER_FULL 2; +#define AE_RING_BUFFER_NOTAVAILABLE 3; + +//#define AE_RING_BUFFER_DEBUG + +#include "utils/log.h" //CLog +#include <string.h> //memset, memcpy + +/** + * This buffer can be used by one read and one write thread at any one time + * without the risk of data corruption. + * If you intend to call the Reset() method, please use Locks. + * All other operations are thread-safe. + */ +class AERingBuffer { + +public: + AERingBuffer() : + m_iReadPos(0), + m_iWritePos(0), + m_iRead(0), + m_iWritten(0), + m_iSize(0), + m_Buffer(NULL) + { + } + + AERingBuffer(unsigned int size) : + m_iReadPos(0), + m_iWritePos(0), + m_iRead(0), + m_iWritten(0), + m_iSize(0), + m_Buffer(NULL) + { + Create(size); + } + + ~AERingBuffer() + { +#ifdef AE_RING_BUFFER_DEBUG + CLog::Log(LOGDEBUG, "AERingBuffer::~AERingBuffer: Deleting buffer."); +#endif + _aligned_free(m_Buffer); + } + + /** + * Allocates space for buffer, and sets it's contents to 0. + * + * @return true on success, false otherwise + */ + bool Create(int size) + { + m_Buffer = (unsigned char*)_aligned_malloc(size,16); + if ( m_Buffer ) + { + m_iSize = size; + memset(m_Buffer, 0, m_iSize); + return true; + } + return false; + } + + /** + * Fills the buffer with zeros and resets the pointers. + * This method is not thread-safe, so before using this method + * please acquire a Lock() + */ + void Reset() { +#ifdef AE_RING_BUFFER_DEBUG + CLog::Log(LOGDEBUG, "AERingBuffer::Reset: Buffer reset."); +#endif + m_iWritten = 0; + m_iRead = 0; + m_iReadPos = 0; + m_iWritePos = 0; + } + + /** + * Writes data to buffer. + * Attempt to write more bytes than available results in AE_RING_BUFFER_FULL. + * + * @return AE_RING_BUFFER_OK on success, otherwise an error code + */ + int Write(unsigned char *src, unsigned int size) + { + unsigned int space = GetWriteSize(); + + //do we have enough space for all the data? + if (size > space) { +#ifdef AE_RING_BUFFER_DEBUG + CLog::Log(LOGDEBUG, "AERingBuffer: Not enough space, ignoring data. Requested: %u Available: %u",size, space); +#endif + return AE_RING_BUFFER_FULL; + } + + //no wrapping? + if ( m_iSize > size + m_iWritePos ) + { +#ifdef AE_RING_BUFFER_DEBUG + CLog::Log(LOGDEBUG, "AERingBuffer: Written to: %u size: %u space before: %u\n", m_iWritePos, size, space); +#endif + memcpy(&(m_Buffer[m_iWritePos]), src, size); + m_iWritePos+=size; + } + //need to wrap + else + { + unsigned int first = m_iSize - m_iWritePos; + unsigned int second = size - first; +#ifdef AE_RING_BUFFER_DEBUG + CLog::Log(LOGDEBUG, "AERingBuffer: Written to (split) first: %u second: %u size: %u space before: %u\n", first, second, size, space); +#endif + memcpy(&(m_Buffer[m_iWritePos]), src, first); + memcpy(&(m_Buffer[0]), &src[first], second); + m_iWritePos = second; + } + + //we can increase the write count now + m_iWritten+=size; + return AE_RING_BUFFER_OK; + } + + /** + * Reads data from buffer. + * Attempt to read more bytes than available results in RING_BUFFER_NOTAVAILABLE. + * Reading from empty buffer returns AE_RING_BUFFER_EMPTY + * + * @return AE_RING_BUFFER_OK on success, otherwise an error code + */ + int Read(unsigned char *dest, unsigned int size) + { + unsigned int space = GetReadSize(); + + //want to read more than we have written? + if( space <= 0 ) + { +#ifdef AE_RING_BUFFER_DEBUG + CLog::Log(LOGDEBUG, "AERingBuffer: Can't read from empty buffer."); +#endif + return AE_RING_BUFFER_EMPTY; + } + + //want to read more than we have available + if( size > space ) + { +#ifdef AE_RING_BUFFER_DEBUG + CLog::Log(LOGDEBUG, "AERingBuffer: Can't read %u bytes when we only have %u.", size, space); +#endif + return AE_RING_BUFFER_NOTAVAILABLE; + } + + //no wrapping? + if ( size + m_iReadPos < m_iSize ) + { +#ifdef AE_RING_BUFFER_DEBUG + CLog::Log(LOGDEBUG, "AERingBuffer: Reading from: %u size: %u space before: %u\n", m_iWritePos, size, space); +#endif + memcpy(dest, &(m_Buffer[m_iReadPos]), size); + m_iReadPos+=size; + } + //need to wrap + else + { + unsigned int first = m_iSize - m_iReadPos; + unsigned int second = size - first; +#ifdef AE_RING_BUFFER_DEBUG + CLog::Log(LOGDEBUG, "AERingBuffer: Reading from (split) first: %u second: %u size: %u space before: %u\n", first, second, size, space); +#endif + memcpy(dest, &(m_Buffer[m_iReadPos]), first); + memcpy(&dest[first], &(m_Buffer[0]), second); + m_iReadPos = second; + } + //we can increase the read count now + m_iRead+=size; + + return AE_RING_BUFFER_OK; + } + + /** + * Dumps the buffer. + */ + void Dump() + { + unsigned char* bufferContents = (unsigned char *)_aligned_malloc(m_iSize + 1,16); + for (unsigned int i=0; i<m_iSize; i++) { + if (i >= m_iReadPos && i<m_iWritePos) + bufferContents[i] = m_Buffer[i]; + else + bufferContents[i] = '_'; + } + bufferContents[m_iSize] = '\0'; + CLog::Log(LOGDEBUG, "AERingBuffer::Dump()\n%s",bufferContents); + _aligned_free(bufferContents); + } + + /** + * Returns available space for writing to buffer. + * Attempt to write more bytes than available results in AE_RING_BUFFER_FULL. + */ + unsigned int GetWriteSize() + { + return m_iSize - ( m_iWritten - m_iRead ); + } + + /** + * Returns available space for reading from buffer. + * Attempt to read more bytes than available results in AE_RING_BUFFER_EMPTY. + */ + unsigned int GetReadSize() + { + return m_iWritten - m_iRead; + } + + /** + * Returns the buffer size. + */ + unsigned int GetMaxSize() + { + return m_iSize; + } + +private: + unsigned int m_iReadPos; + unsigned int m_iWritePos; + unsigned int m_iRead; + unsigned int m_iWritten; + unsigned int m_iSize; + unsigned char *m_Buffer; +}; diff --git a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp index 4213fec7a3..05f162ecdc 100644 --- a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp @@ -64,16 +64,26 @@ static const uint32_t DTSSampleRates[DTS_SFREQ_COUNT] = }; CAEStreamInfo::CAEStreamInfo() : - m_bufferSize(0), - m_skipBytes (0), - m_coreOnly (false), - m_needBytes (0), - m_syncFunc (&CAEStreamInfo::DetectType), - m_hasSync (false), - m_sampleRate(0), - m_dtsBlocks (0), - m_dataType (STREAM_TYPE_NULL), - m_packFunc (NULL) + m_bufferSize (0), + m_skipBytes (0), + m_coreOnly (false), + m_needBytes (0), + m_syncFunc (&CAEStreamInfo::DetectType), + m_hasSync (false), + m_sampleRate (0), + m_outputRate (0), + m_outputChannels(0), + m_channelMap (CAEChannelInfo()), + m_channels (0), + m_coreSize (0), + m_dtsBlocks (0), + m_dtsPeriod (0), + m_fsize (0), + m_repeat (0), + m_substreams (0), + m_dataType (STREAM_TYPE_NULL), + m_dataIsLE (false), + m_packFunc (NULL) { m_dllAvUtil.Load(); m_dllAvUtil.av_crc_init(m_crcTrueHD, 0, 16, 0x2D, sizeof(m_crcTrueHD)); diff --git a/xbmc/cores/AudioEngine/Utils/AEUtil.h b/xbmc/cores/AudioEngine/Utils/AEUtil.h index 12353a5e71..4bf4a99a0c 100644 --- a/xbmc/cores/AudioEngine/Utils/AEUtil.h +++ b/xbmc/cores/AudioEngine/Utils/AEUtil.h @@ -25,6 +25,12 @@ #include "PlatformDefs.h" #include <math.h> +#ifdef TARGET_WINDOWS +#if _M_IX86_FP>0 && !defined(__SSE__) +#define __SSE__ +#endif +#endif + #ifdef __SSE__ #include <xmmintrin.h> #else diff --git a/xbmc/cores/AudioEngine/Utils/AEWAVLoader.cpp b/xbmc/cores/AudioEngine/Utils/AEWAVLoader.cpp index 75aafcbf44..08184af664 100644 --- a/xbmc/cores/AudioEngine/Utils/AEWAVLoader.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEWAVLoader.cpp @@ -25,8 +25,8 @@ #include "system.h" #include "utils/log.h" #include "utils/EndianSwap.h" -#include "filesystem/FileFactory.h" -#include "filesystem/IFile.h" +#include "filesystem/File.h" +#include "URL.h" #include <samplerate.h> #include "AEConvert.h" @@ -59,18 +59,17 @@ bool CAEWAVLoader::Initialize(const std::string &filename, unsigned int resample DeInitialize(); m_filename = filename; - XFILE::IFile *file = XFILE::CFileFactory::CreateLoader(m_filename); - if (!file) + XFILE::CFile file; + if (!file.Open(m_filename)) { CLog::Log(LOGERROR, "CAEWAVLoader::Initialize - Failed to create loader: %s", m_filename.c_str()); return false; } struct __stat64 st; - if (!file->Open(CStdString(m_filename)) || file->Stat(&st) < 0) + if (file.Stat(&st) < 0) { CLog::Log(LOGERROR, "CAEWAVLoader::Initialize - Failed to stat file: %s", m_filename.c_str()); - delete file; return false; } @@ -86,7 +85,7 @@ bool CAEWAVLoader::Initialize(const std::string &filename, unsigned int resample uint16_t bitsPerSample; WAVE_CHUNK chunk; - while (file->Read(&chunk, sizeof(chunk)) == sizeof(chunk)) + while (file.Read(&chunk, sizeof(chunk)) == sizeof(chunk)) { chunk.chunksize = Endian_SwapLE32(chunk.chunksize); @@ -103,14 +102,13 @@ bool CAEWAVLoader::Initialize(const std::string &filename, unsigned int resample if (chunk.chunksize > st.st_size - 8) { CLog::Log(LOGERROR, "CAEWAVLoader::Initialize - Corrupt WAV header: %s", m_filename.c_str()); - file->Close(); - delete file; + file.Close(); return false; } /* we only support WAVE files */ char format[4]; - if (file->Read(&format, 4) != 4) + if (file.Read(&format, 4) != 4) break; isWAVE = memcmp(format, "WAVE", 4) == 0; if (!isWAVE) @@ -123,22 +121,22 @@ bool CAEWAVLoader::Initialize(const std::string &filename, unsigned int resample if (chunk.chunksize < 16) break; uint16_t format; - if (file->Read(&format, sizeof(format)) != sizeof(format)) + if (file.Read(&format, sizeof(format)) != sizeof(format)) break; format = Endian_SwapLE16(format); if (format != WAVE_FORMAT_PCM) break; uint16_t channelCount; - if (file->Read(&channelCount , 2) != 2) + if (file.Read(&channelCount , 2) != 2) break; - if (file->Read(&sampleRate , 4) != 4) + if (file.Read(&sampleRate , 4) != 4) break; - if (file->Read(&byteRate , 4) != 4) + if (file.Read(&byteRate , 4) != 4) break; - if (file->Read(&blockAlign , 2) != 2) + if (file.Read(&blockAlign , 2) != 2) break; - if (file->Read(&bitsPerSample, 2) != 2) + if (file.Read(&bitsPerSample, 2) != 2) break; m_channelCount = Endian_SwapLE16(channelCount ); @@ -152,7 +150,7 @@ bool CAEWAVLoader::Initialize(const std::string &filename, unsigned int resample isPCM = true; if (chunk.chunksize > 16) - file->Seek(chunk.chunksize - 16, SEEK_CUR); + file.Seek(chunk.chunksize - 16, SEEK_CUR); } /* if we have the PCM info and its the DATA section */ else if (isPCM && !isDATA && memcmp(chunk.chunk_id, "data", 4) == 0) @@ -171,8 +169,7 @@ bool CAEWAVLoader::Initialize(const std::string &filename, unsigned int resample case 32: convertFn = CAEConvert::ToFloat(AE_FMT_S32LE); break; default: CLog::Log(LOGERROR, "CAEWAVLoader::Initialize - Unsupported data format in wav: %s", m_filename.c_str()); - file->Close(); - delete file; + file.Close(); return false; } @@ -182,14 +179,13 @@ bool CAEWAVLoader::Initialize(const std::string &filename, unsigned int resample uint8_t *raw = (uint8_t *)_aligned_malloc(bytesPerSample, 16); for (s = 0; s < m_sampleCount; ++s) { - if (file->Read(raw, bytesPerSample) != bytesPerSample) + if (file.Read(raw, bytesPerSample) != bytesPerSample) { CLog::Log(LOGERROR, "CAEWAVLoader::Initialize - WAV data shorter then expected: %s", m_filename.c_str()); _aligned_free(m_samples); _aligned_free(raw); m_samples = NULL; - file->Close(); - delete file; + file.Close(); return false; } @@ -201,21 +197,19 @@ bool CAEWAVLoader::Initialize(const std::string &filename, unsigned int resample else { /* skip any unknown sections */ - file->Seek(chunk.chunksize, SEEK_CUR); + file.Seek(chunk.chunksize, SEEK_CUR); } } if (!isRIFF || !isWAVE || !isFMT || !isPCM || !isDATA || m_sampleCount == 0) { CLog::Log(LOGERROR, "CAEWAVLoader::Initialize - Invalid, or un-supported WAV file: %s", m_filename.c_str()); - file->Close(); - delete file; + file.Close(); return false; } /* close the file as we have the samples now */ - file->Close(); - delete file; + file.Close(); /* if we got here, the file was valid and we have the data but it may need re-sampling still */ if (resampleRate != 0 && m_sampleRate != resampleRate) diff --git a/xbmc/cores/DllLoader/DllLoaderContainer.cpp b/xbmc/cores/DllLoader/DllLoaderContainer.cpp index 09748ffe53..88111fdcf4 100644 --- a/xbmc/cores/DllLoader/DllLoaderContainer.cpp +++ b/xbmc/cores/DllLoader/DllLoaderContainer.cpp @@ -32,6 +32,7 @@ #include "utils/URIUtils.h" #include "utils/StringUtils.h" #include "utils/log.h" +#include "URL.h" #define ENV_PARTIAL_PATH "special://xbmcbin/system/;" \ "special://xbmcbin/system/players/mplayer/;" \ @@ -157,12 +158,21 @@ LibraryLoader* DllLoaderContainer::FindModule(const char* sName, const char* sCu // in environment variable? CStdStringArray vecEnv; + +#if defined(TARGET_ANDROID) + CStdString systemLibs = getenv("XBMC_ANDROID_SYSTEM_LIBS"); + StringUtils::SplitString(systemLibs, ":", vecEnv); + CStdString localLibs = getenv("XBMC_ANDROID_LIBS"); + vecEnv.insert(vecEnv.begin(),localLibs); +#else StringUtils::SplitString(ENV_PATH, ";", vecEnv); +#endif LibraryLoader* pDll = NULL; for (int i=0; i<(int)vecEnv.size(); ++i) { CStdString strPath=vecEnv[i]; + URIUtils::AddSlashAtEnd(strPath); #ifdef LOGALL CLog::Log(LOGDEBUG, "Searching for the dll %s in directory %s", sName, strPath.c_str()); diff --git a/xbmc/cores/DllLoader/SoLoader.cpp b/xbmc/cores/DllLoader/SoLoader.cpp index 97bbd3779f..f61aa9522b 100644 --- a/xbmc/cores/DllLoader/SoLoader.cpp +++ b/xbmc/cores/DllLoader/SoLoader.cpp @@ -24,6 +24,9 @@ #include "utils/StdString.h" #include "filesystem/SpecialProtocol.h" #include "utils/log.h" +#if defined(TARGET_ANDROID) +#include "android/loader/AndroidDyload.h" +#endif SoLoader::SoLoader(const char *so, bool bGlobal) : LibraryLoader(so) { @@ -54,7 +57,12 @@ bool SoLoader::Load() else { CLog::Log(LOGDEBUG, "Loading: %s\n", strFileName.c_str()); +#if defined(TARGET_ANDROID) + CAndroidDyload temp; + m_soHandle = temp.Open(strFileName.c_str()); +#else m_soHandle = dlopen(strFileName.c_str(), flags); +#endif if (!m_soHandle) { CLog::Log(LOGERROR, "Unable to load %s, reason: %s", strFileName.c_str(), dlerror()); @@ -71,7 +79,12 @@ void SoLoader::Unload() if (m_soHandle) { +#if defined(TARGET_ANDROID) + CAndroidDyload temp; + if (temp.Close(m_soHandle) != 0) +#else if (dlclose(m_soHandle) != 0) +#endif CLog::Log(LOGERROR, "Unable to unload %s, reason: %s", GetName(), dlerror()); } m_bLoaded = false; diff --git a/xbmc/cores/DllLoader/exports/Makefile b/xbmc/cores/DllLoader/exports/Makefile.in index d23a680a2d..1b4caf0d69 100644 --- a/xbmc/cores/DllLoader/exports/Makefile +++ b/xbmc/cores/DllLoader/exports/Makefile.in @@ -18,3 +18,6 @@ exports_python_linux.o : exports_python_linux.cpp wrapper.def : wrapper.o nm wrapper.o | grep __wrap | awk '{printf("%s ", $$3);}' | sed "s/___wrap_/__wrap_/g" | sed "s/__wrap_/-Wl,-wrap,/g" > $@ +ifeq (@USE_ANDROID@,1) + echo "-L$(prefix)/lib/dummy-libxbmc/ -lxbmc" >> $@ +endif diff --git a/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp b/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp index 3c38656a65..2e3c42f009 100644 --- a/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp +++ b/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp @@ -71,7 +71,11 @@ #include "utils/CharsetConverter.h" #include "utils/URIUtils.h" #endif - +#if defined(TARGET_ANDROID) +#include "android/loader/AndroidDyload.h" +#elif !defined(_WIN32) +#include <dlfcn.h> +#endif using namespace std; using namespace XFILE; @@ -168,10 +172,21 @@ extern "C" void __stdcall init_emu_environ() dll_putenv(string("PATH=.;" + CSpecialProtocol::TranslatePath("special://xbmc") + ";" + CSpecialProtocol::TranslatePath("special://xbmc/system/python")).c_str()); } + +#if defined(TARGET_ANDROID) + string apkPath = getenv("XBMC_ANDROID_APK"); + apkPath += "/assets/python2.6"; + dll_putenv(string("PYTHONHOME=" + apkPath).c_str()); + dll_putenv("PYTHONOPTIMIZE="); + dll_putenv("PYTHONNOUSERSITE=1"); + dll_putenv("PYTHONPATH="); +#else + dll_putenv("PYTHONOPTIMIZE=1"); +#endif + //dll_putenv("PYTHONCASEOK=1"); //dll_putenv("PYTHONDEBUG=1"); //dll_putenv("PYTHONVERBOSE=2"); // "1" for normal verbose, "2" for more verbose ? - dll_putenv("PYTHONOPTIMIZE=1"); //dll_putenv("PYTHONDUMPREFS=1"); //dll_putenv("THREADDEBUG=1"); //dll_putenv("PYTHONMALLOCSTATS=1"); @@ -442,6 +457,18 @@ extern "C" return NULL; } + void *dll_dlopen(const char *filename, int flag) + { +#if defined(TARGET_ANDROID) + CAndroidDyload temp; + return temp.Open(filename); +#elif !defined(_WIN32) + return dlopen(filename, flag); +#else + return NULL; +#endif + } + int dll_pclose(FILE *stream) { not_implement("msvcrt.dll fake function _pclose(...) called\n"); //warning @@ -1163,7 +1190,7 @@ extern "C" FILE* dll_fopen(const char* filename, const char* mode) { FILE* file = NULL; -#if defined(_LINUX) && !defined(TARGET_DARWIN) && !defined(__FreeBSD__) +#if defined(_LINUX) && !defined(TARGET_DARWIN) && !defined(__FreeBSD__) && !defined(__ANDROID__) if (strcmp(filename, MOUNTED) == 0 || strcmp(filename, MNTTAB) == 0) { @@ -1271,7 +1298,7 @@ extern "C" { // it might be something else than a file, or the file is not emulated // let the operating system handle it -#if defined(TARGET_DARWIN) || defined(__FreeBSD__) +#if defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(__ANDROID__) return fseek(stream, offset, origin); #else return fseeko64(stream, offset, origin); @@ -1336,7 +1363,7 @@ extern "C" { // it might be something else than a file, or the file is not emulated // let the operating system handle it -#if defined(TARGET_DARWIN) || defined(__FreeBSD__) +#if defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(__ANDROID__) return ftello(stream); #else return ftello64(stream); @@ -1382,7 +1409,7 @@ extern "C" CLog::Log(LOGWARNING, "msvcrt.dll: dll_telli64 called, TODO: add 'int64 -> long' type checking"); //warning #ifndef _LINUX return (__int64)tell(fd); -#elif defined(TARGET_DARWIN) || defined(__FreeBSD__) +#elif defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(__ANDROID__) return lseek(fd, 0, SEEK_CUR); #else return lseek64(fd, 0, SEEK_CUR); @@ -1559,7 +1586,7 @@ extern "C" int ret; ret = dll_fgetpos64(stream, &tmpPos); -#if !defined(_LINUX) || defined(TARGET_DARWIN) || defined(__FreeBSD__) +#if !defined(_LINUX) || defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(__ANDROID__) *pos = (fpos_t)tmpPos; #else pos->__pos = (off_t)tmpPos.__pos; @@ -1572,7 +1599,7 @@ extern "C" CFile* pFile = g_emuFileWrapper.GetFileXbmcByStream(stream); if (pFile != NULL) { -#if !defined(_LINUX) || defined(TARGET_DARWIN) || defined(__FreeBSD__) +#if !defined(_LINUX) || defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(__ANDROID__) *pos = pFile->GetPosition(); #else pos->__pos = pFile->GetPosition(); @@ -1594,7 +1621,7 @@ extern "C" int fd = g_emuFileWrapper.GetDescriptorByStream(stream); if (fd >= 0) { -#if !defined(_LINUX) || defined(TARGET_DARWIN) || defined(__FreeBSD__) +#if !defined(_LINUX) || defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(__ANDROID__) if (dll_lseeki64(fd, *pos, SEEK_SET) >= 0) #else if (dll_lseeki64(fd, (__off64_t)pos->__pos, SEEK_SET) >= 0) @@ -1611,7 +1638,7 @@ extern "C" { // it might be something else than a file, or the file is not emulated // let the operating system handle it -#if !defined(_LINUX) || defined(TARGET_DARWIN) || defined(__FreeBSD__) +#if !defined(_LINUX) || defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(__ANDROID__) return fsetpos(stream, pos); #else return fsetpos64(stream, pos); @@ -1627,7 +1654,7 @@ extern "C" if (fd >= 0) { fpos64_t tmpPos; -#if !defined(_LINUX) || defined(TARGET_DARWIN) || defined(__FreeBSD__) +#if !defined(_LINUX) || defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(__ANDROID__) tmpPos= *pos; #else tmpPos.__pos = (off64_t)(pos->__pos); @@ -2079,10 +2106,17 @@ extern "C" } #ifdef _LINUX +#if defined(__ANDROID__) + volatile int * __cdecl dll_errno(void) + { + return &errno; + } +#else int * __cdecl dll_errno(void) { return &errno; } +#endif int __cdecl dll_ioctl(int fd, unsigned long int request, va_list va) { diff --git a/xbmc/cores/DllLoader/exports/emu_msvcrt.h b/xbmc/cores/DllLoader/exports/emu_msvcrt.h index df5cf064e4..4e1f31a667 100644 --- a/xbmc/cores/DllLoader/exports/emu_msvcrt.h +++ b/xbmc/cores/DllLoader/exports/emu_msvcrt.h @@ -33,6 +33,11 @@ typedef int64_t off64_t; typedef off64_t __off64_t; typedef fpos_t fpos64_t; #endif +#if defined(__ANDROID__) +typedef long int __off_t; +typedef long int __off64_t; +typedef fpos_t fpos64_t; // no 64-bit on android +#endif #ifdef WIN32 #include "win32-dirent.h" @@ -178,7 +183,9 @@ extern "C" int dll_filbuf(FILE *fp); int dll_flsbuf(int data, FILE*fp); -#ifdef _LINUX +#if defined(__ANDROID__) + volatile int * __cdecl dll_errno(void); +#elif defined(_LINUX) int * __cdecl dll_errno(void); #endif diff --git a/xbmc/cores/DllLoader/exports/util/EmuFileWrapper.h b/xbmc/cores/DllLoader/exports/util/EmuFileWrapper.h index aa7fe3f498..18942a5404 100644 --- a/xbmc/cores/DllLoader/exports/util/EmuFileWrapper.h +++ b/xbmc/cores/DllLoader/exports/util/EmuFileWrapper.h @@ -28,7 +28,7 @@ #include "system.h" #include "threads/CriticalSection.h" -#if defined(_LINUX) && !defined(TARGET_DARWIN) && !defined(__FreeBSD__) +#if defined(_LINUX) && !defined(TARGET_DARWIN) && !defined(__FreeBSD__) && !defined(__ANDROID__) #define _file _fileno #endif diff --git a/xbmc/cores/DllLoader/exports/wrapper.c b/xbmc/cores/DllLoader/exports/wrapper.c index 1cc45fc57b..2d1706e7c2 100644 --- a/xbmc/cores/DllLoader/exports/wrapper.c +++ b/xbmc/cores/DllLoader/exports/wrapper.c @@ -26,7 +26,9 @@ // #include <sys/types.h> #include <sys/stat.h> +#if !defined(__ANDROID__) #include <sys/statvfs.h> +#endif #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -36,14 +38,15 @@ #else #include <dirent.h> #endif +#include <dlfcn.h> -#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) +#if defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(__ANDROID__) typedef off_t __off_t; typedef int64_t off64_t; typedef off64_t __off64_t; typedef fpos_t fpos64_t; #define stat64 stat -#if defined(TARGET_DARWIN) +#if defined(TARGET_DARWIN) || defined(TARGET_ANDROID) #define _G_va_list va_list #endif #endif @@ -109,9 +112,19 @@ void dll_funlockfile(FILE *file); int dll_fstat64(int fd, struct stat64 *buf); int dll_fstat(int fd, struct _stat *buf); FILE* dll_popen(const char *command, const char *mode); +void* dll_dlopen(const char *filename, int flag); int dll_setvbuf(FILE *stream, char *buf, int type, size_t size); struct mntent *dll_getmntent(FILE *fp); +void *__wrap_dlopen(const char *filename, int flag) +{ +#if defined(TARGET_ANDROID) + return dll_dlopen(filename, flag); +#else + return dlopen(filename, flag); +#endif +} + FILE *__wrap_popen(const char *command, const char *mode) { return dll_popen(command, mode); diff --git a/xbmc/cores/DllLoader/ldt_keeper.c b/xbmc/cores/DllLoader/ldt_keeper.c index 1ed98d0dbc..6757b2b9df 100644 --- a/xbmc/cores/DllLoader/ldt_keeper.c +++ b/xbmc/cores/DllLoader/ldt_keeper.c @@ -48,8 +48,12 @@ extern "C" { #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)) _syscall3( int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount ); #else +#if defined(__ANDROID__) && defined(__i386__) && !defined(modify_ldt) +#define modify_ldt(a,b,c) syscall( __NR_modify_ldt, a, b, c); +#else int modify_ldt(int func, void *ptr, unsigned long bytecount); #endif +#endif #ifdef __cplusplus } #endif diff --git a/xbmc/cores/DummyVideoPlayer.cpp b/xbmc/cores/DummyVideoPlayer.cpp index 7ae55caeec..ddca2753fb 100644 --- a/xbmc/cores/DummyVideoPlayer.cpp +++ b/xbmc/cores/DummyVideoPlayer.cpp @@ -144,7 +144,7 @@ bool CDummyVideoPlayer::CanSeek() void CDummyVideoPlayer::Seek(bool bPlus, bool bLargeStep) { - if (g_advancedSettings.m_videoUseTimeSeeking && GetTotalTime() > 2*g_advancedSettings.m_videoTimeSeekForwardBig) + if (g_advancedSettings.m_videoUseTimeSeeking && GetTotalTime() > 2000*g_advancedSettings.m_videoTimeSeekForwardBig) { int seek = 0; if (bLargeStep) @@ -191,14 +191,13 @@ void CDummyVideoPlayer::SwitchToNextAudioLanguage() void CDummyVideoPlayer::SeekPercentage(float iPercent) { - int64_t iTotalMsec = GetTotalTime() * 1000; - int64_t iTime = (int64_t)(iTotalMsec * iPercent / 100); + int64_t iTime = (int64_t)(GetTotalTime() * iPercent / 100); SeekTime(iTime); } float CDummyVideoPlayer::GetPercentage() { - int64_t iTotalTime = GetTotalTime() * 1000; + int64_t iTotalTime = GetTotalTime(); if (iTotalTime != 0) { @@ -240,10 +239,10 @@ int64_t CDummyVideoPlayer::GetTime() return m_clock; } -// return length in seconds.. this should be changed to return in milleseconds throughout xbmc -int CDummyVideoPlayer::GetTotalTime() +// return length in milliseconds +int64_t CDummyVideoPlayer::GetTotalTime() { - return 1000; + return 1000000; } void CDummyVideoPlayer::ToFFRW(int iSpeed) diff --git a/xbmc/cores/DummyVideoPlayer.h b/xbmc/cores/DummyVideoPlayer.h index 82dd244b8d..c30b750a68 100644 --- a/xbmc/cores/DummyVideoPlayer.h +++ b/xbmc/cores/DummyVideoPlayer.h @@ -68,7 +68,7 @@ public: virtual void SeekTime(int64_t iTime); virtual int64_t GetTime(); - virtual int GetTotalTime(); + virtual int64_t GetTotalTime(); virtual void ToFFRW(int iSpeed); virtual void ShowOSD(bool bOnoff); virtual void DoAudioWork() {} diff --git a/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp b/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp index 62c08923af..01c460854d 100644 --- a/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp +++ b/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp @@ -151,7 +151,7 @@ void CExternalPlayer::Process() mainFile = CMusicDatabaseFile::TranslateUrl(url); } - if (m_filenameReplacers.size() > 0) + if (m_filenameReplacers.size() > 0) { for (unsigned int i = 0; i < m_filenameReplacers.size(); i++) { @@ -173,7 +173,7 @@ void CExternalPlayer::Process() continue; } - if (regExp.RegFind(mainFile) > -1) + if (regExp.RegFind(mainFile) > -1) { CStdString strPat = vecSplit[1]; strPat.Replace(",,",","); @@ -290,7 +290,7 @@ void CExternalPlayer::Process() BOOL ret = TRUE; #if defined(_WIN32) ret = ExecuteAppW32(strFName.c_str(),strFArgs.c_str()); -#elif defined(_LINUX) +#elif defined(_LINUX) || defined(TARGET_DARWIN_OSX) ret = ExecuteAppLinux(strFArgs.c_str()); #endif int64_t elapsedMillis = XbmcThreads::SystemClockMillis() - m_playbackStartTime; @@ -377,12 +377,12 @@ BOOL CExternalPlayer::ExecuteAppW32(const char* strPath, const char* strSwitches if (m_bAbortRequest) return false; BOOL ret = CreateProcessW(WstrPath.IsEmpty() ? NULL : WstrPath.c_str(), - (LPWSTR) WstrSwitches.c_str(), NULL, NULL, FALSE, NULL, + (LPWSTR) WstrSwitches.c_str(), NULL, NULL, FALSE, NULL, NULL, NULL, &si, &m_processInfo); if (ret == FALSE) { - DWORD lastError = GetLastError(); + DWORD lastError = GetLastError(); CLog::Log(LOGNOTICE, "%s - Failure: %d", __FUNCTION__, lastError); } else @@ -416,7 +416,7 @@ BOOL CExternalPlayer::ExecuteAppW32(const char* strPath, const char* strSwitches } #endif -#if defined(_LINUX) +#if defined(_LINUX) || defined(TARGET_DARWIN_OSX) BOOL CExternalPlayer::ExecuteAppLinux(const char* strSwitches) { CLog::Log(LOGNOTICE, "%s: %s", __FUNCTION__, strSwitches); @@ -504,7 +504,7 @@ void CExternalPlayer::SeekPercentage(float iPercent) float CExternalPlayer::GetPercentage() { int64_t iTime = GetTime(); - int64_t iTotalTime = GetTotalTime() * 1000; + int64_t iTotalTime = GetTotalTime(); if (iTotalTime != 0) { @@ -547,9 +547,9 @@ int64_t CExternalPlayer::GetTime() // in millis return m_time; } -int CExternalPlayer::GetTotalTime() // in seconds +int64_t CExternalPlayer::GetTotalTime() // in milliseconds { - return m_totalTime; + return m_totalTime * 1000; } void CExternalPlayer::ToFFRW(int iSpeed) @@ -573,7 +573,7 @@ bool CExternalPlayer::SetPlayerState(CStdString state) bool CExternalPlayer::Initialize(TiXmlElement* pConfig) { - XMLUtils::GetString(pConfig, "filename", m_filename); + XMLUtils::GetString(pConfig, "filename", m_filename); if (m_filename.length() > 0) { CLog::Log(LOGNOTICE, "ExternalPlayer Filename: %s", m_filename.c_str()); @@ -619,7 +619,7 @@ bool CExternalPlayer::Initialize(TiXmlElement* pConfig) XMLUtils::GetInt(pConfig, "playcountminimumtime", m_playCountMinTime, 1, INT_MAX); - CLog::Log(LOGNOTICE, "ExternalPlayer Tweaks: hideconsole (%s), hidexbmc (%s), islauncher (%s), warpcursor (%s)", + CLog::Log(LOGNOTICE, "ExternalPlayer Tweaks: hideconsole (%s), hidexbmc (%s), islauncher (%s), warpcursor (%s)", m_hideconsole ? "true" : "false", m_hidexbmc ? "true" : "false", m_islauncher ? "true" : "false", diff --git a/xbmc/cores/ExternalPlayer/ExternalPlayer.h b/xbmc/cores/ExternalPlayer/ExternalPlayer.h index fc38b9a84b..01377d5ea0 100644 --- a/xbmc/cores/ExternalPlayer/ExternalPlayer.h +++ b/xbmc/cores/ExternalPlayer/ExternalPlayer.h @@ -72,7 +72,7 @@ public: virtual void SeekTime(int64_t iTime); virtual int64_t GetTime(); - virtual int GetTotalTime(); + virtual int64_t GetTotalTime(); virtual void ToFFRW(int iSpeed); virtual void ShowOSD(bool bOnoff); virtual void DoAudioWork() {} diff --git a/xbmc/cores/IPlayer.h b/xbmc/cores/IPlayer.h index 719e5e4634..7339c64791 100644 --- a/xbmc/cores/IPlayer.h +++ b/xbmc/cores/IPlayer.h @@ -135,8 +135,14 @@ public: virtual float GetActualFPS() { return 0.0f; }; virtual void SeekTime(int64_t iTime = 0){}; - virtual int64_t GetTime(){ return 0;}; - virtual int GetTotalTime(){ return 0;}; + /*! + \brief current time in milliseconds + */ + virtual int64_t GetTime() { return 0; } + /*! + \brief total time in milliseconds + */ + virtual int64_t GetTotalTime() { return 0; } virtual int GetAudioBitrate(){ return 0;} virtual int GetVideoBitrate(){ return 0;} virtual int GetSourceBitrate(){ return 0;} diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp index f74693d836..e05e38adc4 100644 --- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp +++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp @@ -38,19 +38,39 @@ CBaseRenderer::CBaseRenderer() m_sourceHeight = 480; m_resolution = RES_DESKTOP; m_fps = 0.0f; + m_renderOrientation = 0; + m_oldRenderOrientation = 0; + m_oldDestRect.SetRect(0.0f, 0.0f, 0.0f, 0.0f); + + for(int i=0; i < 4; i++) + { + m_rotatedDestCoords[i].x = 0; + m_rotatedDestCoords[i].y = 0; + m_savedRotatedDestCoords[i].x = 0; + m_savedRotatedDestCoords[i].y = 0; + } + + m_RenderUpdateCallBackFn = NULL; + m_RenderUpdateCallBackCtx = NULL; } CBaseRenderer::~CBaseRenderer() { } +void CBaseRenderer::RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn) +{ + m_RenderUpdateCallBackFn = fn; + m_RenderUpdateCallBackCtx = ctx; +} + void CBaseRenderer::ChooseBestResolution(float fps) { if (fps == 0.0) return; // Adjust refreshrate to match source fps #if !defined(TARGET_DARWIN_IOS) - if (g_guiSettings.GetBool("videoplayer.adjustrefreshrate")) + if (g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF) { float weight; if (!FindResolutionFromOverride(fps, weight, false)) //find a refreshrate from overrides @@ -232,6 +252,99 @@ void CBaseRenderer::GetVideoRect(CRect &source, CRect &dest) dest = m_destRect; } +inline void CBaseRenderer::ReorderDrawPoints() +{ + // 0 - top left, 1 - top right, 2 - bottom right, 3 - bottom left + float origMat[4][2] = {{m_destRect.x1, m_destRect.y1}, + {m_destRect.x2, m_destRect.y1}, + {m_destRect.x2, m_destRect.y2}, + {m_destRect.x1, m_destRect.y2}}; + bool changeAspect = false; + int pointOffset = 0; + + switch (m_renderOrientation) + { + case 90: + pointOffset = 1; + changeAspect = true; + break; + case 180: + pointOffset = 2; + break; + case 270: + pointOffset = 3; + changeAspect = true; + break; + } + + // if renderer doesn't support rotation + // treat orientation as 0 degree so that + // ffmpeg might handle it. + if (!Supports(RENDERFEATURE_ROTATION)) + { + pointOffset = 0; + changeAspect = false; + } + + + int diff = (int) ((m_destRect.Height() - m_destRect.Width()) / 2); + + for (int destIdx=0, srcIdx=pointOffset; destIdx < 4; destIdx++) + { + m_rotatedDestCoords[destIdx].x = origMat[srcIdx][0]; + m_rotatedDestCoords[destIdx].y = origMat[srcIdx][1]; + + if (changeAspect) + { + switch (srcIdx) + { + case 0: + m_rotatedDestCoords[destIdx].x -= diff; + m_rotatedDestCoords[destIdx].y += diff; + break; + case 1: + m_rotatedDestCoords[destIdx].x += diff; + m_rotatedDestCoords[destIdx].y += diff; + break; + case 2: + m_rotatedDestCoords[destIdx].x += diff; + m_rotatedDestCoords[destIdx].y -= diff; + break; + case 3: + m_rotatedDestCoords[destIdx].x -= diff; + m_rotatedDestCoords[destIdx].y -= diff; + break; + } + } + srcIdx++; + srcIdx = srcIdx % 4; + } +} + +void CBaseRenderer::saveRotatedCoords() +{ + for (int i = 0; i < 4; i++) + m_savedRotatedDestCoords[i] = m_rotatedDestCoords[i]; +} + +void CBaseRenderer::syncDestRectToRotatedPoints() +{ + m_rotatedDestCoords[0].x = m_destRect.x1; + m_rotatedDestCoords[0].y = m_destRect.y1; + m_rotatedDestCoords[1].x = m_destRect.x2; + m_rotatedDestCoords[1].y = m_destRect.y1; + m_rotatedDestCoords[2].x = m_destRect.x2; + m_rotatedDestCoords[2].y = m_destRect.y2; + m_rotatedDestCoords[3].x = m_destRect.x1; + m_rotatedDestCoords[3].y = m_destRect.y2; +} + +void CBaseRenderer::restoreRotatedCoords() +{ + for (int i = 0; i < 4; i++) + m_rotatedDestCoords[i] = m_savedRotatedDestCoords[i]; +} + void CBaseRenderer::CalcNormalDisplayRect(float offsetX, float offsetY, float screenWidth, float screenHeight, float inputFrameRatio, float zoomAmount, float verticalShift) { // if view window is empty, set empty destination @@ -308,6 +421,15 @@ void CBaseRenderer::CalcNormalDisplayRect(float offsetX, float offsetY, float sc m_sourceRect.y2 += (m_destRect.y2 - original.y2) * scaleY; } } + + if (m_oldDestRect != m_destRect || m_oldRenderOrientation != m_renderOrientation) + { + // adapt the drawing rect points if we have to rotate + // and either destrect or orientation changed + ReorderDrawPoints(); + m_oldDestRect = m_destRect; + m_oldRenderOrientation = m_renderOrientation; + } } //*************************************************************************************** diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h index b6d607e399..c7f2b489b6 100644 --- a/xbmc/cores/VideoRenderers/BaseRenderer.h +++ b/xbmc/cores/VideoRenderers/BaseRenderer.h @@ -56,9 +56,12 @@ enum ERENDERFEATURE RENDERFEATURE_CONTRAST, RENDERFEATURE_NOISE, RENDERFEATURE_SHARPNESS, - RENDERFEATURE_NONLINSTRETCH + RENDERFEATURE_NONLINSTRETCH, + RENDERFEATURE_ROTATION }; +typedef void (*RenderUpdateCallBackFn)(const void *ctx, const CRect &SrcRect, const CRect &DestRect); + struct DVDVideoPicture; class CBaseRenderer @@ -77,9 +80,13 @@ public: virtual unsigned int GetProcessorSize() { return 0; } + virtual bool Supports(ERENDERFEATURE feature) { return false; } + // Supported pixel formats, can be called before configure std::vector<ERenderFormat> SupportedFormats() { return std::vector<ERenderFormat>(); } + virtual void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn); + protected: void ChooseBestResolution(float fps); bool FindResolutionFromOverride(float fps, float& weight, bool fallback); @@ -90,12 +97,29 @@ protected: void CalculateFrameAspectRatio(unsigned int desired_width, unsigned int desired_height); void ManageDisplay(); + virtual void ReorderDrawPoints();//might be overwritten (by egl e.x.) + void saveRotatedCoords();//saves the current state of m_rotatedDestCoords + void syncDestRectToRotatedPoints();//sync any changes of m_destRect to m_rotatedDestCoords + void restoreRotatedCoords();//restore the current state of m_rotatedDestCoords from saveRotatedCoords + RESOLUTION m_resolution; // the resolution we're running in unsigned int m_sourceWidth; unsigned int m_sourceHeight; float m_sourceFrameRatio; float m_fps; + unsigned int m_renderOrientation; // orientation of the video in degress counter clockwise + unsigned int m_oldRenderOrientation; // orientation of the previous frame + // for drawing the texture with glVertex4f (holds all 4 corner points of the destination rect + // with correct orientation based on m_renderOrientation + // 0 - top left, 1 - top right, 2 - bottom right, 3 - bottom left + CPoint m_rotatedDestCoords[4]; + CPoint m_savedRotatedDestCoords[4];//saved points from saveRotatedCoords call + CRect m_destRect; + CRect m_oldDestRect; // destrect of the previous frame CRect m_sourceRect; + + const void* m_RenderUpdateCallBackCtx; + RenderUpdateCallBackFn m_RenderUpdateCallBackFn; }; diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp index ea5dabeecb..b64f5ae1b7 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp +++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp @@ -65,6 +65,7 @@ #endif #ifdef TARGET_DARWIN + #include "osx/CocoaInterface.h" #include <CoreVideo/CoreVideo.h> #include <OpenGL/CGLIOSurface.h> #endif @@ -267,10 +268,11 @@ bool CLinuxRendererGL::ValidateRenderTarget() return false; } -bool CLinuxRendererGL::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format) +bool CLinuxRendererGL::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation) { m_sourceWidth = width; m_sourceHeight = height; + m_renderOrientation = orientation; m_fps = fps; // Save the flags. @@ -698,39 +700,39 @@ void CLinuxRendererGL::DrawBlackBars() glBegin(GL_QUADS); //top quad - if (m_destRect.y1 > 0.0) + if (m_rotatedDestCoords[0].y > 0.0) { - glVertex4f(0.0, 0.0, 0.0, 1.0); - glVertex4f(g_graphicsContext.GetWidth(), 0.0, 0.0, 1.0); - glVertex4f(g_graphicsContext.GetWidth(), m_destRect.y1, 0.0, 1.0); - glVertex4f(0.0, m_destRect.y1, 0.0, 1.0); + glVertex4f(0.0, 0.0, 0.0, 1.0); + glVertex4f(g_graphicsContext.GetWidth(), 0.0, 0.0, 1.0); + glVertex4f(g_graphicsContext.GetWidth(), m_rotatedDestCoords[0].y, 0.0, 1.0); + glVertex4f(0.0, m_rotatedDestCoords[0].y, 0.0, 1.0); } //bottom quad - if (m_destRect.y2 < g_graphicsContext.GetHeight()) + if (m_rotatedDestCoords[2].y < g_graphicsContext.GetHeight()) { - glVertex4f(0.0, m_destRect.y2, 0.0, 1.0); - glVertex4f(g_graphicsContext.GetWidth(), m_destRect.y2, 0.0, 1.0); + glVertex4f(0.0, m_rotatedDestCoords[2].y, 0.0, 1.0); + glVertex4f(g_graphicsContext.GetWidth(), m_rotatedDestCoords[2].y, 0.0, 1.0); glVertex4f(g_graphicsContext.GetWidth(), g_graphicsContext.GetHeight(), 0.0, 1.0); glVertex4f(0.0, g_graphicsContext.GetHeight(), 0.0, 1.0); } //left quad - if (m_destRect.x1 > 0.0) + if (m_rotatedDestCoords[0].x > 0.0) { - glVertex4f(0.0, m_destRect.y1, 0.0, 1.0); - glVertex4f(m_destRect.x1, m_destRect.y1, 0.0, 1.0); - glVertex4f(m_destRect.x1, m_destRect.y2, 0.0, 1.0); - glVertex4f(0.0, m_destRect.y2, 0.0, 1.0); + glVertex4f(0.0, m_rotatedDestCoords[0].y, 0.0, 1.0); + glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0.0, 1.0); + glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[2].y, 0.0, 1.0); + glVertex4f(0.0, m_rotatedDestCoords[2].y, 0.0, 1.0); } //right quad - if (m_destRect.x2 < g_graphicsContext.GetWidth()) + if (m_rotatedDestCoords[2].x < g_graphicsContext.GetWidth()) { - glVertex4f(m_destRect.x2, m_destRect.y1, 0.0, 1.0); - glVertex4f(g_graphicsContext.GetWidth(), m_destRect.y1, 0.0, 1.0); - glVertex4f(g_graphicsContext.GetWidth(), m_destRect.y2, 0.0, 1.0); - glVertex4f(m_destRect.x2, m_destRect.y2, 0.0, 1.0); + glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[0].y, 0.0, 1.0); + glVertex4f(g_graphicsContext.GetWidth(), m_rotatedDestCoords[0].y, 0.0, 1.0); + glVertex4f(g_graphicsContext.GetWidth(), m_rotatedDestCoords[2].y, 0.0, 1.0); + glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0.0, 1.0); } glEnd(); @@ -1258,22 +1260,22 @@ void CLinuxRendererGL::RenderSinglePass(int index, int field) glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1); glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y1); glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y1); - glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f ); + glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0, 1.0f );//top left glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y1); glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y1); glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y1); - glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f); + glVertex4f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y, 0, 1.0f );//top right glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y2); glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y2); glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y2); - glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f); + glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0, 1.0f );//bottom right glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y2); glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y2); glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y2); - glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f); + glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0, 1.0f );//bottom left glEnd(); VerifyGLState(); @@ -1471,16 +1473,16 @@ void CLinuxRendererGL::RenderMultiPass(int index, int field) glBegin(GL_QUADS); glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , 0.0f); - glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f ); + glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0, 1.0f ); glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, 0.0f); - glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f); + glVertex4f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y, 0, 1.0f ); glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, imgheight); - glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f); - + glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0, 1.0f ); + glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , imgheight); - glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f); + glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0, 1.0f ); glEnd(); @@ -1548,17 +1550,17 @@ void CLinuxRendererGL::RenderVDPAU(int index, int field) glBegin(GL_QUADS); if (m_textureTarget==GL_TEXTURE_2D) { - glTexCoord2f(0.0, 0.0); glVertex2f(m_destRect.x1, m_destRect.y1); - glTexCoord2f(1.0, 0.0); glVertex2f(m_destRect.x2, m_destRect.y1); - glTexCoord2f(1.0, 1.0); glVertex2f(m_destRect.x2, m_destRect.y2); - glTexCoord2f(0.0, 1.0); glVertex2f(m_destRect.x1, m_destRect.y2); + glTexCoord2f(0.0, 0.0); glVertex2f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y); + glTexCoord2f(1.0, 0.0); glVertex2f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y); + glTexCoord2f(1.0, 1.0); glVertex2f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y); + glTexCoord2f(0.0, 1.0); glVertex2f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y); } else { - glTexCoord2f(m_destRect.x1, m_destRect.y1); glVertex4f(m_destRect.x1, m_destRect.y1, 0.0f, 0.0f); - glTexCoord2f(m_destRect.x2, m_destRect.y1); glVertex4f(m_destRect.x2, m_destRect.y1, 1.0f, 0.0f); - glTexCoord2f(m_destRect.x2, m_destRect.y2); glVertex4f(m_destRect.x2, m_destRect.y2, 1.0f, 1.0f); - glTexCoord2f(m_destRect.x1, m_destRect.y2); glVertex4f(m_destRect.x1, m_destRect.y2, 0.0f, 1.0f); + glTexCoord2f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y); glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0.0f, 0.0f); + glTexCoord2f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y); glVertex4f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y, 1.0f, 0.0f); + glTexCoord2f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y); glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 1.0f, 1.0f); + glTexCoord2f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y); glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0.0f, 1.0f); } glEnd(); VerifyGLState(); @@ -1637,10 +1639,10 @@ void CLinuxRendererGL::RenderVAAPI(int index, int field) VerifyGLState(); glBegin(GL_QUADS); - glTexCoord2f(0.0, 0.0); glVertex2f(m_destRect.x1, m_destRect.y1); - glTexCoord2f(1.0, 0.0); glVertex2f(m_destRect.x2, m_destRect.y1); - glTexCoord2f(1.0, 1.0); glVertex2f(m_destRect.x2, m_destRect.y2); - glTexCoord2f(0.0, 1.0); glVertex2f(m_destRect.x1, m_destRect.y2); + glTexCoord2f(0.0, 0.0); glVertex2f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y); + glTexCoord2f(1.0, 0.0); glVertex2f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y); + glTexCoord2f(1.0, 1.0); glVertex2f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y); + glTexCoord2f(0.0, 1.0); glVertex2f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y); glEnd(); VerifyGLState(); @@ -1676,16 +1678,16 @@ void CLinuxRendererGL::RenderSoftware(int index, int field) glBegin(GL_QUADS); glTexCoord2f(planes[0].rect.x1, planes[0].rect.y1); - glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f ); + glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0, 1.0f ); glTexCoord2f(planes[0].rect.x2, planes[0].rect.y1); - glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f); + glVertex4f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y, 0, 1.0f); glTexCoord2f(planes[0].rect.x2, planes[0].rect.y2); - glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f); + glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0, 1.0f); glTexCoord2f(planes[0].rect.x1, planes[0].rect.y2); - glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f); + glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0, 1.0f); glEnd(); @@ -1702,9 +1704,12 @@ bool CLinuxRendererGL::RenderCapture(CRenderCapture* capture) // save current video rect CRect saveSize = m_destRect; - + + saveRotatedCoords();//backup current m_rotatedDestCoords + // new video rect is capture size m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight()); + syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords //invert Y axis to get non-inverted image glDisable(GL_BLEND); @@ -1729,6 +1734,7 @@ bool CLinuxRendererGL::RenderCapture(CRenderCapture* capture) // restore original video rect m_destRect = saveSize; + restoreRotatedCoords();//restores the previous state of the rotated dest coords return true; } @@ -2450,29 +2456,49 @@ void CLinuxRendererGL::UploadCVRefTexture(int index) YUVFIELDS &fields = m_buffers[index].fields; YUVPLANE &plane = fields[0][0]; - // It is the fastest way to render a CVPixelBuffer backed - // with an IOSurface as there is no CPU -> GPU upload. - CGLContextObj cgl_ctx = (CGLContextObj)g_Windowing.GetCGLContextObj(); - IOSurfaceRef surface = CVPixelBufferGetIOSurface(cvBufferRef); - GLsizei texWidth = IOSurfaceGetWidth(surface); - GLsizei texHeight= IOSurfaceGetHeight(surface); - OSType format_type = CVPixelBufferGetPixelFormatType(cvBufferRef); - size_t rowbytes = CVPixelBufferGetBytesPerRow(cvBufferRef); + if (Cocoa_GetOSVersion() >= 0x1074) + { + // 10.7.4 for Retina Macbooks on Lion breaks CGLTexImageIOSurface2D/GL_YCBCR_422_APPLE, + // 10.8 Mountain Lion breaks CGLTexImageIOSurface2D/GL_YCBCR_422_APPLE, + // upload the old way. + CVPixelBufferLockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly); - glEnable(m_textureTarget); - glBindTexture(m_textureTarget, plane.id); - glPixelStorei(GL_UNPACK_ROW_LENGTH, rowbytes); + GLsizei texHeight = CVPixelBufferGetHeight(cvBufferRef); + size_t rowbytes = CVPixelBufferGetBytesPerRow(cvBufferRef); + unsigned char *bufferBase = (unsigned char*)CVPixelBufferGetBaseAddress(cvBufferRef); - if (format_type == kCVPixelFormatType_422YpCbCr8) - CGLTexImageIOSurface2D(cgl_ctx, m_textureTarget, GL_RGB8, - texWidth, texHeight, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, surface, 0); - else if (format_type == kCVPixelFormatType_32BGRA) - CGLTexImageIOSurface2D(cgl_ctx, m_textureTarget, GL_RGBA8, - texWidth, texHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0); + glEnable(m_textureTarget); + glBindTexture(m_textureTarget, plane.id); + glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE); + glTexSubImage2D(m_textureTarget, 0, 0, 0, rowbytes/2, texHeight, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, bufferBase); + glBindTexture(m_textureTarget, 0); + glDisable(m_textureTarget); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glBindTexture(m_textureTarget, 0); - glDisable(m_textureTarget); + CVPixelBufferUnlockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly); + } + else + { + // It is the fastest way to render a CVPixelBuffer backed + // with an IOSurface as there is no CPU -> GPU upload. + CGLContextObj cgl_ctx = (CGLContextObj)g_Windowing.GetCGLContextObj(); + IOSurfaceRef surface = CVPixelBufferGetIOSurface(cvBufferRef); + GLsizei texWidth = IOSurfaceGetWidth(surface); + GLsizei texHeight= IOSurfaceGetHeight(surface); + OSType format_type = CVPixelBufferGetPixelFormatType(cvBufferRef); + + glEnable(m_textureTarget); + glBindTexture(m_textureTarget, plane.id); + + if (format_type == kCVPixelFormatType_422YpCbCr8) + CGLTexImageIOSurface2D(cgl_ctx, m_textureTarget, GL_RGB8, + texWidth, texHeight, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, surface, 0); + else if (format_type == kCVPixelFormatType_32BGRA) + CGLTexImageIOSurface2D(cgl_ctx, m_textureTarget, GL_RGBA8, + texWidth, texHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0); + + glBindTexture(m_textureTarget, 0); + glDisable(m_textureTarget); + } CVBufferRelease(cvBufferRef); m_buffers[index].cvBufferRef = NULL; @@ -2514,21 +2540,35 @@ bool CLinuxRendererGL::CreateCVRefTexture(int index) memset(&im , 0, sizeof(im)); memset(&fields, 0, sizeof(fields)); - im.height = m_sourceHeight; + im.bpp = 1; im.width = m_sourceWidth; + im.height = m_sourceHeight; + im.cshift_x = 0; + im.cshift_y = 0; - plane.texwidth = im.width; - plane.texheight = im.height; + plane.texwidth = NP2(im.width); + plane.texheight = NP2(im.height); plane.pixpertex_x = 1; plane.pixpertex_y = 1; - if(m_renderMethod & RENDER_POT) - { - plane.texwidth = NP2(plane.texwidth); - plane.texheight = NP2(plane.texheight); - } glEnable(m_textureTarget); glGenTextures(1, &plane.id); + if (Cocoa_GetOSVersion() >= 0x1074) + { + // 10.7.4 for Retina Macbooks on Lion breaks CGLTexImageIOSurface2D/GL_YCBCR_422_APPLE, + // 10.8 Mountain Lion breaks CGLTexImageIOSurface2D/GL_YCBCR_422_APPLE, + // upload the old way. + glBindTexture(m_textureTarget, plane.id); + // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs. + //glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE); + glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + // This is necessary for non-power-of-two textures + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, NULL); + glBindTexture(m_textureTarget, 0); + } glDisable(m_textureTarget); m_eventTexturesDone[index]->Set(); @@ -2838,6 +2878,7 @@ void CLinuxRendererGL::ToRGBFrame(YV12Image* im, unsigned flipIndexPlane, unsign im->width, im->height, srcFormat, im->width, im->height, PIX_FMT_BGRA, SWS_FAST_BILINEAR | SwScaleCPUFlags(), NULL, NULL, NULL); + uint8_t *dst[] = { m_rgbBuffer, 0, 0, 0 }; int dstStride[] = { m_sourceWidth * 4, 0, 0, 0 }; m_dllSwScale->sws_scale(m_context, src, srcStride, 0, im->height, dst, dstStride); @@ -3160,6 +3201,9 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature) return true; } + if (feature == RENDERFEATURE_ROTATION) + return true; + return false; } diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h index f85d21dd7c..b9d0f1e62d 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h +++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h @@ -130,7 +130,7 @@ public: bool RenderCapture(CRenderCapture* capture); // Player functions - virtual bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format); + virtual bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_formatl, unsigned int orientation); virtual bool IsConfigured() { return m_bConfigured; } virtual int GetImage(YV12Image *image, int source = AUTOSOURCE, bool readonly = false); virtual void ReleaseImage(int source, bool preserve = false); @@ -235,7 +235,7 @@ protected: unsigned short m_renderMethod; RenderQuality m_renderQuality; unsigned int m_flipindex; // just a counter to keep track of if a image has been uploaded - + // Raw data used by renderer int m_currentField; int m_reloadShaders; diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp index 253342a8b8..fe84c60185 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp @@ -50,6 +50,7 @@ #if defined(__ARM_NEON__) #include "yuv2rgb.neon.h" +#include "utils/CPUInfo.h" #endif #ifdef HAVE_VIDEOTOOLBOXDECODER #include "DVDCodecs/Video/DVDVideoCodecVideoToolBox.h" @@ -87,6 +88,7 @@ CLinuxRendererGLES::CLinuxRendererGLES() } m_renderMethod = RENDER_GLSL; + m_oldRenderMethod = m_renderMethod; m_renderQuality = RQ_SINGLEPASS; m_iFlags = 0; m_format = RENDER_FMT_NONE; @@ -146,7 +148,7 @@ bool CLinuxRendererGLES::ValidateRenderTarget() { CLog::Log(LOGNOTICE,"Using GL_TEXTURE_2D"); - // create the yuv textures + // create the yuv textures LoadShaders(); for (int i = 0 ; i < m_NumYV12Buffers ; i++) @@ -155,13 +157,14 @@ bool CLinuxRendererGLES::ValidateRenderTarget() m_bValidated = true; return true; } - return false; + return false; } -bool CLinuxRendererGLES::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format) +bool CLinuxRendererGLES::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation) { m_sourceWidth = width; m_sourceHeight = height; + m_renderOrientation = orientation; // Save the flags. m_iFlags = flags; @@ -185,6 +188,10 @@ bool CLinuxRendererGLES::Configure(unsigned int width, unsigned int height, unsi m_buffers[i].image.flags = 0; m_iLastRenderBuffer = -1; + + m_RenderUpdateCallBackFn = NULL; + m_RenderUpdateCallBackCtx = NULL; + return true; } @@ -396,14 +403,12 @@ void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) { ManageDisplay(); ManageTextures(); - g_graphicsContext.BeginPaint(); + // if running bypass, then the player might need the src/dst rects + // for sizing video playback on a layer other than the gles layer. + if (m_RenderUpdateCallBackFn) + (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect); - // RENDER_BYPASS means we are rendering video - // outside the control of gles and on a different - // graphics plane that is under the gles layer. - // Clear a hole where video would appear so we do not see - // background images that have already been rendered. - g_graphicsContext.SetScissors(m_destRect); + g_graphicsContext.BeginPaint(); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -411,7 +416,6 @@ void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) glClear(GL_COLOR_BUFFER_BIT); g_graphicsContext.EndPaint(); - glFinish(); return; } @@ -477,9 +481,6 @@ void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) glEnable(GL_BLEND); g_graphicsContext.EndPaint(); -#if !defined(TARGET_DARWIN) - glFinish(); -#endif } void CLinuxRendererGLES::FlipPage(int source) @@ -695,6 +696,13 @@ void CLinuxRendererGLES::LoadShaders(int field) m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture; m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture; } + + if (m_oldRenderMethod != m_renderMethod) + { + CLog::Log(LOGDEBUG, "CLinuxRendererGLES: Reorder drawpoints due to method change from %i to %i", m_oldRenderMethod, m_renderMethod); + ReorderDrawPoints(); + m_oldRenderMethod = m_renderMethod; + } } void CLinuxRendererGLES::UnInit() @@ -723,6 +731,26 @@ void CLinuxRendererGLES::UnInit() m_bValidated = false; m_bImageReady = false; m_bConfigured = false; + m_RenderUpdateCallBackFn = NULL; + m_RenderUpdateCallBackCtx = NULL; +} + +inline void CLinuxRendererGLES::ReorderDrawPoints() +{ + + CBaseRenderer::ReorderDrawPoints();//call base impl. for rotating the points + + //corevideo is flipped in y + if(m_renderMethod & RENDER_CVREF) + { + CPoint tmp; + tmp = m_rotatedDestCoords[0]; + m_rotatedDestCoords[0] = m_rotatedDestCoords[3]; + m_rotatedDestCoords[3] = tmp; + tmp = m_rotatedDestCoords[1]; + m_rotatedDestCoords[1] = m_rotatedDestCoords[2]; + m_rotatedDestCoords[2] = tmp; + } } void CLinuxRendererGLES::Render(DWORD flags, int index) @@ -846,11 +874,12 @@ void CLinuxRendererGLES::RenderSinglePass(int index, int field) glEnableVertexAttribArray(Vloc); // Setup vertex position values - m_vert[0][0] = m_vert[3][0] = m_destRect.x1; - m_vert[0][1] = m_vert[1][1] = m_destRect.y1; - m_vert[1][0] = m_vert[2][0] = m_destRect.x2; - m_vert[2][1] = m_vert[3][1] = m_destRect.y2; - m_vert[0][2] = m_vert[1][2] = m_vert[2][2] = m_vert[3][2] = 0.0f; + for(int i = 0; i < 4; i++) + { + m_vert[i][0] = m_rotatedDestCoords[i].x; + m_vert[i][1] = m_rotatedDestCoords[i].y; + m_vert[i][2] = 0.0f;// set z to 0 + } // Setup texture coordinates for (int i=0; i<3; i++) @@ -1111,12 +1140,13 @@ void CLinuxRendererGLES::RenderSoftware(int index, int field) glEnableVertexAttribArray(colLoc); // Set vertex coordinates - ver[0][0] = ver[3][0] = m_destRect.x1; - ver[0][1] = ver[1][1] = m_destRect.y1; - ver[1][0] = ver[2][0] = m_destRect.x2; - ver[2][1] = ver[3][1] = m_destRect.y2; - ver[0][2] = ver[1][2] = ver[2][2] = ver[3][2] = 0.0f; - ver[0][3] = ver[1][3] = ver[2][3] = ver[3][3] = 1.0f; + for(int i = 0; i < 4; i++) + { + ver[i][0] = m_rotatedDestCoords[i].x; + ver[i][1] = m_rotatedDestCoords[i].y; + ver[i][2] = 0.0f;// set z to 0 + ver[i][3] = 1.0f; + } // Set texture coordinates tex[0][0] = tex[3][0] = planes[0].rect.x1; @@ -1175,12 +1205,13 @@ void CLinuxRendererGLES::RenderOpenMax(int index, int field) glEnableVertexAttribArray(colLoc); // Set vertex coordinates - ver[0][0] = ver[3][0] = m_destRect.x1; - ver[0][1] = ver[1][1] = m_destRect.y2; - ver[1][0] = ver[2][0] = m_destRect.x2; - ver[2][1] = ver[3][1] = m_destRect.y1; - ver[0][2] = ver[1][2] = ver[2][2] = ver[3][2] = 0.0f; - ver[0][3] = ver[1][3] = ver[2][3] = ver[3][3] = 1.0f; + for(int i = 0; i < 4; i++) + { + ver[i][0] = m_rotatedDestCoords[i].x; + ver[i][1] = m_rotatedDestCoords[i].y; + ver[i][2] = 0.0f;// set z to 0 + ver[i][3] = 1.0f; + } // Set texture coordinates tex[0][0] = tex[3][0] = 0; @@ -1239,12 +1270,13 @@ void CLinuxRendererGLES::RenderCoreVideoRef(int index, int field) glEnableVertexAttribArray(colLoc); // Set vertex coordinates - ver[0][0] = ver[3][0] = m_destRect.x1; - ver[0][1] = ver[1][1] = m_destRect.y2; - ver[1][0] = ver[2][0] = m_destRect.x2; - ver[2][1] = ver[3][1] = m_destRect.y1; - ver[0][2] = ver[1][2] = ver[2][2] = ver[3][2] = 0.0f; - ver[0][3] = ver[1][3] = ver[2][3] = ver[3][3] = 1.0f; + for(int i = 0; i < 4; i++) + { + ver[i][0] = m_rotatedDestCoords[i].x; + ver[i][1] = m_rotatedDestCoords[i].y; + ver[i][2] = 0.0f;// set z to 0 + ver[i][3] = 1.0f; + } // Set texture coordinates (corevideo is flipped in y) tex[0][0] = tex[3][0] = 0; @@ -1273,10 +1305,11 @@ bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture) // save current video rect CRect saveSize = m_destRect; + saveRotatedCoords();//backup current m_rotatedDestCoords // new video rect is thumbnail size m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight()); - + syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords // clear framebuffer and invert Y axis to get non-inverted image glDisable(GL_BLEND); @@ -1308,6 +1341,7 @@ bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture) // restore original video rect m_destRect = saveSize; + restoreRotatedCoords();//restores the previous state of the rotated dest coords return true; } @@ -1343,20 +1377,25 @@ void CLinuxRendererGLES::UploadYV12Texture(int source) } #if defined(__ARM_NEON__) - yuv420_2_rgb8888_neon(m_rgbBuffer, im->plane[0], im->plane[2], im->plane[1], - m_sourceWidth, m_sourceHeight, im->stride[0], im->stride[1], m_sourceWidth * 4); -#else - m_sw_context = m_dllSwScale->sws_getCachedContext(m_sw_context, - im->width, im->height, PIX_FMT_YUV420P, - im->width, im->height, PIX_FMT_RGBA, - SWS_FAST_BILINEAR, NULL, NULL, NULL); - - uint8_t *src[] = { im->plane[0], im->plane[1], im->plane[2], 0 }; - int srcStride[] = { im->stride[0], im->stride[1], im->stride[2], 0 }; - uint8_t *dst[] = { m_rgbBuffer, 0, 0, 0 }; - int dstStride[] = { m_sourceWidth*4, 0, 0, 0 }; - m_dllSwScale->sws_scale(m_sw_context, src, srcStride, 0, im->height, dst, dstStride); + if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON) + { + yuv420_2_rgb8888_neon(m_rgbBuffer, im->plane[0], im->plane[2], im->plane[1], + m_sourceWidth, m_sourceHeight, im->stride[0], im->stride[1], m_sourceWidth * 4); + } + else #endif + { + m_sw_context = m_dllSwScale->sws_getCachedContext(m_sw_context, + im->width, im->height, PIX_FMT_YUV420P, + im->width, im->height, PIX_FMT_RGBA, + SWS_FAST_BILINEAR, NULL, NULL, NULL); + + uint8_t *src[] = { im->plane[0], im->plane[1], im->plane[2], 0 }; + int srcStride[] = { im->stride[0], im->stride[1], im->stride[2], 0 }; + uint8_t *dst[] = { m_rgbBuffer, 0, 0, 0 }; + int dstStride[] = { m_sourceWidth*4, 0, 0, 0 }; + m_dllSwScale->sws_scale(m_sw_context, src, srcStride, 0, im->height, dst, dstStride); + } } bool deinterlacing; @@ -1379,7 +1418,7 @@ void CLinuxRendererGLES::UploadYV12Texture(int source) LoadPlane( fields[FIELD_BOT][0], GL_RGBA, buf.flipindex , im->width, im->height >> 1 - , m_sourceWidth*8, m_rgbBuffer + m_sourceWidth*4); + , m_sourceWidth*8, m_rgbBuffer + m_sourceWidth*4); } else { @@ -1428,7 +1467,7 @@ void CLinuxRendererGLES::UploadYV12Texture(int source) LoadPlane( fields[FIELD_TOP][2], GL_LUMINANCE, buf.flipindex , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) , im->stride[2]*2, im->plane[2] ); - + // Load Odd U & V Fields LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) @@ -1574,9 +1613,9 @@ bool CLinuxRendererGLES::CreateYV12Texture(int index) else CLog::Log(LOGDEBUG, "GL: Creating RGB NPOT texture of size %d x %d", plane.texwidth, plane.texheight); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - } + } else { if(m_renderMethod & RENDER_POT) @@ -1782,13 +1821,13 @@ bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature) { if(feature == RENDERFEATURE_BRIGHTNESS) return false; - + if(feature == RENDERFEATURE_CONTRAST) return false; if(feature == RENDERFEATURE_GAMMA) return false; - + if(feature == RENDERFEATURE_NOISE) return false; @@ -1798,6 +1837,9 @@ bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature) if (feature == RENDERFEATURE_NONLINSTRETCH) return false; + if (feature == RENDERFEATURE_ROTATION) + return true; + return false; } @@ -1890,5 +1932,5 @@ void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef) } #endif - #endif + diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h index 9d6d417d90..87666e945b 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h @@ -129,7 +129,7 @@ public: bool RenderCapture(CRenderCapture* capture); // Player functions - virtual bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format); + virtual bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_formatunsigned, unsigned int orientation); virtual bool IsConfigured() { return m_bConfigured; } virtual int GetImage(YV12Image *image, int source = AUTOSOURCE, bool readonly = false); virtual void ReleaseImage(int source, bool preserve = false); @@ -137,6 +137,7 @@ public: virtual unsigned int PreInit(); virtual void UnInit(); virtual void Reset(); /* resets renderer after seek for example */ + virtual void ReorderDrawPoints(); virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); @@ -157,6 +158,7 @@ public: #ifdef HAVE_VIDEOTOOLBOXDECODER virtual void AddProcessor(struct __CVBuffer *cvBufferRef); #endif + protected: virtual void Render(DWORD flags, int index); @@ -207,6 +209,7 @@ protected: ERenderFormat m_format; GLenum m_textureTarget; unsigned short m_renderMethod; + unsigned short m_oldRenderMethod; RenderQuality m_renderQuality; unsigned int m_flipindex; // just a counter to keep track of if a image has been uploaded bool m_StrictBinding; diff --git a/xbmc/cores/VideoRenderers/OverlayRendererUtil.cpp b/xbmc/cores/VideoRenderers/OverlayRendererUtil.cpp index 84694a56e5..d564a39b85 100644 --- a/xbmc/cores/VideoRenderers/OverlayRendererUtil.cpp +++ b/xbmc/cores/VideoRenderers/OverlayRendererUtil.cpp @@ -24,7 +24,6 @@ #include "cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayImage.h" #include "cores/dvdplayer/DVDCodecs/Overlay/DVDOverlaySpu.h" #include "cores/dvdplayer/DVDCodecs/Overlay/DVDOverlaySSA.h" -#include "Application.h" #include "windowing/WindowingFactory.h" namespace OVERLAY { diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp index 5ed6082a6e..baa10d4d54 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.cpp +++ b/xbmc/cores/VideoRenderers/RenderManager.cpp @@ -31,6 +31,7 @@ #include "utils/log.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "settings/Settings.h" #include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" @@ -227,7 +228,7 @@ CStdString CXBMCRenderManager::GetVSyncState() return state; } -bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format) +bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation) { /* make sure any queued frame was fully presented */ double timeout = m_presenttime + 0.1; @@ -247,13 +248,13 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi return false; } - bool result = m_pRenderer->Configure(width, height, d_width, d_height, fps, flags, format, extended_format); + bool result = m_pRenderer->Configure(width, height, d_width, d_height, fps, flags, format, extended_format, orientation); if(result) { if( flags & CONF_FLAGS_FULLSCREEN ) { lock.Leave(); - g_application.getApplicationMessenger().SwitchToFullscreen(); + CApplicationMessenger::Get().SwitchToFullscreen(); lock.Enter(); } m_pRenderer->Update(false); @@ -372,7 +373,7 @@ bool CXBMCRenderManager::Flush() { ThreadMessage msg = {TMSG_RENDERER_FLUSH}; m_flushEvent.Reset(); - g_application.getApplicationMessenger().SendMessage(msg, false); + CApplicationMessenger::Get().SendMessage(msg, false); if (!m_flushEvent.WaitMSec(1000)) { CLog::Log(LOGERROR, "%s - timed out waiting for renderer to flush", __FUNCTION__); @@ -647,6 +648,12 @@ float CXBMCRenderManager::GetMaximumFPS() return fps; } +void CXBMCRenderManager::RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn) +{ + if (m_pRenderer) + m_pRenderer->RegisterRenderUpdateCallBack(ctx, fn); +} + void CXBMCRenderManager::Render(bool clear, DWORD flags, DWORD alpha) { CSharedLock lock(m_sharedSection); diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h index 8605eed520..062fd5daf8 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.h +++ b/xbmc/cores/VideoRenderers/RenderManager.h @@ -66,7 +66,7 @@ public: void SetViewMode(int iViewMode); // Functions called from mplayer - bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format); + bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation); bool IsConfigured(); int AddVideoPicture(DVDVideoPicture& picture); @@ -131,6 +131,8 @@ public: CSharedSection& GetSection() { return m_sharedSection; }; + void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn); + protected: void Render(bool clear, DWORD flags, DWORD alpha); diff --git a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp index e666a067af..58f26b0972 100644 --- a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp +++ b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp @@ -120,9 +120,9 @@ void CalculateYUVMatrix(TransformMatrix &matrix if(format == RENDER_FMT_YUV420P10) { - matrix *= TransformMatrix::CreateScaler(65535.0 / 1023.0 - , 65535.0 / 1023.0 - , 65535.0 / 1023.0); + matrix *= TransformMatrix::CreateScaler(65535.0f / 1023.0f + , 65535.0f / 1023.0f + , 65535.0f / 1023.0f); } } diff --git a/xbmc/cores/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoRenderers/WinRenderer.cpp index c86cc3dc35..f743656574 100644 --- a/xbmc/cores/VideoRenderers/WinRenderer.cpp +++ b/xbmc/cores/VideoRenderers/WinRenderer.cpp @@ -211,7 +211,7 @@ bool CWinRenderer::UpdateRenderMethod() return true; } -bool CWinRenderer::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format) +bool CWinRenderer::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation) { if(m_sourceWidth != width || m_sourceHeight != height) @@ -927,7 +927,10 @@ bool CWinRenderer::RenderCapture(CRenderCapture* capture) LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice(); CRect saveSize = m_destRect; + saveRotatedCoords();//backup current m_rotatedDestCoords + m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight()); + syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords LPDIRECT3DSURFACE9 oldSurface; pD3DDevice->GetRenderTarget(0, &oldSurface); @@ -946,6 +949,7 @@ bool CWinRenderer::RenderCapture(CRenderCapture* capture) oldSurface->Release(); m_destRect = saveSize; + restoreRotatedCoords();//restores the previous state of the rotated dest coords return succeeded; } diff --git a/xbmc/cores/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoRenderers/WinRenderer.h index 527651f0c7..807284b9b1 100644 --- a/xbmc/cores/VideoRenderers/WinRenderer.h +++ b/xbmc/cores/VideoRenderers/WinRenderer.h @@ -155,7 +155,7 @@ public: bool RenderCapture(CRenderCapture* capture); // Player functions - virtual bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format); + virtual bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation); virtual int GetImage(YV12Image *image, int source = AUTOSOURCE, bool readonly = false); virtual void ReleaseImage(int source, bool preserve = false); virtual bool AddVideoPicture(DVDVideoPicture* picture); diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp new file mode 100644 index 0000000000..64ebca7cd8 --- /dev/null +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -0,0 +1,2269 @@ +/* + * Copyright (C) 2011-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" + +#include "AMLPlayer.h" +#include "Application.h" +#include "FileItem.h" +#include "FileURLProtocol.h" +#include "GUIInfoManager.h" +#include "ThumbLoader.h" +#include "Util.h" +#include "cores/VideoRenderers/RenderFlags.h" +#include "cores/VideoRenderers/RenderFormats.h" +#include "cores/VideoRenderers/RenderManager.h" +#include "dialogs/GUIDialogKaiToast.h" +#include "filesystem/File.h" +#include "filesystem/SpecialProtocol.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "settings/AdvancedSettings.h" +#include "settings/GUISettings.h" +#include "settings/Settings.h" +#include "settings/VideoSettings.h" +#include "threads/SingleLock.h" +#include "utils/log.h" +#include "utils/TimeUtils.h" +#include "utils/URIUtils.h" +#include "utils/LangCodeExpander.h" +#include "utils/Variant.h" +#include "windowing/WindowingFactory.h" +#include "windowing/egl/WinEGLPlatform.h" + +// for external subtitles +#include "xbmc/cores/dvdplayer/DVDClock.h" +#include "xbmc/cores/dvdplayer/DVDPlayerSubtitle.h" +#include "xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.h" + +// amlogic libplayer +#include "DllLibamplayer.h" + +struct AMLChapterInfo +{ + std::string name; + int64_t seekto_ms; +}; + +struct AMLPlayerStreamInfo +{ + void Clear() + { + id = 0; + width = 0; + height = 0; + aspect_ratio_num = 0; + aspect_ratio_den = 0; + frame_rate_num = 0; + frame_rate_den = 0; + bit_rate = 0; + duration = 0; + channel = 0; + sample_rate = 0; + language = ""; + type = STREAM_NONE; + source = STREAM_SOURCE_NONE; + name = ""; + filename = ""; + filename2 = ""; + } + + int id; + StreamType type; + StreamSource source; + int width; + int height; + int aspect_ratio_num; + int aspect_ratio_den; + int frame_rate_num; + int frame_rate_den; + int bit_rate; + int duration; + int channel; + int sample_rate; + int format; + std::string language; + std::string name; + std::string filename; + std::string filename2; // for vobsub subtitles, 2 files are necessary (idx/sub) +}; + + +static int set_sysfs_str(const char *path, const char *val) +{ + int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); + if (fd >= 0) + { + write(fd, val, strlen(val)); + close(fd); + return 0; + } + return -1; +} + +static int set_sysfs_int(const char *path, const int val) +{ + char bcmd[16]; + int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); + if (fd >= 0) + { + sprintf(bcmd, "%d", val); + write(fd, bcmd, strlen(bcmd)); + close(fd); + return 0; + } + return -1; +} + +//////////////////////////////////////////////////////////////////////////////////////////// +static int media_info_dump(media_info_t* minfo) +{ + int i = 0; + CLog::Log(LOGDEBUG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + CLog::Log(LOGDEBUG, "======||file size:%lld", minfo->stream_info.file_size); + CLog::Log(LOGDEBUG, "======||file type:%d", minfo->stream_info.type); + CLog::Log(LOGDEBUG, "======||duration:%d", minfo->stream_info.duration); + CLog::Log(LOGDEBUG, "======||has video track?:%s", minfo->stream_info.has_video>0?"YES!":"NO!"); + CLog::Log(LOGDEBUG, "======||has audio track?:%s", minfo->stream_info.has_audio>0?"YES!":"NO!"); + CLog::Log(LOGDEBUG, "======||has internal subtitle?:%s", minfo->stream_info.has_sub>0?"YES!":"NO!"); + CLog::Log(LOGDEBUG, "======||internal subtile counts:%d", minfo->stream_info.total_sub_num); + if (minfo->stream_info.has_video && minfo->stream_info.total_video_num > 0) + { + CLog::Log(LOGDEBUG, "======||video index:%d", minfo->stream_info.cur_video_index); + CLog::Log(LOGDEBUG, "======||video counts:%d", minfo->stream_info.total_video_num); + CLog::Log(LOGDEBUG, "======||video width :%d", minfo->video_info[0]->width); + CLog::Log(LOGDEBUG, "======||video height:%d", minfo->video_info[0]->height); + CLog::Log(LOGDEBUG, "======||video ratio :%d:%d", minfo->video_info[0]->aspect_ratio_num,minfo->video_info[0]->aspect_ratio_den); + CLog::Log(LOGDEBUG, "======||frame_rate :%.2f", (float)minfo->video_info[0]->frame_rate_num/minfo->video_info[0]->frame_rate_den); + CLog::Log(LOGDEBUG, "======||video bitrate:%d", minfo->video_info[0]->bit_rate); + CLog::Log(LOGDEBUG, "======||video format:%d", minfo->video_info[0]->format); + CLog::Log(LOGDEBUG, "======||video duration:%d", minfo->video_info[0]->duartion); + } + if (minfo->stream_info.has_audio && minfo->stream_info.total_audio_num > 0) + { + CLog::Log(LOGDEBUG, "======||audio index:%d", minfo->stream_info.cur_audio_index); + CLog::Log(LOGDEBUG, "======||audio counts:%d", minfo->stream_info.total_audio_num); + for (i = 0; i < minfo->stream_info.total_audio_num; i++) + { + CLog::Log(LOGDEBUG, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); + CLog::Log(LOGDEBUG, "======||audio track(%d) id:%d", i, minfo->audio_info[i]->id); + CLog::Log(LOGDEBUG, "======||audio track(%d) codec type:%d", i, minfo->audio_info[i]->aformat); + CLog::Log(LOGDEBUG, "======||audio track(%d) audio_channel:%d", i, minfo->audio_info[i]->channel); + CLog::Log(LOGDEBUG, "======||audio track(%d) bit_rate:%d", i, minfo->audio_info[i]->bit_rate); + CLog::Log(LOGDEBUG, "======||audio track(%d) audio_samplerate:%d", i, minfo->audio_info[i]->sample_rate); + CLog::Log(LOGDEBUG, "======||audio track(%d) duration:%d", i, minfo->audio_info[i]->duration); + CLog::Log(LOGDEBUG, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); + if (NULL != minfo->audio_info[i]->audio_tag) + { + CLog::Log(LOGDEBUG, "======||audio track title:%s", minfo->audio_info[i]->audio_tag->title!=NULL?minfo->audio_info[i]->audio_tag->title:"unknown"); + CLog::Log(LOGDEBUG, "======||audio track album:%s", minfo->audio_info[i]->audio_tag->album!=NULL?minfo->audio_info[i]->audio_tag->album:"unknown"); + CLog::Log(LOGDEBUG, "======||audio track author:%s", minfo->audio_info[i]->audio_tag->author!=NULL?minfo->audio_info[i]->audio_tag->author:"unknown"); + CLog::Log(LOGDEBUG, "======||audio track year:%s", minfo->audio_info[i]->audio_tag->year!=NULL?minfo->audio_info[i]->audio_tag->year:"unknown"); + CLog::Log(LOGDEBUG, "======||audio track comment:%s", minfo->audio_info[i]->audio_tag->comment!=NULL?minfo->audio_info[i]->audio_tag->comment:"unknown"); + CLog::Log(LOGDEBUG, "======||audio track genre:%s", minfo->audio_info[i]->audio_tag->genre!=NULL?minfo->audio_info[i]->audio_tag->genre:"unknown"); + CLog::Log(LOGDEBUG, "======||audio track copyright:%s", minfo->audio_info[i]->audio_tag->copyright!=NULL?minfo->audio_info[i]->audio_tag->copyright:"unknown"); + CLog::Log(LOGDEBUG, "======||audio track track:%d", minfo->audio_info[i]->audio_tag->track); + } + } + } + if (minfo->stream_info.has_sub && minfo->stream_info.total_sub_num > 0) + { + CLog::Log(LOGDEBUG, "======||subtitle index:%d", minfo->stream_info.cur_sub_index); + CLog::Log(LOGDEBUG, "======||subtitle counts:%d", minfo->stream_info.total_sub_num); + for (i = 0; i < minfo->stream_info.total_sub_num; i++) + { + if (0 == minfo->sub_info[i]->internal_external){ + CLog::Log(LOGDEBUG, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); + CLog::Log(LOGDEBUG, "======||internal subtitle(%d) pid:%d", i, minfo->sub_info[i]->id); + CLog::Log(LOGDEBUG, "======||internal subtitle(%d) language:%s", i, minfo->sub_info[i]->sub_language?minfo->sub_info[i]->sub_language:"unknown"); + CLog::Log(LOGDEBUG, "======||internal subtitle(%d) width:%d", i, minfo->sub_info[i]->width); + CLog::Log(LOGDEBUG, "======||internal subtitle(%d) height:%d", i, minfo->sub_info[i]->height); + CLog::Log(LOGDEBUG, "======||internal subtitle(%d) resolution:%d", i, minfo->sub_info[i]->resolution); + CLog::Log(LOGDEBUG, "======||internal subtitle(%d) subtitle size:%lld", i, minfo->sub_info[i]->subtitle_size); + CLog::Log(LOGDEBUG, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); + } + } + } + CLog::Log(LOGDEBUG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + return 0; +} + +static const char* VideoCodecName(int vformat) +{ + const char *format = ""; + + switch(vformat) + { + case VFORMAT_MPEG12: + format = "mpeg12"; + break; + case VFORMAT_MPEG4: + format = "mpeg4"; + break; + case VFORMAT_H264: + format = "h264"; + break; + case VFORMAT_MJPEG: + format = "mjpeg"; + break; + case VFORMAT_REAL: + format = "real"; + break; + case VFORMAT_JPEG: + format = "jpeg"; + break; + case VFORMAT_VC1: + format = "vc1"; + break; + case VFORMAT_AVS: + format = "avs"; + break; + case VFORMAT_SW: + format = "sw"; + break; + case VFORMAT_H264MVC: + format = "h264mvc"; + break; + default: + format = "unknown"; + break; + } + return format; +} + +static const char* AudioCodecName(int aformat) +{ + const char *format = ""; + + switch(aformat) + { + case AFORMAT_MPEG: + format = "mpeg"; + break; + case AFORMAT_PCM_S16LE: + format = "pcm"; + break; + case AFORMAT_AAC: + format = "aac"; + break; + case AFORMAT_AC3: + format = "ac3"; + break; + case AFORMAT_ALAW: + format = "alaw"; + break; + case AFORMAT_MULAW: + format = "mulaw"; + break; + case AFORMAT_DTS: + format = "dts"; + break; + case AFORMAT_PCM_S16BE: + format = "pcm"; + break; + case AFORMAT_FLAC: + format = "flac"; + break; + case AFORMAT_COOK: + format = "cook"; + break; + case AFORMAT_PCM_U8: + format = "pcm"; + break; + case AFORMAT_ADPCM: + format = "adpcm"; + break; + case AFORMAT_AMR: + format = "amr"; + break; + case AFORMAT_RAAC: + format = "raac"; + break; + case AFORMAT_WMA: + format = "wma"; + break; + case AFORMAT_WMAPRO: + format = "wmapro"; + break; + case AFORMAT_PCM_BLURAY: + format = "lpcm"; + break; + case AFORMAT_ALAC: + format = "alac"; + break; + case AFORMAT_VORBIS: + format = "vorbis"; + break; + default: + format = "unknown"; + break; + } + + return format; +} + +//////////////////////////////////////////////////////////////////////////////////////////// +CAMLSubTitleThread::CAMLSubTitleThread(DllLibAmplayer *dll) : + CThread("CAMLSubTitleThread"), + m_dll(dll), + m_subtitle_codec(-1) +{ +} + +CAMLSubTitleThread::~CAMLSubTitleThread() +{ + StopThread(); +} + +void CAMLSubTitleThread::UpdateSubtitle(CStdString &subtitle, int64_t elapsed_ms) +{ + CSingleLock lock(m_subtitle_csection); + if (m_subtitle_strings.size()) + { + AMLSubtitle *amlsubtitle; + // remove any expired subtitles + std::deque<AMLSubtitle*>::iterator it = m_subtitle_strings.begin(); + while (it != m_subtitle_strings.end()) + { + amlsubtitle = *it; + if (elapsed_ms > amlsubtitle->endtime) + it = m_subtitle_strings.erase(it); + else + it++; + } + + // find the current subtitle + it = m_subtitle_strings.begin(); + while (it != m_subtitle_strings.end()) + { + amlsubtitle = *it; + if (elapsed_ms > amlsubtitle->bgntime && elapsed_ms < amlsubtitle->endtime) + { + subtitle = amlsubtitle->string; + break; + } + it++; + } + } +} + +void CAMLSubTitleThread::Process(void) +{ + CLog::Log(LOGDEBUG, "CAMLSubTitleThread::Process begin"); + + m_subtitle_codec = m_dll->codec_open_sub_read(); + if (m_subtitle_codec < 0) + CLog::Log(LOGERROR, "CAMLSubTitleThread::Process: codec_open_sub_read failed"); + + while (!m_bStop) + { + if (m_subtitle_codec > 0) + { + // poll sub codec, we return on timeout or when a sub gets loaded + // TODO: codec_poll_sub_fd has a bug in kernel driver, it trashes + // subs in certain conditions so we read garbage, manual poll for now. + //codec_poll_sub_fd(m_subtitle_codec, 1000); + int sub_size = m_dll->codec_get_sub_size_fd(m_subtitle_codec); + if (sub_size > 0) + { + int sub_type = 0, sub_pts = 0; + // calloc sub_size + 1 so we auto terminate the string + char *sub_buffer = (char*)calloc(sub_size + 1, 1); + m_dll->codec_read_sub_data_fd(m_subtitle_codec, sub_buffer, sub_size); + + // check subtitle header stamp + if ((sub_buffer[0] == 0x41) && (sub_buffer[1] == 0x4d) && + (sub_buffer[2] == 0x4c) && (sub_buffer[3] == 0x55) && + (sub_buffer[4] == 0xaa)) + { + // 20 byte header, then subtitle string + if (sub_size >= 20) + { + // csection lock it now as we are diddling shared vars + CSingleLock lock(m_subtitle_csection); + + AMLSubtitle *subtitle = new AMLSubtitle; + + sub_type = (sub_buffer[5] << 16) | (sub_buffer[6] << 8) | sub_buffer[7]; + // sub_pts are in ffmpeg timebase, not ms timebase, convert it. + sub_pts = (sub_buffer[12] << 24) | (sub_buffer[13] << 16) | (sub_buffer[14] << 8) | sub_buffer[15]; + + /* TODO: handle other subtitle codec types + // subtitle codecs + CODEC_ID_DVD_SUBTITLE= 0x17000, + CODEC_ID_DVB_SUBTITLE, + CODEC_ID_TEXT, ///< raw UTF-8 text + CODEC_ID_XSUB, + CODEC_ID_SSA, + CODEC_ID_MOV_TEXT, + CODEC_ID_HDMV_PGS_SUBTITLE, + CODEC_ID_DVB_TELETEXT, + CODEC_ID_SRT, + CODEC_ID_MICRODVD, + */ + switch(sub_type) + { + default: + CLog::Log(LOGDEBUG, "CAMLSubTitleThread::Process: fixme :) " + "sub_type(0x%x), size(%d), bgntime(%lld), endtime(%lld), string(%s)", + sub_type, sub_size-20, subtitle->bgntime, subtitle->endtime, &sub_buffer[20]); + break; + case CODEC_ID_TEXT: + subtitle->bgntime = sub_pts/ 90; + subtitle->endtime = subtitle->bgntime + 4000; + subtitle->string = &sub_buffer[20]; + break; + case CODEC_ID_SSA: + if (strncmp((const char*)&sub_buffer[20], "Dialogue:", 9) == 0) + { + int vars_found, hour1, min1, sec1, hunsec1, hour2, min2, sec2, hunsec2, nothing; + char line3[sub_size]; + char *line = &sub_buffer[20]; + + memset(line3, 0x00, sub_size); + vars_found = sscanf(line, "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d,%[^\n\r]", + ¬hing, &hour1, &min1, &sec1, &hunsec1, &hour2, &min2, &sec2, &hunsec2, line3); + if (vars_found < 10) + vars_found = sscanf(line, "Dialogue: %d,%d:%d:%d.%d,%d:%d:%d.%d,%[^\n\r]", + ¬hing, &hour1, &min1, &sec1, &hunsec1, &hour2, &min2, &sec2, &hunsec2, line3); + + if (vars_found > 9) + { + char *tmp, *line2 = strchr(line3, ','); + // use 32 for the case that the amount of commas increase with newer SSA versions + for (int comma = 4; comma < 32; comma++) + { + tmp = strchr(line2 + 1, ','); + if (!tmp) + break; + if (*(++tmp) == ' ') + break; + // a space after a comma means we are already in a sentence + line2 = tmp; + } + // eliminate the trailing comma + if (*line2 == ',') + line2++; + subtitle->bgntime = 10 * (360000 * hour1 + 6000 * min1 + 100 * sec1 + hunsec1); + subtitle->endtime = 10 * (360000 * hour2 + 6000 * min2 + 100 * sec2 + hunsec2); + subtitle->string = line2; + // convert tags to what we understand + if (subtitle->string.Replace("{\\i1}","[I]")) + subtitle->string.Replace("{\\i0}","[/I]"); + if (subtitle->string.Replace("{\\b1}","[B]")) + subtitle->string.Replace("{\\b0}","[/B]"); + // remove anything other tags + for (std::string::const_iterator it = subtitle->string.begin(); it != subtitle->string.end(); ++it) + { + size_t beg = subtitle->string.find("{\\"); + if (beg != std::string::npos) + { + size_t end = subtitle->string.find("}", beg); + if (end != std::string::npos) + subtitle->string.erase(beg, end-beg+1); + } + } + } + } + break; + } + free(sub_buffer); + + if (subtitle->string.length()) + { + // quirks + subtitle->string.Replace("'","\'"); + m_subtitle_strings.push_back(subtitle); + // fixup existing endtimes so they do not exceed bgntime of previous subtitle + for (size_t i = 0; i < m_subtitle_strings.size() - 1; i++) + { + if (m_subtitle_strings[i]->endtime > m_subtitle_strings[i+1]->bgntime) + m_subtitle_strings[i]->endtime = m_subtitle_strings[i+1]->bgntime; + } + } + } + } + } + else + { + usleep(100 * 1000); + } + } + else + { + usleep(250 * 1000); + } + } + m_subtitle_strings.clear(); + if (m_subtitle_codec > 0) + m_dll->codec_close_sub_fd(m_subtitle_codec); + m_subtitle_codec = -1; + + CLog::Log(LOGDEBUG, "CAMLSubTitleThread::Process end"); +} +//////////////////////////////////////////////////////////////////////////////////////////// +CAMLPlayer::CAMLPlayer(IPlayerCallback &callback) + : IPlayer(callback), + CThread("CAMLPlayer"), + m_ready(true) +{ + m_dll = new DllLibAmplayer; + m_dll->Load(); + m_pid = -1; + m_speed = 0; + m_paused = false; +#if defined(_DEBUG) + m_log_level = 5; +#else + m_log_level = 3; +#endif + m_StopPlaying = false; + + // for external subtitles + m_dvdOverlayContainer = new CDVDOverlayContainer; + m_dvdPlayerSubtitle = new CDVDPlayerSubtitle(m_dvdOverlayContainer); +} + +CAMLPlayer::~CAMLPlayer() +{ + CloseFile(); + + delete m_dvdPlayerSubtitle; + delete m_dvdOverlayContainer; + delete m_dll, m_dll = NULL; +} + +bool CAMLPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options) +{ + try + { + CLog::Log(LOGNOTICE, "CAMLPlayer: Opening: %s", file.GetPath().c_str()); + // if playing a file close it first + // this has to be changed so we won't have to close it. + if (IsRunning()) + CloseFile(); + + m_item = file; + m_options = options; + + m_elapsed_ms = 0; + m_duration_ms = 0; + + m_audio_info = "none"; + m_audio_delay = g_settings.m_currentVideoSettings.m_AudioDelay; + m_audio_passthrough_ac3 = g_guiSettings.GetBool("audiooutput.ac3passthrough"); + m_audio_passthrough_dts = g_guiSettings.GetBool("audiooutput.dtspassthrough"); + + m_video_info = "none"; + m_video_width = 0; + m_video_height = 0; + m_video_fps_numerator = 25; + m_video_fps_denominator = 1; + + m_subtitle_delay = 0; + m_subtitle_thread = NULL; + + m_chapter_index = 0; + m_chapter_count = 0; + + m_show_mainvideo = -1; + m_dst_rect.SetRect(0, 0, 0, 0); + m_zoom = -1; + m_contrast = -1; + m_brightness = -1; + + ClearStreamInfos(); + + m_StopPlaying = false; + // setup to spin the busy dialog until we are playing + m_ready.Reset(); + + g_renderManager.PreInit(); + + // create the playing thread + Create(); + if (!m_ready.WaitMSec(100)) + { + CGUIDialogBusy *dialog = (CGUIDialogBusy*)g_windowManager.GetWindow(WINDOW_DIALOG_BUSY); + dialog->Show(); + while (!m_StopPlaying && !m_ready.WaitMSec(1)) + g_windowManager.ProcessRenderLoop(false); + dialog->Close(); + } + + // Playback might have been stopped due to some error. + if (m_bStop || m_StopPlaying) + return false; + + return true; + } + catch (...) + { + CLog::Log(LOGERROR, "%s - Exception thrown on open", __FUNCTION__); + return false; + } +} + +bool CAMLPlayer::CloseFile() +{ + CLog::Log(LOGDEBUG, "CAMLPlayer::CloseFile"); + + // set the abort request so that other threads can finish up + m_StopPlaying = true; + + CLog::Log(LOGDEBUG, "CAMLPlayer: waiting for threads to exit"); + // wait for the main thread to finish up + // since this main thread cleans up all other resources and threads + // we are done after the StopThread call + StopThread(); + + CLog::Log(LOGDEBUG, "CAMLPlayer: finished waiting"); + + g_renderManager.UnInit(); + + return true; +} + +bool CAMLPlayer::IsPlaying() const +{ + return !m_bStop; +} + +void CAMLPlayer::Pause() +{ + CLog::Log(LOGDEBUG, "CAMLPlayer::Pause"); + CSingleLock lock(m_aml_csection); + + if ((m_pid < 0) && m_StopPlaying) + return; + + if (m_paused) + m_dll->player_resume(m_pid); + else + m_dll->player_pause(m_pid); + + m_paused = !m_paused; +} + +bool CAMLPlayer::IsPaused() const +{ + return m_paused; +} + +bool CAMLPlayer::HasVideo() const +{ + return m_video_count > 0; +} + +bool CAMLPlayer::HasAudio() const +{ + return m_audio_count > 0; +} + +void CAMLPlayer::ToggleFrameDrop() +{ + CLog::Log(LOGDEBUG, "CAMLPlayer::ToggleFrameDrop"); +} + +bool CAMLPlayer::CanSeek() +{ + return GetTotalTime() > 0; +} + +void CAMLPlayer::Seek(bool bPlus, bool bLargeStep) +{ + // force updated to m_elapsed_ms, m_duration_ms. + GetStatus(); + + CSingleLock lock(m_aml_csection); + + // try chapter seeking first, chapter_index is ones based. + int chapter_index = GetChapter(); + if (bLargeStep) + { + // seek to next chapter + if (bPlus && (chapter_index < GetChapterCount())) + { + SeekChapter(chapter_index + 1); + return; + } + // seek to previous chapter + if (!bPlus && chapter_index) + { + SeekChapter(chapter_index - 1); + return; + } + } + + int64_t seek_ms; + if (g_advancedSettings.m_videoUseTimeSeeking) + { + if (bLargeStep && (GetTotalTime() > (2000 * g_advancedSettings.m_videoTimeSeekForwardBig))) + seek_ms = bPlus ? g_advancedSettings.m_videoTimeSeekForwardBig : g_advancedSettings.m_videoTimeSeekBackwardBig; + else + seek_ms = bPlus ? g_advancedSettings.m_videoTimeSeekForward : g_advancedSettings.m_videoTimeSeekBackward; + // convert to milliseconds + seek_ms *= 1000; + seek_ms += m_elapsed_ms; + } + else + { + float percent; + if (bLargeStep) + percent = bPlus ? g_advancedSettings.m_videoPercentSeekForwardBig : g_advancedSettings.m_videoPercentSeekBackwardBig; + else + percent = bPlus ? g_advancedSettings.m_videoPercentSeekForward : g_advancedSettings.m_videoPercentSeekBackward; + percent /= 100.0f; + percent += (float)m_elapsed_ms/(float)m_duration_ms; + // convert to milliseconds + seek_ms = m_duration_ms * percent; + } + + // handle stacked videos, dvdplayer does it so we do it too. + if (g_application.CurrentFileItem().IsStack() && + (seek_ms > m_duration_ms || seek_ms < 0)) + { + CLog::Log(LOGDEBUG, "CAMLPlayer::Seek: In mystery code, what did I do"); + g_application.SeekTime((seek_ms - m_elapsed_ms) * 0.001 + g_application.GetTime()); + // warning, don't access any object variables here as + // the object may have been destroyed + return; + } + + if (seek_ms <= 1000) + seek_ms = 1000; + + if (seek_ms > m_duration_ms) + seek_ms = m_duration_ms; + + // do seek here + g_infoManager.SetDisplayAfterSeek(100000); + SeekTime(seek_ms); + m_callback.OnPlayBackSeek((int)seek_ms, (int)(seek_ms - m_elapsed_ms)); + g_infoManager.SetDisplayAfterSeek(); +} + +bool CAMLPlayer::SeekScene(bool bPlus) +{ + CLog::Log(LOGDEBUG, "CAMLPlayer::SeekScene"); + return false; +} + +void CAMLPlayer::SeekPercentage(float fPercent) +{ + CSingleLock lock(m_aml_csection); + + // force updated to m_elapsed_ms, m_duration_ms. + GetStatus(); + + if (m_duration_ms) + { + int64_t seek_ms = fPercent * m_duration_ms / 100.0; + if (seek_ms <= 1000) + seek_ms = 1000; + + // do seek here + g_infoManager.SetDisplayAfterSeek(100000); + SeekTime(seek_ms); + m_callback.OnPlayBackSeek((int)seek_ms, (int)(seek_ms - m_elapsed_ms)); + g_infoManager.SetDisplayAfterSeek(); + } +} + +float CAMLPlayer::GetPercentage() +{ + GetStatus(); + if (m_duration_ms) + return 100.0f * (float)m_elapsed_ms/(float)m_duration_ms; + else + return 0.0f; +} + +void CAMLPlayer::SetVolume(float volume) +{ + CLog::Log(LOGDEBUG, "CAMLPlayer::SetVolume(%f)", volume); +#if !defined(TARGET_ANDROID) + CSingleLock lock(m_aml_csection); + // volume is a float percent from 0.0 to 1.0 + if (m_dll->check_pid_valid(m_pid)) + m_dll->audio_set_volume(m_pid, volume); +#endif +} + +void CAMLPlayer::GetAudioInfo(CStdString &strAudioInfo) +{ + CSingleLock lock(m_aml_csection); + if (m_audio_streams.size() == 0 || m_audio_index > (int)(m_audio_streams.size() - 1)) + return; + + strAudioInfo.Format("Audio stream (%s) [Kb/s:%.2f]", + AudioCodecName(m_audio_streams[m_audio_index]->format), + (double)m_audio_streams[m_audio_index]->bit_rate / 1024.0); +} + +void CAMLPlayer::GetVideoInfo(CStdString &strVideoInfo) +{ + CSingleLock lock(m_aml_csection); + if (m_video_streams.size() == 0 || m_video_index > (int)(m_video_streams.size() - 1)) + return; + + strVideoInfo.Format("Video stream (%s) [fr:%.3f Mb/s:%.2f]", + VideoCodecName(m_video_streams[m_video_index]->format), + GetActualFPS(), + (double)m_video_streams[m_video_index]->bit_rate / (1024.0*1024.0)); +} + +int CAMLPlayer::GetAudioStreamCount() +{ + //CLog::Log(LOGDEBUG, "CAMLPlayer::GetAudioStreamCount"); + return m_audio_count; +} + +int CAMLPlayer::GetAudioStream() +{ + //CLog::Log(LOGDEBUG, "CAMLPlayer::GetAudioStream"); + return m_audio_index; +} + +void CAMLPlayer::GetAudioStreamName(int iStream, CStdString &strStreamName) +{ + //CLog::Log(LOGDEBUG, "CAMLPlayer::GetAudioStreamName"); + CSingleLock lock(m_aml_csection); + + strStreamName.Format("Undefined"); + + if (iStream > (int)m_audio_streams.size() || iStream < 0) + return; + + if ( m_audio_streams[iStream]->language.size()) + { + CStdString name; + g_LangCodeExpander.Lookup( name, m_audio_streams[iStream]->language); + strStreamName = name; + } + +} + +void CAMLPlayer::SetAudioStream(int SetAudioStream) +{ + //CLog::Log(LOGDEBUG, "CAMLPlayer::SetAudioStream"); + CSingleLock lock(m_aml_csection); + + if (SetAudioStream > (int)m_audio_streams.size() || SetAudioStream < 0) + return; + + m_audio_index = SetAudioStream; + SetAudioPassThrough(m_audio_streams[m_audio_index]->format); + + if (m_dll->check_pid_valid(m_pid)) + { + m_dll->player_aid(m_pid, m_audio_streams[m_audio_index]->id); + } +} + +void CAMLPlayer::SetSubTitleDelay(float fValue = 0.0f) +{ + if (GetSubtitleCount()) + { + CSingleLock lock(m_aml_csection); + m_subtitle_delay = fValue * 1000.0; + } +} + +float CAMLPlayer::GetSubTitleDelay() +{ + return (float)m_subtitle_delay / 1000.0; +} + +int CAMLPlayer::GetSubtitleCount() +{ + return m_subtitle_count; +} + +int CAMLPlayer::GetSubtitle() +{ + if (m_subtitle_show) + return m_subtitle_index; + else + return -1; +} + +void CAMLPlayer::GetSubtitleName(int iStream, CStdString &strStreamName) +{ + CSingleLock lock(m_aml_csection); + + strStreamName = ""; + + if (iStream > (int)m_subtitle_streams.size() || iStream < 0) + return; + + if (m_subtitle_streams[m_subtitle_index]->source == STREAM_SOURCE_NONE) + { + if ( m_subtitle_streams[iStream]->language.size()) + { + CStdString name; + g_LangCodeExpander.Lookup(name, m_subtitle_streams[iStream]->language); + strStreamName = name; + } + else + strStreamName = g_localizeStrings.Get(13205); // Unknown + } + else + { + if(m_subtitle_streams[m_subtitle_index]->name.length() > 0) + strStreamName = m_subtitle_streams[m_subtitle_index]->name; + else + strStreamName = g_localizeStrings.Get(13205); // Unknown + } + if (m_log_level > 5) + CLog::Log(LOGDEBUG, "CAMLPlayer::GetSubtitleName, iStream(%d)", iStream); +} + +void CAMLPlayer::SetSubtitle(int iStream) +{ + CSingleLock lock(m_aml_csection); + + if (iStream > (int)m_subtitle_streams.size() || iStream < 0) + return; + + m_subtitle_index = iStream; + + // smells like a bug, if no showing subs and we get called + // to set the subtitle, we are expected to update internal state + // but not show the subtitle. + if (!m_subtitle_show) + return; + + if (m_dll->check_pid_valid(m_pid) && m_subtitle_streams[m_subtitle_index]->source == STREAM_SOURCE_NONE) + m_dll->player_sid(m_pid, m_subtitle_streams[m_subtitle_index]->id); + else + { + m_dvdPlayerSubtitle->CloseStream(true); + OpenSubtitleStream(m_subtitle_index); + } +} + +bool CAMLPlayer::GetSubtitleVisible() +{ + return m_subtitle_show; +} + +void CAMLPlayer::SetSubtitleVisible(bool bVisible) +{ + m_subtitle_show = (bVisible && m_subtitle_count); + g_settings.m_currentVideoSettings.m_SubtitleOn = bVisible; + + if (m_subtitle_show && m_subtitle_count) + { + // on startup, if asked to show subs and SetSubtitle has not + // been called, we are expected to switch/show the 1st subtitle + if (m_subtitle_index < 0) + m_subtitle_index = 0; + if (m_dll->check_pid_valid(m_pid) && m_subtitle_streams[m_subtitle_index]->source == STREAM_SOURCE_NONE) + m_dll->player_sid(m_pid, m_subtitle_streams[m_subtitle_index]->id); + else + OpenSubtitleStream(m_subtitle_index); + } +} + +int CAMLPlayer::AddSubtitle(const CStdString& strSubPath) +{ + CSingleLock lock(m_aml_csection); + + return AddSubtitleFile(strSubPath); +} + +void CAMLPlayer::Update(bool bPauseDrawing) +{ + g_renderManager.Update(bPauseDrawing); +} + +void CAMLPlayer::GetVideoRect(CRect& SrcRect, CRect& DestRect) +{ + g_renderManager.GetVideoRect(SrcRect, DestRect); +} + +void CAMLPlayer::GetVideoAspectRatio(float &fAR) +{ + fAR = g_renderManager.GetAspectRatio(); +} + +int CAMLPlayer::GetChapterCount() +{ + return m_chapter_count; +} + +int CAMLPlayer::GetChapter() +{ + GetStatus(); + + for (int i = 0; i < m_chapter_count - 1; i++) + { + if (m_elapsed_ms >= m_chapters[i]->seekto_ms && m_elapsed_ms < m_chapters[i + 1]->seekto_ms) + return i + 1; + } + return 0; +} + +void CAMLPlayer::GetChapterName(CStdString& strChapterName) +{ + if (m_chapter_count) + strChapterName = m_chapters[GetChapter() - 1]->name; +} + +int CAMLPlayer::SeekChapter(int chapter_index) +{ + CSingleLock lock(m_aml_csection); + + // chapter_index is a one based value. + if (m_chapter_count > 1) + { + if (chapter_index < 1) + chapter_index = 1; + if (chapter_index > m_chapter_count) + return 0; + + // time units are seconds, + // so we add 1000ms to get into the chapter. + int64_t seek_ms = m_chapters[chapter_index - 1]->seekto_ms + 1000; + + // seek to 1 second and play is immediate. + if (seek_ms <= 0) + seek_ms = 1000; + + // seek to chapter here + g_infoManager.SetDisplayAfterSeek(100000); + SeekTime(seek_ms); + m_callback.OnPlayBackSeekChapter(chapter_index); + g_infoManager.SetDisplayAfterSeek(); + } + else + { + // we do not have a chapter list so do a regular big jump. + if (chapter_index > 0) + Seek(true, true); + else + Seek(false, true); + } + return 0; +} + +float CAMLPlayer::GetActualFPS() +{ + float video_fps = m_video_fps_numerator / m_video_fps_denominator; + CLog::Log(LOGDEBUG, "CAMLPlayer::GetActualFPS:m_video_fps(%f)", video_fps); + return video_fps; +} + +void CAMLPlayer::SeekTime(__int64 seek_ms) +{ + CSingleLock lock(m_aml_csection); + + // we cannot seek if paused + if (m_paused) + return; + + if (seek_ms <= 0) + seek_ms = 100; + + // seek here + if (m_dll->check_pid_valid(m_pid)) + { + if (!CheckPlaying()) + return; + // player_timesearch is seconds (float). + m_dll->player_timesearch(m_pid, (float)seek_ms/1000.0); + WaitForSearchOK(5000); + WaitForPlaying(5000); + } +} + +__int64 CAMLPlayer::GetTime() +{ + return m_elapsed_ms; +} + +__int64 CAMLPlayer::GetTotalTime() +{ + return m_duration_ms; +} + +int CAMLPlayer::GetAudioBitrate() +{ + CSingleLock lock(m_aml_csection); + if (m_audio_streams.size() == 0 || m_audio_index > (int)(m_audio_streams.size() - 1)) + return 0; + + return m_audio_streams[m_audio_index]->bit_rate; +} + +int CAMLPlayer::GetVideoBitrate() +{ + CSingleLock lock(m_aml_csection); + if (m_video_streams.size() == 0 || m_video_index > (int)(m_video_streams.size() - 1)) + return 0; + + return m_video_streams[m_video_index]->bit_rate; +} + +int CAMLPlayer::GetSourceBitrate() +{ + CLog::Log(LOGDEBUG, "CAMLPlayer::GetSourceBitrate"); + return 0; +} + +int CAMLPlayer::GetChannels() +{ + CSingleLock lock(m_aml_csection); + if (m_audio_streams.size() == 0 || m_audio_index > (int)(m_audio_streams.size() - 1)) + return 0; + + return m_audio_streams[m_audio_index]->channel; +} + +int CAMLPlayer::GetBitsPerSample() +{ + CLog::Log(LOGDEBUG, "CAMLPlayer::GetBitsPerSample"); + return 0; +} + +int CAMLPlayer::GetSampleRate() +{ + CSingleLock lock(m_aml_csection); + if (m_audio_streams.size() == 0 || m_audio_index > (int)(m_audio_streams.size() - 1)) + return 0; + + return m_audio_streams[m_audio_index]->sample_rate; +} + +CStdString CAMLPlayer::GetAudioCodecName() +{ + CStdString strAudioCodec = ""; + if (m_audio_streams.size() == 0 || m_audio_index > (int)(m_audio_streams.size() - 1)) + return strAudioCodec; + + strAudioCodec = AudioCodecName(m_audio_streams[m_audio_index]->format); + + return strAudioCodec; +} + +CStdString CAMLPlayer::GetVideoCodecName() +{ + CStdString strVideoCodec = ""; + if (m_video_streams.size() == 0 || m_video_index > (int)(m_video_streams.size() - 1)) + return strVideoCodec; + + strVideoCodec = VideoCodecName(m_video_streams[m_video_index]->format); + + return strVideoCodec; +} + +int CAMLPlayer::GetPictureWidth() +{ + //CLog::Log(LOGDEBUG, "CAMLPlayer::GetPictureWidth(%d)", m_video_width); + return m_video_width; +} + +int CAMLPlayer::GetPictureHeight() +{ + //CLog::Log(LOGDEBUG, "CAMLPlayer::GetPictureHeight(%)", m_video_height); + return m_video_height; +} + +bool CAMLPlayer::GetStreamDetails(CStreamDetails &details) +{ + //CLog::Log(LOGDEBUG, "CAMLPlayer::GetStreamDetails"); + return false; +} + +void CAMLPlayer::ToFFRW(int iSpeed) +{ + CLog::Log(LOGDEBUG, "CAMLPlayer::ToFFRW: iSpeed(%d), m_speed(%d)", iSpeed, m_speed); + CSingleLock lock(m_aml_csection); + + if (!m_dll->check_pid_valid(m_pid) && m_StopPlaying) + return; + + if (m_speed != iSpeed) + { + // recover power of two value + int ipower = 0; + int ispeed = abs(iSpeed); + while (ispeed >>= 1) ipower++; + + switch(ipower) + { + // regular playback + case 0: + m_dll->player_forward(m_pid, 0); + break; + default: + // N x fast forward/rewind (I-frames) + // speed playback 1,2,4,8 + if (iSpeed > 0) + m_dll->player_forward(m_pid, iSpeed); + else + m_dll->player_backward(m_pid, -iSpeed); + break; + } + + m_speed = iSpeed; + } +} + +bool CAMLPlayer::GetCurrentSubtitle(CStdString& strSubtitle) +{ + strSubtitle = ""; + + if (m_subtitle_count) + { + // force updated to m_elapsed_ms. + GetStatus(); + if (m_subtitle_streams[m_subtitle_index]->source == STREAM_SOURCE_NONE && m_subtitle_thread) + { + m_subtitle_thread->UpdateSubtitle(strSubtitle, m_elapsed_ms - m_subtitle_delay); + } + else + { + double pts = DVD_MSEC_TO_TIME(m_elapsed_ms) - DVD_MSEC_TO_TIME(m_subtitle_delay); + m_dvdOverlayContainer->CleanUp(pts); + m_dvdPlayerSubtitle->GetCurrentSubtitle(strSubtitle, pts); + } + } + + return !strSubtitle.IsEmpty(); +} + +void CAMLPlayer::OnStartup() +{ + //m_CurrentVideo.Clear(); + //m_CurrentAudio.Clear(); + //m_CurrentSubtitle.Clear(); + + //CThread::SetName("CAMLPlayer"); +} + +void CAMLPlayer::OnExit() +{ + //CLog::Log(LOGNOTICE, "CAMLPlayer::OnExit()"); + usleep(500 * 1000); + + m_bStop = true; + // if we didn't stop playing, advance to the next item in xbmc's playlist + if (m_options.identify == false) + { + if (m_StopPlaying) + m_callback.OnPlayBackStopped(); + else + m_callback.OnPlayBackEnded(); + } + // set event to inform openfile something went wrong + // in case openfile is still waiting for this event + m_ready.Set(); +} + +void CAMLPlayer::Process() +{ + CLog::Log(LOGNOTICE, "CAMLPlayer::Process"); + try + { + CJobManager::GetInstance().Pause(kJobTypeMediaFlags); + + if (CJobManager::GetInstance().IsProcessing(kJobTypeMediaFlags) > 0) + { + if (!WaitForPausedThumbJobs(20000)) + { + CJobManager::GetInstance().UnPause(kJobTypeMediaFlags); + throw "CAMLPlayer::Process:thumbgen jobs still running !!!"; + } + } + + static AML_URLProtocol vfs_protocol = { + "vfs", + CFileURLProtocol::Open, + CFileURLProtocol::Read, + CFileURLProtocol::Write, + CFileURLProtocol::Seek, + CFileURLProtocol::SeekEx, + CFileURLProtocol::Close, + }; + + CStdString url = m_item.GetPath(); + if (url.Left(strlen("smb://")).Equals("smb://")) + { + // the name string needs to persist + static const char *smb_name = "smb"; + vfs_protocol.name = smb_name; + } + else if (url.Left(strlen("afp://")).Equals("afp://")) + { + // the name string needs to persist + static const char *afp_name = "afp"; + vfs_protocol.name = afp_name; + } + else if (url.Left(strlen("nfs://")).Equals("nfs://")) + { + // the name string needs to persist + static const char *nfs_name = "nfs"; + vfs_protocol.name = nfs_name; + } + else if (url.Left(strlen("rar://")).Equals("rar://")) + { + // the name string needs to persist + static const char *rar_name = "rar"; + vfs_protocol.name = rar_name; + } + else if (url.Left(strlen("ftp://")).Equals("ftp://")) + { + // the name string needs to persist + static const char *http_name = "xb-ftp"; + vfs_protocol.name = http_name; + url = "xb-" + url; + } + else if (url.Left(strlen("ftps://")).Equals("ftps://")) + { + // the name string needs to persist + static const char *http_name = "xb-ftps"; + vfs_protocol.name = http_name; + url = "xb-" + url; + } + else if (url.Left(strlen("http://")).Equals("http://")) + { + // the name string needs to persist + static const char *http_name = "xb-http"; + vfs_protocol.name = http_name; + url = "xb-" + url; + } + else if (url.Left(strlen("https://")).Equals("https://")) + { + // the name string needs to persist + static const char *http_name = "xb-https"; + vfs_protocol.name = http_name; + url = "xb-" + url; + } + CLog::Log(LOGDEBUG, "CAMLPlayer::Process: URL=%s", url.c_str()); + + if (m_dll->player_init() != PLAYER_SUCCESS) + { + CLog::Log(LOGDEBUG, "player init failed"); + throw "CAMLPlayer::Process:player init failed"; + } + CLog::Log(LOGDEBUG, "player init......"); + usleep(250 * 1000); + + // must be after player_init + m_dll->av_register_protocol2(&vfs_protocol, sizeof(vfs_protocol)); + + static play_control_t play_control; + memset(&play_control, 0, sizeof(play_control_t)); + // if we do not register a callback, + // then the libamplayer will free run checking status. + m_dll->player_register_update_callback(&play_control.callback_fn, &UpdatePlayerInfo, 1000); + // amlplayer owns file_name and will release on exit + play_control.file_name = (char*)strdup(url.c_str()); + //play_control.nosound = 1; // if disable audio...,must call this api + play_control.video_index = -1; //MUST + play_control.audio_index = -1; //MUST + play_control.sub_index = -1; //MUST + play_control.hassub = 1; + if (m_options.starttime > 0) // player start position in seconds as is starttime + play_control.t_pos = m_options.starttime; + else + play_control.t_pos = -1; + play_control.need_start = 1; // if 0,you can omit player_start_play API. + // just play video/audio immediately. + // if 1,then need call "player_start_play" API; + //play_control.auto_buffing_enable = 1; + //play_control.buffing_min = 0.2; + //play_control.buffing_middle = 0.5; + //play_control.buffing_max = 0.8; + //play_control.byteiobufsize =; // maps to av_open_input_file buffer size + //play_control.loopbufsize =; + //play_control.enable_rw_on_pause =; + m_aml_state.clear(); + m_aml_state.push_back(0); + m_pid = m_dll->player_start(&play_control, 0); + if (m_pid < 0) + { + if (m_log_level > 5) + CLog::Log(LOGDEBUG, "player start failed! error = %d", m_pid); + throw "CAMLPlayer::Process:player start failed"; + } + + // wait for media to open with 30 second timeout. + if (WaitForFormatValid(30000)) + { + // start the playback. + int res = m_dll->player_start_play(m_pid); + if (res != PLAYER_SUCCESS) + throw "CAMLPlayer::Process:player_start_play() failed"; + } + else + { + throw "CAMLPlayer::Process:WaitForFormatValid timeout"; + } + + // hide the mainvideo layer so we can get stream info + // and setup/transition to gui video playback + // without having video playback blended into it. + if (m_item.IsVideo()) + ShowMainVideo(false); + + // wait for playback to start with 20 second timeout + if (WaitForPlaying(20000)) + { + m_speed = 1; + m_callback.OnPlayBackSpeedChanged(m_speed); + + // get our initial status. + GetStatus(); + + // restore system volume setting. + SetVolume(g_settings.m_fVolumeLevel); + + // drop CGUIDialogBusy dialog and release the hold in OpenFile. + m_ready.Set(); + + // we are playing but hidden and all stream fields are valid. + // check for video in media content + if (GetVideoStreamCount() > 0) + { + // turn on/off subs + SetSubtitleVisible(g_settings.m_currentVideoSettings.m_SubtitleOn); + SetSubTitleDelay(g_settings.m_currentVideoSettings.m_SubtitleDelay); + + // setup renderer for bypass. This tell renderer to get out of the way as + // hw decoder will be doing the actual video rendering in a video plane + // that is under the GUI layer. + int width = GetPictureWidth(); + int height = GetPictureHeight(); + double fFrameRate = GetActualFPS(); + unsigned int flags = 0; + + flags |= CONF_FLAGS_FULLSCREEN; + CStdString formatstr = "BYPASS"; + CLog::Log(LOGDEBUG,"%s - change configuration. %dx%d. framerate: %4.2f. format: %s", + __FUNCTION__, width, height, fFrameRate, formatstr.c_str()); + g_renderManager.IsConfigured(); + if (!g_renderManager.Configure(width, height, width, height, fFrameRate, flags, RENDER_FMT_BYPASS, 0, 0)) + { + CLog::Log(LOGERROR, "%s - failed to configure renderer", __FUNCTION__); + } + if (!g_renderManager.IsStarted()) + { + CLog::Log(LOGERROR, "%s - renderer not started", __FUNCTION__); + } + + g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack); + + m_subtitle_thread = new CAMLSubTitleThread(m_dll); + m_subtitle_thread->Create(); + } + + if (m_options.identify == false) + m_callback.OnPlayBackStarted(); + + while (!m_StopPlaying) + { + player_status pstatus = (player_status)GetPlayerSerializedState(); + switch(pstatus) + { + case PLAYER_INITING: + case PLAYER_TYPE_REDY: + case PLAYER_INITOK: + if (m_log_level > 5) + CLog::Log(LOGDEBUG, "CAMLPlayer::Process: %s", m_dll->player_status2str(pstatus)); + // player is parsing file, decoder not running + break; + + default: + case PLAYER_RUNNING: + GetStatus(); + // playback status, decoder is running + break; + + case PLAYER_START: + case PLAYER_BUFFERING: + case PLAYER_PAUSE: + case PLAYER_SEARCHING: + case PLAYER_SEARCHOK: + case PLAYER_FF_END: + case PLAYER_FB_END: + case PLAYER_PLAY_NEXT: + case PLAYER_BUFFER_OK: + if (m_log_level > 5) + CLog::Log(LOGDEBUG, "CAMLPlayer::Process: %s", m_dll->player_status2str(pstatus)); + break; + + case PLAYER_FOUND_SUB: + // found a NEW subtitle in stream. + // TODO: reload m_subtitle_streams + if (m_log_level > 5) + CLog::Log(LOGDEBUG, "CAMLPlayer::Process: %s", m_dll->player_status2str(pstatus)); + break; + + case PLAYER_PLAYEND: + GetStatus(); + if (m_log_level > 5) + CLog::Log(LOGDEBUG, "CAMLPlayer::Process: %s", m_dll->player_status2str(pstatus)); + break; + + case PLAYER_ERROR: + case PLAYER_STOPED: + case PLAYER_EXIT: + if (m_log_level > 5) + { + CLog::Log(LOGDEBUG, "CAMLPlayer::Process PLAYER_STOPED"); + CLog::Log(LOGDEBUG, "CAMLPlayer::Process: %s", m_dll->player_status2str(pstatus)); + } + m_StopPlaying = true; + break; + } + usleep(250 * 1000); + } + } + } + catch(char* error) + { + CLog::Log(LOGERROR, "%s", error); + } + catch(...) + { + CLog::Log(LOGERROR, "CAMLPlayer::Process Exception thrown"); + } + + if (m_log_level > 5) + CLog::Log(LOGDEBUG, "CAMLPlayer::Process stopped"); + if (m_dll->check_pid_valid(m_pid)) + { + delete m_subtitle_thread; + m_subtitle_thread = NULL; + m_dll->player_stop(m_pid); + m_dll->player_exit(m_pid); + m_pid = -1; + } + + // we are done, hide the mainvideo layer. + ShowMainVideo(false); + m_ready.Set(); + + ClearStreamInfos(); + + // reset ac3/dts passthough + SetAudioPassThrough(AFORMAT_UNKNOWN); + // let thumbgen jobs resume. + CJobManager::GetInstance().UnPause(kJobTypeMediaFlags); + + if (m_log_level > 5) + CLog::Log(LOGDEBUG, "CAMLPlayer::Process exit"); +} +/* +void CAMLPlayer::GetRenderFeatures(Features* renderFeatures) +{ + renderFeatures->push_back(RENDERFEATURE_ZOOM); + renderFeatures->push_back(RENDERFEATURE_CONTRAST); + renderFeatures->push_back(RENDERFEATURE_BRIGHTNESS); + renderFeatures->push_back(RENDERFEATURE_STRETCH); + return; +} + +void CAMLPlayer::GetDeinterlaceMethods(Features* deinterlaceMethods) +{ + deinterlaceMethods->push_back(VS_INTERLACEMETHOD_DEINTERLACE); + return; +} + +void CAMLPlayer::GetDeinterlaceModes(Features* deinterlaceModes) +{ + deinterlaceModes->push_back(VS_DEINTERLACEMODE_AUTO); + return; +} + +void CAMLPlayer::GetScalingMethods(Features* scalingMethods) +{ + return; +} + +void CAMLPlayer::GetAudioCapabilities(Features* audioCaps) +{ + audioCaps->push_back(IPC_AUD_SELECT_STREAM); + return; +} + +void CAMLPlayer::GetSubtitleCapabilities(Features* subCaps) +{ + subCaps->push_back(IPC_SUBS_EXTERNAL); + subCaps->push_back(IPC_SUBS_OFFSET); + subCaps->push_back(IPC_SUBS_SELECT); + return; +} +*/ + +//////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// +int CAMLPlayer::GetVideoStreamCount() +{ + //CLog::Log(LOGDEBUG, "CAMLPlayer::GetVideoStreamCount(%d)", m_video_count); + return m_video_count; +} + +void CAMLPlayer::ShowMainVideo(bool show) +{ + if (m_show_mainvideo == show) + return; + + set_sysfs_int("/sys/class/video/disable_video", show ? 0:1); + + m_show_mainvideo = show; +} + +void CAMLPlayer::SetVideoZoom(float zoom) +{ + // input zoom range is 0.5 to 2.0 with a default of 1.0. + // output zoom range is 2 to 300 with default of 100. + // we limit that to a range of 50 to 200 with default of 100. + set_sysfs_int("/sys/class/video/zoom", (int)(100 * zoom)); +} + +void CAMLPlayer::SetVideoContrast(int contrast) +{ + // input contrast range is 0 to 100 with default of 50. + // output contrast range is -255 to 255 with default of 0. + contrast = (255 * (contrast - 50)) / 50; + set_sysfs_int("/sys/class/video/contrast", contrast); +} +void CAMLPlayer::SetVideoBrightness(int brightness) +{ + // input brightness range is 0 to 100 with default of 50. + // output brightness range is -127 to 127 with default of 0. + brightness = (127 * (brightness - 50)) / 50; + set_sysfs_int("/sys/class/video/brightness", brightness); +} + +void CAMLPlayer::SetAudioPassThrough(int format) +{ + if (m_audio_passthrough_ac3 && format == AFORMAT_AC3) + set_sysfs_int("/sys/class/audiodsp/digital_raw", 1); + else if (m_audio_passthrough_dts && format == AFORMAT_DTS) + set_sysfs_int("/sys/class/audiodsp/digital_raw", 1); + else + set_sysfs_int("/sys/class/audiodsp/digital_raw", 0); +} + +bool CAMLPlayer::WaitForPausedThumbJobs(int timeout_ms) +{ + // use m_bStop and Sleep so we can get canceled. + while (!m_bStop && (timeout_ms > 0)) + { + if (CJobManager::GetInstance().IsProcessing(kJobTypeMediaFlags) > 0) + { + Sleep(100); + timeout_ms -= 100; + } + else + return true; + } + + return false; +} + +int CAMLPlayer::GetPlayerSerializedState(void) +{ + CSingleLock lock(m_aml_state_csection); + + int playerstate; + int dequeue_size = m_aml_state.size(); + + if (dequeue_size > 0) + { + // serialized state is the front element. + playerstate = m_aml_state.front(); + // pop the front element if there are + // more present. + if (dequeue_size > 1) + m_aml_state.pop_front(); + } + else + { + // if queue is empty (only at startup), + // pull the player state directly. this should + // really never happen but we need to cover it. + playerstate = m_dll->player_get_state(m_pid); + m_aml_state.push_back(playerstate); + } + + return playerstate; +} + + +int CAMLPlayer::UpdatePlayerInfo(int pid, player_info_t *info) +{ + // we get called when status changes or after update time expires. + // static callback from libamplayer, since it does not pass an opaque, + // we have to retreve our player class reference the hard way. + CAMLPlayer *amlplayer = dynamic_cast<CAMLPlayer*>(g_application.m_pPlayer); + if (amlplayer) + { + CSingleLock lock(amlplayer->m_aml_state_csection); + if (amlplayer->m_aml_state.back() != info->status) + { + //CLog::Log(LOGDEBUG, "update_player_info: %s, old state %s", player_status2str(info->status), player_status2str(info->last_sta)); + amlplayer->m_aml_state.push_back(info->status); + } + } + return 0; +} + +bool CAMLPlayer::CheckPlaying() +{ + return ((player_status)GetPlayerSerializedState() == PLAYER_RUNNING); +} + +bool CAMLPlayer::WaitForStopped(int timeout_ms) +{ + while (!m_StopPlaying && (timeout_ms > 0)) + { + player_status pstatus = (player_status)GetPlayerSerializedState(); + if (m_log_level > 5) + CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForStopped: %s", m_dll->player_status2str(pstatus)); + switch(pstatus) + { + default: + usleep(100 * 1000); + timeout_ms -= 100; + break; + case PLAYER_PLAYEND: + case PLAYER_STOPED: + case PLAYER_ERROR: + case PLAYER_EXIT: + m_StopPlaying = true; + return true; + break; + } + } + + return false; +} + +bool CAMLPlayer::WaitForSearchOK(int timeout_ms) +{ + while (!m_StopPlaying && (timeout_ms > 0)) + { + player_status pstatus = (player_status)GetPlayerSerializedState(); + if (m_log_level > 5) + CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForSearchOK: %s", m_dll->player_status2str(pstatus)); + switch(pstatus) + { + default: + usleep(100 * 1000); + timeout_ms -= 100; + break; + case PLAYER_STOPED: + return false; + case PLAYER_ERROR: + case PLAYER_EXIT: + m_StopPlaying = true; + return false; + break; + case PLAYER_SEARCHOK: + return true; + break; + } + } + + return false; +} + +bool CAMLPlayer::WaitForPlaying(int timeout_ms) +{ + while (!m_StopPlaying && (timeout_ms > 0)) + { + player_status pstatus = (player_status)GetPlayerSerializedState(); + if (m_log_level > 5) + CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForPlaying: %s", m_dll->player_status2str(pstatus)); + switch(pstatus) + { + default: + usleep(100 * 1000); + timeout_ms -= 100; + break; + case PLAYER_ERROR: + case PLAYER_EXIT: + m_StopPlaying = true; + return false; + break; + case PLAYER_RUNNING: + return true; + break; + } + } + + return false; +} + +bool CAMLPlayer::WaitForFormatValid(int timeout_ms) +{ + while (timeout_ms > 0) + { + player_status pstatus = (player_status)GetPlayerSerializedState(); + if (m_log_level > 5) + CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForFormatValid: %s", m_dll->player_status2str(pstatus)); + switch(pstatus) + { + default: + usleep(100 * 1000); + timeout_ms -= 100; + break; + case PLAYER_ERROR: + case PLAYER_EXIT: + m_StopPlaying = true; + return false; + break; + case PLAYER_INITOK: + + ClearStreamInfos(); + + media_info_t media_info; + int res = m_dll->player_get_media_info(m_pid, &media_info); + if (res != PLAYER_SUCCESS) + return false; + + if (m_log_level > 5) + { + media_info_dump(&media_info); + + // m_video_index, m_audio_index, m_subtitle_index might be -1 eventhough + // total_video_xxx is > 0, not sure why, they should be set to zero or + // some other sensible value. + CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForFormatValid: " + "m_video_index(%d), m_audio_index(%d), m_subtitle_index(%d), m_chapter_count(%d)", + media_info.stream_info.cur_video_index, + media_info.stream_info.cur_audio_index, +#if !defined(TARGET_ANDROID) + media_info.stream_info.cur_sub_index, + media_info.stream_info.total_chapter_num); +#else + media_info.stream_info.cur_sub_index, + 0); +#endif + } + + // video info + if (media_info.stream_info.has_video && media_info.stream_info.total_video_num > 0) + { + for (int i = 0; i < media_info.stream_info.total_video_num; i++) + { + AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo; + info->Clear(); + + info->id = media_info.video_info[i]->id; + info->type = STREAM_VIDEO; + info->width = media_info.video_info[i]->width; + info->height = media_info.video_info[i]->height; + info->frame_rate_num = media_info.video_info[i]->frame_rate_num; + info->frame_rate_den = media_info.video_info[i]->frame_rate_den; + info->bit_rate = media_info.video_info[i]->bit_rate; + info->duration = media_info.video_info[i]->duartion; + info->format = media_info.video_info[i]->format; + + m_video_streams.push_back(info); + } + + m_video_index = media_info.stream_info.cur_video_index; + m_video_count = media_info.stream_info.total_video_num; + if (m_video_index != 0) + m_video_index = 0; + m_video_width = media_info.video_info[m_video_index]->width; + m_video_height= media_info.video_info[m_video_index]->height; + m_video_fps_numerator = media_info.video_info[m_video_index]->frame_rate_num; + m_video_fps_denominator = media_info.video_info[m_video_index]->frame_rate_den; + + // bail if we do not get a valid width/height + if (m_video_width == 0 || m_video_height == 0) + return false; + } + + // audio info + if (media_info.stream_info.has_audio && media_info.stream_info.total_audio_num > 0) + { + for (int i = 0; i < media_info.stream_info.total_audio_num; i++) + { + AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo; + info->Clear(); + + info->id = media_info.audio_info[i]->id; + info->type = STREAM_AUDIO; + info->channel = media_info.audio_info[i]->channel; + info->sample_rate = media_info.audio_info[i]->sample_rate; + info->bit_rate = media_info.audio_info[i]->bit_rate; + info->duration = media_info.audio_info[i]->duration; + info->format = media_info.audio_info[i]->aformat; +#if !defined(TARGET_ANDROID) + if (media_info.audio_info[i]->audio_language[0] != 0) + info->language = std::string(media_info.audio_info[i]->audio_language, 3); +#endif + m_audio_streams.push_back(info); + } + + m_audio_index = media_info.stream_info.cur_audio_index; + if (m_audio_index != 0) + m_audio_index = 0; + m_audio_count = media_info.stream_info.total_audio_num; + // setup ac3/dts passthough if required + SetAudioPassThrough(m_audio_streams[m_audio_index]->format); + } + + // subtitle info + if (media_info.stream_info.has_sub && media_info.stream_info.total_sub_num > 0) + { + for (int i = 0; i < media_info.stream_info.total_sub_num; i++) + { + AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo; + info->Clear(); + + info->id = media_info.sub_info[i]->id; + info->type = STREAM_SUBTITLE; + if (media_info.sub_info[i]->sub_language && media_info.sub_info[i]->sub_language[0] != 0) + info->language = std::string(media_info.sub_info[i]->sub_language, 3); + m_subtitle_streams.push_back(info); + } + m_subtitle_index = media_info.stream_info.cur_sub_index; + } + // find any external subs + FindSubtitleFiles(); + // setup count and index + m_subtitle_count = m_subtitle_streams.size(); + if (m_subtitle_count && m_subtitle_index != 0) + m_subtitle_index = 0; + +#if !defined(TARGET_ANDROID) + // chapter info + if (media_info.stream_info.total_chapter_num > 0) + { + m_chapter_count = media_info.stream_info.total_chapter_num; + for (int i = 0; i < m_chapter_count; i++) + { + if (media_info.chapter_info[i] != NULL) + { + AMLChapterInfo *info = new AMLChapterInfo; + + info->name = media_info.chapter_info[i]->name; + info->seekto_ms = media_info.chapter_info[i]->seekto_ms; + m_chapters.push_back(info); + } + } + } +#endif + return true; + break; + } + } + + return false; +} + +void CAMLPlayer::ClearStreamInfos() +{ + CSingleLock lock(m_aml_csection); + + if (!m_audio_streams.empty()) + { + for (unsigned int i = 0; i < m_audio_streams.size(); i++) + delete m_audio_streams[i]; + m_audio_streams.clear(); + } + m_audio_count = 0; + m_audio_index = -1; + + if (!m_video_streams.empty()) + { + for (unsigned int i = 0; i < m_video_streams.size(); i++) + delete m_video_streams[i]; + m_video_streams.clear(); + } + m_video_count = 0; + m_video_index = -1; + + if (!m_subtitle_streams.empty()) + { + for (unsigned int i = 0; i < m_subtitle_streams.size(); i++) + delete m_subtitle_streams[i]; + m_subtitle_streams.clear(); + } + m_subtitle_count = 0; + m_subtitle_index = -1; + + if (!m_chapters.empty()) + { + for (unsigned int i = 0; i < m_chapters.size(); i++) + delete m_chapters[i]; + m_chapters.clear(); + } + m_chapter_count = 0; +} + +bool CAMLPlayer::GetStatus() +{ + CSingleLock lock(m_aml_csection); + + if (!m_dll->check_pid_valid(m_pid)) + return false; + + player_info_t player_info; + int res = m_dll->player_get_play_info(m_pid, &player_info); + if (res != PLAYER_SUCCESS) + return false; + + m_elapsed_ms = player_info.current_ms; + m_duration_ms = 1000 * player_info.full_time; + //CLog::Log(LOGDEBUG, "CAMLPlayer::GetStatus: audio_bufferlevel(%f), video_bufferlevel(%f), bufed_time(%d), bufed_pos(%lld)", + // player_info.audio_bufferlevel, player_info.video_bufferlevel, player_info.bufed_time, player_info.bufed_pos); + + return true; +} + +void CAMLPlayer::FindSubtitleFiles() +{ + // find any available external subtitles + std::vector<CStdString> filenames; + CUtil::ScanForExternalSubtitles(m_item.GetPath(), filenames); + + // find any upnp subtitles + CStdString key("upnp:subtitle:1"); + for(unsigned s = 1; m_item.HasProperty(key); key.Format("upnp:subtitle:%u", ++s)) + filenames.push_back(m_item.GetProperty(key).asString()); + + for(unsigned int i=0;i<filenames.size();i++) + { + // if vobsub subtitle: + if (URIUtils::GetExtension(filenames[i]) == ".idx") + { + CStdString strSubFile; + if ( CUtil::FindVobSubPair( filenames, filenames[i], strSubFile ) ) + AddSubtitleFile(filenames[i], strSubFile); + } + else + { + if ( !CUtil::IsVobSub(filenames, filenames[i] ) ) + { + AddSubtitleFile(filenames[i]); + } + } + } +} + +int CAMLPlayer::AddSubtitleFile(const std::string &filename, const std::string &subfilename) +{ + std::string ext = URIUtils::GetExtension(filename); + std::string vobsubfile = subfilename; + + if(ext == ".idx") + { + /* TODO: we do not handle idx/sub binary subs yet. + if (vobsubfile.empty()) + vobsubfile = URIUtils::ReplaceExtension(filename, ".sub"); + + CDVDDemuxVobsub v; + if(!v.Open(filename, vobsubfile)) + return -1; + m_SelectionStreams.Update(NULL, &v); + int index = m_SelectionStreams.IndexOf(STREAM_SUBTITLE, m_SelectionStreams.Source(STREAM_SOURCE_DEMUX_SUB, filename), 0); + m_SelectionStreams.Get(STREAM_SUBTITLE, index).flags = flags; + m_SelectionStreams.Get(STREAM_SUBTITLE, index).filename2 = vobsubfile; + return index; + */ + return -1; + } + if(ext == ".sub") + { + // check for texual sub, if this is a idx/sub pair, ignore it. + CStdString strReplace(URIUtils::ReplaceExtension(filename,".idx")); + if (XFILE::CFile::Exists(strReplace)) + return -1; + } + + AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo; + info->Clear(); + + info->id = 0; + info->type = STREAM_SUBTITLE; + info->source = STREAM_SOURCE_TEXT; + info->filename = filename; + info->name = URIUtils::GetFileName(filename); + info->frame_rate_num = m_video_fps_numerator; + info->frame_rate_den = m_video_fps_denominator; + m_subtitle_streams.push_back(info); + + return m_subtitle_streams.size(); +} + +bool CAMLPlayer::OpenSubtitleStream(int index) +{ + CLog::Log(LOGNOTICE, "Opening external subtitle stream: %i", index); + + CDemuxStream* pStream = NULL; + std::string filename; + CDVDStreamInfo hint; + + if (m_subtitle_streams[index]->source == STREAM_SOURCE_DEMUX_SUB) + { + /* + int index = m_SelectionStreams.IndexOf(STREAM_SUBTITLE, source, iStream); + if(index < 0) + return false; + SelectionStream st = m_SelectionStreams.Get(STREAM_SUBTITLE, index); + + if(!m_pSubtitleDemuxer || m_pSubtitleDemuxer->GetFileName() != st.filename) + { + CLog::Log(LOGNOTICE, "Opening Subtitle file: %s", st.filename.c_str()); + auto_ptr<CDVDDemuxVobsub> demux(new CDVDDemuxVobsub()); + if(!demux->Open(st.filename, st.filename2)) + return false; + m_pSubtitleDemuxer = demux.release(); + } + + pStream = m_pSubtitleDemuxer->GetStream(iStream); + if(!pStream || pStream->disabled) + return false; + pStream->SetDiscard(AVDISCARD_NONE); + double pts = m_dvdPlayerVideo.GetCurrentPts(); + if(pts == DVD_NOPTS_VALUE) + pts = m_CurrentVideo.dts; + if(pts == DVD_NOPTS_VALUE) + pts = 0; + pts += m_offset_pts; + m_pSubtitleDemuxer->SeekTime((int)(1000.0 * pts / (double)DVD_TIME_BASE)); + + hint.Assign(*pStream, true); + */ + return false; + } + else if (m_subtitle_streams[index]->source == STREAM_SOURCE_TEXT) + { + filename = m_subtitle_streams[index]->filename; + + hint.Clear(); + hint.fpsscale = m_subtitle_streams[index]->frame_rate_den; + hint.fpsrate = m_subtitle_streams[index]->frame_rate_num; + } + + m_dvdPlayerSubtitle->CloseStream(true); + if (!m_dvdPlayerSubtitle->OpenStream(hint, filename)) + { + CLog::Log(LOGWARNING, "%s - Unsupported stream %d. Stream disabled.", __FUNCTION__, index); + if(pStream) + { + pStream->disabled = true; + pStream->SetDiscard(AVDISCARD_ALL); + } + return false; + } + + return true; +} + +void CAMLPlayer::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) +{ + // this routine gets called every video frame + // and is in the context of the renderer thread so + // do not do anything stupid here. + + // video zoom adjustment. + float zoom = g_settings.m_currentVideoSettings.m_CustomZoomAmount; + if ((int)(zoom * 1000) != (int)(m_zoom * 1000)) + { + SetVideoZoom(zoom); + m_zoom = zoom; + } + // video contrast adjustment. + int contrast = g_settings.m_currentVideoSettings.m_Contrast; + if (contrast != m_contrast) + { + SetVideoContrast(contrast); + m_contrast = contrast; + } + // video brightness adjustment. + int brightness = g_settings.m_currentVideoSettings.m_Brightness; + if (brightness != m_brightness) + { + SetVideoBrightness(brightness); + m_brightness = brightness; + } + + // check if destination rect or video view mode has changed + if ((m_dst_rect != DestRect) || (m_view_mode != g_settings.m_currentVideoSettings.m_ViewMode)) + { + m_dst_rect = DestRect; + m_view_mode = g_settings.m_currentVideoSettings.m_ViewMode; + } + else + { + // mainvideo 'should' be showing already if we get here, make sure. + ShowMainVideo(true); + return; + } + + CRect gui, display, dst_rect; + RESOLUTION res = g_graphicsContext.GetVideoResolution(); + gui.SetRect(0, 0, g_settings.m_ResInfo[res].iWidth, g_settings.m_ResInfo[res].iHeight); + // when display is at 1080p, we have freescale enabled + // and that scales all layers into 1080p display including video, + // so we have to setup video axis for 720p instead of 1080p... Boooo. + display.SetRect(0, 0, g_settings.m_ResInfo[res].iWidth, g_settings.m_ResInfo[res].iHeight); + //display.SetRect(0, 0, g_settings.m_ResInfo[res].iScreenWidth, g_settings.m_ResInfo[res].iScreenHeight); + dst_rect = m_dst_rect; + if (gui != display) + { + float xscale = display.Width() / gui.Width(); + float yscale = display.Height() / gui.Height(); + dst_rect.x1 *= xscale; + dst_rect.x2 *= xscale; + dst_rect.y1 *= yscale; + dst_rect.y2 *= yscale; + } + // destination rectangle cannot be outside display bounds + if (!display.PtInRect(CPoint(dst_rect.x1, dst_rect.y1))) + return; + if (!display.PtInRect(CPoint(dst_rect.x2, dst_rect.y2))) + return; + + ShowMainVideo(false); + + char video_axis[256] = {0}; + sprintf(video_axis, "%d %d %d %d", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.x2, (int)dst_rect.y2); + set_sysfs_str("/sys/class/video/axis", video_axis); + + CStdString rectangle; + rectangle.Format("%i,%i,%i,%i", + (int)dst_rect.x1, (int)dst_rect.y1, + (int)dst_rect.Width(), (int)dst_rect.Height()); + CLog::Log(LOGDEBUG, "CAMLPlayer::SetVideoRect:dst_rect(%s)", rectangle.c_str()); + + // we only get called once gui has changed to something + // that would show video playback, so show it. + ShowMainVideo(true); +} + +void CAMLPlayer::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect) +{ + CAMLPlayer *player = (CAMLPlayer*)ctx; + player->SetVideoRect(SrcRect, DestRect); +} diff --git a/xbmc/cores/amlplayer/AMLPlayer.h b/xbmc/cores/amlplayer/AMLPlayer.h new file mode 100644 index 0000000000..38da8bbc8a --- /dev/null +++ b/xbmc/cores/amlplayer/AMLPlayer.h @@ -0,0 +1,256 @@ +#pragma once +/* + * Copyright (C) 2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "FileItem.h" +#include "cores/IPlayer.h" +#include "dialogs/GUIDialogBusy.h" +#include "threads/Thread.h" + +typedef struct AMLChapterInfo AMLChapterInfo; +typedef struct AMLPlayerStreamInfo AMLPlayerStreamInfo; +typedef struct player_info player_info_t; + +struct AMLSubtitle +{ + int64_t bgntime; + int64_t endtime; + CStdString string; +}; + +class DllLibAmplayer; + +class CAMLSubTitleThread : public CThread +{ +public: + CAMLSubTitleThread(DllLibAmplayer* dll); + virtual ~CAMLSubTitleThread(); + + void UpdateSubtitle(CStdString &subtitle, int64_t elapsed_ms); +protected: + virtual void Process(void); + + DllLibAmplayer *m_dll; + int m_subtitle_codec; + std::deque<AMLSubtitle*> m_subtitle_strings; + CCriticalSection m_subtitle_csection; +}; + +class CDVDPlayerSubtitle; +class CDVDOverlayContainer; + +class CAMLPlayer : public IPlayer, public CThread +{ +public: + + CAMLPlayer(IPlayerCallback &callback); + virtual ~CAMLPlayer(); + + virtual void RegisterAudioCallback(IAudioCallback* pCallback) {} + virtual void UnRegisterAudioCallback() {} + virtual bool OpenFile(const CFileItem &file, const CPlayerOptions &options); + virtual bool QueueNextFile(const CFileItem &file) {return false;} + virtual void OnNothingToQueueNotify() {} + virtual bool CloseFile(); + virtual bool IsPlaying() const; + virtual void Pause(); + virtual bool IsPaused() const; + virtual bool HasVideo() const; + virtual bool HasAudio() const; + virtual void ToggleFrameDrop(); + virtual bool CanSeek(); + virtual void Seek(bool bPlus = true, bool bLargeStep = false); + virtual bool SeekScene(bool bPlus = true); + virtual void SeekPercentage(float fPercent = 0.0f); + virtual float GetPercentage(); + virtual void SetVolume(float volume); + virtual void SetDynamicRangeCompression(long drc) {} + virtual void GetAudioInfo(CStdString &strAudioInfo); + virtual void GetVideoInfo(CStdString &strVideoInfo); + virtual void GetGeneralInfo(CStdString &strVideoInfo) {}; + virtual void Update(bool bPauseDrawing); + virtual void GetVideoRect(CRect& SrcRect, CRect& DestRect); + virtual void GetVideoAspectRatio(float &fAR); + virtual bool CanRecord() {return false;}; + virtual bool IsRecording() {return false;}; + virtual bool Record(bool bOnOff) {return false;}; + + virtual void SetAVDelay(float fValue = 0.0f) {return;} + virtual float GetAVDelay() {return 0.0f;}; + + virtual void SetSubTitleDelay(float fValue); + virtual float GetSubTitleDelay(); + virtual int GetSubtitleCount(); + virtual int GetSubtitle(); + virtual void GetSubtitleName(int iStream, CStdString &strStreamName); + virtual void SetSubtitle(int iStream); + virtual bool GetSubtitleVisible(); + virtual void SetSubtitleVisible(bool bVisible); + virtual bool GetSubtitleExtension(CStdString &strSubtitleExtension) { return false; } + virtual int AddSubtitle(const CStdString& strSubPath); + + virtual int GetAudioStreamCount(); + virtual int GetAudioStream(); + virtual void GetAudioStreamName(int iStream, CStdString &strStreamName); + virtual void SetAudioStream(int iStream); + virtual void GetAudioStreamLanguage(int iStream, CStdString &strLanguage) {}; + + virtual TextCacheStruct_t* GetTeletextCache() {return NULL;}; + virtual void LoadPage(int p, int sp, unsigned char* buffer) {}; + + virtual int GetChapterCount(); + virtual int GetChapter(); + virtual void GetChapterName(CStdString& strChapterName); + virtual int SeekChapter(int iChapter); + + virtual float GetActualFPS(); + virtual void SeekTime(__int64 iTime = 0); + virtual __int64 GetTime(); + virtual __int64 GetTotalTime(); + virtual int GetAudioBitrate(); + virtual int GetVideoBitrate(); + virtual int GetSourceBitrate(); + virtual int GetChannels(); + virtual int GetBitsPerSample(); + virtual int GetSampleRate(); + virtual CStdString GetAudioCodecName(); + virtual CStdString GetVideoCodecName(); + virtual int GetPictureWidth(); + virtual int GetPictureHeight(); + virtual bool GetStreamDetails(CStreamDetails &details); + virtual void ToFFRW(int iSpeed = 0); + // Skip to next track/item inside the current media (if supported). + virtual bool SkipNext() {return false;} + + //Returns true if not playback (paused or stopped beeing filled) + virtual bool IsCaching() const {return false;}; + //Cache filled in Percent + virtual int GetCacheLevel() const {return -1;}; + + virtual bool IsInMenu() const {return false;}; + virtual bool HasMenu() {return false;}; + + virtual void DoAudioWork() {}; + virtual bool OnAction(const CAction &action) {return false;}; + + virtual bool GetCurrentSubtitle(CStdString& strSubtitle); + //returns a state that is needed for resuming from a specific time + virtual CStdString GetPlayerState() {return "";}; + virtual bool SetPlayerState(CStdString state) {return false;}; + + virtual CStdString GetPlayingTitle() {return "";}; +/* + virtual void GetRenderFeatures(Features* renderFeatures); + virtual void GetDeinterlaceMethods(Features* deinterlaceMethods); + virtual void GetDeinterlaceModes(Features* deinterlaceModes); + virtual void GetScalingMethods(Features* scalingMethods); + virtual void GetAudioCapabilities(Features* audioCaps); + virtual void GetSubtitleCapabilities(Features* subCaps); +*/ + +protected: + virtual void OnStartup(); + virtual void OnExit(); + virtual void Process(); + +private: + int GetVideoStreamCount(); + void ShowMainVideo(bool show); + void SetVideoZoom(float zoom); + void SetVideoContrast(int contrast); + void SetVideoBrightness(int brightness); + void SetAudioPassThrough(int format); + bool WaitForPausedThumbJobs(int timeout_ms); + + int GetPlayerSerializedState(void); + static int UpdatePlayerInfo(int pid, player_info_t *info); + bool CheckPlaying(); + bool WaitForStopped(int timeout_ms); + bool WaitForSearchOK(int timeout_ms); + bool WaitForPlaying(int timeout_ms); + bool WaitForOpenMedia(int timeout_ms); + bool WaitForFormatValid(int timeout_ms); + void ClearStreamInfos(); + bool GetStatus(); + + void FindSubtitleFiles(); + int AddSubtitleFile(const std::string& filename, const std::string& subfilename = ""); + bool OpenSubtitleStream(int index); + void SetVideoRect(const CRect &SrcRect, const CRect &DestRect); + static void RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect); + + DllLibAmplayer *m_dll; + int m_cpu; + int m_speed; + bool m_paused; + bool m_StopPlaying; + CEvent m_ready; + CFileItem m_item; + CPlayerOptions m_options; + int m_log_level; + + int64_t m_elapsed_ms; + int64_t m_duration_ms; + + int m_audio_index; + int m_audio_count; + CStdString m_audio_info; + int m_audio_delay; + bool m_audio_passthrough_ac3; + bool m_audio_passthrough_dts; + + int m_video_index; + int m_video_count; + CStdString m_video_info; + int m_video_width; + int m_video_height; + float m_video_fps_numerator; + float m_video_fps_denominator; + + int m_subtitle_index; + int m_subtitle_count; + bool m_subtitle_show; + int m_subtitle_delay; + CAMLSubTitleThread *m_subtitle_thread; + CDVDPlayerSubtitle *m_dvdPlayerSubtitle; + CDVDOverlayContainer *m_dvdOverlayContainer; + + int m_chapter_index; + int m_chapter_count; + + int m_show_mainvideo; + CRect m_dst_rect; + int m_view_mode; + float m_zoom; + int m_contrast; + int m_brightness; + + CCriticalSection m_aml_csection; + CCriticalSection m_aml_state_csection; + std::deque<int> m_aml_state; + int m_pid; + + std::vector<AMLPlayerStreamInfo*> m_video_streams; + std::vector<AMLPlayerStreamInfo*> m_audio_streams; + std::vector<AMLPlayerStreamInfo*> m_subtitle_streams; + std::vector<AMLChapterInfo*> m_chapters; + +}; diff --git a/xbmc/cores/amlplayer/DllLibamplayer.h b/xbmc/cores/amlplayer/DllLibamplayer.h new file mode 100644 index 0000000000..ea78a7b38a --- /dev/null +++ b/xbmc/cores/amlplayer/DllLibamplayer.h @@ -0,0 +1,163 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" + +#include "DynamicDll.h" + +extern "C" +{ +#include <player_type.h> +#include <player_error.h> +} + +struct AML_URLProtocol; + +class DllLibAmplayerInterface +{ +public: + virtual ~DllLibAmplayerInterface() {}; + + virtual int player_init(void)=0; + virtual int player_start(play_control_t *p, unsigned long priv)=0; + virtual int player_stop(int pid)=0; + virtual int player_stop_async(int pid)=0; + virtual int player_exit(int pid)=0; + virtual int player_pause(int pid)=0; + virtual int player_resume(int pid)=0; + virtual int player_timesearch(int pid, float s_time)=0; + virtual int player_forward(int pid, int speed)=0; + virtual int player_backward(int pid, int speed)=0; + virtual int player_aid(int pid, int audio_id)=0; + virtual int player_sid(int pid, int sub_id)=0; + virtual int player_progress_exit(void)=0; + virtual int player_list_allpid(pid_info_t *pid)=0; + virtual int check_pid_valid(int pid)=0; + virtual int player_get_play_info(int pid, player_info_t *info)=0; + virtual int player_get_media_info(int pid, media_info_t *minfo)=0; + virtual int player_video_overlay_en(unsigned enable)=0; + virtual int player_start_play(int pid)=0; + virtual player_status player_get_state(int pid)=0; + virtual unsigned int player_get_extern_priv(int pid)=0; + virtual int player_enable_autobuffer(int pid, int enable)=0; + virtual int player_set_autobuffer_level(int pid, float min, float middle, float max)=0; + virtual int player_register_update_callback(callback_t *cb,update_state_fun_t up_fn,int interval_s)=0; + virtual char* player_status2str(player_status status)=0; + + virtual int audio_set_volume(int pid,float val)=0; + + virtual int codec_open_sub_read(void)=0; + virtual int codec_close_sub_fd(int sub_fd)=0; + virtual int codec_get_sub_size_fd(int sub_fd)=0; + virtual int codec_read_sub_data_fd(int sub_fd, char* buf, unsigned int length)=0; + +#if defined(TARGET_ANDROID) + // on android, libamplayer.so has ffmpeg built in and + // we need to use av_register_protocol2 from there. + virtual int av_register_protocol2(AML_URLProtocol *protocol, int size)=0; +#else + virtual int av_register_protocol2(AML_URLProtocol *protocol, int size) + { return ::av_register_protocol2(protocol, size);}; +#endif +}; + +class DllLibAmplayer : public DllDynamic, DllLibAmplayerInterface +{ + DECLARE_DLL_WRAPPER(DllLibAmplayer, "libamplayer.so") + + DEFINE_METHOD0(int, player_init) + DEFINE_METHOD2(int, player_start, (play_control_t *p1, unsigned long p2)) + DEFINE_METHOD1(int, player_stop, (int p1)) + DEFINE_METHOD1(int, player_stop_async, (int p1)) + DEFINE_METHOD1(int, player_exit, (int p1)) + DEFINE_METHOD1(int, player_pause, (int p1)) + DEFINE_METHOD1(int, player_resume, (int p1)) + DEFINE_METHOD2(int, player_timesearch, (int p1, float p2)) + DEFINE_METHOD2(int, player_forward, (int p1, int p2)) + DEFINE_METHOD2(int, player_backward, (int p1, int p2)) + DEFINE_METHOD2(int, player_aid, (int p1, int p2)) + DEFINE_METHOD2(int, player_sid, (int p1, int p2)) + DEFINE_METHOD0(int, player_progress_exit) + DEFINE_METHOD1(int, player_list_allpid, (pid_info_t *p1)) + DEFINE_METHOD1(int, check_pid_valid, (int p1)) + DEFINE_METHOD2(int, player_get_play_info, (int p1, player_info_t *p2)) + DEFINE_METHOD2(int, player_get_media_info, (int p1, media_info_t *p2)) + DEFINE_METHOD1(int, player_video_overlay_en, (unsigned int p1)) + DEFINE_METHOD1(int, player_start_play, (int p1)) + DEFINE_METHOD1(player_status, player_get_state, (int p1)) + DEFINE_METHOD1(unsigned int, player_get_extern_priv,(int p1)) + DEFINE_METHOD2(int, player_enable_autobuffer, (int p1, int p2)) + DEFINE_METHOD4(int, player_set_autobuffer_level, (int p1, float p2, float p3, float p4)) + DEFINE_METHOD3(int, player_register_update_callback, (callback_t *p1, update_state_fun_t p2, int p3)) + DEFINE_METHOD1(char*, player_status2str, (player_status p1)) + + DEFINE_METHOD2(int, audio_set_volume, (int p1, float p2)) + + DEFINE_METHOD0(int, codec_open_sub_read) + DEFINE_METHOD1(int, codec_close_sub_fd, (int p1)) + DEFINE_METHOD1(int, codec_get_sub_size_fd, (int p1)) + DEFINE_METHOD3(int, codec_read_sub_data_fd,(int p1, char *p2, unsigned int p3)) + +#if defined(TARGET_ANDROID) + DEFINE_METHOD2(int, av_register_protocol2, (AML_URLProtocol *p1, int p2)) +#endif + + BEGIN_METHOD_RESOLVE() + RESOLVE_METHOD(player_init) + RESOLVE_METHOD(player_start) + RESOLVE_METHOD(player_stop) + RESOLVE_METHOD(player_stop_async) + RESOLVE_METHOD(player_exit) + RESOLVE_METHOD(player_pause) + RESOLVE_METHOD(player_resume) + RESOLVE_METHOD(player_timesearch) + RESOLVE_METHOD(player_forward) + RESOLVE_METHOD(player_backward) + RESOLVE_METHOD(player_aid) + RESOLVE_METHOD(player_sid) + RESOLVE_METHOD(player_progress_exit) + RESOLVE_METHOD(player_list_allpid) + RESOLVE_METHOD(check_pid_valid) + RESOLVE_METHOD(player_get_play_info) + RESOLVE_METHOD(player_get_media_info) + RESOLVE_METHOD(player_video_overlay_en) + RESOLVE_METHOD(player_start_play) + RESOLVE_METHOD(player_get_state) + RESOLVE_METHOD(player_get_extern_priv) + RESOLVE_METHOD(player_enable_autobuffer) + RESOLVE_METHOD(player_set_autobuffer_level) + RESOLVE_METHOD(player_register_update_callback) + RESOLVE_METHOD(player_status2str) + + RESOLVE_METHOD(audio_set_volume) + + RESOLVE_METHOD(codec_open_sub_read) + RESOLVE_METHOD(codec_close_sub_fd) + RESOLVE_METHOD(codec_get_sub_size_fd) + RESOLVE_METHOD(codec_read_sub_data_fd) + +#if defined(TARGET_ANDROID) + RESOLVE_METHOD(av_register_protocol2) +#endif + + END_METHOD_RESOLVE() +}; diff --git a/xbmc/cores/amlplayer/FileURLProtocol.cpp b/xbmc/cores/amlplayer/FileURLProtocol.cpp new file mode 100644 index 0000000000..a67062128a --- /dev/null +++ b/xbmc/cores/amlplayer/FileURLProtocol.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2011-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "FileURLProtocol.h" +#include "filesystem/File.h" +#include "utils/log.h" +#include "FileItem.h" + +#define URL_RDONLY 1 /**< read-only */ +#define URL_WRONLY 2 /**< write-only */ +#define URL_RDWR (URL_RDONLY|URL_WRONLY) /**< read-write */ + +#define AVSEEK_SIZE 0x10000 +#define AVSEEK_FORCE 0x20000 + +//======================================================================== +int CFileURLProtocol::Open(AML_URLContext *h, const char *filename, int flags) +{ + if (flags != URL_RDONLY) + { + CLog::Log(LOGDEBUG, "CFileURLProtocol::Open: Only read-only is supported"); + return -EINVAL; + } + + CStdString url = filename; + if (url.Left(strlen("xb-http://")).Equals("xb-http://")) + { + url = url.Right(url.size() - strlen("xb-")); + } + else if (url.Left(strlen("xb-https://")).Equals("xb-https://")) + { + url = url.Right(url.size() - strlen("xb-")); + } + else if (url.Left(strlen("xb-ftp://")).Equals("xb-ftp://")) + { + url = url.Right(url.size() - strlen("xb-")); + } + else if (url.Left(strlen("xb-ftps://")).Equals("xb-ftps://")) + { + url = url.Right(url.size() - strlen("xb-")); + } + + CLog::Log(LOGDEBUG, "CFileURLProtocol::Open filename2(%s)", url.c_str()); + // open the file, always in read mode, calc bitrate + unsigned int cflags = READ_BITRATE; + XFILE::CFile *cfile = new XFILE::CFile(); + + if (CFileItem(url, true).IsInternetStream()) + cflags |= READ_CACHED; + + // open file in binary mode + if (!cfile->Open(url, cflags)) + { + delete cfile; + return -EIO; + } + + h->priv_data = (void *)cfile; + + return 0; +} + +//======================================================================== +int CFileURLProtocol::Read(AML_URLContext *h, unsigned char *buf, int size) +{ + XFILE::CFile *cfile = (XFILE::CFile*)h->priv_data; + + int readsize = cfile->Read(buf, size); + //CLog::Log(LOGDEBUG, "CFileURLProtocol::Read size(%d), readsize(%d)", size, readsize); + + return readsize; +} + +//======================================================================== +int CFileURLProtocol::Write(AML_URLContext *h, unsigned char *buf, int size) +{ + //CLog::Log(LOGDEBUG, "CFileURLProtocol::Write size(%d)", size); + return 0; +} + +//======================================================================== +int64_t CFileURLProtocol::Seek(AML_URLContext *h, int64_t pos, int whence) +{ + //CLog::Log(LOGDEBUG, "CFileURLProtocol::Seek1 pos(%lld), whence(%d)", pos, whence); + XFILE::CFile *cfile = (XFILE::CFile*)h->priv_data; + whence &= ~AVSEEK_FORCE; + + // seek to the end of file + if (pos == -1 || whence == AVSEEK_SIZE) + pos = cfile->GetLength(); + else + pos = cfile->Seek(pos, whence); + + //CLog::Log(LOGDEBUG, "CFileURLProtocol::Seek2 pos(%lld), whence(%d)", pos, whence); + + return pos; +} + +//======================================================================== +int64_t CFileURLProtocol::SeekEx(AML_URLContext *h, int64_t pos, int whence) +{ + //CLog::Log(LOGDEBUG, "CFileURLProtocol::SeekEx1 pos(%lld), whence(%d)", pos, whence); + XFILE::CFile *cfile = (XFILE::CFile*)h->priv_data; + whence &= ~AVSEEK_FORCE; + + // seek to the end of file + if (pos == -1 || whence == AVSEEK_SIZE) + pos = cfile->GetLength(); + else + pos = cfile->Seek(pos, whence); + + //CLog::Log(LOGDEBUG, "CFileURLProtocol::SeekEx2 pos(%lld), whence(%d)", pos, whence); + + return pos; +} + +//======================================================================== +int CFileURLProtocol::Close(AML_URLContext *h) +{ + CLog::Log(LOGDEBUG, "CFileURLProtocol::Close"); + XFILE::CFile *cfile = (XFILE::CFile*)h->priv_data; + cfile->Close(); + delete cfile; + + return 0; +} diff --git a/xbmc/cores/amlplayer/FileURLProtocol.h b/xbmc/cores/amlplayer/FileURLProtocol.h new file mode 100644 index 0000000000..c39f4c3ed9 --- /dev/null +++ b/xbmc/cores/amlplayer/FileURLProtocol.h @@ -0,0 +1,81 @@ +#pragma once +/* + * Copyright (C) 2011-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include <stdint.h> +#include <stdio.h> + +// this is an icky hack, we need to use amffmpeg structures but we cannot +// include them or risk colliding with our internal ffmpeg defs. The only +// this we use is URLProtocol to setup callbacks into uur vfs, so we fake +// a renamed URLContext/URLProtocol. The only thing we need to worry about +// is keeping the alignment to what is in amffmpeg, so we can forward +// declare all pointers to stucts as we never ref them and the compiler is happy. + +struct AVClass; +struct url_lpbuf; + +typedef struct AML_URLContext { + const AVClass *av_class; + struct AML_URLProtocol *prot; + struct url_lpbuf *lpbuf; + int flags; + int is_streamed; + int max_packet_size; + void *priv_data; + char *filename; + char *headers; + int is_connected; + int is_slowmedia; + int fastdetectedinfo; + int support_time_seek; + char *location; +} AML_URLContext; + +typedef struct AML_URLProtocol { + const char *name; + int (*url_open)(AML_URLContext *h, const char *url, int flags); + int (*url_read)(AML_URLContext *h, unsigned char *buf, int size); + int (*url_write)(AML_URLContext *h, unsigned char *buf, int size); + int64_t (*url_seek)(AML_URLContext *h, int64_t pos, int whence); + int64_t (*url_exseek)(AML_URLContext *h, int64_t pos, int whence); + int (*url_close)(AML_URLContext *h); + struct AML_URLContext *next; + int (*url_read_pause)(AML_URLContext *h, int pause); + int64_t (*url_read_seek)(AML_URLContext *h, int stream_index, int64_t timestamp, int flags); + int (*url_get_file_handle)(AML_URLContext *h); + int priv_data_size; + const AVClass *priv_data_class; + int flags; + int (*url_check)(AML_URLContext *h, int mask); +} AML_URLProtocol; + +class CFileURLProtocol +{ + +public: + static int Open (AML_URLContext *h, const char *filename, int flags); + static int Read (AML_URLContext *h, unsigned char *buf, int size); + static int Write(AML_URLContext *h, unsigned char *buf, int size); + static int64_t Seek(AML_URLContext *h, int64_t pos, int whence); + static int64_t SeekEx(AML_URLContext *h, int64_t pos, int whence); + static int Close(AML_URLContext *h); +}; diff --git a/xbmc/cores/amlplayer/Makefile.in b/xbmc/cores/amlplayer/Makefile.in new file mode 100644 index 0000000000..430f2dd5a5 --- /dev/null +++ b/xbmc/cores/amlplayer/Makefile.in @@ -0,0 +1,15 @@ +.PHONY: compile + +INCLUDES += -I$(prefix)/include/amlplayer + +SRCS = AMLPlayer.cpp +SRCS+= FileURLProtocol.cpp + +LIB = amlplayer.a + +@abs_top_srcdir@/system/advancedsettings.xml: $(LIB) + cp -f amlplayer_advancedsettings.xml $@ + +include @abs_top_srcdir@/Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) + diff --git a/xbmc/cores/amlplayer/amlplayer_advancedsettings.xml b/xbmc/cores/amlplayer/amlplayer_advancedsettings.xml new file mode 100644 index 0000000000..7199cd47b6 --- /dev/null +++ b/xbmc/cores/amlplayer/amlplayer_advancedsettings.xml @@ -0,0 +1,6 @@ +<advancedsettings> + <video> + <defaultplayer>amlplayer</defaultplayer> + <defaultdvdplayer>amlplayer</defaultdvdplayer> + </video> +</advancedsettings> diff --git a/xbmc/cores/dvdplayer/DVDAudio.cpp b/xbmc/cores/dvdplayer/DVDAudio.cpp index 0ef2a76c3b..bce8be32d8 100644 --- a/xbmc/cores/dvdplayer/DVDAudio.cpp +++ b/xbmc/cores/dvdplayer/DVDAudio.cpp @@ -22,7 +22,6 @@ #include "threads/SingleLock.h" #include "utils/log.h" #include "DVDAudio.h" -#include "Util.h" #include "DVDClock.h" #include "DVDCodecs/DVDCodecs.h" #include "DVDPlayerAudio.h" @@ -36,6 +35,7 @@ CDVDAudio::CDVDAudio(volatile bool &bStop) : m_bStop(bStop) { m_pAudioStream = NULL; + m_pAudioCallback = NULL; m_iBufferSize = 0; m_dwPacketSize = 0; m_pBuffer = NULL; @@ -93,6 +93,9 @@ bool CDVDAudio::Create(const DVDAudioFrame &audioframe, CodecID codec, bool need m_iBufferSize = 0; SetDynamicRangeCompression((long)(g_settings.m_currentVideoSettings.m_VolumeAmplification * 100)); + if (m_pAudioCallback) + RegisterAudioCallback(m_pAudioCallback); + return true; } @@ -234,6 +237,22 @@ void CDVDAudio::Drain() m_pAudioStream->Drain(); } +void CDVDAudio::RegisterAudioCallback(IAudioCallback* pCallback) +{ + CSingleLock lock (m_critSection); + m_pAudioCallback = pCallback; + if (m_pAudioStream) + m_pAudioStream->RegisterAudioCallback(pCallback); +} + +void CDVDAudio::UnRegisterAudioCallback() +{ + CSingleLock lock (m_critSection); + if (m_pAudioStream) + m_pAudioStream->UnRegisterAudioCallback(); + m_pAudioCallback = NULL; +} + void CDVDAudio::SetVolume(float volume) { CSingleLock lock (m_critSection); diff --git a/xbmc/cores/dvdplayer/DVDAudio.h b/xbmc/cores/dvdplayer/DVDAudio.h index 7886d4322f..533a099a10 100644 --- a/xbmc/cores/dvdplayer/DVDAudio.h +++ b/xbmc/cores/dvdplayer/DVDAudio.h @@ -48,6 +48,7 @@ extern "C" { typedef struct stDVDAudioFrame DVDAudioFrame; class CSingleLock; +class IAudioCallback; class CDVDAudio { @@ -55,6 +56,9 @@ public: CDVDAudio(volatile bool& bStop); ~CDVDAudio(); + void RegisterAudioCallback(IAudioCallback* pCallback); + void UnRegisterAudioCallback(); + void SetVolume(float fVolume); void SetDynamicRangeCompression(long drc); float GetCurrentAttenuation(); @@ -90,6 +94,7 @@ protected: bool m_bPaused; volatile bool& m_bStop; + IAudioCallback* m_pAudioCallback; //the viz audio callback //counter that will go from 0 to m_iSpeed-1 and reset, data will only be output when speedstep is 0 //int m_iSpeedStep; }; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp index be902f79c5..4dd4e32fa9 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp @@ -465,11 +465,7 @@ int CDVDAudioCodecPassthroughFFmpeg::GetChannels() { //Can't return correct channels here as this is used to keep sync. //should probably have some other way to find out this - switch(m_codec) - { - default: - return 2; - } + return 2; } int CDVDAudioCodecPassthroughFFmpeg::GetSampleRate() @@ -642,9 +638,5 @@ CAEChannelInfo CDVDAudioCodecPassthroughFFmpeg::GetChannelMap() {AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_NULL} }; - switch(m_codec) - { - default: - return map[0]; - } + return map[0]; } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h index 5604503b33..d169a129ed 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h @@ -214,6 +214,7 @@ public: FILTER_DEINTERLACE_ANY = 0xf, /* use any deinterlace mode */ FILTER_DEINTERLACE_FLAGGED = 0x10, /* only deinterlace flagged frames */ FILTER_DEINTERLACE_HALFED = 0x20, /* do half rate deinterlacing */ + FILTER_ROTATE = 0x40, /* rotate image according to the codec hints */ }; /* diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp index b7672c5e6f..3754e545fa 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp @@ -366,6 +366,24 @@ unsigned int CDVDVideoCodecFFmpeg::SetFilters(unsigned int flags) if(m_pHardware) return 0; + if(flags & FILTER_ROTATE) + { + switch(m_iOrientation) + { + case 90: + m_filters_next += "transpose=1"; + break; + case 180: + m_filters_next += "vflip,hflip"; + break; + case 270: + m_filters_next += "transpose=2"; + break; + default: + break; + } + } + if(flags & FILTER_DEINTERLACE_YADIF) { if(flags & FILTER_DEINTERLACE_HALFED) @@ -776,10 +794,18 @@ int CDVDVideoCodecFFmpeg::FilterProcess(AVFrame* frame) if (frame) { +#if LIBAVFILTER_VERSION_INT < AV_VERSION_INT(3,0,0) result = m_dllAvFilter.av_vsrc_buffer_add_frame(m_pFilterIn, frame, 0); +#else + result = m_dllAvFilter.av_buffersrc_add_frame(m_pFilterIn, frame, 0); +#endif if (result < 0) { +#if LIBAVFILTER_VERSION_INT < AV_VERSION_INT(3,0,0) CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - av_vsrc_buffer_add_frame"); +#else + CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - av_buffersrc_add_frame"); +#endif return VC_ERROR; } } @@ -792,7 +818,7 @@ int CDVDVideoCodecFFmpeg::FilterProcess(AVFrame* frame) if ((frames = m_dllAvFilter.av_buffersink_poll_frame(m_pFilterOut)) < 0) { - CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - avfilter_poll_frame"); + CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - av_buffersink_poll_frame"); return VC_ERROR; } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVDA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVDA.cpp index 9b799ef3ec..54e84b6b96 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVDA.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVDA.cpp @@ -954,6 +954,10 @@ int CDVDVideoCodecVDA::Decode(BYTE* pData, int iSize, double dts, double pts) } } + // force synchronous decode to fix issues with ATI GPUs, + // we still have to sort returned frames by pts to handle out-of-order demuxer packets. + m_dll->VDADecoderFlush((VDADecoder)m_vda_decoder, kVDADecoderFlush_EmitFrames); + if (m_queue_depth < m_max_ref_frames) return VC_BUFFER; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp index 9d5f8d6c51..476973afc9 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp @@ -82,9 +82,11 @@ DEFINE_GUID(DXVADDI_Intel_ModeH264_C, 0x604F8E66,0x4951,0x4c54,0x88,0xFE,0xAB,0x DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68,0x4951,0x4c54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6); DEFINE_GUID(DXVADDI_Intel_ModeVC1_E , 0xBCC5DB6D,0xA2B6,0x4AF0,0xAC,0xE4,0xAD,0xB1,0xF7,0x87,0xBC,0x89); +#if _MSC_VER < 1700 DEFINE_GUID(DXVA_ModeMPEG2and1_VLD, 0x86695f12,0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60); // When exposed by an accelerator, indicates compliance with the August 2010 spec update DEFINE_GUID(DXVA_ModeVC1_D2010, 0x1b81beA4,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); +#endif typedef struct { const char *name; diff --git a/xbmc/cores/dvdplayer/DVDDemuxSPU.cpp b/xbmc/cores/dvdplayer/DVDDemuxSPU.cpp index ef7eefa7b6..b515cf2f51 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxSPU.cpp +++ b/xbmc/cores/dvdplayer/DVDDemuxSPU.cpp @@ -20,7 +20,6 @@ */ #include "DVDDemuxSPU.h" -#include "Util.h" #include "DVDClock.h" #include "utils/log.h" diff --git a/xbmc/cores/dvdplayer/DVDFileInfo.cpp b/xbmc/cores/dvdplayer/DVDFileInfo.cpp index 8d6e3826e8..287fc05aa4 100644 --- a/xbmc/cores/dvdplayer/DVDFileInfo.cpp +++ b/xbmc/cores/dvdplayer/DVDFileInfo.cpp @@ -187,8 +187,7 @@ bool CDVDFileInfo::ExtractThumb(const CStdString &strPath, CTextureDetails &deta DVDVideoPicture picture; // num streams * 80 frames, should get a valid frame, if not abort. - int packetsToTry = 80; - int abort_index = pDemuxer->GetNrOfStreams() * packetsToTry; + int abort_index = pDemuxer->GetNrOfStreams() * 80; do { pPacket = pDemuxer->Read(); diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp index 06205f4167..e9fce7fb61 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp @@ -63,7 +63,8 @@ CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IDVDPlayer* pPlayer, || file.substr(0, 6) == "tcp://" || file.substr(0, 6) == "mms://" || file.substr(0, 7) == "mmst://" - || file.substr(0, 7) == "mmsh://") + || file.substr(0, 7) == "mmsh://" + || (item.IsInternetStream() && item.IsType(".m3u8"))) return new CDVDInputStreamFFmpeg(); else if(file.substr(0, 8) == "sling://" || file.substr(0, 7) == "myth://" diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStream.h b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStream.h index 29453c47fa..3631387ed2 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStream.h +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStream.h @@ -23,7 +23,7 @@ #include <string> #include "utils/BitstreamStats.h" -#include "filesystem/IFile.h" +#include "filesystem/IFileTypes.h" #include "FileItem.h" diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp index e2b78e64f7..c3c28cef3f 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp @@ -32,6 +32,7 @@ #include "filesystem/File.h" #include "filesystem/Directory.h" #include "DllLibbluray.h" +#include "URL.h" #define LIBBLURAY_BYTESEEK 0 @@ -640,7 +641,7 @@ void CDVDInputStreamBluray::OverlayCallback(const BD_OVERLAY * const ov) return; } - group->iPTSStartTime = ov->pts; + group->iPTSStartTime = (double) ov->pts; group->iPTSStopTime = 0; if (ov->plane > 1) diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamFile.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamFile.cpp index 24e042a270..88fbe13ad8 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamFile.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamFile.cpp @@ -21,6 +21,7 @@ #include "DVDInputStreamFile.h" #include "filesystem/File.h" +#include "filesystem/IFile.h" #include "utils/log.h" #include "utils/URIUtils.h" diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp index 9155ffc52e..b68e572609 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp @@ -20,7 +20,6 @@ */ #include "DVDInputStreamNavigator.h" -#include "Util.h" #include "utils/LangCodeExpander.h" #include "../DVDDemuxSPU.h" #include "DVDStateSerializer.h" @@ -28,7 +27,6 @@ #include "LangInfo.h" #include "utils/log.h" #include "guilib/Geometry.h" -#include "filesystem/IFile.h" #if defined(TARGET_DARWIN) #include "CocoaInterface.h" #endif @@ -265,7 +263,7 @@ int CDVDInputStreamNavigator::ProcessBlock(BYTE* dest_buffer, int* read) if (!m_dvdnav) return -1; int result; - int len; + int len = 2048; int iNavresult = NAVRESULT_NOP; // m_tempbuffer will be used for anything that isn't a normal data block diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamRTMP.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamRTMP.cpp index 165576eeb1..3203e1cc52 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamRTMP.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamRTMP.cpp @@ -29,7 +29,6 @@ #ifdef HAS_LIBRTMP #include "settings/AdvancedSettings.h" #include "DVDInputStreamRTMP.h" -#include "filesystem/IFile.h" #include "threads/SingleLock.h" #include "utils/log.h" #include "utils/Variant.h" diff --git a/xbmc/cores/dvdplayer/DVDMessageQueue.cpp b/xbmc/cores/dvdplayer/DVDMessageQueue.cpp index ce70ffd9e6..75b663d5a4 100644 --- a/xbmc/cores/dvdplayer/DVDMessageQueue.cpp +++ b/xbmc/cores/dvdplayer/DVDMessageQueue.cpp @@ -264,7 +264,7 @@ int CDVDMessageQueue::GetTimeSize() const if(IsDataBased()) return 0; else - return (m_TimeFront - m_TimeBack) / DVD_TIME_BASE; + return (int)((m_TimeFront - m_TimeBack) / DVD_TIME_BASE); } bool CDVDMessageQueue::IsDataBased() const diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp index 025e8e2aba..9f48b5cc24 100644 --- a/xbmc/cores/dvdplayer/DVDPlayer.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp @@ -47,6 +47,7 @@ #include "GUIInfoManager.h" #include "guilib/GUIWindowManager.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "DVDPerformanceCounter.h" #include "filesystem/File.h" #include "pictures/Picture.h" @@ -72,6 +73,7 @@ #include "storage/MediaManager.h" #include "dialogs/GUIDialogBusy.h" #include "dialogs/GUIDialogKaiToast.h" +#include "xbmc/playlists/PlayListM3U.h" #include "utils/StringUtils.h" #include "Util.h" #include "LangInfo.h" @@ -408,7 +410,7 @@ CDVDPlayer::CDVDPlayer(IPlayerCallback& callback) m_errorCount = 0; m_playSpeed = DVD_PLAYSPEED_NORMAL; m_caching = CACHESTATE_DONE; - + #ifdef DVDDEBUG_MESSAGE_TRACKER g_dvdMessageTracker.Init(); #endif @@ -447,11 +449,11 @@ bool CDVDPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options) m_filename = file.GetPath(); m_ready.Reset(); - + #if defined(HAS_VIDEO_PLAYBACK) g_renderManager.PreInit(); #endif - + Create(); if(!m_ready.WaitMSec(100)) { @@ -542,6 +544,18 @@ bool CDVDPlayer::OpenInputStream() m_filename = g_mediaManager.TranslateDevicePath(""); } retry: + // before creating the input stream, if this is an HLS playlist then get the + // most appropriate bitrate based on our network settings + if (filename.Left(7) == "http://" && filename.Right(5) == ".m3u8") + { + // get the available bandwidth (as per user settings) + int maxrate = g_guiSettings.GetInt("network.bandwidth"); + if(maxrate <= 0) + maxrate = INT_MAX; + + // determine the most appropriate stream + m_filename = PLAYLIST::CPlayListM3U::GetBestBandwidthStream(m_filename, (size_t)maxrate); + } m_pInputStream = CDVDFactoryInputStream::CreateInputStream(this, m_filename, m_mimetype); if(m_pInputStream == NULL) { @@ -562,7 +576,7 @@ retry: int title = (int)m_item.GetProperty("BlurayStartingTitle").asInteger(); if( title ) filename.AppendFormat("?title=%d",title); - + m_filename = filename; goto retry; } @@ -586,21 +600,21 @@ retry: for(unsigned int i=0;i<filenames.size();i++) { - // if vobsub subtitle: + // if vobsub subtitle: if (URIUtils::GetExtension(filenames[i]) == ".idx") { CStdString strSubFile; if ( CUtil::FindVobSubPair( filenames, filenames[i], strSubFile ) ) AddSubtitleFile(filenames[i], strSubFile); } - else + else { if ( !CUtil::IsVobSub(filenames, filenames[i] ) ) { AddSubtitleFile(filenames[i]); } - } - } // end loop over all subtitle files + } + } // end loop over all subtitle files g_settings.m_currentVideoSettings.m_SubtitleCached = true; } @@ -662,6 +676,10 @@ bool CDVDPlayer::OpenDemuxStream() void CDVDPlayer::OpenDefaultStreams() { + // bypass for DVDs. The DVD Navigator has already dictated which streams to open. + if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) + return; + SelectionStreams streams; bool valid; @@ -933,10 +951,10 @@ void CDVDPlayer::Process() starttime = m_Edl.RestoreCutTime(playerStartTime); } else - { + { starttime = m_Edl.RestoreCutTime((int64_t)m_PlayerOptions.starttime * 1000); // s to ms } - CLog::Log(LOGDEBUG, "%s - Start position set to last stopped position: %d", __FUNCTION__, starttime); + CLog::Log(LOGDEBUG, "%s - Start position set to last stopped position: %d", __FUNCTION__, starttime); } else if(m_Edl.InCut(0, &cut) && (cut.action == CEdl::CUT || cut.action == CEdl::COMM_BREAK)) @@ -2228,7 +2246,7 @@ void CDVDPlayer::Seek(bool bPlus, bool bLargeStep) } int64_t seek; - if (g_advancedSettings.m_videoUseTimeSeeking && GetTotalTime() > 2*g_advancedSettings.m_videoTimeSeekForwardBig) + if (g_advancedSettings.m_videoUseTimeSeeking && GetTotalTime() > 2000*g_advancedSettings.m_videoTimeSeekForwardBig) { if (bLargeStep) seek = bPlus ? g_advancedSettings.m_videoTimeSeekForwardBig : g_advancedSettings.m_videoTimeSeekBackwardBig; @@ -2296,7 +2314,7 @@ void CDVDPlayer::Seek(bool bPlus, bool bLargeStep) } int64_t time = GetTime(); - if(g_application.CurrentFileItem().IsStack() + if(g_application.CurrentFileItem().IsStack() && (seek > GetTotalTimeInMsec() || seek < 0)) { g_application.SeekTime((seek - time) * 0.001 + g_application.GetTime()); @@ -2415,7 +2433,7 @@ float CDVDPlayer::GetPercentage() float CDVDPlayer::GetCachePercentage() { CSingleLock lock(m_StateSection); - return min(100.0, GetPercentage() + m_State.cache_offset * 100); + return m_State.cache_offset * 100; // NOTE: Percentage returned is relative } void CDVDPlayer::SetAVDelay(float fValue) @@ -2574,9 +2592,9 @@ int64_t CDVDPlayer::GetTotalTimeInMsec() } // return length in seconds.. this should be changed to return in milleseconds throughout xbmc -int CDVDPlayer::GetTotalTime() +int64_t CDVDPlayer::GetTotalTime() { - return (int)(GetTotalTimeInMsec() / 1000); + return GetTotalTimeInMsec(); } void CDVDPlayer::ToFFRW(int iSpeed) @@ -3111,7 +3129,7 @@ int CDVDPlayer::OnDVDNavResult(void* pData, int iMessage) //Force an aspect ratio that is set in the dvdheaders if available m_CurrentVideo.hint.aspect = pStream->GetVideoAspectRatio(); - if( m_dvdPlayerAudio.IsInited() ) + if( m_dvdPlayerVideo.IsInited() ) m_dvdPlayerVideo.SendMessage(new CDVDMsgDouble(CDVDMsg::VIDEO_SET_ASPECT, m_CurrentVideo.hint.aspect)); m_SelectionStreams.Clear(STREAM_NONE, STREAM_SOURCE_NAV); @@ -3431,13 +3449,13 @@ bool CDVDPlayer::GetCurrentSubtitle(CStdString& strSubtitle) return false; m_dvdPlayerSubtitle.GetCurrentSubtitle(strSubtitle, pts - m_dvdPlayerVideo.GetSubtitleDelay()); - + // In case we stalled, don't output any subs if ((m_dvdPlayerVideo.IsStalled() && HasVideo()) || (m_dvdPlayerAudio.IsStalled() && HasAudio())) strSubtitle = m_lastSub; else m_lastSub = strSubtitle; - + return !strSubtitle.IsEmpty(); } @@ -3540,7 +3558,7 @@ int CDVDPlayer::AddSubtitleFile(const std::string& filename, const std::string& { if (vobsubfile.empty()) vobsubfile = URIUtils::ReplaceExtension(filename, ".sub"); - + CDVDDemuxVobsub v; if(!v.Open(filename, vobsubfile)) return -1; @@ -3705,7 +3723,7 @@ void CDVDPlayer::UpdateApplication(double timeout) if(pStream->UpdateItem(item)) { g_application.CurrentFileItem() = item; - g_infoManager.SetCurrentItem(item); + CApplicationMessenger::Get().SetCurrentItem(item); } } m_UpdateApplication = CDVDClock::GetAbsoluteClock(); @@ -3790,7 +3808,7 @@ bool CDVDPlayer::GetStreamDetails(CStreamDetails &details) if (result && details.GetStreamCount(CStreamDetail::VIDEO) > 0) // this is more correct (dvds in particular) { GetVideoAspectRatio(((CStreamDetailVideo*)details.GetNthStream(CStreamDetail::VIDEO,0))->m_fAspect); - ((CStreamDetailVideo*)details.GetNthStream(CStreamDetail::VIDEO,0))->m_iDuration = GetTotalTime(); + ((CStreamDetailVideo*)details.GetNthStream(CStreamDetail::VIDEO,0))->m_iDuration = GetTotalTime() / 1000; } return result; } diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h index 13c0282912..d63219477b 100644 --- a/xbmc/cores/dvdplayer/DVDPlayer.h +++ b/xbmc/cores/dvdplayer/DVDPlayer.h @@ -105,7 +105,7 @@ typedef struct StreamType type; int type_index; std::string filename; - std::string filename2; // for vobsub subtitles, 2 files are necessary (idx/sub) + std::string filename2; // for vobsub subtitles, 2 files are necessary (idx/sub) std::string language; std::string name; CDemuxStream::EFlags flags; @@ -177,6 +177,8 @@ public: virtual float GetPercentage(); virtual float GetCachePercentage(); + virtual void RegisterAudioCallback(IAudioCallback* pCallback) { m_dvdPlayerAudio.RegisterAudioCallback(pCallback); } + virtual void UnRegisterAudioCallback() { m_dvdPlayerAudio.UnRegisterAudioCallback(); } virtual void SetVolume(float nVolume) { m_dvdPlayerAudio.SetVolume(nVolume); } virtual void SetDynamicRangeCompression(long drc) { m_dvdPlayerAudio.SetDynamicRangeCompression(drc); } virtual void GetAudioInfo(CStdString& strAudioInfo); @@ -219,7 +221,7 @@ public: virtual void SeekTime(int64_t iTime); virtual int64_t GetTime(); - virtual int GetTotalTime(); + virtual int64_t GetTotalTime(); virtual void ToFFRW(int iSpeed); virtual bool OnAction(const CAction &action); virtual bool HasMenu(); @@ -364,7 +366,7 @@ protected: CDVDDemux* m_pSubtitleDemuxer; CStdString m_lastSub; - + struct SDVDInfo { void Clear() diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp index 4e050cdcb3..f8e1362eef 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp @@ -232,7 +232,9 @@ void CDVDPlayerAudio::OpenStream( CDVDStreamInfo &hints, CDVDAudioCodec* codec ) m_started = false; m_synctype = SYNC_DISCON; - m_setsynctype = g_guiSettings.GetInt("videoplayer.synctype"); + m_setsynctype = SYNC_DISCON; + if (g_guiSettings.GetBool("videoplayer.usedisplayasclock")) + m_setsynctype = g_guiSettings.GetInt("videoplayer.synctype"); m_prevsynctype = -1; m_error = 0; @@ -902,7 +904,7 @@ string CDVDPlayerAudio::GetPlayerInfo() { std::ostringstream s; s << "aq:" << setw(2) << min(99,m_messageQueue.GetLevel() + MathUtils::round_int(100.0/8.0*m_dvdAudio.GetCacheTime())) << "%"; - s << ", kB/s:" << fixed << setprecision(2) << (double)GetAudioBitrate() / 1024.0; + s << ", Kb/s:" << fixed << setprecision(2) << (double)GetAudioBitrate() / 1024.0; //print the inverse of the resample ratio, since that makes more sense //if the resample ratio is 0.5, then we're playing twice as fast diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.h b/xbmc/cores/dvdplayer/DVDPlayerAudio.h index e71bd51f07..988d171c6b 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerAudio.h +++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.h @@ -101,6 +101,9 @@ public: void OpenStream(CDVDStreamInfo &hints, CDVDAudioCodec* codec); void CloseStream(bool bWaitForBuffers); + void RegisterAudioCallback(IAudioCallback* pCallback) { m_dvdAudio.RegisterAudioCallback(pCallback); } + void UnRegisterAudioCallback() { m_dvdAudio.UnRegisterAudioCallback(); } + void SetSpeed(int speed); void Flush(); diff --git a/xbmc/cores/dvdplayer/DVDPlayerSubtitle.cpp b/xbmc/cores/dvdplayer/DVDPlayerSubtitle.cpp index 7a3177cb85..a1da73bb70 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerSubtitle.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerSubtitle.cpp @@ -186,6 +186,7 @@ bool CDVDPlayerSubtitle::OpenStream(CDVDStreamInfo &hints, string &filename) CloseStream(false); return false; } + m_pSubtitleFileParser->Reset(); return true; } diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp index 948f3af462..1ef9ee1155 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp @@ -35,7 +35,6 @@ #include "DVDCodecs/Video/DVDVideoCodecFFmpeg.h" #include "DVDDemuxers/DVDDemux.h" #include "DVDDemuxers/DVDDemuxUtils.h" -#include "../../Util.h" #include "DVDOverlayRenderer.h" #include "DVDPerformanceCounter.h" #include "DVDCodecs/DVDCodecs.h" @@ -224,7 +223,7 @@ void CDVDPlayerVideo::OpenStream(CDVDStreamInfo &hint, CDVDVideoCodec* codec) m_bFpsInvalid = (hint.fpsrate == 0 || hint.fpsscale == 0); m_bCalcFrameRate = g_guiSettings.GetBool("videoplayer.usedisplayasclock") || - g_guiSettings.GetBool("videoplayer.adjustrefreshrate"); + g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF; ResetFrameRateCalc(); m_iDroppedRequest = 0; @@ -528,6 +527,9 @@ void CDVDPlayerVideo::Process() mFilters |= CDVDVideoCodec::FILTER_DEINTERLACE_FLAGGED; } + if (!g_renderManager.Supports(RENDERFEATURE_ROTATION)) + mFilters |= CDVDVideoCodec::FILTER_ROTATE; + mFilters = m_pVideoCodec->SetFilters(mFilters); int iDecoderState = m_pVideoCodec->Decode(pPacket->pData, pPacket->iSize, pPacket->dts, pPacket->pts); @@ -536,7 +538,7 @@ void CDVDPlayerVideo::Process() if(m_pVideoCodec->GetConvergeCount() > 0) { m_packets.push_back(DVDMessageListItem(pMsg, 0)); - if(m_packets.size() > m_pVideoCodec->GetConvergeCount() + if(m_packets.size() > m_pVideoCodec->GetConvergeCount() || m_packets.size() * frametime > DVD_SEC_TO_TIME(10)) m_packets.pop_front(); } @@ -607,7 +609,7 @@ void CDVDPlayerVideo::Process() m_iNrOfPicturesNotToSkip--; } - // validate picture timing, + // validate picture timing, // if both dts/pts invalid, use pts calulated from picture.iDuration // if pts invalid use dts, else use picture.pts as passed if (picture.dts == DVD_NOPTS_VALUE && picture.pts == DVD_NOPTS_VALUE) @@ -1121,7 +1123,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) } CLog::Log(LOGDEBUG,"%s - change configuration. %dx%d. framerate: %4.2f. format: %s",__FUNCTION__,pPicture->iWidth, pPicture->iHeight, config_framerate, formatstr.c_str()); - if(!g_renderManager.Configure(pPicture->iWidth, pPicture->iHeight, pPicture->iDisplayWidth, pPicture->iDisplayHeight, config_framerate, flags, pPicture->format, pPicture->extended_format)) + if(!g_renderManager.Configure(pPicture->iWidth, pPicture->iHeight, pPicture->iDisplayWidth, pPicture->iDisplayHeight, config_framerate, flags, pPicture->format, pPicture->extended_format, m_hints.orientation)) { CLog::Log(LOGERROR, "%s - failed to configure renderer", __FUNCTION__); return EOS_ABORT; diff --git a/xbmc/cores/dvdplayer/DVDSubtitles/DVDFactorySubtitle.cpp b/xbmc/cores/dvdplayer/DVDSubtitles/DVDFactorySubtitle.cpp index 7b057abaf9..7d1449d278 100644 --- a/xbmc/cores/dvdplayer/DVDSubtitles/DVDFactorySubtitle.cpp +++ b/xbmc/cores/dvdplayer/DVDSubtitles/DVDFactorySubtitle.cpp @@ -29,7 +29,6 @@ #include "DVDSubtitleParserSami.h" #include "DVDSubtitleParserSSA.h" #include "DVDSubtitleParserVplayer.h" -#include "Util.h" #include "utils/log.h" using namespace std; diff --git a/xbmc/cores/dvdplayer/DVDTSCorrection.cpp b/xbmc/cores/dvdplayer/DVDTSCorrection.cpp index 20d40e6812..55d81d639b 100644 --- a/xbmc/cores/dvdplayer/DVDTSCorrection.cpp +++ b/xbmc/cores/dvdplayer/DVDTSCorrection.cpp @@ -19,12 +19,13 @@ * */ -#include "Util.h" #include "DVDTSCorrection.h" #include "DVDClock.h" #include "DVDCodecs/DVDCodecUtils.h" #include "utils/log.h" +#include <cmath> + #define MAXERR DVD_MSEC_TO_TIME(2.5) using namespace std; diff --git a/xbmc/cores/dvdplayer/DVDTSCorrection.h b/xbmc/cores/dvdplayer/DVDTSCorrection.h index ded74b24d4..0b1c9764ea 100644 --- a/xbmc/cores/dvdplayer/DVDTSCorrection.h +++ b/xbmc/cores/dvdplayer/DVDTSCorrection.h @@ -23,6 +23,8 @@ #include <vector> +#include "utils/StdString.h" + #define DIFFRINGSIZE 120 class CPullupCorrection diff --git a/xbmc/cores/dvdplayer/Edl.cpp b/xbmc/cores/dvdplayer/Edl.cpp index 09e127e188..d8d69bb922 100644 --- a/xbmc/cores/dvdplayer/Edl.cpp +++ b/xbmc/cores/dvdplayer/Edl.cpp @@ -28,6 +28,7 @@ #include "utils/log.h" #include "utils/XBMCTinyXML.h" #include "PlatformDefs.h" +#include "URL.h" extern "C" { diff --git a/xbmc/cores/dvdplayer/Edl.h b/xbmc/cores/dvdplayer/Edl.h index cf2e17aaa4..0f73b8b0be 100644 --- a/xbmc/cores/dvdplayer/Edl.h +++ b/xbmc/cores/dvdplayer/Edl.h @@ -25,7 +25,6 @@ #include <vector> #include <stdint.h> #include "utils/StdString.h" -#include "URL.h" class CEdl { diff --git a/xbmc/cores/paplayer/ADPCMCodec.cpp b/xbmc/cores/paplayer/ADPCMCodec.cpp index 028a88f1cf..329b80413d 100644 --- a/xbmc/cores/paplayer/ADPCMCodec.cpp +++ b/xbmc/cores/paplayer/ADPCMCodec.cpp @@ -21,6 +21,7 @@ #include "ADPCMCodec.h" #include "utils/log.h" +#include "cores/AudioEngine/Utils/AEUtil.h" ADPCMCodec::ADPCMCodec() { @@ -91,3 +92,15 @@ bool ADPCMCodec::CanInit() return m_dll.CanLoad(); } +CAEChannelInfo ADPCMCodec::GetChannelInfo() +{ + static enum AEChannel map[2][3] = { + {AE_CH_FC, AE_CH_NULL}, + {AE_CH_FL, AE_CH_FR , AE_CH_NULL} + }; + + if (m_Channels > 2) + return CAEUtil::GuessChLayout(m_Channels); + + return CAEChannelInfo(map[m_Channels - 1]); +}
\ No newline at end of file diff --git a/xbmc/cores/paplayer/ADPCMCodec.h b/xbmc/cores/paplayer/ADPCMCodec.h index bd21cf407e..fc12aa81de 100644 --- a/xbmc/cores/paplayer/ADPCMCodec.h +++ b/xbmc/cores/paplayer/ADPCMCodec.h @@ -35,6 +35,7 @@ public: virtual int64_t Seek(int64_t iSeekTime); virtual int ReadPCM(BYTE *pBuffer, int size, int *actualsize); virtual bool CanInit(); + virtual CAEChannelInfo GetChannelInfo(); private: void* m_adpcm; diff --git a/xbmc/cores/paplayer/CDDAcodec.cpp b/xbmc/cores/paplayer/CDDAcodec.cpp index 68fff3d308..5e73b0c383 100644 --- a/xbmc/cores/paplayer/CDDAcodec.cpp +++ b/xbmc/cores/paplayer/CDDAcodec.cpp @@ -27,6 +27,7 @@ typedef int32_t lsn_t; #define CDIO_CD_FRAMESIZE_RAW 2352 #define CDIO_CD_FRAMES_PER_SEC 75 #endif +#include "cores/AudioEngine/Utils/AEUtil.h" #define SECTOR_COUNT 55 // max. sectors that can be read at once #define MAX_BUFFER_SIZE 2*SECTOR_COUNT*CDIO_CD_FRAMESIZE_RAW @@ -141,3 +142,16 @@ bool CDDACodec::CanInit() { return true; } + +CAEChannelInfo CDDACodec::GetChannelInfo() +{ + static enum AEChannel map[2][3] = { + {AE_CH_FC, AE_CH_NULL}, + {AE_CH_FL, AE_CH_FR , AE_CH_NULL} + }; + + if (m_Channels > 2) + return CAEUtil::GuessChLayout(m_Channels); + + return CAEChannelInfo(map[m_Channels - 1]); +}
\ No newline at end of file diff --git a/xbmc/cores/paplayer/CDDAcodec.h b/xbmc/cores/paplayer/CDDAcodec.h index fb813f1c98..0f6f6b7f89 100644 --- a/xbmc/cores/paplayer/CDDAcodec.h +++ b/xbmc/cores/paplayer/CDDAcodec.h @@ -34,6 +34,7 @@ public: virtual int64_t Seek(int64_t iSeekTime); virtual int ReadPCM(BYTE *pBuffer, int size, int *actualsize); virtual bool CanInit(); + virtual CAEChannelInfo GetChannelInfo(); private: // Input buffer to read our cdda data into diff --git a/xbmc/cores/paplayer/DVDPlayerCodec.cpp b/xbmc/cores/paplayer/DVDPlayerCodec.cpp index 9cac9cf5c5..07bdb4b0cd 100644 --- a/xbmc/cores/paplayer/DVDPlayerCodec.cpp +++ b/xbmc/cores/paplayer/DVDPlayerCodec.cpp @@ -20,7 +20,6 @@ */ #include "DVDPlayerCodec.h" -#include "Util.h" #include "cores/AudioEngine/Utils/AEUtil.h" #include "cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.h" @@ -30,6 +29,7 @@ #include "cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h" #include "utils/log.h" #include "settings/GUISettings.h" +#include "URL.h" #include "AudioDecoder.h" diff --git a/xbmc/cores/paplayer/PAPlayer.cpp b/xbmc/cores/paplayer/PAPlayer.cpp index 4da756eabb..a09dbcd558 100644 --- a/xbmc/cores/paplayer/PAPlayer.cpp +++ b/xbmc/cores/paplayer/PAPlayer.cpp @@ -21,8 +21,6 @@ #include "PAPlayer.h" #include "CodecFactory.h" -#include "GUIInfoManager.h" -#include "Application.h" #include "FileItem.h" #include "settings/AdvancedSettings.h" #include "settings/GUISettings.h" @@ -71,7 +69,7 @@ PAPlayer::~PAPlayer() { if (!m_isPaused) SoftStop(true, true); - CloseAllStreams(false); + CloseAllStreams(false); /* wait for the thread to terminate */ StopThread(true);//true - wait for end of thread @@ -119,7 +117,7 @@ void PAPlayer::SoftStart(bool wait/* = false */) StreamInfo* si = *itt; if (si->m_stream->IsFading()) { - lock.Leave(); + lock.Leave(); wait = true; Sleep(1); lock.Enter(); @@ -165,7 +163,7 @@ void PAPlayer::SoftStop(bool wait/* = false */, bool close/* = true */) StreamInfo* si = *itt; if (si->m_stream && si->m_stream->IsFading()) { - lock.Leave(); + lock.Leave(); wait = true; Sleep(1); lock.Enter(); @@ -190,7 +188,7 @@ void PAPlayer::CloseAllStreams(bool fade/* = true */) { if (!fade) { - CExclusiveLock lock(m_streamsLock); + CExclusiveLock lock(m_streamsLock); while(!m_streams.empty()) { StreamInfo* si = m_streams.front(); @@ -234,9 +232,10 @@ bool PAPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options) { m_defaultCrossfadeMS = g_guiSettings.GetInt("musicplayer.crossfade") * 1000; - if (m_streams.size() > 1 || !m_defaultCrossfadeMS) + if (m_streams.size() > 1 || !m_defaultCrossfadeMS || m_isPaused) { - CloseAllStreams(); + CloseAllStreams(!m_isPaused); + m_isPaused = false; // Make sure to reset the pause state } if (!QueueNextFileEx(file, false)) @@ -584,7 +583,7 @@ inline void PAPlayer::ProcessStreams(double &delay, double &buffer) si->m_stream->UnRegisterAudioCallback(); } - si->m_playNextTriggered = true; + si->m_playNextTriggered = true; } } } @@ -790,9 +789,9 @@ int64_t PAPlayer::GetTotalTime64() return total; } -int PAPlayer::GetTotalTime() +int64_t PAPlayer::GetTotalTime() { - return (int)m_playerGUIData.m_totalTime; + return m_playerGUIData.m_totalTime; } int PAPlayer::GetCacheLevel() const diff --git a/xbmc/cores/paplayer/PAPlayer.h b/xbmc/cores/paplayer/PAPlayer.h index 924eab3d8b..a84c6ac6c0 100644 --- a/xbmc/cores/paplayer/PAPlayer.h +++ b/xbmc/cores/paplayer/PAPlayer.h @@ -63,7 +63,7 @@ public: virtual void Update(bool bPauseDrawing = false) {} virtual void ToFFRW(int iSpeed = 0); virtual int GetCacheLevel() const; - virtual int GetTotalTime(); + virtual int64_t GetTotalTime(); virtual int GetAudioBitrate(); virtual int GetChannels(); virtual int GetBitsPerSample(); diff --git a/xbmc/cores/paplayer/SIDCodec.cpp b/xbmc/cores/paplayer/SIDCodec.cpp index ad61281da8..393227c3af 100644 --- a/xbmc/cores/paplayer/SIDCodec.cpp +++ b/xbmc/cores/paplayer/SIDCodec.cpp @@ -24,6 +24,7 @@ #include "FileItem.h" #include "utils/log.h" #include "utils/URIUtils.h" +#include "cores/AudioEngine/Utils/AEUtil.h" using namespace MUSIC_INFO; @@ -77,6 +78,7 @@ bool SIDCodec::Init(const CStdString &strFile, unsigned int filecache) m_SampleRate = 48000; m_BitsPerSample = 16; m_TotalTime = 4*60*1000; + m_DataFormat = AE_FMT_S16NE; return true; } @@ -143,3 +145,15 @@ bool SIDCodec::CanInit() { return m_dll.CanLoad(); } + +CAEChannelInfo SIDCodec::GetChannelInfo() +{ + static enum AEChannel map[1][2] = { + {AE_CH_FC, AE_CH_NULL} + }; + + if (m_Channels > 1) + return CAEUtil::GuessChLayout(m_Channels); + + return CAEChannelInfo(map[m_Channels - 1]); +}
\ No newline at end of file diff --git a/xbmc/cores/paplayer/SIDCodec.h b/xbmc/cores/paplayer/SIDCodec.h index 64e24c4348..93ffa62d60 100644 --- a/xbmc/cores/paplayer/SIDCodec.h +++ b/xbmc/cores/paplayer/SIDCodec.h @@ -36,6 +36,7 @@ public: virtual int64_t Seek(int64_t iSeekTime); virtual int ReadPCM(BYTE *pBuffer, int size, int *actualsize); virtual bool CanInit(); + virtual CAEChannelInfo GetChannelInfo(); virtual void SetTotalTime(int64_t totaltime) { diff --git a/xbmc/cores/paplayer/TimidityCodec.cpp b/xbmc/cores/paplayer/TimidityCodec.cpp index b99a22e584..91177592c1 100644 --- a/xbmc/cores/paplayer/TimidityCodec.cpp +++ b/xbmc/cores/paplayer/TimidityCodec.cpp @@ -20,6 +20,7 @@ */ #include "TimidityCodec.h" +#include "URL.h" #include "../DllLoader/LibraryLoader.h" #include "../DllLoader/SoLoader.h" #include "../DllLoader/DllLoader.h" diff --git a/xbmc/cores/paplayer/WAVcodec.cpp b/xbmc/cores/paplayer/WAVcodec.cpp index 40b58a02e7..18ad23bf77 100644 --- a/xbmc/cores/paplayer/WAVcodec.cpp +++ b/xbmc/cores/paplayer/WAVcodec.cpp @@ -23,6 +23,7 @@ #include "WAVcodec.h" #include "utils/EndianSwap.h" #include "utils/log.h" +#include "cores/AudioEngine/Utils/AEUtil.h" #if defined(WIN32) #include <mmreg.h> @@ -271,3 +272,16 @@ bool WAVCodec::CanInit() { return true; } + +CAEChannelInfo WAVCodec::GetChannelInfo() +{ + static enum AEChannel map[2][3] = { + {AE_CH_FC, AE_CH_NULL}, + {AE_CH_FL, AE_CH_FR , AE_CH_NULL} + }; + + if (m_Channels > 2) + return CAEUtil::GuessChLayout(m_Channels); + + return CAEChannelInfo(map[m_Channels - 1]); +}
\ No newline at end of file diff --git a/xbmc/cores/paplayer/WAVcodec.h b/xbmc/cores/paplayer/WAVcodec.h index 6c2e165d9b..35e9306eee 100644 --- a/xbmc/cores/paplayer/WAVcodec.h +++ b/xbmc/cores/paplayer/WAVcodec.h @@ -35,6 +35,7 @@ public: virtual int64_t Seek(int64_t iSeekTime); virtual int ReadPCM(BYTE *pBuffer, int size, int *actualsize); virtual bool CanInit(); + virtual CAEChannelInfo GetChannelInfo(); private: uint32_t m_iDataStart; diff --git a/xbmc/cores/playercorefactory/PlayerCoreConfig.h b/xbmc/cores/playercorefactory/PlayerCoreConfig.h index cd78a822e7..486c09f0e1 100644 --- a/xbmc/cores/playercorefactory/PlayerCoreConfig.h +++ b/xbmc/cores/playercorefactory/PlayerCoreConfig.h @@ -25,6 +25,9 @@ #include "PlayerCoreFactory.h" #include "cores/dvdplayer/DVDPlayer.h" #include "cores/paplayer/PAPlayer.h" +#if defined(HAS_AMLPLAYER) +#include "cores/amlplayer/AMLPlayer.h" +#endif #include "cores/ExternalPlayer/ExternalPlayer.h" #include "utils/log.h" @@ -74,6 +77,9 @@ public: case EPC_DVDPLAYER: pPlayer = new CDVDPlayer(callback); break; case EPC_PAPLAYER: pPlayer = new PAPlayer(callback); break; case EPC_EXTPLAYER: pPlayer = new CExternalPlayer(callback); break; +#if defined(HAS_AMLPLAYER) + case EPC_AMLPLAYER: pPlayer = new CAMLPlayer(callback); break; +#endif default: return NULL; } diff --git a/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp b/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp index 3aaf54660c..9a4506bbf9 100644 --- a/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp +++ b/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp @@ -280,6 +280,13 @@ bool CPlayerCoreFactory::LoadConfiguration(TiXmlElement* pConfig, bool clear) paplayer->m_bPlaysAudio = true; s_vecCoreConfigs.push_back(paplayer); +#if defined(HAS_AMLPLAYER) + CPlayerCoreConfig* amlplayer = new CPlayerCoreConfig("AMLPlayer", EPC_AMLPLAYER, NULL); + amlplayer->m_bPlaysAudio = true; + amlplayer->m_bPlaysVideo = true; + s_vecCoreConfigs.push_back(amlplayer); +#endif + for(std::vector<CPlayerSelectionRule *>::iterator it = s_vecCoreSelectionRules.begin(); it != s_vecCoreSelectionRules.end(); it++) delete *it; s_vecCoreSelectionRules.clear(); diff --git a/xbmc/cores/playercorefactory/PlayerCoreFactory.h b/xbmc/cores/playercorefactory/PlayerCoreFactory.h index 04ac1dc3aa..69070e0908 100644 --- a/xbmc/cores/playercorefactory/PlayerCoreFactory.h +++ b/xbmc/cores/playercorefactory/PlayerCoreFactory.h @@ -37,15 +37,21 @@ enum EPLAYERCORES EPC_DVDPLAYER, EPC_MPLAYER, EPC_PAPLAYER, - EPC_EXTPLAYER + EPC_EXTPLAYER, +#if defined(HAS_AMLPLAYER) + EPC_AMLPLAYER +#endif }; typedef unsigned int PLAYERCOREID; typedef std::vector<PLAYERCOREID> VECPLAYERCORES; -const PLAYERCOREID PCID_NONE = 0; -const PLAYERCOREID PCID_DVDPLAYER = 1; -const PLAYERCOREID PCID_MPLAYER = 2; -const PLAYERCOREID PCID_PAPLAYER = 3; +const PLAYERCOREID PCID_NONE = EPC_NONE; +const PLAYERCOREID PCID_DVDPLAYER = EPC_DVDPLAYER; +const PLAYERCOREID PCID_MPLAYER = EPC_MPLAYER; +const PLAYERCOREID PCID_PAPLAYER = EPC_PAPLAYER; +#if defined(HAS_AMLPLAYER) +const PLAYERCOREID PCID_AMLPLAYER = EPC_AMLPLAYER; +#endif class CPlayerCoreFactory { diff --git a/xbmc/dbwrappers/Database.cpp b/xbmc/dbwrappers/Database.cpp index 5377630243..0cb26e68e0 100644 --- a/xbmc/dbwrappers/Database.cpp +++ b/xbmc/dbwrappers/Database.cpp @@ -20,7 +20,6 @@ */ #include "Database.h" -#include "Util.h" #include "settings/Settings.h" #include "settings/AdvancedSettings.h" #include "utils/Crc32.h" @@ -31,6 +30,7 @@ #include "utils/URIUtils.h" #include "sqlitedataset.h" #include "DatabaseManager.h" +#include "DbUrl.h" #ifdef HAS_MYSQL #include "mysqldataset.h" @@ -41,6 +41,65 @@ using namespace dbiplus; #define MAX_COMPRESS_COUNT 20 +void CDatabase::Filter::AppendField(const std::string &strField) +{ + if (strField.empty()) + return; + + if (fields.empty() || fields == "*") + fields = strField; + else + fields += ", " + strField; +} + +void CDatabase::Filter::AppendJoin(const std::string &strJoin) +{ + if (strJoin.empty()) + return; + + if (join.empty()) + join = strJoin; + else + join += " " + strJoin; +} + +void CDatabase::Filter::AppendWhere(const std::string &strWhere, bool combineWithAnd /* = true */) +{ + if (strWhere.empty()) + return; + + if (where.empty()) + where = strWhere; + else + { + where = "(" + where + ") "; + where += combineWithAnd ? "AND" : "OR"; + where += " (" + strWhere + ")"; + } +} + +void CDatabase::Filter::AppendOrder(const std::string &strOrder) +{ + if (strOrder.empty()) + return; + + if (order.empty()) + order = strOrder; + else + order += ", " + strOrder; +} + +void CDatabase::Filter::AppendGroup(const std::string &strGroup) +{ + if (strGroup.empty()) + return; + + if (group.empty()) + group = strGroup; + else + group += ", " + strGroup; +} + CDatabase::CDatabase(void) { m_openCount = 0; @@ -623,3 +682,30 @@ bool CDatabase::UpdateVersionNumber() return true; } +bool CDatabase::BuildSQL(const CStdString &strQuery, const Filter &filter, CStdString &strSQL) +{ + strSQL = strQuery; + + if (!filter.join.empty()) + strSQL += filter.join; + if (!filter.where.empty()) + strSQL += " WHERE " + filter.where; + if (!filter.group.empty()) + strSQL += " GROUP BY " + filter.group; + if (!filter.order.empty()) + strSQL += " ORDER BY " + filter.order; + if (!filter.limit.empty()) + strSQL += " LIMIT " + filter.limit; + + return true; +} + +bool CDatabase::BuildSQL(const CStdString &strBaseDir, const CStdString &strQuery, Filter &filter, CStdString &strSQL, CDbUrl &dbUrl) +{ + // parse the base path to get additional filters + dbUrl.Reset(); + if (!dbUrl.FromString(strBaseDir) || !GetFilter(dbUrl, filter)) + return false; + + return BuildSQL(strQuery, filter, strSQL); +} diff --git a/xbmc/dbwrappers/Database.h b/xbmc/dbwrappers/Database.h index 223812e39a..2e22866338 100644 --- a/xbmc/dbwrappers/Database.h +++ b/xbmc/dbwrappers/Database.h @@ -31,10 +31,32 @@ namespace dbiplus { #include <memory> class DatabaseSettings; // forward +class CDbUrl; class CDatabase { public: + class Filter + { + public: + Filter() : fields("*") {}; + Filter(const char *w) : fields("*"), where(w) {}; + Filter(const std::string &w) : fields("*"), where(w) {}; + + void AppendField(const std::string &strField); + void AppendJoin(const std::string &strJoin); + void AppendWhere(const std::string &strWhere, bool combineWithAnd = true); + void AppendOrder(const std::string &strOrder); + void AppendGroup(const std::string &strGroup); + + std::string fields; + std::string join; + std::string where; + std::string order; + std::string group; + std::string limit; + }; + CDatabase(void); virtual ~CDatabase(void); bool IsOpen(); @@ -113,6 +135,9 @@ public: */ bool CommitInsertQueries(); + virtual bool GetFilter(const CDbUrl &dbUrl, Filter &filter) { return true; } + virtual bool BuildSQL(const CStdString &strBaseDir, const CStdString &strQuery, Filter &filter, CStdString &strSQL, CDbUrl &dbUrl); + protected: friend class CDatabaseManager; bool Update(const DatabaseSettings &db); @@ -131,6 +156,8 @@ protected: int GetDBVersion(); bool UpdateVersion(const CStdString &dbName); + bool BuildSQL(const CStdString &strQuery, const Filter &filter, CStdString &strSQL); + bool m_sqlite; ///< \brief whether we use sqlite (defaults to true) std::auto_ptr<dbiplus::Database> m_pDB; diff --git a/xbmc/dbwrappers/mysqldataset.cpp b/xbmc/dbwrappers/mysqldataset.cpp index 21ea5e7896..06b5ae0e31 100644 --- a/xbmc/dbwrappers/mysqldataset.cpp +++ b/xbmc/dbwrappers/mysqldataset.cpp @@ -460,7 +460,7 @@ string MysqlDatabase::vprepare(const char *format, va_list args) #define etINVALID 0 /* Any unrecognized conversion type */ -#define ARRAYSIZE(X) ((int)(sizeof(X)/sizeof(X[0]))) +#define ARRAY_SIZE(X) ((int)(sizeof(X)/sizeof(X[0]))) /* ** An "etByte" is an 8-bit unsigned value. @@ -732,7 +732,7 @@ void MysqlDatabase::mysqlVXPrintf( /* Fetch the info entry for the field */ infop = &fmtinfo[0]; xtype = etINVALID; - for(idx=0; idx<ARRAYSIZE(fmtinfo); idx++){ + for(idx=0; idx<ARRAY_SIZE(fmtinfo); idx++){ if( c==fmtinfo[idx].fmttype ){ infop = &fmtinfo[idx]; if( useExtended || (infop->flags & FLAG_INTERN)==0 ){ diff --git a/xbmc/dialogs/GUIDialogCache.cpp b/xbmc/dialogs/GUIDialogCache.cpp index 85548e4e56..d8e8bea34a 100644 --- a/xbmc/dialogs/GUIDialogCache.cpp +++ b/xbmc/dialogs/GUIDialogCache.cpp @@ -21,7 +21,7 @@ #include "threads/SystemClock.h" #include "GUIDialogCache.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogProgress.h" #include "guilib/LocalizeStrings.h" @@ -56,7 +56,7 @@ void CGUIDialogCache::Close(bool bForceClose) // we cannot wait for the app thread to process the close message // as this might happen during player startup which leads to a deadlock if (m_pDlg->IsDialogRunning()) - g_application.getApplicationMessenger().Close(m_pDlg,bForceClose,false); + CApplicationMessenger::Get().Close(m_pDlg,bForceClose,false); //Set stop, this will kill this object, when thread stops CThread::m_bStop = true; diff --git a/xbmc/dialogs/GUIDialogContextMenu.cpp b/xbmc/dialogs/GUIDialogContextMenu.cpp index 1d0afd8ba5..e3e54f6508 100644 --- a/xbmc/dialogs/GUIDialogContextMenu.cpp +++ b/xbmc/dialogs/GUIDialogContextMenu.cpp @@ -23,8 +23,6 @@ #include "GUIDialogContextMenu.h" #include "guilib/GUIButtonControl.h" #include "guilib/GUIControlGroupList.h" -#include "GUIDialogNumeric.h" -#include "GUIDialogGamepad.h" #include "GUIDialogFileBrowser.h" #include "GUIUserMessages.h" #include "Autorun.h" @@ -44,6 +42,7 @@ #include "guilib/LocalizeStrings.h" #include "TextureCache.h" #include "video/windows/GUIWindowVideoBase.h" +#include "URL.h" #ifdef _WIN32 #include "WIN32Util.h" diff --git a/xbmc/dialogs/GUIDialogFavourites.cpp b/xbmc/dialogs/GUIDialogFavourites.cpp index fac9ac0f5f..961289ac19 100644 --- a/xbmc/dialogs/GUIDialogFavourites.cpp +++ b/xbmc/dialogs/GUIDialogFavourites.cpp @@ -23,7 +23,7 @@ #include "GUIDialogContextMenu.h" #include "Favourites.h" #include "guilib/GUIWindowManager.h" -#include "GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "FileItem.h" #include "guilib/LocalizeStrings.h" @@ -172,7 +172,7 @@ void CGUIDialogFavourites::OnRename(int item) return; CStdString label((*m_favourites)[item]->GetLabel()); - if (CGUIDialogKeyboard::ShowAndGetInput(label, g_localizeStrings.Get(16008), false)) + if (CGUIKeyboardFactory::ShowAndGetInput(label, g_localizeStrings.Get(16008), false)) (*m_favourites)[item]->SetLabel(label); CFavourites::Save(*m_favourites); diff --git a/xbmc/dialogs/GUIDialogFileBrowser.cpp b/xbmc/dialogs/GUIDialogFileBrowser.cpp index 68db4dad77..9285af13ba 100644 --- a/xbmc/dialogs/GUIDialogFileBrowser.cpp +++ b/xbmc/dialogs/GUIDialogFileBrowser.cpp @@ -33,7 +33,7 @@ #include "Application.h" #include "GUIDialogOK.h" #include "GUIDialogYesNo.h" -#include "GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "GUIUserMessages.h" #include "filesystem/Directory.h" #include "filesystem/File.h" @@ -44,6 +44,7 @@ #include "settings/GUISettings.h" #include "guilib/LocalizeStrings.h" #include "utils/log.h" +#include "URL.h" using namespace XFILE; @@ -246,7 +247,7 @@ bool CGUIDialogFileBrowser::OnMessage(CGUIMessage& message) else if (message.GetSenderId() == CONTROL_NEWFOLDER) { CStdString strInput; - if (CGUIDialogKeyboard::ShowAndGetInput(strInput,g_localizeStrings.Get(119),false)) + if (CGUIKeyboardFactory::ShowAndGetInput(strInput,g_localizeStrings.Get(119),false)) { CStdString strPath; URIUtils::AddFileToFolder(m_vecItems->GetPath(),strInput,strPath); diff --git a/xbmc/dialogs/GUIDialogGamepad.cpp b/xbmc/dialogs/GUIDialogGamepad.cpp index 35c993af7e..e26557e157 100644 --- a/xbmc/dialogs/GUIDialogGamepad.cpp +++ b/xbmc/dialogs/GUIDialogGamepad.cpp @@ -45,7 +45,11 @@ bool CGUIDialogGamepad::OnAction(const CAction &action) if ((action.GetButtonCode() >= KEY_BUTTON_A && action.GetButtonCode() <= KEY_BUTTON_RIGHT_TRIGGER) || (action.GetButtonCode() >= KEY_BUTTON_DPAD_UP && - action.GetButtonCode() <= KEY_BUTTON_DPAD_RIGHT)) + action.GetButtonCode() <= KEY_BUTTON_DPAD_RIGHT) || + (action.GetID() >= ACTION_MOVE_LEFT && + action.GetID() <= ACTION_MOVE_DOWN) || + action.GetID() == ACTION_PLAYER_PLAY + ) { switch (action.GetButtonCode()) { @@ -61,7 +65,18 @@ bool CGUIDialogGamepad::OnAction(const CAction &action) case KEY_BUTTON_DPAD_DOWN : m_strUserInput += "D"; break; case KEY_BUTTON_DPAD_LEFT : m_strUserInput += "L"; break; case KEY_BUTTON_DPAD_RIGHT : m_strUserInput += "R"; break; - default : return true; break; + default: + switch (action.GetID()) + { + case ACTION_MOVE_LEFT: m_strUserInput += "L"; break; + case ACTION_MOVE_RIGHT: m_strUserInput += "R"; break; + case ACTION_MOVE_UP: m_strUserInput += "U"; break; + case ACTION_MOVE_DOWN: m_strUserInput += "D"; break; + case ACTION_PLAYER_PLAY: m_strUserInput += "P"; break; + default: + return true; + } + break; } CStdString strHiddenInput(m_strUserInput); @@ -81,7 +96,7 @@ bool CGUIDialogGamepad::OnAction(const CAction &action) Close(); return true; } - else if (action.GetButtonCode() == KEY_BUTTON_START) + else if (action.GetButtonCode() == KEY_BUTTON_START || action.GetID() == ACTION_SELECT_ITEM) { m_bConfirmed = false; m_bCanceled = false; diff --git a/xbmc/dialogs/GUIDialogKeyboard.h b/xbmc/dialogs/GUIDialogKeyboard.h deleted file mode 100644 index 029a32c970..0000000000 --- a/xbmc/dialogs/GUIDialogKeyboard.h +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -/* - * Copyright (C) 2005-2008 Team XBMC - * http://www.xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program 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. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "guilib/GUIDialog.h" -#include "utils/Variant.h" - -enum KEYBOARD {CAPS, LOWER, SYMBOLS }; - -class CGUIDialogKeyboard: public CGUIDialog -{ - -public: - CGUIDialogKeyboard(void); - virtual ~CGUIDialogKeyboard(void); - - virtual void FrameMove(); - void SetHeading(const CVariant& heading); - void SetText(const CStdString& aTextString); - CStdString GetText() const; - bool IsConfirmed() { return m_bIsConfirmed; }; - void SetHiddenInput(bool hiddenInput) { m_hiddenInput = hiddenInput; }; - - static bool ShowAndGetInput(CStdString& aTextString, bool allowEmptyResult); - static bool ShowAndGetInput(CStdString& aTextString, const CVariant &heading, bool allowEmptyResult, bool hiddenInput = false); - static bool ShowAndGetNewPassword(CStdString& strNewPassword); - static bool ShowAndGetNewPassword(CStdString& newPassword, const CVariant &heading, bool allowEmpty); - static bool ShowAndVerifyNewPassword(CStdString& strNewPassword); - static bool ShowAndVerifyNewPassword(CStdString& newPassword, const CVariant &heading, bool allowEmpty); - static int ShowAndVerifyPassword(CStdString& strPassword, const CStdString& strHeading, int iRetries); - static bool ShowAndGetFilter(CStdString& aTextString, bool searching); -protected: - virtual void OnInitWindow(); - virtual bool OnAction(const CAction &action); - virtual bool OnMessage(CGUIMessage& message); - virtual void OnDeinitWindow(int nextWindowID); - void SetControlLabel(int id, const CStdString &label); - void OnShift(); - void MoveCursor(int iAmount); - int GetCursorPos() const; - void OnSymbols(); - void OnIPAddress(); - void OnOK(); - -private: - - void OnClickButton(int iButtonControl); - void OnRemoteNumberClick(int key); - void UpdateButtons(); - char GetCharacter(int iButton); - void UpdateLabel(); - void ResetShiftAndSymbols(); - - void Character(WCHAR wch); - void Backspace(); - void SendSearchMessage(); - - CStdStringW m_strEdit; - bool m_bIsConfirmed; - KEYBOARD m_keyType; - int m_iMode; - bool m_bShift; - bool m_hiddenInput; - // filtering type - enum FILTERING { FILTERING_NONE = 0, FILTERING_CURRENT, FILTERING_SEARCH }; - FILTERING m_filtering; - - unsigned int m_lastRemoteClickTime; - WORD m_lastRemoteKeyClicked; - int m_indexInSeries; - CStdString m_strHeading; - static const char* s_charsSeries[10]; -}; diff --git a/xbmc/dialogs/GUIDialogKeyboard.cpp b/xbmc/dialogs/GUIDialogKeyboardGeneric.cpp index 594de64796..e9f19637d2 100644 --- a/xbmc/dialogs/GUIDialogKeyboard.cpp +++ b/xbmc/dialogs/GUIDialogKeyboardGeneric.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Team XBMC + * Copyright (C) 2012 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -19,22 +19,20 @@ * */ -#include "GUIDialogKeyboard.h" -#include "settings/GUISettings.h" +#include "interfaces/AnnouncementManager.h" +#include "input/XBMC_vkeys.h" #include "guilib/GUILabelControl.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "GUIUserMessages.h" #include "GUIDialogNumeric.h" #include "GUIDialogOK.h" -#include "GUIUserMessages.h" -#include "guilib/GUIWindowManager.h" -#include "input/XBMC_vkeys.h" -#include "utils/RegExp.h" -#include "GUIPassword.h" -#include "utils/md5.h" +#include "GUIDialogKeyboardGeneric.h" #include "utils/TimeUtils.h" -#include "Application.h" -#include "settings/AdvancedSettings.h" -#include "guilib/LocalizeStrings.h" -#include "interfaces/AnnouncementManager.h" +#include "utils/RegExp.h" +#include "ApplicationMessenger.h" +#include "utils/CharsetConverter.h" + // Symbol mapping (based on MS virtual keyboard - may need improving) static char symbol_map[37] = ")!@#$%^&*([]{}-_=+;:\'\",.<>/?\\|`~ "; @@ -59,22 +57,20 @@ static char symbolButtons[] = "._-@/\\"; #define SEARCH_DELAY 1000 #define REMOTE_SMS_DELAY 1000 -CGUIDialogKeyboard::CGUIDialogKeyboard(void) +CGUIDialogKeyboardGeneric::CGUIDialogKeyboardGeneric() : CGUIDialog(WINDOW_DIALOG_KEYBOARD, "DialogKeyboard.xml") +, CGUIKeyboard() +, m_pCharCallback(NULL) { m_bIsConfirmed = false; m_bShift = false; m_hiddenInput = false; - m_filtering = FILTERING_NONE; m_keyType = LOWER; m_strHeading = ""; m_lastRemoteClickTime = 0; } -CGUIDialogKeyboard::~CGUIDialogKeyboard(void) -{} - -void CGUIDialogKeyboard::OnInitWindow() +void CGUIDialogKeyboardGeneric::OnInitWindow() { CGUIDialog::OnInitWindow(); @@ -90,7 +86,7 @@ void CGUIDialogKeyboard::OnInitWindow() } // set heading - if (!m_strHeading.IsEmpty()) + if (!m_strHeading.empty()) { SET_CONTROL_LABEL(CTL_LABEL_HEADING, m_strHeading); SET_CONTROL_VISIBLE(CTL_LABEL_HEADING); @@ -102,11 +98,12 @@ void CGUIDialogKeyboard::OnInitWindow() CVariant data; data["title"] = m_strHeading; - data["type"] = "keyboard"; + data["type"] = !m_hiddenInput ? "keyboard" : "password"; + data["value"] = GetText(); ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Input, "xbmc", "OnInputRequested", data); } -bool CGUIDialogKeyboard::OnAction(const CAction &action) +bool CGUIDialogKeyboardGeneric::OnAction(const CAction &action) { bool handled(true); if (action.GetID() == ACTION_BACKSPACE) @@ -199,14 +196,14 @@ bool CGUIDialogKeyboard::OnAction(const CAction &action) else // unhandled by us - let's see if the baseclass wants it handled = CGUIDialog::OnAction(action); - if (handled && m_filtering == FILTERING_SEARCH) + if (handled && m_pCharCallback) { // we did _something_, so make sure our search message filter is reset - SendSearchMessage(); + m_pCharCallback(this, GetText()); } return handled; } -bool CGUIDialogKeyboard::OnMessage(CGUIMessage& message) +bool CGUIDialogKeyboardGeneric::OnMessage(CGUIMessage& message) { CGUIDialog::OnMessage(message); @@ -274,7 +271,7 @@ bool CGUIDialogKeyboard::OnMessage(CGUIMessage& message) return true; } -void CGUIDialogKeyboard::SetText(const CStdString& aTextString) +void CGUIDialogKeyboardGeneric::SetText(const CStdString& aTextString) { m_strEdit.Empty(); g_charsetConverter.utf8ToW(aTextString, m_strEdit); @@ -282,14 +279,14 @@ void CGUIDialogKeyboard::SetText(const CStdString& aTextString) MoveCursor(m_strEdit.size()); } -CStdString CGUIDialogKeyboard::GetText() const +CStdString CGUIDialogKeyboardGeneric::GetText() const { CStdString utf8String; g_charsetConverter.wToUTF8(m_strEdit, utf8String); return utf8String; } -void CGUIDialogKeyboard::Character(WCHAR ch) +void CGUIDialogKeyboardGeneric::Character(WCHAR ch) { if (!ch) return; // TODO: May have to make this routine take a WCHAR for the symbols? @@ -298,7 +295,7 @@ void CGUIDialogKeyboard::Character(WCHAR ch) MoveCursor(1); } -void CGUIDialogKeyboard::FrameMove() +void CGUIDialogKeyboardGeneric::FrameMove() { // reset the hide state of the label when the remote // sms style input times out @@ -310,7 +307,7 @@ void CGUIDialogKeyboard::FrameMove() CGUIDialog::FrameMove(); } -void CGUIDialogKeyboard::UpdateLabel() // FIXME seems to be called twice for one USB SDL keyboard action/character +void CGUIDialogKeyboardGeneric::UpdateLabel() // FIXME seems to be called twice for one USB SDL keyboard action/character { CGUILabelControl* pEdit = ((CGUILabelControl*)GetControl(CTL_LABEL_EDIT)); if (pEdit) @@ -336,31 +333,13 @@ void CGUIDialogKeyboard::UpdateLabel() // FIXME seems to be called twice for one // don't send until the REMOTE_SMS_DELAY has passed if (m_lastRemoteClickTime && m_lastRemoteClickTime + REMOTE_SMS_DELAY >= now) return; - if (m_filtering == FILTERING_CURRENT) - { // send our filter message - CGUIMessage message(GUI_MSG_NOTIFY_ALL, GetID(), 0, GUI_MSG_FILTER_ITEMS); - message.SetStringParam(utf8Edit); - g_windowManager.SendMessage(message); - } - if (m_filtering == FILTERING_SEARCH) - SendSearchMessage(); + if (m_pCharCallback) + m_pCharCallback(this, utf8Edit); } } -void CGUIDialogKeyboard::SendSearchMessage() -{ - CStdString utf8Edit; - g_charsetConverter.wToUTF8(m_strEdit, utf8Edit); - // send our search message (only the active window needs it) - CGUIMessage message(GUI_MSG_NOTIFY_ALL, GetID(), 0, GUI_MSG_SEARCH_UPDATE); - message.SetStringParam(utf8Edit); - CGUIWindow *window = g_windowManager.GetWindow(g_windowManager.GetActiveWindow()); - if (window) - window->OnMessage(message); -} - -void CGUIDialogKeyboard::Backspace() +void CGUIDialogKeyboardGeneric::Backspace() { int iPos = GetCursorPos(); if (iPos > 0) @@ -371,7 +350,7 @@ void CGUIDialogKeyboard::Backspace() } } -void CGUIDialogKeyboard::OnClickButton(int iButtonControl) +void CGUIDialogKeyboardGeneric::OnClickButton(int iButtonControl) { if (iButtonControl == CTL_BUTTON_BACKSPACE) { @@ -381,7 +360,7 @@ void CGUIDialogKeyboard::OnClickButton(int iButtonControl) Character(GetCharacter(iButtonControl)); } -void CGUIDialogKeyboard::OnRemoteNumberClick(int key) +void CGUIDialogKeyboardGeneric::OnRemoteNumberClick(int key) { unsigned int now = CTimeUtils::GetFrameTime(); @@ -423,7 +402,7 @@ void CGUIDialogKeyboard::OnRemoteNumberClick(int key) Character(ch); } -char CGUIDialogKeyboard::GetCharacter(int iButton) +char CGUIDialogKeyboardGeneric::GetCharacter(int iButton) { // First the numbers if (iButton >= 48 && iButton <= 57) @@ -464,7 +443,7 @@ char CGUIDialogKeyboard::GetCharacter(int iButton) return 0; } -void CGUIDialogKeyboard::UpdateButtons() +void CGUIDialogKeyboardGeneric::UpdateButtons() { if (m_bShift) { // show the button depressed @@ -537,142 +516,8 @@ void CGUIDialogKeyboard::UpdateButtons() } } -// Show keyboard with initial value (aTextString) and replace with result string. -// Returns: true - successful display and input (empty result may return true or false depending on parameter) -// false - unsucessful display of the keyboard or cancelled editing -bool CGUIDialogKeyboard::ShowAndGetInput(CStdString& aTextString, const CVariant &heading, bool allowEmptyResult, bool hiddenInput /* = false */) -{ - CGUIDialogKeyboard *pKeyboard = (CGUIDialogKeyboard*)g_windowManager.GetWindow(WINDOW_DIALOG_KEYBOARD); - - if (!pKeyboard) - return false; - // setup keyboard - pKeyboard->Initialize(); - pKeyboard->SetHeading(heading); - pKeyboard->SetHiddenInput(hiddenInput); - pKeyboard->SetText(aTextString); - // do this using a thread message to avoid render() conflicts - ThreadMessage tMsg = {TMSG_DIALOG_DOMODAL, WINDOW_DIALOG_KEYBOARD, g_windowManager.GetActiveWindow()}; - g_application.getApplicationMessenger().SendMessage(tMsg, true); - pKeyboard->Close(); - - // If have text - update this. - if (pKeyboard->IsConfirmed()) - { - aTextString = pKeyboard->GetText(); - if (!allowEmptyResult && aTextString.IsEmpty()) - return false; - return true; - } - else return false; -} - -bool CGUIDialogKeyboard::ShowAndGetInput(CStdString& aTextString, bool allowEmptyResult) -{ - return ShowAndGetInput(aTextString, "", allowEmptyResult) != 0; -} - -// Shows keyboard and prompts for a password. -// Differs from ShowAndVerifyNewPassword() in that no second verification is necessary. -bool CGUIDialogKeyboard::ShowAndGetNewPassword(CStdString& newPassword, const CVariant &heading, bool allowEmpty) -{ - return ShowAndGetInput(newPassword, heading, allowEmpty, true); -} - -// Shows keyboard and prompts for a password. -// Differs from ShowAndVerifyNewPassword() in that no second verification is necessary. -bool CGUIDialogKeyboard::ShowAndGetNewPassword(CStdString& newPassword) -{ - return ShowAndGetNewPassword(newPassword, 12340, false); -} - -// \brief Show keyboard twice to get and confirm a user-entered password string. -// \param newPassword Overwritten with user input if return=true. -// \param heading Heading to display -// \param allowEmpty Whether a blank password is valid or not. -// \return true if successful display and user input entry/re-entry. false if unsucessful display, no user input, or canceled editing. -bool CGUIDialogKeyboard::ShowAndVerifyNewPassword(CStdString& newPassword, const CVariant &heading, bool allowEmpty) -{ - // Prompt user for password input - CStdString userInput = ""; - if (!ShowAndGetInput(userInput, heading, allowEmpty, true)) - { // user cancelled, or invalid input - return false; - } - // success - verify the password - CStdString checkInput = ""; - if (!ShowAndGetInput(checkInput, 12341, allowEmpty, true)) - { // user cancelled, or invalid input - return false; - } - // check the password - if (checkInput == userInput) - { - XBMC::XBMC_MD5 md5state; - md5state.append(userInput); - md5state.getDigest(newPassword); - newPassword.ToLower(); - return true; - } - CGUIDialogOK::ShowAndGetInput(12341, 12344, 0, 0); - return false; -} - -// \brief Show keyboard twice to get and confirm a user-entered password string. -// \param strNewPassword Overwritten with user input if return=true. -// \return true if successful display and user input entry/re-entry. false if unsucessful display, no user input, or canceled editing. -bool CGUIDialogKeyboard::ShowAndVerifyNewPassword(CStdString& newPassword) -{ - CStdString heading = g_localizeStrings.Get(12340); - return ShowAndVerifyNewPassword(newPassword, heading, false); -} - -// \brief Show keyboard and verify user input against strPassword. -// \param strPassword Value to compare against user input. -// \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer. -// \param iRetries If greater than 0, shows "Incorrect password, %d retries left" on dialog line 2, else line 2 is blank. -// \return 0 if successful display and user input. 1 if unsucessful input. -1 if no user input or canceled editing. -int CGUIDialogKeyboard::ShowAndVerifyPassword(CStdString& strPassword, const CStdString& strHeading, int iRetries) -{ - CStdString strHeadingTemp; - if (1 > iRetries && strHeading.size()) - strHeadingTemp = strHeading; - else - strHeadingTemp.Format("%s - %i %s", g_localizeStrings.Get(12326).c_str(), g_guiSettings.GetInt("masterlock.maxretries") - iRetries, g_localizeStrings.Get(12343).c_str()); - - CStdString strUserInput = ""; - if (!ShowAndGetInput(strUserInput, strHeadingTemp, false, true)) //bool hiddenInput = false/true ? TODO: GUI Setting to enable disable this feature y/n? - return -1; // user canceled out - - if (!strPassword.IsEmpty()) - { - if (strPassword == strUserInput) - return 0; - - CStdString md5pword2; - XBMC::XBMC_MD5 md5state; - md5state.append(strUserInput); - md5state.getDigest(md5pword2); - if (strPassword.Equals(md5pword2)) - return 0; // user entered correct password - else return 1; // user must have entered an incorrect password - } - else - { - if (!strUserInput.IsEmpty()) - { - XBMC::XBMC_MD5 md5state; - md5state.append(strUserInput); - md5state.getDigest(strPassword); - strPassword.ToLower(); - return 0; // user entered correct password - } - else return 1; - } -} - -void CGUIDialogKeyboard::OnDeinitWindow(int nextWindowID) +void CGUIDialogKeyboardGeneric::OnDeinitWindow(int nextWindowID) { // call base class CGUIDialog::OnDeinitWindow(nextWindowID); @@ -682,7 +527,7 @@ void CGUIDialogKeyboard::OnDeinitWindow(int nextWindowID) ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Input, "xbmc", "OnInputFinished"); } -void CGUIDialogKeyboard::MoveCursor(int iAmount) +void CGUIDialogKeyboardGeneric::MoveCursor(int iAmount) { CGUILabelControl* pEdit = ((CGUILabelControl*)GetControl(CTL_LABEL_EDIT)); if (pEdit) @@ -691,7 +536,7 @@ void CGUIDialogKeyboard::MoveCursor(int iAmount) } } -int CGUIDialogKeyboard::GetCursorPos() const +int CGUIDialogKeyboardGeneric::GetCursorPos() const { const CGUILabelControl* pEdit = (const CGUILabelControl*)GetControl(CTL_LABEL_EDIT); if (pEdit) @@ -701,7 +546,7 @@ int CGUIDialogKeyboard::GetCursorPos() const return 0; } -void CGUIDialogKeyboard::OnSymbols() +void CGUIDialogKeyboardGeneric::OnSymbols() { if (m_keyType == SYMBOLS) m_keyType = LOWER; @@ -710,13 +555,13 @@ void CGUIDialogKeyboard::OnSymbols() UpdateButtons(); } -void CGUIDialogKeyboard::OnShift() +void CGUIDialogKeyboardGeneric::OnShift() { m_bShift = !m_bShift; UpdateButtons(); } -void CGUIDialogKeyboard::OnIPAddress() +void CGUIDialogKeyboardGeneric::OnIPAddress() { // find any IP address in the current string if there is any // We match to #.#.#.# @@ -745,16 +590,16 @@ void CGUIDialogKeyboard::OnIPAddress() } } -void CGUIDialogKeyboard::ResetShiftAndSymbols() +void CGUIDialogKeyboardGeneric::ResetShiftAndSymbols() { if (m_bShift) OnShift(); if (m_keyType == SYMBOLS) OnSymbols(); m_lastRemoteClickTime = 0; } -const char* CGUIDialogKeyboard::s_charsSeries[10] = { " 0!@#$%^&*()[]{}<>/\\|", ".,1;:\'\"-+_=?`~", "ABC2", "DEF3", "GHI4", "JKL5", "MNO6", "PQRS7", "TUV8", "WXYZ9" }; +const char* CGUIDialogKeyboardGeneric::s_charsSeries[10] = { " 0!@#$%^&*()[]{}<>/\\|", ".,1;:\'\"-+_=?`~", "ABC2", "DEF3", "GHI4", "JKL5", "MNO6", "PQRS7", "TUV8", "WXYZ9" }; -void CGUIDialogKeyboard::SetControlLabel(int id, const CStdString &label) +void CGUIDialogKeyboardGeneric::SetControlLabel(int id, const CStdString &label) { // find all controls with this id, and set all their labels CGUIMessage message(GUI_MSG_LABEL_SET, GetID(), id); message.SetLabel(label); @@ -765,29 +610,45 @@ void CGUIDialogKeyboard::SetControlLabel(int id, const CStdString &label) } } -void CGUIDialogKeyboard::OnOK() +void CGUIDialogKeyboardGeneric::OnOK() { m_bIsConfirmed = true; Close(); } -bool CGUIDialogKeyboard::ShowAndGetFilter(CStdString &filter, bool searching) +void CGUIDialogKeyboardGeneric::SetHeading(const std::string &heading) +{ + m_strHeading = heading; +} + +int CGUIDialogKeyboardGeneric::GetWindowId() const { - CGUIDialogKeyboard *pKeyboard = (CGUIDialogKeyboard*)g_windowManager.GetWindow(WINDOW_DIALOG_KEYBOARD); + return GetID(); +} + +bool CGUIDialogKeyboardGeneric::ShowAndGetInput(char_callback_t pCallback, const std::string &initialString, std::string &typedString, const std::string &heading, bool bHiddenInput) +{ + CGUIDialogKeyboardGeneric *pKeyboard = (CGUIDialogKeyboardGeneric*)g_windowManager.GetWindow(WINDOW_DIALOG_KEYBOARD); if (!pKeyboard) return false; - pKeyboard->m_filtering = searching ? FILTERING_SEARCH : FILTERING_CURRENT; - bool ret = ShowAndGetInput(filter, searching ? 16017 : 16028, true); - pKeyboard->m_filtering = FILTERING_NONE; - return ret; -} + m_pCharCallback = pCallback; + // setup keyboard + pKeyboard->Initialize(); + pKeyboard->SetHeading(heading); + pKeyboard->SetHiddenInput(bHiddenInput); + pKeyboard->SetText(initialString); + // do this using a thread message to avoid render() conflicts + ThreadMessage tMsg = {TMSG_DIALOG_DOMODAL, WINDOW_DIALOG_KEYBOARD, g_windowManager.GetActiveWindow()}; + CApplicationMessenger::Get().SendMessage(tMsg, true); + pKeyboard->Close(); -void CGUIDialogKeyboard::SetHeading(const CVariant &heading) -{ - if (heading.isString()) - m_strHeading = heading.asString(); - else if (heading.isInteger() && heading.asInteger()) - m_strHeading = g_localizeStrings.Get((uint32_t)heading.asInteger()); + // If have text - update this. + if (pKeyboard->IsConfirmed()) + { + typedString = pKeyboard->GetText(); + return true; + } + else return false; } diff --git a/xbmc/dialogs/GUIDialogKeyboardGeneric.h b/xbmc/dialogs/GUIDialogKeyboardGeneric.h new file mode 100644 index 0000000000..9e3b2b8955 --- /dev/null +++ b/xbmc/dialogs/GUIDialogKeyboardGeneric.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once + +#include "guilib/GUIKeyboard.h" +#include "guilib/GUIDialog.h" +#include "utils/Variant.h" + +enum KEYBOARD {CAPS, LOWER, SYMBOLS }; + +class CGUIDialogKeyboardGeneric : public CGUIDialog, public CGUIKeyboard +{ + public: + CGUIDialogKeyboardGeneric(); + + //CGUIKeyboard Interface + virtual bool ShowAndGetInput(char_callback_t pCallback, const std::string &initialString, std::string &typedString, const std::string &heading, bool bHiddenInput); + virtual int GetWindowId() const; + + //CGUIDialog Interface + virtual void FrameMove(); + void SetHeading(const std::string& heading); + void SetText(const CStdString& aTextString); + CStdString GetText() const; + bool IsConfirmed() { return m_bIsConfirmed; }; + void SetHiddenInput(bool hiddenInput) { m_hiddenInput = hiddenInput; }; + void Character(WCHAR wch); + + protected: + virtual void OnInitWindow(); + virtual bool OnAction(const CAction &action); + virtual bool OnMessage(CGUIMessage& message); + virtual void OnDeinitWindow(int nextWindowID); + void SetControlLabel(int id, const CStdString &label); + void OnShift(); + void MoveCursor(int iAmount); + int GetCursorPos() const; + void OnSymbols(); + void OnIPAddress(); + void OnOK(); + + private: + void OnClickButton(int iButtonControl); + void OnRemoteNumberClick(int key); + void UpdateButtons(); + char GetCharacter(int iButton); + void UpdateLabel(); + void ResetShiftAndSymbols(); + void Backspace(); + void SendSearchMessage(); + + CStdStringW m_strEdit; + bool m_bIsConfirmed; + KEYBOARD m_keyType; + int m_iMode; + bool m_bShift; + bool m_hiddenInput; + + unsigned int m_lastRemoteClickTime; + WORD m_lastRemoteKeyClicked; + int m_indexInSeries; + std::string m_strHeading; + static const char* s_charsSeries[10]; + + + char_callback_t m_pCharCallback; +}; diff --git a/xbmc/dialogs/GUIDialogMediaSource.cpp b/xbmc/dialogs/GUIDialogMediaSource.cpp index c25a788cf3..95345484d8 100644 --- a/xbmc/dialogs/GUIDialogMediaSource.cpp +++ b/xbmc/dialogs/GUIDialogMediaSource.cpp @@ -20,7 +20,7 @@ */ #include "GUIDialogMediaSource.h" -#include "GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "GUIDialogFileBrowser.h" #include "video/windows/GUIWindowVideoBase.h" #include "video/dialogs/GUIDialogVideoScan.h" @@ -34,6 +34,12 @@ #include "settings/GUISettings.h" #include "guilib/LocalizeStrings.h" #include "PasswordManager.h" +#include "URL.h" + +#if defined(TARGET_ANDROID) +#include "android/activity/XBMCApp.h" +#include "filesystem/File.h" +#endif using namespace std; using namespace XFILE; @@ -220,8 +226,21 @@ void CGUIDialogMediaSource::OnPathBrowse(int item) m_bNameChanged=true; if (m_type == "music") - { // add the music playlist location + { CMediaSource share1; +#if defined(TARGET_ANDROID) + // add the default android music directory + std::string path; + if (CXBMCApp::GetExternalStorage(path, "music") && !path.empty() && CFile::Exists(path)) + { + share1.strPath = path; + share1.strName = g_localizeStrings.Get(20240); + share1.m_ignore = true; + extraShares.push_back(share1); + } +#endif + + // add the music playlist location share1.strPath = "special://musicplaylists/"; share1.strName = g_localizeStrings.Get(20011); share1.m_ignore = true; @@ -246,8 +265,21 @@ void CGUIDialogMediaSource::OnPathBrowse(int item) } } else if (m_type == "video") - { // add the music playlist location + { CMediaSource share1; +#if defined(TARGET_ANDROID) + // add the default android video directory + std::string path; + if (CXBMCApp::GetExternalStorage(path, "videos") && !path.empty() && CFile::Exists(path)) + { + share1.strPath = path; + share1.strName = g_localizeStrings.Get(20241); + share1.m_ignore = true; + extraShares.push_back(share1); + } +#endif + + // add the video playlist location share1.m_ignore = true; share1.strPath = "special://videoplaylists/"; share1.strName = g_localizeStrings.Get(20012); @@ -268,6 +300,27 @@ void CGUIDialogMediaSource::OnPathBrowse(int item) else if (m_type == "pictures") { CMediaSource share1; +#if defined(TARGET_ANDROID) + // add the default android music directory + std::string path; + if (CXBMCApp::GetExternalStorage(path, "pictures") && !path.empty() && CFile::Exists(path)) + { + share1.strPath = path; + share1.strName = g_localizeStrings.Get(20242); + share1.m_ignore = true; + extraShares.push_back(share1); + } + + path.clear(); + if (CXBMCApp::GetExternalStorage(path, "photos") && !path.empty() && CFile::Exists(path)) + { + share1.strPath = path; + share1.strName = g_localizeStrings.Get(20243); + share1.m_ignore = true; + extraShares.push_back(share1); + } +#endif + share1.m_ignore = true; if (g_guiSettings.GetString("debug.screenshotpath",false)!= "") { @@ -303,7 +356,7 @@ void CGUIDialogMediaSource::OnPath(int item) m_bNameChanged=true; CStdString path(m_paths->Get(item)->GetPath()); - CGUIDialogKeyboard::ShowAndGetInput(path, g_localizeStrings.Get(1021), false); + CGUIKeyboardFactory::ShowAndGetInput(path, g_localizeStrings.Get(1021), false); URIUtils::AddSlashAtEnd(path); m_paths->Get(item)->SetPath(path); diff --git a/xbmc/dialogs/GUIDialogNumeric.cpp b/xbmc/dialogs/GUIDialogNumeric.cpp index 0443f48a4f..fa82a0db5a 100644 --- a/xbmc/dialogs/GUIDialogNumeric.cpp +++ b/xbmc/dialogs/GUIDialogNumeric.cpp @@ -72,7 +72,7 @@ void CGUIDialogNumeric::OnInitWindow() data["type"] = "ip"; break; case INPUT_PASSWORD: - data["type"] = "password"; + data["type"] = "numericpassword"; break; case INPUT_NUMBER: data["type"] = "number"; @@ -89,6 +89,7 @@ void CGUIDialogNumeric::OnInitWindow() if (control != NULL) data["title"] = control->GetDescription(); + data["value"] = GetOutput(); ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Input, "xbmc", "OnInputRequested", data); } @@ -585,23 +586,37 @@ void CGUIDialogNumeric::SetMode(INPUT_MODE mode, const CStdString &initial) SetMode(mode, (void*)&initial); } -void CGUIDialogNumeric::GetOutput(void *output) +void CGUIDialogNumeric::GetOutput(void *output) const { if (!output) return; if (m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS || m_mode == INPUT_DATE) memcpy(output, &m_datetime, sizeof(m_datetime)); - if (m_mode == INPUT_IP_ADDRESS) + else if (m_mode == INPUT_IP_ADDRESS) { CStdString *ipaddress = (CStdString *)output; ipaddress->Format("%d.%d.%d.%d", m_ip[0], m_ip[1], m_ip[2], m_ip[3]); } - if (m_mode == INPUT_NUMBER || m_mode == INPUT_PASSWORD) + else if (m_mode == INPUT_NUMBER || m_mode == INPUT_PASSWORD) { CStdString *number = (CStdString *)output; *number = m_number; } } +CStdString CGUIDialogNumeric::GetOutput() const +{ + CStdString output; + if (m_mode == INPUT_DATE) + output.Format("%02i/%02i/%04i", m_datetime.wDay, m_datetime.wMonth, m_datetime.wYear); + else if (m_mode == INPUT_TIME) + output.Format("%i:%02i", m_datetime.wHour, m_datetime.wMinute); + else if (m_mode == INPUT_TIME_SECONDS) + output.Format("%i:%02i", m_datetime.wMinute, m_datetime.wSecond); + else + GetOutput(&output); + return output; +} + bool CGUIDialogNumeric::ShowAndGetSeconds(CStdString &timeString, const CStdString &heading) { CGUIDialogNumeric *pDialog = (CGUIDialogNumeric *)g_windowManager.GetWindow(WINDOW_DIALOG_NUMERIC); diff --git a/xbmc/dialogs/GUIDialogNumeric.h b/xbmc/dialogs/GUIDialogNumeric.h index 7f74cf12e2..5dd8275e3f 100644 --- a/xbmc/dialogs/GUIDialogNumeric.h +++ b/xbmc/dialogs/GUIDialogNumeric.h @@ -45,7 +45,8 @@ public: void SetHeading(const CStdString &strHeading); void SetMode(INPUT_MODE mode, void *initial); void SetMode(INPUT_MODE mode, const CStdString &initial); - void GetOutput(void *output); + void GetOutput(void *output) const; + CStdString GetOutput() const; static bool ShowAndGetTime(SYSTEMTIME &time, const CStdString &heading); static bool ShowAndGetDate(SYSTEMTIME &date, const CStdString &heading); diff --git a/xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp b/xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp index 679013c334..458c842b09 100644 --- a/xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp +++ b/xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp @@ -20,7 +20,7 @@ */ #include "GUIDialogSmartPlaylistEditor.h" -#include "GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "Util.h" #include "utils/URIUtils.h" #include "GUIDialogSmartPlaylistRule.h" @@ -57,6 +57,7 @@ typedef struct static const translateType types[] = { { CGUIDialogSmartPlaylistEditor::TYPE_SONGS, "songs", 134 }, { CGUIDialogSmartPlaylistEditor::TYPE_ALBUMS, "albums", 132 }, + { CGUIDialogSmartPlaylistEditor::TYPE_ARTISTS, "artists", 133 }, { CGUIDialogSmartPlaylistEditor::TYPE_MIXED, "mixed", 20395 }, { CGUIDialogSmartPlaylistEditor::TYPE_MUSICVIDEOS, "musicvideos", 20389 }, { CGUIDialogSmartPlaylistEditor::TYPE_MOVIES, "movies", 20342 }, @@ -166,7 +167,7 @@ void CGUIDialogSmartPlaylistEditor::OnOK() { CStdString filename(CUtil::MakeLegalFileName(m_playlist.m_playlistName)); CStdString path; - if (CGUIDialogKeyboard::ShowAndGetInput(filename, g_localizeStrings.Get(16013), false)) + if (CGUIKeyboardFactory::ShowAndGetInput(filename, g_localizeStrings.Get(16013), false)) { path = URIUtils::AddFileToFolder(g_guiSettings.GetString("system.playlistspath"),m_playlist.GetSaveLocation()); path = URIUtils::AddFileToFolder(path, CUtil::MakeLegalFileName(filename)); @@ -356,6 +357,7 @@ void CGUIDialogSmartPlaylistEditor::OnWindowLoaded() { // music types + mixed allowedTypes.push_back(TYPE_SONGS); allowedTypes.push_back(TYPE_ALBUMS); + allowedTypes.push_back(TYPE_ARTISTS); allowedTypes.push_back(TYPE_MIXED); } else if (m_mode.Equals("video")) @@ -496,6 +498,8 @@ bool CGUIDialogSmartPlaylistEditor::EditPlaylist(const CStdString &path, const C } editor->m_playlist = playlist; + if (editor->m_playlist.m_playlistRules.size() <= 0) + editor->m_playlist.m_playlistRules.push_back(CSmartPlaylistRule()); editor->m_path = path; editor->Initialize(); editor->DoModal(g_windowManager.GetActiveWindow()); diff --git a/xbmc/dialogs/GUIDialogSmartPlaylistEditor.h b/xbmc/dialogs/GUIDialogSmartPlaylistEditor.h index 28d19c941b..8418ec3389 100644 --- a/xbmc/dialogs/GUIDialogSmartPlaylistEditor.h +++ b/xbmc/dialogs/GUIDialogSmartPlaylistEditor.h @@ -30,7 +30,7 @@ class CGUIDialogSmartPlaylistEditor : public CGUIDialog { public: - enum PLAYLIST_TYPE { TYPE_SONGS = 1, TYPE_ALBUMS, TYPE_MIXED, TYPE_MUSICVIDEOS, TYPE_MOVIES, TYPE_TVSHOWS, TYPE_EPISODES }; + enum PLAYLIST_TYPE { TYPE_SONGS = 1, TYPE_ALBUMS, TYPE_ARTISTS, TYPE_MIXED, TYPE_MUSICVIDEOS, TYPE_MOVIES, TYPE_TVSHOWS, TYPE_EPISODES }; CGUIDialogSmartPlaylistEditor(void); virtual ~CGUIDialogSmartPlaylistEditor(void); diff --git a/xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp b/xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp index 1ca5f0271b..20c739d4c1 100644 --- a/xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp +++ b/xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp @@ -117,8 +117,8 @@ void CGUIDialogSmartPlaylistRule::OnBrowse() { if (m_type.Equals("tvshows") || m_type.Equals("episodes") || m_type.Equals("movies")) videodatabase.GetGenresNav("videodb://2/1/",items,type); - else if (m_type.Equals("songs") || m_type.Equals("albums") || m_type.Equals("mixed")) - database.GetGenresNav("musicdb://4/",items); + else if (m_type.Equals("songs") || m_type.Equals("albums") || m_type.Equals("artists") || m_type.Equals("mixed")) + database.GetGenresNav("musicdb://1/",items); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; @@ -134,8 +134,8 @@ void CGUIDialogSmartPlaylistRule::OnBrowse() } else if (m_rule.m_field == FieldArtist || m_rule.m_field == FieldAlbumArtist) { - if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums")) - database.GetArtistsNav("musicdb://5/",items,-1,m_rule.m_field == FieldAlbumArtist); + if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums") || m_type.Equals("artists")) + database.GetArtistsNav("musicdb://2/", items, m_rule.m_field == FieldAlbumArtist, -1); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; @@ -147,7 +147,7 @@ void CGUIDialogSmartPlaylistRule::OnBrowse() else if (m_rule.m_field == FieldAlbum) { if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums")) - database.GetAlbumsNav("musicdb://6/",items,-1,-1,-1,-1); + database.GetAlbumsNav("musicdb://3/", items); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; @@ -164,7 +164,7 @@ void CGUIDialogSmartPlaylistRule::OnBrowse() else if (m_rule.m_field == FieldYear) { if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums")) - database.GetYearsNav("", items); + database.GetYearsNav("musicdb://9/", items); if (!m_type.Equals("songs") && !m_type.Equals("albums")) { CFileItemList items2; diff --git a/xbmc/dialogs/Makefile b/xbmc/dialogs/Makefile index 49ae5f2399..85ebf3b319 100644 --- a/xbmc/dialogs/Makefile +++ b/xbmc/dialogs/Makefile @@ -7,7 +7,7 @@ SRCS=GUIDialogBoxBase.cpp \ GUIDialogFileBrowser.cpp \ GUIDialogGamepad.cpp \ GUIDialogKaiToast.cpp \ - GUIDialogKeyboard.cpp \ + GUIDialogKeyboardGeneric.cpp \ GUIDialogMediaSource.cpp \ GUIDialogMuteBug.cpp \ GUIDialogNumeric.cpp \ diff --git a/xbmc/filesystem/APKDirectory.cpp b/xbmc/filesystem/APKDirectory.cpp new file mode 100644 index 0000000000..b9a0e5fc57 --- /dev/null +++ b/xbmc/filesystem/APKDirectory.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "APKDirectory.h" +#include "APKFile.h" +#include "FileItem.h" +#include "utils/CharsetConverter.h" +#include "utils/log.h" +#include "utils/URIUtils.h" + +#include <zip.h> + +using namespace XFILE; + +// Android apk directory i/o. Depends on libzip +// Basically the same format as zip. +// We might want to refactor CZipDirectory someday... +////////////////////////////////////////////////////////////////////// +bool CAPKDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) +{ + // uses a <fully qualified path>/filename.apk/... + CURL url(strPath); + + CStdString path = url.GetFileName(); + CStdString host = url.GetHostName(); + URIUtils::AddSlashAtEnd(path); + + // host name might be encoded rfc1738.txt, decode it. + CURL::Decode(host); + + int zip_flags = 0, zip_error = 0, dir_marker = 0; + struct zip *zip_archive; + zip_archive = zip_open(host.c_str(), zip_flags, &zip_error); + if (!zip_archive || zip_error) + { + CLog::Log(LOGERROR, "CAPKDirectory::GetDirectory: Unable to open archive : '%s'", + host.c_str()); + return false; + } + + CStdString test_name; + int numFiles = zip_get_num_files(zip_archive); + for (int zip_index = 0; zip_index < numFiles; zip_index++) + { + test_name = zip_get_name(zip_archive, zip_index, zip_flags); + + // check for non matching path. + if (!test_name.Left(path.size()).Equals(path)) + continue; + + // libzip does not index folders, only filenames. We search for a /, + // add it if it's not in our list already, and hope that no one has + // any "file/name.exe" files in a zip. + + dir_marker = test_name.Find('/', path.size() + 1); + if (dir_marker > 0) + { + // return items relative to path + test_name=test_name.Left(dir_marker); + + if (items.Contains(host + "/" + test_name)) + continue; + } + + struct zip_stat sb; + zip_stat_init(&sb); + if (zip_stat_index(zip_archive, zip_index, zip_flags, &sb) != -1) + { + g_charsetConverter.unknownToUTF8(test_name); + CFileItemPtr pItem(new CFileItem(test_name)); + pItem->m_dwSize = sb.size; + pItem->m_dateTime = sb.mtime; + pItem->m_bIsFolder = dir_marker > 0 ; + pItem->SetPath(host + "/" + test_name); + pItem->SetLabel(test_name.Right(test_name.size() - path.size())); + items.Add(pItem); + } + } + zip_close(zip_archive); + + return true; +} + +bool CAPKDirectory::ContainsFiles(const CStdString& strPath) +{ + // TODO: why might we need this ? + return false; +} + +DIR_CACHE_TYPE CAPKDirectory::GetCacheType(const CStdString& strPath) const +{ + return DIR_CACHE_ALWAYS; +} + +bool CAPKDirectory::Exists(const char* strPath) +{ + // uses a <fully qualified path>/filename.apk/... + CAPKFile apk; + CURL url(strPath); + return apk.Exists(url); +} diff --git a/xbmc/filesystem/APKDirectory.h b/xbmc/filesystem/APKDirectory.h new file mode 100644 index 0000000000..652900c80e --- /dev/null +++ b/xbmc/filesystem/APKDirectory.h @@ -0,0 +1,37 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "IFileDirectory.h" + +namespace XFILE +{ + class CAPKDirectory : public IFileDirectory + { + public: + CAPKDirectory() {}; + virtual ~CAPKDirectory() {}; + virtual bool GetDirectory(const CStdString& strPath, CFileItemList &items); + virtual bool ContainsFiles(const CStdString& strPath); + virtual DIR_CACHE_TYPE GetCacheType(const CStdString& strPath) const; + virtual bool Exists(const char* strPath); + }; +} diff --git a/xbmc/filesystem/APKFile.cpp b/xbmc/filesystem/APKFile.cpp new file mode 100644 index 0000000000..9c6b265190 --- /dev/null +++ b/xbmc/filesystem/APKFile.cpp @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +// Android apk file i/o. Depends on libzip +// Basically the same format as zip. +// We might want to refactor CFileZip someday... +////////////////////////////////////////////////////////////////////// +#include "system.h" + +#include "APKFile.h" +#include "utils/log.h" +#include "utils/URIUtils.h" + +#include <zip.h> + +using namespace XFILE; + +CAPKFile::CAPKFile() +{ + m_file_pos = 0; + m_file_size = 0; + m_zip_index =-1; + m_zip_file = NULL; + m_zip_archive = NULL; +} + +CAPKFile::~CAPKFile() +{ +} + +bool CAPKFile::Open(const CURL& url) +{ + Close(); + + m_url = url; + CStdString path = url.GetFileName(); + CStdString host = url.GetHostName(); + // host name might be encoded rfc1738.txt, decode it. + CURL::Decode(host); + + int zip_flags = 0, zip_error = 0; + m_zip_archive = zip_open(host.c_str(), zip_flags, &zip_error); + if (!m_zip_archive || zip_error) + { + CLog::Log(LOGERROR, "CAPKFile::Open: Unable to open archive : '%s'", + host.c_str()); + return false; + } + + m_zip_index = zip_name_locate(m_zip_archive, path.c_str(), zip_flags); + if (m_zip_index == -1) + { + // might not be an error if caller is just testing for presence/absence + CLog::Log(LOGDEBUG, "CAPKFile::Open: Unable to locate file : '%s'", + path.c_str()); + zip_close(m_zip_archive); + m_zip_archive = NULL; + return false; + } + + // cache the file size + struct zip_stat sb; + zip_stat_init(&sb); + int rtn = zip_stat_index(m_zip_archive, m_zip_index, zip_flags, &sb); + if (rtn == -1) + { + CLog::Log(LOGERROR, "CAPKFile::Open: Unable to stat file : '%s'", + path.c_str()); + zip_close(m_zip_archive); + m_zip_archive = NULL; + return false; + } + m_file_pos = 0; + m_file_size = sb.size; + + // finally open the file + m_zip_file = zip_fopen_index(m_zip_archive, m_zip_index, zip_flags); + if (!m_zip_file) + { + CLog::Log(LOGERROR, "CAPKFile::Open: Unable to open file : '%s'", + path.c_str()); + zip_close(m_zip_archive); + m_zip_archive = NULL; + return false; + } + + // We've successfully opened the file! + return true; +} + +bool CAPKFile::Exists(const CURL& url) +{ + struct __stat64 buffer; + return (Stat(url, &buffer) == 0); +} + +void CAPKFile::Close() +{ + if (m_zip_archive) + { + if (m_zip_file) + zip_fclose(m_zip_file); + m_zip_file = NULL; + } + zip_close(m_zip_archive); + m_zip_archive = NULL; + m_file_pos = 0; + m_file_size = 0; + m_zip_index =-1; +} + +int64_t CAPKFile::Seek(int64_t iFilePosition, int iWhence) +{ + // libzip has no seek so we have to fake it with reads + off64_t file_pos = -1; + if (m_zip_archive && m_zip_file) + { + switch(iWhence) + { + default: + case SEEK_CUR: + // set file offset to current plus offset + if (m_file_pos + iFilePosition > m_file_size) + return -1; + file_pos = m_file_pos + iFilePosition; + break; + + case SEEK_SET: + // set file offset to offset + if (iFilePosition > m_file_size) + return -1; + file_pos = iFilePosition; + break; + + case SEEK_END: + // set file offset to EOF minus offset + if (iFilePosition > m_file_size) + return -1; + file_pos = m_file_size - iFilePosition; + break; + } + // if offset is past current file position + // then we must close, open then seek from zero. + if (file_pos < m_file_pos) + { + zip_fclose(m_zip_file); + int zip_flags = 0; + m_zip_file = zip_fopen_index(m_zip_archive, m_zip_index, zip_flags); + } + char buffer[1024]; + int read_bytes = 1024 * (file_pos / 1024); + for (int i = 0; i < read_bytes; i += 1024) + zip_fread(m_zip_file, buffer, 1024); + if (file_pos - read_bytes > 0) + zip_fread(m_zip_file, buffer, file_pos - read_bytes); + m_file_pos = file_pos; + } + + return m_file_pos; +} + +unsigned int CAPKFile::Read(void *lpBuf, int64_t uiBufSize) +{ + int bytes_read = uiBufSize; + if (m_zip_archive && m_zip_file) + { + // check for a read pas EOF and clamp it to EOF + if ((m_file_pos + bytes_read) > m_file_size) + bytes_read = m_file_size - m_file_pos; + + bytes_read = zip_fread(m_zip_file, lpBuf, bytes_read); + if (bytes_read != -1) + m_file_pos += bytes_read; + else + bytes_read = 0; + } + + return (unsigned int)bytes_read; +} + +int CAPKFile::Stat(struct __stat64* buffer) +{ + return Stat(m_url, buffer); +} + +int CAPKFile::Stat(const CURL& url, struct __stat64* buffer) +{ + memset(buffer, 0, sizeof(struct __stat64)); + + // do not use interal member vars here, + // we might be called without opening + CStdString path = url.GetFileName(); + CStdString host = url.GetHostName(); + // host name might be encoded rfc1738.txt, decode it. + CURL::Decode(host); + + struct zip *zip_archive; + int zip_flags = 0, zip_error = 0; + zip_archive = zip_open(host.c_str(), zip_flags, &zip_error); + if (!zip_archive || zip_error) + { + CLog::Log(LOGERROR, "CAPKFile::Stat: Unable to open archive : '%s'", + host.c_str()); + errno = ENOENT; + return -1; + } + + // check if file exists + int zip_index = zip_name_locate(zip_archive, url.GetFileName().c_str(), zip_flags); + if (zip_index != -1) + { + struct zip_stat sb; + zip_stat_init(&sb); + int rtn = zip_stat_index(zip_archive, zip_index, zip_flags, &sb); + if (rtn != -1) + { + buffer->st_gid = 0; + buffer->st_size = sb.size; + buffer->st_mode = _S_IFREG; + buffer->st_atime = sb.mtime; + buffer->st_ctime = sb.mtime; + buffer->st_mtime = sb.mtime; + } + } + + // check if directory exists + if (buffer->st_mode != _S_IFREG) + { + // zip directories have a '/' at end. + if (!URIUtils::HasSlashAtEnd(path)) + URIUtils::AddSlashAtEnd(path); + + int numFiles = zip_get_num_files(zip_archive); + for (int i = 0; i < numFiles; i++) + { + CStdString name = zip_get_name(zip_archive, i, zip_flags); + if (!name.IsEmpty() && name.Left(path.size()).Equals(path)) + { + buffer->st_gid = 0; + buffer->st_mode = _S_IFDIR; + break; + } + } + } + zip_close(zip_archive); + + if (buffer->st_mode != 0) + { + errno = 0; + return 0; + } + else + { + errno = ENOENT; + return -1; + } +} + +int64_t CAPKFile::GetPosition() +{ + return m_file_pos; +} + +int64_t CAPKFile::GetLength() +{ + return m_file_size; +} + +int CAPKFile::GetChunkSize() +{ + return 1; +} diff --git a/xbmc/filesystem/APKFile.h b/xbmc/filesystem/APKFile.h new file mode 100644 index 0000000000..f012fb1df9 --- /dev/null +++ b/xbmc/filesystem/APKFile.h @@ -0,0 +1,55 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "IFile.h" +#include "URL.h" + +struct zip; +struct zip_file; + +namespace XFILE +{ + class CAPKFile : public IFile + { + public: + CAPKFile(); + virtual ~CAPKFile(); + virtual bool Open(const CURL& url); + virtual void Close(); + virtual bool Exists(const CURL& url); + + virtual int64_t Seek(int64_t iFilePosition, int iWhence = SEEK_SET); + virtual unsigned int Read(void* lpBuf, int64_t uiBufSize); + virtual int Stat(struct __stat64* buffer); + virtual int Stat(const CURL& url, struct __stat64* buffer); + virtual int64_t GetLength(); + virtual int64_t GetPosition(); + virtual int GetChunkSize(); + protected: + CURL m_url; + int m_zip_index; + int64_t m_file_pos; + int64_t m_file_size; + struct zip_file *m_zip_file; + struct zip *m_zip_archive; + }; +} diff --git a/xbmc/filesystem/AddonsDirectory.cpp b/xbmc/filesystem/AddonsDirectory.cpp index 418f10f37b..3b36459915 100644 --- a/xbmc/filesystem/AddonsDirectory.cpp +++ b/xbmc/filesystem/AddonsDirectory.cpp @@ -32,6 +32,7 @@ #include "guilib/TextureManager.h" #include "File.h" #include "utils/URIUtils.h" +#include "URL.h" using namespace ADDON; @@ -294,10 +295,19 @@ bool CAddonsDirectory::GetScriptsAndPlugins(const CStdString &content, CFileItem for (unsigned i=0; i<addons.size(); i++) { - if (addons[i]->Type() == ADDON_PLUGIN) - items.Add(FileItemFromAddon(addons[i], "plugin://", true)); - else - items.Add(FileItemFromAddon(addons[i], "script://", false)); + CFileItemPtr item(FileItemFromAddon(addons[i], + addons[i]->Type()==ADDON_PLUGIN?"plugin://":"script://", + addons[i]->Type() == ADDON_PLUGIN)); + PluginPtr plugin = boost::dynamic_pointer_cast<CPluginSource>(addons[i]); + if (plugin->ProvidesSeveral()) + { + CURL url = item->GetAsUrl(); + CStdString opt; + opt.Format("?content_type=%s",content.c_str()); + url.SetOptions(opt); + item->SetPath(url.Get()); + } + items.Add(item); } items.Add(GetMoreItem(content)); diff --git a/xbmc/filesystem/AndroidAppDirectory.cpp b/xbmc/filesystem/AndroidAppDirectory.cpp new file mode 100644 index 0000000000..f11286abf0 --- /dev/null +++ b/xbmc/filesystem/AndroidAppDirectory.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" + +#if defined(TARGET_ANDROID) +#include "AndroidAppDirectory.h" +#include "xbmc/android/activity/XBMCApp.h" +#include "FileItem.h" +#include "File.h" +#include "utils/URIUtils.h" +#include <vector> +#include "utils/log.h" +#include "URL.h" + +using namespace XFILE; +using namespace std; + +CAndroidAppDirectory::CAndroidAppDirectory(void) +{ +} + +CAndroidAppDirectory::~CAndroidAppDirectory(void) +{ +} + +bool CAndroidAppDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) +{ + CURL url(strPath); + CStdString dirname = url.GetFileName(); + URIUtils::RemoveSlashAtEnd(dirname); + CLog::Log(LOGDEBUG, "CAndroidAppDirectory::GetDirectory: %s",dirname.c_str()); + if (dirname == "apps") + { + vector<androidPackage> applications; + CXBMCApp::ListApplications(&applications); + if (!applications.size()) + { + CLog::Log(LOGERROR, "CAndroidAppDirectory::GetDirectory Application lookup listing failed"); + return false; + } + for(unsigned int i = 0; i < applications.size(); i++) + { + if (applications[i].packageName == "org.xbmc.xbmc") + continue; + CFileItemPtr pItem(new CFileItem(applications[i].packageName)); + pItem->m_bIsFolder = false; + CStdString path; + path.Format("androidapp://%s/%s/%s", url.GetHostName(), dirname, applications[i].packageName); + pItem->SetPath(path); + pItem->SetLabel(applications[i].packageLabel); + pItem->SetThumbnailImage(path+".png"); + items.Add(pItem); + } + return true; + } + + CLog::Log(LOGERROR, "CAndroidAppDirectory::GetDirectory Failed to open %s",strPath.c_str()); + return false; +} + +bool CAndroidAppDirectory::IsAllowed(const CStdString& strFile) const +{ + // Entries are virtual, so we want them all. + return true; +} + +#endif diff --git a/xbmc/filesystem/AndroidAppDirectory.h b/xbmc/filesystem/AndroidAppDirectory.h new file mode 100644 index 0000000000..00c529087b --- /dev/null +++ b/xbmc/filesystem/AndroidAppDirectory.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once +#if defined(TARGET_ANDROID) +#include "IDirectory.h" +#include "FileItem.h" +namespace XFILE +{ + +class CAndroidAppDirectory : + public IDirectory +{ +public: + CAndroidAppDirectory(void); + virtual ~CAndroidAppDirectory(void); + virtual bool GetDirectory(const CStdString& strPath, CFileItemList &items); + virtual bool Exists(const char* strPath) { return true; }; + virtual bool IsAllowed(const CStdString& strFile) const; +}; +} +#endif + diff --git a/xbmc/filesystem/AndroidAppFile.cpp b/xbmc/filesystem/AndroidAppFile.cpp new file mode 100644 index 0000000000..c64548805d --- /dev/null +++ b/xbmc/filesystem/AndroidAppFile.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" + +#if defined(TARGET_ANDROID) + +#include "AndroidAppFile.h" +#include <sys/stat.h> +#include "Util.h" +#include "URL.h" +#include "utils/log.h" +#include "utils/URIUtils.h" +#include <jni.h> +#include "android/activity/XBMCApp.h" +using namespace XFILE; + +CFileAndroidApp::CFileAndroidApp(void) +{ + m_iconWidth = 0; + m_iconHeight = 0; +} + +CFileAndroidApp::~CFileAndroidApp(void) +{ + Close(); +} + +bool CFileAndroidApp::Open(const CURL& url) +{ + + m_url = url; + m_appname = URIUtils::GetFileName(url.Get()); + m_appname = m_appname.Left(m_appname.size() - 4); + + return m_appname.size() > 0; +} + +bool CFileAndroidApp::Exists(const CURL& url) +{ + return true; +} + +unsigned int CFileAndroidApp::Read(void* lpBuf, int64_t uiBufSize) +{ + CXBMCApp::GetIcon(m_appname, lpBuf, uiBufSize); + return uiBufSize; +} + +void CFileAndroidApp::Close() +{ +} + +int64_t CFileAndroidApp::GetLength() +{ + CXBMCApp::GetIconSize(m_appname, &m_iconWidth, &m_iconHeight); + return m_iconWidth * m_iconHeight * 4; +} + +unsigned int CFileAndroidApp::GetIconWidth() +{ + return m_iconWidth; +} + +unsigned int CFileAndroidApp::GetIconHeight() +{ + return m_iconHeight; +} + +int CFileAndroidApp::GetChunkSize() +{ + return 0; +} +int CFileAndroidApp::Stat(const CURL& url, struct __stat64* buffer) +{ + return 0; +} +int CFileAndroidApp::IoControl(EIoControl request, void* param) +{ + if(request == IOCTRL_SEEK_POSSIBLE) + return 0; + return 1; +} +#endif + diff --git a/xbmc/filesystem/AndroidAppFile.h b/xbmc/filesystem/AndroidAppFile.h new file mode 100644 index 0000000000..a4d4e98baf --- /dev/null +++ b/xbmc/filesystem/AndroidAppFile.h @@ -0,0 +1,67 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" + +#if defined(TARGET_ANDROID) +#include "IFile.h" +#include "URL.h" +#include "utils/StdString.h" +namespace XFILE +{ +class CFileAndroidApp : public IFile +{ +public: + /*! \brief Currently only used for retrieving App Icons. */ + CFileAndroidApp(void); + virtual ~CFileAndroidApp(void); + virtual bool Open(const CURL& url); + virtual bool Exists(const CURL& url); + virtual int Stat(const CURL& url, struct __stat64* buffer); + + /*! \brief Return 32bit rgba raw bitmap. */ + virtual unsigned int Read(void* lpBuf, int64_t uiBufSize); + virtual void Close(); + virtual int64_t GetLength(); + virtual int64_t Seek(int64_t, int) {return -1;}; + virtual int64_t GetPosition() {return 0;}; + virtual int GetChunkSize(); + virtual int IoControl(EIoControl request, void* param); + + /*! \brief Only valid after GetLength() has been called, usually by Open(). */ + unsigned int GetIconWidth(); + /*! \brief Only valid after GetLength() has been called, usually by Open(). */ + unsigned int GetIconHeight(); + +protected: + bool IsValidFile(const CURL& url); + +private: + CURL m_url; + CStdString m_appname; + int m_iconWidth; + int m_iconHeight; +}; +} + +#endif + diff --git a/xbmc/filesystem/CircularCache.cpp b/xbmc/filesystem/CircularCache.cpp index 30429d19c0..a0de8d4c10 100644 --- a/xbmc/filesystem/CircularCache.cpp +++ b/xbmc/filesystem/CircularCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Team XBMC + * Copyright (C) 2005-2012 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -51,7 +51,7 @@ int CCircularCache::Open() { #ifdef _WIN32 m_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, m_size, NULL); - if(m_handle == INVALID_HANDLE_VALUE) + if(m_handle == NULL) return CACHE_RC_ERROR; m_buf = (uint8_t*)MapViewOfFile(m_handle, FILE_MAP_ALL_ACCESS, 0, 0, 0); #else diff --git a/xbmc/filesystem/Directory.cpp b/xbmc/filesystem/Directory.cpp index 4dd4d69d05..522d1d8a23 100644 --- a/xbmc/filesystem/Directory.cpp +++ b/xbmc/filesystem/Directory.cpp @@ -167,6 +167,8 @@ bool CDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items, c cancel = true; break; } + + lock.Leave(); // prevent an occasional deadlock on exit g_windowManager.ProcessRenderLoop(false); } if(dialog) diff --git a/xbmc/filesystem/DirectoryFactory.cpp b/xbmc/filesystem/DirectoryFactory.cpp index 45e549b1d4..00eb9a3dab 100644 --- a/xbmc/filesystem/DirectoryFactory.cpp +++ b/xbmc/filesystem/DirectoryFactory.cpp @@ -77,6 +77,9 @@ #ifdef HAS_FILESYSTEM_HTSP #include "HTSPDirectory.h" #endif +#if defined(TARGET_ANDROID) +#include "APKDirectory.h" +#endif #include "ZipDirectory.h" #ifdef HAS_FILESYSTEM_RAR #include "RarDirectory.h" @@ -103,6 +106,9 @@ #ifdef HAVE_LIBBLURAY #include "BlurayDirectory.h" #endif +#if defined(TARGET_ANDROID) +#include "AndroidAppDirectory.h" +#endif using namespace XFILE; @@ -135,6 +141,9 @@ IDirectory* CDirectoryFactory::Create(const CStdString& strPath) #endif if (strProtocol == "udf") return new CUDFDirectory(); if (strProtocol == "plugin") return new CPluginDirectory(); +#if defined(TARGET_ANDROID) + if (strProtocol == "apk") return new CAPKDirectory(); +#endif if (strProtocol == "zip") return new CZipDirectory(); if (strProtocol == "rar") { @@ -209,6 +218,9 @@ IDirectory* CDirectoryFactory::Create(const CStdString& strPath) #ifdef HAVE_LIBBLURAY if (strProtocol == "bluray") return new CBlurayDirectory(); #endif +#if defined(TARGET_ANDROID) + if (strProtocol == "androidapp") return new CAndroidAppDirectory(); +#endif } CLog::Log(LOGWARNING, "%s - Unsupported protocol(%s) in %s", __FUNCTION__, strProtocol.c_str(), url.Get().c_str() ); diff --git a/xbmc/filesystem/File.cpp b/xbmc/filesystem/File.cpp index 78c96ea04f..52d5fd18d0 100644 --- a/xbmc/filesystem/File.cpp +++ b/xbmc/filesystem/File.cpp @@ -19,6 +19,7 @@ */ #include "File.h" +#include "IFile.h" #include "FileFactory.h" #include "Application.h" #include "DirectoryCache.h" @@ -28,6 +29,7 @@ #include "utils/URIUtils.h" #include "utils/BitstreamStats.h" #include "Util.h" +#include "URL.h" #include "commons/Exception.h" @@ -82,7 +84,7 @@ bool CFile::Cache(const CStdString& strFileName, const CStdString& strDest, XFIL // special case for zips - ignore caching CURL url(strFileName); - if (URIUtils::IsInZIP(strFileName)) + if (URIUtils::IsInZIP(strFileName) || URIUtils::IsInAPK(strFileName)) url.SetOptions("?cache=no"); if (file.Open(url.Get(), READ_TRUNCATED)) { @@ -215,6 +217,8 @@ bool CFile::Open(const CStdString& strFileName, unsigned int flags) { bool bPathInCache; CURL url2(strFileName); + if (url2.GetProtocol() == "apk") + url2.SetOptions(""); if (url2.GetProtocol() == "zip") url2.SetOptions(""); if (!g_directoryCache.FileExists(url2.Get(), bPathInCache) ) @@ -395,6 +399,13 @@ int CFile::Stat(struct __stat64 *buffer) return m_pFile->Stat(buffer); } +bool CFile::SkipNext() +{ + if (m_pFile) + return m_pFile->SkipNext(); + return false; +} + int CFile::Stat(const CStdString& strFileName, struct __stat64* buffer) { CURL url; @@ -764,6 +775,13 @@ int CFile::IoControl(EIoControl request, void* param) return result; } + +int CFile::GetChunkSize() +{ + if (m_pFile) + return m_pFile->GetChunkSize(); + return 0; +} //********************************************************************************************* //*************** Stream IO for CFile objects ************************************************* //********************************************************************************************* diff --git a/xbmc/filesystem/File.h b/xbmc/filesystem/File.h index 5240569a42..743fc366ae 100644 --- a/xbmc/filesystem/File.h +++ b/xbmc/filesystem/File.h @@ -30,14 +30,18 @@ #endif // _MSC_VER > 1000 #include <iostream> -#include "IFile.h" #include "utils/StdString.h" +#include "IFileTypes.h" +#include "PlatformDefs.h" class BitstreamStats; class CURL; namespace XFILE { + +class IFile; + class IFileCallback { public: @@ -78,7 +82,7 @@ public: int64_t GetPosition(); int64_t GetLength(); void Close(); - int GetChunkSize() {if (m_pFile) return m_pFile->GetChunkSize(); return 0;} + int GetChunkSize(); // will return a size, that is aligned to chunk size // but always greater or equal to the file's chunk size @@ -90,7 +94,7 @@ public: return minimum; } - bool SkipNext(){if (m_pFile) return m_pFile->SkipNext(); return false;} + bool SkipNext(); BitstreamStats* GetBitstreamStats() { return m_bitStreamStats; } int IoControl(EIoControl request, void* param); diff --git a/xbmc/filesystem/FileDirectoryFactory.cpp b/xbmc/filesystem/FileDirectoryFactory.cpp index 843691bc96..14e49925b7 100644 --- a/xbmc/filesystem/FileDirectoryFactory.cpp +++ b/xbmc/filesystem/FileDirectoryFactory.cpp @@ -35,6 +35,9 @@ #ifdef HAS_FILESYSTEM_RAR #include "RarDirectory.h" #endif +#if defined(TARGET_ANDROID) +#include "APKDirectory.h" +#endif #include "ZipDirectory.h" #include "SmartPlaylistDirectory.h" #include "playlists/SmartPlayList.h" @@ -112,6 +115,29 @@ IFileDirectory* CFileDirectoryFactory::Create(const CStdString& strPath, CFileIt return new CRSSDirectory(); #endif +#if defined(TARGET_ANDROID) + if (strExtension.Equals(".apk")) + { + CStdString strUrl; + URIUtils::CreateArchivePath(strUrl, "apk", strPath, ""); + + CFileItemList items; + CDirectory::GetDirectory(strUrl, items, strMask); + if (items.Size() == 0) // no files + pItem->m_bIsFolder = true; + else if (items.Size() == 1 && items[0]->m_idepth == 0) + { + // one STORED file - collapse it down + *pItem = *items[0]; + } + else + { // compressed or more than one file -> create a apk dir + pItem->SetPath(strUrl); + return new CAPKDirectory; + } + return NULL; + } +#endif if (strExtension.Equals(".zip")) { CStdString strUrl; diff --git a/xbmc/filesystem/FileFactory.cpp b/xbmc/filesystem/FileFactory.cpp index 2c492a61dd..9be1fb7b1c 100644 --- a/xbmc/filesystem/FileFactory.cpp +++ b/xbmc/filesystem/FileFactory.cpp @@ -55,6 +55,9 @@ #ifdef HAS_FILESYSTEM_VTP #include "VTPFile.h" #endif +#if defined(TARGET_ANDROID) +#include "APKFile.h" +#endif #include "ZipFile.h" #ifdef HAS_FILESYSTEM_RAR #include "RarFile.h" @@ -68,6 +71,9 @@ #ifdef HAS_FILESYSTEM_AFP #include "AFPFile.h" #endif +#if defined(TARGET_ANDROID) +#include "AndroidAppFile.h" +#endif #include "UPnPFile.h" #include "PipesManager.h" #include "PipeFile.h" @@ -105,6 +111,9 @@ IFile* CFileFactory::CreateLoader(const CURL& url) CStdString strProtocol = url.GetProtocol(); strProtocol.MakeLower(); +#if defined(TARGET_ANDROID) + if (strProtocol == "apk") return new CAPKFile(); +#endif if (strProtocol == "zip") return new CZipFile(); else if (strProtocol == "rar") { @@ -177,6 +186,9 @@ IFile* CFileFactory::CreateLoader(const CURL& url) #endif else if (strProtocol == "pipe") return new CPipeFile(); else if (strProtocol == "upnp") return new CUPnPFile(); +#if defined(TARGET_ANDROID) + else if (strProtocol == "androidapp") return new CFileAndroidApp(); +#endif } CLog::Log(LOGWARNING, "%s - Unsupported protocol(%s) in %s", __FUNCTION__, strProtocol.c_str(), url.Get().c_str() ); diff --git a/xbmc/filesystem/FileReaderFile.h b/xbmc/filesystem/FileReaderFile.h index 9ad8c9bb42..cb147f4a0e 100644 --- a/xbmc/filesystem/FileReaderFile.h +++ b/xbmc/filesystem/FileReaderFile.h @@ -20,6 +20,7 @@ */ #include "File.h" +#include "IFile.h" namespace XFILE { diff --git a/xbmc/filesystem/HTSPDirectory.h b/xbmc/filesystem/HTSPDirectory.h index f5651a21b1..00d283ed47 100644 --- a/xbmc/filesystem/HTSPDirectory.h +++ b/xbmc/filesystem/HTSPDirectory.h @@ -23,10 +23,10 @@ #include "threads/Thread.h" #include "threads/CriticalSection.h" #include "threads/Event.h" -#include "URL.h" #include "HTSPSession.h" #include "boost/shared_ptr.hpp" +class CURL; class CFileItem; typedef boost::shared_ptr<CFileItem> CFileItemPtr; namespace HTSP diff --git a/xbmc/filesystem/IDirectory.cpp b/xbmc/filesystem/IDirectory.cpp index 784427e6a0..052f4d6713 100644 --- a/xbmc/filesystem/IDirectory.cpp +++ b/xbmc/filesystem/IDirectory.cpp @@ -23,7 +23,7 @@ #include "IDirectory.h" #include "Util.h" #include "dialogs/GUIDialogOK.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "URL.h" #include "PasswordManager.h" #include "utils/URIUtils.h" @@ -114,7 +114,7 @@ bool IDirectory::ProcessRequirements() if (type == "keyboard") { CStdString input; - if (CGUIDialogKeyboard::ShowAndGetInput(input, m_requirements["heading"], false)) + if (CGUIKeyboardFactory::ShowAndGetInput(input, m_requirements["heading"], false)) { m_requirements["input"] = input; return true; diff --git a/xbmc/filesystem/IFile.cpp b/xbmc/filesystem/IFile.cpp index d4ea1ebcf0..7b94ecda4c 100644 --- a/xbmc/filesystem/IFile.cpp +++ b/xbmc/filesystem/IFile.cpp @@ -19,6 +19,7 @@ */ #include "IFile.h" +#include "URL.h" #include <cstring> #include <errno.h> @@ -88,3 +89,13 @@ bool IFile::ReadString(char *szLine, int iLineLength) } return true; } + +CRedirectException::CRedirectException() : + m_pNewFileImp(NULL), m_pNewUrl(NULL) +{ +} + +CRedirectException::CRedirectException(IFile *pNewFileImp, CURL *pNewUrl) : + m_pNewFileImp(pNewFileImp), m_pNewUrl(pNewUrl) +{ +} diff --git a/xbmc/filesystem/IFile.h b/xbmc/filesystem/IFile.h index 1d02724537..6c33e8726c 100644 --- a/xbmc/filesystem/IFile.h +++ b/xbmc/filesystem/IFile.h @@ -32,35 +32,17 @@ #include "PlatformDefs.h" // for __stat64 #endif -#include "URL.h" - #include <stdio.h> #include <stdint.h> #include <sys/stat.h> -namespace XFILE -{ +#include "utils/StdString.h" +#include "IFileTypes.h" -struct SNativeIoControl -{ - int request; - void* param; -}; +class CURL; -struct SCacheStatus +namespace XFILE { - uint64_t forward; /**< number of bytes cached forward of current position */ - unsigned maxrate; /**< maximum number of bytes per second cache is allowed to fill */ - unsigned currate; /**< average read rate from source file since last position change */ - bool full; /**< is the cache full */ -}; - -typedef enum { - IOCTRL_NATIVE = 1, /**< SNativeIoControl structure, containing what should be passed to native ioctrl */ - IOCTRL_SEEK_POSSIBLE = 2, /**< return 0 if known not to work, 1 if it should work */ - IOCTRL_CACHE_STATUS = 3, /**< SCacheStatus structure */ - IOCTRL_CACHE_SETRATE = 4, /**< unsigned int with speed limit for caching in bytes per second */ -} EIoControl; class IFile { @@ -107,16 +89,11 @@ public: IFile *m_pNewFileImp; CURL *m_pNewUrl; - CRedirectException() : m_pNewFileImp(NULL), m_pNewUrl(NULL) { } + CRedirectException(); - CRedirectException(IFile *pNewFileImp, CURL *pNewUrl=NULL) - : m_pNewFileImp(pNewFileImp) - , m_pNewUrl(pNewUrl) - { } + CRedirectException(IFile *pNewFileImp, CURL *pNewUrl=NULL); }; } #endif // !defined(AFX_IFILE_H__7EE73AC7_36BC_4822_93FF_44F3B0C766F6__INCLUDED_) - - diff --git a/xbmc/filesystem/IFileTypes.h b/xbmc/filesystem/IFileTypes.h new file mode 100644 index 0000000000..be72dc059d --- /dev/null +++ b/xbmc/filesystem/IFileTypes.h @@ -0,0 +1,48 @@ + +/* + * Copyright (C) 2005-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ +#pragma once + +namespace XFILE +{ + +struct SNativeIoControl +{ + int request; + void* param; +}; + +struct SCacheStatus +{ + uint64_t forward; /**< number of bytes cached forward of current position */ + unsigned maxrate; /**< maximum number of bytes per second cache is allowed to fill */ + unsigned currate; /**< average read rate from source file since last position change */ + bool full; /**< is the cache full */ +}; + +typedef enum { + IOCTRL_NATIVE = 1, /**< SNativeIoControl structure, containing what should be passed to native ioctrl */ + IOCTRL_SEEK_POSSIBLE = 2, /**< return 0 if known not to work, 1 if it should work */ + IOCTRL_CACHE_STATUS = 3, /**< SCacheStatus structure */ + IOCTRL_CACHE_SETRATE = 4, /**< unsigned int with speed limit for caching in bytes per second */ +} EIoControl; + +} diff --git a/xbmc/filesystem/ImageFile.h b/xbmc/filesystem/ImageFile.h index b956b44deb..f73eb13295 100644 --- a/xbmc/filesystem/ImageFile.h +++ b/xbmc/filesystem/ImageFile.h @@ -21,6 +21,7 @@ */ #include "File.h" +#include "IFile.h" namespace XFILE { diff --git a/xbmc/filesystem/Makefile.in b/xbmc/filesystem/Makefile.in index cee6f27e13..b7519b7b04 100644 --- a/xbmc/filesystem/Makefile.in +++ b/xbmc/filesystem/Makefile.in @@ -3,6 +3,8 @@ ARCH=@ARCH@ CXXFLAGS+=-D__STDC_FORMAT_MACROS \ SRCS=AddonsDirectory.cpp \ + AndroidAppFile.cpp \ + AndroidAppDirectory.cpp \ ASAPFileDirectory.cpp \ CacheStrategy.cpp \ CircularCache.cpp \ @@ -92,6 +94,11 @@ SRCS=AddonsDirectory.cpp \ ZipFile.cpp \ ZipManager.cpp +ifeq (@USE_ANDROID@,1) +SRCS+=APKDirectory.cpp +SRCS+=APKFile.cpp +endif + ifeq (@HAVE_XBMC_NONFREE@,1) SRCS+=RarFile.cpp SRCS+=RarDirectory.cpp diff --git a/xbmc/filesystem/MultiPathFile.h b/xbmc/filesystem/MultiPathFile.h index a89938e308..d14487add1 100644 --- a/xbmc/filesystem/MultiPathFile.h +++ b/xbmc/filesystem/MultiPathFile.h @@ -21,6 +21,7 @@ */ #include "File.h" +#include "IFile.h" namespace XFILE { diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.cpp index 6d87ce4988..0e3c91cc76 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.cpp @@ -47,6 +47,7 @@ #include "FileItem.h" #include "utils/StringUtils.h" #include "guilib/LocalizeStrings.h" +#include "music/MusicDbUrl.h" using namespace std; using namespace XFILE::MUSICDATABASEDIRECTORY; @@ -88,6 +89,9 @@ CDirectoryNode* CDirectoryNode::ParseURL(const CStdString& strPath) pParent=pNode; } + // Add all the additional URL options to the last node + pNode->AddOptions(url.GetOptions()); + return pNode; } @@ -217,9 +221,21 @@ CStdString CDirectoryNode::BuildPath() const for (int i=0; i<(int)array.size(); ++i) strPath+=array[i]+"/"; + string options = m_options.GetOptionsString(); + if (!options.empty()) + strPath += "?" + options; + return strPath; } +void CDirectoryNode::AddOptions(const CStdString &options) +{ + if (options.empty()) + return; + + m_options.AddOptions(options); +} + // Collects Query params from this and all parent nodes. If a NODE_TYPE can // be used as a database parameter, it will be added to the // params object. @@ -253,6 +269,7 @@ bool CDirectoryNode::GetChilds(CFileItemList& items) bool bSuccess=false; if (pNode.get()) { + pNode->m_options = m_options; bSuccess=pNode->GetContent(items); if (bSuccess) { @@ -275,6 +292,10 @@ void CDirectoryNode::AddQueuingFolder(CFileItemList& items) const { CFileItemPtr pItem; + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(BuildPath())) + return; + // always hide "all" items if (g_advancedSettings.m_bMusicLibraryHideAllItems) return; @@ -294,14 +315,16 @@ void CDirectoryNode::AddQueuingFolder(CFileItemList& items) const /* no need for all genres case NODE_TYPE_GENRE: pItem.reset(new CFileItem(g_localizeStrings.Get(15105))); // "All Genres" - pItem->GetPath() = BuildPath() + "-1/"; + musicUrl.AppendPath("-1/"); + pItem->SetPath(musicUrl.ToString()); break; */ case NODE_TYPE_ARTIST: if (GetType() == NODE_TYPE_OVERVIEW) return; pItem.reset(new CFileItem(g_localizeStrings.Get(15103))); // "All Artists" - pItem->SetPath(BuildPath() + "-1/"); + musicUrl.AppendPath("-1/"); + pItem->SetPath(musicUrl.ToString()); break; // All album related nodes @@ -313,7 +336,8 @@ void CDirectoryNode::AddQueuingFolder(CFileItemList& items) const case NODE_TYPE_ALBUM_TOP100: case NODE_TYPE_YEAR_ALBUM: pItem.reset(new CFileItem(g_localizeStrings.Get(15102))); // "All Albums" - pItem->SetPath(BuildPath() + "-1/"); + musicUrl.AppendPath("-1/"); + pItem->SetPath(musicUrl.ToString()); break; // All song related nodes @@ -324,7 +348,8 @@ void CDirectoryNode::AddQueuingFolder(CFileItemList& items) const case NODE_TYPE_SONG_TOP100: case NODE_TYPE_SONG: pItem = new CFileItem(g_localizeStrings.Get(15104)); // "All Songs" - pItem->GetPath() = BuildPath() + "-1/"; + musicUrl.AppendPath("-1/"); + pItem->SetPath(musicUrl.ToString()); break;*/ default: break; diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.h b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.h index b659d0e0c7..56034d5c6e 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.h +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNode.h @@ -20,8 +20,8 @@ * */ - #include "utils/StdString.h" +#include "utils/UrlOptions.h" class CFileItemList; @@ -82,6 +82,7 @@ namespace XFILE CDirectoryNode(NODE_TYPE Type, const CStdString& strName, CDirectoryNode* pParent); static CDirectoryNode* CreateNode(NODE_TYPE Type, const CStdString& strName, CDirectoryNode* pParent); + void AddOptions(const CStdString &options); void CollectQueryParams(CQueryParams& params) const; const CStdString& GetName() const; @@ -99,6 +100,7 @@ namespace XFILE NODE_TYPE m_Type; CStdString m_strName; CDirectoryNode* m_pParent; + CUrlOptions m_options; }; } } diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbum.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbum.cpp index fdc6d32272..04368dd46f 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbum.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeAlbum.cpp @@ -55,7 +55,7 @@ bool CDirectoryNodeAlbum::GetContent(CFileItemList& items) const CQueryParams params; CollectQueryParams(params); - bool bSuccess=musicdatabase.GetAlbumsNav(BuildPath(), items, params.GetGenreId(), params.GetArtistId(),-1,-1); + bool bSuccess=musicdatabase.GetAlbumsNav(BuildPath(), items, params.GetGenreId(), params.GetArtistId()); musicdatabase.Close(); diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeArtist.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeArtist.cpp index 4f0f11bce8..b5cfc53c1b 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeArtist.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeArtist.cpp @@ -56,7 +56,7 @@ bool CDirectoryNodeArtist::GetContent(CFileItemList& items) const CQueryParams params; CollectQueryParams(params); - bool bSuccess = musicdatabase.GetArtistsNav(BuildPath(), items, params.GetGenreId(), !g_guiSettings.GetBool("musiclibrary.showcompilationartists")); + bool bSuccess = musicdatabase.GetArtistsNav(BuildPath(), items, !g_guiSettings.GetBool("musiclibrary.showcompilationartists"), params.GetGenreId()); musicdatabase.Close(); diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp index c218021141..c8968738ca 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeOverview.cpp @@ -74,7 +74,8 @@ bool CDirectoryNodeOverview::GetContent(CFileItemList& items) const bool showSingles = false; if (musicDatabase.Open()) { - if (musicDatabase.GetSongsCount("where idAlbum in (select idAlbum from album where strAlbum='')") > 0) + CDatabase::Filter filter("idAlbum IN (SELECT idAlbum FROM album WHERE strAlbum = '')"); + if (musicDatabase.GetSongsCount(filter) > 0) showSingles = true; } diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeSingles.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeSingles.cpp index 8ce6438f13..16d095af97 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeSingles.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeSingles.cpp @@ -37,8 +37,9 @@ bool CDirectoryNodeSingles::GetContent(CFileItemList& items) const if (!musicdatabase.Open()) return false; - CStdString strBaseDir=BuildPath(); - bool bSuccess=musicdatabase.GetSongsByWhere(strBaseDir, "where idAlbum in (select idAlbum from album where strAlbum='')", items); + CDatabase::Filter filter; + filter.where = "idAlbum IN (SELECT idAlbum FROM album WHERE strAlbum = '')"; + bool bSuccess=musicdatabase.GetSongsByWhere(BuildPath(), filter, items); musicdatabase.Close(); diff --git a/xbmc/filesystem/MusicDatabaseFile.h b/xbmc/filesystem/MusicDatabaseFile.h index ccc555be96..4b4ebf170b 100644 --- a/xbmc/filesystem/MusicDatabaseFile.h +++ b/xbmc/filesystem/MusicDatabaseFile.h @@ -20,6 +20,7 @@ * */ +#include "IFile.h" #include "File.h" namespace XFILE diff --git a/xbmc/filesystem/NFSFile.cpp b/xbmc/filesystem/NFSFile.cpp index 751eb54360..9a73403e65 100644 --- a/xbmc/filesystem/NFSFile.cpp +++ b/xbmc/filesystem/NFSFile.cpp @@ -751,6 +751,7 @@ bool CNFSFile::OpenForWrite(const CURL& url, bool bOverWrite) if(ret == 0) { gNfsConnection.GetImpl()->nfs_close(m_pNfsContext,m_pFileHandle); + m_pFileHandle = NULL; } } diff --git a/xbmc/filesystem/PipeFile.cpp b/xbmc/filesystem/PipeFile.cpp index 5415dba701..5c83e0d6f9 100644 --- a/xbmc/filesystem/PipeFile.cpp +++ b/xbmc/filesystem/PipeFile.cpp @@ -23,6 +23,7 @@ #include "threads/SingleLock.h" #include "PipesManager.h" #include "utils/StringUtils.h" +#include "URL.h" using namespace XFILE; diff --git a/xbmc/filesystem/PluginDirectory.cpp b/xbmc/filesystem/PluginDirectory.cpp index aa4612e3c3..2a35eefe67 100644 --- a/xbmc/filesystem/PluginDirectory.cpp +++ b/xbmc/filesystem/PluginDirectory.cpp @@ -35,10 +35,12 @@ #include "dialogs/GUIDialogProgress.h" #include "settings/GUISettings.h" #include "FileItem.h" +#include "video/VideoInfoTag.h" #include "guilib/LocalizeStrings.h" #include "utils/log.h" #include "utils/TimeUtils.h" -#include "Application.h" +#include "ApplicationMessenger.h" +#include "URL.h" using namespace XFILE; using namespace std; @@ -147,6 +149,8 @@ bool CPluginDirectory::GetPluginResult(const CStdString& strPath, CFileItem &res resultItem.SetPath(newDir->m_fileResult->GetPath()); resultItem.SetMimeType(newDir->m_fileResult->GetMimeType(false)); resultItem.UpdateInfo(*newDir->m_fileResult); + if (newDir->m_fileResult->HasVideoInfoTag() && newDir->m_fileResult->GetVideoInfoTag()->m_resumePoint.IsSet()) + resultItem.m_lStartOffset = STARTOFFSET_RESUME; // resume point set in the resume item, so force resume } delete newDir; @@ -321,6 +325,15 @@ void CPluginDirectory::AddSortMethod(int handle, SORT_METHOD sortMethod, const C dir->m_listItems->AddSortMethod(SORT_METHOD_VIDEO_TITLE, 369, LABEL_MASKS("%T", label2Mask)); break; } + case SORT_METHOD_VIDEO_SORT_TITLE: + case SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE: + { + if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + dir->m_listItems->AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE, 369, LABEL_MASKS("%T", label2Mask)); + else + dir->m_listItems->AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE, 369, LABEL_MASKS("%T", label2Mask)); + break; + } case SORT_METHOD_MPAA_RATING: { dir->m_listItems->AddSortMethod(SORT_METHOD_MPAA_RATING, 563, LABEL_MASKS("%T", "%O")); @@ -539,7 +552,7 @@ bool CPluginDirectory::WaitOnScriptResult(const CStdString &scriptPath, const CS } } if (progressBar) - g_application.getApplicationMessenger().Close(progressBar, false, false); + CApplicationMessenger::Get().Close(progressBar, false, false); return !m_cancelled && m_success; } diff --git a/xbmc/filesystem/RarFile.h b/xbmc/filesystem/RarFile.h index 30beab466a..206d47f189 100644 --- a/xbmc/filesystem/RarFile.h +++ b/xbmc/filesystem/RarFile.h @@ -26,6 +26,7 @@ #define FILERAR_H_ #include "File.h" +#include "IFile.h" #include "threads/Thread.h" #include "threads/Event.h" diff --git a/xbmc/filesystem/SAPFile.cpp b/xbmc/filesystem/SAPFile.cpp index df31b08776..0b5a79e59e 100644 --- a/xbmc/filesystem/SAPFile.cpp +++ b/xbmc/filesystem/SAPFile.cpp @@ -20,6 +20,7 @@ #include "SAPFile.h" #include "SAPDirectory.h" #include "threads/SingleLock.h" +#include "URL.h" #include <sys/stat.h> #include <vector> @@ -175,4 +176,4 @@ int CSAPFile::IoControl(EIoControl request, void* param) return 1; return -1; -}
\ No newline at end of file +} diff --git a/xbmc/filesystem/SFTPFile.cpp b/xbmc/filesystem/SFTPFile.cpp index a948b4fbfd..2b28fb9351 100644 --- a/xbmc/filesystem/SFTPFile.cpp +++ b/xbmc/filesystem/SFTPFile.cpp @@ -28,6 +28,7 @@ #include "utils/TimeUtils.h" #include "utils/Variant.h" #include "Util.h" +#include "URL.h" #include <fcntl.h> #include <sstream> diff --git a/xbmc/filesystem/SFTPFile.h b/xbmc/filesystem/SFTPFile.h index bf29db6ebd..eb6d2295f3 100644 --- a/xbmc/filesystem/SFTPFile.h +++ b/xbmc/filesystem/SFTPFile.h @@ -24,7 +24,6 @@ #include "system.h" #ifdef HAS_FILESYSTEM_SFTP #include "IFile.h" -#include "URL.h" #include "FileItem.h" #include "threads/CriticalSection.h" @@ -34,6 +33,8 @@ #include <map> #include <boost/shared_ptr.hpp> +class CURL; + #if LIBSSH_VERSION_INT < SSH_VERSION_INT(0,3,2) #define ssh_session SSH_SESSION #endif diff --git a/xbmc/filesystem/ShoutcastFile.cpp b/xbmc/filesystem/ShoutcastFile.cpp index ef9289d873..9a0acfda13 100644 --- a/xbmc/filesystem/ShoutcastFile.cpp +++ b/xbmc/filesystem/ShoutcastFile.cpp @@ -35,7 +35,7 @@ #include "utils/HTMLUtil.h" #include "utils/CharsetConverter.h" #include "utils/TimeUtils.h" -#include "GUIInfoManager.h" +#include "ApplicationMessenger.h" #include "utils/log.h" using namespace XFILE; @@ -80,7 +80,7 @@ bool CShoutcastFile::Open(const CURL& url) if (m_tag.GetGenre().empty()) m_tag.SetGenre(m_file.GetHttpHeader().GetValue("ice-genre")); // icecast m_tag.SetLoaded(true); - g_infoManager.SetCurrentSongTag(m_tag); + CApplicationMessenger::Get().SetCurrentSongTag(m_tag); } m_metaint = atoi(m_file.GetHttpHeader().GetValue("icy-metaint").c_str()); if (!m_metaint) @@ -104,7 +104,7 @@ unsigned int CShoutcastFile::Read(void* lpBuf, int64_t uiBufSize) if (XbmcThreads::SystemClockMillis() - m_lastTime > 500) { m_lastTime = XbmcThreads::SystemClockMillis(); - g_infoManager.SetCurrentSongTag(m_tag); + CApplicationMessenger::Get().SetCurrentSongTag(m_tag); } unsigned int toRead; diff --git a/xbmc/filesystem/SlingboxFile.cpp b/xbmc/filesystem/SlingboxFile.cpp index abaecdc5b6..5804f65713 100644 --- a/xbmc/filesystem/SlingboxFile.cpp +++ b/xbmc/filesystem/SlingboxFile.cpp @@ -26,6 +26,7 @@ #include "settings/Settings.h" #include "utils/log.h" #include "utils/XMLUtils.h" +#include "URL.h" using namespace XFILE; using namespace std; @@ -68,7 +69,7 @@ bool CSlingboxFile::Open(const CURL& url) // Connect to the Slingbox if (m_pSlingbox->Connect(bAdmin, url.GetPassWord())) { - CLog::Log(LOGDEBUG, "%s - Sucessfully connected to Slingbox: %s", + CLog::Log(LOGDEBUG, "%s - Successfully connected to Slingbox: %s", __FUNCTION__, url.GetHostName().c_str()); } else diff --git a/xbmc/filesystem/SmartPlaylistDirectory.cpp b/xbmc/filesystem/SmartPlaylistDirectory.cpp index 15293b86bf..5cb822ce20 100644 --- a/xbmc/filesystem/SmartPlaylistDirectory.cpp +++ b/xbmc/filesystem/SmartPlaylistDirectory.cpp @@ -71,8 +71,6 @@ namespace XFILE if (db.Open()) { MediaType mediaType = DatabaseUtils::MediaTypeFromString(playlist.GetType()); - CVideoDatabase::Filter filter; - filter.where = playlist.GetWhereClause(db, playlists); CStdString strBaseDir; switch (mediaType) @@ -90,7 +88,16 @@ namespace XFILE return false; } - success = db.GetSortedVideos(mediaType, strBaseDir, sorting, items, filter, true); + CVideoDbUrl videoUrl; + CStdString xsp; + if (!videoUrl.FromString(strBaseDir) || !playlist.SaveAsJson(xsp, false)) + return false; + + // store the smartplaylist as JSON in the URL as well + videoUrl.AddOption("xsp", xsp); + + CDatabase::Filter filter; + success = db.GetSortedVideos(mediaType, videoUrl.ToString(), sorting, items, filter, true); db.Close(); } } @@ -99,33 +106,60 @@ namespace XFILE CMusicDatabase db; if (db.Open()) { - CStdString whereClause = playlist.GetWhereClause(db, playlists); - if (!whereClause.empty()) - whereClause = "WHERE " + whereClause; - success = db.GetAlbumsByWhere("musicdb://3/", whereClause, "", items, sorting); + CMusicDbUrl musicUrl; + CStdString xsp; + if (!musicUrl.FromString("musicdb://3/") || !playlist.SaveAsJson(xsp, false)) + return false; + + // store the smartplaylist as JSON in the URL as well + musicUrl.AddOption("xsp", xsp); + + CDatabase::Filter filter; + success = db.GetAlbumsByWhere(musicUrl.ToString(), filter, items, sorting); items.SetContent("albums"); db.Close(); } } + else if (playlist.GetType().Equals("artists")) + { + CMusicDatabase db; + if (db.Open()) + { + CMusicDbUrl musicUrl; + CStdString xsp; + + if (!musicUrl.FromString("musicdb://2/") || !playlist.SaveAsJson(xsp, false)) + return false; + + // store the smartplaylist as JSON in the URL as well + musicUrl.AddOption("xsp", xsp); + + CDatabase::Filter filter; + success = db.GetArtistsByWhere(musicUrl.ToString(), filter, items, sorting); + items.SetContent("albums"); + db.Close(); + } + } + if (playlist.GetType().Equals("songs") || playlist.GetType().Equals("mixed") || playlist.GetType().IsEmpty()) { CMusicDatabase db; if (db.Open()) { - CStdString whereClause; + CSmartPlaylist songPlaylist(playlist); if (playlist.GetType().IsEmpty() || playlist.GetType().Equals("mixed")) - { - CSmartPlaylist songPlaylist(playlist); songPlaylist.SetType("songs"); - whereClause = songPlaylist.GetWhereClause(db, playlists); - } - else - whereClause = playlist.GetWhereClause(db, playlists); + + CMusicDbUrl musicUrl; + CStdString xsp; + if (!musicUrl.FromString("musicdb://4/") || !songPlaylist.SaveAsJson(xsp, false)) + return false; - if (!whereClause.empty()) - whereClause = "WHERE " + whereClause; + // store the smartplaylist as JSON in the URL as well + musicUrl.AddOption("xsp", xsp); - success = db.GetSongsByWhere("", whereClause, items, sorting); + CDatabase::Filter filter; + success = db.GetSongsByWhere(musicUrl.ToString(), filter, items, sorting); items.SetContent("songs"); db.Close(); } @@ -135,18 +169,20 @@ namespace XFILE CVideoDatabase db; if (db.Open()) { - CVideoDatabase::Filter filter; + CSmartPlaylist mvidPlaylist(playlist); if (playlist.GetType().Equals("mixed")) - { - CSmartPlaylist mvidPlaylist(playlist); mvidPlaylist.SetType("musicvideos"); - filter.where = mvidPlaylist.GetWhereClause(db, playlists); - } - else - filter.where = playlist.GetWhereClause(db, playlists); + CVideoDbUrl videoUrl; + CStdString xsp; + if (!videoUrl.FromString("videodb://3/2/") || !mvidPlaylist.SaveAsJson(xsp, false)) + return false; + + // store the smartplaylist as JSON in the URL as well + videoUrl.AddOption("xsp", xsp); + CFileItemList items2; - success2 = db.GetSortedVideos(MediaTypeMusicVideo, "videodb://3/2/", sorting, items2, filter); + success2 = db.GetSortedVideos(MediaTypeMusicVideo, videoUrl.ToString(), sorting, items2); db.Close(); items.Append(items2); diff --git a/xbmc/filesystem/SpecialProtocol.cpp b/xbmc/filesystem/SpecialProtocol.cpp index c351babbaf..cde5af7f84 100644 --- a/xbmc/filesystem/SpecialProtocol.cpp +++ b/xbmc/filesystem/SpecialProtocol.cpp @@ -145,6 +145,9 @@ CStdString CSpecialProtocol::TranslatePath(const CURL &url) URIUtils::AddFileToFolder(CUtil::VideoPlaylistsLocation(), FileName, translatedPath); else if (RootDir.Equals("skin")) URIUtils::AddFileToFolder(g_graphicsContext.GetMediaDir(), FileName, translatedPath); + else if (RootDir.Equals("logpath")) + URIUtils::AddFileToFolder(g_settings.m_logFolder, FileName, translatedPath); + // from here on, we have our "real" special paths else if (RootDir.Equals("xbmc") || diff --git a/xbmc/filesystem/SpecialProtocolFile.h b/xbmc/filesystem/SpecialProtocolFile.h index d9e05de64f..300be8124d 100644 --- a/xbmc/filesystem/SpecialProtocolFile.h +++ b/xbmc/filesystem/SpecialProtocolFile.h @@ -21,6 +21,7 @@ */ #include "File.h" +#include "IFile.h" namespace XFILE { diff --git a/xbmc/filesystem/UPnPFile.cpp b/xbmc/filesystem/UPnPFile.cpp index 3d7db4bc55..8502c0dab2 100644 --- a/xbmc/filesystem/UPnPFile.cpp +++ b/xbmc/filesystem/UPnPFile.cpp @@ -24,6 +24,7 @@ #include "FileFactory.h" #include "FileItem.h" #include "utils/log.h" +#include "URL.h" using namespace XFILE; diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp index 1eb27b31ce..3a804f6260 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp @@ -94,6 +94,9 @@ CDirectoryNode* CDirectoryNode::ParseURL(const CStdString& strPath) pParent=pNode; } + // Add all the additional URL options to the last node + pNode->AddOptions(url.GetOptions()); + return pNode; } @@ -227,9 +230,21 @@ CStdString CDirectoryNode::BuildPath() const for (int i=0; i<(int)array.size(); ++i) strPath+=array[i]+"/"; + string options = m_options.GetOptionsString(); + if (!options.empty()) + strPath += "?" + options; + return strPath; } +void CDirectoryNode::AddOptions(const CStdString &options) +{ + if (options.empty()) + return; + + m_options.AddOptions(options); +} + // Collects Query params from this and all parent nodes. If a NODE_TYPE can // be used as a database parameter, it will be added to the // params object. @@ -263,6 +278,7 @@ bool CDirectoryNode::GetChilds(CFileItemList& items) bool bSuccess=false; if (pNode.get()) { + pNode->m_options = m_options; bSuccess=pNode->GetContent(items); if (bSuccess) { @@ -293,6 +309,10 @@ void CDirectoryNode::AddQueuingFolder(CFileItemList& items) const if (items.GetObjectCount() <= 1) return; + CVideoDbUrl videoUrl; + if (!videoUrl.FromString(BuildPath())) + return; + // hack - as the season node might return episodes auto_ptr<CDirectoryNode> pNode(ParseURL(items.GetPath())); @@ -302,7 +322,8 @@ void CDirectoryNode::AddQueuingFolder(CFileItemList& items) const { CStdString strLabel = g_localizeStrings.Get(20366); pItem.reset(new CFileItem(strLabel)); // "All Seasons" - pItem->SetPath(BuildPath() + "-1/"); + videoUrl.AppendPath("-1/"); + pItem->SetPath(videoUrl.ToString()); // set the number of watched and unwatched items accordingly int watched = 0; int unwatched = 0; diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.h b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.h index 0ba9896bf4..107af31f17 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.h +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.h @@ -20,8 +20,8 @@ * */ - #include "utils/StdString.h" +#include "utils/UrlOptions.h" class CFileItemList; @@ -84,6 +84,7 @@ namespace XFILE CDirectoryNode(NODE_TYPE Type, const CStdString& strName, CDirectoryNode* pParent); static CDirectoryNode* CreateNode(NODE_TYPE Type, const CStdString& strName, CDirectoryNode* pParent); + void AddOptions(const CStdString &options); void CollectQueryParams(CQueryParams& params) const; const CStdString& GetName() const; @@ -101,6 +102,7 @@ namespace XFILE NODE_TYPE m_Type; CStdString m_strName; CDirectoryNode* m_pParent; + CUrlOptions m_options; }; } } diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeEpisodes.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeEpisodes.cpp index 3bfee107a1..dbb2c9ba82 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeEpisodes.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeEpisodes.cpp @@ -40,13 +40,11 @@ bool CDirectoryNodeEpisodes::GetContent(CFileItemList& items) const CQueryParams params; CollectQueryParams(params); - CStdString strBaseDir=BuildPath(); - int season = (int)params.GetSeason(); if (season == -2) season = -1; - bool bSuccess=videodatabase.GetEpisodesNav(strBaseDir, items, params.GetGenreId(), params.GetYear(), params.GetActorId(), params.GetDirectorId(), params.GetTvShowId(), season); + bool bSuccess=videodatabase.GetEpisodesNav(BuildPath(), items, params.GetGenreId(), params.GetYear(), params.GetActorId(), params.GetDirectorId(), params.GetTvShowId(), season); videodatabase.Close(); diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp index 87c5370e89..ffde698dd8 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp @@ -23,6 +23,7 @@ #include "FileItem.h" #include "guilib/LocalizeStrings.h" #include "video/VideoDatabase.h" +#include "video/VideoDbUrl.h" using namespace XFILE::VIDEODATABASEDIRECTORY; using namespace std; @@ -64,6 +65,10 @@ CStdString CDirectoryNodeMoviesOverview::GetLocalizedName() const bool CDirectoryNodeMoviesOverview::GetContent(CFileItemList& items) const { + CVideoDbUrl videoUrl; + if (!videoUrl.FromString(BuildPath())) + return false; + for (unsigned int i = 0; i < sizeof(MovieChildren) / sizeof(Node); ++i) { if (i == 6) @@ -72,9 +77,12 @@ bool CDirectoryNodeMoviesOverview::GetContent(CFileItemList& items) const if (db.Open() && !db.HasSets()) continue; } - CStdString path; - path.Format("%s%ld/", BuildPath().c_str(), MovieChildren[i].id); - CFileItemPtr pItem(new CFileItem(path, true)); + + CVideoDbUrl itemUrl = videoUrl; + CStdString strDir; strDir.Format("%ld/", MovieChildren[i].id); + itemUrl.AppendPath(strDir); + + CFileItemPtr pItem(new CFileItem(itemUrl.ToString(), true)); pItem->SetLabel(g_localizeStrings.Get(MovieChildren[i].label)); pItem->SetCanQueue(false); items.Add(pItem); diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMusicVideosOverview.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMusicVideosOverview.cpp index 43c54c7438..073f2d2eb2 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMusicVideosOverview.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMusicVideosOverview.cpp @@ -22,6 +22,7 @@ #include "DirectoryNodeMusicVideosOverview.h" #include "FileItem.h" #include "guilib/LocalizeStrings.h" +#include "video/VideoDbUrl.h" using namespace XFILE::VIDEODATABASEDIRECTORY; @@ -60,12 +61,19 @@ CStdString CDirectoryNodeMusicVideosOverview::GetLocalizedName() const bool CDirectoryNodeMusicVideosOverview::GetContent(CFileItemList& items) const { + CVideoDbUrl videoUrl; + if (!videoUrl.FromString(BuildPath())) + return false; + for (unsigned int i = 0; i < sizeof(MusicVideoChildren) / sizeof(Node); ++i) { CFileItemPtr pItem(new CFileItem(g_localizeStrings.Get(MusicVideoChildren[i].label))); - CStdString strDir; - strDir.Format("%ld/", MusicVideoChildren[i].id); - pItem->SetPath(BuildPath() + strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString strDir; strDir.Format("%ld/", MusicVideoChildren[i].id); + itemUrl.AppendPath(strDir); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder = true; pItem->SetCanQueue(false); items.Add(pItem); diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp index 312a9db1a5..2b0f0e9846 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp @@ -25,6 +25,7 @@ #include "settings/Settings.h" #include "FileItem.h" #include "guilib/LocalizeStrings.h" +#include "video/VideoDbUrl.h" using namespace XFILE::VIDEODATABASEDIRECTORY; using namespace std; @@ -64,6 +65,10 @@ CStdString CDirectoryNodeOverview::GetLocalizedName() const bool CDirectoryNodeOverview::GetContent(CFileItemList& items) const { + CVideoDbUrl videoUrl; + if (!videoUrl.FromString(BuildPath())) + return false; + CVideoDatabase database; database.Open(); bool hasMovies = database.HasContent(VIDEODB_CONTENT_MOVIES); @@ -100,10 +105,14 @@ bool CDirectoryNodeOverview::GetContent(CFileItemList& items) const if (hasMusicVideos) vec.push_back(make_pair("6", 20390)); // Recently Added Music Videos } - CStdString path = BuildPath(); + for (unsigned int i = 0; i < vec.size(); ++i) { - CFileItemPtr pItem(new CFileItem(path + vec[i].first + "/", true)); + CVideoDbUrl itemUrl = videoUrl; + CStdString strDir; strDir.Format("%s/", vec[i].first); + itemUrl.AppendPath(strDir); + + CFileItemPtr pItem(new CFileItem(itemUrl.ToString())); pItem->SetLabel(g_localizeStrings.Get(vec[i].second)); pItem->SetLabelPreformated(true); pItem->SetCanQueue(false); diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedEpisodes.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedEpisodes.cpp index 478072005f..cbadaa2cd9 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedEpisodes.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedEpisodes.cpp @@ -41,9 +41,8 @@ bool CDirectoryNodeRecentlyAddedEpisodes::GetContent(CFileItemList& items) const CVideoDatabase videodatabase; if (!videodatabase.Open()) return false; - - CStdString strBaseDir=BuildPath(); - bool bSuccess=videodatabase.GetRecentlyAddedEpisodesNav(strBaseDir, items); + + bool bSuccess=videodatabase.GetRecentlyAddedEpisodesNav(BuildPath(), items); videodatabase.Close(); diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMovies.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMovies.cpp index d61cc8455b..a0704015ac 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMovies.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMovies.cpp @@ -41,9 +41,8 @@ bool CDirectoryNodeRecentlyAddedMovies::GetContent(CFileItemList& items) const CVideoDatabase videodatabase; if (!videodatabase.Open()) return false; - - CStdString strBaseDir=BuildPath(); - bool bSuccess=videodatabase.GetRecentlyAddedMoviesNav(strBaseDir, items); + + bool bSuccess=videodatabase.GetRecentlyAddedMoviesNav(BuildPath(), items); videodatabase.Close(); diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMusicVideos.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMusicVideos.cpp index 18a9445d31..5c68d69371 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMusicVideos.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeRecentlyAddedMusicVideos.cpp @@ -41,9 +41,8 @@ bool CDirectoryNodeRecentlyAddedMusicVideos::GetContent(CFileItemList& items) co CVideoDatabase videodatabase; if (!videodatabase.Open()) return false; - - CStdString strBaseDir=BuildPath(); - bool bSuccess=videodatabase.GetRecentlyAddedMusicVideosNav(strBaseDir, items); + + bool bSuccess=videodatabase.GetRecentlyAddedMusicVideosNav(BuildPath(), items); videodatabase.Close(); diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeSeasons.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeSeasons.cpp index 0a6f2af956..7feda19ddf 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeSeasons.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeSeasons.cpp @@ -22,6 +22,7 @@ #include "DirectoryNodeSeasons.h" #include "QueryParams.h" #include "video/VideoDatabase.h" +#include "video/VideoDbUrl.h" #include "settings/GUISettings.h" #include "settings/Settings.h" #include "FileItem.h" @@ -92,8 +93,14 @@ bool CDirectoryNodeSeasons::GetContent(CFileItemList& items) const if (bFlatten) { // flatten if one season or flatten always items.Clear(); - bSuccess=videodatabase.GetEpisodesNav(BuildPath()+"-2/",items,params.GetGenreId(),params.GetYear(),params.GetActorId(),params.GetDirectorId(),params.GetTvShowId()); - items.SetPath(BuildPath()+"-2/"); + + CVideoDbUrl videoUrl; + if (!videoUrl.FromString(BuildPath())) + return false; + + videoUrl.AppendPath("-2/"); + bSuccess=videodatabase.GetEpisodesNav(videoUrl.ToString(), items, params.GetGenreId(), params.GetYear(), params.GetActorId(), params.GetDirectorId(), params.GetTvShowId()); + items.SetPath(videoUrl.ToString()); } videodatabase.Close(); diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp index 7989c81049..222f8e5e07 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp @@ -40,8 +40,7 @@ bool CDirectoryNodeTitleMovies::GetContent(CFileItemList& items) const CQueryParams params; CollectQueryParams(params); - CStdString strBaseDir=BuildPath(); - bool bSuccess=videodatabase.GetMoviesNav(strBaseDir, items, params.GetGenreId(), params.GetYear(), params.GetActorId(), params.GetDirectorId(), params.GetStudioId(), params.GetCountryId(), params.GetSetId(), params.GetTagId()); + bool bSuccess=videodatabase.GetMoviesNav(BuildPath(), items, params.GetGenreId(), params.GetYear(), params.GetActorId(), params.GetDirectorId(), params.GetStudioId(), params.GetCountryId(), params.GetSetId(), params.GetTagId()); videodatabase.Close(); diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMusicVideos.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMusicVideos.cpp index 67b1b86be6..093a4532ef 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMusicVideos.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMusicVideos.cpp @@ -40,8 +40,7 @@ bool CDirectoryNodeTitleMusicVideos::GetContent(CFileItemList& items) const CQueryParams params; CollectQueryParams(params); - CStdString strBaseDir=BuildPath(); - bool bSuccess=videodatabase.GetMusicVideosNav(strBaseDir, items, params.GetGenreId(), params.GetYear(), params.GetActorId(), params.GetDirectorId(),params.GetStudioId(),params.GetAlbumId()); + bool bSuccess=videodatabase.GetMusicVideosNav(BuildPath(), items, params.GetGenreId(), params.GetYear(), params.GetActorId(), params.GetDirectorId(),params.GetStudioId(),params.GetAlbumId()); videodatabase.Close(); diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTvShowsOverview.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTvShowsOverview.cpp index 47060303c3..75db3cf3d7 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTvShowsOverview.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTvShowsOverview.cpp @@ -22,6 +22,7 @@ #include "DirectoryNodeTvShowsOverview.h" #include "FileItem.h" #include "guilib/LocalizeStrings.h" +#include "video/VideoDbUrl.h" using namespace XFILE::VIDEODATABASEDIRECTORY; @@ -61,12 +62,19 @@ CStdString CDirectoryNodeTvShowsOverview::GetLocalizedName() const bool CDirectoryNodeTvShowsOverview::GetContent(CFileItemList& items) const { + CVideoDbUrl videoUrl; + if (!videoUrl.FromString(BuildPath())) + return false; + for (unsigned int i = 0; i < sizeof(TvShowChildren) / sizeof(Node); ++i) { CFileItemPtr pItem(new CFileItem(g_localizeStrings.Get(TvShowChildren[i].label))); - CStdString strDir; - strDir.Format("%ld/", TvShowChildren[i].id); - pItem->SetPath(BuildPath() + strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString strDir; strDir.Format("%ld/", TvShowChildren[i].id); + itemUrl.AppendPath(strDir); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder = true; pItem->SetCanQueue(false); items.Add(pItem); diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeYear.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeYear.cpp index 32787ece40..ba1ff2933a 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeYear.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeYear.cpp @@ -57,8 +57,7 @@ bool CDirectoryNodeYear::GetContent(CFileItemList& items) const CQueryParams params; CollectQueryParams(params); - CStdString strBaseDir=BuildPath(); - bool bSuccess=videodatabase.GetYearsNav(strBaseDir, items, params.GetContentType()); + bool bSuccess=videodatabase.GetYearsNav(BuildPath(), items, params.GetContentType()); videodatabase.Close(); diff --git a/xbmc/filesystem/udf25.cpp b/xbmc/filesystem/udf25.cpp index 9dc605fe18..f9a84d9070 100644 --- a/xbmc/filesystem/udf25.cpp +++ b/xbmc/filesystem/udf25.cpp @@ -391,7 +391,7 @@ static int file_seek(CFile* fp, int blocks) pos = fp->Seek((off64_t)blocks * (off64_t)DVD_VIDEO_LB_LEN, SEEK_SET); if(pos < 0) { - return pos; + return (int) pos; } /* assert pos % DVD_VIDEO_LB_LEN == 0 */ return (int) (pos / DVD_VIDEO_LB_LEN); @@ -422,7 +422,7 @@ static int file_read(CFile* fp, void *buffer, int blocks, int flags) /* Nothing more to read. Return all of the whole blocks, if any. * Adjust the file position back to the previous block boundary. */ size_t bytes = (size_t)blocks * DVD_VIDEO_LB_LEN - len; - off_t over_read = -(bytes % DVD_VIDEO_LB_LEN); + off_t over_read = -(off_t)(bytes % DVD_VIDEO_LB_LEN); /*off_t pos =*/ fp->Seek(over_read, SEEK_CUR); /* should have pos % 2048 == 0 */ return (int) (bytes / DVD_VIDEO_LB_LEN); @@ -1236,7 +1236,7 @@ long udf25::ReadFile(HANDLE hFile, unsigned char *pBuffer, long lSize) if( bdfile == NULL || pBuffer == NULL ) return -1; - seek_sector = bdfile->seek_pos / DVD_VIDEO_LB_LEN; + seek_sector =(unsigned int) (bdfile->seek_pos / DVD_VIDEO_LB_LEN); seek_byte = bdfile->seek_pos % DVD_VIDEO_LB_LEN; numsec = ( ( seek_byte + lSize ) / DVD_VIDEO_LB_LEN ) + @@ -1363,7 +1363,7 @@ udf_dir_t *udf25::OpenDir( const char *subdir ) result->dir_location = UDFFileBlockPos(bd_file->file, 0); result->dir_current = UDFFileBlockPos(bd_file->file, 0); - result->dir_length = bd_file->filesize; + result->dir_length = (uint32_t) bd_file->filesize; UDFFreeFile(bd_file->file); free(bd_file); diff --git a/xbmc/guilib/GUIAction.cpp b/xbmc/guilib/GUIAction.cpp index 23beb9f05f..a42447f669 100644 --- a/xbmc/guilib/GUIAction.cpp +++ b/xbmc/guilib/GUIAction.cpp @@ -38,7 +38,7 @@ CGUIAction::CGUIAction(int controlID) SetNavigation(controlID); } -bool CGUIAction::Execute(int controlID, int parentID, int direction /*= 0*/) const +bool CGUIAction::ExecuteActions(int controlID, int parentID) const { if (m_actions.size() == 0) return false; bool retval = false; @@ -47,21 +47,7 @@ bool CGUIAction::Execute(int controlID, int parentID, int direction /*= 0*/) con { if (it->condition.IsEmpty() || g_infoManager.EvaluateBool(it->condition)) { - if (StringUtils::IsInteger(it->action)) - { - CGUIMessage msg(GUI_MSG_MOVE, parentID, controlID, direction); - if (parentID) - { - CGUIWindow *pWindow = g_windowManager.GetWindow(parentID); - if (pWindow) - { - retval |= pWindow->OnMessage(msg); - continue; - } - } - retval |= g_windowManager.SendMessage(msg); - } - else + if (!StringUtils::IsInteger(it->action)) { CGUIMessage msg(GUI_MSG_EXECUTE, controlID, parentID); msg.SetStringParam(it->action); diff --git a/xbmc/guilib/GUIAction.h b/xbmc/guilib/GUIAction.h index 0a7a6d756a..3a54f42dc2 100644 --- a/xbmc/guilib/GUIAction.h +++ b/xbmc/guilib/GUIAction.h @@ -35,9 +35,9 @@ public: CGUIAction(int controlID); /** - * Execute actions, if action is paired with condition - evaluate condition first + * Execute actions (no navigation paths), if action is paired with condition - evaluate condition first */ - bool Execute(int controlID, int parentID, int direction = 0) const; + bool ExecuteActions(int controlID, int parentID) const; /** * Check if there is any action that meet its condition */ diff --git a/xbmc/guilib/GUIAudioManager.cpp b/xbmc/guilib/GUIAudioManager.cpp index b18698357e..c8cc5d5aec 100644 --- a/xbmc/guilib/GUIAudioManager.cpp +++ b/xbmc/guilib/GUIAudioManager.cpp @@ -31,7 +31,6 @@ #include "cores/AudioEngine/AEFactory.h" using namespace std; -using namespace XFILE; CGUIAudioManager g_audioManager; @@ -84,7 +83,7 @@ void CGUIAudioManager::PlayActionSound(const CAction& action) return; if (it->second) - it->second->Play();; + it->second->Play(); } // \brief Play a sound associated with a window and its event diff --git a/xbmc/guilib/GUIBaseContainer.cpp b/xbmc/guilib/GUIBaseContainer.cpp index 152a43361b..421fb0e819 100644 --- a/xbmc/guilib/GUIBaseContainer.cpp +++ b/xbmc/guilib/GUIBaseContainer.cpp @@ -51,7 +51,6 @@ CGUIBaseContainer::CGUIBaseContainer(int parentID, int controlID, float posX, fl m_pageControl = 0; m_orientation = orientation; m_analogScrollCount = 0; - m_lastItem = NULL; m_staticContent = false; m_staticUpdateTime = 0; m_staticDefaultItem = -1; @@ -60,6 +59,7 @@ CGUIBaseContainer::CGUIBaseContainer(int parentID, int controlID, float posX, fl m_layout = NULL; m_focusedLayout = NULL; m_cacheItems = preloadItems; + m_scrollItemsPerFrame = 0.0f; } CGUIBaseContainer::~CGUIBaseContainer(void) @@ -119,9 +119,9 @@ void CGUIBaseContainer::Process(unsigned int currentTime, CDirtyRegionList &dirt CGUIListItemPtr item = m_items[itemNo]; // render our item if (m_orientation == VERTICAL) - ProcessItem(origin.x, pos, item.get(), focused, currentTime, dirtyregions); + ProcessItem(origin.x, pos, item, focused, currentTime, dirtyregions); else - ProcessItem(pos, origin.y, item.get(), focused, currentTime, dirtyregions); + ProcessItem(pos, origin.y, item, focused, currentTime, dirtyregions); } // increment our position pos += focused ? m_focusedLayout->Size(m_orientation) : m_layout->Size(m_orientation); @@ -133,7 +133,7 @@ void CGUIBaseContainer::Process(unsigned int currentTime, CDirtyRegionList &dirt CGUIControl::Process(currentTime, dirtyregions); } -void CGUIBaseContainer::ProcessItem(float posX, float posY, CGUIListItem *item, bool focused, unsigned int currentTime, CDirtyRegionList &dirtyregions) +void CGUIBaseContainer::ProcessItem(float posX, float posY, CGUIListItemPtr& item, bool focused, unsigned int currentTime, CDirtyRegionList &dirtyregions) { if (!m_focusedLayout || !m_layout) return; @@ -163,7 +163,7 @@ void CGUIBaseContainer::ProcessItem(float posX, float posY, CGUIListItem *item, subItem = m_lastItem->GetFocusedLayout()->GetFocusedItem(); item->GetFocusedLayout()->SetFocusedItem(subItem ? subItem : 1); } - item->GetFocusedLayout()->Process(item, m_parentID, currentTime, dirtyregions); + item->GetFocusedLayout()->Process(item.get(), m_parentID, currentTime, dirtyregions); } m_lastItem = item; } @@ -177,9 +177,9 @@ void CGUIBaseContainer::ProcessItem(float posX, float posY, CGUIListItem *item, item->SetLayout(layout); } if (item->GetFocusedLayout()) - item->GetFocusedLayout()->Process(item, m_parentID, currentTime, dirtyregions); + item->GetFocusedLayout()->Process(item.get(), m_parentID, currentTime, dirtyregions); if (item->GetLayout()) - item->GetLayout()->Process(item, m_parentID, currentTime, dirtyregions); + item->GetLayout()->Process(item.get(), m_parentID, currentTime, dirtyregions); } g_graphicsContext.RestoreOrigin(); @@ -295,24 +295,38 @@ bool CGUIBaseContainer::OnAction(const CAction &action) case ACTION_NAV_BACK: { if (!HasFocus()) return false; + if (action.GetHoldTime() > HOLD_TIME_START && ((m_orientation == VERTICAL && (action.GetID() == ACTION_MOVE_UP || action.GetID() == ACTION_MOVE_DOWN)) || (m_orientation == HORIZONTAL && (action.GetID() == ACTION_MOVE_LEFT || action.GetID() == ACTION_MOVE_RIGHT)))) { // action is held down - repeat a number of times float speed = std::min(1.0f, (float)(action.GetHoldTime() - HOLD_TIME_START) / (HOLD_TIME_END - HOLD_TIME_START)); - unsigned int itemsPerFrame = 1; - if (m_lastHoldTime) // number of rows/10 items/second max speed - itemsPerFrame = std::max((unsigned int)1, (unsigned int)(speed * 0.0001f * GetRows() * (CTimeUtils::GetFrameTime() - m_lastHoldTime))); + unsigned int frameDuration = std::min(CTimeUtils::GetFrameTime() - m_lastHoldTime, 50u); // max 20fps + + // scrollrate is minimum 10 items/sec and timed to take around 10 seconds + // with ramp up (num_rows/7 items per second max speed) to traverse a long list + m_scrollItemsPerFrame += std::max(0.01f*(float)frameDuration, (float)(speed * 0.00015f * GetRows() * frameDuration)); m_lastHoldTime = CTimeUtils::GetFrameTime(); - if (action.GetID() == ACTION_MOVE_LEFT || action.GetID() == ACTION_MOVE_UP) - while (itemsPerFrame--) MoveUp(false); - else - while (itemsPerFrame--) MoveDown(false); + + if(m_scrollItemsPerFrame < 1.0f)//not enough hold time accumulated for one step + return false; + + while (m_scrollItemsPerFrame >= 1) + { + if (action.GetID() == ACTION_MOVE_LEFT || action.GetID() == ACTION_MOVE_UP) + MoveUp(false); + else + MoveDown(false); + m_scrollItemsPerFrame--; + } return true; } else { - m_lastHoldTime = 0; + //if HOLD_TIME_START is reached we need + //a sane initial value for calculating m_scrollItemsPerPage + m_lastHoldTime = CTimeUtils::GetFrameTime(); + m_scrollItemsPerFrame = 0.0f; return CGUIControl::OnAction(action); } } @@ -701,7 +715,7 @@ bool CGUIBaseContainer::OnClick(int actionID) if (selected >= 0 && selected < (int)m_items.size()) { CGUIStaticItemPtr item = boost::static_pointer_cast<CGUIStaticItem>(m_items[selected]); - item->GetClickActions().Execute(GetID(), GetParentID()); + item->GetClickActions().ExecuteActions(GetID(), GetParentID()); } return true; } @@ -735,7 +749,7 @@ void CGUIBaseContainer::SetFocus(bool bOnOff) if (bOnOff != HasFocus()) { SetInvalid(); - m_lastItem = NULL; + m_lastItem.reset(); } CGUIControl::SetFocus(bOnOff); } @@ -827,39 +841,51 @@ void CGUIBaseContainer::UpdateVisibility(const CGUIListItem *item) SelectItem(itemIndex); } + UpdateStaticItems(); +} + +void CGUIBaseContainer::UpdateStaticItems(bool refreshItems) +{ if (m_staticContent) { // update our item list with our new content, but only add those items that should // be visible. Save the previous item and keep it if we are adding that one. - CGUIListItem *lastItem = m_lastItem; + std::vector<CGUIListItemPtr> items; + int reselect = -1; int selected = GetSelectedItem(); CGUIListItem* selectedItem = (selected >= 0 && (unsigned int)selected < m_items.size()) ? m_items[selected].get() : NULL; - Reset(); - bool updateItems = false; + bool updateItemsProperties = false; if (!m_staticUpdateTime) m_staticUpdateTime = CTimeUtils::GetFrameTime(); if (CTimeUtils::GetFrameTime() - m_staticUpdateTime > 1000) { m_staticUpdateTime = CTimeUtils::GetFrameTime(); - updateItems = true; + updateItemsProperties = true; } for (unsigned int i = 0; i < m_staticItems.size(); ++i) { CGUIStaticItemPtr staticItem = boost::static_pointer_cast<CGUIStaticItem>(m_staticItems[i]); if (staticItem->UpdateVisibility(GetParentID())) - MarkDirtyRegion(); + refreshItems = true; if (staticItem->IsVisible()) { - m_items.push_back(staticItem); - if (staticItem.get() == lastItem) - m_lastItem = lastItem; + items.push_back(staticItem); // if item is selected and it changed position, re-select it - if (staticItem.get() == selectedItem && selected != (int)m_items.size() - 1) - SelectItem(m_items.size() - 1); + if (staticItem.get() == selectedItem && selected != (int)items.size() - 1) + reselect = items.size() - 1; } // update any properties - if (updateItems) + if (updateItemsProperties) staticItem->UpdateProperties(GetParentID()); } + if (refreshItems) + { + Reset(); + m_items = items; + SetPageControlRange(); + if (reselect >= 0 && reselect < (int)m_items.size()) + SelectItem(reselect); + MarkDirtyRegion(); + } UpdateScrollByLetter(); } } @@ -975,7 +1001,6 @@ void CGUIBaseContainer::Reset() { m_wasReset = true; m_items.clear(); - m_lastItem = NULL; } void CGUIBaseContainer::LoadLayout(TiXmlElement *layout) @@ -1024,7 +1049,7 @@ void CGUIBaseContainer::SetStaticContent(const vector<CGUIListItemPtr> &items) m_staticUpdateTime = 0; m_staticItems.clear(); m_staticItems.assign(items.begin(), items.end()); - UpdateVisibility(); + UpdateStaticItems(true); } void CGUIBaseContainer::SetRenderOffset(const CPoint &offset) diff --git a/xbmc/guilib/GUIBaseContainer.h b/xbmc/guilib/GUIBaseContainer.h index df62f94b1d..ef6353ab43 100644 --- a/xbmc/guilib/GUIBaseContainer.h +++ b/xbmc/guilib/GUIBaseContainer.h @@ -101,7 +101,7 @@ protected: virtual EVENT_RESULT OnMouseEvent(const CPoint &point, const CMouseEvent &event); bool OnClick(int actionID); - virtual void ProcessItem(float posX, float posY, CGUIListItem *item, bool focused, unsigned int currentTime, CDirtyRegionList &dirtyregions); + virtual void ProcessItem(float posX, float posY, CGUIListItemPtr& item, bool focused, unsigned int currentTime, CDirtyRegionList &dirtyregions); virtual void Render(); virtual void RenderItem(float posX, float posY, CGUIListItem *item, bool focused); @@ -124,6 +124,7 @@ protected: virtual int GetCurrentPage() const; bool InsideLayout(const CGUIListItemLayout *layout, const CPoint &point) const; virtual void OnFocus(); + void UpdateStaticItems(bool refreshItems = false); int ScrollCorrectionRange() const; inline float Size() const; @@ -142,7 +143,7 @@ protected: std::vector< CGUIListItemPtr > m_items; typedef std::vector<CGUIListItemPtr> ::iterator iItems; - CGUIListItem *m_lastItem; + CGUIListItemPtr m_lastItem; int m_pageControl; @@ -207,6 +208,7 @@ private: // letter match searching CStopWatch m_matchTimer; CStdString m_match; + float m_scrollItemsPerFrame; static const int letter_match_timeout = 1000; }; diff --git a/xbmc/guilib/GUIButtonControl.cpp b/xbmc/guilib/GUIButtonControl.cpp index 04bd373c7f..f991ced1bf 100644 --- a/xbmc/guilib/GUIButtonControl.cpp +++ b/xbmc/guilib/GUIButtonControl.cpp @@ -115,6 +115,9 @@ CGUILabel::COLOR CGUIButtonControl::GetTextColor() const void CGUIButtonControl::ProcessText(unsigned int currentTime) { + CRect labelRenderRect = m_label.GetRenderRect(); + CRect label2RenderRect = m_label2.GetRenderRect(); + bool changed = m_label.SetMaxRect(m_posX, m_posY, m_width, m_height); changed |= m_label.SetText(m_info.GetLabel(m_parentID)); changed |= m_label.SetScrolling(HasFocus()); @@ -128,7 +131,11 @@ void CGUIButtonControl::ProcessText(unsigned int currentTime) changed |= m_label2.SetAlign(XBFONT_RIGHT | (m_label.GetLabelInfo().align & XBFONT_CENTER_Y) | XBFONT_TRUNCATED); changed |= m_label2.SetScrolling(HasFocus()); - changed |= CGUILabel::CheckAndCorrectOverlap(m_label, m_label2); + // If overlapping was corrected - compare render rects to determine + // if they changed since last frame. + if (CGUILabel::CheckAndCorrectOverlap(m_label, m_label2)) + changed |= (m_label.GetRenderRect() != labelRenderRect || + m_label2.GetRenderRect() != label2RenderRect); changed |= m_label2.SetColor(GetTextColor()); } @@ -311,17 +318,17 @@ void CGUIButtonControl::OnClick() CGUIMessage msg(GUI_MSG_CLICKED, controlID, parentID, 0); SendWindowMessage(msg); - clickActions.Execute(controlID, parentID); + clickActions.ExecuteActions(controlID, parentID); } void CGUIButtonControl::OnFocus() { - m_focusActions.Execute(GetID(), GetParentID()); + m_focusActions.ExecuteActions(GetID(), GetParentID()); } void CGUIButtonControl::OnUnFocus() { - m_unfocusActions.Execute(GetID(), GetParentID()); + m_unfocusActions.ExecuteActions(GetID(), GetParentID()); } void CGUIButtonControl::SetSelected(bool bSelected) diff --git a/xbmc/guilib/GUIControl.cpp b/xbmc/guilib/GUIControl.cpp index 7eed981092..9bad35c9d1 100644 --- a/xbmc/guilib/GUIControl.cpp +++ b/xbmc/guilib/GUIControl.cpp @@ -129,7 +129,7 @@ void CGUIControl::DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyreg { CRect dirtyRegion = m_renderRegion; - bool changed = m_bInvalidated; + bool changed = m_bInvalidated && IsVisible(); changed |= Animate(currentTime); @@ -226,46 +226,50 @@ bool CGUIControl::OnAction(const CAction &action) return false; } +bool CGUIControl::Navigate(int direction) +{ + if (HasFocus()) + { + CGUIMessage msg(GUI_MSG_MOVE, GetParentID(), GetID(), direction); + return SendWindowMessage(msg); + } + return false; +} + // Movement controls (derived classes can override) void CGUIControl::OnUp() { - if (HasFocus()) - m_actionUp.Execute(GetID(), GetParentID(), ACTION_MOVE_UP); + Navigate(ACTION_MOVE_UP); } void CGUIControl::OnDown() { - if (HasFocus()) - m_actionDown.Execute(GetID(), GetParentID(), ACTION_MOVE_DOWN); + Navigate(ACTION_MOVE_DOWN); } void CGUIControl::OnLeft() { - if (HasFocus()) - m_actionLeft.Execute(GetID(), GetParentID(), ACTION_MOVE_LEFT); + Navigate(ACTION_MOVE_LEFT); } void CGUIControl::OnRight() { - if (HasFocus()) - m_actionRight.Execute(GetID(), GetParentID(), ACTION_MOVE_RIGHT); + Navigate(ACTION_MOVE_RIGHT); } bool CGUIControl::OnBack() { - return HasFocus() ? m_actionBack.Execute(GetID(), GetParentID(), ACTION_NAV_BACK) : false; + return Navigate(ACTION_NAV_BACK); } void CGUIControl::OnNextControl() { - if (HasFocus()) - m_actionNext.Execute(GetID(), GetParentID(), ACTION_NEXT_CONTROL); + Navigate(ACTION_NEXT_CONTROL); } void CGUIControl::OnPrevControl() { - if (HasFocus()) - m_actionPrev.Execute(GetID(), GetParentID(), ACTION_PREV_CONTROL); + Navigate(ACTION_PREV_CONTROL); } bool CGUIControl::SendWindowMessage(CGUIMessage &message) @@ -892,22 +896,27 @@ bool CGUIControl::IsAnimating(ANIMATION_TYPE animType) return false; } -int CGUIControl::GetNextControl(int direction) const +bool CGUIControl::GetNavigationAction(int direction, CGUIAction& action) const { switch (direction) { case ACTION_MOVE_UP: - return m_actionUp.GetNavigation(); + action = m_actionUp; + return true; case ACTION_MOVE_DOWN: - return m_actionDown.GetNavigation(); + action = m_actionDown; + return true; case ACTION_MOVE_LEFT: - return m_actionLeft.GetNavigation(); + action = m_actionLeft; + return true; case ACTION_MOVE_RIGHT: - return m_actionRight.GetNavigation(); + action = m_actionRight; + return true; case ACTION_NAV_BACK: - return m_actionBack.GetNavigation(); + action = m_actionBack; + return true; default: - return -1; + return false; } } diff --git a/xbmc/guilib/GUIControl.h b/xbmc/guilib/GUIControl.h index 72f4189ec1..b283bea3c1 100644 --- a/xbmc/guilib/GUIControl.h +++ b/xbmc/guilib/GUIControl.h @@ -199,7 +199,10 @@ public: int GetControlIdLeft() const { return m_actionLeft.GetNavigation(); }; int GetControlIdRight() const { return m_actionRight.GetNavigation(); }; int GetControlIdBack() const { return m_actionBack.GetNavigation(); }; - virtual int GetNextControl(int direction) const; + bool GetNavigationAction(int direction, CGUIAction& action) const; + /*! \brief Start navigating in given direction. + */ + bool Navigate(int direction); virtual void SetFocus(bool focus); virtual void SetWidth(float width); virtual void SetHeight(float height); diff --git a/xbmc/guilib/GUIControlGroup.cpp b/xbmc/guilib/GUIControlGroup.cpp index 5a3b06e2aa..94ea837df8 100644 --- a/xbmc/guilib/GUIControlGroup.cpp +++ b/xbmc/guilib/GUIControlGroup.cpp @@ -464,18 +464,33 @@ int CGUIControlGroup::GetFocusedControlID() const CGUIControl *CGUIControlGroup::GetFocusedControl() const { + // try lookup first + if (m_focusedControl) + { + // we may have multiple controls with same id - we pick first that has focus + pair<LookupMap::const_iterator, LookupMap::const_iterator> range = m_lookup.equal_range(m_focusedControl); + for (LookupMap::const_iterator i = range.first; i != range.second; ++i) + { + if (i->second->HasFocus()) + return i->second; + } + } + + // if lookup didn't find focused control, iterate m_children to find it for (ciControls it = m_children.begin(); it != m_children.end(); ++it) { const CGUIControl* control = *it; - if (control->HasFocus()) + // Avoid calling HasFocus() on control group as it will (possibly) recursively + // traverse entire group tree just to check if there is focused control. + // We are recursively traversing it here so no point in doing it twice. + if (control->IsGroup()) { - if (control->IsGroup()) - { - CGUIControlGroup *group = (CGUIControlGroup *)control; - return group->GetFocusedControl(); - } - return (CGUIControl *)control; + CGUIControl* focusedControl = ((CGUIControlGroup *)control)->GetFocusedControl(); + if (focusedControl) + return (CGUIControl *)focusedControl; } + else if (control->HasFocus()) + return (CGUIControl *)control; } return NULL; } diff --git a/xbmc/guilib/GUIDialog.cpp b/xbmc/guilib/GUIDialog.cpp index 74c6ad0a48..92bdd9986a 100644 --- a/xbmc/guilib/GUIDialog.cpp +++ b/xbmc/guilib/GUIDialog.cpp @@ -27,6 +27,7 @@ #include "threads/SingleLock.h" #include "utils/TimeUtils.h" #include "Application.h" +#include "ApplicationMessenger.h" CGUIDialog::CGUIDialog(int id, const CStdString &xmlFile) : CGUIWindow(id, xmlFile) @@ -208,7 +209,7 @@ void CGUIDialog::DoModal(int iWindowID /*= WINDOW_INVALID */, const CStdString & { // make sure graphics lock is not held CSingleExit leaveIt(g_graphicsContext); - g_application.getApplicationMessenger().DoModal(this, iWindowID, param); + CApplicationMessenger::Get().DoModal(this, iWindowID, param); } else DoModal_Internal(iWindowID, param); @@ -220,7 +221,7 @@ void CGUIDialog::Show() { // make sure graphics lock is not held CSingleExit leaveIt(g_graphicsContext); - g_application.getApplicationMessenger().Show(this); + CApplicationMessenger::Get().Show(this); } else Show_Internal(); diff --git a/xbmc/guilib/GUIEditControl.cpp b/xbmc/guilib/GUIEditControl.cpp index 2fa67b926d..054e47221c 100644 --- a/xbmc/guilib/GUIEditControl.cpp +++ b/xbmc/guilib/GUIEditControl.cpp @@ -22,7 +22,7 @@ #include "GUIEditControl.h" #include "GUIWindowManager.h" #include "utils/CharsetConverter.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "GUIKeyboardFactory.h" #include "dialogs/GUIDialogNumeric.h" #include "input/XBMC_vkeys.h" #include "LocalizeStrings.h" @@ -287,17 +287,17 @@ void CGUIEditControl::OnClick() textChanged = CGUIDialogNumeric::ShowAndGetIPAddress(utf8, heading); break; case INPUT_TYPE_SEARCH: - textChanged = CGUIDialogKeyboard::ShowAndGetFilter(utf8, true); + textChanged = CGUIKeyboardFactory::ShowAndGetFilter(utf8, true); break; case INPUT_TYPE_FILTER: - textChanged = CGUIDialogKeyboard::ShowAndGetFilter(utf8, false); + textChanged = CGUIKeyboardFactory::ShowAndGetFilter(utf8, false); break; case INPUT_TYPE_PASSWORD_MD5: utf8 = ""; // TODO: Ideally we'd send this to the keyboard and tell the keyboard we have this type of input // fallthrough case INPUT_TYPE_TEXT: default: - textChanged = CGUIDialogKeyboard::ShowAndGetInput(utf8, heading, true, m_inputType == INPUT_TYPE_PASSWORD || m_inputType == INPUT_TYPE_PASSWORD_MD5); + textChanged = CGUIKeyboardFactory::ShowAndGetInput(utf8, heading, true, m_inputType == INPUT_TYPE_PASSWORD || m_inputType == INPUT_TYPE_PASSWORD_MD5); break; } if (textChanged) @@ -317,7 +317,7 @@ void CGUIEditControl::UpdateText(bool sendUpdate) { SEND_CLICK_MESSAGE(GetID(), GetParentID(), 0); - m_textChangeActions.Execute(GetID(), GetParentID()); + m_textChangeActions.ExecuteActions(GetID(), GetParentID()); } SetInvalid(); } diff --git a/xbmc/guilib/GUIFontManager.cpp b/xbmc/guilib/GUIFontManager.cpp index 02553d98d9..55eb303447 100644 --- a/xbmc/guilib/GUIFontManager.cpp +++ b/xbmc/guilib/GUIFontManager.cpp @@ -33,6 +33,7 @@ #include "utils/URIUtils.h" #include "utils/StringUtils.h" #include "windowing/WindowingFactory.h" +#include "URL.h" using namespace std; diff --git a/xbmc/guilib/GUIFontTTFDX.cpp b/xbmc/guilib/GUIFontTTFDX.cpp index fefd3eb79d..a6f10d017a 100644 --- a/xbmc/guilib/GUIFontTTFDX.cpp +++ b/xbmc/guilib/GUIFontTTFDX.cpp @@ -181,7 +181,7 @@ CBaseTexture* CGUIFontTTFDX::ReallocTexture(unsigned int& newHeight) // There might be data to copy from the previous texture if ((newSpeedupTexture && m_speedupTexture) || (newTexture && m_texture)) { - if (m_speedupTexture) + if (m_speedupTexture && newSpeedupTexture) { m_speedupTexture->GetSurfaceLevel(0, &pSource); newSpeedupTexture->GetSurfaceLevel(0, &pTarget); diff --git a/xbmc/guilib/GUIInfoTypes.cpp b/xbmc/guilib/GUIInfoTypes.cpp index 724b02b6b9..c3ae973e68 100644 --- a/xbmc/guilib/GUIInfoTypes.cpp +++ b/xbmc/guilib/GUIInfoTypes.cpp @@ -56,7 +56,7 @@ void CGUIInfoBool::Parse(const CStdString &expression, int context) } } -void CGUIInfoBool::Update(const CGUIListItem *item) +void CGUIInfoBool::Update(const CGUIListItem *item /*= NULL*/) { if (m_info) m_value = g_infoManager.GetBoolValue(m_info, item); @@ -128,18 +128,18 @@ CGUIInfoLabel::CGUIInfoLabel() { } -CGUIInfoLabel::CGUIInfoLabel(const CStdString &label, const CStdString &fallback, int context) +CGUIInfoLabel::CGUIInfoLabel(const CStdString &label, const CStdString &fallback /*= ""*/, int context /*= 0*/) { SetLabel(label, fallback, context); } -void CGUIInfoLabel::SetLabel(const CStdString &label, const CStdString &fallback, int context) +void CGUIInfoLabel::SetLabel(const CStdString &label, const CStdString &fallback, int context /*= 0*/) { m_fallback = fallback; Parse(label, context); } -CStdString CGUIInfoLabel::GetLabel(int contextWindow, bool preferImage, CStdString *fallback) const +CStdString CGUIInfoLabel::GetLabel(int contextWindow, bool preferImage, CStdString *fallback /*= NULL*/) const { CStdString label; for (unsigned int i = 0; i < m_info.size(); i++) @@ -165,7 +165,7 @@ CStdString CGUIInfoLabel::GetLabel(int contextWindow, bool preferImage, CStdStri return label; } -CStdString CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool preferImages, CStdString *fallback) const +CStdString CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool preferImages, CStdString *fallback /*= NULL*/) const { if (!item->IsFileItem()) return ""; CStdString label; @@ -341,7 +341,7 @@ void CGUIInfoLabel::Parse(const CStdString &label, int context) m_info.push_back(CInfoPortion(0, work, "")); } -CGUIInfoLabel::CInfoPortion::CInfoPortion(int info, const CStdString &prefix, const CStdString &postfix, bool escaped) +CGUIInfoLabel::CInfoPortion::CInfoPortion(int info, const CStdString &prefix, const CStdString &postfix, bool escaped /*= false */) { m_info = info; m_prefix = prefix; @@ -365,7 +365,7 @@ CStdString CGUIInfoLabel::CInfoPortion::GetLabel(const CStdString &info) const return label; } -CStdString CGUIInfoLabel::GetLabel(const CStdString &label, int contextWindow, bool preferImage) +CStdString CGUIInfoLabel::GetLabel(const CStdString &label, int contextWindow /*= 0*/, bool preferImage /*= false */) { // translate the label CGUIInfoLabel info(label, "", contextWindow); return info.GetLabel(contextWindow, preferImage); diff --git a/xbmc/guilib/GUIInfoTypes.h b/xbmc/guilib/GUIInfoTypes.h index 3c6de98a20..97278f2c4f 100644 --- a/xbmc/guilib/GUIInfoTypes.h +++ b/xbmc/guilib/GUIInfoTypes.h @@ -75,8 +75,25 @@ public: CGUIInfoLabel(const CStdString &label, const CStdString &fallback = "", int context = 0); void SetLabel(const CStdString &label, const CStdString &fallback, int context = 0); + + /*! + \brief Gets a label (or image) for a given window context from the info manager. + \param contextWindow the context in which to evaluate the expression. + \param preferImage caller is specifically wanting an image rather than a label. Defaults to false. + \param fallback if non-NULL, is set to an alternate value to use should the actual value be not appropriate. Defaults to NULL. + \return label (or image). + */ CStdString GetLabel(int contextWindow, bool preferImage = false, CStdString *fallback = NULL) const; + + /*! + \brief Gets a label (or image) for a given listitem from the info manager. + \param item listitem in question. + \param preferImage caller is specifically wanting an image rather than a label. Defaults to false. + \param fallback if non-NULL, is set to an alternate value to use should the actual value be not appropriate. Defaults to NULL. + \return label (or image). + */ CStdString GetItemLabel(const CGUIListItem *item, bool preferImage = false, CStdString *fallback = NULL) const; + bool IsConstant() const; bool IsEmpty() const; diff --git a/xbmc/guilib/GUIKeyboard.h b/xbmc/guilib/GUIKeyboard.h new file mode 100644 index 0000000000..61610b5733 --- /dev/null +++ b/xbmc/guilib/GUIKeyboard.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once + +#include <string> + +class CGUIKeyboard; +enum FILTERING { FILTERING_NONE = 0, FILTERING_CURRENT, FILTERING_SEARCH }; +typedef void (*char_callback_t) (CGUIKeyboard *ref, const std::string &typedString); + +class CGUIKeyboard +{ + public: + + CGUIKeyboard(){}; + virtual ~CGUIKeyboard(){}; + + //entrypoint + virtual bool ShowAndGetInput(char_callback_t pCallback, const std::string &initialString, std::string &typedString, const std::string &heading, bool bHiddenInput = false) = 0; + virtual int GetWindowId() const {return 0;} +}; diff --git a/xbmc/guilib/GUIKeyboardFactory.cpp b/xbmc/guilib/GUIKeyboardFactory.cpp new file mode 100644 index 0000000000..7bb58e3a8f --- /dev/null +++ b/xbmc/guilib/GUIKeyboardFactory.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Application.h" +#include "LocalizeStrings.h" +#include "GUIKeyboardFactory.h" +#include "dialogs/GUIDialogOK.h" +#include "GUIUserMessages.h" +#include "GUIWindowManager.h" +#include "settings/GUISettings.h" +#include "utils/md5.h" + + +#include "dialogs/GUIDialogKeyboardGeneric.h" +#if defined(TARGET_DARWIN_IOS) +#include "osx/ios/IOSKeyboard.h" +#endif + +FILTERING CGUIKeyboardFactory::m_filtering = FILTERING_NONE; + +CGUIKeyboardFactory::CGUIKeyboardFactory(void) +{ +} + +CGUIKeyboardFactory::~CGUIKeyboardFactory(void) +{} + +void CGUIKeyboardFactory::keyTypedCB(CGUIKeyboard *ref, const std::string &typedString) +{ + if(ref) + { + // send our search message (only the active window needs it) + CGUIMessage message(GUI_MSG_NOTIFY_ALL, ref->GetWindowId(), 0); + CGUIWindow *window = NULL; + switch(m_filtering) + { + case FILTERING_SEARCH: + window = g_windowManager.GetWindow(g_windowManager.GetActiveWindow()); + message.SetParam1(GUI_MSG_SEARCH_UPDATE); + message.SetStringParam(typedString); + if (window) + window->OnMessage(message); + break; + case FILTERING_CURRENT: + message.SetParam1(GUI_MSG_FILTER_ITEMS); + message.SetStringParam(typedString); + g_windowManager.SendMessage(message); + break; + case FILTERING_NONE: + break; + } + } +} + +// Show keyboard with initial value (aTextString) and replace with result string. +// Returns: true - successful display and input (empty result may return true or false depending on parameter) +// false - unsucessful display of the keyboard or cancelled editing +bool CGUIKeyboardFactory::ShowAndGetInput(CStdString& aTextString, const CVariant &heading, bool allowEmptyResult, bool hiddenInput /* = false */) +{ + bool confirmed = false; + CGUIKeyboard *kb = NULL; + bool needsFreeing = true; + //heading can be a string or a localization id + std::string headingStr; + if (heading.isString()) + headingStr = heading.asString(); + else if (heading.isInteger() && heading.asInteger()) + headingStr = g_localizeStrings.Get((uint32_t)heading.asInteger()); + +#if defined(TARGET_DARWIN_IOS) && !defined(TARGET_DARWIN_IOS_ATV2) + kb = new CIOSKeyboard(); +#endif + + if(!kb) + { + kb = (CGUIDialogKeyboardGeneric*)g_windowManager.GetWindow(WINDOW_DIALOG_KEYBOARD); + needsFreeing = false; + } + + confirmed = kb->ShowAndGetInput(keyTypedCB, aTextString, aTextString, headingStr, hiddenInput); + if(needsFreeing) + delete kb; + + if (confirmed) + { + if (!allowEmptyResult && aTextString.IsEmpty()) + confirmed = false; + } + + return confirmed; +} + +bool CGUIKeyboardFactory::ShowAndGetInput(CStdString& aTextString, bool allowEmptyResult) +{ + return ShowAndGetInput(aTextString, "", allowEmptyResult) != 0; +} + +// Shows keyboard and prompts for a password. +// Differs from ShowAndVerifyNewPassword() in that no second verification is necessary. +bool CGUIKeyboardFactory::ShowAndGetNewPassword(CStdString& newPassword, const CVariant &heading, bool allowEmpty) +{ + return ShowAndGetInput(newPassword, heading, allowEmpty, true); +} + +// Shows keyboard and prompts for a password. +// Differs from ShowAndVerifyNewPassword() in that no second verification is necessary. +bool CGUIKeyboardFactory::ShowAndGetNewPassword(CStdString& newPassword) +{ + return ShowAndGetNewPassword(newPassword, 12340, false); +} + +bool CGUIKeyboardFactory::ShowAndGetFilter(CStdString &filter, bool searching) +{ + m_filtering = searching ? FILTERING_SEARCH : FILTERING_CURRENT; + bool ret = ShowAndGetInput(filter, searching ? 16017 : 16028, true); + m_filtering = FILTERING_NONE; + return ret; +} + + +// \brief Show keyboard twice to get and confirm a user-entered password string. +// \param newPassword Overwritten with user input if return=true. +// \param heading Heading to display +// \param allowEmpty Whether a blank password is valid or not. +// \return true if successful display and user input entry/re-entry. false if unsucessful display, no user input, or canceled editing. +bool CGUIKeyboardFactory::ShowAndVerifyNewPassword(CStdString& newPassword, const CVariant &heading, bool allowEmpty) +{ + // Prompt user for password input + CStdString userInput = ""; + if (!ShowAndGetInput(userInput, heading, allowEmpty, true)) + { // user cancelled, or invalid input + return false; + } + // success - verify the password + CStdString checkInput = ""; + if (!ShowAndGetInput(checkInput, 12341, allowEmpty, true)) + { // user cancelled, or invalid input + return false; + } + // check the password + if (checkInput == userInput) + { + XBMC::XBMC_MD5 md5state; + md5state.append(userInput); + md5state.getDigest(newPassword); + newPassword.ToLower(); + return true; + } + CGUIDialogOK::ShowAndGetInput(12341, 12344, 0, 0); + return false; +} + +// \brief Show keyboard twice to get and confirm a user-entered password string. +// \param strNewPassword Overwritten with user input if return=true. +// \return true if successful display and user input entry/re-entry. false if unsucessful display, no user input, or canceled editing. +bool CGUIKeyboardFactory::ShowAndVerifyNewPassword(CStdString& newPassword) +{ + CStdString heading = g_localizeStrings.Get(12340); + return ShowAndVerifyNewPassword(newPassword, heading, false); +} + +// \brief Show keyboard and verify user input against strPassword. +// \param strPassword Value to compare against user input. +// \param dlgHeading String shown on dialog title. Converts to localized string if contains a positive integer. +// \param iRetries If greater than 0, shows "Incorrect password, %d retries left" on dialog line 2, else line 2 is blank. +// \return 0 if successful display and user input. 1 if unsucessful input. -1 if no user input or canceled editing. +int CGUIKeyboardFactory::ShowAndVerifyPassword(CStdString& strPassword, const CStdString& strHeading, int iRetries) +{ + CStdString strHeadingTemp; + if (1 > iRetries && strHeading.size()) + strHeadingTemp = strHeading; + else + strHeadingTemp.Format("%s - %i %s", g_localizeStrings.Get(12326).c_str(), g_guiSettings.GetInt("masterlock.maxretries") - iRetries, g_localizeStrings.Get(12343).c_str()); + + CStdString strUserInput = ""; + if (!ShowAndGetInput(strUserInput, strHeadingTemp, false, true)) //bool hiddenInput = false/true ? TODO: GUI Setting to enable disable this feature y/n? + return -1; // user canceled out + + if (!strPassword.IsEmpty()) + { + if (strPassword == strUserInput) + return 0; + + CStdString md5pword2; + XBMC::XBMC_MD5 md5state; + md5state.append(strUserInput); + md5state.getDigest(md5pword2); + if (strPassword.Equals(md5pword2)) + return 0; // user entered correct password + else return 1; // user must have entered an incorrect password + } + else + { + if (!strUserInput.IsEmpty()) + { + XBMC::XBMC_MD5 md5state; + md5state.append(strUserInput); + md5state.getDigest(strPassword); + strPassword.ToLower(); + return 0; // user entered correct password + } + else return 1; + } +} + diff --git a/xbmc/guilib/GUIKeyboardFactory.h b/xbmc/guilib/GUIKeyboardFactory.h new file mode 100644 index 0000000000..811794b4a7 --- /dev/null +++ b/xbmc/guilib/GUIKeyboardFactory.h @@ -0,0 +1,47 @@ +#pragma once + +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GUIDialog.h" +#include "utils/Variant.h" +#include "GUIKeyboard.h" + +class CGUIKeyboardFactory +{ + + public: + CGUIKeyboardFactory(void); + virtual ~CGUIKeyboardFactory(void); + + static bool ShowAndGetInput(CStdString& aTextString, bool allowEmptyResult); + static bool ShowAndGetInput(CStdString& aTextString, const CVariant &heading, bool allowEmptyResult, bool hiddenInput = false); + static bool ShowAndGetNewPassword(CStdString& strNewPassword); + static bool ShowAndGetNewPassword(CStdString& newPassword, const CVariant &heading, bool allowEmpty); + static bool ShowAndVerifyNewPassword(CStdString& strNewPassword); + static bool ShowAndVerifyNewPassword(CStdString& newPassword, const CVariant &heading, bool allowEmpty); + static int ShowAndVerifyPassword(CStdString& strPassword, const CStdString& strHeading, int iRetries); + static bool ShowAndGetFilter(CStdString& aTextString, bool searching); + + private: + static FILTERING m_filtering; + static void keyTypedCB(CGUIKeyboard *ref, const std::string &typedString); +}; diff --git a/xbmc/guilib/GUIListContainer.cpp b/xbmc/guilib/GUIListContainer.cpp index 96671b564a..4d326e85ce 100644 --- a/xbmc/guilib/GUIListContainer.cpp +++ b/xbmc/guilib/GUIListContainer.cpp @@ -21,7 +21,6 @@ #include "GUIListContainer.h" #include "GUIListItem.h" -#include "GUIInfoManager.h" #include "Key.h" CGUIListContainer::CGUIListContainer(int parentID, int controlID, float posX, float posY, float width, float height, ORIENTATION orientation, const CScroller& scroller, int preloadItems) diff --git a/xbmc/guilib/GUIMoverControl.h b/xbmc/guilib/GUIMoverControl.h index f1a748dbca..81c28b23a9 100644 --- a/xbmc/guilib/GUIMoverControl.h +++ b/xbmc/guilib/GUIMoverControl.h @@ -76,6 +76,7 @@ public: void SetLocation(int iLocX, int iLocY, bool bSetPosition = true); int GetXLocation() const { return m_iLocationX;}; int GetYLocation() const { return m_iLocationY;}; + virtual bool CanFocus() const { return true; }; protected: virtual EVENT_RESULT OnMouseEvent(const CPoint &point, const CMouseEvent &event); diff --git a/xbmc/guilib/GUIMultiImage.cpp b/xbmc/guilib/GUIMultiImage.cpp index 89aa2e9ad6..43a75ee90a 100644 --- a/xbmc/guilib/GUIMultiImage.cpp +++ b/xbmc/guilib/GUIMultiImage.cpp @@ -23,8 +23,11 @@ #include "TextureManager.h" #include "filesystem/Directory.h" #include "utils/URIUtils.h" +#include "utils/JobManager.h" #include "FileItem.h" +#include "settings/Settings.h" #include "Key.h" +#include "TextureCache.h" using namespace std; using namespace XFILE; @@ -41,7 +44,8 @@ CGUIMultiImage::CGUIMultiImage(int parentID, int controlID, float posX, float po m_loop = loop; ControlType = GUICONTROL_MULTI_IMAGE; m_bDynamicResourceAlloc=false; - m_directoryLoaded = false; + m_directoryStatus = UNLOADED; + m_jobID = 0; } CGUIMultiImage::CGUIMultiImage(const CGUIMultiImage &from) @@ -53,7 +57,7 @@ CGUIMultiImage::CGUIMultiImage(const CGUIMultiImage &from) m_randomized = from.m_randomized; m_loop = from.m_loop; m_bDynamicResourceAlloc=false; - m_directoryLoaded = false; + m_directoryStatus = UNLOADED; if (m_texturePath.IsConstant()) m_currentPath = m_texturePath.GetLabel(WINDOW_INVALID); m_currentImage = 0; @@ -62,6 +66,7 @@ CGUIMultiImage::CGUIMultiImage(const CGUIMultiImage &from) CGUIMultiImage::~CGUIMultiImage(void) { + CancelLoading(); } void CGUIMultiImage::UpdateVisibility(const CGUIListItem *item) @@ -77,13 +82,14 @@ void CGUIMultiImage::UpdateVisibility(const CGUIListItem *item) } // we are either delayed or visible, so we can allocate our resources - if (!m_directoryLoaded) - { + if (m_directoryStatus == UNLOADED) LoadDirectory(); - m_image.SetFileName(m_files.size() ? m_files[0] : ""); - } + if (!m_bAllocated) AllocResources(); + + if (m_directoryStatus == LOADED) + OnDirectoryLoaded(); } void CGUIMultiImage::UpdateInfo(const CGUIListItem *item) @@ -101,7 +107,7 @@ void CGUIMultiImage::UpdateInfo(const CGUIListItem *item) { // a new path - set our current path and tell ourselves to load our directory m_currentPath = texturePath; - m_directoryLoaded = false; + CancelLoading(); } } } @@ -109,7 +115,7 @@ void CGUIMultiImage::UpdateInfo(const CGUIListItem *item) void CGUIMultiImage::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { // Set a viewport so that we don't render outside the defined area - if (!m_files.empty() && g_graphicsContext.SetClipRegion(m_posX, m_posY, m_width, m_height)) + if (m_directoryStatus == READY && !m_files.empty()) { unsigned int nextImage = m_currentImage + 1; if (nextImage >= m_files.size()) @@ -131,7 +137,10 @@ void CGUIMultiImage::Process(unsigned int currentTime, CDirtyRegionList &dirtyre m_imageTimer.StartZero(); } } + } + if (g_graphicsContext.SetClipRegion(m_posX, m_posY, m_width, m_height)) + { if (m_image.SetColorDiffuse(m_diffuseColor)) MarkDirtyRegion(); @@ -145,9 +154,7 @@ void CGUIMultiImage::Process(unsigned int currentTime, CDirtyRegionList &dirtyre void CGUIMultiImage::Render() { - if (!m_files.empty()) - m_image.Render(); - + m_image.Render(); CGUIControl::Render(); } @@ -172,18 +179,8 @@ void CGUIMultiImage::AllocResources() FreeResources(); CGUIControl::AllocResources(); - if (!m_directoryLoaded) + if (m_directoryStatus == UNLOADED) LoadDirectory(); - - // Load in the current image, and reset our timer - m_currentImage = 0; - m_imageTimer.StartZero(); - - // and re-randomize if our control has been reallocated - if (m_randomized) - random_shuffle(m_files.begin(), m_files.end()); - - m_image.SetFileName(m_files.size() ? m_files[0] : ""); } void CGUIMultiImage::FreeResources(bool immediately) @@ -217,39 +214,35 @@ void CGUIMultiImage::SetAspectRatio(const CAspectRatio &ratio) void CGUIMultiImage::LoadDirectory() { - // Load any images from our texture bundle first + // clear current stuff out m_files.clear(); // don't load any images if our path is empty if (m_currentPath.IsEmpty()) return; - // check to see if we have a single image or a folder of images + /* Check the fast cases: + 1. Picture extension + 2. Cached picture (in case an extension is not present) + 3. Bundled folder + */ CFileItem item(m_currentPath, false); - if (item.IsPicture()) - { + if (item.IsPicture() || CTextureCache::Get().HasCachedImage(m_currentPath)) m_files.push_back(m_currentPath); - } - else - { // folder of images + else // bundled folder? g_TextureManager.GetBundledTexturesFromPath(m_currentPath, m_files); - - // Load in our images from the directory specified - // m_currentPath is relative (as are all skin paths) - CStdString realPath = g_TextureManager.GetTexturePath(m_currentPath, true); - if (realPath.IsEmpty() && m_files.empty()) - return; - - URIUtils::AddSlashAtEnd(realPath); - CFileItemList items; - CDirectory::GetDirectory(realPath, items); - for (int i=0; i < items.Size(); i++) - { - CFileItemPtr pItem = items[i]; - if (pItem->IsPicture()) - m_files.push_back(pItem->GetPath()); - } + if (!m_files.empty()) + { // found - nothing more to do + OnDirectoryLoaded(); + return; } + // slow(er) checks necessary - do them in the background + CSingleLock lock(m_section); + m_directoryStatus = LOADING; + m_jobID = CJobManager::GetInstance().AddJob(new CMultiImageJob(m_currentPath), this, CJob::PRIORITY_NORMAL); +} +void CGUIMultiImage::OnDirectoryLoaded() +{ // Randomize or sort our images if necessary if (m_randomized) random_shuffle(m_files.begin(), m_files.end()); @@ -257,8 +250,28 @@ void CGUIMultiImage::LoadDirectory() sort(m_files.begin(), m_files.end()); // flag as loaded - no point in constantly reloading them - m_directoryLoaded = true; + m_directoryStatus = READY; m_imageTimer.StartZero(); + m_currentImage = 0; + m_image.SetFileName(m_files.empty() ? "" : m_files[0]); +} + +void CGUIMultiImage::CancelLoading() +{ + CSingleLock lock(m_section); + if (m_directoryStatus == LOADING) + CJobManager::GetInstance().CancelJob(m_jobID); + m_directoryStatus = UNLOADED; +} + +void CGUIMultiImage::OnJobComplete(unsigned int jobID, bool success, CJob *job) +{ + CSingleLock lock(m_section); + if (m_directoryStatus == LOADING && strncmp(job->GetType(), "multiimage", 10) == 0) + { + m_files = ((CMultiImageJob *)job)->m_files; + m_directoryStatus = LOADED; + } } void CGUIMultiImage::SetInfo(const CGUIInfoLabel &info) @@ -272,3 +285,33 @@ CStdString CGUIMultiImage::GetDescription() const { return m_image.GetDescription(); } + +CGUIMultiImage::CMultiImageJob::CMultiImageJob(const CStdString &path) + : m_path(path) +{ +} + +bool CGUIMultiImage::CMultiImageJob::DoWork() +{ + // check to see if we have a single image or a folder of images + CFileItem item(m_path, false); + if (item.IsPicture() || item.GetMimeType().Left(6).Equals("image/")) + { + m_files.push_back(m_path); + } + else + { + // Load in images from the directory specified + // m_path is relative (as are all skin paths) + CStdString realPath = g_TextureManager.GetTexturePath(m_path, true); + if (realPath.IsEmpty()) + return true; + + URIUtils::AddSlashAtEnd(realPath); + CFileItemList items; + CDirectory::GetDirectory(realPath, items, g_settings.m_pictureExtensions + "|.tbn|.dds", DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_NO_FILE_INFO); + for (int i=0; i < items.Size(); i++) + m_files.push_back(items[i]->GetPath()); + } + return true; +} diff --git a/xbmc/guilib/GUIMultiImage.h b/xbmc/guilib/GUIMultiImage.h index 5c3b03ca26..acb9008627 100644 --- a/xbmc/guilib/GUIMultiImage.h +++ b/xbmc/guilib/GUIMultiImage.h @@ -31,12 +31,14 @@ #include "GUIImage.h" #include "utils/Stopwatch.h" +#include "utils/Job.h" +#include "threads/CriticalSection.h" /*! \ingroup controls \brief */ -class CGUIMultiImage : public CGUIControl +class CGUIMultiImage : public CGUIControl, public IJobCallback { public: CGUIMultiImage(int parentID, int controlID, float posX, float posY, float width, float height, const CTextureInfo& texture, unsigned int timePerImage, unsigned int fadeTime, bool randomized, bool loop, unsigned int timeToPauseAtEnd); @@ -63,6 +65,22 @@ public: protected: void LoadDirectory(); + void OnDirectoryLoaded(); + void CancelLoading(); + + enum DIRECTORY_STATUS { UNLOADED = 0, LOADING, LOADED, READY }; + virtual void OnJobComplete(unsigned int jobID, bool success, CJob *job); + + class CMultiImageJob : public CJob + { + public: + CMultiImageJob(const CStdString &path); + virtual bool DoWork(); + virtual const char *GetType() const { return "multiimage"; }; + + std::vector<CStdString> m_files; + CStdString m_path; + }; CGUIInfoLabel m_texturePath; CStdString m_currentPath; @@ -74,9 +92,12 @@ protected: bool m_loop; bool m_bDynamicResourceAlloc; - bool m_directoryLoaded; std::vector<CStdString> m_files; CGUIImage m_image; + + CCriticalSection m_section; + DIRECTORY_STATUS m_directoryStatus; + unsigned int m_jobID; }; #endif diff --git a/xbmc/guilib/GUIPanelContainer.cpp b/xbmc/guilib/GUIPanelContainer.cpp index 27bf307a7e..5470247013 100644 --- a/xbmc/guilib/GUIPanelContainer.cpp +++ b/xbmc/guilib/GUIPanelContainer.cpp @@ -75,9 +75,9 @@ void CGUIPanelContainer::Process(unsigned int currentTime, CDirtyRegionList &dir bool focused = (current == GetOffset() * m_itemsPerRow + GetCursor()) && m_bHasFocus; if (m_orientation == VERTICAL) - ProcessItem(origin.x + col * m_layout->Size(HORIZONTAL), pos, item.get(), focused, currentTime, dirtyregions); + ProcessItem(origin.x + col * m_layout->Size(HORIZONTAL), pos, item, focused, currentTime, dirtyregions); else - ProcessItem(pos, origin.y + col * m_layout->Size(VERTICAL), item.get(), focused, currentTime, dirtyregions); + ProcessItem(pos, origin.y + col * m_layout->Size(VERTICAL), item, focused, currentTime, dirtyregions); } // increment our position if (col < m_itemsPerRow - 1) diff --git a/xbmc/guilib/GUIResizeControl.h b/xbmc/guilib/GUIResizeControl.h index abac66c5e1..9085e55532 100644 --- a/xbmc/guilib/GUIResizeControl.h +++ b/xbmc/guilib/GUIResizeControl.h @@ -65,6 +65,7 @@ public: virtual void SetInvalid(); virtual void SetPosition(float posX, float posY); void SetLimits(float x1, float y1, float x2, float y2); + virtual bool CanFocus() const { return true; }; protected: virtual EVENT_RESULT OnMouseEvent(const CPoint &point, const CMouseEvent &event); diff --git a/xbmc/guilib/GUIWindow.cpp b/xbmc/guilib/GUIWindow.cpp index 847e55e20e..03c4e7cfa8 100644 --- a/xbmc/guilib/GUIWindow.cpp +++ b/xbmc/guilib/GUIWindow.cpp @@ -41,6 +41,7 @@ #include "utils/XMLUtils.h" #include "GUIAudioManager.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "utils/Variant.h" #ifdef HAS_PERFORMANCE_SAMPLE @@ -301,6 +302,12 @@ void CGUIWindow::DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyregi CGUIControlGroup::DoProcess(currentTime, dirtyregions); if (size != g_graphicsContext.RemoveTransform()) CLog::Log(LOGERROR, "Unbalanced UI transforms (was %d)", size); + + // check if currently focused control can have it + // and fallback to default control if not + CGUIControl* focusedControl = GetFocusedControl(); + if (focusedControl && !focusedControl->CanFocus()) + SET_CONTROL_FOCUS(m_defaultControl, 0); } void CGUIWindow::DoRender() @@ -365,7 +372,7 @@ void CGUIWindow::Close(bool forceClose /*= false*/, int nextWindowID /*= 0*/, bo { // make sure graphics lock is not held CSingleExit leaveIt(g_graphicsContext); - g_application.getApplicationMessenger().Close(this, forceClose, true, nextWindowID, enableSound); + CApplicationMessenger::Get().Close(this, forceClose, true, nextWindowID, enableSound); } else Close_Internal(forceClose, nextWindowID, enableSound); @@ -848,7 +855,13 @@ bool CGUIWindow::OnMove(int fromControl, int moveAction) while (control) { // grab the next control direction moveHistory.push_back(nextControl); - nextControl = control->GetNextControl(moveAction); + CGUIAction action; + if (!control->GetNavigationAction(moveAction, action)) + return false; + action.ExecuteActions(nextControl, GetParentID()); + nextControl = action.GetNavigation(); + if (!nextControl) // 0 isn't valid control id + return false; // check our history - if the nextControl is in it, we can't focus it for (unsigned int i = 0; i < moveHistory.size(); i++) { @@ -966,12 +979,12 @@ void CGUIWindow::SetRunActionsManually() void CGUIWindow::RunLoadActions() { - m_loadActions.Execute(GetID(), GetParentID()); + m_loadActions.ExecuteActions(GetID(), GetParentID()); } void CGUIWindow::RunUnloadActions() { - m_unloadActions.Execute(GetID(), GetParentID()); + m_unloadActions.ExecuteActions(GetID(), GetParentID()); } void CGUIWindow::ClearBackground() diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp index 477449aa3e..028bb173c1 100644 --- a/xbmc/guilib/GUIWindowManager.cpp +++ b/xbmc/guilib/GUIWindowManager.cpp @@ -23,6 +23,7 @@ #include "GUIAudioManager.h" #include "GUIDialog.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "GUIPassword.h" #include "GUIInfoManager.h" #include "threads/SingleLock.h" @@ -342,7 +343,7 @@ void CGUIWindowManager::ActivateWindow(int iWindowID, const vector<CStdString>& { // make sure graphics lock is not held CSingleExit leaveIt(g_graphicsContext); - g_application.getApplicationMessenger().ActivateWindow(iWindowID, params, swappingWindows); + CApplicationMessenger::Get().ActivateWindow(iWindowID, params, swappingWindows); } else { @@ -970,7 +971,7 @@ void CGUIWindowManager::CloseWindowSync(CGUIWindow *window, int nextWindowID /*= { window->Close(false, nextWindowID); while (window->IsAnimating(ANIM_TYPE_WINDOW_CLOSE)) - g_windowManager.ProcessRenderLoop(true); + ProcessRenderLoop(true); } #ifdef _DEBUG diff --git a/xbmc/guilib/Geometry.h b/xbmc/guilib/Geometry.h index f77d81e090..c4838f79a1 100644 --- a/xbmc/guilib/Geometry.h +++ b/xbmc/guilib/Geometry.h @@ -27,6 +27,8 @@ #else #define XBMC_FORCE_INLINE #endif + +#include <vector> #include <algorithm> class CPoint @@ -154,6 +156,65 @@ public: return Width() * Height(); }; + std::vector<CRect> SubtractRect(CRect splitterRect) + { + std::vector<CRect> newRectaglesList; + CRect intersection = splitterRect.Intersect(*this); + + if (!intersection.IsEmpty()) + { + CRect add; + + // add rect above intersection if not empty + add = CRect(x1, y1, x2, intersection.y1); + if (!add.IsEmpty()) + newRectaglesList.push_back(add); + + // add rect below intersection if not empty + add = CRect(x1, intersection.y2, x2, y2); + if (!add.IsEmpty()) + newRectaglesList.push_back(add); + + // add rect left intersection if not empty + add = CRect(x1, intersection.y1, intersection.x1, intersection.y2); + if (!add.IsEmpty()) + newRectaglesList.push_back(add); + + // add rect right intersection if not empty + add = CRect(intersection.x2, intersection.y1, x2, intersection.y2); + if (!add.IsEmpty()) + newRectaglesList.push_back(add); + } + else + { + newRectaglesList.push_back(*this); + } + + return newRectaglesList; + } + + std::vector<CRect> SubtractRects(std::vector<CRect> intersectionList) + { + std::vector<CRect> fragmentsList; + fragmentsList.push_back(*this); + + for (std::vector<CRect>::iterator splitter = intersectionList.begin(); splitter != intersectionList.end(); ++splitter) + { + std::vector<CRect> toAddList; + + for (std::vector<CRect>::iterator fragment = fragmentsList.begin(); fragment != fragmentsList.end(); ++fragment) + { + std::vector<CRect> newFragmentsList = fragment->SubtractRect(*splitter); + toAddList.insert(toAddList.end(), newFragmentsList.begin(), newFragmentsList.end()); + } + + fragmentsList.clear(); + fragmentsList.insert(fragmentsList.end(), toAddList.begin(), toAddList.end()); + } + + return fragmentsList; + } + bool operator !=(const CRect &rect) const { if (x1 != rect.x1) return true; diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp index 8a6cfc8a41..bddfa9abb1 100644 --- a/xbmc/guilib/GraphicContext.cpp +++ b/xbmc/guilib/GraphicContext.cpp @@ -23,6 +23,7 @@ #include "GraphicContext.h" #include "threads/SingleLock.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "settings/GUISettings.h" #include "settings/Settings.h" #include "settings/AdvancedSettings.h" @@ -42,19 +43,18 @@ extern bool g_fullScreen; static CSettingInt* g_guiSkinzoom = NULL; CGraphicContext::CGraphicContext(void) : - m_iScreenHeight(576), - m_iScreenWidth(720), - m_iScreenId(0), - m_strMediaDir(""), - /*m_videoRect,*/ - m_bFullScreenRoot(false), + m_iScreenHeight(576), + m_iScreenWidth(720), + m_iScreenId(0), + /*m_videoRect,*/ + m_bFullScreenRoot(false), m_bFullScreenVideo(false), - m_bCalibrating(false), - m_Resolution(RES_INVALID), + m_bCalibrating(false), + m_Resolution(RES_INVALID), /*m_windowResolution,*/ - m_guiScaleX(1.0f), - m_guiScaleY(1.0f) - /*,m_cameras, */ + m_guiScaleX(1.0f), + m_guiScaleY(1.0f) + /*,m_cameras, */ /*m_origins, */ /*m_clipRegions,*/ /*m_guiTransform,*/ @@ -279,7 +279,8 @@ void CGraphicContext::SetFullScreenVideo(bool bOnOff) #if defined(HAS_VIDEO_PLAYBACK) if(m_bFullScreenRoot) { - if(m_bFullScreenVideo) + bool allowDesktopRes = g_guiSettings.GetInt("videoplayer.adjustrefreshrate") == ADJUST_REFRESHRATE_ALWAYS; + if(m_bFullScreenVideo || (!allowDesktopRes && g_application.IsPlayingVideo())) SetVideoResolution(g_renderManager.GetResolution()); else if(g_guiSettings.m_LookAndFeelResolution > RES_DESKTOP) SetVideoResolution(g_guiSettings.m_LookAndFeelResolution); @@ -340,7 +341,7 @@ void CGraphicContext::SetVideoResolution(RESOLUTION res, bool forceUpdate) { //pause the player during the refreshrate change int delay = g_guiSettings.GetInt("videoplayer.pauseafterrefreshchange"); - if (delay > 0 && g_guiSettings.GetBool("videoplayer.adjustrefreshrate") && g_application.IsPlayingVideo() && !g_application.IsPaused()) + if (delay > 0 && g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF && g_application.IsPlayingVideo() && !g_application.IsPaused()) { g_application.m_pPlayer->Pause(); ThreadMessage msg = {TMSG_MEDIA_UNPAUSE}; diff --git a/xbmc/guilib/Makefile.in b/xbmc/guilib/Makefile.in index d824caa797..6a6576e91f 100644 --- a/xbmc/guilib/Makefile.in +++ b/xbmc/guilib/Makefile.in @@ -27,6 +27,7 @@ SRCS=AnimatedGif.cpp \ GUIImage.cpp \ GUIIncludes.cpp \ GUIInfoTypes.cpp \ + GUIKeyboardFactory.cpp \ GUILabel.cpp \ GUILabelControl.cpp \ GUIListContainer.cpp \ diff --git a/xbmc/guilib/MatrixGLES.cpp b/xbmc/guilib/MatrixGLES.cpp index 03c7fa6f8e..a0962d56e3 100644 --- a/xbmc/guilib/MatrixGLES.cpp +++ b/xbmc/guilib/MatrixGLES.cpp @@ -28,6 +28,9 @@ #include <cmath> #include "MatrixGLES.h" #include "utils/log.h" +#if defined(__ARM_NEON__) +#include "utils/CPUInfo.h" +#endif CMatrixGLES g_matrices; @@ -43,6 +46,9 @@ CMatrixGLES::CMatrixGLES() } m_matrixMode = (EMATRIXMODE)-1; m_pMatrix = NULL; +#if defined(__ARM_NEON__) + m_has_neon = (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON) == CPU_FEATURE_NEON; +#endif } CMatrixGLES::~CMatrixGLES() @@ -236,20 +242,19 @@ inline void Matrix4Mul(const float* src_mat_1, const float* src_mat_2, float* ds : "memory", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11" //clobber ); } +#endif void CMatrixGLES::MultMatrixf(const GLfloat *matrix) { if (m_pMatrix) { - GLfloat m[16]; - Matrix4Mul(m_pMatrix, matrix, m); - } -} - -#else -void CMatrixGLES::MultMatrixf(const GLfloat *matrix) -{ - if (m_pMatrix) - { +#if defined(__ARM_NEON__) + if (m_has_neon) + { + GLfloat m[16]; + Matrix4Mul(m_pMatrix, matrix, m); + return; + } +#endif GLfloat a = (matrix[0] * m_pMatrix[0]) + (matrix[1] * m_pMatrix[4]) + (matrix[2] * m_pMatrix[8]) + (matrix[3] * m_pMatrix[12]); GLfloat b = (matrix[0] * m_pMatrix[1]) + (matrix[1] * m_pMatrix[5]) + (matrix[2] * m_pMatrix[9]) + (matrix[3] * m_pMatrix[13]); GLfloat c = (matrix[0] * m_pMatrix[2]) + (matrix[1] * m_pMatrix[6]) + (matrix[2] * m_pMatrix[10]) + (matrix[3] * m_pMatrix[14]); @@ -272,7 +277,6 @@ void CMatrixGLES::MultMatrixf(const GLfloat *matrix) m_pMatrix[3] = d; m_pMatrix[7] = h; m_pMatrix[11] = l; m_pMatrix[15] = p; } } -#endif // gluLookAt implementation taken from Mesa3D void CMatrixGLES::LookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx, GLfloat centery, GLfloat centerz, GLfloat upx, GLfloat upy, GLfloat upz) diff --git a/xbmc/guilib/MatrixGLES.h b/xbmc/guilib/MatrixGLES.h index 365445fea7..2ee26e7636 100644 --- a/xbmc/guilib/MatrixGLES.h +++ b/xbmc/guilib/MatrixGLES.h @@ -71,6 +71,9 @@ protected: std::vector<struct MatrixWrapper> m_matrices[(int)MM_MATRIXSIZE]; GLfloat *m_pMatrix; EMATRIXMODE m_matrixMode; +#if defined(__ARM_NEON__) + bool m_has_neon; +#endif }; extern CMatrixGLES g_matrices; diff --git a/xbmc/guilib/Texture.cpp b/xbmc/guilib/Texture.cpp index 5aedff311d..4c44c6ab56 100644 --- a/xbmc/guilib/Texture.cpp +++ b/xbmc/guilib/Texture.cpp @@ -32,7 +32,10 @@ #include "filesystem/File.h" #include "osx/DarwinUtils.h" #endif - +#if defined(TARGET_ANDROID) +#include "URL.h" +#include "filesystem/AndroidAppFile.h" +#endif /************************************************************************/ /* */ /************************************************************************/ @@ -91,6 +94,16 @@ void CBaseTexture::Allocate(unsigned int width, unsigned int height, unsigned in m_textureWidth = ((m_textureWidth + 3) / 4) * 4; m_textureHeight = ((m_textureHeight + 3) / 4) * 4; } + else + { + // align all textures so that they have an even width + // in some circumstances when we downsize a thumbnail + // which has an uneven number of pixels in width + // we crash in CPicture::ScaleImage in ffmpegs swscale + // because it tries to access beyond the source memory + // (happens on osx and ios) + m_textureWidth = ((m_textureWidth + 1) / 2) * 2; + } // check for max texture size #define CLAMP(x, y) { if (x > y) x = y; } @@ -173,6 +186,31 @@ void CBaseTexture::ClampToEdge() CBaseTexture *CBaseTexture::LoadFromFile(const CStdString& texturePath, unsigned int idealWidth, unsigned int idealHeight, bool autoRotate) { +#if defined(TARGET_ANDROID) + CURL url(texturePath); + if (url.GetProtocol() == "androidapp") + { + XFILE::CFileAndroidApp file; + if (file.Open(url)) + { + unsigned int imgsize = (unsigned int)file.GetLength(); + unsigned char* inputBuff = new unsigned char[imgsize]; + unsigned int inputBuffSize = file.Read(inputBuff, imgsize); + file.Close(); + if (inputBuffSize != imgsize) + { + delete [] inputBuff; + return NULL; + } + CTexture *texture = new CTexture(); + unsigned int width = file.GetIconWidth(); + unsigned int height = file.GetIconHeight(); + texture->LoadFromMemory(width, height, width*4, XB_FMT_RGBA8, true, inputBuff); + delete [] inputBuff; + return texture; + } + } +#endif CTexture *texture = new CTexture(); if (texture->LoadFromFile(texturePath, idealWidth, idealHeight, autoRotate, NULL, NULL)) return texture; diff --git a/xbmc/guilib/TextureManager.cpp b/xbmc/guilib/TextureManager.cpp index 9ef788965d..a02465e721 100644 --- a/xbmc/guilib/TextureManager.cpp +++ b/xbmc/guilib/TextureManager.cpp @@ -33,6 +33,7 @@ #endif #include "filesystem/File.h" #include "filesystem/Directory.h" +#include "URL.h" #include <assert.h> using namespace std; @@ -392,7 +393,7 @@ int CGUITextureManager::Load(const CStdString& strTextureName, bool checkBundleO int width = 0, height = 0; if (bundle >= 0) { - if (FAILED(m_TexBundle[bundle].LoadTexture(strTextureName, &pTexture, width, height))) + if (!m_TexBundle[bundle].LoadTexture(strTextureName, &pTexture, width, height)) { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); return 0; diff --git a/xbmc/guilib/XBTFReader.cpp b/xbmc/guilib/XBTFReader.cpp index 85d5b8732a..3af0aa6008 100644 --- a/xbmc/guilib/XBTFReader.cpp +++ b/xbmc/guilib/XBTFReader.cpp @@ -189,7 +189,7 @@ bool CXBTFReader::Load(const CXBTFFrame& frame, unsigned char* buffer) { return false; } -#if defined(TARGET_DARWIN) || defined(__FreeBSD__) +#if defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(__ANDROID__) if (fseeko(m_file, (off_t)frame.GetOffset(), SEEK_SET) == -1) #else if (fseeko64(m_file, (off_t)frame.GetOffset(), SEEK_SET) == -1) diff --git a/xbmc/input/Makefile b/xbmc/input/Makefile index f74c2b3c65..b796cfc710 100644 --- a/xbmc/input/Makefile +++ b/xbmc/input/Makefile @@ -4,6 +4,7 @@ SRCS=ButtonTranslator.cpp \ KeyboardStat.cpp \ MouseStat.cpp \ SDLJoystick.cpp \ + TouchInput.cpp \ XBMC_keytable.cpp \ LIB=input.a diff --git a/xbmc/input/TouchInput.cpp b/xbmc/input/TouchInput.cpp new file mode 100644 index 0000000000..2eb2b09d48 --- /dev/null +++ b/xbmc/input/TouchInput.cpp @@ -0,0 +1,550 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "TouchInput.h" +#include "threads/SingleLock.h" +#include "utils/log.h" + +CTouchInput::CTouchInput() + : m_holdTimeout(1000), + m_handler(NULL), + m_gestureState(TouchGestureUnknown), + m_gestureStateOld(TouchGestureUnknown) +{ + m_holdTimer = new CTimer(this); +} + +CTouchInput::~CTouchInput() +{ + delete m_holdTimer; +} + +CTouchInput &CTouchInput::Get() +{ + static CTouchInput sTouchInput; + return sTouchInput; +} + +void CTouchInput::RegisterHandler(ITouchHandler *touchHandler) +{ + m_handler = touchHandler; +} + +void CTouchInput::UnregisterHandler() +{ + m_handler = NULL; +} + +void CTouchInput::SetTouchHoldTimeout(int32_t timeout) +{ + if (timeout <= 0) + return; + + m_holdTimeout = timeout; +} + +bool CTouchInput::Handle(TouchEvent event, float x, float y, int64_t time, int32_t pointer /* = 0 */, float size /* = 0.0f */) +{ + if (time < 0 || pointer < 0 || pointer >= TOUCH_MAX_POINTERS) + return false; + + CSingleLock lock(m_critical); + + bool result = true; + + m_pointers[pointer].current.x = x; + m_pointers[pointer].current.y = y; + m_pointers[pointer].current.time = time; + + switch (event) + { + case TouchEventAbort: + { + CLog::Log(LOGDEBUG, "CTouchInput: TouchEventAbort"); + setGestureState(TouchGestureUnknown); + for (unsigned int pIndex = 0; pIndex < TOUCH_MAX_POINTERS; pIndex++) + m_pointers[pIndex].reset(); + + OnTouchAbort(); + break; + } + + case TouchEventDown: + { + CLog::Log(LOGDEBUG, "CTouchInput: TouchEventDown"); + m_pointers[pointer].down.x = x; + m_pointers[pointer].down.y = y; + m_pointers[pointer].down.time = time; + m_pointers[pointer].moving = false; + m_pointers[pointer].size = size; + + // If this is the down event of the primary pointer + // we start by assuming that it's a single touch + if (pointer == 0) + { + setGestureState(TouchGestureSingleTouch); + result = OnSingleTouchStart(x, y); + + m_holdTimer->Start(m_holdTimeout); + } + // Otherwise it's the down event of another pointer + else + { + // If we so far assumed single touch or still have the primary + // pointer of a previous multi touch pressed down, we can update to multi touch + if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold || + m_gestureState == TouchGestureMultiTouchDone) + { + if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold) + { + result = OnMultiTouchStart(x, y); + + m_holdTimer->Stop(true); + m_holdTimer->Start(m_holdTimeout); + } + else + { + result = OnMultiTouchDown(x, y, pointer); + + m_holdTimer->Stop(false); + } + + setGestureState(TouchGestureMultiTouchStart); + } + // Otherwise we should ignore this pointer + else + { + m_pointers[pointer].reset(); + break; + } + } + return result; + } + + case TouchEventUp: + { + CLog::Log(LOGDEBUG, "CTouchInput: TouchEventUp"); + // unexpected event => abort + if (!m_pointers[pointer].valid() || + m_gestureState == TouchGestureUnknown) + break; + + m_holdTimer->Stop(false); + + // Just a single tap with a pointer + if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold) + { + result = OnSingleTouchEnd(x, y); + + if (m_gestureState == TouchGestureSingleTouch) + OnSingleTap(x, y); + } + // A pan gesture started with a single pointer (ignoring any other pointers) + else if (m_gestureState == TouchGesturePan) + { + float velocityX = 0.0f; // number of pixels per second + float velocityY = 0.0f; // number of pixels per second + m_pointers[pointer].velocity(velocityX, velocityY, false); + + result = OnTouchGesturePanEnd(x, y, + x - m_pointers[pointer].down.x, y - m_pointers[pointer].down.y, + velocityX, velocityY); + } + // we are in multi-touch + else + result = OnMultiTouchUp(x, y, pointer); + + // If we were in multi touch mode and lifted one pointer + // we can go into the TouchGestureMultiTouchDone state which will allow + // the user to go back into multi touch mode without lifting the primary pointer + if (m_gestureState == TouchGestureMultiTouchStart || m_gestureState == TouchGestureMultiTouchHold || m_gestureState == TouchGestureMultiTouch) + { + setGestureState(TouchGestureMultiTouchDone); + + // after lifting the primary pointer, the secondary pointer will + // become the primary pointer in the next event + if (pointer == 0) + { + m_pointers[0] = m_pointers[1]; + pointer = 1; + } + } + // Otherwise abort + else + { + if (m_gestureState == TouchGestureMultiTouchDone) + { + result = OnMultiTouchEnd(m_pointers[0].down.x, m_pointers[0].down.y); + + // if neither of the two pointers moved we have a double tap + if (m_gestureStateOld != TouchGestureMultiTouchHold && m_gestureStateOld != TouchGestureMultiTouch) + OnDoubleTap(m_pointers[0].down.x, m_pointers[0].down.y, + m_pointers[1].down.x, m_pointers[1].down.y); + } + + setGestureState(TouchGestureUnknown); + } + + m_pointers[pointer].reset(); + return result; + } + + case TouchEventMove: + { + CLog::Log(LOGDEBUG, "CTouchInput: TouchEventMove"); + // unexpected event => abort + if (!m_pointers[pointer].valid() || + m_gestureState == TouchGestureUnknown || + m_gestureState == TouchGestureMultiTouchDone) + break; + + if (m_pointers[pointer].moving) + m_holdTimer->Stop(); + + if (m_gestureState == TouchGestureSingleTouch) + { + // Check if the touch has moved far enough to count as movement + if (!m_pointers[pointer].moving) + break; + + result = OnTouchGesturePanStart(m_pointers[pointer].down.x, m_pointers[pointer].down.y); + + m_pointers[pointer].last.copy(m_pointers[pointer].down); + setGestureState(TouchGesturePan); + } + else if (m_gestureState == TouchGestureMultiTouchStart) + { + setGestureState(TouchGestureMultiTouch); + + // set the starting point + saveLastTouch(); + } + + float offsetX = x - m_pointers[pointer].last.x; + float offsetY = y - m_pointers[pointer].last.y; + float velocityX = 0.0f; // number of pixels per second + float velocityY = 0.0f; // number of pixels per second + m_pointers[pointer].velocity(velocityX, velocityY); + + if (m_pointers[pointer].moving && + (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold || m_gestureState == TouchGesturePan)) + result = OnSingleTouchMove(x, y, offsetX, offsetY, velocityX, velocityY); + + // Let's see if we have a pan gesture (i.e. the primary and only pointer moving) + if (m_gestureState == TouchGesturePan) + { + result = OnTouchGesturePan(x, y, offsetX, offsetY, velocityX, velocityY); + + m_pointers[pointer].last.x = x; + m_pointers[pointer].last.y = y; + } + else if (m_gestureState == TouchGestureMultiTouch) + { + if (m_pointers[pointer].moving) + result = OnMultiTouchMove(x, y,offsetX, offsetY, velocityX, velocityY, pointer); + + handleMultiTouchGesture(); + } + else + break; + + return result; + } + + default: + CLog::Log(LOGDEBUG, "CTouchInput: unknown TouchEvent"); + break; + } + + return false; +} + +bool CTouchInput::Update(int32_t pointer, float x, float y, int64_t time, float size /* = 0.0f */) +{ + if (pointer < 0 || pointer > TOUCH_MAX_POINTERS) + return false; + + CSingleLock lock(m_critical); + + m_pointers[pointer].last.copy(m_pointers[pointer].current); + + m_pointers[pointer].current.x = x; + m_pointers[pointer].current.y = y; + m_pointers[pointer].current.time = time; + if (size > 0.0f) + m_pointers[pointer].size = size; + + // calculate whether the pointer has moved at all + if (!m_pointers[pointer].moving) + { + CVector down = m_pointers[pointer].down; + CVector current = m_pointers[pointer].current; + CVector distance = down - current; + + if (distance.length() > m_pointers[pointer].size) + m_pointers[pointer].moving = true; + } + + return true; +} + +void CTouchInput::saveLastTouch() +{ + for (unsigned int pointer = 0; pointer < TOUCH_MAX_POINTERS; pointer++) + m_pointers[pointer].last.copy(m_pointers[pointer].current); +} + +void CTouchInput::handleMultiTouchGesture() +{ + handleZoomPinch(); +} + +void CTouchInput::handleZoomPinch() +{ + Pointer& primaryPointer = m_pointers[0]; + Pointer& secondaryPointer = m_pointers[1]; + + // calculate zoom/pinch + CVector primary = primaryPointer.down; + CVector secondary = secondaryPointer.down; + CVector diagonal = primary - secondary; + + float baseDiffLength = diagonal.length(); + if (baseDiffLength != 0.0f) + { + CVector primaryNow = primaryPointer.current; + CVector secondaryNow = secondaryPointer.current; + CVector diagonalNow = primaryNow - secondaryNow; + float curDiffLength = diagonalNow.length(); + + float centerX = (primary.x + secondary.x) / 2; + float centerY = (primary.y + secondary.y) / 2; + + float zoom = curDiffLength / baseDiffLength; + + OnZoomPinch(centerX, centerY, zoom); + } +} + +void CTouchInput::OnTimeout() +{ + CSingleLock lock(m_critical); + + switch (m_gestureState) + { + case TouchGestureSingleTouch: + setGestureState(TouchGestureSingleTouchHold); + + OnSingleTouchHold(m_pointers[0].down.x, m_pointers[0].down.y); + OnSingleLongPress(m_pointers[0].down.x, m_pointers[0].down.y); + break; + + case TouchGestureMultiTouchStart: + if (!m_pointers[0].moving && !m_pointers[1].moving) + { + setGestureState(TouchGestureMultiTouchHold); + + OnMultiTouchHold(m_pointers[0].down.x, m_pointers[0].down.y); + OnDoubleLongPress(m_pointers[0].down.x, m_pointers[0].down.y, m_pointers[1].down.x, m_pointers[1].down.y); + } + break; + + default: + break; + } +} + +void CTouchInput::OnTouchAbort() +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + m_handler->OnTouchAbort(); +} + +bool CTouchInput::OnSingleTouchStart(float x, float y) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnSingleTouchStart(x, y); + + return true; +} + +bool CTouchInput::OnSingleTouchHold(float x, float y) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnSingleTouchHold(x, y); + + return true; +} + +bool CTouchInput::OnSingleTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnSingleTouchMove(x, y, offsetX, offsetY, velocityX, velocityY); + + return true; +} + +bool CTouchInput::OnSingleTouchEnd(float x, float y) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnSingleTouchEnd(x, y); + + return true; +} + +bool CTouchInput::OnMultiTouchStart(float x, float y, int32_t pointers /* = 2 */) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnMultiTouchStart(x, y, pointers); + + return true; +} + +bool CTouchInput::OnMultiTouchDown(float x, float y, int32_t pointer) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnMultiTouchDown(x, y, pointer); + + return true; +} + +bool CTouchInput::OnMultiTouchHold(float x, float y, int32_t pointers /* = 2 */) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnMultiTouchHold(x, y, pointers); + + return true; +} + +bool CTouchInput::OnMultiTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY, int32_t pointer) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnMultiTouchMove(x, y, offsetX, offsetY, velocityX, velocityY, pointer); + + return true; +} + +bool CTouchInput::OnMultiTouchUp(float x, float y, int32_t pointer) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnMultiTouchUp(x, y, pointer); + + return true; +} + +bool CTouchInput::OnMultiTouchEnd(float x, float y, int32_t pointers /* = 2 */) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnMultiTouchEnd(x, y, pointers); + + return true; +} + +bool CTouchInput::OnTouchGesturePanStart(float x, float y) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnTouchGesturePanStart(x, y); + + return true; +} + +bool CTouchInput::OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnTouchGesturePan(x, y, offsetX, offsetY, velocityX, velocityY); + + return true; +} + +bool CTouchInput::OnTouchGesturePanEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + return m_handler->OnTouchGesturePanEnd(x, y, offsetX, offsetY, velocityX, velocityY); + + return true; +} + +void CTouchInput::OnSingleTap(float x, float y) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + m_handler->OnSingleTap(x, y); +} + +void CTouchInput::OnSingleLongPress(float x, float y) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + m_handler->OnSingleLongPress(x, y); +} + +void CTouchInput::OnDoubleTap(float x1, float y1, float x2, float y2) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + m_handler->OnDoubleTap(x1, y1, x2, y2); +} + +void CTouchInput::OnDoubleLongPress(float x1, float y1, float x2, float y2) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + m_handler->OnDoubleLongPress(x1, y1, x2, y2); +} + +void CTouchInput::OnZoomPinch(float centerX, float centerY, float zoomFactor) +{ + CLog::Log(LOGDEBUG, "%s", __FUNCTION__); + + if (m_handler) + m_handler->OnZoomPinch(centerX, centerY, zoomFactor); +} diff --git a/xbmc/input/TouchInput.h b/xbmc/input/TouchInput.h new file mode 100644 index 0000000000..a926b99385 --- /dev/null +++ b/xbmc/input/TouchInput.h @@ -0,0 +1,414 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "threads/CriticalSection.h" +#include "threads/Timer.h" +#include "utils/Vector.h" + +#define TOUCH_MAX_POINTERS 2 + +class ITouchHandler +{ +public: + virtual ~ITouchHandler() { } + + /*! + \brief A touch action has been aborted + */ + virtual void OnTouchAbort() { }; + + /*! + \brief A single touch has started + + \param x The x coordinate (with sub-pixel) of the touch + \param y The y coordinate (with sub-pixel) of the touch + \return True if the event was handled otherwise false + \sa OnSingleTap + */ + virtual bool OnSingleTouchStart(float x, float y) { return true; } + /*! + \brief A single touch has been held down for a certain amount of time + + \param x The x coordinate (with sub-pixel) of the touch + \param y The y coordinate (with sub-pixel) of the touch + \return True if the event was handled otherwise false + \sa OnSingleLongPress + */ + virtual bool OnSingleTouchHold(float x, float y) { return true; } + /*! + \brief A single touch has moved * + + \param x The x coordinate (with sub-pixel) of the current touch + \param y The y coordinate (with sub-pixel) of the current touch + \param offsetX The covered distance on the x axis (with sub-pixel) + \param offsetX The covered distance on the y axis (with sub-pixel) + \param velocityX The velocity of the gesture in x direction (pixels/second) + \param velocityX The velocity of the gesture in y direction (pixels/second) + \return True if the event was handled otherwise false + \sa OnTouchGesturePan + */ + virtual bool OnSingleTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY) { return true; } + /*! + \brief A single touch has been lifted + + \param x The x coordinate (with sub-pixel) of the touch + \param y The y coordinate (with sub-pixel) of the touch + \return True if the event was handled otherwise false + \sa OnSingleTap + */ + virtual bool OnSingleTouchEnd(float x, float y) { return true; } + + /*! + \brief A multi touch gesture has started + + \param x The x coordinate (with sub-pixel) of the touch + \param y The y coordinate (with sub-pixel) of the touch + \param pointers The number of pointers involved (default 2) + \return True if the event was handled otherwise false + */ + virtual bool OnMultiTouchStart(float x, float y, int32_t pointers = 2) { return true; } + /*! + \brief An additional touch has been performed + + \param x The x coordinate (with sub-pixel) of the touch + \param y The y coordinate (with sub-pixel) of the touch + \param pointer The pointer that has performed the touch + \return True if the event was handled otherwise false + */ + virtual bool OnMultiTouchDown(float x, float y, int32_t pointer) { return true; } + /*! + \brief Multiple simultaneous touches have been held down for a certain amount of time + + \param x The x coordinate (with sub-pixel) of the touch + \param y The y coordinate (with sub-pixel) of the touch + \param pointers The number of pointers involved (default 2) + \return True if the event was handled otherwise false + \sa OnDoubleLongPress + */ + virtual bool OnMultiTouchHold(float x, float y, int32_t pointers = 2) { return true; } + /*! + \brief A touch has moved + + \param x The x coordinate (with sub-pixel) of the current touch + \param y The y coordinate (with sub-pixel) of the current touch + \param offsetX The covered distance on the x axis (with sub-pixel) + \param offsetX The covered distance on the y axis (with sub-pixel) + \param velocityX The velocity of the gesture in x direction (pixels/second) + \param velocityX The velocity of the gesture in y direction (pixels/second) + \param pointer The pointer that has performed the touch + \return True if the event was handled otherwise false + */ + virtual bool OnMultiTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY, int32_t pointer) { return true; } + /*! + \brief A touch has been lifted (but there are still active touches) + + \param x The x coordinate (with sub-pixel) of the touch + \param y The y coordinate (with sub-pixel) of the touch + \param pointer The pointer that has performed the touch + \return True if the event was handled otherwise false + */ + virtual bool OnMultiTouchUp(float x, float y, int32_t pointer) { return true; } + /*! + \brief A multi touch gesture has ended (the last touch has been lifted) + + \param x The x coordinate (with sub-pixel) of the touch + \param y The y coordinate (with sub-pixel) of the touch + \param pointers The number of pointers involved (default 2) + \return True if the event was handled otherwise false + */ + virtual bool OnMultiTouchEnd(float x, float y, int32_t pointers = 2) { return true; } + + /*! + \brief A pan gesture with a single touch has been started + + \param x The x coordinate (with sub-pixel) of the initial touch + \param y The y coordinate (with sub-pixel) of the initial touch + \return True if the event was handled otherwise false + */ + virtual bool OnTouchGesturePanStart(float x, float y) { return true; } + /*! + \brief A pan gesture with a single touch is in progress + + \param x The x coordinate (with sub-pixel) of the current touch + \param y The y coordinate (with sub-pixel) of the current touch + \param offsetX The covered distance on the x axis (with sub-pixel) + \param offsetX The covered distance on the y axis (with sub-pixel) + \param velocityX The velocity of the gesture in x direction (pixels/second) + \param velocityX The velocity of the gesture in y direction (pixels/second) + \return True if the event was handled otherwise false + */ + virtual bool OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY) { return true; } + /*! + \brief A pan gesture with a single touch has ended + + \param x The x coordinate (with sub-pixel) of the current touch + \param y The y coordinate (with sub-pixel) of the current touch + \param offsetX The covered distance on the x axis (with sub-pixel) + \param offsetX The covered distance on the y axis (with sub-pixel) + \param velocityX The velocity of the gesture in x direction (pixels/second) + \param velocityX The velocity of the gesture in y direction (pixels/second) + \return True if the event was handled otherwise false + */ + virtual bool OnTouchGesturePanEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY) { return true; } + + // convenience events + /*! + \brief A tap with a single touch has been performed + + \param x The x coordinate (with sub-pixel) of the touch + \param y The y coordinate (with sub-pixel) of the touch + \return True if the event was handled otherwise false + */ + virtual void OnSingleTap(float x, float y) { } + /*! + \brief A single touch has been held down for a certain amount of time + + \param x The x coordinate (with sub-pixel) of the touch + \param y The y coordinate (with sub-pixel) of the touch + \return True if the event was handled otherwise false + \sa OnSingleTouchHold + */ + virtual void OnSingleLongPress(float x, float y) { } + /*! + \brief A tap with two simultaneous touches has been performed + + \param x1 The x coordinate (with sub-pixel) of the first touch + \param y1 The y coordinate (with sub-pixel) of the first touch + \param x2 The x coordinate (with sub-pixel) of the second touch + \param y2 The y coordinate (with sub-pixel) of the second touch + \return True if the event was handled otherwise false + \sa + */ + virtual void OnDoubleTap(float x1, float y1, float x2, float y2) { } + /*! + \brief Two simultaneous touches have been held down for a certain amount of time + + \param x1 The x coordinate (with sub-pixel) of the first touch + \param y1 The y coordinate (with sub-pixel) of the first touch + \param x2 The x coordinate (with sub-pixel) of the second touch + \param y2 The y coordinate (with sub-pixel) of the second touch + \return True if the event was handled otherwise false + \sa OnMultiTouchHold + */ + virtual void OnDoubleLongPress(float x1, float y1, float x2, float y2) { } + /*! + \brief Two simultaneous touches have been held down and moved to perform a zooming/pinching gesture + + \param centerX The x coordinate (with sub-pixel) of the center of the two touches + \param centerY The y coordinate (with sub-pixel) of the center of the two touches + \param zoomFactor The zoom (> 1.0) or pinch (< 1.0) factor of the two touches + \return True if the event was handled otherwise false + \sa + */ + virtual void OnZoomPinch(float centerX, float centerY, float zoomFactor) { } +}; + +class CTouchInput : private ITouchHandler, private ITimerCallback +{ +public: + typedef enum { + TouchEventAbort, + TouchEventDown, + TouchEventUp, + TouchEventMove + } TouchEvent; + + /*! + \brief Get an instance of the touch input manager + */ + static CTouchInput &Get(); + + /*! + \brief Register a touch input handler + + There can only be one touch input handler + active. + + \param touchHandler An instance of a touch handler implementing the ITouchHandler interface + */ + void RegisterHandler(ITouchHandler *touchHandler); + /*! + \brief Unregister the touch handler + */ + void UnregisterHandler(); + + /*! + \brief Set the timeout after which a touch turns into a touch hold + \param timeout Timeout in milliseconds + */ + void SetTouchHoldTimeout(int32_t timeout); + + /*! + \brief Handle a touch event + + Handles the given touch event at the given location. + This takes into account all the currently active pointers + which need to be updated before calling this method to + actually interprete and handle the changes in touch. + + \param event The actual touch event (abort, down, up, move) + \param x The x coordinate (with sub-pixel) of the touch + \param y The y coordinate (with sub-pixel) of the touch + \param time The time (in nanoseconds) when this touch occured + \param pointer The number of the touch pointer which caused this event (default 0) + \param size The size of the touch pointer (with sub-pixel) (default 0.0) + \return True if the event was handled otherwise false. + \sa Update + */ + bool Handle(TouchEvent event, float x, float y, int64_t time, int32_t pointer = 0, float size = 0.0f); + + /*! + \brief Update the coordinates of a pointer + + Depending on how a platform handles touch input and provides the necessary events + this method needs to be called at different times. If there's an event for every + touch action this method does not need to be called at all. If there's only a + touch event for the primary pointer (and no special events for any secondary + pointers in a multi touch gesture) this method should be called for every active + secondary pointer before calling Handle. + + \param pointer The number of the touch pointer which caused this event (default 0) + \param x The x coordinate (with sub-pixel) of the touch + \param y The y coordinate (with sub-pixel) of the touch + \param time The time (in nanoseconds) when this touch occured + \param size The size of the touch pointer (with sub-pixel) (default 0.0) + \return True if the pointer was updated otherwise false. + \sa Handle + */ + bool Update(int32_t pointer, float x, float y, int64_t time, float size = 0.0f); + +private: + // private construction, and no assignements; use the provided singleton methods + CTouchInput(); + CTouchInput(const CTouchInput&); + CTouchInput const& operator=(CTouchInput const&); + virtual ~CTouchInput(); + + void saveLastTouch(); + + void handleMultiTouchGesture(); + void handleZoomPinch(); + + // implementation of ITimerCallback + virtual void OnTimeout(); + + // implementation of ITouchHandler + virtual void OnTouchAbort(); + + virtual bool OnSingleTouchStart(float x, float y); + virtual bool OnSingleTouchHold(float x, float y); + virtual bool OnSingleTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY); + virtual bool OnSingleTouchEnd(float x, float y); + + virtual bool OnMultiTouchStart(float x, float y, int32_t pointers = 2); + virtual bool OnMultiTouchDown(float x, float y, int32_t pointer); + virtual bool OnMultiTouchHold(float x, float y, int32_t pointers = 2); + virtual bool OnMultiTouchMove(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY, int32_t pointer); + virtual bool OnMultiTouchUp(float x, float y, int32_t pointer); + virtual bool OnMultiTouchEnd(float x, float y, int32_t pointers = 2); + + virtual bool OnTouchGesturePanStart(float x, float y); + virtual bool OnTouchGesturePan(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY); + virtual bool OnTouchGesturePanEnd(float x, float y, float offsetX, float offsetY, float velocityX, float velocityY); + + // convenience events + virtual void OnSingleTap(float x, float y); + virtual void OnSingleLongPress(float x, float y); + virtual void OnDoubleTap(float x1, float y1, float x2, float y2); + virtual void OnDoubleLongPress(float x1, float y1, float x2, float y2); + virtual void OnZoomPinch(float centerX, float centerY, float zoomFactor); + + CCriticalSection m_critical; + + int32_t m_holdTimeout; + ITouchHandler *m_handler; + CTimer *m_holdTimer; + + class Touch : public CVector { + public: + Touch() { reset(); } + virtual ~Touch() { } + + virtual void reset() { CVector::reset(); time = -1; } + + bool valid() const { return x >= 0.0f && y >= 0.0f && time >= 0; } + void copy(const Touch &other) { x = other.x; y = other.y; time = other.time; } + + int64_t time; // in nanoseconds + }; + + class Pointer { + public: + Pointer() { reset(); } + + bool valid() const { return down.valid(); } + void reset() { down.reset(); last.reset(); moving = false; size = 0.0f; } + + bool velocity(float &velocityX, float &velocityY, bool fromLast = true) + { + Touch &from = last; + if (!fromLast) + from = down; + + velocityX = 0.0f; // number of pixels per second + velocityY = 0.0f; // number of pixels per second + + int64_t timeDiff = current.time - from.time; + if (timeDiff <= 0) + return false; + + velocityX = ((current.x - from.x) * 1000000000) / timeDiff; + velocityY = ((current.y - from.y) * 1000000000) / timeDiff; + return true; + } + + Touch down; + Touch last; + Touch current; + bool moving; + float size; + }; + + Pointer m_pointers[TOUCH_MAX_POINTERS]; + + typedef enum { + TouchGestureUnknown = 0, + // only primary pointer active but stationary so far + TouchGestureSingleTouch, + // primary pointer active but stationary for a certain time + TouchGestureSingleTouchHold, + // primary pointer moving + TouchGesturePan, + // at least two pointers active but stationary so far + TouchGestureMultiTouchStart, + // at least two pointers active but stationary for a certain time + TouchGestureMultiTouchHold, + // at least two pointers active and moving + TouchGestureMultiTouch, + // all but primary pointer have been lifted + TouchGestureMultiTouchDone + } TouchGestureState; + + TouchGestureState m_gestureState; + TouchGestureState m_gestureStateOld; + + void setGestureState(TouchGestureState gestureState) { m_gestureStateOld = m_gestureState; m_gestureState = gestureState; } +}; diff --git a/xbmc/input/linux/LinuxInputDevices.cpp b/xbmc/input/linux/LinuxInputDevices.cpp index 3d660839e5..70cf3d0cf9 100644 --- a/xbmc/input/linux/LinuxInputDevices.cpp +++ b/xbmc/input/linux/LinuxInputDevices.cpp @@ -92,6 +92,7 @@ typedef unsigned long kernel_ulong_t; #endif #include <linux/keyboard.h> +#include <linux/kd.h> #include <string.h> #include <unistd.h> @@ -101,7 +102,6 @@ typedef unsigned long kernel_ulong_t; #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/kd.h> #include <stdlib.h> #include <stdio.h> @@ -302,7 +302,7 @@ int ext_keycodes[] = { DIKS_OK, DIKS_SELECT, DIKS_GOTO, DIKS_CLEAR, typedef enum { - LI_DEVICE_ANY = 0, + LI_DEVICE_NONE = 0, LI_DEVICE_MOUSE = 1, LI_DEVICE_JOYSTICK = 2, LI_DEVICE_KEYBOARD = 4, @@ -726,9 +726,14 @@ XBMC_Event CLinuxInputDevice::ReadEvent() while (1) { + bzero(&levt, sizeof(levt)); + bzero(&devt, sizeof(devt)); devt.type = XBMC_NOEVENT; + if(m_devicePreferredId == LI_DEVICE_NONE) + return devt; + readlen = read(m_fd, &levt, sizeof(levt)); if (readlen <= 0) @@ -736,6 +741,13 @@ XBMC_Event CLinuxInputDevice::ReadEvent() //printf("read event readlen = %d device name %s m_fileName %s\n", readlen, m_deviceName, m_fileName.c_str()); + // sanity check if we realy read the event + if(readlen != sizeof(levt)) + { + printf("CLinuxInputDevice: read error : %s\n", strerror(errno)); + break; + } + if (!TranslateEvent(levt, devt)) continue; @@ -759,6 +771,53 @@ XBMC_Event CLinuxInputDevice::ReadEvent() return devt; } +void CLinuxInputDevice::SetupKeyboardAutoRepeat(int fd) +{ + bool enable = true; + +#if defined(HAS_AMLPLAYER) + // ignore the native aml driver named 'key_input', + // it is the dedicated power key handler (am_key_input) + if (strncmp(m_deviceName, "key_input", strlen("key_input")) == 0) + return; + // ignore the native aml driver named 'aml_keypad', + // it is the dedicated IR remote handler (amremote) + else if (strncmp(m_deviceName, "aml_keypad", strlen("aml_keypad")) == 0) + return; + + // turn off any keyboard autorepeat, there is a kernel bug + // where if the cpu is max'ed then key up is missed and + // we get a flood of EV_REP that never stop until next + // key down/up. Very nasty when seeking during video playback. + enable = false; +#endif + + if (enable) + { + int kbdrep[2] = { 400, 80 }; + ioctl(fd, EVIOCSREP, kbdrep); + } + else + { + struct input_event event; + memset(&event, 0, sizeof(event)); + + gettimeofday(&event.time, NULL); + event.type = EV_REP; + event.code = REP_DELAY; + event.value = 0; + write(fd, &event, sizeof(event)); + + gettimeofday(&event.time, NULL); + event.type = EV_REP; + event.code = REP_PERIOD; + event.value = 0; + write(fd, &event, sizeof(event)); + + CLog::Log(LOGINFO, "CLinuxInputDevice: auto key repeat disabled on device '%s'\n", m_deviceName); + } +} + /* * Fill device information. * Queries the input device and tries to classify it. @@ -890,7 +949,7 @@ void CLinuxInputDevice::GetInfo(int fd) else if (m_deviceType & LI_DEVICE_MOUSE) m_devicePreferredId = LI_DEVICE_MOUSE; else - m_devicePreferredId = LI_DEVICE_ANY; + m_devicePreferredId = LI_DEVICE_NONE; //printf("type: %d\n", m_deviceType); //printf("caps: %d\n", m_deviceCaps); @@ -980,9 +1039,6 @@ bool CLinuxInputDevice::Open() return false; } - int kbdrep[2] = { 400, 80 }; - ioctl(fd, EVIOCSREP, kbdrep); - // Set the socket to non-blocking int opts = 0; if ((opts = fcntl(fd, F_GETFL)) < 0) @@ -1003,6 +1059,9 @@ bool CLinuxInputDevice::Open() /* fill device info structure */ GetInfo(fd); + if (m_deviceType & LI_DEVICE_KEYBOARD) + SetupKeyboardAutoRepeat(fd); + m_fd = fd; m_vt_fd = -1; diff --git a/xbmc/interfaces/Builtins.cpp b/xbmc/interfaces/Builtins.cpp index 1c2f923e41..4921195b5f 100644 --- a/xbmc/interfaces/Builtins.cpp +++ b/xbmc/interfaces/Builtins.cpp @@ -22,13 +22,14 @@ #include "system.h" #include "utils/AlarmClock.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "Autorun.h" #include "Builtins.h" #include "input/ButtonTranslator.h" #include "FileItem.h" #include "addons/GUIDialogAddonSettings.h" #include "dialogs/GUIDialogFileBrowser.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "dialogs/GUIDialogKaiToast.h" #include "music/dialogs/GUIDialogMusicScan.h" #include "dialogs/GUIDialogNumeric.h" @@ -53,6 +54,7 @@ #include "utils/StringUtils.h" #include "utils/URIUtils.h" #include "Util.h" +#include "URL.h" #include "filesystem/PluginDirectory.h" #ifdef HAS_FILESYSTEM_RAR @@ -86,6 +88,7 @@ #endif #include <vector> +#include "xbmc/settings/AdvancedSettings.h" using namespace std; using namespace XFILE; @@ -104,21 +107,22 @@ typedef struct const BUILT_IN commands[] = { { "Help", false, "This help message" }, - { "Reboot", false, "Reboot the xbox (power cycle)" }, - { "Restart", false, "Restart the xbox (power cycle)" }, - { "ShutDown", false, "Shutdown the xbox" }, + { "Reboot", false, "Reboot the system" }, + { "Restart", false, "Restart the system (same as reboot)" }, + { "ShutDown", false, "Shutdown the system" }, { "Powerdown", false, "Powerdown system" }, { "Quit", false, "Quit XBMC" }, { "Hibernate", false, "Hibernates the system" }, { "Suspend", false, "Suspends the system" }, { "RestartApp", false, "Restart XBMC" }, { "Minimize", false, "Minimize XBMC" }, - { "Reset", false, "Reset the xbox (warm reboot)" }, + { "Reset", false, "Reset the system (same as reboot)" }, { "Mastermode", false, "Control master mode" }, { "ActivateWindow", true, "Activate the specified window" }, { "ReplaceWindow", true, "Replaces the current window with the new one" }, { "TakeScreenshot", false, "Takes a Screenshot" }, { "RunScript", true, "Run the specified script" }, + { "StopScript", true, "Stop the script by ID or path, if running" }, #if defined(TARGET_DARWIN) { "RunAppleScript", true, "Run the specified AppleScript command" }, #endif @@ -206,6 +210,7 @@ const BUILT_IN commands[] = { { "LCD.Resume", false, "Resumes LCDproc" }, #endif { "VideoLibrary.Search", false, "Brings up a search dialog which will search the library" }, + { "toggledebug", false, "Enables/disables debug mode" }, }; bool CBuiltins::HasCommand(const CStdString& execString) @@ -243,37 +248,37 @@ int CBuiltins::Execute(const CStdString& execString) CStdString parameter = params.size() ? params[0] : ""; CStdString strParameterCaseIntact = parameter; - if (execute.Equals("reboot") || execute.Equals("restart")) //Will reboot the xbox, aka cold reboot + if (execute.Equals("reboot") || execute.Equals("restart") || execute.Equals("reset")) //Will reboot the system { - g_application.getApplicationMessenger().Restart(); + CApplicationMessenger::Get().Restart(); } else if (execute.Equals("shutdown")) { - g_application.getApplicationMessenger().Shutdown(); + CApplicationMessenger::Get().Shutdown(); } else if (execute.Equals("powerdown")) { - g_application.getApplicationMessenger().Powerdown(); + CApplicationMessenger::Get().Powerdown(); } else if (execute.Equals("restartapp")) { - g_application.getApplicationMessenger().RestartApp(); + CApplicationMessenger::Get().RestartApp(); } else if (execute.Equals("hibernate")) { - g_application.getApplicationMessenger().Hibernate(); + CApplicationMessenger::Get().Hibernate(); } else if (execute.Equals("suspend")) { - g_application.getApplicationMessenger().Suspend(); + CApplicationMessenger::Get().Suspend(); } else if (execute.Equals("quit")) { - g_application.getApplicationMessenger().Quit(); + CApplicationMessenger::Get().Quit(); } else if (execute.Equals("minimize")) { - g_application.getApplicationMessenger().Minimize(); + CApplicationMessenger::Get().Minimize(); } else if (execute.Equals("loadprofile")) { @@ -311,10 +316,6 @@ int CBuiltins::Execute(const CStdString& execString) { CUtil::TakeScreenshot(); } - else if (execute.Equals("reset")) //Will reset the xbox, aka soft reset - { - g_application.getApplicationMessenger().Reset(); - } else if (execute.Equals("activatewindow") || execute.Equals("replacewindow")) { // get the parameters @@ -386,15 +387,28 @@ int CBuiltins::Execute(const CStdString& execString) Cocoa_DoAppleScript(strParameterCaseIntact.c_str()); } #endif + else if (execute.Equals("stopscript")) + { +#ifdef HAS_PYTHON + CStdString scriptpath(params[0]); + + // Test to see if the param is an addon ID + AddonPtr script; + if (CAddonMgr::Get().GetAddon(params[0], script)) + scriptpath = script->LibPath(); + + g_pythonParser.StopScript(scriptpath); +#endif + } else if (execute.Equals("system.exec")) { - g_application.getApplicationMessenger().Minimize(); - g_application.getApplicationMessenger().ExecOS(parameter, false); + CApplicationMessenger::Get().Minimize(); + CApplicationMessenger::Get().ExecOS(parameter, false); } else if (execute.Equals("system.execwait")) { - g_application.getApplicationMessenger().Minimize(); - g_application.getApplicationMessenger().ExecOS(parameter, true); + CApplicationMessenger::Get().Minimize(); + CApplicationMessenger::Get().ExecOS(parameter, true); } else if (execute.Equals("resolution")) { @@ -712,7 +726,7 @@ int CBuiltins::Execute(const CStdString& execString) { #ifdef HAS_WEB_SERVER_BROADCAST if (m_pXbmcHttp && g_settings.m_HttpApiBroadcastLevel>=1) - g_application.getApplicationMessenger().HttpApi(g_application.m_pPlayer->IsRecording()?"broadcastlevel; RecordStopping;1":"broadcastlevel; RecordStarting;1"); + CApplicationMessenger::Get().HttpApi(g_application.m_pPlayer->IsRecording()?"broadcastlevel; RecordStopping;1":"broadcastlevel; RecordStarting;1"); #endif g_application.m_pPlayer->Record(!g_application.m_pPlayer->IsRecording()); } @@ -833,7 +847,7 @@ int CBuiltins::Execute(const CStdString& execString) { if(params.size() > 1 && params[1].Equals("showVolumeBar")) { - g_application.getApplicationMessenger().ShowVolumeBar(oldVolume < volume); + CApplicationMessenger::Get().ShowVolumeBar(oldVolume < volume); } } } @@ -1000,7 +1014,8 @@ int CBuiltins::Execute(const CStdString& execString) int iTheme = -1; // find current theme - if (!g_guiSettings.GetString("lookandfeel.skintheme").Equals("skindefault")) + if (!g_guiSettings.GetString("lookandfeel.skintheme").Equals("SKINDEFAULT")) + { for (unsigned int i=0;i<vecTheme.size();++i) { CStdString strTmpTheme(g_guiSettings.GetString("lookandfeel.skintheme")); @@ -1011,6 +1026,7 @@ int CBuiltins::Execute(const CStdString& execString) break; } } + } int iParam = atoi(parameter.c_str()); if (iParam == 0 || iParam == 1) @@ -1022,15 +1038,16 @@ int CBuiltins::Execute(const CStdString& execString) if (iTheme < -1) iTheme = vecTheme.size()-1; - CStdString strSkinTheme; - if (iTheme==-1) - g_guiSettings.SetString("lookandfeel.skintheme","skindefault"); - else - g_guiSettings.SetString("lookandfeel.skintheme",strSkinTheme); + CStdString strSkinTheme = "SKINDEFAULT"; + if (iTheme != -1 && iTheme < (int)vecTheme.size()) + strSkinTheme = vecTheme[iTheme]; + g_guiSettings.SetString("lookandfeel.skintheme", strSkinTheme); // also set the default color theme - g_guiSettings.SetString("lookandfeel.skincolors", URIUtils::ReplaceExtension(strSkinTheme, ".xml")); - + CStdString colorTheme(URIUtils::ReplaceExtension(strSkinTheme, ".xml")); + if (colorTheme.Equals("Textures.xml")) + colorTheme = "defaults.xml"; + g_guiSettings.SetString("lookandfeel.skincolors", colorTheme); g_application.ReloadSkin(); } else if (execute.Equals("skin.setstring") || execute.Equals("skin.setimage") || execute.Equals("skin.setfile") || @@ -1055,7 +1072,7 @@ int CBuiltins::Execute(const CStdString& execString) g_mediaManager.GetLocalDrives(localShares); if (execute.Equals("skin.setstring")) { - if (CGUIDialogKeyboard::ShowAndGetInput(value, g_localizeStrings.Get(1029), true)) + if (CGUIKeyboardFactory::ShowAndGetInput(value, g_localizeStrings.Get(1029), true)) g_settings.SetSkinString(string, value); } else if (execute.Equals("skin.setnumeric")) @@ -1430,7 +1447,7 @@ int CBuiltins::Execute(const CStdString& execString) if (CButtonTranslator::TranslateActionString(params[0].c_str(), actionID)) { int windowID = params.size() == 2 ? CButtonTranslator::TranslateWindow(params[1]) : WINDOW_INVALID; - g_application.getApplicationMessenger().SendAction(CAction(actionID), windowID); + CApplicationMessenger::Get().SendAction(CAction(actionID), windowID); } } else if (execute.Equals("setproperty") && params.size() >= 2) @@ -1553,8 +1570,13 @@ int CBuiltins::Execute(const CStdString& execString) CGUIMessage msg(GUI_MSG_SEARCH, 0, 0, 0); g_windowManager.SendMessage(msg, WINDOW_VIDEO_NAV); } + else if (execute.Equals("toggledebug")) + { + bool debug = g_guiSettings.GetBool("debug.showloginfo"); + g_guiSettings.SetBool("debug.showloginfo", !debug); + g_advancedSettings.SetDebugMode(!debug); + } else return -1; return 0; } - diff --git a/xbmc/interfaces/http-api/HttpApi.cpp b/xbmc/interfaces/http-api/HttpApi.cpp index 25144bfd92..16ad9e9f74 100644 --- a/xbmc/interfaces/http-api/HttpApi.cpp +++ b/xbmc/interfaces/http-api/HttpApi.cpp @@ -21,17 +21,17 @@ CStdString CHttpApi::MethodCall(CStdString &command, CStdString ¶meter) int cnt=0; if (!parameter.IsEmpty()) - g_application.getApplicationMessenger().HttpApi(command + "; " + parameter, true); + CApplicationMessenger::Get().HttpApi(command + "; " + parameter, true); else - g_application.getApplicationMessenger().HttpApi(command, true); + CApplicationMessenger::Get().HttpApi(command, true); //wait for response - max 20s Sleep(0); - CStdString response = g_application.getApplicationMessenger().GetResponse(); + CStdString response = CApplicationMessenger::Get().GetResponse(); while (response=="[No response yet]" && cnt++<200 && !g_application.m_bStop) { - response=g_application.getApplicationMessenger().GetResponse(); + response=CApplicationMessenger::Get().GetResponse(); CLog::Log(LOGDEBUG, "HttpApi: waiting %d", cnt); Sleep(100); } diff --git a/xbmc/interfaces/http-api/Makefile b/xbmc/interfaces/http-api/Makefile index 63e1a2a322..d3651614c2 100644 --- a/xbmc/interfaces/http-api/Makefile +++ b/xbmc/interfaces/http-api/Makefile @@ -3,4 +3,4 @@ SRCS=HttpApi.cpp XBMChttp.cpp LIB=http-api.a include ../../../Makefile.include - +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/interfaces/http-api/XBMChttp.cpp b/xbmc/interfaces/http-api/XBMChttp.cpp index 6ed17197cb..c366a9f2c9 100644 --- a/xbmc/interfaces/http-api/XBMChttp.cpp +++ b/xbmc/interfaces/http-api/XBMChttp.cpp @@ -11,6 +11,7 @@ #include "threads/SystemClock.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "XBMCConfiguration.h" #include "XBMChttp.h" //#include "includes.h" @@ -20,6 +21,7 @@ #include "Util.h" #include "PlayListPlayer.h" #include "playlists/PlayList.h" +#include "filesystem/CurlFile.h" #include "filesystem/HDDirectory.h" #include "filesystem/CDDADirectory.h" #include "filesystem/SpecialProtocol.h" @@ -51,6 +53,7 @@ #include "utils/log.h" #include "TextureCache.h" #include "ThumbLoader.h" +#include "URL.h" #ifdef _WIN32 extern "C" FILE *fopen_utf8(const char *_Filename, const char *_Mode); @@ -357,12 +360,12 @@ int CXbmcHttp::SetResponse(const CStdString &response) if (response.length()>=closeTag.length()) { if ((response.Right(closeTag.length())!=closeTag) && closeFinalTag) - return g_application.getApplicationMessenger().SetResponse(response+closeTag); + return CApplicationMessenger::Get().SetResponse(response+closeTag); } else if (closeFinalTag) - return g_application.getApplicationMessenger().SetResponse(response+closeTag); - return g_application.getApplicationMessenger().SetResponse(response); + return CApplicationMessenger::Get().SetResponse(response+closeTag); + return CApplicationMessenger::Get().SetResponse(response); } int CXbmcHttp::displayDir(int numParas, CStdString paras[]) @@ -467,7 +470,7 @@ void CXbmcHttp::SetCurrentMediaItem(CFileItem& newItem) // If we have tag information, ... if (newItem.HasMusicInfoTag() && newItem.GetMusicInfoTag()->Loaded()) { - g_infoManager.SetCurrentSongTag(*newItem.GetMusicInfoTag()); + CApplicationMessenger::Get().SetCurrentSongTag(*newItem.GetMusicInfoTag()); } } @@ -536,7 +539,7 @@ bool CXbmcHttp::LoadPlayList(CStdString strPath, int iPlaylist, bool clearList, if ((playlist.size() == 1) && (autoStart)) { // just 1 song? then play it (no need to have a playlist of 1 song) - g_application.getApplicationMessenger().MediaPlay(playlistItem->GetPath()); + CApplicationMessenger::Get().MediaPlay(playlistItem->GetPath()); return true; } @@ -550,7 +553,7 @@ bool CXbmcHttp::LoadPlayList(CStdString strPath, int iPlaylist, bool clearList, { g_playlistPlayer.SetCurrentPlaylist(iPlaylist); g_playlistPlayer.Reset(); - g_application.getApplicationMessenger().PlayListPlayerPlay(); + CApplicationMessenger::Get().PlayListPlayerPlay(); return true; } else @@ -1030,12 +1033,11 @@ int CXbmcHttp::xbmcAddToPlayListFromDB(int numParas, CStdString paras[]) if (type.Equals("songs")) { playList = PLAYLIST_MUSIC; - where = " where " + where; CMusicDatabase musicdatabase; if (!musicdatabase.Open()) return SetResponse(openTag+ "Error: Could not open music database"); - musicdatabase.GetSongsByWhere("", where, filelist); + musicdatabase.GetSongsByWhere("musicdb://4/", where, filelist); musicdatabase.Close(); } else if (type.Equals("movies") || @@ -1825,7 +1827,7 @@ int CXbmcHttp::xbmcPlayerPlayFile(int numParas, CStdString paras[]) } else { - g_application.getApplicationMessenger().MediaPlay(paras[0]); + CApplicationMessenger::Get().MediaPlay(paras[0]); if(g_application.IsPlaying()) return SetResponse(openTag+"OK"); } @@ -2108,7 +2110,7 @@ int CXbmcHttp::xbmcAction(int numParas, CStdString paras[], int theAction) pSlideShow->OnAction(CAction(ACTION_PAUSE)); } else - g_application.getApplicationMessenger().MediaPause(); + CApplicationMessenger::Get().MediaPause(); return SetResponse(openTag+"OK"); break; case 2: @@ -2119,7 +2121,7 @@ int CXbmcHttp::xbmcAction(int numParas, CStdString paras[], int theAction) pSlideShow->OnAction(CAction(ACTION_STOP)); } else - g_application.getApplicationMessenger().MediaStop(); + CApplicationMessenger::Get().MediaStop(); return SetResponse(openTag+"OK"); break; case 3: @@ -2392,7 +2394,7 @@ int CXbmcHttp::xbmcSetFile(int numParas, CStdString paras[]) int CXbmcHttp::xbmcCopyFile(int numParas, CStdString paras[]) //parameter = srcFilename ; destFilename -// both file names are relative to the XBox not the calling client +// both file names are relative to the server, not the calling client { if (numParas<2) return SetResponse(openTag+"Error:Missing parameter"); @@ -2480,7 +2482,7 @@ int CXbmcHttp::xbmcShowPicture(int numParas, CStdString paras[]) { if (!playableFile(paras[0])) return SetResponse(openTag+"Error:Unable to open file"); - g_application.getApplicationMessenger().PictureShow(paras[0]); + CApplicationMessenger::Get().PictureShow(paras[0]); return SetResponse(openTag+"OK"); } } @@ -2505,7 +2507,7 @@ int CXbmcHttp::xbmcExecBuiltIn(int numParas, CStdString paras[]) return SetResponse(openTag+"Error:Missing parameter"); else { - g_application.getApplicationMessenger().ExecBuiltIn(paras[0]); + CApplicationMessenger::Get().ExecBuiltIn(paras[0]); return SetResponse(openTag+"OK"); } } @@ -3000,8 +3002,8 @@ int CXbmcHttp::xbmcHelp() { CStdString output; output="<p><b>XBMC HTTP API Commands</b></p><p>There are two alternative but equivalent syntax forms:</p>"; - output+="<p><b>Syntax 1: http://xbox/xbmcCmds/xbmcHttp?command=</b>command<b>&parameter=</b>first_parameter<b>;</b>second_parameter<b>;...</b></p>"; - output+="<p><b>Syntax 2: http://xbox/xbmcCmds/xbmcHttp?command=</b>command<b>(</b>first_parameter<b>;</b>second_parameter<b>;...</b><b>)</b></p>"; + output+="<p><b>Syntax 1: http://xbmc-host/xbmcCmds/xbmcHttp?command=</b>command<b>&parameter=</b>first_parameter<b>;</b>second_parameter<b>;...</b></p>"; + output+="<p><b>Syntax 2: http://xbmc-host/xbmcCmds/xbmcHttp?command=</b>command<b>(</b>first_parameter<b>;</b>second_parameter<b>;...</b><b>)</b></p>"; output+="<p>Note the use of the semi colon to separate multiple parameters.</p><p>The commands are case insensitive.</p>"; output+= "<p>The full documentation can be found here: <a href=\"http://wiki.xbmc.org/index.php?title=WebServerHTTP-API\">http://wiki.xbmc.org/index.php?title=WebServerHTTP-API</a></p>"; return SetResponse(output); diff --git a/xbmc/interfaces/json-rpc/ApplicationOperations.cpp b/xbmc/interfaces/json-rpc/ApplicationOperations.cpp index 3f8110f592..0eba658731 100644 --- a/xbmc/interfaces/json-rpc/ApplicationOperations.cpp +++ b/xbmc/interfaces/json-rpc/ApplicationOperations.cpp @@ -85,7 +85,7 @@ JSONRPC_STATUS CApplicationOperations::SetVolume(const CStdString &method, ITran else return InvalidParams; - g_application.getApplicationMessenger().ShowVolumeBar(up); + CApplicationMessenger::Get().ShowVolumeBar(up); return GetPropertyValue("volume", result); } @@ -94,7 +94,7 @@ JSONRPC_STATUS CApplicationOperations::SetMute(const CStdString &method, ITransp { if ((parameterObject["mute"].isString() && parameterObject["mute"].asString().compare("toggle") == 0) || (parameterObject["mute"].isBoolean() && parameterObject["mute"].asBoolean() != g_application.IsMuted())) - g_application.getApplicationMessenger().SendAction(CAction(ACTION_MUTE)); + CApplicationMessenger::Get().SendAction(CAction(ACTION_MUTE)); else if (!parameterObject["mute"].isBoolean() && !parameterObject["mute"].isString()) return InvalidParams; @@ -103,7 +103,7 @@ JSONRPC_STATUS CApplicationOperations::SetMute(const CStdString &method, ITransp JSONRPC_STATUS CApplicationOperations::Quit(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { - g_application.getApplicationMessenger().Quit(); + CApplicationMessenger::Get().Quit(); return ACK; } diff --git a/xbmc/interfaces/json-rpc/AudioLibrary.cpp b/xbmc/interfaces/json-rpc/AudioLibrary.cpp index 929737b00e..56029e6783 100644 --- a/xbmc/interfaces/json-rpc/AudioLibrary.cpp +++ b/xbmc/interfaces/json-rpc/AudioLibrary.cpp @@ -29,7 +29,7 @@ #include "music/Album.h" #include "music/Song.h" #include "music/Artist.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "filesystem/Directory.h" #include "filesystem/File.h" #include "settings/GUISettings.h" @@ -44,23 +44,41 @@ JSONRPC_STATUS CAudioLibrary::GetArtists(const CStdString &method, ITransportLay if (!musicdatabase.Open()) return InternalError; - int genreID = (int)parameterObject["genreid"].asInteger(); - - // Add "artist" to "properties" array by default - CVariant param = parameterObject; - if (!param.isMember("properties")) - param["properties"] = CVariant(CVariant::VariantTypeArray); - param["properties"].append("artist"); + CMusicDbUrl musicUrl; + musicUrl.FromString("musicdb://2/"); + int genreID = -1, albumID = -1, songID = -1; + const CVariant &filter = parameterObject["filter"]; + if (filter.isMember("genreid")) + genreID = (int)filter["genreid"].asInteger(); + if (filter.isMember("genre")) + musicUrl.AddOption("genre", filter["genre"].asString()); + if (filter.isMember("albumid")) + albumID = (int)filter["albumid"].asInteger(); + if (filter.isMember("album")) + musicUrl.AddOption("album", filter["album"].asString()); + if (filter.isMember("songid")) + songID = (int)filter["songid"].asInteger(); bool albumArtistsOnly = !g_guiSettings.GetBool("musiclibrary.showcompilationartists"); if (parameterObject["albumartistsonly"].isBoolean()) albumArtistsOnly = parameterObject["albumartistsonly"].asBoolean(); + SortDescription sorting; + ParseLimits(parameterObject, sorting.limitStart, sorting.limitEnd); + if (!ParseSorting(parameterObject, sorting.sortBy, sorting.sortOrder, sorting.sortAttributes)) + return InvalidParams; + CFileItemList items; - if (!musicdatabase.GetArtistsNav("musicdb://2/", items, genreID, albumArtistsOnly)) + if (!musicdatabase.GetArtistsNav(musicUrl.ToString(), items, albumArtistsOnly, genreID, albumID, songID, sorting)) return InternalError; - HandleFileItemList("artistid", false, "artists", items, param, result); + // Add "artist" to "properties" array by default + CVariant param = parameterObject; + if (!param.isMember("properties")) + param["properties"] = CVariant(CVariant::VariantTypeArray); + param["properties"].append("artist"); + + HandleFileItemList("artistid", false, "artists", items, param, result, false); return OK; } @@ -68,17 +86,28 @@ JSONRPC_STATUS CAudioLibrary::GetArtistDetails(const CStdString &method, ITransp { int artistID = (int)parameterObject["artistid"].asInteger(); + CMusicDbUrl musicUrl; + if (!musicUrl.FromString("musicdb://2/")) + return InternalError; + CMusicDatabase musicdatabase; if (!musicdatabase.Open()) return InternalError; + musicUrl.AddOption("artistid", artistID); + CFileItemList items; - CStdString where; - where.Format("idArtist = %d", artistID); - if (!musicdatabase.GetArtistsByWhere("musicdb://2/", where, items) || items.Size() != 1) + CDatabase::Filter filter; + if (!musicdatabase.GetArtistsByWhere(musicUrl.ToString(), filter, items) || items.Size() != 1) return InvalidParams; - HandleFileItem("artistid", false, "artistdetails", items[0], parameterObject, parameterObject["properties"], result, false); + // Add "artist" to "properties" array by default + CVariant param = parameterObject; + if (!param.isMember("properties")) + param["properties"] = CVariant(CVariant::VariantTypeArray); + param["properties"].append("artist"); + + HandleFileItem("artistid", false, "artistdetails", items[0], parameterObject, param["properties"], result, false); return OK; } @@ -88,8 +117,18 @@ JSONRPC_STATUS CAudioLibrary::GetAlbums(const CStdString &method, ITransportLaye if (!musicdatabase.Open()) return InternalError; - int artistID = (int)parameterObject["artistid"].asInteger(); - int genreID = (int)parameterObject["genreid"].asInteger(); + CMusicDbUrl musicUrl; + musicUrl.FromString("musicdb://3/"); + int artistID = -1, genreID = -1; + const CVariant &filter = parameterObject["filter"]; + if (filter.isMember("artistid")) + artistID = (int)filter["artistid"].asInteger(); + if (filter.isMember("artist")) + musicUrl.AddOption("artist", filter["artist"].asString()); + if (filter.isMember("genreid")) + genreID = (int)filter["genreid"].asInteger(); + if (filter.isMember("genre")) + musicUrl.AddOption("genre", filter["genre"].asString()); SortDescription sorting; ParseLimits(parameterObject, sorting.limitStart, sorting.limitEnd); @@ -97,7 +136,7 @@ JSONRPC_STATUS CAudioLibrary::GetAlbums(const CStdString &method, ITransportLaye return InvalidParams; CFileItemList items; - if (!musicdatabase.GetAlbumsNav("musicdb://3/", items, genreID, artistID, -1, -1, sorting)) + if (!musicdatabase.GetAlbumsNav(musicUrl.ToString(), items, genreID, artistID, sorting)) return InternalError; int size = items.Size(); @@ -137,9 +176,22 @@ JSONRPC_STATUS CAudioLibrary::GetSongs(const CStdString &method, ITransportLayer if (!musicdatabase.Open()) return InternalError; - int artistID = (int)parameterObject["artistid"].asInteger(); - int albumID = (int)parameterObject["albumid"].asInteger(); - int genreID = (int)parameterObject["genreid"].asInteger(); + CMusicDbUrl musicUrl; + musicUrl.FromString("musicdb://4/"); + int genreID = -1, albumID = -1, artistID = -1; + const CVariant &filter = parameterObject["filter"]; + if (filter.isMember("artistid")) + artistID = (int)filter["artistid"].asInteger(); + if (filter.isMember("artist")) + musicUrl.AddOption("artist", filter["artist"].asString()); + if (filter.isMember("genreid")) + genreID = (int)filter["genreid"].asInteger(); + if (filter.isMember("genre")) + musicUrl.AddOption("genre", filter["genre"].asString()); + if (filter.isMember("albumid")) + albumID = (int)filter["albumid"].asInteger(); + if (filter.isMember("album")) + musicUrl.AddOption("album", filter["album"].asString()); SortDescription sorting; ParseLimits(parameterObject, sorting.limitStart, sorting.limitEnd); @@ -147,7 +199,7 @@ JSONRPC_STATUS CAudioLibrary::GetSongs(const CStdString &method, ITransportLayer return InvalidParams; CFileItemList items; - if (!musicdatabase.GetSongsNav("musicdb://4/", items, genreID, artistID, albumID, sorting)) + if (!musicdatabase.GetSongsNav(musicUrl.ToString(), items, genreID, artistID, albumID, sorting)) return InternalError; int size = items.Size(); @@ -231,7 +283,7 @@ JSONRPC_STATUS CAudioLibrary::GetRecentlyPlayedAlbums(const CStdString &method, for (unsigned int index = 0; index < albums.size(); index++) { CStdString path; - path.Format("musicdb://8/%i/", albums[index].idAlbum); + path.Format("musicdb://7/%i/", albums[index].idAlbum); CFileItemPtr item; FillAlbumItem(albums[index], path, item); @@ -415,7 +467,7 @@ JSONRPC_STATUS CAudioLibrary::Scan(const CStdString &method, ITransportLayer *tr else cmd.Format("updatelibrary(music, %s)", directory.c_str()); - g_application.getApplicationMessenger().ExecBuiltIn(cmd); + CApplicationMessenger::Get().ExecBuiltIn(cmd); return ACK; } @@ -429,13 +481,13 @@ JSONRPC_STATUS CAudioLibrary::Export(const CStdString &method, ITransportLayer * parameterObject["options"]["images"].asBoolean() ? "true" : "false", parameterObject["options"]["overwrite"].asBoolean() ? "true" : "false"); - g_application.getApplicationMessenger().ExecBuiltIn(cmd); + CApplicationMessenger::Get().ExecBuiltIn(cmd); return ACK; } JSONRPC_STATUS CAudioLibrary::Clean(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { - g_application.getApplicationMessenger().ExecBuiltIn("cleanlibrary(music)"); + CApplicationMessenger::Get().ExecBuiltIn("cleanlibrary(music)"); return ACK; } @@ -486,7 +538,7 @@ bool CAudioLibrary::FillFileItemList(const CVariant ¶meterObject, CFileItemL } if (artistID != -1 || albumID != -1 || genreID != -1) - success |= musicdatabase.GetSongsNav("", list, genreID, artistID, albumID); + success |= musicdatabase.GetSongsNav("musicdb://4/", list, genreID, artistID, albumID); int songID = (int)parameterObject["songid"].asInteger(-1); if (songID != -1) diff --git a/xbmc/interfaces/json-rpc/FileItemHandler.cpp b/xbmc/interfaces/json-rpc/FileItemHandler.cpp index 6026b409d7..9fe73cba60 100644 --- a/xbmc/interfaces/json-rpc/FileItemHandler.cpp +++ b/xbmc/interfaces/json-rpc/FileItemHandler.cpp @@ -36,6 +36,7 @@ #include "filesystem/File.h" #include "TextureCache.h" #include "ThumbLoader.h" +#include "Util.h" using namespace MUSIC_INFO; using namespace JSONRPC; @@ -66,12 +67,11 @@ void CFileItemHandler::FillDetails(ISerializable* info, CFileItemPtr item, const result["albumlabel"] = item->GetProperty("album_label"); continue; } - /* This would break backwards compatibility to JSON-RPC API v4 if (item->HasProperty("album_" + field + "_array")) { result[field] = item->GetProperty("album_" + field + "_array"); continue; - }*/ + } if (item->HasProperty("album_" + field)) { result[field] = item->GetProperty("album_" + field); @@ -79,12 +79,11 @@ void CFileItemHandler::FillDetails(ISerializable* info, CFileItemPtr item, const } } - /* This would break backwards compatibility to JSON-RPC API v4 if (item->HasProperty("artist_" + field + "_array")) { result[field] = item->GetProperty("artist_" + field + "_array"); continue; - }*/ + } if (item->HasProperty("artist_" + field)) { result[field] = item->GetProperty("artist_" + field); diff --git a/xbmc/interfaces/json-rpc/GUIOperations.cpp b/xbmc/interfaces/json-rpc/GUIOperations.cpp index 0bf77b27a0..d84aa97703 100644 --- a/xbmc/interfaces/json-rpc/GUIOperations.cpp +++ b/xbmc/interfaces/json-rpc/GUIOperations.cpp @@ -21,6 +21,7 @@ #include "GUIOperations.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "GUIInfoManager.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogKaiToast.h" @@ -76,7 +77,7 @@ JSONRPC_STATUS CGUIOperations::SetFullscreen(const CStdString &method, ITranspor parameterObject["fullscreen"].asString().compare("toggle") == 0) || (parameterObject["fullscreen"].isBoolean() && parameterObject["fullscreen"].asBoolean() != g_application.IsFullScreen())) - g_application.getApplicationMessenger().SendAction(CAction(ACTION_SHOW_GUI)); + CApplicationMessenger::Get().SendAction(CAction(ACTION_SHOW_GUI)); else if (!parameterObject["fullscreen"].isBoolean() && !parameterObject["fullscreen"].isString()) return InvalidParams; diff --git a/xbmc/interfaces/json-rpc/InputOperations.cpp b/xbmc/interfaces/json-rpc/InputOperations.cpp index e7d67d5857..24882292e8 100644 --- a/xbmc/interfaces/json-rpc/InputOperations.cpp +++ b/xbmc/interfaces/json-rpc/InputOperations.cpp @@ -21,6 +21,7 @@ #include "InputOperations.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "guilib/GUIAudioManager.h" #include "guilib/GUIWindow.h" #include "guilib/GUIWindowManager.h" @@ -79,7 +80,7 @@ JSONRPC_STATUS CInputOperations::SendAction(int actionID, bool wakeScreensaver / { g_application.ResetSystemIdleTimer(); g_audioManager.PlayActionSound(actionID); - g_application.getApplicationMessenger().SendAction(CAction(actionID), WINDOW_INVALID, waitResult); + CApplicationMessenger::Get().SendAction(CAction(actionID), WINDOW_INVALID, waitResult); } return ACK; } @@ -87,7 +88,7 @@ JSONRPC_STATUS CInputOperations::SendAction(int actionID, bool wakeScreensaver / JSONRPC_STATUS CInputOperations::activateWindow(int windowID) { if(!handleScreenSaver()) - g_application.getApplicationMessenger().ActivateWindow(windowID, std::vector<CStdString>(), false); + CApplicationMessenger::Get().ActivateWindow(windowID, std::vector<CStdString>(), false); return ACK; } @@ -105,7 +106,7 @@ JSONRPC_STATUS CInputOperations::SendText(const CStdString &method, ITransportLa CGUIMessage msg(GUI_MSG_SET_TEXT, 0, 0); msg.SetLabel(text); msg.SetParam1(parameterObject["done"].asBoolean() ? 1 : 0); - g_application.getApplicationMessenger().SendGUIMessage(msg, window->GetID()); + CApplicationMessenger::Get().SendGUIMessage(msg, window->GetID()); return ACK; } diff --git a/xbmc/interfaces/json-rpc/JSONRPC.cpp b/xbmc/interfaces/json-rpc/JSONRPC.cpp index 31278b323a..ce4b726447 100644 --- a/xbmc/interfaces/json-rpc/JSONRPC.cpp +++ b/xbmc/interfaces/json-rpc/JSONRPC.cpp @@ -61,7 +61,7 @@ void CJSONRPC::Initialize() CJSONServiceDescription::AddNotification(JSONRPC_SERVICE_NOTIFICATIONS[index]); m_initialized = true; - CLog::Log(LOGINFO, "JSONRPC: Sucessfully initialized"); + CLog::Log(LOGINFO, "JSONRPC: Successfully initialized"); } JSONRPC_STATUS CJSONRPC::Introspect(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant& parameterObject, CVariant &result) @@ -131,6 +131,9 @@ JSONRPC_STATUS CJSONRPC::SetConfiguration(const CStdString &method, ITransportLa if ((notifications["Application"].isNull() && (oldFlags & Other)) || (notifications["Application"].isBoolean() && notifications["Application"].asBoolean())) flags |= Application; + if ((notifications["Input"].isNull() && (oldFlags & Input)) || + (notifications["Input"].isBoolean() && notifications["Input"].asBoolean())) + flags |= Input; if ((notifications["Other"].isNull() && (oldFlags & Other)) || (notifications["Other"].isBoolean() && notifications["Other"].asBoolean())) flags |= Other; diff --git a/xbmc/interfaces/json-rpc/JSONUtils.h b/xbmc/interfaces/json-rpc/JSONUtils.h index c7e3f2077e..eb1110fd1d 100644 --- a/xbmc/interfaces/json-rpc/JSONUtils.h +++ b/xbmc/interfaces/json-rpc/JSONUtils.h @@ -263,7 +263,10 @@ namespace JSONRPC } if (jsonObject.size() == 1) - jsonObject = jsonObject[0]; + { + CVariant jsonType = jsonObject[0]; + jsonObject = jsonType; + } } static inline const char *ValueTypeToString(CVariant::VariantType valueType) diff --git a/xbmc/interfaces/json-rpc/Makefile b/xbmc/interfaces/json-rpc/Makefile index 35d2b8d29e..c62d296658 100644 --- a/xbmc/interfaces/json-rpc/Makefile +++ b/xbmc/interfaces/json-rpc/Makefile @@ -15,4 +15,4 @@ SRCS=ApplicationOperations.cpp \ LIB=json-rpc.a include ../../../Makefile.include - +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/interfaces/json-rpc/PlayerOperations.cpp b/xbmc/interfaces/json-rpc/PlayerOperations.cpp index 5c0f9d39f0..f4109fecfb 100644 --- a/xbmc/interfaces/json-rpc/PlayerOperations.cpp +++ b/xbmc/interfaces/json-rpc/PlayerOperations.cpp @@ -200,7 +200,7 @@ JSONRPC_STATUS CPlayerOperations::PlayPause(const CStdString &method, ITransport else { if (parameterObject["play"].asBoolean() == g_application.IsPaused()) - g_application.getApplicationMessenger().MediaPause(); + CApplicationMessenger::Get().MediaPause(); } result["speed"] = g_application.IsPaused() ? 0 : g_application.GetPlaySpeed(); return OK; @@ -230,7 +230,7 @@ JSONRPC_STATUS CPlayerOperations::Stop(const CStdString &method, ITransportLayer { case Video: case Audio: - g_application.getApplicationMessenger().SendAction(CAction(ACTION_STOP)); + CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP)); return ACK; case Picture: @@ -476,7 +476,7 @@ JSONRPC_STATUS CPlayerOperations::Open(const CStdString &method, ITransportLayer { case PLAYLIST_MUSIC: case PLAYLIST_VIDEO: - g_application.getApplicationMessenger().MediaPlay(playlistid, (int)parameterObject["item"]["position"].asInteger()); + CApplicationMessenger::Get().MediaPlay(playlistid, (int)parameterObject["item"]["position"].asInteger()); OnPlaylistChanged(); break; @@ -540,7 +540,7 @@ JSONRPC_STATUS CPlayerOperations::Open(const CStdString &method, ITransportLayer list[0]->m_lStartOffset = (int)(ParseTimeInSeconds(optionResume) * 75.0); } - g_application.getApplicationMessenger().MediaPlay(list); + CApplicationMessenger::Get().MediaPlay(list); } return ACK; @@ -558,7 +558,7 @@ JSONRPC_STATUS CPlayerOperations::GoPrevious(const CStdString &method, ITranspor { case Video: case Audio: - g_application.getApplicationMessenger().SendAction(CAction(ACTION_PREV_ITEM)); + CApplicationMessenger::Get().SendAction(CAction(ACTION_PREV_ITEM)); return ACK; case Picture: @@ -577,7 +577,7 @@ JSONRPC_STATUS CPlayerOperations::GoNext(const CStdString &method, ITransportLay { case Video: case Audio: - g_application.getApplicationMessenger().SendAction(CAction(ACTION_NEXT_ITEM)); + CApplicationMessenger::Get().SendAction(CAction(ACTION_NEXT_ITEM)); return ACK; case Picture: @@ -597,7 +597,7 @@ JSONRPC_STATUS CPlayerOperations::GoTo(const CStdString &method, ITransportLayer { case Video: case Audio: - g_application.getApplicationMessenger().PlayListPlayerPlay(position); + CApplicationMessenger::Get().PlayListPlayerPlay(position); break; case Picture: @@ -617,7 +617,7 @@ JSONRPC_STATUS CPlayerOperations::Shuffle(const CStdString &method, ITransportLa { case Video: case Audio: - g_application.getApplicationMessenger().PlayListPlayerShuffle(GetPlaylist(GetPlayer(parameterObject["playerid"])), true); + CApplicationMessenger::Get().PlayListPlayerShuffle(GetPlaylist(GetPlayer(parameterObject["playerid"])), true); OnPlaylistChanged(); break; @@ -641,7 +641,7 @@ JSONRPC_STATUS CPlayerOperations::UnShuffle(const CStdString &method, ITransport { case Video: case Audio: - g_application.getApplicationMessenger().PlayListPlayerShuffle(GetPlaylist(GetPlayer(parameterObject["playerid"])), false); + CApplicationMessenger::Get().PlayListPlayerShuffle(GetPlaylist(GetPlayer(parameterObject["playerid"])), false); OnPlaylistChanged(); break; @@ -658,7 +658,7 @@ JSONRPC_STATUS CPlayerOperations::Repeat(const CStdString &method, ITransportLay { case Video: case Audio: - g_application.getApplicationMessenger().PlayListPlayerRepeat(GetPlaylist(GetPlayer(parameterObject["playerid"])), (REPEAT_STATE)ParseRepeatState(parameterObject["state"])); + CApplicationMessenger::Get().PlayListPlayerRepeat(GetPlaylist(GetPlayer(parameterObject["playerid"])), (REPEAT_STATE)ParseRepeatState(parameterObject["state"])); OnPlaylistChanged(); break; @@ -859,14 +859,14 @@ JSONRPC_STATUS CPlayerOperations::StartSlideshow(const std::string path, bool re CGUIMessage msg(GUI_MSG_START_SLIDESHOW, 0, 0, flags); msg.SetStringParam(path); - g_application.getApplicationMessenger().SendGUIMessage(msg, WINDOW_SLIDESHOW, true); + CApplicationMessenger::Get().SendGUIMessage(msg, WINDOW_SLIDESHOW, true); return ACK; } void CPlayerOperations::SendSlideshowAction(int actionID) { - g_application.getApplicationMessenger().SendAction(CAction(actionID), WINDOW_SLIDESHOW); + CApplicationMessenger::Get().SendAction(CAction(actionID), WINDOW_SLIDESHOW); } void CPlayerOperations::OnPlaylistChanged() diff --git a/xbmc/interfaces/json-rpc/PlaylistOperations.cpp b/xbmc/interfaces/json-rpc/PlaylistOperations.cpp index 9d07201128..d09e8e3ea6 100644 --- a/xbmc/interfaces/json-rpc/PlaylistOperations.cpp +++ b/xbmc/interfaces/json-rpc/PlaylistOperations.cpp @@ -25,7 +25,7 @@ #include "Util.h" #include "guilib/GUIWindowManager.h" #include "GUIUserMessages.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "pictures/GUIWindowSlideShow.h" #include "pictures/PictureInfoTag.h" @@ -80,7 +80,7 @@ JSONRPC_STATUS CPlaylistOperations::GetItems(const CStdString &method, ITranspor { case PLAYLIST_VIDEO: case PLAYLIST_MUSIC: - g_application.getApplicationMessenger().PlayListPlayerGetItems(playlist, list); + CApplicationMessenger::Get().PlayListPlayerGetItems(playlist, list); break; case PLAYLIST_PICTURE: @@ -116,7 +116,7 @@ JSONRPC_STATUS CPlaylistOperations::Add(const CStdString &method, ITransportLaye if (!FillFileItemList(params["item"], list)) return InvalidParams; - g_application.getApplicationMessenger().PlayListPlayerAdd(playlist, list); + CApplicationMessenger::Get().PlayListPlayerAdd(playlist, list); break; @@ -163,7 +163,7 @@ JSONRPC_STATUS CPlaylistOperations::Insert(const CStdString &method, ITransportL if (!FillFileItemList(params["item"], list)) return InvalidParams; - g_application.getApplicationMessenger().PlayListPlayerInsert(GetPlaylist(parameterObject["playlistid"]), list, (int)parameterObject["position"].asInteger()); + CApplicationMessenger::Get().PlayListPlayerInsert(GetPlaylist(parameterObject["playlistid"]), list, (int)parameterObject["position"].asInteger()); NotifyAll(); return ACK; @@ -179,7 +179,7 @@ JSONRPC_STATUS CPlaylistOperations::Remove(const CStdString &method, ITransportL if (g_playlistPlayer.GetCurrentPlaylist() == playlist && g_playlistPlayer.GetCurrentSong() == position) return InvalidParams; - g_application.getApplicationMessenger().PlayListPlayerRemove(playlist, position); + CApplicationMessenger::Get().PlayListPlayerRemove(playlist, position); NotifyAll(); return ACK; @@ -193,14 +193,14 @@ JSONRPC_STATUS CPlaylistOperations::Clear(const CStdString &method, ITransportLa { case PLAYLIST_MUSIC: case PLAYLIST_VIDEO: - g_application.getApplicationMessenger().PlayListPlayerClear(playlist); + CApplicationMessenger::Get().PlayListPlayerClear(playlist); break; case PLAYLIST_PICTURE: slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (!slideshow) return FailedToExecute; - g_application.getApplicationMessenger().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW); + CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW); slideshow->Reset(); break; } @@ -215,7 +215,7 @@ JSONRPC_STATUS CPlaylistOperations::Swap(const CStdString &method, ITransportLay if (playlist == PLAYLIST_PICTURE) return FailedToExecute; - g_application.getApplicationMessenger().PlayListPlayerSwap(playlist, (int)parameterObject["position1"].asInteger(), (int)parameterObject["position2"].asInteger()); + CApplicationMessenger::Get().PlayListPlayerSwap(playlist, (int)parameterObject["position1"].asInteger(), (int)parameterObject["position2"].asInteger()); NotifyAll(); return ACK; @@ -267,7 +267,7 @@ JSONRPC_STATUS CPlaylistOperations::GetPropertyValue(int playlist, const CStdStr { case PLAYLIST_MUSIC: case PLAYLIST_VIDEO: - g_application.getApplicationMessenger().PlayListPlayerGetItems(playlist, list); + CApplicationMessenger::Get().PlayListPlayerGetItems(playlist, list); result = list.Size(); break; diff --git a/xbmc/interfaces/json-rpc/ServiceDescription.h b/xbmc/interfaces/json-rpc/ServiceDescription.h index ce62951e1c..0fe63198d8 100644 --- a/xbmc/interfaces/json-rpc/ServiceDescription.h +++ b/xbmc/interfaces/json-rpc/ServiceDescription.h @@ -32,15 +32,15 @@ namespace JSONRPC "\"default\": null" "}", "\"Optional.String\": {" - "\"type\": [ \"null\", \"string\" ], " + "\"type\": [ \"null\", \"string\" ]," "\"default\": null" "}", "\"Optional.Integer\": {" - "\"type\": [ \"null\", \"integer\" ], " + "\"type\": [ \"null\", \"integer\" ]," "\"default\": null" "}", "\"Optional.Number\": {" - "\"type\": [ \"null\", \"number\" ], " + "\"type\": [ \"null\", \"number\" ]," "\"default\": null" "}", "\"Array.String\": {" @@ -79,6 +79,8 @@ namespace JSONRPC "\"System\": { \"type\": \"boolean\", \"required\": true }," "\"VideoLibrary\": { \"type\": \"boolean\", \"required\": true }," "\"AudioLibrary\": { \"type\": \"boolean\", \"required\": true }," + "\"Application\": { \"type\": \"boolean\", \"required\": true }," + "\"Input\": { \"type\": \"boolean\", \"required\": true }," "\"Other\": { \"type\": \"boolean\", \"required\": true }" "}," "\"additionalProperties\": false" @@ -364,14 +366,14 @@ namespace JSONRPC "\"Audio.Details.Base\": {" "\"extends\": \"Media.Details.Base\"," "\"properties\": {" - "\"genre\": { \"type\": \"string\" }" + "\"genre\": { \"$ref\": \"Array.String\" }" "}" "}", "\"Audio.Details.Media\": {" "\"extends\": \"Audio.Details.Base\"," "\"properties\": {" "\"title\": { \"type\": \"string\" }," - "\"artist\": { \"type\": \"string\" }," + "\"artist\": { \"$ref\": \"Array.String\" }," "\"year\": { \"type\": \"integer\" }," "\"rating\": { \"type\": \"integer\" }," "\"musicbrainzalbumid\": { \"type\": \"string\" }," @@ -383,15 +385,15 @@ namespace JSONRPC "\"properties\": {" "\"artistid\": { \"$ref\": \"Library.Id\", \"required\": true }," "\"artist\": { \"type\": \"string\", \"required\": true }," - "\"instrument\": { \"type\": \"string\" }," - "\"style\": { \"type\": \"string\" }," - "\"mood\": { \"type\": \"string\" }," + "\"instrument\": { \"$ref\": \"Array.String\" }," + "\"style\": { \"$ref\": \"Array.String\" }," + "\"mood\": { \"$ref\": \"Array.String\" }," "\"born\": { \"type\": \"string\" }," "\"formed\": { \"type\": \"string\" }," "\"description\": { \"type\": \"string\" }," "\"died\": { \"type\": \"string\" }," "\"disbanded\": { \"type\": \"string\" }," - "\"yearsactive\": { \"type\": \"string\" }," + "\"yearsactive\": { \"$ref\": \"Array.String\" }," "\"musicbrainzartistid\": { \"type\": \"string\" }" "}" "}", @@ -400,12 +402,11 @@ namespace JSONRPC "\"properties\": {" "\"albumid\": { \"$ref\": \"Library.Id\", \"required\": true }," "\"description\": { \"type\": \"string\" }," - "\"theme\": { \"type\": \"string\" }," - "\"mood\": { \"type\": \"string\" }," - "\"style\": { \"type\": \"string\" }," + "\"theme\": { \"$ref\": \"Array.String\" }," + "\"mood\": { \"$ref\": \"Array.String\" }," + "\"style\": { \"$ref\": \"Array.String\" }," "\"type\": { \"type\": \"string\" }," - "\"albumlabel\": { \"type\": \"string\" }," - "\"artistid\": { \"$ref\": \"Library.Id\" }" + "\"albumlabel\": { \"type\": \"string\" }" "}" "}", "\"Audio.Details.Song\": {" @@ -413,7 +414,7 @@ namespace JSONRPC "\"properties\": {" "\"songid\": { \"$ref\": \"Library.Id\", \"required\": true }," "\"file\": { \"type\": \"string\" }," - "\"albumartist\": { \"type\": \"string\" }," + "\"albumartist\": { \"$ref\": \"Array.String\" }," "\"album\": { \"type\": \"string\" }," "\"track\": { \"type\": \"integer\" }," "\"duration\": { \"type\": \"integer\" }," @@ -422,7 +423,6 @@ namespace JSONRPC "\"playcount\": { \"type\": \"integer\" }," "\"musicbrainztrackid\": { \"type\": \"string\" }," "\"musicbrainzartistid\": { \"type\": \"string\" }," - "\"artistid\": { \"$ref\": \"Library.Id\" }," "\"albumid\": { \"$ref\": \"Library.Id\" }," "\"lastplayed\": { \"type\": \"string\" }," "\"disc\": { \"type\": \"integer\" }" @@ -431,13 +431,13 @@ namespace JSONRPC "\"Video.Fields.Movie\": {" "\"extends\": \"Item.Fields.Base\"," "\"items\": { \"type\": \"string\"," - "\"description\": \"Requesting the cast, set, showlink and/or resume field will result in increased response times\"," + "\"description\": \"Requesting the cast, showlink and/or resume field will result in increased response times\"," "\"enum\": [ \"title\", \"genre\", \"year\", \"rating\", \"director\", \"trailer\"," "\"tagline\", \"plot\", \"plotoutline\", \"originaltitle\", \"lastplayed\"," "\"playcount\", \"writer\", \"studio\", \"mpaa\", \"cast\", \"country\"," - "\"imdbnumber\", \"premiered\", \"productioncode\", \"runtime\", \"set\"," - "\"showlink\", \"streamdetails\", \"top250\", \"votes\", \"fanart\"," - "\"thumbnail\", \"file\", \"sorttitle\", \"resume\", \"setid\", \"dateadded\" ]" + "\"imdbnumber\", \"runtime\", \"set\", \"showlink\", \"streamdetails\"," + "\"top250\", \"votes\", \"fanart\", \"thumbnail\", \"file\", \"sorttitle\"," + "\"resume\", \"setid\", \"dateadded\", \"tag\" ]" "}" "}", "\"Video.Fields.MovieSet\": {" @@ -566,7 +566,7 @@ namespace JSONRPC "\"extends\": \"Video.Details.Item\"," "\"properties\": {" "\"runtime\": { \"type\": \"string\" }," - "\"director\": { \"type\": \"string\" }," + "\"director\": { \"$ref\": \"Array.String\" }," "\"streamdetails\": { \"$ref\": \"Video.Streams\" }," "\"resume\": { \"$ref\": \"Video.Resume\" }" "}" @@ -575,7 +575,7 @@ namespace JSONRPC "\"extends\": \"Video.Details.File\"," "\"properties\": {" "\"movieid\": { \"$ref\": \"Library.Id\", \"required\": true }," - "\"genre\": { \"type\": \"string\" }," + "\"genre\": { \"$ref\": \"Array.String\" }," "\"year\": { \"type\": \"integer\" }," "\"rating\": { \"type\": \"number\" }," "\"trailer\": { \"type\": \"string\" }," @@ -583,19 +583,18 @@ namespace JSONRPC "\"plotoutline\": { \"type\": \"string\" }," "\"originaltitle\": { \"type\": \"string\" }," "\"sorttitle\": { \"type\": \"string\" }," - "\"writer\": { \"type\": \"string\" }," - "\"studio\": { \"type\": \"string\" }," + "\"writer\": { \"$ref\": \"Array.String\" }," + "\"studio\": { \"$ref\": \"Array.String\" }," "\"mpaa\": { \"type\": \"string\" }," "\"cast\": { \"$ref\": \"Video.Cast\" }," - "\"country\": { \"type\": \"string\" }," + "\"country\": { \"$ref\": \"Array.String\" }," "\"imdbnumber\": { \"type\": \"string\" }," - "\"premiered\": { \"type\": \"string\" }," - "\"productioncode\": { \"type\": \"string\" }," - "\"set\": { \"$ref\": \"Array.String\" }," - "\"showlink\": { \"type\": \"string\" }," + "\"set\": { \"type\": \"string\" }," + "\"showlink\": { \"$ref\": \"Array.String\" }," "\"top250\": { \"type\": \"integer\" }," "\"votes\": { \"type\": \"string\" }," - "\"setid\": { \"$ref\": \"Array.Integer\" }" + "\"setid\": { \"$ref\": \"Library.Id\" }," + "\"tag\": { \"$ref\": \"Array.String\" }" "}" "}", "\"Video.Details.MovieSet\": {" @@ -616,12 +615,12 @@ namespace JSONRPC "\"extends\": \"Video.Details.Item\"," "\"properties\": {" "\"tvshowid\": { \"$ref\": \"Library.Id\", \"required\": true }," - "\"genre\": { \"type\": \"string\" }," + "\"genre\": { \"$ref\": \"Array.String\" }," "\"year\": { \"type\": \"integer\" }," "\"rating\": { \"type\": \"number\" }," "\"originaltitle\": { \"type\": \"string\" }," "\"sorttitle\": { \"type\": \"string\" }," - "\"studio\": { \"type\": \"string\" }," + "\"studio\": { \"$ref\": \"Array.String\" }," "\"mpaa\": { \"type\": \"string\" }," "\"cast\": { \"$ref\": \"Video.Cast\" }," "\"episode\": { \"type\": \"integer\" }," @@ -649,7 +648,7 @@ namespace JSONRPC "\"episodeid\": { \"$ref\": \"Library.Id\", \"required\": true }," "\"votes\": { \"type\": \"string\" }," "\"rating\": { \"type\": \"number\" }," - "\"writer\": { \"type\": \"string\" }," + "\"writer\": { \"$ref\": \"Array.String\" }," "\"firstaired\": { \"type\": \"string\" }," "\"productioncode\": { \"type\": \"string\" }," "\"season\": { \"type\": \"integer\" }," @@ -664,11 +663,11 @@ namespace JSONRPC "\"extends\": \"Video.Details.File\"," "\"properties\": {" "\"musicvideoid\": { \"$ref\": \"Library.Id\", \"required\": true }," - "\"studio\": { \"type\": \"string\" }," + "\"studio\": { \"$ref\": \"Array.String\" }," "\"year\": { \"type\": \"integer\" }," "\"album\": { \"type\": \"string\" }," - "\"artist\": { \"type\": \"string\" }," - "\"genre\": { \"type\": \"string\" }," + "\"artist\": { \"$ref\": \"Array.String\" }," + "\"genre\": { \"$ref\": \"Array.String\" }," "\"track\": { \"type\": \"integer\" }" "}" "}", @@ -723,7 +722,7 @@ namespace JSONRPC "\"runtime\", \"set\", \"showlink\", \"streamdetails\", \"top250\", \"votes\"," "\"firstaired\", \"season\", \"episode\", \"showtitle\", \"thumbnail\", \"file\"," "\"resume\", \"artistid\", \"albumid\", \"tvshowid\", \"setid\", \"watchedepisodes\"," - "\"disc\" ]" + "\"disc\", \"tag\" ]" "}" "}", "\"List.Item.All\": {" @@ -731,7 +730,7 @@ namespace JSONRPC "\"properties\": {" "\"id\": { \"$ref\": \"Library.Id\" }," "\"type\": { \"type\": \"string\", \"enum\": [ \"unknown\", \"movie\", \"episode\", \"musicvideo\", \"song\", \"picture\" ] }," - "\"albumartist\": { \"type\": \"string\" }," + "\"albumartist\": { \"$ref\": \"Array.String\" }," "\"album\": { \"type\": \"string\" }," "\"track\": { \"type\": \"integer\" }," "\"duration\": { \"type\": \"integer\" }," @@ -743,28 +742,28 @@ namespace JSONRPC "\"tagline\": { \"type\": \"string\" }," "\"plotoutline\": { \"type\": \"string\" }," "\"originaltitle\": { \"type\": \"string\" }," - "\"writer\": { \"type\": \"string\" }," - "\"studio\": { \"type\": \"string\" }," + "\"writer\": { \"$ref\": \"Array.String\" }," + "\"studio\": { \"$ref\": \"Array.String\" }," "\"mpaa\": { \"type\": \"string\" }," "\"cast\": { \"$ref\": \"Video.Cast\" }," "\"country\": { \"type\": \"string\" }," "\"imdbnumber\": { \"type\": \"string\" }," "\"premiered\": { \"type\": \"string\" }," "\"productioncode\": { \"type\": \"string\" }," - "\"set\": { \"$ref\": \"Array.String\" }," - "\"showlink\": { \"type\": \"string\" }," + "\"set\": { \"type\": \"string\" }," + "\"showlink\": { \"$ref\": \"Array.String\" }," "\"top250\": { \"type\": \"integer\" }," "\"votes\": { \"type\": \"string\" }," "\"firstaired\": { \"type\": \"string\" }," "\"season\": { \"type\": \"integer\" }," "\"episode\": { \"type\": \"integer\" }," "\"showtitle\": { \"type\": \"string\" }," - "\"artistid\": { \"$ref\": \"Library.Id\" }," "\"albumid\": { \"$ref\": \"Library.Id\" }," - "\"setid\": { \"$ref\": \"Array.Integer\" }," + "\"setid\": { \"$ref\": \"Library.Id\" }," "\"tvshowid\": { \"$ref\": \"Library.Id\" }," "\"watchedepisodes\": { \"type\": \"integer\" }," - "\"disc\": { \"type\": \"integer\" }" + "\"disc\": { \"type\": \"integer\" }," + "\"tag\": { \"$ref\": \"Array.String\" }" "}" "}", "\"List.Fields.Files\": {" @@ -1453,10 +1452,18 @@ namespace JSONRPC "\"permission\": \"ReadData\"," "\"params\": [" "{ \"name\": \"albumartistsonly\", \"$ref\": \"Optional.Boolean\", \"description\": \"Whether or not to include artists only appearing in compilations. If the parameter is not passed or is passed as null the GUI setting will be used\" }," - "{ \"name\": \"genreid\", \"$ref\": \"Library.Id\" }," "{ \"name\": \"properties\", \"$ref\": \"Audio.Fields.Artist\" }," "{ \"name\": \"limits\", \"$ref\": \"List.Limits\" }," - "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }" + "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }," + "{ \"name\": \"filter\"," + "\"type\": [" + "{ \"type\": \"object\", \"properties\": { \"genreid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"genre\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"albumid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"album\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"songid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }" + "]" + "}" "]," "\"returns\": {" "\"type\": \"object\"," @@ -1489,11 +1496,17 @@ namespace JSONRPC "\"transport\": \"Response\"," "\"permission\": \"ReadData\"," "\"params\": [" - "{ \"name\": \"artistid\", \"$ref\": \"Library.Id\" }," - "{ \"name\": \"genreid\", \"$ref\": \"Library.Id\" }," "{ \"name\": \"properties\", \"$ref\": \"Audio.Fields.Album\" }," "{ \"name\": \"limits\", \"$ref\": \"List.Limits\" }," - "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }" + "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }," + "{ \"name\": \"filter\"," + "\"type\": [" + "{ \"type\": \"object\", \"properties\": { \"genreid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"genre\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"artistid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"artist\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }" + "]" + "}" "]," "\"returns\": {" "\"type\": \"object\"," @@ -1526,12 +1539,19 @@ namespace JSONRPC "\"transport\": \"Response\"," "\"permission\": \"ReadData\"," "\"params\": [" - "{ \"name\": \"artistid\", \"$ref\": \"Library.Id\" }," - "{ \"name\": \"albumid\", \"$ref\": \"Library.Id\" }," - "{ \"name\": \"genreid\", \"$ref\": \"Library.Id\" }," "{ \"name\": \"properties\", \"$ref\": \"Audio.Fields.Song\" }," "{ \"name\": \"limits\", \"$ref\": \"List.Limits\" }," - "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }" + "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }," + "{ \"name\": \"filter\"," + "\"type\": [" + "{ \"type\": \"object\", \"properties\": { \"genreid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"genre\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"artistid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"artist\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"albumid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"album\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }" + "]" + "}" "]," "\"returns\": {" "\"type\": \"object\"," @@ -1775,7 +1795,21 @@ namespace JSONRPC "\"params\": [" "{ \"name\": \"properties\", \"$ref\": \"Video.Fields.Movie\" }," "{ \"name\": \"limits\", \"$ref\": \"List.Limits\" }," - "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }" + "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }," + "{ \"name\": \"filter\"," + "\"type\": [" + "{ \"type\": \"object\", \"properties\": { \"genreid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"genre\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"year\": { \"type\": \"integer\", \"minimum\": 0, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"actor\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"director\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"studio\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"country\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"setid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"set\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"tag\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }" + "]" + "}" "]," "\"returns\": {" "\"type\": \"object\"," @@ -1851,7 +1885,16 @@ namespace JSONRPC "\"params\": [" "{ \"name\": \"properties\", \"$ref\": \"Video.Fields.TVShow\" }," "{ \"name\": \"limits\", \"$ref\": \"List.Limits\" }," - "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }" + "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }," + "{ \"name\": \"filter\"," + "\"type\": [" + "{ \"type\": \"object\", \"properties\": { \"genreid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"genre\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"year\": { \"type\": \"integer\", \"minimum\": 0, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"actor\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"studio\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }" + "]" + "}" "]," "\"returns\": { \"type\": \"object\"," "\"properties\": {" @@ -1907,7 +1950,16 @@ namespace JSONRPC "{ \"name\": \"season\", \"type\": \"integer\", \"minimum\": 0, \"default\": -1 }," "{ \"name\": \"properties\", \"$ref\": \"Video.Fields.Episode\" }," "{ \"name\": \"limits\", \"$ref\": \"List.Limits\" }," - "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }" + "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }," + "{ \"name\": \"filter\"," + "\"type\": [" + "{ \"type\": \"object\", \"properties\": { \"genreid\": { \"$ref\": \"Library.Id\", \"required\": true, \"description\": \"Requires tvshowid to be set\" } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"genre\": { \"type\": \"string\", \"minLength\": 1, \"required\": true, \"description\": \"Requires tvshowid to be set\" } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"year\": { \"type\": \"integer\", \"minimum\": 0, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"actor\": { \"type\": \"string\", \"minLength\": 1, \"required\": true, \"description\": \"Requires tvshowid to be set\" } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"director\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }" + "]" + "}" "]," "\"returns\": { \"type\": \"object\"," "\"properties\": {" @@ -1939,11 +1991,19 @@ namespace JSONRPC "\"transport\": \"Response\"," "\"permission\": \"ReadData\"," "\"params\": [" - "{ \"name\": \"artistid\", \"$ref\": \"Library.Id\" }," - "{ \"name\": \"albumid\", \"$ref\": \"Library.Id\" }," "{ \"name\": \"properties\", \"$ref\": \"Video.Fields.MusicVideo\" }," "{ \"name\": \"limits\", \"$ref\": \"List.Limits\" }," - "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }" + "{ \"name\": \"sort\", \"$ref\": \"List.Sort\" }," + "{ \"name\": \"filter\"," + "\"type\": [" + "{ \"type\": \"object\", \"properties\": { \"artist\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"genreid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"genre\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"year\": { \"type\": \"integer\", \"minimum\": 0, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"director\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"studio\": { \"type\": \"string\", \"minLength\": 1, \"required\": true } }, \"additionalProperties\": false }" + "]" + "}" "]," "\"returns\": { \"type\": \"object\"," "\"properties\": {" @@ -2075,10 +2135,11 @@ namespace JSONRPC "{ \"name\": \"country\", \"type\": [ \"null\", { \"$ref\": \"Array.String\", \"required\": true } ], \"default\": null }," "{ \"name\": \"top250\", \"$ref\": \"Optional.Integer\" }," "{ \"name\": \"sorttitle\", \"$ref\": \"Optional.String\" }," - "{ \"name\": \"set\", \"type\": [ \"null\", { \"$ref\": \"Array.String\", \"required\": true } ], \"default\": null }," + "{ \"name\": \"set\", \"$ref\": \"Optional.String\" }," "{ \"name\": \"showlink\", \"type\": [ \"null\", { \"$ref\": \"Array.String\", \"required\": true } ], \"default\": null }," "{ \"name\": \"thumbnail\", \"$ref\": \"Optional.String\" }," - "{ \"name\": \"fanart\", \"$ref\": \"Optional.String\" }" + "{ \"name\": \"fanart\", \"$ref\": \"Optional.String\" }," + "{ \"name\": \"tag\", \"type\": [ \"null\", { \"$ref\": \"Array.String\", \"required\": true } ], \"default\": null }" "]," "\"returns\": \"string\"" "}", @@ -2092,7 +2153,6 @@ namespace JSONRPC "{ \"name\": \"title\", \"$ref\": \"Optional.String\" }," "{ \"name\": \"playcount\", \"$ref\": \"Optional.Integer\" }," "{ \"name\": \"studio\", \"type\": [ \"null\", { \"$ref\": \"Array.String\", \"required\": true } ], \"default\": null }," - "{ \"name\": \"year\", \"$ref\": \"Optional.Integer\" }," "{ \"name\": \"plot\", \"$ref\": \"Optional.String\" }," "{ \"name\": \"genre\", \"type\": [ \"null\", { \"$ref\": \"Array.String\", \"required\": true } ], \"default\": null }," "{ \"name\": \"rating\", \"$ref\": \"Optional.Number\" }," @@ -2532,7 +2592,7 @@ namespace JSONRPC "\"description\": \"Playback of a media item has been stopped. If there is no ID available extra information will be provided.\"," "\"params\": [" "{ \"name\": \"sender\", \"type\": \"string\", \"required\": true }," - "{ \"name\": \"data\", \"type\": \"object\", \"required\": true, " + "{ \"name\": \"data\", \"type\": \"object\", \"required\": true," "\"properties\": {" "\"item\": { \"$ref\": \"Player.Notifications.Item\" }," "\"end\": { \"type\": \"boolean\", \"required\": true, \"description\": \"Whether the player has reached the end of the playable item(s) or not\" }" @@ -2555,7 +2615,7 @@ namespace JSONRPC "\"description\": \"The playback position has been changed. If there is no ID available extra information will be provided.\"," "\"params\": [" "{ \"name\": \"sender\", \"type\": \"string\", \"required\": true }," - "{ \"name\": \"data\", \"type\": \"object\", \"required\": true, " + "{ \"name\": \"data\", \"type\": \"object\", \"required\": true," "\"properties\": {" "\"item\": { \"$ref\": \"Player.Notifications.Item\" }," "\"player\": { \"$ref\": \"Player.Notifications.Player.Seek\", \"required\": true }" @@ -2705,7 +2765,8 @@ namespace JSONRPC "{ \"name\": \"sender\", \"type\": \"string\", \"required\": true }," "{ \"name\": \"data\", \"type\": \"object\", \"required\": true," "\"properties\": {" - "\"type\": { \"type\": \"string\", \"enum\": [ \"keyboard\", \"time\", \"date\", \"ip\", \"password\", \"number\", \"seconds\" ], \"required\": true }," + "\"type\": { \"type\": \"string\", \"enum\": [ \"keyboard\", \"time\", \"date\", \"ip\", \"password\", \"numericpassword\", \"number\", \"seconds\" ], \"required\": true }," + "\"value\": { \"type\": \"string\", \"required\": true }," "\"title\": { \"type\": \"string\" }" "}" "}" diff --git a/xbmc/interfaces/json-rpc/SystemOperations.cpp b/xbmc/interfaces/json-rpc/SystemOperations.cpp index 58df809077..022266f5c2 100644 --- a/xbmc/interfaces/json-rpc/SystemOperations.cpp +++ b/xbmc/interfaces/json-rpc/SystemOperations.cpp @@ -20,7 +20,7 @@ */ #include "SystemOperations.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "interfaces/Builtins.h" #include "utils/Variant.h" #include "powermanagement/PowerManager.h" @@ -55,7 +55,7 @@ JSONRPC_STATUS CSystemOperations::Shutdown(const CStdString &method, ITransportL { if (g_powerManager.CanPowerdown()) { - g_application.getApplicationMessenger().Powerdown(); + CApplicationMessenger::Get().Powerdown(); return ACK; } else @@ -66,7 +66,7 @@ JSONRPC_STATUS CSystemOperations::Suspend(const CStdString &method, ITransportLa { if (g_powerManager.CanSuspend()) { - g_application.getApplicationMessenger().Suspend(); + CApplicationMessenger::Get().Suspend(); return ACK; } else @@ -77,7 +77,7 @@ JSONRPC_STATUS CSystemOperations::Hibernate(const CStdString &method, ITransport { if (g_powerManager.CanHibernate()) { - g_application.getApplicationMessenger().Hibernate(); + CApplicationMessenger::Get().Hibernate(); return ACK; } else @@ -88,7 +88,7 @@ JSONRPC_STATUS CSystemOperations::Reboot(const CStdString &method, ITransportLay { if (g_powerManager.CanReboot()) { - g_application.getApplicationMessenger().Restart(); + CApplicationMessenger::Get().Restart(); return ACK; } else diff --git a/xbmc/interfaces/json-rpc/VideoLibrary.cpp b/xbmc/interfaces/json-rpc/VideoLibrary.cpp index 413b2bd321..1dfc967a41 100644 --- a/xbmc/interfaces/json-rpc/VideoLibrary.cpp +++ b/xbmc/interfaces/json-rpc/VideoLibrary.cpp @@ -20,7 +20,7 @@ */ #include "VideoLibrary.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "Util.h" #include "utils/URIUtils.h" #include "video/VideoDatabase.h" @@ -33,12 +33,45 @@ JSONRPC_STATUS CVideoLibrary::GetMovies(const CStdString &method, ITransportLaye if (!videodatabase.Open()) return InternalError; + SortDescription sorting; + ParseLimits(parameterObject, sorting.limitStart, sorting.limitEnd); + if (!ParseSorting(parameterObject, sorting.sortBy, sorting.sortOrder, sorting.sortAttributes)) + return InvalidParams; + + CVideoDbUrl videoUrl; + videoUrl.FromString("videodb://1/2/"); + int genreID = -1, year = -1, setID = 0; + const CVariant &filter = parameterObject["filter"]; + if (filter.isMember("genreid")) + genreID = (int)filter["genreid"].asInteger(); + if (filter.isMember("genre")) + videoUrl.AddOption("genre", filter["genre"].asString()); + if (filter.isMember("year")) + year = (int)filter["year"].asInteger(); + if (filter.isMember("actor")) + videoUrl.AddOption("actor", filter["actor"].asString()); + if (filter.isMember("director")) + videoUrl.AddOption("director", filter["director"].asString()); + if (filter.isMember("studio")) + videoUrl.AddOption("studio", filter["studio"].asString()); + if (filter.isMember("country")) + videoUrl.AddOption("country", filter["country"].asString()); + if (filter.isMember("setid")) + setID = (int)filter["setid"].asInteger(); + if (filter.isMember("set")) + videoUrl.AddOption("set", filter["set"].asString()); + if (filter.isMember("tag")) + videoUrl.AddOption("tag", filter["tag"].asString()); + + // setID must not be -1 otherwise GetMoviesNav() will return sets + if (setID < 0) + setID = 0; + CFileItemList items; - JSONRPC_STATUS ret = OK; - if ((ret = GetVideos(MediaTypeMovie, "videodb://1/2/", parameterObject, items, result, videodatabase)) == OK) - ret = GetAdditionalMovieDetails(parameterObject, items, result, videodatabase); + if (!videodatabase.GetMoviesNav(videoUrl.ToString(), items, genreID, year, -1, -1, -1, -1, setID, -1, sorting)) + return InvalidParams; - return ret; + return GetAdditionalMovieDetails(parameterObject, items, result, videodatabase); } JSONRPC_STATUS CVideoLibrary::GetMovieDetails(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) @@ -53,6 +86,16 @@ JSONRPC_STATUS CVideoLibrary::GetMovieDetails(const CStdString &method, ITranspo if (!videodatabase.GetMovieInfo("", infos, id) || infos.m_iDbId <= 0) return InvalidParams; + for (CVariant::const_iterator_array itr = parameterObject["properties"].begin_array(); itr != parameterObject["properties"].end_array(); itr++) + { + CStdString fieldValue = itr->asString(); + if (fieldValue == "streamdetails") + { + videodatabase.GetStreamDetails(infos); + break; + } + } + HandleFileItem("movieid", true, "moviedetails", CFileItemPtr(new CFileItem(infos)), parameterObject, parameterObject["properties"], result, false); return OK; } @@ -100,10 +143,29 @@ JSONRPC_STATUS CVideoLibrary::GetTVShows(const CStdString &method, ITransportLay if (!videodatabase.Open()) return InternalError; + SortDescription sorting; + ParseLimits(parameterObject, sorting.limitStart, sorting.limitEnd); + if (!ParseSorting(parameterObject, sorting.sortBy, sorting.sortOrder, sorting.sortAttributes)) + return InvalidParams; + + CVideoDbUrl videoUrl; + videoUrl.FromString("videodb://2/2/"); + int genreID = -1, year = -1; + const CVariant &filter = parameterObject["filter"]; + if (filter.isMember("genreid")) + genreID = (int)filter["genreid"].asInteger(); + if (filter.isMember("genre")) + videoUrl.AddOption("genre", filter["genre"].asString()); + if (filter.isMember("year")) + year = (int)filter["year"].asInteger(); + if (filter.isMember("actor")) + videoUrl.AddOption("actor", filter["actor"].asString()); + if (filter.isMember("studio")) + videoUrl.AddOption("studio", filter["studio"].asString()); + CFileItemList items; - JSONRPC_STATUS ret = OK; - if ((ret = GetVideos(MediaTypeTvShow, "videodb://2/2/", parameterObject, items, result, videodatabase)) != OK) - return ret; + if (!videodatabase.GetTvShowsNav(videoUrl.ToString(), items, genreID, year, -1, -1, -1, sorting)) + return InvalidParams; bool additionalInfo = false; for (CVariant::const_iterator_array itr = parameterObject["properties"].begin_array(); itr != parameterObject["properties"].end_array(); itr++) @@ -124,7 +186,7 @@ JSONRPC_STATUS CVideoLibrary::GetTVShows(const CStdString &method, ITransportLay size = (int)items.GetProperty("total").asInteger(); HandleFileItemList("tvshowid", true, "tvshows", items, parameterObject, result, size, false); - return ret; + return OK; } JSONRPC_STATUS CVideoLibrary::GetTVShowDetails(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) @@ -174,11 +236,30 @@ JSONRPC_STATUS CVideoLibrary::GetEpisodes(const CStdString &method, ITransportLa int tvshowID = (int)parameterObject["tvshowid"].asInteger(); int season = (int)parameterObject["season"].asInteger(); - + CStdString strPath; strPath.Format("videodb://2/2/%i/%i/", tvshowID, season); + + CVideoDbUrl videoUrl; + videoUrl.FromString(strPath); + int genreID = -1, year = -1; + const CVariant &filter = parameterObject["filter"]; + if (filter.isMember("genreid")) + genreID = (int)filter["genreid"].asInteger(); + if (filter.isMember("genre")) + videoUrl.AddOption("genre", filter["genre"].asString()); + if (filter.isMember("year")) + year = (int)filter["year"].asInteger(); + if (filter.isMember("actor")) + videoUrl.AddOption("actor", filter["actor"].asString()); + if (filter.isMember("director")) + videoUrl.AddOption("director", filter["director"].asString()); + + if (tvshowID <= 0 && (genreID > 0 || filter.isMember("actor"))) + return InvalidParams; + CFileItemList items; - if (!videodatabase.GetEpisodesNav(strPath, items, -1, -1, -1, -1, tvshowID, season, sorting)) + if (!videodatabase.GetEpisodesNav(videoUrl.ToString(), items, genreID, year, -1, -1, tvshowID, season, sorting)) return InternalError; return GetAdditionalEpisodeDetails(parameterObject, items, result, videodatabase); @@ -196,6 +277,16 @@ JSONRPC_STATUS CVideoLibrary::GetEpisodeDetails(const CStdString &method, ITrans if (!videodatabase.GetEpisodeInfo("", infos, id) || infos.m_iDbId <= 0) return InvalidParams; + for (CVariant::const_iterator_array itr = parameterObject["properties"].begin_array(); itr != parameterObject["properties"].end_array(); itr++) + { + CStdString fieldValue = itr->asString(); + if (fieldValue == "streamdetails") + { + videodatabase.GetStreamDetails(infos); + break; + } + } + CFileItemPtr pItem = CFileItemPtr(new CFileItem(infos)); // We need to set the correct base path to get the valid fanart int tvshowid = infos.m_iIdShow; @@ -220,11 +311,25 @@ JSONRPC_STATUS CVideoLibrary::GetMusicVideos(const CStdString &method, ITranspor if (!ParseSorting(parameterObject, sorting.sortBy, sorting.sortOrder, sorting.sortAttributes)) return InvalidParams; - int artistID = (int)parameterObject["artistid"].asInteger(); - int albumID = (int)parameterObject["albumid"].asInteger(); + CVideoDbUrl videoUrl; + videoUrl.FromString("videodb://3/2/"); + int genreID = -1, year = -1; + const CVariant &filter = parameterObject["filter"]; + if (filter.isMember("artist")) + videoUrl.AddOption("artist", filter["artist"].asString()); + if (filter.isMember("genreid")) + genreID = (int)filter["genreid"].asInteger(); + if (filter.isMember("genre")) + videoUrl.AddOption("genre", filter["genre"].asString()); + if (filter.isMember("year")) + year = (int)filter["year"].asInteger(); + if (filter.isMember("director")) + videoUrl.AddOption("director", filter["director"].asString()); + if (filter.isMember("studio")) + videoUrl.AddOption("studio", filter["studio"].asString()); CFileItemList items; - if (!videodatabase.GetMusicVideosNav("videodb://3/2/", items, -1, -1, artistID, -1, -1, albumID, sorting)) + if (!videodatabase.GetMusicVideosNav(videoUrl.ToString(), items, genreID, year, -1, -1, -1, -1, sorting)) return InternalError; return GetAdditionalMusicVideoDetails(parameterObject, items, result, videodatabase); @@ -242,6 +347,16 @@ JSONRPC_STATUS CVideoLibrary::GetMusicVideoDetails(const CStdString &method, ITr if (!videodatabase.GetMusicVideoInfo("", infos, id) || infos.m_iDbId <= 0) return InvalidParams; + for (CVariant::const_iterator_array itr = parameterObject["properties"].begin_array(); itr != parameterObject["properties"].end_array(); itr++) + { + CStdString fieldValue = itr->asString(); + if (fieldValue == "streamdetails") + { + videodatabase.GetStreamDetails(infos); + break; + } + } + HandleFileItem("musicvideoid", true, "musicvideodetails", CFileItemPtr(new CFileItem(infos)), parameterObject, parameterObject["properties"], result, false); return OK; } @@ -509,7 +624,7 @@ JSONRPC_STATUS CVideoLibrary::Scan(const CStdString &method, ITransportLayer *tr else cmd.Format("updatelibrary(video, %s)", directory.c_str()); - g_application.getApplicationMessenger().ExecBuiltIn(cmd); + CApplicationMessenger::Get().ExecBuiltIn(cmd); return ACK; } @@ -524,13 +639,13 @@ JSONRPC_STATUS CVideoLibrary::Export(const CStdString &method, ITransportLayer * parameterObject["options"]["overwrite"].asBoolean() ? "true" : "false", parameterObject["options"]["actorthumbs"].asBoolean() ? "true" : "false"); - g_application.getApplicationMessenger().ExecBuiltIn(cmd); + CApplicationMessenger::Get().ExecBuiltIn(cmd); return ACK; } JSONRPC_STATUS CVideoLibrary::Clean(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { - g_application.getApplicationMessenger().ExecBuiltIn("cleanlibrary(video)"); + CApplicationMessenger::Get().ExecBuiltIn("cleanlibrary(video)"); return ACK; } @@ -600,33 +715,31 @@ bool CVideoLibrary::FillFileItemList(const CVariant ¶meterObject, CFileItemL return success; } -JSONRPC_STATUS CVideoLibrary::GetVideos(MediaType mediaType, const CStdString &strBaseDir, const CVariant ¶meterObject, CFileItemList &items, CVariant &result, CVideoDatabase &videodatabase) -{ - SortDescription sorting; - ParseLimits(parameterObject, sorting.limitStart, sorting.limitEnd); - if (!ParseSorting(parameterObject, sorting.sortBy, sorting.sortOrder, sorting.sortAttributes)) - return InvalidParams; - - return videodatabase.GetSortedVideos(mediaType, strBaseDir, sorting, items) ? OK : InternalError; -} - JSONRPC_STATUS CVideoLibrary::GetAdditionalMovieDetails(const CVariant ¶meterObject, CFileItemList &items, CVariant &result, CVideoDatabase &videodatabase) { if (!videodatabase.Open()) return InternalError; bool additionalInfo = false; + bool streamdetails = false; for (CVariant::const_iterator_array itr = parameterObject["properties"].begin_array(); itr != parameterObject["properties"].end_array(); itr++) { CStdString fieldValue = itr->asString(); if (fieldValue == "cast" || fieldValue == "set" || fieldValue == "setid" || fieldValue == "showlink" || fieldValue == "resume") additionalInfo = true; + else if (fieldValue == "streamdetails") + streamdetails = true; } - if (additionalInfo) + if (additionalInfo || streamdetails) { for (int index = 0; index < items.Size(); index++) - videodatabase.GetMovieInfo("", *(items[index]->GetVideoInfoTag()), items[index]->GetVideoInfoTag()->m_iDbId); + { + if (additionalInfo) + videodatabase.GetMovieInfo("", *(items[index]->GetVideoInfoTag()), items[index]->GetVideoInfoTag()->m_iDbId); + if (streamdetails) + videodatabase.GetStreamDetails(*(items[index]->GetVideoInfoTag())); + } } int size = items.Size(); @@ -643,17 +756,25 @@ JSONRPC_STATUS CVideoLibrary::GetAdditionalEpisodeDetails(const CVariant ¶me return InternalError; bool additionalInfo = false; + bool streamdetails = false; for (CVariant::const_iterator_array itr = parameterObject["properties"].begin_array(); itr != parameterObject["properties"].end_array(); itr++) { CStdString fieldValue = itr->asString(); if (fieldValue == "cast" || fieldValue == "resume") additionalInfo = true; + else if (fieldValue == "streamdetails") + streamdetails = true; } - if (additionalInfo) + if (additionalInfo || streamdetails) { for (int index = 0; index < items.Size(); index++) - videodatabase.GetEpisodeInfo("", *(items[index]->GetVideoInfoTag()), items[index]->GetVideoInfoTag()->m_iDbId); + { + if (additionalInfo) + videodatabase.GetEpisodeInfo("", *(items[index]->GetVideoInfoTag()), items[index]->GetVideoInfoTag()->m_iDbId); + if (streamdetails) + videodatabase.GetStreamDetails(*(items[index]->GetVideoInfoTag())); + } } int size = items.Size(); @@ -670,19 +791,27 @@ JSONRPC_STATUS CVideoLibrary::GetAdditionalMusicVideoDetails(const CVariant &par return InternalError; bool additionalInfo = false; + bool streamdetails = false; for (CVariant::const_iterator_array itr = parameterObject["properties"].begin_array(); itr != parameterObject["properties"].end_array(); itr++) { CStdString fieldValue = itr->asString(); if (fieldValue == "resume") additionalInfo = true; + else if (fieldValue == "streamdetails") + streamdetails = true; } - if (additionalInfo) + if (additionalInfo || streamdetails) { for (int index = 0; index < items.Size(); index++) - videodatabase.GetMusicVideoInfo("", *(items[index]->GetVideoInfoTag()), items[index]->GetVideoInfoTag()->m_iDbId); + { + if (additionalInfo) + videodatabase.GetMusicVideoInfo("", *(items[index]->GetVideoInfoTag()), items[index]->GetVideoInfoTag()->m_iDbId); + if (streamdetails) + videodatabase.GetStreamDetails(*(items[index]->GetVideoInfoTag())); + } } - + int size = items.Size(); if (items.HasProperty("total") && items.GetProperty("total").asInteger() > size) size = (int)items.GetProperty("total").asInteger(); @@ -771,11 +900,13 @@ void CVideoLibrary::UpdateVideoTag(const CVariant ¶meterObject, CVideoInfoTa if (ParameterNotNull(parameterObject, "episodeguide")) details.m_strEpisodeGuide = parameterObject["episodeguide"].asString(); if (ParameterNotNull(parameterObject, "set")) - CopyStringArray(parameterObject["set"], details.m_set); + details.m_strSet = parameterObject["set"].asString(); if (ParameterNotNull(parameterObject, "showlink")) CopyStringArray(parameterObject["showlink"], details.m_showLink); if (ParameterNotNull(parameterObject, "thumbnail")) artwork["thumb"] = parameterObject["thumbnail"].asString(); if (ParameterNotNull(parameterObject, "fanart")) artwork["fanart"] = parameterObject["fanart"].asString(); + if (ParameterNotNull(parameterObject, "tag")) + CopyStringArray(parameterObject["tag"], details.m_tags); } diff --git a/xbmc/interfaces/json-rpc/VideoLibrary.h b/xbmc/interfaces/json-rpc/VideoLibrary.h index cb13509537..d461036455 100644 --- a/xbmc/interfaces/json-rpc/VideoLibrary.h +++ b/xbmc/interfaces/json-rpc/VideoLibrary.h @@ -70,7 +70,6 @@ namespace JSONRPC static bool FillFileItemList(const CVariant ¶meterObject, CFileItemList &list); private: - static JSONRPC_STATUS GetVideos(MediaType mediaType, const CStdString &strBaseDir, const CVariant ¶meterObject, CFileItemList &items, CVariant &result, CVideoDatabase &videodatabase); static JSONRPC_STATUS GetAdditionalMovieDetails(const CVariant ¶meterObject, CFileItemList &items, CVariant &result, CVideoDatabase &videodatabase); static JSONRPC_STATUS GetAdditionalEpisodeDetails(const CVariant ¶meterObject, CFileItemList &items, CVariant &result, CVideoDatabase &videodatabase); static JSONRPC_STATUS GetAdditionalMusicVideoDetails(const CVariant ¶meterObject, CFileItemList &items, CVariant &result, CVideoDatabase &videodatabase); diff --git a/xbmc/interfaces/json-rpc/XBMCOperations.cpp b/xbmc/interfaces/json-rpc/XBMCOperations.cpp index beac445d13..ba10658da7 100644 --- a/xbmc/interfaces/json-rpc/XBMCOperations.cpp +++ b/xbmc/interfaces/json-rpc/XBMCOperations.cpp @@ -20,7 +20,6 @@ */ #include "XBMCOperations.h" -#include "Application.h" #include "ApplicationMessenger.h" #include "Util.h" #include "utils/Variant.h" @@ -42,7 +41,7 @@ JSONRPC_STATUS CXBMCOperations::GetInfoLabels(const CStdString &method, ITranspo if (info.size() > 0) { - std::vector<CStdString> infoLabels = g_application.getApplicationMessenger().GetInfoLabels(info); + std::vector<CStdString> infoLabels = CApplicationMessenger::Get().GetInfoLabels(info); for (unsigned int i = 0; i < info.size(); i++) { if (i >= infoLabels.size()) @@ -83,7 +82,7 @@ JSONRPC_STATUS CXBMCOperations::GetInfoBooleans(const CStdString &method, ITrans if (info.size() > 0) { - std::vector<bool> infoLabels = g_application.getApplicationMessenger().GetInfoBooleans(info); + std::vector<bool> infoLabels = CApplicationMessenger::Get().GetInfoBooleans(info); for (unsigned int i = 0; i < info.size(); i++) { if (i >= infoLabels.size()) diff --git a/xbmc/interfaces/json-rpc/methods.json b/xbmc/interfaces/json-rpc/methods.json index 877a9983ba..4098f80814 100644 --- a/xbmc/interfaces/json-rpc/methods.json +++ b/xbmc/interfaces/json-rpc/methods.json @@ -588,10 +588,18 @@ "permission": "ReadData", "params": [ { "name": "albumartistsonly", "$ref": "Optional.Boolean", "description": "Whether or not to include artists only appearing in compilations. If the parameter is not passed or is passed as null the GUI setting will be used" }, - { "name": "genreid", "$ref": "Library.Id" }, { "name": "properties", "$ref": "Audio.Fields.Artist" }, { "name": "limits", "$ref": "List.Limits" }, - { "name": "sort", "$ref": "List.Sort" } + { "name": "sort", "$ref": "List.Sort" }, + { "name": "filter", + "type": [ + { "type": "object", "properties": { "genreid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "genre": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "albumid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "album": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "songid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false } + ] + } ], "returns": { "type": "object", @@ -624,11 +632,17 @@ "transport": "Response", "permission": "ReadData", "params": [ - { "name": "artistid", "$ref": "Library.Id" }, - { "name": "genreid", "$ref": "Library.Id" }, { "name": "properties", "$ref": "Audio.Fields.Album" }, { "name": "limits", "$ref": "List.Limits" }, - { "name": "sort", "$ref": "List.Sort" } + { "name": "sort", "$ref": "List.Sort" }, + { "name": "filter", + "type": [ + { "type": "object", "properties": { "genreid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "genre": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "artistid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "artist": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false } + ] + } ], "returns": { "type": "object", @@ -661,12 +675,19 @@ "transport": "Response", "permission": "ReadData", "params": [ - { "name": "artistid", "$ref": "Library.Id" }, - { "name": "albumid", "$ref": "Library.Id" }, - { "name": "genreid", "$ref": "Library.Id" }, { "name": "properties", "$ref": "Audio.Fields.Song" }, { "name": "limits", "$ref": "List.Limits" }, - { "name": "sort", "$ref": "List.Sort" } + { "name": "sort", "$ref": "List.Sort" }, + { "name": "filter", + "type": [ + { "type": "object", "properties": { "genreid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "genre": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "artistid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "artist": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "albumid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "album": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false } + ] + } ], "returns": { "type": "object", @@ -910,7 +931,21 @@ "params": [ { "name": "properties", "$ref": "Video.Fields.Movie" }, { "name": "limits", "$ref": "List.Limits" }, - { "name": "sort", "$ref": "List.Sort" } + { "name": "sort", "$ref": "List.Sort" }, + { "name": "filter", + "type": [ + { "type": "object", "properties": { "genreid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "genre": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "year": { "type": "integer", "minimum": 0, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "actor": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "director": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "studio": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "country": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "setid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "set": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "tag": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false } + ] + } ], "returns": { "type": "object", @@ -986,7 +1021,16 @@ "params": [ { "name": "properties", "$ref": "Video.Fields.TVShow" }, { "name": "limits", "$ref": "List.Limits" }, - { "name": "sort", "$ref": "List.Sort" } + { "name": "sort", "$ref": "List.Sort" }, + { "name": "filter", + "type": [ + { "type": "object", "properties": { "genreid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "genre": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "year": { "type": "integer", "minimum": 0, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "actor": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "studio": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false } + ] + } ], "returns": { "type": "object", "properties": { @@ -1042,7 +1086,16 @@ { "name": "season", "type": "integer", "minimum": 0, "default": -1 }, { "name": "properties", "$ref": "Video.Fields.Episode" }, { "name": "limits", "$ref": "List.Limits" }, - { "name": "sort", "$ref": "List.Sort" } + { "name": "sort", "$ref": "List.Sort" }, + { "name": "filter", + "type": [ + { "type": "object", "properties": { "genreid": { "$ref": "Library.Id", "required": true, "description": "Requires tvshowid to be set" } }, "additionalProperties": false }, + { "type": "object", "properties": { "genre": { "type": "string", "minLength": 1, "required": true, "description": "Requires tvshowid to be set" } }, "additionalProperties": false }, + { "type": "object", "properties": { "year": { "type": "integer", "minimum": 0, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "actor": { "type": "string", "minLength": 1, "required": true, "description": "Requires tvshowid to be set" } }, "additionalProperties": false }, + { "type": "object", "properties": { "director": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false } + ] + } ], "returns": { "type": "object", "properties": { @@ -1074,11 +1127,19 @@ "transport": "Response", "permission": "ReadData", "params": [ - { "name": "artistid", "$ref": "Library.Id" }, - { "name": "albumid", "$ref": "Library.Id" }, { "name": "properties", "$ref": "Video.Fields.MusicVideo" }, { "name": "limits", "$ref": "List.Limits" }, - { "name": "sort", "$ref": "List.Sort" } + { "name": "sort", "$ref": "List.Sort" }, + { "name": "filter", + "type": [ + { "type": "object", "properties": { "artist": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "genreid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "genre": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "year": { "type": "integer", "minimum": 0, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "director": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false }, + { "type": "object", "properties": { "studio": { "type": "string", "minLength": 1, "required": true } }, "additionalProperties": false } + ] + } ], "returns": { "type": "object", "properties": { @@ -1210,10 +1271,11 @@ { "name": "country", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null }, { "name": "top250", "$ref": "Optional.Integer" }, { "name": "sorttitle", "$ref": "Optional.String" }, - { "name": "set", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null }, + { "name": "set", "$ref": "Optional.String" }, { "name": "showlink", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null }, { "name": "thumbnail", "$ref": "Optional.String" }, - { "name": "fanart", "$ref": "Optional.String" } + { "name": "fanart", "$ref": "Optional.String" }, + { "name": "tag", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null } ], "returns": "string" }, @@ -1227,7 +1289,6 @@ { "name": "title", "$ref": "Optional.String" }, { "name": "playcount", "$ref": "Optional.Integer" }, { "name": "studio", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null }, - { "name": "year", "$ref": "Optional.Integer" }, { "name": "plot", "$ref": "Optional.String" }, { "name": "genre", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null }, { "name": "rating", "$ref": "Optional.Number" }, diff --git a/xbmc/interfaces/json-rpc/notifications.json b/xbmc/interfaces/json-rpc/notifications.json index 372122941b..53263dc659 100644 --- a/xbmc/interfaces/json-rpc/notifications.json +++ b/xbmc/interfaces/json-rpc/notifications.json @@ -22,7 +22,7 @@ "description": "Playback of a media item has been stopped. If there is no ID available extra information will be provided.", "params": [ { "name": "sender", "type": "string", "required": true }, - { "name": "data", "type": "object", "required": true, + { "name": "data", "type": "object", "required": true, "properties": { "item": { "$ref": "Player.Notifications.Item" }, "end": { "type": "boolean", "required": true, "description": "Whether the player has reached the end of the playable item(s) or not" } @@ -45,7 +45,7 @@ "description": "The playback position has been changed. If there is no ID available extra information will be provided.", "params": [ { "name": "sender", "type": "string", "required": true }, - { "name": "data", "type": "object", "required": true, + { "name": "data", "type": "object", "required": true, "properties": { "item": { "$ref": "Player.Notifications.Item" }, "player": { "$ref": "Player.Notifications.Player.Seek", "required": true } @@ -195,7 +195,8 @@ { "name": "sender", "type": "string", "required": true }, { "name": "data", "type": "object", "required": true, "properties": { - "type": { "type": "string", "enum": [ "keyboard", "time", "date", "ip", "password", "number", "seconds" ], "required": true }, + "type": { "type": "string", "enum": [ "keyboard", "time", "date", "ip", "password", "numericpassword", "number", "seconds" ], "required": true }, + "value": { "type": "string", "required": true }, "title": { "type": "string" } } } diff --git a/xbmc/interfaces/json-rpc/types.json b/xbmc/interfaces/json-rpc/types.json index 7eb34558ce..9ab1917f67 100644 --- a/xbmc/interfaces/json-rpc/types.json +++ b/xbmc/interfaces/json-rpc/types.json @@ -4,15 +4,15 @@ "default": null }, "Optional.String": { - "type": [ "null", "string" ], + "type": [ "null", "string" ], "default": null }, "Optional.Integer": { - "type": [ "null", "integer" ], + "type": [ "null", "integer" ], "default": null }, "Optional.Number": { - "type": [ "null", "number" ], + "type": [ "null", "number" ], "default": null }, "Array.String": { @@ -51,6 +51,8 @@ "System": { "type": "boolean", "required": true }, "VideoLibrary": { "type": "boolean", "required": true }, "AudioLibrary": { "type": "boolean", "required": true }, + "Application": { "type": "boolean", "required": true }, + "Input": { "type": "boolean", "required": true }, "Other": { "type": "boolean", "required": true } }, "additionalProperties": false @@ -65,7 +67,7 @@ "type": "integer", "default": -1, "minimum": 1 - }, + }, "Playlist.Id": { "type": "integer", "minimum": 0, @@ -336,14 +338,14 @@ "Audio.Details.Base": { "extends": "Media.Details.Base", "properties": { - "genre": { "type": "string" } + "genre": { "$ref": "Array.String" } } }, "Audio.Details.Media": { "extends": "Audio.Details.Base", "properties": { "title": { "type": "string" }, - "artist": { "type": "string" }, + "artist": { "$ref": "Array.String" }, "year": { "type": "integer" }, "rating": { "type": "integer" }, "musicbrainzalbumid": { "type": "string" }, @@ -355,15 +357,15 @@ "properties": { "artistid": { "$ref": "Library.Id", "required": true }, "artist": { "type": "string", "required": true }, - "instrument": { "type": "string" }, - "style": { "type": "string" }, - "mood": { "type": "string" }, + "instrument": { "$ref": "Array.String" }, + "style": { "$ref": "Array.String" }, + "mood": { "$ref": "Array.String" }, "born": { "type": "string" }, "formed": { "type": "string" }, "description": { "type": "string" }, "died": { "type": "string" }, "disbanded": { "type": "string" }, - "yearsactive": { "type": "string" }, + "yearsactive": { "$ref": "Array.String" }, "musicbrainzartistid": { "type": "string" } } }, @@ -372,12 +374,11 @@ "properties": { "albumid": { "$ref": "Library.Id", "required": true }, "description": { "type": "string" }, - "theme": { "type": "string" }, - "mood": { "type": "string" }, - "style": { "type": "string" }, + "theme": { "$ref": "Array.String" }, + "mood": { "$ref": "Array.String" }, + "style": { "$ref": "Array.String" }, "type": { "type": "string" }, - "albumlabel": { "type": "string" }, - "artistid": { "$ref": "Library.Id" } + "albumlabel": { "type": "string" } } }, "Audio.Details.Song": { @@ -385,7 +386,7 @@ "properties": { "songid": { "$ref": "Library.Id", "required": true }, "file": { "type": "string" }, - "albumartist": { "type": "string" }, + "albumartist": { "$ref": "Array.String" }, "album": { "type": "string" }, "track": { "type": "integer" }, "duration": { "type": "integer" }, @@ -394,7 +395,6 @@ "playcount": { "type": "integer" }, "musicbrainztrackid": { "type": "string" }, "musicbrainzartistid": { "type": "string" }, - "artistid": { "$ref": "Library.Id" }, "albumid": { "$ref": "Library.Id" }, "lastplayed": { "type": "string" }, "disc": { "type": "integer" } @@ -403,13 +403,13 @@ "Video.Fields.Movie": { "extends": "Item.Fields.Base", "items": { "type": "string", - "description": "Requesting the cast, set, showlink and/or resume field will result in increased response times", + "description": "Requesting the cast, showlink and/or resume field will result in increased response times", "enum": [ "title", "genre", "year", "rating", "director", "trailer", "tagline", "plot", "plotoutline", "originaltitle", "lastplayed", "playcount", "writer", "studio", "mpaa", "cast", "country", - "imdbnumber", "premiered", "productioncode", "runtime", "set", - "showlink", "streamdetails", "top250", "votes", "fanart", - "thumbnail", "file", "sorttitle", "resume", "setid", "dateadded" ] + "imdbnumber", "runtime", "set", "showlink", "streamdetails", + "top250", "votes", "fanart", "thumbnail", "file", "sorttitle", + "resume", "setid", "dateadded", "tag" ] } }, "Video.Fields.MovieSet": { @@ -538,7 +538,7 @@ "extends": "Video.Details.Item", "properties": { "runtime": { "type": "string" }, - "director": { "type": "string" }, + "director": { "$ref": "Array.String" }, "streamdetails": { "$ref": "Video.Streams" }, "resume": { "$ref": "Video.Resume" } } @@ -547,7 +547,7 @@ "extends": "Video.Details.File", "properties": { "movieid": { "$ref": "Library.Id", "required": true }, - "genre": { "type": "string" }, + "genre": { "$ref": "Array.String" }, "year": { "type": "integer" }, "rating": { "type": "number" }, "trailer": { "type": "string" }, @@ -555,19 +555,18 @@ "plotoutline": { "type": "string" }, "originaltitle": { "type": "string" }, "sorttitle": { "type": "string" }, - "writer": { "type": "string" }, - "studio": { "type": "string" }, + "writer": { "$ref": "Array.String" }, + "studio": { "$ref": "Array.String" }, "mpaa": { "type": "string" }, "cast": { "$ref": "Video.Cast" }, - "country": { "type": "string" }, + "country": { "$ref": "Array.String" }, "imdbnumber": { "type": "string" }, - "premiered": { "type": "string" }, - "productioncode": { "type": "string" }, - "set": { "$ref": "Array.String" }, - "showlink": { "type": "string" }, + "set": { "type": "string" }, + "showlink": { "$ref": "Array.String" }, "top250": { "type": "integer" }, "votes": { "type": "string" }, - "setid": { "$ref": "Array.Integer" } + "setid": { "$ref": "Library.Id" }, + "tag": { "$ref": "Array.String" } } }, "Video.Details.MovieSet": { @@ -588,12 +587,12 @@ "extends": "Video.Details.Item", "properties": { "tvshowid": { "$ref": "Library.Id", "required": true }, - "genre": { "type": "string" }, + "genre": { "$ref": "Array.String" }, "year": { "type": "integer" }, "rating": { "type": "number" }, "originaltitle": { "type": "string" }, "sorttitle": { "type": "string" }, - "studio": { "type": "string" }, + "studio": { "$ref": "Array.String" }, "mpaa": { "type": "string" }, "cast": { "$ref": "Video.Cast" }, "episode": { "type": "integer" }, @@ -621,7 +620,7 @@ "episodeid": { "$ref": "Library.Id", "required": true }, "votes": { "type": "string" }, "rating": { "type": "number" }, - "writer": { "type": "string" }, + "writer": { "$ref": "Array.String" }, "firstaired": { "type": "string" }, "productioncode": { "type": "string" }, "season": { "type": "integer" }, @@ -636,11 +635,11 @@ "extends": "Video.Details.File", "properties": { "musicvideoid": { "$ref": "Library.Id", "required": true }, - "studio": { "type": "string" }, + "studio": { "$ref": "Array.String" }, "year": { "type": "integer" }, "album": { "type": "string" }, - "artist": { "type": "string" }, - "genre": { "type": "string" }, + "artist": { "$ref": "Array.String" }, + "genre": { "$ref": "Array.String" }, "track": { "type": "integer" } } }, @@ -695,7 +694,7 @@ "runtime", "set", "showlink", "streamdetails", "top250", "votes", "firstaired", "season", "episode", "showtitle", "thumbnail", "file", "resume", "artistid", "albumid", "tvshowid", "setid", "watchedepisodes", - "disc" ] + "disc", "tag" ] } }, "List.Item.All": { @@ -703,7 +702,7 @@ "properties": { "id": { "$ref": "Library.Id" }, "type": { "type": "string", "enum": [ "unknown", "movie", "episode", "musicvideo", "song", "picture" ] }, - "albumartist": { "type": "string" }, + "albumartist": { "$ref": "Array.String" }, "album": { "type": "string" }, "track": { "type": "integer" }, "duration": { "type": "integer" }, @@ -715,28 +714,28 @@ "tagline": { "type": "string" }, "plotoutline": { "type": "string" }, "originaltitle": { "type": "string" }, - "writer": { "type": "string" }, - "studio": { "type": "string" }, + "writer": { "$ref": "Array.String" }, + "studio": { "$ref": "Array.String" }, "mpaa": { "type": "string" }, "cast": { "$ref": "Video.Cast" }, "country": { "type": "string" }, "imdbnumber": { "type": "string" }, "premiered": { "type": "string" }, "productioncode": { "type": "string" }, - "set": { "$ref": "Array.String" }, - "showlink": { "type": "string" }, + "set": { "type": "string" }, + "showlink": { "$ref": "Array.String" }, "top250": { "type": "integer" }, "votes": { "type": "string" }, "firstaired": { "type": "string" }, "season": { "type": "integer" }, "episode": { "type": "integer" }, "showtitle": { "type": "string" }, - "artistid": { "$ref": "Library.Id" }, "albumid": { "$ref": "Library.Id" }, - "setid": { "$ref": "Array.Integer" }, + "setid": { "$ref": "Library.Id" }, "tvshowid": { "$ref": "Library.Id" }, "watchedepisodes": { "type": "integer" }, - "disc": { "type": "integer" } + "disc": { "type": "integer" }, + "tag": { "$ref": "Array.String" } } }, "List.Fields.Files": { @@ -833,4 +832,4 @@ } } } -}
\ No newline at end of file +} diff --git a/xbmc/interfaces/python/XBPyThread.cpp b/xbmc/interfaces/python/XBPyThread.cpp index ad1a87babd..435d3ce42d 100644 --- a/xbmc/interfaces/python/XBPyThread.cpp +++ b/xbmc/interfaces/python/XBPyThread.cpp @@ -37,6 +37,8 @@ #include "utils/URIUtils.h" #include "addons/AddonManager.h" #include "addons/Addon.h" +#include "Application.h" +#include "ApplicationMessenger.h" #include "XBPyThread.h" #include "XBPython.h" @@ -54,6 +56,9 @@ extern "C" FILE *fopen_utf8(const char *_Filename, const char *_Mode); #define PY_PATH_SEP DELIM +// Time before ill-behaved scripts are terminated +#define PYTHON_SCRIPT_TIMEOUT 5000 // ms + extern "C" { int xbp_chdir(const char *dirname); @@ -379,7 +384,7 @@ void XBPyThread::Process() //this event has to be fired without holding m_pExecuter->m_critSection //before //Also the GIL (PyEval_AcquireLock) must not be held - //if not obeyed there is still no deadlock because ::stop waits with timeout (smart one!) + //if not obeyed there is still no deadlock because ::stop waits with timeout stoppedEvent.Set(); { CSingleLock lock(m_pExecuter->m_critSection); @@ -442,20 +447,39 @@ void XBPyThread::stop() PyThreadState_Swap(old); PyEval_ReleaseLock(); - if(!stoppedEvent.WaitMSec(5000))//let the script 5 secs for shut stuff down + XbmcThreads::EndTime timeout(PYTHON_SCRIPT_TIMEOUT); + while (!stoppedEvent.WaitMSec(15)) { - CLog::Log(LOGERROR, "XBPyThread::stop - script didn't stop in proper time - lets kill it"); + if (timeout.IsTimePast()) + { + CLog::Log(LOGERROR, "XBPyThread::stop - script didn't stop in %d seconds - let's kill it", PYTHON_SCRIPT_TIMEOUT / 1000); + break; + } + // We can't empty-spin in the main thread and expect scripts to be able to + // dismantle themselves. Python dialogs aren't normal XBMC dialogs, they rely + // on TMSG_GUI_PYTHON_DIALOG messages, so pump the message loop. + if (g_application.IsCurrentThread()) + { + CSingleExit ex(g_graphicsContext); + CApplicationMessenger::Get().ProcessMessages(); + } } + // Useful for add-on performance metrics + if (!timeout.IsTimePast()) + CLog::Log(LOGDEBUG, "XBPyThread::stop - script termination took %dms", PYTHON_SCRIPT_TIMEOUT - timeout.MillisLeft()); //everything which didn't exit by now gets killed PyEval_AcquireLock(); old = PyThreadState_Swap((PyThreadState*)m_threadState); for(PyThreadState* state = ((PyThreadState*)m_threadState)->interp->tstate_head; state; state = state->next) { + // Raise a SystemExit exception in python threads Py_XDECREF(state->async_exc); state->async_exc = PyExc_SystemExit; Py_XINCREF(state->async_exc); } + // If a dialog entered its doModal(), we need to wake it to see the exception + g_pythonParser.PulseGlobalEvent(); PyThreadState_Swap(old); PyEval_ReleaseLock(); diff --git a/xbmc/interfaces/python/XBPython.cpp b/xbmc/interfaces/python/XBPython.cpp index 4469f0a431..e0d00f6e84 100644 --- a/xbmc/interfaces/python/XBPython.cpp +++ b/xbmc/interfaces/python/XBPython.cpp @@ -471,6 +471,7 @@ void XBPython::InitializeInterpreter(ADDON::AddonPtr addon) InitGUIModule(); // init xbmcgui modules InitAddonModule(); // init xbmcaddon modules InitVFSModule(); // init xbmcvfs modules + InitVFSTypes(); CStdString addonVer = ADDON::GetXbmcApiVersionDependency(addon); bool bwcompatMode = (addon.get() == NULL || (ADDON::AddonVersion(addonVer) <= ADDON::AddonVersion("1.0"))); @@ -521,7 +522,7 @@ void XBPython::Initialize() // Info about interesting python envvars available // at http://docs.python.org/using/cmdline.html#environment-variables -#if !defined(_WIN32) +#if !defined(_WIN32) && !defined(TARGET_ANDROID) /* PYTHONOPTIMIZE is set off intentionally when using external Python. Reason for this is because we cannot be sure what version of Python was used to compile the various Python object files (i.e. .pyo, @@ -552,6 +553,13 @@ void XBPython::Initialize() buf = "OS=win32"; pgwin32_putenv(buf.c_str()); +#elif defined(TARGET_ANDROID) + CStdString apkPath = getenv("XBMC_ANDROID_APK"); + apkPath += "/assets/python2.6"; + setenv("PYTHONHOME",apkPath.c_str(), 1); + setenv("PYTHONPATH", "", 1); + setenv("PYTHONOPTIMIZE","",1); + setenv("PYTHONNOUSERSITE","1",1); #endif if (PyEval_ThreadsInitialized()) diff --git a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowDialog.cpp b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowDialog.cpp index 1be83abaa9..826a27a2de 100644 --- a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowDialog.cpp +++ b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowDialog.cpp @@ -21,7 +21,6 @@ #include "GUIPythonWindowDialog.h" #include "guilib/GUIWindowManager.h" -#include "Application.h" #include "threads/SingleLock.h" CGUIPythonWindowDialog::CGUIPythonWindowDialog(int id) diff --git a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXMLDialog.cpp b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXMLDialog.cpp index f50c4f6e72..88fbc120a8 100644 --- a/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXMLDialog.cpp +++ b/xbmc/interfaces/python/xbmcmodule/GUIPythonWindowXMLDialog.cpp @@ -21,7 +21,6 @@ #include "GUIPythonWindowXMLDialog.h" #include "guilib/GUIWindowManager.h" -#include "Application.h" #include "threads/SingleLock.h" CGUIPythonWindowXMLDialog::CGUIPythonWindowXMLDialog(int id, CStdString strXML, CStdString strFallBackPath) diff --git a/xbmc/interfaces/python/xbmcmodule/control.cpp b/xbmc/interfaces/python/xbmcmodule/control.cpp index e6420cc69d..06b5226b61 100644 --- a/xbmc/interfaces/python/xbmcmodule/control.cpp +++ b/xbmc/interfaces/python/xbmcmodule/control.cpp @@ -21,7 +21,6 @@ #include "control.h" #include "pyutil.h" -#include "GUIInfoManager.h" #include "guilib/GUIControlFactory.h" #include "guilib/GUITexture.h" #include "utils/StringUtils.h" diff --git a/xbmc/interfaces/python/xbmcmodule/dialog.cpp b/xbmc/interfaces/python/xbmcmodule/dialog.cpp index fb2aed8ba3..3fc08b4e56 100644 --- a/xbmc/interfaces/python/xbmcmodule/dialog.cpp +++ b/xbmc/interfaces/python/xbmcmodule/dialog.cpp @@ -21,13 +21,12 @@ #include "dialog.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "settings/Settings.h" #include "pyutil.h" #include "pythreadstate.h" #include "dialogs/GUIDialogFileBrowser.h" #include "dialogs/GUIDialogNumeric.h" -#include "dialogs/GUIDialogGamepad.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogProgress.h" diff --git a/xbmc/interfaces/python/xbmcmodule/keyboard.cpp b/xbmc/interfaces/python/xbmcmodule/keyboard.cpp index 5597f6b7b9..83b3c1ec8f 100644 --- a/xbmc/interfaces/python/xbmcmodule/keyboard.cpp +++ b/xbmc/interfaces/python/xbmcmodule/keyboard.cpp @@ -23,8 +23,8 @@ #include "pythreadstate.h" #include "pyutil.h" #include "guilib/GUIWindowManager.h" -#include "dialogs/GUIDialogKeyboard.h" -#include "Application.h" +#include "dialogs/GUIDialogKeyboardGeneric.h" +#include "ApplicationMessenger.h" using namespace std; @@ -58,7 +58,7 @@ namespace PYXBMC self->strHeading = utf8Heading; self->bHidden = (0 != bHidden); PyXBMCGUILock(); - self->dlg = (CGUIDialogKeyboard*)g_windowManager.GetWindow(WINDOW_DIALOG_KEYBOARD); + self->dlg = (CGUIDialogKeyboardGeneric*)g_windowManager.GetWindow(WINDOW_DIALOG_KEYBOARD); PyXBMCGUIUnlock(); return (PyObject*)self; @@ -82,7 +82,7 @@ namespace PYXBMC PyObject* Keyboard_DoModal(Keyboard *self, PyObject *args) { - CGUIDialogKeyboard *pKeyboard = ((Keyboard*)self)->dlg; + CGUIDialogKeyboardGeneric *pKeyboard = ((Keyboard*)self)->dlg; if(!pKeyboard) { PyErr_SetString(PyExc_SystemError, "Unable to load virtual keyboard"); @@ -127,7 +127,7 @@ namespace PYXBMC if (line && !PyXBMCGetUnicodeString(utf8Line, line, 1)) return NULL; self->strDefault = utf8Line; - CGUIDialogKeyboard *pKeyboard = ((Keyboard*)self)->dlg; + CGUIDialogKeyboardGeneric *pKeyboard = ((Keyboard*)self)->dlg; if(!pKeyboard) { PyErr_SetString(PyExc_SystemError, "Unable to load keyboard"); @@ -157,7 +157,7 @@ namespace PYXBMC if (!PyArg_ParseTuple(args, (char*)"|b", &bHidden)) return NULL; self->bHidden = (0 != bHidden); - CGUIDialogKeyboard *pKeyboard = ((Keyboard*)self)->dlg; + CGUIDialogKeyboardGeneric *pKeyboard = ((Keyboard*)self)->dlg; if(!pKeyboard) { PyErr_SetString(PyExc_SystemError, "Unable to load keyboard"); @@ -190,7 +190,7 @@ namespace PYXBMC if (line && !PyXBMCGetUnicodeString(utf8Line, line, 1)) return NULL; self->strHeading = utf8Line; - CGUIDialogKeyboard *pKeyboard = ((Keyboard*)self)->dlg; + CGUIDialogKeyboardGeneric *pKeyboard = ((Keyboard*)self)->dlg; if(!pKeyboard) { PyErr_SetString(PyExc_SystemError, "Unable to load keyboard"); @@ -217,7 +217,7 @@ namespace PYXBMC PyObject* Keyboard_GetText(Keyboard *self, PyObject *args) { - CGUIDialogKeyboard *pKeyboard = ((Keyboard*)self)->dlg; + CGUIDialogKeyboardGeneric *pKeyboard = ((Keyboard*)self)->dlg; if(!pKeyboard) { PyErr_SetString(PyExc_SystemError, "Unable to load keyboard"); @@ -239,7 +239,7 @@ namespace PYXBMC PyObject* Keyboard_IsConfirmed(Keyboard *self, PyObject *args) { - CGUIDialogKeyboard *pKeyboard = ((Keyboard*)self)->dlg; + CGUIDialogKeyboardGeneric *pKeyboard = ((Keyboard*)self)->dlg; if(!pKeyboard) { PyErr_SetString(PyExc_SystemError, "Unable to load keyboard"); diff --git a/xbmc/interfaces/python/xbmcmodule/keyboard.h b/xbmc/interfaces/python/xbmcmodule/keyboard.h index d164be5b15..4b2f40d12a 100644 --- a/xbmc/interfaces/python/xbmcmodule/keyboard.h +++ b/xbmc/interfaces/python/xbmcmodule/keyboard.h @@ -24,7 +24,7 @@ #include <string> #pragma once -class CGUIDialogKeyboard; +class CGUIDialogKeyboardGeneric; #ifdef __cplusplus extern "C" { @@ -37,7 +37,7 @@ namespace PYXBMC std::string strDefault; std::string strHeading; bool bHidden; - CGUIDialogKeyboard* dlg; + CGUIDialogKeyboardGeneric* dlg; } Keyboard; extern PyTypeObject Keyboard_Type; diff --git a/xbmc/interfaces/python/xbmcmodule/listitem.cpp b/xbmc/interfaces/python/xbmcmodule/listitem.cpp index 5898a4433a..5aa7363ce1 100644 --- a/xbmc/interfaces/python/xbmcmodule/listitem.cpp +++ b/xbmc/interfaces/python/xbmcmodule/listitem.cpp @@ -351,6 +351,7 @@ namespace PYXBMC " plotoutline : string (Short Description)\n" " title : string (Big Fan)\n" " originaltitle : string (Big Fan)\n" + " sorttitle : string (Big Fan)\n" " duration : string (3:18)\n" " studio : string (Warner Bros.)\n" " tagline : string (An awesome movie) - short description of movie\n" @@ -504,6 +505,8 @@ namespace PYXBMC self->item->GetVideoInfoTag()->m_strTitle = tmp; else if (strcmpi(PyString_AsString(key), "originaltitle") == 0) self->item->GetVideoInfoTag()->m_strOriginalTitle = tmp; + else if (strcmpi(PyString_AsString(key), "sorttitle") == 0) + self->item->GetVideoInfoTag()->m_strSortTitle = tmp; else if (strcmpi(PyString_AsString(key), "duration") == 0) self->item->GetVideoInfoTag()->m_strRuntime = tmp; else if (strcmpi(PyString_AsString(key), "studio") == 0) @@ -755,13 +758,13 @@ namespace PYXBMC " You can use the above as keywords for arguments and skip certain optional arguments.\n" " Once you use a keyword, all following arguments require the keyword.\n" "\n" - " Some of these are treated internally by XBMC, such as the 'StartOffset' property, which is\n" - " the offset in seconds at which to start playback of an item. Others may be used in the skin\n" - " to add extra information, such as 'WatchedCount' for tvshow items\n" + " Some of these are treated internally by XBMC.\n" + " Others may be used in the skin to add extra information, such as 'WatchedCount' for tvshow items\n" "\n" "example:\n" " - self.list.getSelectedItem().setProperty('AspectRatio', '1.85 : 1')\n" - " - self.list.getSelectedItem().setProperty('StartOffset', '256.4')\n"); + " - self.list.getSelectedItem().setProperty('TotalTime', '3668.4')\n" + " - self.list.getSelectedItem().setProperty('ResumeTime', '306.8')\n"); PyObject* ListItem_SetProperty(ListItem *self, PyObject *args, PyObject *kwds) { @@ -798,6 +801,10 @@ namespace PYXBMC { // special case for mime type - don't actually stored in a property, self->item->SetMimeType(uText); } + else if (lowerKey.CompareNoCase("totaltime") == 0) + self->item->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds = (float)atof(uText.c_str()); + else if (lowerKey.CompareNoCase("resumetime") == 0) + self->item->GetVideoInfoTag()->m_resumePoint.timeInSeconds = (float)atof(uText.c_str()); else if (lowerKey.CompareNoCase("specialsort") == 0) { if (uText == "bottom") @@ -851,6 +858,10 @@ namespace PYXBMC // we store it in item.m_lStartOffset instead value.Format("%f", self->item->m_lStartOffset / 75.0); } + else if (lowerKey.CompareNoCase("totaltime") == 0) + value.Format("%f", self->item->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds); + else if (lowerKey.CompareNoCase("resumetime") == 0) + value.Format("%f", self->item->GetVideoInfoTag()->m_resumePoint.timeInSeconds); else value = self->item->GetProperty(lowerKey.ToLower()).asString(); PyXBMCGUIUnlock(); diff --git a/xbmc/interfaces/python/xbmcmodule/player.cpp b/xbmc/interfaces/python/xbmcmodule/player.cpp index 257d97a903..adc605d322 100644 --- a/xbmc/interfaces/python/xbmcmodule/player.cpp +++ b/xbmc/interfaces/python/xbmcmodule/player.cpp @@ -21,6 +21,7 @@ #include "pyutil.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "GUIInfoManager.h" #include "PlayListPlayer.h" #include "player.h" @@ -139,7 +140,7 @@ namespace PYXBMC } CPyThreadState pyState; - g_application.getApplicationMessenger().PlayListPlayerPlay(g_playlistPlayer.GetCurrentSong()); + CApplicationMessenger::Get().PlayListPlayerPlay(g_playlistPlayer.GetCurrentSong()); } else if ((PyString_Check(pObject) || PyUnicode_Check(pObject)) && pObjectListItem != NULL && ListItem_CheckExact(pObjectListItem)) { @@ -151,14 +152,14 @@ namespace PYXBMC pListItem->item->SetPath(PyString_AsString(pObject)); CPyThreadState pyState; - g_application.getApplicationMessenger().PlayFile((const CFileItem)*pListItem->item, false); + CApplicationMessenger::Get().PlayFile((const CFileItem)*pListItem->item, false); } else if (PyString_Check(pObject) || PyUnicode_Check(pObject)) { CFileItem item(PyString_AsString(pObject), false); CPyThreadState pyState; - g_application.getApplicationMessenger().MediaPlay(item.GetPath()); + CApplicationMessenger::Get().MediaPlay(item.GetPath()); } else if (PlayList_Check(pObject)) { @@ -168,7 +169,7 @@ namespace PYXBMC g_playlistPlayer.SetCurrentPlaylist(pPlayList->iPlayList); CPyThreadState pyState; - g_application.getApplicationMessenger().PlayListPlayerPlay(); + CApplicationMessenger::Get().PlayListPlayerPlay(); } Py_INCREF(Py_None); @@ -182,7 +183,7 @@ namespace PYXBMC PyObject* pyPlayer_Stop(PyObject *self, PyObject *args) { CPyThreadState pyState; - g_application.getApplicationMessenger().MediaStop(); + CApplicationMessenger::Get().MediaStop(); pyState.Restore(); Py_INCREF(Py_None); @@ -196,7 +197,7 @@ namespace PYXBMC PyObject* Player_Pause(PyObject *self, PyObject *args) { CPyThreadState pyState; - g_application.getApplicationMessenger().MediaPause(); + CApplicationMessenger::Get().MediaPause(); pyState.Restore(); Py_INCREF(Py_None); @@ -213,7 +214,7 @@ namespace PYXBMC g_application.m_eForcedNextPlayer = self->playerCore; CPyThreadState pyState; - g_application.getApplicationMessenger().PlayListPlayerNext(); + CApplicationMessenger::Get().PlayListPlayerNext(); pyState.Restore(); Py_INCREF(Py_None); @@ -230,7 +231,7 @@ namespace PYXBMC g_application.m_eForcedNextPlayer = self->playerCore; CPyThreadState pyState; - g_application.getApplicationMessenger().PlayListPlayerPrevious(); + CApplicationMessenger::Get().PlayListPlayerPrevious(); pyState.Restore(); Py_INCREF(Py_None); @@ -256,7 +257,7 @@ namespace PYXBMC g_playlistPlayer.SetCurrentSong(iItem); CPyThreadState pyState; - g_application.getApplicationMessenger().PlayListPlayerPlay(iItem); + CApplicationMessenger::Get().PlayListPlayerPlay(iItem); pyState.Restore(); //g_playlistPlayer.Play(iItem); diff --git a/xbmc/interfaces/python/xbmcmodule/pyutil.cpp b/xbmc/interfaces/python/xbmcmodule/pyutil.cpp index 0405bd9434..9213732f54 100644 --- a/xbmc/interfaces/python/xbmcmodule/pyutil.cpp +++ b/xbmc/interfaces/python/xbmcmodule/pyutil.cpp @@ -29,7 +29,7 @@ #include "utils/CharsetConverter.h" #include "threads/CriticalSection.h" #include "threads/SingleLock.h" -#include "Application.h" +#include "ApplicationMessenger.h" using namespace std; @@ -87,7 +87,7 @@ namespace PYXBMC { CPyThreadState pyState; ThreadMessage tMsg = {message, param1, param2}; - g_application.getApplicationMessenger().SendMessage(tMsg, true); + CApplicationMessenger::Get().SendMessage(tMsg, true); } static char defaultImage[1024]; diff --git a/xbmc/interfaces/python/xbmcmodule/window.cpp b/xbmc/interfaces/python/xbmcmodule/window.cpp index 69780c4cb0..e24b9c9d29 100644 --- a/xbmc/interfaces/python/xbmcmodule/window.cpp +++ b/xbmc/interfaces/python/xbmcmodule/window.cpp @@ -33,7 +33,9 @@ #include "guilib/GUIWindowManager.h" #include "settings/Settings.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "threads/SingleLock.h" +#include "utils/log.h" using namespace std; @@ -425,13 +427,13 @@ namespace PYXBMC CPyThreadState pyState; ThreadMessage tMsg = {TMSG_GUI_PYTHON_DIALOG, WindowXMLDialog_Check(self) ? 1 : 0, 1}; tMsg.lpVoid = self->pWindow; - g_application.getApplicationMessenger().SendMessage(tMsg, true); + CApplicationMessenger::Get().SendMessage(tMsg, true); } else { CPyThreadState pyState; vector<CStdString> params; - g_application.getApplicationMessenger().ActivateWindow(self->iWindowId, params, false); + CApplicationMessenger::Get().ActivateWindow(self->iWindowId, params, false); } Py_INCREF(Py_None); @@ -463,13 +465,13 @@ namespace PYXBMC CPyThreadState pyState; ThreadMessage tMsg = {TMSG_GUI_PYTHON_DIALOG, WindowXMLDialog_Check(self) ? 1 : 0, 0}; tMsg.lpVoid = self->pWindow; - g_application.getApplicationMessenger().SendMessage(tMsg, true); + CApplicationMessenger::Get().SendMessage(tMsg, true); } else { CPyThreadState pyState; vector<CStdString> params; - g_application.getApplicationMessenger().ActivateWindow(self->iOldWindowId, params, false); + CApplicationMessenger::Get().ActivateWindow(self->iOldWindowId, params, false); } self->iOldWindowId = 0; @@ -536,6 +538,14 @@ namespace PYXBMC while (self->bModal && !g_application.m_bStop) { + // Check if XBPyThread::stop() raised a SystemExit exception + if (PyThreadState_Get()->async_exc == PyExc_SystemExit) + { + CLog::Log(LOGDEBUG, "PYTHON: doModal() encountered a SystemExit exception, closing window and returning"); + Window_Close(self, NULL); + break; + } + PyXBMC_MakePendingCalls(); CPyThreadState pyState; @@ -705,7 +715,7 @@ namespace PYXBMC CPyThreadState state; CGUIMessage msg(GUI_MSG_ADD_CONTROL, 0, 0); msg.SetPointer(pControl->pGUIControl); - g_application.getApplicationMessenger().SendGUIMessage(msg, self->iWindowId, wait); + CApplicationMessenger::Get().SendGUIMessage(msg, self->iWindowId, wait); } return true; } @@ -746,7 +756,7 @@ namespace PYXBMC CPyThreadState state; CGUIMessage msg(GUI_MSG_REMOVE_CONTROL, 0, 0); msg.SetPointer(pControl->pGUIControl); - g_application.getApplicationMessenger().SendGUIMessage(msg, self->iWindowId, wait); + CApplicationMessenger::Get().SendGUIMessage(msg, self->iWindowId, wait); } // initialize control to zero diff --git a/xbmc/interfaces/python/xbmcmodule/xbmcmodule.cpp b/xbmc/interfaces/python/xbmcmodule/xbmcmodule.cpp index 462067412b..5b15888b0f 100644 --- a/xbmc/interfaces/python/xbmcmodule/xbmcmodule.cpp +++ b/xbmc/interfaces/python/xbmcmodule/xbmcmodule.cpp @@ -39,6 +39,7 @@ #include "guilib/GUIWindowManager.h" #include "guilib/GUIAudioManager.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "utils/Crc32.h" #include "utils/URIUtils.h" #include "Util.h" @@ -55,6 +56,7 @@ #include "utils/log.h" #include "pyrendercapture.h" #include "monitor.h" +#include "URL.h" // include for constants #include "pyutil.h" @@ -130,16 +132,16 @@ namespace PYXBMC PyDoc_STRVAR(output__doc__, "'xbmc.output()' is depreciated and will be removed in future releases,\n" "please use 'xbmc.log()' instead"); - + PyObject* XBMC_Output(PyObject *self, PyObject *args, PyObject *kwds) { CLog::Log(LOGWARNING,"'xbmc.output()' is depreciated and will be removed in future releases, please use 'xbmc.log()' instead"); return XBMC_Log(self, args, kwds); } - + // shutdown() method PyDoc_STRVAR(shutdown__doc__, - "shutdown() -- Shutdown the xbox.\n" + "shutdown() -- Shutdown the system.\n" "\n" "example:\n" " - xbmc.shutdown()\n"); @@ -147,7 +149,7 @@ namespace PYXBMC PyObject* XBMC_Shutdown(PyObject *self, PyObject *args) { ThreadMessage tMsg = {TMSG_SHUTDOWN}; - g_application.getApplicationMessenger().SendMessage(tMsg); + CApplicationMessenger::Get().SendMessage(tMsg); Py_INCREF(Py_None); return Py_None; @@ -155,7 +157,7 @@ namespace PYXBMC // restart() method PyDoc_STRVAR(restart__doc__, - "restart() -- Restart the xbox.\n" + "restart() -- Restart the system.\n" "\n" "example:\n" " - xbmc.restart()\n"); @@ -163,7 +165,7 @@ namespace PYXBMC PyObject* XBMC_Restart(PyObject *self, PyObject *args) { ThreadMessage tMsg = {TMSG_RESTART}; - g_application.getApplicationMessenger().SendMessage(tMsg); + CApplicationMessenger::Get().SendMessage(tMsg); Py_INCREF(Py_None); return Py_None; @@ -185,7 +187,7 @@ namespace PYXBMC ThreadMessage tMsg = {TMSG_EXECUTE_SCRIPT}; tMsg.strParam = cLine; - g_application.getApplicationMessenger().SendMessage(tMsg); + CApplicationMessenger::Get().SendMessage(tMsg); Py_INCREF(Py_None); return Py_None; @@ -211,7 +213,7 @@ namespace PYXBMC bool bWait = false; if (!PyArg_ParseTuple(args, (char*)"s|b", &cLine, &bWait)) return NULL; - g_application.getApplicationMessenger().ExecBuiltIn(cLine, bWait); + CApplicationMessenger::Get().ExecBuiltIn(cLine, bWait); Py_INCREF(Py_None); return Py_None; @@ -936,7 +938,54 @@ namespace PYXBMC return Py_BuildValue((char*)"b", exists); } - + + // startServer() method + PyDoc_STRVAR(startServer__doc__, + "startServer(typ, bStart, bWait) -- start or stop a server.\n" + "\n" + "typ : integer - use SERVER_* constants\n" + "\n" + "bStart : bool - start (True) or stop (False) a server\n" + "\n" + "bWait : [opt] bool - wait on stop before returning (not supported by all servers)\n" + "\n" + "returnValue : bool - True or False\n" + "example:\n" + " - xbmc.startServer(xbmc.SERVER_AIRPLAYSERVER, False)\n"); + + PyObject* XBMC_StartServer(PyObject *self, PyObject *args, PyObject *kwds) + { + static const char *keywords[] = { + "typ", + "bStart", + "bWait", + NULL}; + + int iTyp = 0; + char bStart = false; + char bWait = false; + bool ret = false; + + if (!PyArg_ParseTupleAndKeywords( + args, + kwds, + (char*)"ib|b", + (char**)keywords, + &iTyp, + &bStart, + &bWait)) + { + return NULL; + } + + { + CPyThreadState save; + ret = g_application.StartServer((CApplication::ESERVERS)iTyp, bStart != 0, bWait != 0); + } + + return Py_BuildValue((char*)"b", ret); + } + // define c functions to be used in python here PyMethodDef xbmcMethods[] = { {(char*)"output", (PyCFunction)XBMC_Output, METH_VARARGS|METH_KEYWORDS, output__doc__}, @@ -983,6 +1032,8 @@ namespace PYXBMC {(char*)"skinHasImage", (PyCFunction)XBMC_SkinHasImage, METH_VARARGS|METH_KEYWORDS, skinHasImage__doc__}, + {(char*)"startServer", (PyCFunction)XBMC_StartServer, METH_VARARGS|METH_KEYWORDS, startServer__doc__}, + {NULL, NULL, 0, NULL} }; @@ -1074,6 +1125,16 @@ namespace PYXBMC PyModule_AddIntConstant(pXbmcModule, (char*)"PLAYER_CORE_MPLAYER", EPC_MPLAYER); PyModule_AddIntConstant(pXbmcModule, (char*)"PLAYER_CORE_PAPLAYER", EPC_PAPLAYER); + // server constants for startServer method + PyModule_AddIntConstant(pXbmcModule, (char*)"SERVER_WEBSERVER", CApplication::ES_WEBSERVER); + PyModule_AddIntConstant(pXbmcModule, (char*)"SERVER_AIRPLAYSERVER", CApplication::ES_AIRPLAYSERVER); + PyModule_AddIntConstant(pXbmcModule, (char*)"SERVER_UPNPSERVER", CApplication::ES_UPNPSERVER); + PyModule_AddIntConstant(pXbmcModule, (char*)"SERVER_UPNPRENDERER", CApplication::ES_UPNPRENDERER); + PyModule_AddIntConstant(pXbmcModule, (char*)"SERVER_EVENTSERVER", CApplication::ES_EVENTSERVER); + PyModule_AddIntConstant(pXbmcModule, (char*)"SERVER_JSONRPCSERVER", CApplication::ES_JSONRPCSERVER); + PyModule_AddIntConstant(pXbmcModule, (char*)"SERVER_ZEROCONF", CApplication::ES_ZEROCONF); + + // dvd state constants PyModule_AddIntConstant(pXbmcModule, (char*)"TRAY_OPEN", TRAY_OPEN); PyModule_AddIntConstant(pXbmcModule, (char*)"DRIVE_NOT_READY", DRIVE_NOT_READY); diff --git a/xbmc/interfaces/python/xbmcmodule/xbmcplugin.cpp b/xbmc/interfaces/python/xbmcmodule/xbmcplugin.cpp index c4b2aa24ec..79de044675 100644 --- a/xbmc/interfaces/python/xbmcmodule/xbmcplugin.cpp +++ b/xbmc/interfaces/python/xbmcmodule/xbmcplugin.cpp @@ -255,7 +255,8 @@ namespace PYXBMC " applies to: SORT_METHOD_NONE, SORT_METHOD_UNSORTED, SORT_METHOD_VIDEO_TITLE,\n" " SORT_METHOD_TRACKNUM, SORT_METHOD_FILE, SORT_METHOD_TITLE\n" " SORT_METHOD_TITLE_IGNORE_THE, SORT_METHOD_LABEL\n" - " SORT_METHOD_LABEL_IGNORE_THE\n" + " SORT_METHOD_LABEL_IGNORE_THE, SORT_METHOD_VIDEO_SORT_TITLE,\n" + " SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE\n" "\n" "*Note, You can use the above as keywords for arguments and skip certain optional arguments.\n" " Once you use a keyword, all following arguments require the keyword.\n" @@ -623,6 +624,8 @@ namespace PYXBMC PyModule_AddIntConstant(pXbmcPluginModule, (char*)"SORT_METHOD_UNSORTED", SORT_METHOD_UNSORTED); PyModule_AddIntConstant(pXbmcPluginModule, (char*)"SORT_METHOD_BITRATE", SORT_METHOD_BITRATE); PyModule_AddIntConstant(pXbmcPluginModule, (char*)"SORT_METHOD_LISTENERS", SORT_METHOD_LISTENERS); + PyModule_AddIntConstant(pXbmcPluginModule, (char*)"SORT_METHOD_VIDEO_SORT_TITLE", SORT_METHOD_VIDEO_SORT_TITLE); + PyModule_AddIntConstant(pXbmcPluginModule, (char*)"SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE", SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE); } } diff --git a/xbmc/interfaces/python/xbmcmodule/xbmcvfsmodule.cpp b/xbmc/interfaces/python/xbmcmodule/xbmcvfsmodule.cpp index 368daa6559..f899ccbd02 100644 --- a/xbmc/interfaces/python/xbmcmodule/xbmcvfsmodule.cpp +++ b/xbmc/interfaces/python/xbmcmodule/xbmcvfsmodule.cpp @@ -421,7 +421,7 @@ extern "C" { return NULL; int64_t size = self->pFile->GetLength(); if (!readBytes || readBytes > size) - readBytes = size; + readBytes = (unsigned int) size; char* buffer = new char[readBytes + 1]; PyObject* ret = NULL; if (buffer) @@ -455,7 +455,7 @@ extern "C" { return NULL; CPyThreadState pyState; - bool bResult = self->pFile->Write( (void*) pBuffer, strlen( pBuffer ) + 1 ); + bool bResult = self->pFile->Write( (void*) pBuffer, strlen( pBuffer ) + 1 ) > 0 ? true : false; pyState.Restore(); return Py_BuildValue((char*)"b", bResult); diff --git a/xbmc/linux/LinuxTimezone.cpp b/xbmc/linux/LinuxTimezone.cpp index 6d593696d5..6965b69cee 100644 --- a/xbmc/linux/LinuxTimezone.cpp +++ b/xbmc/linux/LinuxTimezone.cpp @@ -21,6 +21,9 @@ #include <time.h> #include "system.h" +#ifdef TARGET_ANDROID +#include "linux/getdelim.h" +#endif #include "PlatformInclude.h" #include "LinuxTimezone.h" #include "utils/SystemInfo.h" diff --git a/xbmc/linux/Makefile.in b/xbmc/linux/Makefile.in index 43f552b9c7..412357a74c 100644 --- a/xbmc/linux/Makefile.in +++ b/xbmc/linux/Makefile.in @@ -16,6 +16,10 @@ SRCS=ConvUtils.cpp \ XMemUtils.cpp \ XTimeUtils.cpp \ +ifeq (@USE_ANDROID@,1) +SRCS+=getdelim.c +endif + LIB=linux.a include @abs_top_srcdir@/Makefile.include diff --git a/xbmc/linux/XFileUtils.cpp b/xbmc/linux/XFileUtils.cpp index 76257a4197..8e19ff1004 100644 --- a/xbmc/linux/XFileUtils.cpp +++ b/xbmc/linux/XFileUtils.cpp @@ -29,7 +29,7 @@ #include "XHandle.h" #include <sys/types.h> #include <sys/stat.h> -#if !defined(TARGET_DARWIN) && !defined(__FreeBSD__) +#if !defined(TARGET_DARWIN) && !defined(__FreeBSD__) && !defined(__ANDROID__) #include <sys/vfs.h> #else #include <sys/param.h> @@ -38,6 +38,14 @@ #include <dirent.h> #include <errno.h> +#if defined(__ANDROID__) +#include <sys/file.h> +#include <sys/statfs.h> + +/* from android header: note: this corresponds to the kernel's statfs64 type */ +//typedef struct statfs statfs64; +#endif + #include "storage/cdioSupport.h" #include "utils/log.h" @@ -60,7 +68,7 @@ HANDLE FindFirstFile(LPCSTR szPath,LPWIN32_FIND_DATA lpFindData) strPath.Replace("\\","/"); // if the file name is a directory then we add a * to look for all files in this directory -#if defined(TARGET_DARWIN) || defined(__FreeBSD__) +#if defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(__ANDROID__) DIR *testDir = opendir(strPath.c_str()); #else DIR *testDir = opendir(szPath); @@ -97,7 +105,13 @@ HANDLE FindFirstFile(LPCSTR szPath,LPWIN32_FIND_DATA lpFindData) return(INVALID_HANDLE_VALUE); struct dirent **namelist = NULL; +#if defined(__ANDROID__) + // android is more strict with the sort function. Let's hope it is implemented correctly. + typedef int (*sortFunc)(const struct dirent ** a, const struct dirent **b); + int n = scandir(strDir, &namelist, 0, (sortFunc)alphasort); +#else int n = scandir(strDir, &namelist, 0, alphasort); +#endif CXHandle *pHandle = new CXHandle(CXHandle::HND_FIND_FILE); pHandle->m_FindFileDir = strDir; @@ -575,9 +589,16 @@ BOOL GetDiskFreeSpaceEx( ) { +#if defined(__ANDROID__) + struct statfs fsInfo; + // is 64-bit on android + if (statfs(CSpecialProtocol::TranslatePath(lpDirectoryName), &fsInfo) != 0) + return false; +#else struct statfs64 fsInfo; if (statfs64(CSpecialProtocol::TranslatePath(lpDirectoryName), &fsInfo) != 0) return false; +#endif if (lpFreeBytesAvailable) lpFreeBytesAvailable->QuadPart = (ULONGLONG)fsInfo.f_bavail * (ULONGLONG)fsInfo.f_bsize; diff --git a/xbmc/linux/XTimeUtils.cpp b/xbmc/linux/XTimeUtils.cpp index ac141d1bd6..818d5eb456 100644 --- a/xbmc/linux/XTimeUtils.cpp +++ b/xbmc/linux/XTimeUtils.cpp @@ -35,6 +35,10 @@ #include <CoreVideo/CVHostTime.h> #endif +#if defined(__ANDROID__) +#include <time64.h> +#endif + #define WIN32_TIME_OFFSET ((unsigned long long)(369 * 365 + 89) * 24 * 3600 * 10000000) /* @@ -55,13 +59,7 @@ void WINAPI Sleep(DWORD dwMilliSeconds) } #endif - struct timespec req; - req.tv_sec = dwMilliSeconds / 1000; - req.tv_nsec = (dwMilliSeconds % 1000) * 1000000; - - // many calls will be interupted. so we keep looping till we're done. - while ( nanosleep(&req, &req) == -1 && errno == EINTR && (req.tv_nsec > 0 || req.tv_sec > 0)) - ; + usleep(dwMilliSeconds * 1000); } VOID GetLocalTime(LPSYSTEMTIME sysTime) @@ -114,7 +112,12 @@ BOOL SystemTimeToFileTime(const SYSTEMTIME* lpSystemTime, LPFILETIME lpFileTi #if defined(TARGET_DARWIN) CAtomicSpinLock lock(timegm_lock); #endif + +#if defined(__ANDROID__) + time64_t t = timegm64(&sysTime); +#else time_t t = timegm(&sysTime); +#endif LARGE_INTEGER result; result.QuadPart = (long long) t * 10000000 + (long long) lpSystemTime->wMilliseconds * 10000; diff --git a/xbmc/linux/getdelim.c b/xbmc/linux/getdelim.c new file mode 100644 index 0000000000..aab1641911 --- /dev/null +++ b/xbmc/linux/getdelim.c @@ -0,0 +1,104 @@ +/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <errno.h> + +/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR + (and null-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'd as + necessary. Returns the number of characters read (not including the + null terminator), or -1 on error or EOF. */ + +ssize_t +getdelim (lineptr, n, terminator, stream) + char **lineptr; + size_t *n; + int terminator; + FILE *stream; +{ + char *line, *p; + size_t size, copy; + + if (stream == NULL || lineptr == NULL || n == NULL) + { + errno = EINVAL; + return -1; + } + + if (ferror (stream)) + return -1; + + /* Make sure we have a line buffer to start with. */ + if (*lineptr == NULL || *n < 2) /* !seen and no buf yet need 2 chars. */ + { +#ifndef MAX_CANON +#define MAX_CANON 256 +#endif + line = realloc (*lineptr, MAX_CANON); + if (line == NULL) + return -1; + *lineptr = line; + *n = MAX_CANON; + } + + line = *lineptr; + size = *n; + + copy = size; + p = line; + + while (1) + { + size_t len; + + while (--copy > 0) + { + register int c = getc (stream); + if (c == EOF) + goto lose; + else if ((*p++ = c) == terminator) + goto win; + } + + /* Need to enlarge the line buffer. */ + len = p - line; + size *= 2; + line = realloc (line, size); + if (line == NULL) + goto lose; + *lineptr = line; + *n = size; + p = line + len; + copy = size - len; + } + + lose: + if (p == *lineptr) + return -1; + /* Return a partial line since we got an error in the middle. */ + win: + *p = '\0'; + return p - *lineptr; +} + diff --git a/xbmc/linux/getdelim.h b/xbmc/linux/getdelim.h new file mode 100644 index 0000000000..8440fe3a4a --- /dev/null +++ b/xbmc/linux/getdelim.h @@ -0,0 +1,32 @@ +/* getdelim.h --- Prototype for replacement getdelim function. + Copyright (C) 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* Written by Simon Josefsson. */ +# include <stddef.h> +# include <stdio.h> +# include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +ssize_t getdelim(char **lineptr, size_t *n, int delimiter, FILE *stream); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ diff --git a/xbmc/music/GUIViewStateMusic.cpp b/xbmc/music/GUIViewStateMusic.cpp index 55bbc3ca43..46a203b7a9 100644 --- a/xbmc/music/GUIViewStateMusic.cpp +++ b/xbmc/music/GUIViewStateMusic.cpp @@ -21,7 +21,6 @@ #include "GUIViewStateMusic.h" #include "PlayListPlayer.h" -#include "guilib/GUIBaseContainer.h" // for VIEW_TYPE_* #include "video/VideoDatabase.h" #include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" diff --git a/xbmc/music/LastFmManager.cpp b/xbmc/music/LastFmManager.cpp index 94fb12ae6d..14c1e0a53f 100644 --- a/xbmc/music/LastFmManager.cpp +++ b/xbmc/music/LastFmManager.cpp @@ -24,6 +24,7 @@ #include "Album.h" #include "Artist.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "PlayListPlayer.h" #include "playlists/PlayListFactory.h" #include "utils/md5.h" @@ -852,7 +853,7 @@ bool CLastFmManager::Love(const CMusicInfoTag& musicinfotag) //update the rating to 5, we loved it. CMusicInfoTag newTag(musicinfotag); newTag.SetRating('5'); - g_infoManager.SetCurrentSongTag(newTag); + CApplicationMessenger::Get().SetCurrentSongTag(newTag); //try updating the rating in the database if it's a local file. CMusicDatabase musicdatabase; if (musicdatabase.Open()) @@ -881,7 +882,7 @@ bool CLastFmManager::Ban(const CMusicInfoTag& musicinfotag) if (CallXmlRpc("banTrack", StringUtils::Join(musicinfotag.GetArtist(), g_advancedSettings.m_musicItemSeparator), musicinfotag.GetTitle())) { //we banned this track so skip to the next track - g_application.getApplicationMessenger().ExecBuiltIn("playercontrol(next)"); + CApplicationMessenger::Get().ExecBuiltIn("playercontrol(next)"); m_CurrentSong.IsBanned = true; return true; } diff --git a/xbmc/music/Makefile b/xbmc/music/Makefile index 32b722a37a..66e4a7d5a6 100644 --- a/xbmc/music/Makefile +++ b/xbmc/music/Makefile @@ -3,6 +3,7 @@ SRCS=Album.cpp \ GUIViewStateMusic.cpp \ LastFmManager.cpp \ MusicDatabase.cpp \ + MusicDbUrl.cpp \ MusicInfoLoader.cpp \ Song.cpp \ diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp index c646aa9aa3..a8d4e3b12b 100644 --- a/xbmc/music/MusicDatabase.cpp +++ b/xbmc/music/MusicDatabase.cpp @@ -62,6 +62,8 @@ #include "interfaces/AnnouncementManager.h" #include "dbwrappers/dataset.h" #include "utils/XMLUtils.h" +#include "URL.h" +#include "playlists/SmartPlayList.h" using namespace std; using namespace AUTOPTR; @@ -451,7 +453,7 @@ int CMusicDatabase::AddAlbum(const CStdString& strAlbum1, const CStdString &strA if (NULL == m_pDB.get()) return -1; if (NULL == m_pDS.get()) return -1; - map <CStdString, CAlbumCache>::const_iterator it; + map <CStdString, CAlbum>::const_iterator it; it = m_albumCache.find(strAlbum + strArtist); if (it != m_albumCache.end()) @@ -467,22 +469,22 @@ int CMusicDatabase::AddAlbum(const CStdString& strAlbum1, const CStdString &strA strSQL=PrepareSQL("insert into album (idAlbum, strAlbum, strArtists, strGenres, iYear, bCompilation) values( NULL, '%s', '%s', '%s', %i, %i)", strAlbum.c_str(), strArtist.c_str(), strGenre.c_str(), year, bCompilation); m_pDS->exec(strSQL.c_str()); - CAlbumCache album; + CAlbum album; album.idAlbum = (int)m_pDS->lastinsertid(); album.strAlbum = strAlbum; album.artist = StringUtils::Split(strArtist, g_advancedSettings.m_musicItemSeparator); - m_albumCache.insert(pair<CStdString, CAlbumCache>(album.strAlbum + strArtist, album)); + m_albumCache.insert(pair<CStdString, CAlbum>(album.strAlbum + strArtist, album)); return album.idAlbum; } else { // exists in our database and not scanned during this scan, so we should update it as the details // may have changed (there's a reason we're rescanning, afterall!) - CAlbumCache album; + CAlbum album; album.idAlbum = m_pDS->fv("idAlbum").get_asInt(); album.strAlbum = strAlbum; album.artist = StringUtils::Split(strArtist, g_advancedSettings.m_musicItemSeparator); - m_albumCache.insert(pair<CStdString, CAlbumCache>(album.strAlbum + strArtist, album)); + m_albumCache.insert(pair<CStdString, CAlbum>(album.strAlbum + strArtist, album)); m_pDS->close(); strSQL=PrepareSQL("update album set strGenres='%s', iYear=%i where idAlbum=%i", strGenre.c_str(), year, album.idAlbum); m_pDS->exec(strSQL.c_str()); @@ -858,8 +860,8 @@ CSong CMusicDatabase::GetSongFromDataset(bool bWithMusicDbPath/*=false*/) URIUtils::AddFileToFolder(m_pDS->fv(song_strPath).get_asString(), m_pDS->fv(song_strFileName).get_asString(), song.strFileName); else { - CStdString strFileName=m_pDS->fv(song_strFileName).get_asString(); - CStdString strExt=URIUtils::GetExtension(strFileName); + CStdString strFileName = m_pDS->fv(song_strFileName).get_asString(); + CStdString strExt = URIUtils::GetExtension(strFileName); song.strFileName.Format("musicdb://3/%ld/%ld%s", m_pDS->fv(song_idAlbum).get_asInt(), m_pDS->fv(song_idSong).get_asInt(), strExt.c_str()); } @@ -910,10 +912,15 @@ void CMusicDatabase::GetFileItemFromDataset(const dbiplus::sql_record* const rec item->SetPath(strRealPath); else { + CMusicDbUrl itemUrl; + if (!itemUrl.FromString(strMusicDBbasePath)) + return; + CStdString strFileName = record->at(song_strFileName).get_asString(); CStdString strExt = URIUtils::GetExtension(strFileName); - CStdString path; path.Format("%s%ld%s", strMusicDBbasePath.c_str(), record->at(song_idSong).get_asInt(), strExt.c_str()); - item->SetPath(path); + CStdString path; path.Format("%ld%s", record->at(song_idSong).get_asInt(), strExt.c_str()); + itemUrl.AppendPath(path); + item->SetPath(itemUrl.ToString()); } } @@ -948,25 +955,30 @@ CAlbum CMusicDatabase::GetAlbumFromDataset(const dbiplus::sql_record* const reco CArtist CMusicDatabase::GetArtistFromDataset(dbiplus::Dataset* pDS, bool needThumb) { + return GetArtistFromDataset(pDS->get_sql_record(), needThumb); +} + +CArtist CMusicDatabase::GetArtistFromDataset(const dbiplus::sql_record* const record, bool needThumb /* = true */) +{ CArtist artist; - artist.idArtist = pDS->fv(artist_idArtist).get_asInt(); - artist.strArtist = pDS->fv(artist_strArtist).get_asString(); - artist.genre = StringUtils::Split(pDS->fv(artist_strGenres).get_asString(), g_advancedSettings.m_musicItemSeparator); - artist.strBiography = pDS->fv(artist_strBiography).get_asString(); - artist.styles = StringUtils::Split(pDS->fv(artist_strStyles).get_asString(), g_advancedSettings.m_musicItemSeparator); - artist.moods = StringUtils::Split(pDS->fv(artist_strMoods).get_asString(), g_advancedSettings.m_musicItemSeparator); - artist.strBorn = pDS->fv(artist_strBorn).get_asString(); - artist.strFormed = pDS->fv(artist_strFormed).get_asString(); - artist.strDied = pDS->fv(artist_strDied).get_asString(); - artist.strDisbanded = pDS->fv(artist_strDisbanded).get_asString(); - artist.yearsActive = StringUtils::Split(pDS->fv(artist_strYearsActive).get_asString(), g_advancedSettings.m_musicItemSeparator); - artist.instruments = StringUtils::Split(pDS->fv(artist_strInstruments).get_asString(), g_advancedSettings.m_musicItemSeparator); + artist.idArtist = record->at(artist_idArtist).get_asInt(); + artist.strArtist = record->at(artist_strArtist).get_asString(); + artist.genre = StringUtils::Split(record->at(artist_strGenres).get_asString(), g_advancedSettings.m_musicItemSeparator); + artist.strBiography = record->at(artist_strBiography).get_asString(); + artist.styles = StringUtils::Split(record->at(artist_strStyles).get_asString(), g_advancedSettings.m_musicItemSeparator); + artist.moods = StringUtils::Split(record->at(artist_strMoods).get_asString(), g_advancedSettings.m_musicItemSeparator); + artist.strBorn = record->at(artist_strBorn).get_asString(); + artist.strFormed = record->at(artist_strFormed).get_asString(); + artist.strDied = record->at(artist_strDied).get_asString(); + artist.strDisbanded = record->at(artist_strDisbanded).get_asString(); + artist.yearsActive = StringUtils::Split(record->at(artist_strYearsActive).get_asString(), g_advancedSettings.m_musicItemSeparator); + artist.instruments = StringUtils::Split(record->at(artist_strInstruments).get_asString(), g_advancedSettings.m_musicItemSeparator); if (needThumb) { - artist.fanart.m_xml = pDS->fv(artist_strFanart).get_asString(); + artist.fanart.m_xml = record->at(artist_strFanart).get_asString(); artist.fanart.Unpack(); - artist.thumbURL.ParseString(pDS->fv(artist_strImage).get_asString()); + artist.thumbURL.ParseString(record->at(artist_strImage).get_asString()); } return artist; @@ -2040,7 +2052,6 @@ bool CMusicDatabase::CleanupSongsByIds(const CStdString &strSongIds) return false; } - bool CMusicDatabase::CleanupSongs() { try @@ -2353,10 +2364,10 @@ void CMusicDatabase::DeleteAlbumInfo() m_pDS->close(); CGUIDialogOK::ShowAndGetInput(313, 425, 0, 0); } - vector<CAlbumCache> vecAlbums; + vector<CAlbum> vecAlbums; while (!m_pDS->eof()) { - CAlbumCache album; + CAlbum album; album.idAlbum = m_pDS->fv("album.idAlbum").get_asInt() ; album.strAlbum = m_pDS->fv("album.strAlbum").get_asString(); album.artist = StringUtils::Split(m_pDS->fv("album.strArtists").get_asString(), g_advancedSettings.m_musicItemSeparator); @@ -2373,7 +2384,7 @@ void CMusicDatabase::DeleteAlbumInfo() pDlg->Reset(); for (int i = 0; i < (int)vecAlbums.size(); ++i) { - CMusicDatabase::CAlbumCache& album = vecAlbums[i]; + CAlbum& album = vecAlbums[i]; pDlg->Add(album.strAlbum + " - " + StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator)); } pDlg->DoModal(); @@ -2386,7 +2397,7 @@ void CMusicDatabase::DeleteAlbumInfo() return ; } - CAlbumCache& album = vecAlbums[iSelectedAlbum]; + CAlbum& album = vecAlbums[iSelectedAlbum]; strSQL=PrepareSQL("delete from albuminfo where albuminfo.idAlbum=%i", album.idAlbum); if (!m_pDS->exec(strSQL.c_str())) return ; @@ -2618,6 +2629,10 @@ bool CMusicDatabase::GetGenresNav(const CStdString& strBaseDir, CFileItemList& i if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(strBaseDir)) + return false; + // get primary genres for songs - could be simplified to just SELECT * FROM genre? CStdString strSQL="SELECT * " " FROM genre " @@ -2630,7 +2645,8 @@ bool CMusicDatabase::GetGenresNav(const CStdString& strBaseDir, CFileItemList& i // run query CLog::Log(LOGDEBUG, "%s query: %s", __FUNCTION__, strSQL.c_str()); - if (!m_pDS->query(strSQL.c_str())) return false; + if (!m_pDS->query(strSQL.c_str())) + return false; int iRowsFound = m_pDS->num_rows(); if (iRowsFound == 0) { @@ -2644,10 +2660,13 @@ bool CMusicDatabase::GetGenresNav(const CStdString& strBaseDir, CFileItemList& i CFileItemPtr pItem(new CFileItem(m_pDS->fv("strGenre").get_asString())); pItem->GetMusicInfoTag()->SetGenre(m_pDS->fv("strGenre").get_asString()); pItem->GetMusicInfoTag()->SetDatabaseId(m_pDS->fv("idGenre").get_asInt(), "genre"); - CStdString strDir; - strDir.Format("%ld/", m_pDS->fv("idGenre").get_asInt()); - pItem->SetPath(strBaseDir + strDir); - pItem->m_bIsFolder=true; + + CMusicDbUrl itemUrl = musicUrl; + CStdString strDir; strDir.Format("%ld/", m_pDS->fv("idGenre").get_asInt()); + itemUrl.AppendPath(strDir); + pItem->SetPath(itemUrl.ToString()); + + pItem->m_bIsFolder = true; items.Add(pItem); m_pDS->next(); @@ -2672,12 +2691,17 @@ bool CMusicDatabase::GetYearsNav(const CStdString& strBaseDir, CFileItemList& it if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(strBaseDir)) + return false; + // get years from album list CStdString strSQL="select distinct iYear from album where iYear <> 0"; // run query CLog::Log(LOGDEBUG, "%s query: %s", __FUNCTION__, strSQL.c_str()); - if (!m_pDS->query(strSQL.c_str())) return false; + if (!m_pDS->query(strSQL.c_str())) + return false; int iRowsFound = m_pDS->num_rows(); if (iRowsFound == 0) { @@ -2692,10 +2716,13 @@ bool CMusicDatabase::GetYearsNav(const CStdString& strBaseDir, CFileItemList& it SYSTEMTIME stTime; stTime.wYear = (WORD)m_pDS->fv("iYear").get_asInt(); pItem->GetMusicInfoTag()->SetReleaseDate(stTime); - CStdString strDir; - strDir.Format("%ld/", m_pDS->fv("iYear").get_asInt()); - pItem->SetPath(strBaseDir + strDir); - pItem->m_bIsFolder=true; + + CMusicDbUrl itemUrl = musicUrl; + CStdString strDir; strDir.Format("%ld/", m_pDS->fv("iYear").get_asInt()); + itemUrl.AppendPath(strDir); + pItem->SetPath(itemUrl.ToString()); + + pItem->m_bIsFolder = true; items.Add(pItem); m_pDS->next(); @@ -2715,12 +2742,17 @@ bool CMusicDatabase::GetYearsNav(const CStdString& strBaseDir, CFileItemList& it bool CMusicDatabase::GetAlbumsByYear(const CStdString& strBaseDir, CFileItemList& items, int year) { - CStdString where = PrepareSQL("where iYear=%ld", year); + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(strBaseDir)) + return false; - return GetAlbumsByWhere(strBaseDir, where, "", items); + musicUrl.AddOption("year", year); + + Filter filter; + return GetAlbumsByWhere(musicUrl.ToString(), filter, items); } -bool CMusicDatabase::GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, bool albumArtistsOnly) +bool CMusicDatabase::GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, bool albumArtistsOnly /* = false */, int idGenre /* = -1 */, int idAlbum /* = -1 */, int idSong /* = -1 */, const SortDescription &sortDescription /* = SortDescription() */) { if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; @@ -2728,55 +2760,21 @@ bool CMusicDatabase::GetArtistsNav(const CStdString& strBaseDir, CFileItemList& { unsigned int time = XbmcThreads::SystemClockMillis(); - CStdString strSQL = "(idArtist IN "; - - if (idGenre==-1) - { - if (!albumArtistsOnly) // show all artists in this case (ie those linked to a song) - strSQL += "(" - "SELECT song_artist.idArtist FROM song_artist" // All artists linked to a song - ") " - "or idArtist IN "; + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(strBaseDir)) + return false; - // and always show any artists linked to an album (may be different from above due to album artist tag) - strSQL += "(" - "SELECT album_artist.idArtist from album_artist "; // All artists linked to an album - if (albumArtistsOnly) - strSQL += "WHERE album_artist.boolFeatured = 0"; // then exclude those that have no extra artists - strSQL += ")" - ") "; - } - else - { // same statements as above, but limit to the specified genre - // in this case we show the whole lot always - there is no limitation to just album artists - if (!albumArtistsOnly) // show all artists in this case (ie those linked to a song) - strSQL+=PrepareSQL("(" - "SELECT song_artist.idArtist FROM song_artist " // All artists linked to extra genres - "JOIN song_genre ON song_artist.idSong = song_genre.idSong " - "WHERE song_genre.idGenre=%i" - ") " - "or idArtist IN " - , idGenre); - // and add any artists linked to an album (may be different from above due to album artist tag) - strSQL += PrepareSQL("(" - "SELECT album_artist.idArtist FROM album_artist " // All album artists linked to extra genres - "JOIN album_genre ON album_artist.idAlbum = album_genre.idAlbum " - "WHERE album_genre.idGenre=%i" - ") " - ")", idGenre); - } + if (idGenre > 0) + musicUrl.AddOption("genreid", idGenre); + else if (idAlbum > 0) + musicUrl.AddOption("albumid", idAlbum); + else if (idSong > 0) + musicUrl.AddOption("songid", idSong); - // remove the null string - strSQL += " and strArtist != \"\""; - // and the various artist entry if applicable - if (!albumArtistsOnly) - { - CStdString strVariousArtists = g_localizeStrings.Get(340); - int idVariousArtists = AddArtist(strVariousArtists); - strSQL+=PrepareSQL(" and artistview.idArtist<>%i", idVariousArtists); - } + musicUrl.AddOption("albumartistsonly", albumArtistsOnly); - bool result = GetArtistsByWhere(strBaseDir, strSQL, items); + Filter filter; + bool result = GetArtistsByWhere(musicUrl.ToString(), filter, items, sortDescription); CLog::Log(LOGDEBUG,"Time to retrieve artists from dataset = %i", XbmcThreads::SystemClockMillis() - time); return result; @@ -2789,16 +2787,56 @@ bool CMusicDatabase::GetArtistsNav(const CStdString& strBaseDir, CFileItemList& return false; } -bool CMusicDatabase::GetArtistsByWhere(const CStdString& strBaseDir, const CStdString &where, CFileItemList& items) +bool CMusicDatabase::GetArtistsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription /* = SortDescription() */) { if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; try { - CStdString strSQL = "select * from artistview"; - if (!where.empty()) - strSQL += " WHERE " + where; + int total = -1; + + CStdString strSQL = "SELECT %s FROM artistview "; + + Filter extFilter = filter; + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(strBaseDir) || !GetFilter(musicUrl, extFilter)) + return false; + + // if there are extra WHERE conditions we might need access + // to songview or albumview for these conditions + if (extFilter.where.size() > 0) + { + bool extended = false; + if (extFilter.where.find("songview") != string::npos) + { + extended = true; + extFilter.AppendJoin("JOIN song_artist ON song_artist.idArtist = artistview.idArtist JOIN songview ON songview.idSong = song_artist.idSong"); + } + else if (extFilter.where.find("albumview") != string::npos) + { + extended = true; + extFilter.AppendJoin("JOIN album_artist ON album_artist.idArtist = artistview.idArtist JOIN albumview ON albumview.idAlbum = album_artist.idAlbum"); + } + + if (extended) + extFilter.AppendGroup("artistview.idArtist"); + } + + CStdString strSQLExtra; + if (!BuildSQL(strSQLExtra, extFilter, strSQLExtra)) + return false; + + // Apply the limiting directly here if there's no special sorting but limiting + if (extFilter.limit.empty() && + sortDescription.sortBy == SortByNone && + (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) + { + total = (int)strtol(GetSingleValue(PrepareSQL(strSQL, "COUNT(1)") + strSQLExtra, m_pDS).c_str(), NULL, 10); + strSQLExtra += DatabaseUtils::BuildLimitClause(sortDescription.limitEnd, sortDescription.limitStart); + } + + strSQL = PrepareSQL(strSQL.c_str(), !extFilter.fields.empty() && extFilter.fields.compare("*") != 0 ? extFilter.fields.c_str() : "artistview.*") + strSQLExtra; // run query CLog::Log(LOGDEBUG, "%s query: %s", __FUNCTION__, strSQL.c_str()); @@ -2810,23 +2848,45 @@ bool CMusicDatabase::GetArtistsByWhere(const CStdString& strBaseDir, const CStdS return false; } - items.Reserve(iRowsFound); + // store the total value of items as a property + if (total < iRowsFound) + total = iRowsFound; + items.SetProperty("total", total); + + DatabaseResults results; + results.reserve(iRowsFound); + if (!SortUtils::SortFromDataset(sortDescription, MediaTypeArtist, m_pDS, results)) + return false; // get data from returned rows - while (!m_pDS->eof()) + items.Reserve(results.size()); + const dbiplus::query_data &data = m_pDS->get_result_set().records; + for (DatabaseResults::const_iterator it = results.begin(); it != results.end(); it++) { - CArtist artist = GetArtistFromDataset(m_pDS.get(), false); - CFileItemPtr pItem(new CFileItem(artist)); - CStdString strDir; - strDir.Format("%ld/", artist.idArtist); - pItem->SetPath(strBaseDir + strDir); - pItem->GetMusicInfoTag()->SetDatabaseId(artist.idArtist, "artist"); - pItem->SetIconImage("DefaultArtist.png"); + unsigned int targetRow = (unsigned int)it->at(FieldRow).asInteger(); + const dbiplus::sql_record* const record = data.at(targetRow); + + try + { + CArtist artist = GetArtistFromDataset(record, false); + CFileItemPtr pItem(new CFileItem(artist)); - SetPropertiesFromArtist(*pItem,artist); - items.Add(pItem); + CMusicDbUrl itemUrl = musicUrl; + CStdString path; path.Format("%ld/", artist.idArtist); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); - m_pDS->next(); + pItem->GetMusicInfoTag()->SetDatabaseId(artist.idArtist, "artist"); + pItem->SetIconImage("DefaultArtist.png"); + + SetPropertiesFromArtist(*pItem, artist); + items.Add(pItem); + } + catch (...) + { + m_pDS->close(); + CLog::Log(LOGERROR, "%s - out of memory getting listing (got %i)", __FUNCTION__, items.Size()); + } } // cleanup @@ -2905,62 +2965,24 @@ bool CMusicDatabase::GetAlbumFromSong(const CSong &song, CAlbum &album) return false; } -bool CMusicDatabase::GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idArtist, int start, int end, const SortDescription &sortDescription /* = SortDescription() */) +bool CMusicDatabase::GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre /* = -1 */, int idArtist /* = -1 */, const SortDescription &sortDescription /* = SortDescription() */) { - //Create limit - CStdString limit; - if (start >= 0 && end >= 0) - { - limit.Format(" limit %i,%i", start, end); - } + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(strBaseDir)) + return false; // where clause - CStdString strWhere; - if (idGenre!=-1) - { - strWhere+=PrepareSQL("where (idAlbum IN " - "(" - "select song.idAlbum from song " // All song genres - "JOIN song_genre ON song.idSong=song_genre.idSong " - "where song_genre.idGenre=%i" - ")" - ") " + limit - , idGenre); - } + if (idGenre > 0) + musicUrl.AddOption("genreid", idGenre); - if (idArtist!=-1) - { - if (strWhere.IsEmpty()) - strWhere += "where "; - else - strWhere += "and "; - - strWhere +=PrepareSQL("(idAlbum IN " - "(" - "select song.idAlbum from song " // All albums linked to this artist via songs - "JOIN song_artist ON song.idSong=song_artist.idSong " - "WHERE song_artist.idArtist=%i" - ")" - " or idAlbum IN " - "(" - "select album_artist.idAlbum from album_artist " // All albums where album artists fit - "where album_artist.idArtist=%i" - ")" - ") " + limit - , idArtist, idArtist); - } - else - { // no artist given, so exclude any single albums (aka empty tagged albums) - if (strWhere.IsEmpty()) - strWhere += "where albumview.strAlbum <> ''" + limit; - else - strWhere += "and albumview.strAlbum <> ''" + limit; - } + if (idArtist > 0) + musicUrl.AddOption("artistid", idArtist); - return GetAlbumsByWhere(strBaseDir, strWhere, "", items, sortDescription); + Filter filter; + return GetAlbumsByWhere(musicUrl.ToString(), filter, items, sortDescription); } -bool CMusicDatabase::GetAlbumsByWhere(const CStdString &baseDir, const CStdString &where, const CStdString &order, CFileItemList &items, const SortDescription &sortDescription /* = SortDescription() */) +bool CMusicDatabase::GetAlbumsByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList &items, const SortDescription &sortDescription /* = SortDescription() */) { if (m_pDB.get() == NULL || m_pDS.get() == NULL) return false; @@ -2969,22 +2991,40 @@ bool CMusicDatabase::GetAlbumsByWhere(const CStdString &baseDir, const CStdStrin { int total = -1; - CStdString sql = "select * from albumview " + where; + CStdString strSQL = "SELECT %s FROM albumview "; + + Filter extFilter = filter; + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(baseDir) || !GetFilter(musicUrl, extFilter)) + return false; + + // if there are extra WHERE conditions we might need access + // to songview for these conditions + if (extFilter.where.find("songview") != string::npos) + { + extFilter.AppendJoin("JOIN songview ON songview.idAlbum = albumview.idAlbum"); + extFilter.AppendGroup("albumview.idAlbum"); + } + + CStdString strSQLExtra; + if (!BuildSQL(strSQLExtra, extFilter, strSQLExtra)) + return false; + // Apply the limiting directly here if there's no special sorting but limiting - CStdString whereLower = where; - whereLower.ToLower(); - if (whereLower.find(" limit ") == string::npos && + if (extFilter.limit.empty() && sortDescription.sortBy == SortByNone && (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) { - total = (int)strtol(GetSingleValue("SELECT COUNT(1) FROM albumview " + where, m_pDS).c_str(), NULL, 10); - sql += DatabaseUtils::BuildLimitClause(sortDescription.limitEnd, sortDescription.limitStart); + total = (int)strtol(GetSingleValue(PrepareSQL(strSQL, "COUNT(1)") + strSQLExtra, m_pDS).c_str(), NULL, 10); + strSQLExtra += DatabaseUtils::BuildLimitClause(sortDescription.limitEnd, sortDescription.limitStart); } - CLog::Log(LOGDEBUG, "%s query: %s", __FUNCTION__, sql.c_str()); + strSQL = PrepareSQL(strSQL, !filter.fields.empty() && filter.fields.compare("*") != 0 ? filter.fields.c_str() : "albumview.*") + strSQLExtra; + + CLog::Log(LOGDEBUG, "%s query: %s", __FUNCTION__, strSQL.c_str()); // run query unsigned int time = XbmcThreads::SystemClockMillis(); - if (!m_pDS->query(sql.c_str())) + if (!m_pDS->query(strSQL.c_str())) return false; CLog::Log(LOGDEBUG, "%s - query took %i ms", __FUNCTION__, XbmcThreads::SystemClockMillis() - time); time = XbmcThreads::SystemClockMillis(); @@ -3016,10 +3056,11 @@ bool CMusicDatabase::GetAlbumsByWhere(const CStdString &baseDir, const CStdStrin try { - CStdString strDir; - int idAlbum = record->at(album_idAlbum).get_asInt(); - strDir.Format("%s%ld/", baseDir.c_str(), idAlbum); - CFileItemPtr pItem(new CFileItem(strDir, GetAlbumFromDataset(record))); + CMusicDbUrl itemUrl = musicUrl; + CStdString path; path.Format("%ld/", record->at(album_idAlbum).get_asInt()); + itemUrl.AppendPath(path); + + CFileItemPtr pItem(new CFileItem(itemUrl.ToString(), GetAlbumFromDataset(record))); pItem->SetIconImage("DefaultAlbumCover.png"); items.Add(pItem); } @@ -3037,12 +3078,12 @@ bool CMusicDatabase::GetAlbumsByWhere(const CStdString &baseDir, const CStdStrin catch (...) { m_pDS->close(); - CLog::Log(LOGERROR, "%s (%s) failed", __FUNCTION__, where.c_str()); + CLog::Log(LOGERROR, "%s (%s) failed", __FUNCTION__, filter.where.c_str()); } return false; } -bool CMusicDatabase::GetSongsByWhere(const CStdString &baseDir, const CStdString &whereClause, CFileItemList &items, const SortDescription &sortDescription /* = SortDescription() */) +bool CMusicDatabase::GetSongsByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList &items, const SortDescription &sortDescription /* = SortDescription() */) { if (m_pDB.get() == NULL || m_pDS.get() == NULL) return false; @@ -3052,19 +3093,36 @@ bool CMusicDatabase::GetSongsByWhere(const CStdString &baseDir, const CStdString unsigned int time = XbmcThreads::SystemClockMillis(); int total = -1; - // We don't use PrepareSQL here, as the WHERE clause is already formatted. - CStdString strSQL = "select * from songview " + whereClause; + CStdString strSQL = "SELECT %s FROM songview "; + + Filter extFilter = filter; + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(baseDir) || !GetFilter(musicUrl, extFilter)) + return false; + + // if there are extra WHERE conditions we might need access + // to songview for these conditions + if (extFilter.where.find("albumview") != string::npos) + { + extFilter.AppendJoin("JOIN albumview ON albumview.idAlbum = songview.idAlbum"); + extFilter.AppendGroup("songview.idSong"); + } + + CStdString strSQLExtra; + if (!BuildSQL(strSQLExtra, extFilter, strSQLExtra)) + return false; + // Apply the limiting directly here if there's no special sorting but limiting - CStdString whereLower = whereClause; - whereLower.ToLower(); - if (whereLower.find(" limit ") == string::npos && + if (extFilter.limit.empty() && sortDescription.sortBy == SortByNone && (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) { - total = (int)strtol(GetSingleValue("SELECT COUNT(1) FROM songview " + whereClause, m_pDS).c_str(), NULL, 10); - strSQL += DatabaseUtils::BuildLimitClause(sortDescription.limitEnd, sortDescription.limitStart); + total = (int)strtol(GetSingleValue(PrepareSQL(strSQL, "COUNT(1)") + strSQLExtra, m_pDS).c_str(), NULL, 10); + strSQLExtra += DatabaseUtils::BuildLimitClause(sortDescription.limitEnd, sortDescription.limitStart); } + strSQL = PrepareSQL(strSQL, !filter.fields.empty() && filter.fields.compare("*") != 0 ? filter.fields.c_str() : "songview.*") + strSQLExtra; + CLog::Log(LOGDEBUG, "%s query = %s", __FUNCTION__, strSQL.c_str()); // run query if (!m_pDS->query(strSQL.c_str())) @@ -3099,7 +3157,7 @@ bool CMusicDatabase::GetSongsByWhere(const CStdString &baseDir, const CStdString try { CFileItemPtr item(new CFileItem); - GetFileItemFromDataset(record, item.get(), baseDir); + GetFileItemFromDataset(record, item.get(), musicUrl.ToString()); // HACK for sorting by database returned order item->m_iprogramCount = ++count; items.Add(item); @@ -3107,77 +3165,53 @@ bool CMusicDatabase::GetSongsByWhere(const CStdString &baseDir, const CStdString catch (...) { m_pDS->close(); - CLog::Log(LOGERROR, "%s: out of memory loading query: %s", __FUNCTION__, whereClause.c_str()); + CLog::Log(LOGERROR, "%s: out of memory loading query: %s", __FUNCTION__, filter.where.c_str()); return (items.Size() > 0); } } // cleanup m_pDS->close(); - CLog::Log(LOGDEBUG, "%s(%s) - took %d ms", __FUNCTION__, whereClause.c_str(), XbmcThreads::SystemClockMillis() - time); + CLog::Log(LOGDEBUG, "%s(%s) - took %d ms", __FUNCTION__, filter.where.c_str(), XbmcThreads::SystemClockMillis() - time); return true; } catch (...) { // cleanup m_pDS->close(); - CLog::Log(LOGERROR, "%s(%s) failed", __FUNCTION__, whereClause.c_str()); + CLog::Log(LOGERROR, "%s(%s) failed", __FUNCTION__, filter.where.c_str()); } return false; } bool CMusicDatabase::GetSongsByYear(const CStdString& baseDir, CFileItemList& items, int year) { - CStdString where=PrepareSQL("where (iYear=%ld)", year); - return GetSongsByWhere(baseDir, where, items); + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(baseDir)) + return false; + + musicUrl.AddOption("year", year); + + Filter filter; + return GetSongsByWhere(baseDir, filter, items); } -bool CMusicDatabase::GetSongsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idArtist,int idAlbum, const SortDescription &sortDescription /* = SortDescription() */) +bool CMusicDatabase::GetSongsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idArtist, int idAlbum, const SortDescription &sortDescription /* = SortDescription() */) { - CStdString strWhere; + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(strBaseDir)) + return false; - if (idAlbum!=-1) - strWhere=PrepareSQL("where (idAlbum=%ld) ", idAlbum); + if (idAlbum > 0) + musicUrl.AddOption("albumid", idAlbum); - if (idGenre!=-1) - { - if (strWhere.IsEmpty()) - strWhere += "where "; - else - strWhere += "and "; + if (idGenre > 0) + musicUrl.AddOption("genreid", idGenre); - strWhere += PrepareSQL("(idSong IN " - "(" - "SELECT song_genre.idSong FROM song_genre " - "WHERE song_genre.idGenre = %i" - ")" - ") " - , idGenre); - } + if (idArtist > 0) + musicUrl.AddOption("artistid", idArtist); - if (idArtist!=-1) - { - if (strWhere.IsEmpty()) - strWhere += "where "; - else - strWhere += "and "; - - strWhere += PrepareSQL("(idSong IN " // song artists - "(" - "SELECT song_artist.idSong FROM song_artist " - "WHERE song_artist.idArtist=%i" - ") " - "or idSong IN " // album artists - "(" - "SELECT song.idSong FROM song " - "JOIN album_artist ON song.idAlbum=album_artist.idAlbum " - "WHERE album_artist.idArtist=%i" - ")" - ") " - , idArtist, idArtist); - } - - // run query - return GetSongsByWhere(strBaseDir, strWhere, items, sortDescription); + Filter filter; + return GetSongsByWhere(musicUrl.ToString(), filter, items, sortDescription); } bool CMusicDatabase::UpdateOldVersion(int version) @@ -3521,14 +3555,17 @@ bool CMusicDatabase::UpdateOldVersion(int version) return true; } -unsigned int CMusicDatabase::GetSongIDs(const CStdString& strWhere, vector<pair<int,int> > &songIDs) +unsigned int CMusicDatabase::GetSongIDs(const Filter &filter, vector<pair<int,int> > &songIDs) { try { if (NULL == m_pDB.get()) return 0; if (NULL == m_pDS.get()) return 0; - CStdString strSQL = "select idSong from songview " + strWhere; + CStdString strSQL = "select idSong from songview "; + if (!CDatabase::BuildSQL(strSQL, filter, strSQL)) + return false; + if (!m_pDS->query(strSQL.c_str())) return 0; songIDs.clear(); if (m_pDS->num_rows() == 0) @@ -3547,19 +3584,22 @@ unsigned int CMusicDatabase::GetSongIDs(const CStdString& strWhere, vector<pair< } catch (...) { - CLog::Log(LOGERROR, "%s(%s) failed", __FUNCTION__, strWhere.c_str()); + CLog::Log(LOGERROR, "%s(%s) failed", __FUNCTION__, filter.where.c_str()); } return 0; } -int CMusicDatabase::GetSongsCount(const CStdString& strWhere) +int CMusicDatabase::GetSongsCount(const Filter &filter) { try { if (NULL == m_pDB.get()) return 0; if (NULL == m_pDS.get()) return 0; - CStdString strSQL = "select count(idSong) as NumSongs from songview " + strWhere; + CStdString strSQL = "select count(idSong) as NumSongs from songview "; + if (!CDatabase::BuildSQL(strSQL, filter, strSQL)) + return false; + if (!m_pDS->query(strSQL.c_str())) return false; if (m_pDS->num_rows() == 0) { @@ -3574,7 +3614,7 @@ int CMusicDatabase::GetSongsCount(const CStdString& strWhere) } catch (...) { - CLog::Log(LOGERROR, "%s(%s) failed", __FUNCTION__, strWhere.c_str()); + CLog::Log(LOGERROR, "%s(%s) failed", __FUNCTION__, filter.where.c_str()); } return 0; } @@ -3612,7 +3652,6 @@ bool CMusicDatabase::GetAlbumPath(int idAlbum, CStdString& path) return false; } - bool CMusicDatabase::SaveAlbumThumb(int idAlbum, const CStdString& strThumb) { SetArtForItem(idAlbum, "album", "thumb", strThumb); @@ -3789,13 +3828,13 @@ int CMusicDatabase::GetGenreByName(const CStdString& strGenre) return -1; } -bool CMusicDatabase::GetRandomSong(CFileItem* item, int& idSong, const CStdString& strWhere) +bool CMusicDatabase::GetRandomSong(CFileItem* item, int& idSong, const Filter &filter) { try { idSong = -1; - int iCount = GetSongsCount(strWhere); + int iCount = GetSongsCount(filter); if (iCount <= 0) return false; int iRandom = rand() % iCount; @@ -3804,8 +3843,15 @@ bool CMusicDatabase::GetRandomSong(CFileItem* item, int& idSong, const CStdStrin if (NULL == m_pDS.get()) return false; // We don't use PrepareSQL here, as the WHERE clause is already formatted - CStdString strSQL; - strSQL.Format("select * from songview %s order by idSong limit 1 offset %i", strWhere.c_str(), iRandom); + CStdString strSQL = PrepareSQL("select %s from songview ", !filter.fields.empty() ? filter.fields.c_str() : "*"); + Filter extFilter = filter; + extFilter.AppendOrder("idSong"); + extFilter.limit = "1"; + + if (!CDatabase::BuildSQL(strSQL, extFilter, strSQL)) + return false; + + strSQL += PrepareSQL(" OFFSET %i", iRandom); CLog::Log(LOGDEBUG, "%s query = %s", __FUNCTION__, strSQL.c_str()); // run query @@ -3824,19 +3870,33 @@ bool CMusicDatabase::GetRandomSong(CFileItem* item, int& idSong, const CStdStrin } catch(...) { - CLog::Log(LOGERROR, "%s(%s) failed", __FUNCTION__, strWhere.c_str()); + CLog::Log(LOGERROR, "%s(%s) failed", __FUNCTION__, filter.where.c_str()); } return false; } bool CMusicDatabase::GetCompilationAlbums(const CStdString& strBaseDir, CFileItemList& items) { - return GetAlbumsByWhere(strBaseDir, "WHERE bCompilation = 1", "", items); + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(strBaseDir)) + return false; + + musicUrl.AddOption("compilation", true); + + Filter filter; + return GetAlbumsByWhere(strBaseDir, filter, items); } bool CMusicDatabase::GetCompilationSongs(const CStdString& strBaseDir, CFileItemList& items) { - return GetSongsByWhere(strBaseDir, "WHERE bCompilation = 1", items); + CMusicDbUrl musicUrl; + if (!musicUrl.FromString(strBaseDir)) + return false; + + musicUrl.AddOption("compilation", true); + + Filter filter; + return GetSongsByWhere(musicUrl.ToString(), filter, items); } int CMusicDatabase::GetCompilationAlbumsCount() @@ -4089,7 +4149,7 @@ bool CMusicDatabase::CommitTransaction() { if (CDatabase::CommitTransaction()) { // number of items in the db has likely changed, so reset the infomanager cache - g_infoManager.SetLibraryBool(LIBRARY_HAS_MUSIC, GetSongsCount("") > 0); + g_infoManager.SetLibraryBool(LIBRARY_HAS_MUSIC, GetSongsCount() > 0); return true; } return false; @@ -4551,7 +4611,6 @@ void CMusicDatabase::AddKaraokeData(int idSong, const CSong& song) } } - bool CMusicDatabase::GetSongByKaraokeNumber(int number, CSong & song) { try @@ -4582,7 +4641,6 @@ bool CMusicDatabase::GetSongByKaraokeNumber(int number, CSong & song) return false; } - void CMusicDatabase::ExportKaraokeInfo(const CStdString & outFile, bool asHTML) { try @@ -4678,7 +4736,6 @@ void CMusicDatabase::ExportKaraokeInfo(const CStdString & outFile, bool asHTML) } } - void CMusicDatabase::ImportKaraokeInfo(const CStdString & inputFile) { CGUIDialogProgress *progress = (CGUIDialogProgress *)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS); @@ -4834,7 +4891,6 @@ void CMusicDatabase::ImportKaraokeInfo(const CStdString & inputFile) progress->Close(); } - bool CMusicDatabase::SetKaraokeSongDelay(int idSong, int delay) { try @@ -5051,3 +5107,189 @@ string CMusicDatabase::GetArtistArtForItem(int mediaId, const string &mediaType, std::string query = PrepareSQL("SELECT url FROM art WHERE media_id=(SELECT idArtist from %s_artist WHERE id%s=%i) AND media_type='artist' AND type='%s'", mediaType.c_str(), mediaType.c_str(), mediaId, artType.c_str()); return GetSingleValue(query, m_pDS2); } + +bool CMusicDatabase::GetFilter(const CDbUrl &musicUrl, Filter &filter) +{ + if (!musicUrl.IsValid()) + return false; + + std::string type = musicUrl.GetType(); + const CUrlOptions::UrlOptions& options = musicUrl.GetOptions(); + CUrlOptions::UrlOptions::const_iterator option; + + if (type == "artists") + { + int idArtist = -1, idGenre = -1, idAlbum = -1, idSong = -1; + bool albumArtistsOnly = false; + + option = options.find("artistid"); + if (option != options.end()) + idArtist = (int)option->second.asInteger(); + + option = options.find("genreid"); + if (option != options.end()) + idGenre = (int)option->second.asInteger(); + else + { + option = options.find("genre"); + if (option != options.end()) + idGenre = GetGenreByName(option->second.asString()); + } + + option = options.find("albumid"); + if (option != options.end()) + idAlbum = (int)option->second.asInteger(); + else + { + option = options.find("album"); + if (option != options.end()) + idAlbum = GetAlbumByName(option->second.asString()); + } + + option = options.find("songid"); + if (option != options.end()) + idSong = (int)option->second.asInteger(); + + option = options.find("albumartistsonly"); + if (option != options.end()) + albumArtistsOnly = option->second.asBoolean(); + + CStdString strSQL = "(artistview.idArtist IN "; + if (idArtist > 0) + strSQL += PrepareSQL("(%d)", idArtist); + else if (idAlbum > 0) + strSQL += PrepareSQL("(SELECT album_artist.idArtist FROM album_artist WHERE album_artist.idAlbum = %i)", idAlbum); + else if (idSong > 0) + strSQL += PrepareSQL("(SELECT song_artist.idArtist FROM song_artist WHERE song_artist.idSong = %i)", idSong); + else if (idGenre > 0) + { // same statements as below, but limit to the specified genre + // in this case we show the whole lot always - there is no limitation to just album artists + if (!albumArtistsOnly) // show all artists in this case (ie those linked to a song) + strSQL+=PrepareSQL("(SELECT song_artist.idArtist FROM song_artist" // All artists linked to extra genres + " JOIN song_genre ON song_artist.idSong = song_genre.idSong" + " WHERE song_genre.idGenre = %i)" + " OR idArtist IN ", idGenre); + // and add any artists linked to an album (may be different from above due to album artist tag) + strSQL += PrepareSQL("(SELECT album_artist.idArtist FROM album_artist" // All album artists linked to extra genres + " JOIN album_genre ON album_artist.idAlbum = album_genre.idAlbum" + " WHERE album_genre.idGenre = %i)", idGenre); + } + else + { + if (!albumArtistsOnly) // show all artists in this case (ie those linked to a song) + strSQL += "(SELECT song_artist.idArtist FROM song_artist)" + " OR artistview.idArtist IN "; + + // and always show any artists linked to an album (may be different from above due to album artist tag) + strSQL += "(SELECT album_artist.idArtist FROM album_artist"; // All artists linked to an album + if (albumArtistsOnly) + strSQL += " WHERE album_artist.boolFeatured = 0"; // then exclude those that have no extra artists + strSQL += ")"; + } + + // remove the null string + strSQL += ") and artistview.strArtist != ''"; + + // and the various artist entry if applicable + if (!albumArtistsOnly) + { + CStdString strVariousArtists = g_localizeStrings.Get(340); + int idVariousArtists = AddArtist(strVariousArtists); + strSQL += PrepareSQL(" and artistview.idArtist <> %i", idVariousArtists); + } + + filter.AppendWhere(strSQL); + } + else if (type == "albums") + { + option = options.find("year"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("albumview.iYear = %i", (int)option->second.asInteger())); + + option = options.find("compilation"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("albumview.bCompilation = %i", option->second.asBoolean() ? 1 : 0)); + + option = options.find("genreid"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("albumview.idAlbum IN (SELECT song.idAlbum FROM song JOIN song_genre ON song.idSong = song_genre.idSong WHERE song_genre.idGenre = %i)", (int)option->second.asInteger())); + + option = options.find("genre"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("albumview.idAlbum IN (SELECT song.idAlbum FROM song JOIN song_genre ON song.idSong = song_genre.idSong JOIN genre ON genre.idGenre = song_genre.idGenre WHERE genre.strGenre like '%s')", option->second.asString().c_str())); + + option = options.find("artistid"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("albumview.idAlbum IN (SELECT song.idAlbum FROM song JOIN song_artist ON song.idSong = song_artist.idSong WHERE song_artist.idArtist = %i)" // All albums linked to this artist via songs + " OR albumview.idAlbum IN (SELECT album_artist.idAlbum FROM album_artist WHERE album_artist.idArtist = %i)", // All albums where album artists fit + (int)option->second.asInteger(), (int)option->second.asInteger())); + else + { + option = options.find("artist"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("albumview.idAlbum IN (SELECT song.idAlbum FROM song JOIN song_artist ON song.idSong = song_artist.idSong JOIN artist ON artist.idArtist = song_artist.idArtist WHERE artist.strArtist like '%s')" // All albums linked to this artist via songs + " OR albumview.idAlbum IN (SELECT album_artist.idAlbum FROM album_artist JOIN artist ON artist.idArtist = album_artist.idArtist WHERE artist.strArtist like '%s')", // All albums where album artists fit + option->second.asString().c_str(), option->second.asString().c_str())); + // no artist given, so exclude any single albums (aka empty tagged albums) + else + filter.AppendWhere("albumview.strAlbum <> ''"); + } + } + else if (type == "songs") + { + option = options.find("year"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("songview.iYear = %i", (int)option->second.asInteger())); + + option = options.find("compilation"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("songview.bCompilation = %i", option->second.asBoolean() ? 1 : 0)); + + option = options.find("albumid"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("songview.idAlbum = %i", (int)option->second.asInteger())); + + option = options.find("album"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("songview.strAlbum like '%s'", option->second.asString().c_str())); + + option = options.find("genreid"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("songview.idSong IN (SELECT song_genre.idSong FROM song_genre WHERE song_genre.idGenre = %i)", (int)option->second.asInteger())); + + option = options.find("genre"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("songview.idSong IN (SELECT song_genre.idSong FROM song_genre JOIN genre ON genre.idGenre = song_genre.idGenre WHERE genre.strGenre like '%s')", option->second.asString().c_str())); + + option = options.find("artistid"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("songview.idSong IN (SELECT song_artist.idSong FROM song_artist WHERE song_artist.idArtist = %i)" // song artists + " OR songview.idSong IN (SELECT song.idSong FROM song JOIN album_artist ON song.idAlbum=album_artist.idAlbum WHERE album_artist.idArtist = %i)", // album artists + (int)option->second.asInteger(), (int)option->second.asInteger())); + + option = options.find("artist"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("songview.idSong IN (SELECT song_artist.idSong FROM song_artist JOIN artist ON artist.idArtist = song_artist.idArtist WHERE artist.strArtist like '%s')" // song artists + " OR songview.idSong IN (SELECT song.idSong FROM song JOIN album_artist ON song.idAlbum=album_artist.idAlbum JOIN artist ON artist.idArtist = album_artist.idArtist WHERE artist.strArtist like '%s')", // album artists + option->second.asString().c_str(), option->second.asString().c_str())); + } + else + return false; + + option = options.find("xsp"); + if (option != options.end()) + { + CSmartPlaylist xsp; + if (!xsp.LoadFromJson(option->second.asString())) + return false; + + // check if the filter playlist matches the item type + if (xsp.GetType() != "artists"|| xsp.GetType() == type) + { + std::set<CStdString> playlists; + filter.AppendWhere(xsp.GetWhereClause(*this, playlists)); + } + } + + return true; +} diff --git a/xbmc/music/MusicDatabase.h b/xbmc/music/MusicDatabase.h index 4101eb6c47..b73234ba09 100644 --- a/xbmc/music/MusicDatabase.h +++ b/xbmc/music/MusicDatabase.h @@ -27,6 +27,7 @@ #include "Album.h" #include "addons/Scraper.h" #include "utils/SortUtils.h" +#include "MusicDbUrl.h" class CArtist; class CFileItem; @@ -88,33 +89,6 @@ class CMusicDatabase : public CDatabase { friend class DatabaseUtils; - class CArtistCache - { - public: - int idArtist; - CStdString strArtist; - }; - - class CPathCache - { - public: - int idPath; - CStdString strPath; - }; - - class CGenreCache - { - public: - int idGenre; - CStdString strGenre; - }; - - class CAlbumCache : public CAlbum - { - public: - int idAlbum; - }; - public: CMusicDatabase(void); virtual ~CMusicDatabase(void); @@ -178,18 +152,18 @@ public: bool GetPathHash(const CStdString &path, CStdString &hash); bool GetGenresNav(const CStdString& strBaseDir, CFileItemList& items); bool GetYearsNav(const CStdString& strBaseDir, CFileItemList& items); - bool GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, bool albumArtistsOnly); - bool GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idArtist, int start, int end, const SortDescription &sortDescription = SortDescription()); + bool GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, bool albumArtistsOnly = false, int idGenre = -1, int idAlbum = -1, int idSong = -1, const SortDescription &sortDescription = SortDescription()); + bool GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre = -1, int idArtist = -1, const SortDescription &sortDescription = SortDescription()); bool GetAlbumsByYear(const CStdString &strBaseDir, CFileItemList& items, int year); bool GetSongsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idArtist,int idAlbum, const SortDescription &sortDescription = SortDescription()); bool GetSongsByYear(const CStdString& baseDir, CFileItemList& items, int year); - bool GetSongsByWhere(const CStdString &baseDir, const CStdString &whereClause, CFileItemList& items, const SortDescription &sortDescription = SortDescription()); - bool GetAlbumsByWhere(const CStdString &baseDir, const CStdString &where, const CStdString &order, CFileItemList &items, const SortDescription &sortDescription = SortDescription()); - bool GetArtistsByWhere(const CStdString& strBaseDir, const CStdString &where, CFileItemList& items); - bool GetRandomSong(CFileItem* item, int& idSong, const CStdString& strWhere); + bool GetSongsByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription()); + bool GetAlbumsByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList &items, const SortDescription &sortDescription = SortDescription()); + bool GetArtistsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription()); + bool GetRandomSong(CFileItem* item, int& idSong, const Filter &filter); int GetKaraokeSongsCount(); - int GetSongsCount(const CStdString& strWhere = ""); - unsigned int GetSongIDs(const CStdString& strWhere, std::vector<std::pair<int,int> > &songIDs); + int GetSongsCount(const Filter &filter = Filter()); + unsigned int GetSongIDs(const Filter &filter, std::vector<std::pair<int,int> > &songIDs); bool GetAlbumPath(int idAlbum, CStdString &path); bool SaveAlbumThumb(int idAlbum, const CStdString &thumb); @@ -291,12 +265,14 @@ public: */ std::string GetArtistArtForItem(int mediaId, const std::string &mediaType, const std::string &artType); + virtual bool GetFilter(const CDbUrl &musicUrl, Filter &filter); + protected: - std::map<CStdString, int /*CArtistCache*/> m_artistCache; - std::map<CStdString, int /*CGenreCache*/> m_genreCache; - std::map<CStdString, int /*CPathCache*/> m_pathCache; - std::map<CStdString, int /*CPathCache*/> m_thumbCache; - std::map<CStdString, CAlbumCache> m_albumCache; + std::map<CStdString, int> m_artistCache; + std::map<CStdString, int> m_genreCache; + std::map<CStdString, int> m_pathCache; + std::map<CStdString, int> m_thumbCache; + std::map<CStdString, CAlbum> m_albumCache; virtual bool CreateTables(); virtual int GetMinVersion() const { return 27; }; @@ -323,7 +299,8 @@ private: void SplitString(const CStdString &multiString, std::vector<std::string> &vecStrings, CStdString &extraStrings); CSong GetSongFromDataset(bool bWithMusicDbPath=false); - CArtist GetArtistFromDataset(dbiplus::Dataset* pDS, bool needThumb=true); + CArtist GetArtistFromDataset(dbiplus::Dataset* pDS, bool needThumb = true); + CArtist GetArtistFromDataset(const dbiplus::sql_record* const record, bool needThumb = true); CAlbum GetAlbumFromDataset(dbiplus::Dataset* pDS, bool imageURL=false); CAlbum GetAlbumFromDataset(const dbiplus::sql_record* const record, bool imageURL=false); void GetFileItemFromDataset(CFileItem* item, const CStdString& strMusicDBbasePath); diff --git a/xbmc/music/MusicDbUrl.cpp b/xbmc/music/MusicDbUrl.cpp new file mode 100644 index 0000000000..d9c157d0c3 --- /dev/null +++ b/xbmc/music/MusicDbUrl.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "MusicDbUrl.h" +#include "filesystem/MusicDatabaseDirectory.h" +#include "utils/StringUtils.h" +#include "utils/Variant.h" + +using namespace std; +using namespace XFILE; +using namespace XFILE::MUSICDATABASEDIRECTORY; + +CMusicDbUrl::CMusicDbUrl() + : CDbUrl() +{ } + +CMusicDbUrl::~CMusicDbUrl() +{ } + +bool CMusicDbUrl::parse() +{ + // the URL must start with musicdb:// + if (m_url.GetProtocol() != "musicdb" || m_url.GetFileName().empty()) + return false; + + CStdString path = m_url.Get(); + NODE_TYPE dirType = CMusicDatabaseDirectory::GetDirectoryType(path); + NODE_TYPE childType = CMusicDatabaseDirectory::GetDirectoryChildType(path); + + switch (dirType) + { + case NODE_TYPE_ARTIST: + m_type = "artists"; + break; + + case NODE_TYPE_ALBUM: + case NODE_TYPE_ALBUM_RECENTLY_ADDED: + case NODE_TYPE_ALBUM_RECENTLY_PLAYED: + case NODE_TYPE_ALBUM_TOP100: + case NODE_TYPE_ALBUM_COMPILATIONS: + case NODE_TYPE_YEAR_ALBUM: + case NODE_TYPE_SINGLES: + m_type = "albums"; + break; + + case NODE_TYPE_ALBUM_RECENTLY_ADDED_SONGS: + case NODE_TYPE_ALBUM_RECENTLY_PLAYED_SONGS: + case NODE_TYPE_ALBUM_TOP100_SONGS: + case NODE_TYPE_ALBUM_COMPILATIONS_SONGS: + case NODE_TYPE_SONG: + case NODE_TYPE_SONG_TOP100: + case NODE_TYPE_YEAR_SONG: + m_type = "songs"; + break; + + default: + break; + } + + switch (childType) + { + case NODE_TYPE_ARTIST: + m_type = "artists"; + break; + + case NODE_TYPE_ALBUM: + case NODE_TYPE_ALBUM_RECENTLY_ADDED: + case NODE_TYPE_ALBUM_RECENTLY_PLAYED: + case NODE_TYPE_ALBUM_TOP100: + case NODE_TYPE_YEAR_ALBUM: + m_type = "albums"; + break; + + case NODE_TYPE_SONG: + case NODE_TYPE_ALBUM_RECENTLY_ADDED_SONGS: + case NODE_TYPE_ALBUM_RECENTLY_PLAYED_SONGS: + case NODE_TYPE_ALBUM_TOP100_SONGS: + case NODE_TYPE_ALBUM_COMPILATIONS_SONGS: + case NODE_TYPE_SONG_TOP100: + case NODE_TYPE_YEAR_SONG: + m_type = "songs"; + break; + + case NODE_TYPE_GENRE: + m_type = "genres"; + break; + + case NODE_TYPE_YEAR: + m_type = "years"; + break; + + case NODE_TYPE_ALBUM_COMPILATIONS: + m_type = "albums"; + break; + + case NODE_TYPE_SINGLES: + m_type = "albums"; + break; + + case NODE_TYPE_TOP100: + m_type = "top100"; + break; + + case NODE_TYPE_ROOT: + case NODE_TYPE_OVERVIEW: + default: + return false; + } + + if (m_type.empty()) + return false; + + // parse query params + CQueryParams queryParams; + CDirectoryNode::GetDatabaseInfo(path, queryParams); + + // retrieve and parse all options + AddOptions(m_url.GetOptions()); + + // add options based on the QueryParams + if (queryParams.GetArtistId() != -1) + AddOption("artistid", (int)queryParams.GetArtistId()); + if (queryParams.GetAlbumId() != -1) + AddOption("albumid", (int)queryParams.GetAlbumId()); + if (queryParams.GetGenreId() != -1) + AddOption("genreid", (int)queryParams.GetGenreId()); + if (queryParams.GetSongId() != -1) + AddOption("songid", (int)queryParams.GetSongId()); + if (queryParams.GetYear() != -1) + AddOption("year", (int)queryParams.GetYear()); + + return true; +} diff --git a/xbmc/music/MusicDbUrl.h b/xbmc/music/MusicDbUrl.h new file mode 100644 index 0000000000..68973bb49a --- /dev/null +++ b/xbmc/music/MusicDbUrl.h @@ -0,0 +1,33 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <string> + +#include "DbUrl.h" + +class CMusicDbUrl : public CDbUrl +{ +public: + CMusicDbUrl(); + virtual ~CMusicDbUrl(); + +protected: + virtual bool parse(); +}; diff --git a/xbmc/music/dialogs/GUIDialogMusicInfo.cpp b/xbmc/music/dialogs/GUIDialogMusicInfo.cpp index 4b438e8fae..14fbc3d245 100644 --- a/xbmc/music/dialogs/GUIDialogMusicInfo.cpp +++ b/xbmc/music/dialogs/GUIDialogMusicInfo.cpp @@ -21,7 +21,6 @@ #include "GUIDialogMusicInfo.h" #include "guilib/GUIWindowManager.h" -#include "Util.h" #include "guilib/GUIImage.h" #include "dialogs/GUIDialogFileBrowser.h" #include "GUIPassword.h" diff --git a/xbmc/music/dialogs/GUIDialogMusicOSD.cpp b/xbmc/music/dialogs/GUIDialogMusicOSD.cpp index a5c26e6971..353719939c 100644 --- a/xbmc/music/dialogs/GUIDialogMusicOSD.cpp +++ b/xbmc/music/dialogs/GUIDialogMusicOSD.cpp @@ -20,7 +20,6 @@ */ #include "GUIDialogMusicOSD.h" -#include "Application.h" #include "guilib/GUIWindowManager.h" #include "input/MouseStat.h" #include "GUIUserMessages.h" diff --git a/xbmc/music/dialogs/GUIDialogMusicOverlay.cpp b/xbmc/music/dialogs/GUIDialogMusicOverlay.cpp index 0fd8aab5e6..381e3fa7e7 100644 --- a/xbmc/music/dialogs/GUIDialogMusicOverlay.cpp +++ b/xbmc/music/dialogs/GUIDialogMusicOverlay.cpp @@ -20,7 +20,6 @@ */ #include "GUIDialogMusicOverlay.h" -#include "GUIInfoManager.h" #include "guilib/GUIWindowManager.h" #include "input/MouseStat.h" diff --git a/xbmc/music/dialogs/GUIDialogMusicScan.cpp b/xbmc/music/dialogs/GUIDialogMusicScan.cpp index 096b94f266..1e2a0d20ef 100644 --- a/xbmc/music/dialogs/GUIDialogMusicScan.cpp +++ b/xbmc/music/dialogs/GUIDialogMusicScan.cpp @@ -22,6 +22,7 @@ #include "GUIDialogMusicScan.h" #include "guilib/GUIProgressControl.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "Util.h" #include "URL.h" #include "guilib/GUIWindowManager.h" @@ -124,7 +125,7 @@ void CGUIDialogMusicScan::OnFinished() if (!g_guiSettings.GetBool("musiclibrary.backgroundupdate")) { - g_application.getApplicationMessenger().Close(this, false, false); + CApplicationMessenger::Get().Close(this, false, false); } } diff --git a/xbmc/music/dialogs/GUIDialogSongInfo.cpp b/xbmc/music/dialogs/GUIDialogSongInfo.cpp index 770d6466fc..1735864ff9 100644 --- a/xbmc/music/dialogs/GUIDialogSongInfo.cpp +++ b/xbmc/music/dialogs/GUIDialogSongInfo.cpp @@ -20,7 +20,6 @@ */ #include "GUIDialogSongInfo.h" -#include "Util.h" #include "utils/URIUtils.h" #include "utils/StringUtils.h" #include "dialogs/GUIDialogFileBrowser.h" diff --git a/xbmc/music/infoscanner/MusicInfoScanner.cpp b/xbmc/music/infoscanner/MusicInfoScanner.cpp index 6f8928edb9..1f6dcc01b2 100644 --- a/xbmc/music/infoscanner/MusicInfoScanner.cpp +++ b/xbmc/music/infoscanner/MusicInfoScanner.cpp @@ -35,7 +35,7 @@ #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogProgress.h" #include "dialogs/GUIDialogSelect.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "filesystem/File.h" #include "filesystem/Directory.h" #include "settings/AdvancedSettings.h" @@ -239,7 +239,7 @@ void CMusicInfoScanner::FetchAlbumInfo(const CStdString& strDirectory, if (strDirectory.IsEmpty()) { m_musicDatabase.Open(); - m_musicDatabase.GetAlbumsNav("musicdb://3/",items,-1,-1,-1,-1); + m_musicDatabase.GetAlbumsNav("musicdb://3/", items); m_musicDatabase.Close(); } else @@ -289,7 +289,7 @@ void CMusicInfoScanner::FetchArtistInfo(const CStdString& strDirectory, if (strDirectory.IsEmpty()) { m_musicDatabase.Open(); - m_musicDatabase.GetArtistsNav("musicdb://2/",items,-1,false); + m_musicDatabase.GetArtistsNav("musicdb://2/", items, false, -1); m_musicDatabase.Close(); } else @@ -739,10 +739,15 @@ void CMusicInfoScanner::FindArtForAlbums(VECALBUMS &albums, const CStdString &pa for (VECALBUMS::iterator i = albums.begin(); i != albums.end(); ++i) { CAlbum &album = *i; + + if (albums.size() != 1) + albumArt = ""; + /* Find art that is common across these items If we find a single art image we treat it as the album art - else we keep everything as song art. + and discard song art else we use first as album art and + keep everything as song art. */ bool singleArt = true; CSong *art = NULL; @@ -760,23 +765,28 @@ void CMusicInfoScanner::FindArtForAlbums(VECALBUMS &albums, const CStdString &pa art = &song; } } + + /* + assign the first art found to the album - better than no art at all + */ + + if (art && albumArt.empty()) + { + if (!art->strThumb.empty()) + albumArt = art->strThumb; + else + albumArt = CTextureCache::GetWrappedImageURL(art->strFileName, "music"); + } + + album.art["thumb"] = albumArt; + if (singleArt) - { // a single piece of art was found for these songs so assign to the album - // and clear out of the songs - if (art && albumArt.empty()) - { - if (!art->strThumb.empty()) - albumArt = art->strThumb; - else - albumArt = CTextureCache::GetWrappedImageURL(art->strFileName, "music"); - } + { //if singleArt then we can clear the artwork for all songs for (VECSONGS::iterator k = album.songs.begin(); k != album.songs.end(); ++k) k->strThumb.clear(); - albums[0].art["thumb"] = albumArt; } else { // more than one piece of art was found for these songs, so cache per song - // and don't assign to the album for (VECSONGS::iterator k = album.songs.begin(); k != album.songs.end(); ++k) { if (k->strThumb.empty() && !k->embeddedArt.empty()) @@ -930,16 +940,18 @@ bool CMusicInfoScanner::DownloadAlbumInfo(const CStdString& strPath, const CStdS } if (!scraper.GetAlbumCount()) + { scraper.FindAlbumInfo(strAlbum, strArtist); - while (!scraper.Completed()) - { - if (m_bStop) + while (!scraper.Completed()) { - scraper.Cancel(); - bCanceled = true; + if (m_bStop) + { + scraper.Cancel(); + bCanceled = true; + } + Sleep(1); } - Sleep(1); } CGUIDialogSelect *pDlg=NULL; @@ -1021,11 +1033,11 @@ bool CMusicInfoScanner::DownloadAlbumInfo(const CStdString& strPath, const CStdS } // manual button pressed CStdString strNewAlbum = strAlbum; - if (!CGUIDialogKeyboard::ShowAndGetInput(strNewAlbum, g_localizeStrings.Get(16011), false)) return false; + if (!CGUIKeyboardFactory::ShowAndGetInput(strNewAlbum, g_localizeStrings.Get(16011), false)) return false; if (strNewAlbum == "") return false; CStdString strNewArtist = strArtist; - if (!CGUIDialogKeyboard::ShowAndGetInput(strNewArtist, g_localizeStrings.Get(16025), false)) return false; + if (!CGUIKeyboardFactory::ShowAndGetInput(strNewArtist, g_localizeStrings.Get(16025), false)) return false; pDialog->SetLine(0, strNewAlbum); pDialog->SetLine(1, strNewArtist); @@ -1156,16 +1168,18 @@ bool CMusicInfoScanner::DownloadArtistInfo(const CStdString& strPath, const CStd } if (!scraper.GetArtistCount()) + { scraper.FindArtistInfo(strArtist); - while (!scraper.Completed()) - { - if (m_bStop) + while (!scraper.Completed()) { - scraper.Cancel(); - bCanceled = true; + if (m_bStop) + { + scraper.Cancel(); + bCanceled = true; + } + Sleep(1); } - Sleep(1); } int iSelectedArtist = 0; @@ -1213,7 +1227,7 @@ bool CMusicInfoScanner::DownloadArtistInfo(const CStdString& strPath, const CStd } // manual button pressed CStdString strNewArtist = strArtist; - if (!CGUIDialogKeyboard::ShowAndGetInput(strNewArtist, g_localizeStrings.Get(16025), false)) return false; + if (!CGUIKeyboardFactory::ShowAndGetInput(strNewArtist, g_localizeStrings.Get(16025), false)) return false; if (pDialog) { diff --git a/xbmc/music/infoscanner/MusicInfoScraper.cpp b/xbmc/music/infoscanner/MusicInfoScraper.cpp index 9564e21f28..6959514897 100644 --- a/xbmc/music/infoscanner/MusicInfoScraper.cpp +++ b/xbmc/music/infoscanner/MusicInfoScraper.cpp @@ -20,9 +20,9 @@ */ #include "MusicInfoScraper.h" -#include "URL.h" #include "utils/CharsetConverter.h" #include "utils/log.h" +#include "filesystem/CurlFile.h" using namespace MUSIC_GRABBER; using namespace ADDON; @@ -35,11 +35,13 @@ CMusicInfoScraper::CMusicInfoScraper(const ADDON::ScraperPtr &scraper) : CThread m_iAlbum=-1; m_iArtist=-1; m_scraper = scraper; + m_http = new XFILE::CCurlFile; } CMusicInfoScraper::~CMusicInfoScraper(void) { StopThread(); + delete m_http; } int CMusicInfoScraper::GetAlbumCount() const @@ -81,13 +83,13 @@ void CMusicInfoScraper::FindArtistInfo(const CStdString& strArtist) void CMusicInfoScraper::FindAlbumInfo() { - m_vecAlbums = m_scraper->FindAlbum(m_http, m_strAlbum, m_strArtist); + m_vecAlbums = m_scraper->FindAlbum(*m_http, m_strAlbum, m_strArtist); m_bSucceeded = !m_vecAlbums.empty(); } void CMusicInfoScraper::FindArtistInfo() { - m_vecArtists = m_scraper->FindArtist(m_http, m_strArtist); + m_vecArtists = m_scraper->FindArtist(*m_http, m_strArtist); m_bSucceeded = !m_vecArtists.empty(); } @@ -115,7 +117,7 @@ void CMusicInfoScraper::LoadAlbumInfo() CMusicAlbumInfo& album=m_vecAlbums[m_iAlbum]; album.GetAlbum().artist.clear(); - if (album.Load(m_http,m_scraper)) + if (album.Load(*m_http,m_scraper)) m_bSucceeded=true; } @@ -126,7 +128,7 @@ void CMusicInfoScraper::LoadArtistInfo() CMusicArtistInfo& artist=m_vecArtists[m_iArtist]; artist.GetArtist().strArtist.Empty(); - if (artist.Load(m_http,m_scraper,m_strSearch)) + if (artist.Load(*m_http,m_scraper,m_strSearch)) m_bSucceeded=true; } @@ -142,9 +144,9 @@ bool CMusicInfoScraper::Succeeded() void CMusicInfoScraper::Cancel() { - m_http.Cancel(); + m_http->Cancel(); m_bCanceled=true; - m_http.Reset(); + m_http->Reset(); } bool CMusicInfoScraper::IsCanceled() diff --git a/xbmc/music/infoscanner/MusicInfoScraper.h b/xbmc/music/infoscanner/MusicInfoScraper.h index 6a0c8634fe..445a53483d 100644 --- a/xbmc/music/infoscanner/MusicInfoScraper.h +++ b/xbmc/music/infoscanner/MusicInfoScraper.h @@ -25,7 +25,11 @@ #include "MusicArtistInfo.h" #include "addons/Scraper.h" #include "threads/Thread.h" -#include "filesystem/CurlFile.h" + +namespace XFILE +{ +class CurlFile; +} namespace MUSIC_GRABBER { @@ -82,7 +86,7 @@ protected: int m_iArtist; bool m_bSucceeded; bool m_bCanceled; - XFILE::CCurlFile m_http; + XFILE::CCurlFile* m_http; ADDON::ScraperPtr m_scraper; }; diff --git a/xbmc/music/karaoke/GUIDialogKaraokeSongSelector.cpp b/xbmc/music/karaoke/GUIDialogKaraokeSongSelector.cpp index 8abdd30090..4df571f69c 100644 --- a/xbmc/music/karaoke/GUIDialogKaraokeSongSelector.cpp +++ b/xbmc/music/karaoke/GUIDialogKaraokeSongSelector.cpp @@ -20,7 +20,7 @@ */ #include "GUIDialogKaraokeSongSelector.h" -#include "Application.h" +#include "PlayListPlayer.h" #include "playlists/PlayList.h" #include "guilib/LocalizeStrings.h" #include "utils/log.h" diff --git a/xbmc/music/tags/FlacTag.cpp b/xbmc/music/tags/FlacTag.cpp index da9ca7bb24..1669ee33a6 100644 --- a/xbmc/music/tags/FlacTag.cpp +++ b/xbmc/music/tags/FlacTag.cpp @@ -21,7 +21,6 @@ #include "system.h" #include "FlacTag.h" -#include "Util.h" #include "filesystem/File.h" #include "utils/log.h" #include "utils/EndianSwap.h" diff --git a/xbmc/music/tags/Id3Tag.cpp b/xbmc/music/tags/Id3Tag.cpp index 3dd2c4ef18..8f112ed933 100644 --- a/xbmc/music/tags/Id3Tag.cpp +++ b/xbmc/music/tags/Id3Tag.cpp @@ -20,7 +20,6 @@ */ #include "Id3Tag.h" -#include "Util.h" #include "utils/StringUtils.h" #include "settings/AdvancedSettings.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/music/tags/MusicInfoTag.cpp b/xbmc/music/tags/MusicInfoTag.cpp index c93e664071..990d42ea51 100644 --- a/xbmc/music/tags/MusicInfoTag.cpp +++ b/xbmc/music/tags/MusicInfoTag.cpp @@ -503,15 +503,15 @@ void CMusicInfoTag::SetSong(const CSong& song) void CMusicInfoTag::Serialize(CVariant& value) { - /* TODO: - All the StringUtils::Join() calls can be removed once backwards-compatibility to - JSON-RPC v4 can be broken */ value["url"] = m_strURL; value["title"] = m_strTitle; - value["artist"] = StringUtils::Join(m_artist, " / "); + if (m_type.compare("artist") == 0 && m_artist.size() == 1) + value["artist"] = m_artist[0]; + else + value["artist"] = m_artist; value["album"] = m_strAlbum; - value["albumartist"] = StringUtils::Join(m_albumArtist, " / "); - value["genre"] = StringUtils::Join(m_genre, " / "); + value["albumartist"] = m_albumArtist; + value["genre"] = m_genre; value["duration"] = m_iDuration; value["track"] = GetTrackNumber(); value["disc"] = GetDiscNumber(); diff --git a/xbmc/music/tags/MusicInfoTagLoaderMP4.cpp b/xbmc/music/tags/MusicInfoTagLoaderMP4.cpp index ec5f184357..e35b106241 100644 --- a/xbmc/music/tags/MusicInfoTagLoaderMP4.cpp +++ b/xbmc/music/tags/MusicInfoTagLoaderMP4.cpp @@ -20,7 +20,6 @@ */ #include "MusicInfoTagLoaderMP4.h" -#include "Util.h" #include "id3v1genre.h" #include "MusicInfoTag.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/music/tags/MusicInfoTagLoaderWMA.cpp b/xbmc/music/tags/MusicInfoTagLoaderWMA.cpp index 535014ed42..3d8febba09 100644 --- a/xbmc/music/tags/MusicInfoTagLoaderWMA.cpp +++ b/xbmc/music/tags/MusicInfoTagLoaderWMA.cpp @@ -20,7 +20,6 @@ */ #include "MusicInfoTagLoaderWMA.h" -#include "Util.h" #include "MusicInfoTag.h" #include "filesystem/File.h" #include "settings/AdvancedSettings.h" diff --git a/xbmc/music/windows/GUIWindowMusicBase.cpp b/xbmc/music/windows/GUIWindowMusicBase.cpp index 1b0a5dd068..faaeb86acf 100644 --- a/xbmc/music/windows/GUIWindowMusicBase.cpp +++ b/xbmc/music/windows/GUIWindowMusicBase.cpp @@ -51,7 +51,7 @@ #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogYesNo.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "dialogs/GUIDialogProgress.h" #include "FileItem.h" #include "filesystem/File.h" @@ -66,6 +66,7 @@ #include "video/VideoInfoTag.h" #include "utils/StringUtils.h" #include "ThumbLoader.h" +#include "URL.h" using namespace std; using namespace XFILE; @@ -379,11 +380,11 @@ void CGUIWindowMusicBase::OnManualAlbumInfo() { CAlbum album; album.idAlbum = -1; // not in the db - if (!CGUIDialogKeyboard::ShowAndGetInput(album.strAlbum, g_localizeStrings.Get(16011), false)) + if (!CGUIKeyboardFactory::ShowAndGetInput(album.strAlbum, g_localizeStrings.Get(16011), false)) return; CStdString strArtist = StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator); - if (!CGUIDialogKeyboard::ShowAndGetInput(strArtist, g_localizeStrings.Get(16025), false)) + if (!CGUIKeyboardFactory::ShowAndGetInput(strArtist, g_localizeStrings.Get(16025), false)) return; ShowAlbumInfo(album,"",true); @@ -671,7 +672,10 @@ void CGUIWindowMusicBase::AddItemToPlayList(const CFileItemPtr &pItem, CFileItem { // grab the ALL item in this category // Genres will still require 2 lookups, and queuing the entire Genre folder // will require 3 lookups (genre, artist, album) - CFileItemPtr item(new CFileItem(pItem->GetPath() + "-1/", true)); + CMusicDbUrl musicUrl; + musicUrl.FromString(pItem->GetPath()); + musicUrl.AppendPath("-1/"); + CFileItemPtr item(new CFileItem(musicUrl.ToString(), true)); item->SetCanQueue(true); // workaround for CanQueue() check above AddItemToPlayList(item, queuedItems); return; @@ -790,10 +794,10 @@ bool CGUIWindowMusicBase::FindAlbumInfo(const CStdString& strAlbum, const CStdSt return false; if (m_dlgProgress && allowSelection != SELECTION_AUTO) { - if (!CGUIDialogKeyboard::ShowAndGetInput(strTempAlbum, g_localizeStrings.Get(16011), false)) + if (!CGUIKeyboardFactory::ShowAndGetInput(strTempAlbum, g_localizeStrings.Get(16011), false)) return false; - if (!CGUIDialogKeyboard::ShowAndGetInput(strTempArtist, g_localizeStrings.Get(16025), false)) + if (!CGUIKeyboardFactory::ShowAndGetInput(strTempArtist, g_localizeStrings.Get(16025), false)) return false; } else @@ -840,7 +844,7 @@ bool CGUIWindowMusicBase::FindArtistInfo(const CStdString& strArtist, CMusicArti return false; if (m_dlgProgress && allowSelection != SELECTION_AUTO) { - if (!CGUIDialogKeyboard::ShowAndGetInput(strTempArtist, g_localizeStrings.Get(16025), false)) + if (!CGUIKeyboardFactory::ShowAndGetInput(strTempArtist, g_localizeStrings.Get(16025), false)) return false; } else diff --git a/xbmc/music/windows/GUIWindowMusicNav.cpp b/xbmc/music/windows/GUIWindowMusicNav.cpp index 8130a01bce..752dbb5e6a 100644 --- a/xbmc/music/windows/GUIWindowMusicNav.cpp +++ b/xbmc/music/windows/GUIWindowMusicNav.cpp @@ -24,7 +24,6 @@ #include "utils/URIUtils.h" #include "PlayListPlayer.h" #include "GUIPassword.h" -#include "dialogs/GUIDialogFileBrowser.h" #include "settings/GUIDialogContentSettings.h" #include "filesystem/MusicDatabaseDirectory.h" #include "filesystem/VideoDatabaseDirectory.h" @@ -36,19 +35,22 @@ #include "music/tags/MusicInfoTag.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogOK.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "dialogs/GUIDialogYesNo.h" #include "guilib/GUIEditControl.h" #include "GUIUserMessages.h" #include "filesystem/File.h" #include "FileItem.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "settings/Settings.h" #include "settings/AdvancedSettings.h" #include "guilib/LocalizeStrings.h" #include "utils/log.h" #include "utils/StringUtils.h" #include "TextureCache.h" +#include "Util.h" +#include "URL.h" using namespace std; using namespace XFILE; @@ -162,7 +164,7 @@ bool CGUIWindowMusicNav::OnMessage(CGUIMessage& message) return true; } CStdString search(GetProperty("search").asString()); - CGUIDialogKeyboard::ShowAndGetFilter(search, true); + CGUIKeyboardFactory::ShowAndGetFilter(search, true); SetProperty("search", search); return true; } @@ -253,7 +255,7 @@ bool CGUIWindowMusicNav::OnClick(int iItem) else { CStdString search(GetProperty("search").asString()); - CGUIDialogKeyboard::ShowAndGetFilter(search, true); + CGUIKeyboardFactory::ShowAndGetFilter(search, true); SetProperty("search", search); } return true; @@ -641,7 +643,7 @@ bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) database.Open(); CVideoInfoTag details; database.GetMusicVideoInfo("",details,database.GetMatchingMusicVideo(StringUtils::Join(item->GetMusicInfoTag()->GetArtist(), g_advancedSettings.m_musicItemSeparator),item->GetMusicInfoTag()->GetAlbum(),item->GetMusicInfoTag()->GetTitle())); - g_application.getApplicationMessenger().PlayFile(CFileItem(details)); + CApplicationMessenger::Get().PlayFile(CFileItem(details)); return true; } diff --git a/xbmc/music/windows/GUIWindowMusicPlaylist.cpp b/xbmc/music/windows/GUIWindowMusicPlaylist.cpp index a72fc04e09..b7c1978684 100644 --- a/xbmc/music/windows/GUIWindowMusicPlaylist.cpp +++ b/xbmc/music/windows/GUIWindowMusicPlaylist.cpp @@ -30,7 +30,7 @@ #include "utils/LabelFormatter.h" #include "music/tags/MusicInfoTag.h" #include "guilib/GUIWindowManager.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "GUIUserMessages.h" #include "Favourites.h" #include "settings/Settings.h" @@ -282,7 +282,7 @@ bool CGUIWindowMusicPlayList::MoveCurrentPlayListItem(int iItem, int iAction, bo void CGUIWindowMusicPlayList::SavePlayList() { CStdString strNewFileName; - if (CGUIDialogKeyboard::ShowAndGetInput(strNewFileName, g_localizeStrings.Get(16012), false)) + if (CGUIKeyboardFactory::ShowAndGetInput(strNewFileName, g_localizeStrings.Get(16012), false)) { // need 2 rename it CStdString strFolder, strPath; diff --git a/xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp b/xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp index 6ad9538ac7..73a08d2f59 100644 --- a/xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp +++ b/xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp @@ -31,8 +31,7 @@ #include "filesystem/Directory.h" #include "playlists/PlayListM3U.h" #include "guilib/GUIWindowManager.h" -#include "dialogs/GUIDialogKeyboard.h" -#include "dialogs/GUIDialogYesNo.h" +#include "guilib/GUIKeyboardFactory.h" #include "FileItem.h" #include "settings/GUISettings.h" #include "GUIUserMessages.h" @@ -393,7 +392,7 @@ void CGUIWindowMusicPlaylistEditor::OnSavePlaylist() CStdString name = URIUtils::GetFileName(m_strLoadedPlaylist); CStdString strExt = URIUtils::GetExtension(name); name = name.Mid(0,name.size()-strExt.size()); - if (CGUIDialogKeyboard::ShowAndGetInput(name, g_localizeStrings.Get(16012), false)) + if (CGUIKeyboardFactory::ShowAndGetInput(name, g_localizeStrings.Get(16012), false)) { // save playlist as an .m3u PLAYLIST::CPlayListM3U playlist; playlist.Add(*m_playlist); diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp index 5cf254b27c..747e4eba48 100644 --- a/xbmc/network/AirPlayServer.cpp +++ b/xbmc/network/AirPlayServer.cpp @@ -29,12 +29,13 @@ #include "utils/StringUtils.h" #include "threads/SingleLock.h" #include "filesystem/File.h" -#include "Util.h" #include "FileItem.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "utils/md5.h" #include "utils/Variant.h" #include "guilib/GUIWindowManager.h" +#include "URL.h" #ifdef TARGET_WINDOWS #define close closesocket @@ -667,7 +668,7 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, { if (g_application.m_pPlayer && g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused()) { - g_application.getApplicationMessenger().MediaPause(); + CApplicationMessenger::Get().MediaPause(); ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_PAUSED); } } @@ -675,7 +676,7 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, { if (g_application.m_pPlayer && g_application.m_pPlayer->IsPlaying() && g_application.m_pPlayer->IsPaused()) { - g_application.getApplicationMessenger().MediaPause(); + CApplicationMessenger::Get().MediaPause(); ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_PLAYING); } } @@ -703,7 +704,7 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, if(oldVolume != (int)volume) { g_application.SetVolume(volume); - g_application.getApplicationMessenger().ShowVolumeBar(oldVolume < volume); + CApplicationMessenger::Get().ShowVolumeBar(oldVolume < volume); } } } @@ -800,7 +801,7 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, CFileItem fileToPlay(location, false); fileToPlay.SetProperty("StartPercent", position*100.0f); - g_application.getApplicationMessenger().MediaPlay(fileToPlay); + CApplicationMessenger::Get().MediaPlay(fileToPlay); ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_PLAYING); } } @@ -820,7 +821,7 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, if (g_application.m_pPlayer && g_application.m_pPlayer->GetTotalTime()) { float position = ((float) g_application.m_pPlayer->GetTime()) / 1000; - responseBody.Format("duration: %d\r\nposition: %f", g_application.m_pPlayer->GetTotalTime(), position); + responseBody.Format("duration: %d\r\nposition: %f", g_application.m_pPlayer->GetTotalTime() / 1000, position); } else { @@ -852,7 +853,7 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, { if (IsPlaying()) //only stop player if we started him { - g_application.getApplicationMessenger().MediaStop(); + CApplicationMessenger::Get().MediaStop(); CAirPlayServer::m_isPlaying--; } else //if we are not playing and get the stop request - we just wanna stop picture streaming @@ -892,7 +893,7 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, if (writtenBytes > 0 && (unsigned int)writtenBytes == m_httpParser->getContentLength()) { - g_application.getApplicationMessenger().PictureShow(tmpFileName); + CApplicationMessenger::Get().PictureShow(tmpFileName); } else { @@ -906,7 +907,7 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, { float position = 0.0f; float duration = 0.0f; - float cacheDuration = 0.0f; + float cachePosition = 0.0f; bool playing = false; CLog::Log(LOGDEBUG, "AIRPLAY: got request %s", uri.c_str()); @@ -920,12 +921,12 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, if (g_application.m_pPlayer->GetTotalTime()) { position = ((float) g_application.m_pPlayer->GetTime()) / 1000; - duration = (float) g_application.m_pPlayer->GetTotalTime(); + duration = ((float) g_application.m_pPlayer->GetTotalTime()) / 1000; playing = g_application.m_pPlayer ? !g_application.m_pPlayer->IsPaused() : false; - cacheDuration = (float) g_application.m_pPlayer->GetTotalTime() * g_application.GetCachePercentage()/100.0f; + cachePosition = position + (duration * g_application.m_pPlayer->GetCachePercentage() / 100.0f); } - responseBody.Format(PLAYBACK_INFO, duration, cacheDuration, position, (playing ? 1 : 0), duration); + responseBody.Format(PLAYBACK_INFO, duration, cachePosition, position, (playing ? 1 : 0), duration); responseHeader = "Content-Type: text/x-apple-plist+xml\r\n"; if (g_application.m_pPlayer->IsCaching()) @@ -943,7 +944,7 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, } else { - responseBody.Format(PLAYBACK_INFO_NOT_READY, duration, cacheDuration, position, (playing ? 1 : 0), duration); + responseBody.Format(PLAYBACK_INFO_NOT_READY, duration, cachePosition, position, (playing ? 1 : 0), duration); responseHeader = "Content-Type: text/x-apple-plist+xml\r\n"; ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_STOPPED); } diff --git a/xbmc/network/AirTunesServer.cpp b/xbmc/network/AirTunesServer.cpp index 2ad097e8e5..66f2ceff56 100644 --- a/xbmc/network/AirTunesServer.cpp +++ b/xbmc/network/AirTunesServer.cpp @@ -43,6 +43,7 @@ #include "utils/Variant.h" #include "settings/AdvancedSettings.h" #include "utils/EndianSwap.h" +#include "URL.h" #include <map> #include <string> @@ -87,7 +88,7 @@ void CAirTunesServer::SetMetadataFromBuffer(const char *buffer, unsigned int siz tag.SetTitle(metadata["minm"]);//title if(metadata["asar"].length()) tag.SetArtist(metadata["asar"]);//artist - g_infoManager.SetCurrentSongTag(tag); + CApplicationMessenger::Get().SetCurrentSongTag(tag); } void CAirTunesServer::SetCoverArtFromBuffer(const char *buffer, unsigned int size) @@ -171,16 +172,16 @@ void* CAirTunesServer::AudioOutputFunctions::audio_init(void *cls, int bits, int return 0; ThreadMessage tMsg = { TMSG_MEDIA_STOP }; - g_application.getApplicationMessenger().SendMessage(tMsg, true); + CApplicationMessenger::Get().SendMessage(tMsg, true); CFileItem item; item.SetPath(pipe->GetName()); item.SetMimeType("audio/x-xbmc-pcm"); ThreadMessage tMsg2 = { TMSG_GUI_ACTIVATE_WINDOW, WINDOW_VISUALISATION, 0 }; - g_application.getApplicationMessenger().SendMessage(tMsg2, true); + CApplicationMessenger::Get().SendMessage(tMsg2, true); - g_application.getApplicationMessenger().PlayFile(item); + CApplicationMessenger::Get().PlayFile(item); return "XBMC-AirTunes";//session } @@ -234,7 +235,7 @@ void CAirTunesServer::AudioOutputFunctions::audio_destroy(void *cls, void *sess #endif { ThreadMessage tMsg = { TMSG_MEDIA_STOP }; - g_application.getApplicationMessenger().SendMessage(tMsg, true); + CApplicationMessenger::Get().SendMessage(tMsg, true); CLog::Log(LOGDEBUG, "AIRTUNES: AirPlay not running - stopping player"); } } @@ -339,7 +340,7 @@ ao_device* CAirTunesServer::AudioOutputFunctions::ao_open_live(int driver_id, ao return 0; ThreadMessage tMsg = { TMSG_MEDIA_STOP }; - g_application.getApplicationMessenger().SendMessage(tMsg, true); + CApplicationMessenger::Get().SendMessage(tMsg, true); CFileItem item; item.SetPath(device->pipe->GetName()); @@ -355,9 +356,9 @@ ao_device* CAirTunesServer::AudioOutputFunctions::ao_open_live(int driver_id, ao item.GetMusicInfoTag()->SetTitle(ao_get_option(option, "name")); ThreadMessage tMsg2 = { TMSG_GUI_ACTIVATE_WINDOW, WINDOW_VISUALISATION, 0 }; - g_application.getApplicationMessenger().SendMessage(tMsg2, true); + CApplicationMessenger::Get().SendMessage(tMsg2, true); - g_application.getApplicationMessenger().PlayFile(item); + CApplicationMessenger::Get().PlayFile(item); return (ao_device*) device; } @@ -380,7 +381,7 @@ int CAirTunesServer::AudioOutputFunctions::ao_close(ao_device *device) #endif { ThreadMessage tMsg = { TMSG_MEDIA_STOP }; - g_application.getApplicationMessenger().SendMessage(tMsg, true); + CApplicationMessenger::Get().SendMessage(tMsg, true); CLog::Log(LOGDEBUG, "AIRTUNES: AirPlay not running - stopping player"); } @@ -667,8 +668,10 @@ bool CAirTunesServer::Initialize(const CStdString &password) ao.ao_append_option = AudioOutputFunctions::ao_append_option; ao.ao_free_options = AudioOutputFunctions::ao_free_options; ao.ao_get_option = AudioOutputFunctions::ao_get_option; +#ifdef HAVE_STRUCT_AUDIOOUTPUT_AO_SET_METADATA ao.ao_set_metadata = AudioOutputFunctions::ao_set_metadata; ao.ao_set_metadata_coverart = AudioOutputFunctions::ao_set_metadata_coverart; +#endif struct printfPtr funcPtr; funcPtr.extprintf = shairport_log; diff --git a/xbmc/network/DNSNameCache.cpp b/xbmc/network/DNSNameCache.cpp index c30752c55f..b920933dfb 100644 --- a/xbmc/network/DNSNameCache.cpp +++ b/xbmc/network/DNSNameCache.cpp @@ -20,7 +20,6 @@ */ #include "DNSNameCache.h" -#include "Application.h" #include "threads/SingleLock.h" #include "utils/log.h" diff --git a/xbmc/network/GUIDialogAccessPoints.cpp b/xbmc/network/GUIDialogAccessPoints.cpp index 38715ec2c2..98f8ccf54b 100644 --- a/xbmc/network/GUIDialogAccessPoints.cpp +++ b/xbmc/network/GUIDialogAccessPoints.cpp @@ -20,7 +20,7 @@ */ #include "GUIDialogAccessPoints.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #ifdef _LINUX #include "linux/NetworkLinux.h" #endif @@ -52,7 +52,7 @@ bool CGUIDialogAccessPoints::OnAction(const CAction &action) if (iItem == (int) m_aps.size()) { m_selectedAPEssId = ""; - if (CGUIDialogKeyboard::ShowAndGetInput(m_selectedAPEssId, g_localizeStrings.Get(789), false)) + if (CGUIKeyboardFactory::ShowAndGetInput(m_selectedAPEssId, g_localizeStrings.Get(789), false)) { m_selectedAPEncMode = m_aps[iItem].getEncryptionMode(); m_wasItemSelected = true; diff --git a/xbmc/network/GUIDialogNetworkSetup.cpp b/xbmc/network/GUIDialogNetworkSetup.cpp index db7c3ff248..2736872d8e 100644 --- a/xbmc/network/GUIDialogNetworkSetup.cpp +++ b/xbmc/network/GUIDialogNetworkSetup.cpp @@ -21,8 +21,6 @@ #include "GUIDialogNetworkSetup.h" #include "guilib/GUISpinControlEx.h" -#include "dialogs/GUIDialogNumeric.h" -#include "dialogs/GUIDialogKeyboard.h" #include "dialogs/GUIDialogFileBrowser.h" #include "guilib/GUIWindowManager.h" #include "guilib/GUIEditControl.h" diff --git a/xbmc/network/Network.cpp b/xbmc/network/Network.cpp index b9e6227ec2..f44addda6b 100644 --- a/xbmc/network/Network.cpp +++ b/xbmc/network/Network.cpp @@ -22,6 +22,7 @@ #include "system.h" #include "Network.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "libscrobbler/lastfmscrobbler.h" #include "libscrobbler/librefmscrobbler.h" #include "utils/RssReader.h" @@ -94,12 +95,12 @@ bool in_ether (const char *bufp, unsigned char *addr) CNetwork::CNetwork() { - g_application.getApplicationMessenger().NetworkMessage(SERVICES_UP, 0); + CApplicationMessenger::Get().NetworkMessage(SERVICES_UP, 0); } CNetwork::~CNetwork() { - g_application.getApplicationMessenger().NetworkMessage(SERVICES_DOWN, 0); + CApplicationMessenger::Get().NetworkMessage(SERVICES_DOWN, 0); } int CNetwork::ParseHex(char *str, unsigned char *addr) diff --git a/xbmc/network/UPnP.cpp b/xbmc/network/UPnP.cpp index d6ce95bdc8..f114afd68b 100644 --- a/xbmc/network/UPnP.cpp +++ b/xbmc/network/UPnP.cpp @@ -24,7 +24,7 @@ #include "UPnP.h" #include "utils/URIUtils.h" #include "Application.h" - +#include "ApplicationMessenger.h" #include "Network.h" #include "utils/log.h" #include "filesystem/MusicDatabaseDirectory.h" @@ -59,13 +59,12 @@ #include "utils/md5.h" #include "guilib/Key.h" #include "ThumbLoader.h" +#include "Util.h" using namespace std; using namespace MUSIC_INFO; using namespace XFILE; -extern CGUIInfoManager g_infoManager; - NPT_SET_LOCAL_LOGGER("xbmc.upnp") #define UPNP_DEFAULT_MAX_RETURNED_ITEMS 200 @@ -1792,9 +1791,9 @@ CUPnPRenderer::OnNext(PLT_ActionReference& action) { if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) { CAction action(ACTION_NEXT_PICTURE); - g_application.getApplicationMessenger().SendAction(action, WINDOW_SLIDESHOW); + CApplicationMessenger::Get().SendAction(action, WINDOW_SLIDESHOW); } else { - g_application.getApplicationMessenger().PlayListPlayerNext(); + CApplicationMessenger::Get().PlayListPlayerNext(); } return NPT_SUCCESS; } @@ -1807,9 +1806,9 @@ CUPnPRenderer::OnPause(PLT_ActionReference& action) { if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) { CAction action(ACTION_PAUSE); - g_application.getApplicationMessenger().SendAction(action, WINDOW_SLIDESHOW); + CApplicationMessenger::Get().SendAction(action, WINDOW_SLIDESHOW); } else if (!g_application.IsPaused()) - g_application.getApplicationMessenger().MediaPause(); + CApplicationMessenger::Get().MediaPause(); return NPT_SUCCESS; } @@ -1822,7 +1821,7 @@ CUPnPRenderer::OnPlay(PLT_ActionReference& action) if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) { return NPT_SUCCESS; } else if (g_application.IsPaused()) { - g_application.getApplicationMessenger().MediaPause(); + CApplicationMessenger::Get().MediaPause(); } else if (!g_application.IsPlaying()) { NPT_String uri, meta; PLT_Service* service; @@ -1845,9 +1844,9 @@ CUPnPRenderer::OnPrevious(PLT_ActionReference& action) { if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) { CAction action(ACTION_PREV_PICTURE); - g_application.getApplicationMessenger().SendAction(action, WINDOW_SLIDESHOW); + CApplicationMessenger::Get().SendAction(action, WINDOW_SLIDESHOW); } else { - g_application.getApplicationMessenger().PlayListPlayerPrevious(); + CApplicationMessenger::Get().PlayListPlayerPrevious(); } return NPT_SUCCESS; } @@ -1860,9 +1859,9 @@ CUPnPRenderer::OnStop(PLT_ActionReference& action) { if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) { CAction action(ACTION_STOP); - g_application.getApplicationMessenger().SendAction(action, WINDOW_SLIDESHOW); + CApplicationMessenger::Get().SendAction(action, WINDOW_SLIDESHOW); } else { - g_application.getApplicationMessenger().MediaStop(); + CApplicationMessenger::Get().MediaStop(); } return NPT_SUCCESS; } @@ -1954,13 +1953,13 @@ CUPnPRenderer::PlayMedia(const char* uri, const char* meta, PLT_Action* action) } else if (object->m_ObjectClass.type.StartsWith("object.item.imageItem")) { bImageFile = true; } - bImageFile?g_application.getApplicationMessenger().PictureShow(item.GetPath()) - :g_application.getApplicationMessenger().MediaPlay(item); + bImageFile?CApplicationMessenger::Get().PictureShow(item.GetPath()) + :CApplicationMessenger::Get().MediaPlay(item); } else { bImageFile = NPT_String(PLT_MediaObject::GetUPnPClass(uri)).StartsWith("object.item.imageItem", true); - bImageFile?g_application.getApplicationMessenger().PictureShow((const char*)uri) - :g_application.getApplicationMessenger().MediaPlay((const char*)uri); + bImageFile?CApplicationMessenger::Get().PictureShow((const char*)uri) + :CApplicationMessenger::Get().MediaPlay((const char*)uri); } if (g_application.IsPlaying() || g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) { diff --git a/xbmc/network/WebServer.cpp b/xbmc/network/WebServer.cpp index 19a1febe74..0d4567ab5a 100644 --- a/xbmc/network/WebServer.cpp +++ b/xbmc/network/WebServer.cpp @@ -28,6 +28,7 @@ #include "utils/Base64.h" #include "threads/SingleLock.h" #include "XBDateTime.h" +#include "URL.h" #ifdef _WIN32 #pragma comment(lib, "libmicrohttpd.dll.lib") diff --git a/xbmc/network/ZeroconfBrowser.h b/xbmc/network/ZeroconfBrowser.h index 14f701b776..101ce851ef 100644 --- a/xbmc/network/ZeroconfBrowser.h +++ b/xbmc/network/ZeroconfBrowser.h @@ -25,7 +25,12 @@ #include <set> #include <vector> #include <map> -#include "URL.h" + +#include "utils/StdString.h" + +#ifdef _WIN32 +#undef SetPort // WIN32INCLUDES this is defined as SetPortA in WinSpool.h which is being included _somewhere_ +#endif //forwards class CCriticalSection; diff --git a/xbmc/network/httprequesthandler/HTTPVfsHandler.cpp b/xbmc/network/httprequesthandler/HTTPVfsHandler.cpp index 4c83459e40..73ae07ddd8 100644 --- a/xbmc/network/httprequesthandler/HTTPVfsHandler.cpp +++ b/xbmc/network/httprequesthandler/HTTPVfsHandler.cpp @@ -21,7 +21,6 @@ #include "HTTPVfsHandler.h" #include "network/WebServer.h" -#include "URL.h" #include "filesystem/File.h" using namespace std; diff --git a/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp b/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp index 6dd2c5cf17..b63f9dbe06 100644 --- a/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp +++ b/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp @@ -25,6 +25,7 @@ #include "utils/URIUtils.h" #include "filesystem/Directory.h" #include "filesystem/File.h" +#include "Util.h" #define DEFAULT_PAGE "index.html" diff --git a/xbmc/network/libscrobbler/scrobbler.cpp b/xbmc/network/libscrobbler/scrobbler.cpp index cd8cf57eac..b1b72dc78c 100644 --- a/xbmc/network/libscrobbler/scrobbler.cpp +++ b/xbmc/network/libscrobbler/scrobbler.cpp @@ -36,6 +36,7 @@ #include "guilib/LocalizeStrings.h" #include "filesystem/File.h" #include "filesystem/CurlFile.h" +#include "URL.h" #define SCROBBLER_CLIENT "xbm" //#define SCROBBLER_CLIENT "tst" // For testing ONLY! diff --git a/xbmc/network/linux/NetworkLinux.cpp b/xbmc/network/linux/NetworkLinux.cpp index 33c6fb042c..5ad3f743dc 100644 --- a/xbmc/network/linux/NetworkLinux.cpp +++ b/xbmc/network/linux/NetworkLinux.cpp @@ -28,6 +28,10 @@ #include <linux/wireless.h> #include <linux/sockios.h> #endif +#ifdef TARGET_ANDROID +#include "linux/getdelim.h" +#include "sys/system_properties.h" +#endif #include <errno.h> #include <resolv.h> #if defined(TARGET_DARWIN) @@ -475,12 +479,24 @@ std::vector<CStdString> CNetworkLinux::GetNameServers(void) } pclose(pipe); } +#elif defined(TARGET_ANDROID) + char nameserver[PROP_VALUE_MAX]; + + if (__system_property_get("net.dns1",nameserver)) + result.push_back(nameserver); + if (__system_property_get("net.dns2",nameserver)) + result.push_back(nameserver); + if (__system_property_get("net.dns3",nameserver)) + result.push_back(nameserver); + + if (!result.size()) + CLog::Log(LOGWARNING, "Unable to determine nameserver"); #else res_init(); for (int i = 0; i < _res.nscount; i ++) { - CStdString ns = inet_ntoa(((struct sockaddr_in *)&_res.nsaddr_list[0])->sin_addr); + CStdString ns = inet_ntoa(((struct sockaddr_in *)&_res.nsaddr_list[i])->sin_addr); result.push_back(ns); } #endif @@ -489,6 +505,7 @@ std::vector<CStdString> CNetworkLinux::GetNameServers(void) void CNetworkLinux::SetNameServers(std::vector<CStdString> nameServers) { +#if !defined(__ANDROID__) FILE* fp = fopen("/etc/resolv.conf", "w"); if (fp != NULL) { @@ -502,6 +519,7 @@ void CNetworkLinux::SetNameServers(std::vector<CStdString> nameServers) { // TODO: } +#endif } std::vector<NetworkAccessPoint> CNetworkInterfaceLinux::GetAccessPoints(void) diff --git a/xbmc/network/websocket/WebSocketV13.cpp b/xbmc/network/websocket/WebSocketV13.cpp index 173ae3a66d..aad4d6cee6 100644 --- a/xbmc/network/websocket/WebSocketV13.cpp +++ b/xbmc/network/websocket/WebSocketV13.cpp @@ -98,7 +98,7 @@ bool CWebSocketV13::Handshake(const char* data, size_t length, std::string &resp // There must be a "Upgrade" header with the value "websocket" value = header.getValue(WS_HEADER_UPGRADE_LC); - if (value == NULL || strcmp(value, WS_HEADER_UPGRADE_VALUE) != 0) + if (value == NULL || strnicmp(value, WS_HEADER_UPGRADE_VALUE, strlen(WS_HEADER_UPGRADE_VALUE)) != 0) { CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid \"%s\" received", WS_HEADER_UPGRADE); return true; diff --git a/xbmc/network/websocket/WebSocketV8.cpp b/xbmc/network/websocket/WebSocketV8.cpp index 2d5323ce85..06abe34878 100644 --- a/xbmc/network/websocket/WebSocketV8.cpp +++ b/xbmc/network/websocket/WebSocketV8.cpp @@ -185,7 +185,7 @@ const CWebSocketFrame* CWebSocketV8::close(WebSocketCloseReason reason /* = WebS m_state = WebSocketStateClosed; CWebSocketFrame* frame = new CWebSocketFrame(WebSocketConnectionClose, data, length); - delete data; + delete[] data; return frame; } diff --git a/xbmc/osx/IOSEAGLView.mm b/xbmc/osx/IOSEAGLView.mm index b47536855f..14147b0d77 100644 --- a/xbmc/osx/IOSEAGLView.mm +++ b/xbmc/osx/IOSEAGLView.mm @@ -30,6 +30,7 @@ #include "AdvancedSettings.h" #include "FileItem.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "WindowingFactory.h" #include "VideoReferenceClock.h" #include "utils/log.h" @@ -346,7 +347,7 @@ if (!g_application.m_bStop) { ThreadMessage tMsg = {TMSG_QUIT}; - g_application.getApplicationMessenger().SendMessage(tMsg); + CApplicationMessenger::Get().SendMessage(tMsg); } // wait for animation thread to die if ([animationThread isFinished] == NO) diff --git a/xbmc/osx/IOSScreenManager.mm b/xbmc/osx/IOSScreenManager.mm index 1c304a819f..4dc3d2bd9f 100644 --- a/xbmc/osx/IOSScreenManager.mm +++ b/xbmc/osx/IOSScreenManager.mm @@ -18,10 +18,10 @@ * http://www.gnu.org/copyleft/gpl.html * */ - + //hack around problem with xbmc's typedef int BOOL // and obj-c's typedef unsigned char BOOL -#define BOOL XBMC_BOOL +#define BOOL XBMC_BOOL #include <sys/resource.h> #include <signal.h> #include "utils/log.h" @@ -86,14 +86,37 @@ static CEvent screenChangeEvent; [_glView setScreen:newScreen withFrameBufferResize:TRUE];//will also resize the framebuffer [g_xbmcController activateScreen:newScreen];// will attach the screen to xbmc mainwindow - + if(toExternal)//changing the external screen might need some time ... { + //deactivate any overscan compensation when switching to external screens + if([newScreen respondsToSelector:@selector(overscanCompensation)]) + { + //since iOS5.0 tvout has an default overscan compensation and property + //we need to switch it off here so that the tv can handle any + //needed overscan compensation (else on tvs without "just scan" option + //we might end up with black borders. + //Beside that in Apples documentation to setOverscanCompensation + //the parameter enum is lacking the UIScreenOverscanCompensationNone value. + //Someone on stackoverflow figured out that value 3 is for turning it off + //(though there is no enum value for it). +#ifdef __IPHONE_5_0 + [newScreen setOverscanCompensation:(UIScreenOverscanCompensation)3]; +#else + [newScreen setOverscanCompensation:3]; +#endif + CLog::Log(LOGDEBUG, "[IOSScreenManager] Disabling overscancompensation."); + } + else + { + CLog::Log(LOGDEBUG, "[IOSScreenManager] Disabling overscancompensation not supported on this iOS version."); + } + [[IOSScreenManager sharedInstance] fadeFromBlack:timeSwitchingToExternalSecs]; } else { - [[IOSScreenManager sharedInstance] fadeFromBlack:timeSwitchingToInternalSecs]; + [[IOSScreenManager sharedInstance] fadeFromBlack:timeSwitchingToInternalSecs]; } int w = [[newScreen currentMode] size].width; @@ -109,27 +132,27 @@ static CEvent screenChangeEvent; - (void) changeScreenSelector:(NSDictionary *)dict { bool activateExternalTouchController = false; - int screenIdx = [[dict objectForKey:@"screenIdx"] intValue]; - UIScreenMode *mode = [dict objectForKey:@"screenMode"]; + int screenIdx = [[dict objectForKey:@"screenIdx"] intValue]; + UIScreenMode *mode = [dict objectForKey:@"screenMode"]; if([self willSwitchToInternal:screenIdx] && _externalTouchController != nil) { [_externalTouchController release]; _externalTouchController = nil; } - + if([self willSwitchToExternal:screenIdx]) { activateExternalTouchController = true; - } - + } + [UIView animateWithDuration:timeFadeSecs delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ [_glView setAlpha:0.0]; } completion:^(BOOL finished) { - [self setScreen:screenIdx withMode:mode]; + [self setScreen:screenIdx withMode:mode]; if(activateExternalTouchController) { _externalTouchController = [[IOSExternalTouchController alloc] init]; @@ -142,24 +165,24 @@ static CEvent screenChangeEvent; //screen has changed - get the new screen if(screenIdx >= [[UIScreen screens] count]) return false; - + //if we are about to switch to current screen //with current mode - don't do anything - if(screenIdx == _screenIdx && + if(screenIdx == _screenIdx && mode == (UIScreenMode *)[[[UIScreen screens] objectAtIndex:screenIdx] currentMode]) return true; //put the params into a dict - NSNumber *idx = [NSNumber numberWithInt:screenIdx]; - NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:mode, @"screenMode", - idx, @"screenIdx", nil]; - + NSNumber *idx = [NSNumber numberWithInt:screenIdx]; + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:mode, @"screenMode", + idx, @"screenIdx", nil]; + CLog::Log(LOGINFO, "Changing screen to %d with %f x %f",screenIdx,[mode size].width, [mode size].height); //ensure that the screen change is done in the mainthread if([NSThread currentThread] != [NSThread mainThread]) { - [self performSelectorOnMainThread:@selector(changeScreenSelector:) withObject:dict waitUntilDone:YES]; + [self performSelectorOnMainThread:@selector(changeScreenSelector:) withObject:dict waitUntilDone:YES]; screenChangeEvent.WaitMSec(30000); } else @@ -234,7 +257,7 @@ static CEvent screenChangeEvent; [super dealloc]; } //-------------------------------------------------------------- -+ (id) sharedInstance ++ (id) sharedInstance { static IOSScreenManager* sharedManager = nil; static dispatch_once_t onceToken; diff --git a/xbmc/osx/Info.plist b/xbmc/osx/Info.plist index 1fa8776caf..78dc688cb8 100644 --- a/xbmc/osx/Info.plist +++ b/xbmc/osx/Info.plist @@ -9,7 +9,7 @@ <key>CFBundleExecutable</key> <string>XBMC</string> <key>CFBundleGetInfoString</key> - <string>12.0.alpha4</string> + <string>12.0.alpha5</string> <key>CFBundleIconFile</key> <string>xbmc.icns</string> <key>CFBundleIdentifier</key> @@ -19,7 +19,7 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>12.0.alpha4</string> + <string>12.0.alpha5</string> <key>CFBundleVersion</key> <string>r####</string> <key>CFBundleSignature</key> diff --git a/xbmc/osx/ios/IOSKeyboard.h b/xbmc/osx/ios/IOSKeyboard.h new file mode 100644 index 0000000000..87c8f670d5 --- /dev/null +++ b/xbmc/osx/ios/IOSKeyboard.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ +#pragma once + +#include "guilib/GUIKeyboard.h" + +class CIOSKeyboard : public CGUIKeyboard +{ + public: + virtual bool ShowAndGetInput(char_callback_t pCallback, const std::string &initialString, std::string &typedString, const std::string &heading, bool bHiddenInput); + void fireCallback(const std::string &str); + void invalidateCallback(){m_pCharCallback = NULL;} + + private: + char_callback_t m_pCharCallback; +}; diff --git a/xbmc/osx/ios/IOSKeyboard.mm b/xbmc/osx/ios/IOSKeyboard.mm new file mode 100644 index 0000000000..4b699695c5 --- /dev/null +++ b/xbmc/osx/ios/IOSKeyboard.mm @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "XBMCController.h" +#include "IOSKeyboard.h" +#include "IOSKeyboardView.h" + + +bool CIOSKeyboard::ShowAndGetInput(char_callback_t pCallback, const std::string &initialString, std::string &typedString, const std::string &heading, bool bHiddenInput) +{ + bool confirmed = false; + CGRect keyboardFrame; + + // assume we are only drawn on the mainscreen ever! + UIScreen *pCurrentScreen = [UIScreen mainScreen]; + CGFloat scale = [g_xbmcController getScreenScale:pCurrentScreen]; + int frameHeight = 30; + keyboardFrame.size.width = pCurrentScreen.bounds.size.height - frameHeight; + keyboardFrame.size.height = frameHeight; + keyboardFrame.origin.x = frameHeight / 2; + keyboardFrame.origin.y = (pCurrentScreen.bounds.size.width/2) - frameHeight*scale + 10; + //create the keyboardview + KeyboardView *iosKeyboard = [[KeyboardView alloc] initWithFrame:keyboardFrame]; + + m_pCharCallback = pCallback; + + // init keyboard stuff + [iosKeyboard setText:[NSString stringWithUTF8String:initialString.c_str()]]; + [iosKeyboard SetHiddenInput:bHiddenInput]; + [iosKeyboard SetHeading:[NSString stringWithUTF8String:heading.c_str()]]; + [iosKeyboard RegisterKeyboard:this]; // for calling back + [iosKeyboard activate];//blocks and loops our application loop (like a modal dialog) + // user is done - get resulted text and confirmation + typedString = [[iosKeyboard GetText] UTF8String]; + confirmed = [iosKeyboard GetResult]; + [iosKeyboard release]; // bye bye native keyboard + return confirmed; +} + +//wrap our callback between objc and c++ +void CIOSKeyboard::fireCallback(const std::string &str) +{ + if(m_pCharCallback) + { + m_pCharCallback(this, str); + } +} diff --git a/xbmc/osx/ios/IOSKeyboardView.h b/xbmc/osx/ios/IOSKeyboardView.h new file mode 100644 index 0000000000..628f512c33 --- /dev/null +++ b/xbmc/osx/ios/IOSKeyboardView.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#import <UIKit/UIKit.h> +#include "IOSKeyboard.h" + +@interface KeyboardView : UIView <UIKeyInput> +{ + NSMutableString *_heading; + NSMutableString *_text; + bool _result; + bool _hiddenInput; + CIOSKeyboard *_iosKeyboard; +} + +@property (nonatomic, retain, getter = GetText) NSMutableString *_text; +@property (copy, setter = SetHeading:) NSMutableString *_heading; +@property (getter = GetResult) bool _result; +@property (setter = SetHiddenInput:) bool _hiddenInput; +@property (assign, setter = RegisterKeyboard:) CIOSKeyboard *_iosKeyboard; + +- (void) setText:(NSMutableString *)text; +- (void) activate; +- (void) deactivate; +@end diff --git a/xbmc/osx/ios/IOSKeyboardView.mm b/xbmc/osx/ios/IOSKeyboardView.mm new file mode 100644 index 0000000000..832367ed93 --- /dev/null +++ b/xbmc/osx/ios/IOSKeyboardView.mm @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ +#define BOOL XBMC_BOOL +#include "guilib/GUIWindowManager.h" +#include "guilib/GUIKeyboardFactory.h" +#include "threads/Event.h" +#include "Application.h" +#undef BOOL + +#import "IOSKeyboardView.h" +#import "IOSScreenManager.h" +#import "XBMCController.h" +#include "IOSKeyboard.h" + +static CEvent keyboardFinishedEvent; + +@implementation KeyboardView +@synthesize _text; +@synthesize _heading; +@synthesize _result; +@synthesize _hiddenInput; +@synthesize _iosKeyboard; + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) + { + _iosKeyboard = nil; + _text = [[NSMutableString alloc] initWithString:@""]; + _heading = [[NSMutableString alloc] initWithString:@""]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardDidHide:) + name:UIKeyboardDidHideNotification + object:nil]; + [self setBackgroundColor:[UIColor whiteColor]]; + } + return self; +} + +- (void)drawRect:(CGRect)rect +{ + CGRect rectForText = CGRectInset(rect, 10.0, 5.0); + // init with heading + NSMutableString *drawText = [[NSMutableString alloc] initWithString:self._heading];; + [drawText appendString:@": "]; + + if(_hiddenInput)//hidden input requested + { + NSMutableString *hiddenText = [[NSMutableString alloc] initWithString:@""]; + // hide chars with * + for(unsigned int i = 0; i < [self._text length]; i++) + { + [hiddenText appendString:@"*"]; + } + //append to heading + [drawText appendString:hiddenText]; + [hiddenText release]; + } + else + { + //append to heading + [drawText appendString:self._text]; + } + //finally draw the text + [drawText drawInRect:rectForText withFont:[UIFont systemFontOfSize:14.0]]; + [drawText release]; +} + +- (void)keyboardDidHide:(id)sender +{ + // user left the keyboard by hiding it + // we treat this as a cancel + _result = false; + [self deactivate]; +} + +- (void) doActivate:(NSDictionary *)dict +{ + [g_xbmcController activateKeyboard:self]; + [self becomeFirstResponder]; +} + +- (void)activate +{ + if([NSThread currentThread] != [NSThread mainThread]) + { + [self performSelectorOnMainThread:@selector(doActivate:) withObject:nil waitUntilDone:YES]; + } + else + { + // this would be fatal! We never should be called from the ios mainthread + return; + } + + keyboardFinishedEvent.Reset(); + + // emulate a modale dialog here + // we are waiting on the user finishing the keyboard + // and have to process our app while doing that + // basicall what our GUIDialog does if called modal + while(!keyboardFinishedEvent.WaitMSec(500) && !g_application.m_bStop) + { + g_windowManager.ProcessRenderLoop(); + } +} + +- (void) doDeactivate:(NSDictionary *)dict +{ + // allways calld in the mainloop context + // detach the keyboard view from our main controller + [g_xbmcController deactivateKeyboard:self]; + + // invalidate our callback object + if(_iosKeyboard) + { + _iosKeyboard->invalidateCallback(); + _iosKeyboard = nil; + } + // give back the control to whoever + [self resignFirstResponder]; +} + +- (void) deactivate +{ + if([NSThread currentThread] != [NSThread mainThread]) + { + [self performSelectorOnMainThread:@selector(doDeactivate:) withObject:nil waitUntilDone:YES]; + } + else + { + [self doDeactivate:nil]; + } + + keyboardFinishedEvent.Set(); +} + +// yes we can! +- (BOOL)canBecomeFirstResponder +{ + return YES; +} + +- (BOOL)hasText +{ + return YES; +} + +- (void) setText:(NSMutableString *)text +{ + [_text setString:@""]; + if([NSThread currentThread] != [NSThread mainThread]) + { + [self performSelectorOnMainThread:@selector(insertText:) withObject:text waitUntilDone:YES]; + } + else + { + [self insertText:text]; + } +} + +- (void)insertText:(NSString *)newText +{ + for(int i=0; i < [newText length];i++) + { + // we leave the keyboard ui if enter was hit + // and treat it as an user confirmation + if([newText characterAtIndex:i] == '\n') + { + _result = true; + [self deactivate]; + return; + } + } + + // new typed text gets appended to the + // whole string + [self._text appendString:newText]; + [self setNeedsDisplay]; // update the UI + + // fire the string callback to our + // handle realtime filtering and so on + if(_iosKeyboard) + { + _iosKeyboard->fireCallback([_text UTF8String]); + } +} + +// handle backspace +- (void)deleteBackward +{ + if([self._text length] == 0) + return; + + NSRange rangeToDelete = NSMakeRange(self._text.length-1, 1); + [self._text deleteCharactersInRange:rangeToDelete]; + [self setNeedsDisplay]; + + // fire the string callback to our + // handle realtime filtering and so on + if(_iosKeyboard) + { + _iosKeyboard->fireCallback([_text UTF8String]); + } +} + +- (void) dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver: self]; + [_text release]; + [_heading release]; + [super dealloc]; +} +@end diff --git a/xbmc/osx/ios/XBMCController.h b/xbmc/osx/ios/XBMCController.h index be647afd13..c876593702 100644 --- a/xbmc/osx/ios/XBMCController.h +++ b/xbmc/osx/ios/XBMCController.h @@ -71,8 +71,11 @@ - (void) setFramebuffer; - (bool) presentFramebuffer; - (CGSize) getScreenSize; +- (CGFloat) getScreenScale:(UIScreen *)screen; - (UIInterfaceOrientation) getOrientation; - (void) createGestureRecognizers; +- (void) activateKeyboard:(UIView *)view; +- (void) deactivateKeyboard:(UIView *)view; - (void) disableSystemSleep; - (void) enableSystemSleep; diff --git a/xbmc/osx/ios/XBMCController.mm b/xbmc/osx/ios/XBMCController.mm index fa22f8af18..0b24635919 100644 --- a/xbmc/osx/ios/XBMCController.mm +++ b/xbmc/osx/ios/XBMCController.mm @@ -29,7 +29,7 @@ #include "settings/AdvancedSettings.h" #include "settings/Settings.h" #include "FileItem.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "input/MouseStat.h" #include "windowing/WindowingFactory.h" #include "video/VideoReferenceClock.h" @@ -197,6 +197,16 @@ extern NSString* kBRScreenSaverDismissed; currentPinchScale = lastPinchScale; } //-------------------------------------------------------------- +- (void) activateKeyboard:(UIView *)view +{ + [self.view addSubview:view]; +} +//-------------------------------------------------------------- +- (void) deactivateKeyboard:(UIView *)view +{ + [view removeFromSuperview]; +} +//-------------------------------------------------------------- -(void)handlePinch:(UIPinchGestureRecognizer*)sender { if( [m_glView isXBMCAlive] )//NO GESTURES BEFORE WE ARE UP AND RUNNING @@ -212,7 +222,7 @@ extern NSString* kBRScreenSaverDismissed; case UIGestureRecognizerStateBegan: break; case UIGestureRecognizerStateChanged: - g_application.getApplicationMessenger().SendAction(CAction(ACTION_GESTURE_ZOOM, 0, (float)point.x, (float)point.y, + CApplicationMessenger::Get().SendAction(CAction(ACTION_GESTURE_ZOOM, 0, (float)point.x, (float)point.y, currentPinchScale, 0), WINDOW_INVALID,false); break; case UIGestureRecognizerStateEnded: @@ -259,12 +269,12 @@ extern NSString* kBRScreenSaverDismissed; { if( !touchBeginSignaled ) { - g_application.getApplicationMessenger().SendAction(CAction(ACTION_GESTURE_BEGIN, 0, (float)point.x, (float)point.y, + CApplicationMessenger::Get().SendAction(CAction(ACTION_GESTURE_BEGIN, 0, (float)point.x, (float)point.y, 0, 0), WINDOW_INVALID,false); touchBeginSignaled = true; } - g_application.getApplicationMessenger().SendAction(CAction(ACTION_GESTURE_PAN, 0, (float)point.x, (float)point.y, + CApplicationMessenger::Get().SendAction(CAction(ACTION_GESTURE_PAN, 0, (float)point.x, (float)point.y, xMovement, yMovement), WINDOW_INVALID,false); lastGesturePoint = point; } @@ -274,7 +284,7 @@ extern NSString* kBRScreenSaverDismissed; { CGPoint velocity = [sender velocityInView:m_glView]; //signal end of pan - this will start inertial scrolling with deacceleration in CApplication - g_application.getApplicationMessenger().SendAction(CAction(ACTION_GESTURE_END, 0, (float)velocity.x, (float)velocity.y, (int)lastGesturePoint.x, (int)lastGesturePoint.y),WINDOW_INVALID,false); + CApplicationMessenger::Get().SendAction(CAction(ACTION_GESTURE_END, 0, (float)velocity.x, (float)velocity.y, (int)lastGesturePoint.x, (int)lastGesturePoint.y),WINDOW_INVALID,false); touchBeginSignaled = false; } } @@ -535,6 +545,12 @@ extern NSString* kBRScreenSaverDismissed; return screensize; } //-------------------------------------------------------------- +- (CGFloat) getScreenScale:(UIScreen *)screen; +{ + return [m_glView getScreenScale:screen]; +} +//-------------------------------------------------------------- +//-------------------------------------------------------------- - (BOOL) recreateOnReselect { //NSLog(@"%s", __PRETTY_FUNCTION__); diff --git a/xbmc/peripherals/Peripherals.cpp b/xbmc/peripherals/Peripherals.cpp index 46ddb0368e..ed08632ef5 100644 --- a/xbmc/peripherals/Peripherals.cpp +++ b/xbmc/peripherals/Peripherals.cpp @@ -40,6 +40,7 @@ #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" #include "dialogs/GUIDialogKaiToast.h" +#include "GUIUserMessages.h" #include "utils/StringUtils.h" #include "Util.h" #include "guilib/Key.h" @@ -311,6 +312,10 @@ void CPeripherals::OnDeviceAdded(const CPeripheralBus &bus, const CPeripheral &p if (dialog && dialog->IsActive()) dialog->Update(); + // refresh settings (peripherals manager could be enabled now) + CGUIMessage msg(GUI_MSG_UPDATE, WINDOW_SETTINGS_SYSTEM, 0); + g_windowManager.SendThreadMessage(msg, WINDOW_SETTINGS_SYSTEM); + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(35005), peripheral.DeviceName()); } @@ -320,6 +325,10 @@ void CPeripherals::OnDeviceDeleted(const CPeripheralBus &bus, const CPeripheral if (dialog && dialog->IsActive()) dialog->Update(); + // refresh settings (peripherals manager could be disabled now) + CGUIMessage msg(GUI_MSG_UPDATE, WINDOW_SETTINGS_SYSTEM, 0); + g_windowManager.SendThreadMessage(msg, WINDOW_SETTINGS_SYSTEM); + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(35006), peripheral.DeviceName()); } diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp index 3dff72d6be..7824c369c9 100644 --- a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp +++ b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp @@ -85,7 +85,6 @@ CPeripheralBusUSB::CPeripheralBusUSB(CPeripherals *manager) : m_udev = NULL; m_udevMon = NULL; - m_udevFd = -1; if (!(m_udev = udev_new())) { @@ -96,9 +95,8 @@ CPeripheralBusUSB::CPeripheralBusUSB(CPeripherals *manager) : /* set up a devices monitor that listen for any device change */ m_udevMon = udev_monitor_new_from_netlink(m_udev, "udev"); udev_monitor_enable_receiving(m_udevMon); - m_udevFd = udev_monitor_get_fd(m_udevMon); - CLog::Log(LOGDEBUG, "%s - initialised udev monitor: %d", __FUNCTION__, m_udevFd); + CLog::Log(LOGDEBUG, "%s - initialised udev monitor", __FUNCTION__); } CPeripheralBusUSB::~CPeripheralBusUSB(void) @@ -218,18 +216,19 @@ void CPeripheralBusUSB::Process(void) void CPeripheralBusUSB::Clear(void) { StopThread(false); - if (m_udevFd != -1) - close(m_udevFd); - - udev_unref(m_udev); CPeripheralBus::Clear(); } bool CPeripheralBusUSB::WaitForUpdate() { - if (!m_udevFd) + int m_udevFd = udev_monitor_get_fd(m_udevMon); + + if (m_udevFd < 0) + { + CLog::Log(LOGERROR, "%s - get udev monitor", __FUNCTION__); return false; + } /* poll for udev changes */ struct pollfd pollFd; diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h index 06c60683e3..e9876cd25d 100644 --- a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h +++ b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h @@ -51,6 +51,5 @@ namespace PERIPHERALS struct udev * m_udev; struct udev_monitor *m_udevMon; - int m_udevFd; }; } diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp index 6c5e9e688f..0b7cf83d57 100644 --- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp @@ -24,12 +24,15 @@ #include "PeripheralCecAdapter.h" #include "input/XBIRRemote.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "DynamicDll.h" #include "threads/SingleLock.h" #include "dialogs/GUIDialogKaiToast.h" +#include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" #include "peripherals/Peripherals.h" #include "peripherals/bus/PeripheralBus.h" +#include "pictures/GUIWindowSlideShow.h" #include "settings/GUISettings.h" #include "settings/Settings.h" #include "utils/log.h" @@ -185,6 +188,7 @@ bool CPeripheralCecAdapter::InitialiseFeature(const PeripheralFeature feature) m_callbacks.CBCecCommand = &CecCommand; m_callbacks.CBCecConfigurationChanged = &CecConfiguration; m_callbacks.CBCecAlert = &CecAlert; + m_callbacks.CBCecSourceActivated = &CecSourceActivated; m_configuration.callbackParam = this; m_configuration.callbacks = &m_callbacks; @@ -609,7 +613,7 @@ void CPeripheralCecAdapter::SetMenuLanguage(const char *strLanguage) if (!strGuiLanguage.IsEmpty()) { - g_application.getApplicationMessenger().SetGUILanguage(strGuiLanguage); + CApplicationMessenger::Get().SetGUILanguage(strGuiLanguage); CLog::Log(LOGDEBUG, "%s - language set to '%s'", __FUNCTION__, strGuiLanguage.c_str()); } else @@ -637,9 +641,9 @@ int CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command &command) { adapter->m_bStarted = false; if (adapter->m_configuration.bPowerOffOnStandby == 1) - g_application.getApplicationMessenger().Suspend(); + CApplicationMessenger::Get().Suspend(); else if (adapter->m_configuration.bShutdownOnStandby == 1) - g_application.getApplicationMessenger().Shutdown(); + CApplicationMessenger::Get().Shutdown(); } break; case CEC_OPCODE_SET_MENU_LANGUAGE: @@ -1031,6 +1035,14 @@ void CPeripheralCecAdapter::PushCecKeypress(const cec_keypress &key) xbmcKey.iButton = XINPUT_IR_REMOTE_TITLE; // context menu PushCecKeypress(xbmcKey); break; + case CEC_USER_CONTROL_CODE_DATA: + xbmcKey.iButton = XINPUT_IR_REMOTE_TELETEXT; + PushCecKeypress(xbmcKey); + break; + case CEC_USER_CONTROL_CODE_SUB_PICTURE: + xbmcKey.iButton = XINPUT_IR_REMOTE_SUBTITLE; + PushCecKeypress(xbmcKey); + break; case CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION: case CEC_USER_CONTROL_CODE_EJECT: case CEC_USER_CONTROL_CODE_INPUT_SELECT: @@ -1039,7 +1051,6 @@ void CPeripheralCecAdapter::PushCecKeypress(const cec_keypress &key) case CEC_USER_CONTROL_CODE_STOP_RECORD: case CEC_USER_CONTROL_CODE_PAUSE_RECORD: case CEC_USER_CONTROL_CODE_ANGLE: - case CEC_USER_CONTROL_CODE_SUB_PICTURE: case CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND: case CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING: case CEC_USER_CONTROL_CODE_PLAY_FUNCTION: @@ -1056,7 +1067,6 @@ void CPeripheralCecAdapter::PushCecKeypress(const cec_keypress &key) case CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION: case CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION: case CEC_USER_CONTROL_CODE_F5: - case CEC_USER_CONTROL_CODE_DATA: case CEC_USER_CONTROL_CODE_UNKNOWN: default: break; @@ -1125,6 +1135,35 @@ void CPeripheralCecAdapter::OnSettingChanged(const CStdString &strChangedSetting } } +void CPeripheralCecAdapter::CecSourceActivated(void *cbParam, const CEC::cec_logical_address address, const uint8_t activated) +{ + CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; + if (!adapter) + return; + + // wake up the screensaver, so the user doesn't switch to a black screen + if (activated == 1) + g_application.WakeUpScreenSaverAndDPMS(); + + if (adapter->GetSettingBool("pause_playback_on_deactivate")) + { + bool bShowingSlideshow = (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW); + CGUIWindowSlideShow *pSlideShow = bShowingSlideshow ? (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW) : NULL; + + if (pSlideShow) + { + // pause/resume slideshow + pSlideShow->OnAction(CAction(ACTION_PAUSE)); + } + else if ((g_application.IsPlaying() && activated == 0) || + (g_application.IsPaused() && activated == 1)) + { + // pause/resume player + CApplicationMessenger::Get().MediaPause(); + } + } +} + int CPeripheralCecAdapter::CecLogMessage(void *cbParam, const cec_log_message &message) { CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h index 152e50b3d4..b8ec1f2b7b 100644 --- a/xbmc/peripherals/devices/PeripheralCecAdapter.h +++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h @@ -123,6 +123,7 @@ namespace PERIPHERALS static int CecCommand(void *cbParam, const CEC::cec_command &command); static int CecConfiguration(void *cbParam, const CEC::libcec_configuration &config); static int CecAlert(void *cbParam, const CEC::libcec_alert alert, const CEC::libcec_parameter &data); + static void CecSourceActivated(void *param, const CEC::cec_logical_address address, const uint8_t activated); bool IsRunning(void) const; void ReopenConnection(void); diff --git a/xbmc/pictures/GUIDialogPictureInfo.cpp b/xbmc/pictures/GUIDialogPictureInfo.cpp index 27c32dd769..bc53dc9b5c 100644 --- a/xbmc/pictures/GUIDialogPictureInfo.cpp +++ b/xbmc/pictures/GUIDialogPictureInfo.cpp @@ -24,6 +24,7 @@ #include "guilib/GUIWindowManager.h" #include "FileItem.h" #include "guilib/LocalizeStrings.h" +#include "PictureInfoTag.h" #define CONTROL_PICTURE_INFO 5 @@ -88,6 +89,11 @@ void CGUIDialogPictureInfo::UpdatePictureInfo() m_pictureInfo->Clear(); for (int info = SLIDE_INFO_START; info <= SLIDE_INFO_END; ++info) { + // we don't need want to add both SLIDE_EXIF_DATE_TIME and SLIDE_EXIF_DATE + // so we skip one without time + if (info == SLIDE_EXIF_DATE) + continue; + CStdString picInfo = g_infoManager.GetLabel(info); if (!picInfo.IsEmpty()) { diff --git a/xbmc/pictures/GUIViewStatePictures.cpp b/xbmc/pictures/GUIViewStatePictures.cpp index 5ddda6da23..ab1f7d2b75 100644 --- a/xbmc/pictures/GUIViewStatePictures.cpp +++ b/xbmc/pictures/GUIViewStatePictures.cpp @@ -27,7 +27,6 @@ #include "settings/Settings.h" #include "filesystem/Directory.h" #include "filesystem/PluginDirectory.h" -#include "Util.h" #include "guilib/LocalizeStrings.h" #include "guilib/Key.h" diff --git a/xbmc/pictures/GUIWindowSlideShow.cpp b/xbmc/pictures/GUIWindowSlideShow.cpp index dc6a2e7fbf..7f2e2ddd26 100644 --- a/xbmc/pictures/GUIWindowSlideShow.cpp +++ b/xbmc/pictures/GUIWindowSlideShow.cpp @@ -23,6 +23,7 @@ #include "system.h" #include "GUIWindowSlideShow.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "utils/URIUtils.h" #include "URL.h" #include "guilib/TextureManager.h" @@ -427,7 +428,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re { CLog::Log(LOGDEBUG, "Playing slide %s as video", m_slides->Get(m_iCurrentSlide)->GetPath().c_str()); m_bPlayingVideo = true; - g_application.getApplicationMessenger().PlayFile(*m_slides->Get(m_iCurrentSlide)); + CApplicationMessenger::Get().PlayFile(*m_slides->Get(m_iCurrentSlide)); m_iCurrentSlide = m_iNextSlide; m_iNextSlide = GetNextSlide(); } diff --git a/xbmc/pictures/Picture.cpp b/xbmc/pictures/Picture.cpp index 3812b7fb66..0980efb79e 100644 --- a/xbmc/pictures/Picture.cpp +++ b/xbmc/pictures/Picture.cpp @@ -24,7 +24,6 @@ #include "settings/GUISettings.h" #include "FileItem.h" #include "filesystem/File.h" -#include "filesystem/CurlFile.h" #include "DllImageLib.h" #include "utils/log.h" #include "utils/URIUtils.h" diff --git a/xbmc/pictures/PictureInfoTag.cpp b/xbmc/pictures/PictureInfoTag.cpp index 62b04c643c..732e2bb78e 100644 --- a/xbmc/pictures/PictureInfoTag.cpp +++ b/xbmc/pictures/PictureInfoTag.cpp @@ -306,6 +306,7 @@ const CStdString CPictureInfoTag::GetInfo(int info) const value = m_exifInfo.Comments; break; case SLIDE_EXIF_DATE_TIME: + case SLIDE_EXIF_DATE: if (m_exifInfo.DateTime && strlen(m_exifInfo.DateTime) >= 19 && m_exifInfo.DateTime[0] != ' ') { CStdString dateTime = m_exifInfo.DateTime; @@ -316,7 +317,10 @@ const CStdString CPictureInfoTag::GetInfo(int info) const int min = atoi(dateTime.Mid(14,2).c_str()); int sec = atoi(dateTime.Mid(17,2).c_str()); CDateTime date(year, month, day, hour, min, sec); - value = date.GetAsLocalizedDateTime(); + if(SLIDE_EXIF_DATE_TIME == info) + value = date.GetAsLocalizedDateTime(); + else + value = date.GetAsLocalizedDate(); } break; case SLIDE_EXIF_DESCRIPTION: @@ -512,6 +516,7 @@ int CPictureInfoTag::TranslateString(const CStdString &info) else if (info.Equals("colour")) return SLIDE_COLOUR; else if (info.Equals("process")) return SLIDE_PROCESS; else if (info.Equals("exiftime")) return SLIDE_EXIF_DATE_TIME; + else if (info.Equals("exifdate")) return SLIDE_EXIF_DATE; else if (info.Equals("exifdescription")) return SLIDE_EXIF_DESCRIPTION; else if (info.Equals("cameramake")) return SLIDE_EXIF_CAMERA_MAKE; else if (info.Equals("cameramodel")) return SLIDE_EXIF_CAMERA_MODEL; diff --git a/xbmc/pictures/PictureInfoTag.h b/xbmc/pictures/PictureInfoTag.h index a9d03a366d..edd7d85f3a 100644 --- a/xbmc/pictures/PictureInfoTag.h +++ b/xbmc/pictures/PictureInfoTag.h @@ -35,6 +35,8 @@ #define SLIDE_COLOUR 907 #define SLIDE_PROCESS 908 +#define SLIDE_EXIF_DATE 919 /* Implementation only to just get + localized date */ #define SLIDE_EXIF_DATE_TIME 920 #define SLIDE_EXIF_DESCRIPTION 921 #define SLIDE_EXIF_CAMERA_MAKE 922 diff --git a/xbmc/pictures/PictureThumbLoader.cpp b/xbmc/pictures/PictureThumbLoader.cpp index cafcfccd14..ee579567ac 100644 --- a/xbmc/pictures/PictureThumbLoader.cpp +++ b/xbmc/pictures/PictureThumbLoader.cpp @@ -21,7 +21,6 @@ #include "PictureThumbLoader.h" #include "Picture.h" -#include "URL.h" #include "filesystem/File.h" #include "FileItem.h" #include "TextureCache.h" diff --git a/xbmc/playlists/PlayListFactory.cpp b/xbmc/playlists/PlayListFactory.cpp index a60bc2b223..2315aafd39 100644 --- a/xbmc/playlists/PlayListFactory.cpp +++ b/xbmc/playlists/PlayListFactory.cpp @@ -63,7 +63,8 @@ CPlayList* CPlayListFactory::Create(const CFileItem& item) || strMimeType == "text/html") return new CPlayListPLS(); - if (strMimeType == "audio/x-mpegurl") + // online m3u8 files are for hls streaming -- do not treat as playlist + if (strMimeType == "audio/x-mpegurl" && !item.IsType(".m3u8")) return new CPlayListM3U(); if (strMimeType == "application/vnd.ms-wpl") @@ -118,6 +119,10 @@ bool CPlayListFactory::IsPlaylist(const CFileItem& item) return true; */ + // online m3u8 files are hls:// -- do not treat as playlist + if (item.IsInternetStream() && item.IsType(".m3u8")) + return false; + if(strMimeType == "audio/x-pn-realaudio" || strMimeType == "playlist" || strMimeType == "audio/x-mpegurl") diff --git a/xbmc/playlists/PlayListM3U.cpp b/xbmc/playlists/PlayListM3U.cpp index b8f60e32f8..5cab97ffa0 100644 --- a/xbmc/playlists/PlayListM3U.cpp +++ b/xbmc/playlists/PlayListM3U.cpp @@ -21,6 +21,7 @@ #include "PlayListM3U.h" #include "filesystem/File.h" +#include "URL.h" #include "Util.h" #include "utils/StringUtils.h" #include "utils/CharsetConverter.h" @@ -37,6 +38,8 @@ using namespace XFILE; #define M3U_INFO_MARKER "#EXTINF" #define M3U_ARTIST_MARKER "#EXTART" #define M3U_ALBUM_MARKER "#EXTALB" +#define M3U_STREAM_MARKER "#EXT-X-STREAM-INF" +#define M3U_BANDWIDTH_MARKER "BANDWIDTH" // example m3u file: // #EXTM3U @@ -48,6 +51,14 @@ using namespace XFILE; // E:\Program Files\Winamp3\demo.mp3 +// example m3u8 containing streams of different bitrates +// #EXTM3U +// #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=1600000 +// playlist_1600.m3u8 +// #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=3000000 +// playlist_3000.m3u8 +// #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=800000 +// playlist_800.m3u8 CPlayListM3U::CPlayListM3U(void) @@ -170,3 +181,109 @@ void CPlayListM3U::Save(const CStdString& strFileName) const } file.Close(); } + +CStdString CPlayListM3U::GetBestBandwidthStream(const CStdString &strFileName, size_t bandwidth) +{ + // we may be passed a playlist that does not contain playlists of different + // bitrates (eg: this playlist is really the HLS video). So, default the + // return to the filename so it can be played + char szLine[4096]; + CStdString strLine; + CStdString strPlaylist = strFileName; + size_t maxBandwidth = 0; + + // if we cannot get the last / we wont be able to determine the sub-playlists + size_t baseEnd = strPlaylist.rfind('/'); + if (baseEnd == std::string::npos) + return strPlaylist; + + // store the base path (the path without the filename) + CStdString basePath = strPlaylist.substr(0, baseEnd + 1); + + // open the file, and if it fails, return + CFile file; + if (!file.Open(strFileName) ) + { + file.Close(); + return strPlaylist; + } + + // convert bandwidth specified in kbps to bps used by the m3u8 + bandwidth *= 1000; + + while (file.ReadString(szLine, 1024)) + { + // read and trim a line + strLine = szLine; + strLine.TrimRight(" \t\r\n"); + strLine.TrimLeft(" \t"); + + // skip the first line + if (strLine == M3U_START_MARKER) + continue; + else if (strLine.Left(strlen(M3U_STREAM_MARKER)) == M3U_STREAM_MARKER) + { + // parse the line so we can pull out the bandwidth + std::map< CStdString, CStdString > params = ParseStreamLine(strLine); + std::map< CStdString, CStdString >::iterator it = params.find(M3U_BANDWIDTH_MARKER); + + if (it != params.end()) + { + size_t streamBandwidth = atoi(it->second.c_str()); + if ((maxBandwidth < streamBandwidth) && (streamBandwidth <= bandwidth)) + { + // read the next line + file.ReadString(szLine, 1024); + strLine = szLine; + strLine.TrimRight(" \t\r\n"); + strLine.TrimLeft(" \t"); + + // this line was empty + if (strLine.empty()) + continue; + + // store the max bandwidth + maxBandwidth = streamBandwidth; + + // if the path is absolute just use it + if (CURL::IsFullPath(strLine)) + strPlaylist = strLine; + else + strPlaylist = basePath + strLine; + } + } + } + } + + CLog::Log(LOGINFO, "Auto-selecting %s based on configured bandwidth.", strPlaylist.c_str()); + + return strPlaylist; +} + +std::map< CStdString, CStdString > CPlayListM3U::ParseStreamLine(const CStdString &streamLine) +{ + std::map< CStdString, CStdString > params; + + // ensure the line has something beyond the stream marker and ':' + if (strlen(streamLine) < strlen(M3U_STREAM_MARKER) + 2) + return params; + + // get the actual params following the : + CStdString strParams(streamLine.substr(strlen(M3U_STREAM_MARKER) + 1)); + + // separate the parameters + CStdStringArray vecParams = StringUtils::SplitString(strParams, ","); + for (size_t i = 0; i < vecParams.size(); i++) + { + // split the param, ensure there was an = + CStdStringArray vecTuple = StringUtils::SplitString(vecParams[i].Trim(), "="); + if (vecTuple.size() < 2) + continue; + + // remove white space from name and value and store it in the dictionary + params[vecTuple[0].Trim()] = vecTuple[1].Trim(); + } + + return params; +} + diff --git a/xbmc/playlists/PlayListM3U.h b/xbmc/playlists/PlayListM3U.h index 434e608eec..beeb947d39 100644 --- a/xbmc/playlists/PlayListM3U.h +++ b/xbmc/playlists/PlayListM3U.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2005-2008 Team XBMC + * Copyright (C) 2005-2012 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -31,5 +31,11 @@ public: virtual ~CPlayListM3U(void); virtual bool Load(const CStdString& strFileName); virtual void Save(const CStdString& strFileName) const; + + static CStdString GetBestBandwidthStream(const CStdString &strFileName, size_t bandwidth); + +protected: + + static std::map< CStdString, CStdString > ParseStreamLine(const CStdString &streamLine); }; } diff --git a/xbmc/playlists/SmartPlayList.cpp b/xbmc/playlists/SmartPlayList.cpp index 815ecadfa2..50dde8f37d 100644 --- a/xbmc/playlists/SmartPlayList.cpp +++ b/xbmc/playlists/SmartPlayList.cpp @@ -26,7 +26,10 @@ #include "filesystem/File.h" #include "utils/CharsetConverter.h" #include "utils/DatabaseUtils.h" +#include "utils/JSONVariantParser.h" +#include "utils/JSONVariantWriter.h" #include "utils/URIUtils.h" +#include "utils/Variant.h" #include "utils/XMLUtils.h" #include "video/VideoDatabase.h" #include "Util.h" @@ -99,7 +102,13 @@ static const translateField fields[] = { { "subtitlelanguage", FieldSubtitleLanguage, SortBySubtitleLanguage, CSmartPlaylistRule::TEXTIN_FIELD, 21448 }, { "random", FieldRandom, SortByRandom, CSmartPlaylistRule::TEXT_FIELD, 590 }, { "playlist", FieldPlaylist, SortByPlaylistOrder, CSmartPlaylistRule::PLAYLIST_FIELD, 559 }, - { "tag", FieldTag, SortByNone, CSmartPlaylistRule::BROWSEABLE_FIELD, 20459 } + { "tag", FieldTag, SortByNone, CSmartPlaylistRule::BROWSEABLE_FIELD, 20459 }, + { "instruments", FieldInstruments, SortByNone, CSmartPlaylistRule::TEXT_FIELD, 21892 }, + { "biography", FieldBiography, SortByNone, CSmartPlaylistRule::TEXT_FIELD, 21887 }, + { "born", FieldBorn, SortByNone, CSmartPlaylistRule::TEXT_FIELD, 21893 }, + { "bandformed", FieldBandFormed, SortByNone, CSmartPlaylistRule::TEXT_FIELD, 21894 }, + { "disbanded", FieldDisbanded, SortByNone, CSmartPlaylistRule::TEXT_FIELD, 21896 }, + { "died", FieldDied, SortByNone, CSmartPlaylistRule::TEXT_FIELD, 21897 } }; #define NUM_FIELDS sizeof(fields) / sizeof(translateField) @@ -147,8 +156,17 @@ bool CSmartPlaylistRule::Load(TiXmlElement *element, const CStdString &encoding // <value> tags containing a string const char *field = element->Attribute("field"); const char *oper = element->Attribute("operator"); + if (field == NULL || oper == NULL) + return false; + + m_field = TranslateField(field); + m_operator = TranslateOperator(oper); + + if (m_operator == OPERATOR_TRUE || m_operator == OPERATOR_FALSE) + return true; + TiXmlNode *parameter = element->FirstChild(); - if (field == NULL || oper == NULL || parameter == NULL) + if (parameter == NULL) return false; if (parameter->Type() == TiXmlNode::TINYXML_TEXT) @@ -186,14 +204,45 @@ bool CSmartPlaylistRule::Load(TiXmlElement *element, const CStdString &encoding else return false; - m_field = TranslateField(field); - m_operator = TranslateOperator(oper); + return true; +} + +bool CSmartPlaylistRule::Load(const CVariant &obj) +{ + if (!obj.isObject() || + !obj.isMember("field") || !obj["field"].isString() || + !obj.isMember("operator") || !obj["operator"].isString()) + return false; + + m_field = TranslateField(obj["field"].asString().c_str()); + m_operator = TranslateOperator(obj["operator"].asString().c_str()); + + if (m_operator == OPERATOR_TRUE || m_operator == OPERATOR_FALSE) + return true; + + if (!obj.isMember("value") || (!obj["value"].isString() && !obj["value"].isArray())) + return false; + + const CVariant &value = obj["value"]; + if (value.isString() && !value.asString().empty()) + m_parameter.push_back(value.asString()); + else if (value.isArray()) + { + for (CVariant::const_iterator_array val = value.begin_array(); val != value.end_array(); val++) + { + if (val->isString() && !val->asString().empty()) + m_parameter.push_back(val->asString()); + } + } + else + return false; + return true; } bool CSmartPlaylistRule::Save(TiXmlNode *parent) const { - if (parent == NULL || m_parameter.empty()) + if (parent == NULL || (m_parameter.empty() && m_operator != OPERATOR_TRUE && m_operator != OPERATOR_FALSE)) return false; TiXmlElement rule("rule"); @@ -213,6 +262,23 @@ bool CSmartPlaylistRule::Save(TiXmlNode *parent) const return true; } +bool CSmartPlaylistRule::Save(CVariant &obj) const +{ + if (obj.isNull() || (m_parameter.empty() && m_operator != OPERATOR_TRUE && m_operator != OPERATOR_FALSE)) + return false; + + CVariant rule(CVariant::VariantTypeObject); + rule["field"] = TranslateField(m_field); + rule["operator"] = TranslateOperator(m_operator); + + rule["value"] = CVariant(CVariant::VariantTypeArray); + for (vector<CStdString>::const_iterator it = m_parameter.begin(); it != m_parameter.end(); it++) + rule["value"].push_back(*it); + + obj.push_back(rule); + return true; +} + Field CSmartPlaylistRule::TranslateField(const char *field) { for (unsigned int i = 0; i < NUM_FIELDS; i++) @@ -313,6 +379,19 @@ vector<Field> CSmartPlaylistRule::GetFields(const CStdString &type) fields.push_back(FieldMusicLabel); fields.push_back(FieldRating); } + else if (type == "artists") + { + fields.push_back(FieldArtist); + fields.push_back(FieldGenre); + fields.push_back(FieldMoods); + fields.push_back(FieldStyles); + fields.push_back(FieldInstruments); + fields.push_back(FieldBiography); + fields.push_back(FieldBorn); + fields.push_back(FieldBandFormed); + fields.push_back(FieldDisbanded); + fields.push_back(FieldDied); + } else if (type == "tvshows") { fields.push_back(FieldTitle); @@ -452,6 +531,10 @@ std::vector<SortBy> CSmartPlaylistRule::GetOrders(const CStdString &type) //orders.push_back(SortByMusicLabel); orders.push_back(SortByRating); } + else if (type == "artists") + { + orders.push_back(SortByArtist); + } else if (type == "tvshows") { orders.push_back(SortBySortTitle); @@ -575,7 +658,7 @@ CStdString CSmartPlaylistRule::GetVideoResolutionQuery(const CStdString ¶met return retVal; } -CStdString CSmartPlaylistRule::GetWhereClause(CDatabase &db, const CStdString& strType) const +CStdString CSmartPlaylistRule::GetWhereClause(const CDatabase &db, const CStdString& strType) const { SEARCH_OPERATOR op = m_operator; if ((strType == "tvshows" || strType == "episodes") && m_field == FieldYear) @@ -627,9 +710,22 @@ CStdString CSmartPlaylistRule::GetWhereClause(CDatabase &db, const CStdString& s } } - // FieldInProgress does not have any values in m_parameter, it works on the operator - if (m_field == FieldInProgress && (strType == "movies" || strType == "episodes")) - return "idFile " + negate + " in (select idFile from bookmark where type = 1)"; + // boolean operators don't have any values in m_parameter, they work on the operator + if (m_operator == OPERATOR_FALSE || m_operator == OPERATOR_TRUE) + { + if (strType == "movies") + { + if (m_field == FieldInProgress) + return "movieview.idFile " + negate + " IN (select idFile from bookmark where type = 1)"; + else if (m_field == FieldTrailer) + return negate + GetField(m_field, strType) + "!= ''"; + } + else if (strType == "episodes") + { + if (m_field == FieldInProgress) + return "episodeview.idFile " + negate + " IN (select idFile from bookmark where type = 1)"; + } + } // now the query parameter CStdString wholeQuery; @@ -690,7 +786,7 @@ CStdString CSmartPlaylistRule::GetWhereClause(CDatabase &db, const CStdString& s if (m_field == FieldGenre) query = GetField(FieldId, strType) + negate + " IN (SELECT song.idAlbum FROM song, song_genre, genre WHERE song.idSong = song_genre.idSong AND song_genre.idGenre = genre.idGenre AND genre.strGenre" + parameter + ")"; else if (m_field == FieldArtist) - query = GetField(FieldId, strType) + negate + " IN (SELECT song.idAlbum FROM song, song_artist, artists WHERE song.idSong = song_artist.idSong AND song_artist.idArtist = artist.idArtist AND artist.strArtist" + parameter + ")"; + query = GetField(FieldId, strType) + negate + " IN (SELECT song.idAlbum FROM song, song_artist, artist WHERE song.idSong = song_artist.idSong AND song_artist.idArtist = artist.idArtist AND artist.strArtist" + parameter + ")"; else if (m_field == FieldAlbumArtist) query = GetField(FieldId, strType) + negate + " IN (SELECT album_artist.idAlbum FROM album_artist, artist WHERE album_artist.idArtist = artist.idArtist AND artist.strArtist" + parameter + ")"; } @@ -710,8 +806,6 @@ CStdString CSmartPlaylistRule::GetWhereClause(CDatabase &db, const CStdString& s query = GetField(FieldId, strType) + negate + " IN (SELECT idMovie FROM studiolinkmovie JOIN studio ON studio.idStudio=studiolinkmovie.idStudio WHERE studio.strStudio" + parameter + ")"; else if (m_field == FieldCountry) query = GetField(FieldId, strType) + negate + " IN (SELECT idMovie FROM countrylinkmovie JOIN country ON country.idCountry=countrylinkmovie.idCountry WHERE country.strCountry" + parameter + ")"; - else if (m_field == FieldTrailer) - query = negate + GetField(m_field, strType) + "!= ''"; else if ((m_field == FieldLastPlayed || m_field == FieldDateAdded) && (m_operator == OPERATOR_LESS_THAN || m_operator == OPERATOR_BEFORE || m_operator == OPERATOR_NOT_IN_THE_LAST)) query = GetField(m_field, strType) + " IS NULL OR " + GetField(m_field, strType) + parameter; else if (m_field == FieldInProgress) @@ -842,6 +936,18 @@ TiXmlElement *CSmartPlaylist::OpenAndReadName(const CStdString &path) m_xmlDoc.Clear(); file >> m_xmlDoc; + TiXmlElement *root = readName(); + if (m_playlistName.empty()) + { + m_playlistName = CUtil::GetTitleFromPath(path); + if (URIUtils::GetExtension(m_playlistName) == ".xsp") + URIUtils::RemoveExtension(m_playlistName); + } + return root; +} + +TiXmlElement* CSmartPlaylist::readName() +{ if (m_xmlDoc.Error()) { CLog::Log(LOGERROR, "Error loading Smart playlist (failed to parse xml: %s)", m_xmlDoc.ErrorDesc()); @@ -851,7 +957,7 @@ TiXmlElement *CSmartPlaylist::OpenAndReadName(const CStdString &path) TiXmlElement *root = m_xmlDoc.RootElement(); if (!root || strcmpi(root->Value(),"smartplaylist") != 0) { - CLog::Log(LOGERROR, "Error loading Smart playlist %s", path.c_str()); + CLog::Log(LOGERROR, "Error loading Smart playlist"); return NULL; } // load the playlist type @@ -868,18 +974,86 @@ TiXmlElement *CSmartPlaylist::OpenAndReadName(const CStdString &path) TiXmlHandle name = ((TiXmlHandle)root->FirstChild("name")).FirstChild(); if (name.Node()) m_playlistName = name.Node()->Value(); - else + + return root; +} + +TiXmlElement *CSmartPlaylist::readNameFromXml(const CStdString &xml) +{ + if (xml.empty()) { - m_playlistName = CUtil::GetTitleFromPath(path); - if (URIUtils::GetExtension(m_playlistName) == ".xsp") - URIUtils::RemoveExtension(m_playlistName); + CLog::Log(LOGERROR, "Error loading empty Smart playlist"); + return NULL; } - return root; + + m_xmlDoc.Clear(); + if (!m_xmlDoc.Parse(xml)) + { + CLog::Log(LOGERROR, "Error loading Smart playlist (failed to parse xml: %s)", m_xmlDoc.ErrorDesc()); + return NULL; + } + + return readName(); } bool CSmartPlaylist::Load(const CStdString &path) { - TiXmlElement *root = OpenAndReadName(path); + return load(OpenAndReadName(path)); +} + +bool CSmartPlaylist::Load(const CVariant &obj) +{ + if (!obj.isObject() || + !obj.isMember("match") || !obj["match"].isString() || + !obj.isMember("rules") || !obj["rules"].isArray()) + return false; + + // load the playlist type + if (obj.isMember("type") && obj["type"].isString()) + m_playlistType = obj["type"].asString(); + // backward compatibility: + if (m_playlistType == "music") + m_playlistType = "songs"; + if (m_playlistType == "video") + m_playlistType = "musicvideos"; + + // load the playlist name + if (obj.isMember("name") && obj["name"].isString()) + m_playlistName = obj["name"].asString(); + + m_matchAllRules = strcmpi(obj["match"].asString().c_str(), "all") == 0; + + // now the rules + for (CVariant::const_iterator_array it = obj["rules"].begin_array(); it != obj["rules"].end_array(); it++) + { + CSmartPlaylistRule rule; + if (rule.Load(*it)) + m_playlistRules.push_back(rule); + } + + // now any limits + if (obj.isMember("limit") && (obj["limit"].isInteger() || obj["limit"].isUnsignedInteger()) && obj["limit"].asUnsignedInteger() > 0) + m_limit = (unsigned int)obj["limit"].asUnsignedInteger(); + + // and order + if (obj.isMember("order") && obj["order"].isMember("method") && obj["order"]["method"].isString()) + { + if (obj["order"].isMember("direction") && obj["order"]["direction"].isString()) + m_orderAscending = strcmpi(obj["order"]["direction"].asString().c_str(), "ascending") == 0; + + m_orderField = CSmartPlaylistRule::TranslateOrder(obj["order"]["method"].asString().c_str()); + } + + return true; +} + +bool CSmartPlaylist::LoadFromXml(const CStdString &xml) +{ + return load(readNameFromXml(xml)); +} + +bool CSmartPlaylist::load(TiXmlElement *root) +{ if (!root) return false; @@ -905,8 +1079,8 @@ bool CSmartPlaylist::LoadFromXML(TiXmlElement *root, const CStdString &encoding) while (ruleElement) { CSmartPlaylistRule rule; - rule.Load(ruleElement, encoding); - m_playlistRules.push_back(rule); + if (rule.Load(ruleElement, encoding)) + m_playlistRules.push_back(rule); ruleElement = ruleElement->NextSiblingElement("rule"); } @@ -930,7 +1104,16 @@ bool CSmartPlaylist::LoadFromXML(TiXmlElement *root, const CStdString &encoding) return true; } -bool CSmartPlaylist::Save(const CStdString &path) +bool CSmartPlaylist::LoadFromJson(const CStdString &json) +{ + if (json.empty()) + return false; + + CVariant obj = CJSONVariantParser::Parse((const unsigned char *)json.c_str(), json.size()); + return Load(obj); +} + +bool CSmartPlaylist::Save(const CStdString &path) const { CXBMCTinyXML doc; TiXmlDeclaration decl("1.0", "UTF-8", "yes"); @@ -955,7 +1138,7 @@ bool CSmartPlaylist::Save(const CStdString &path) pRoot->InsertEndChild(nodeMatch); // add <rule> tags - for (vector<CSmartPlaylistRule>::iterator it = m_playlistRules.begin(); it != m_playlistRules.end(); ++it) + for (vector<CSmartPlaylistRule>::const_iterator it = m_playlistRules.begin(); it != m_playlistRules.end(); ++it) it->Save(pRoot); // add <limit> tag @@ -981,6 +1164,49 @@ bool CSmartPlaylist::Save(const CStdString &path) return doc.SaveFile(path); } +bool CSmartPlaylist::Save(CVariant &obj, bool full /* = true */) const +{ + if (obj.type() == CVariant::VariantTypeConstNull) + return false; + + obj.clear(); + // add "type", "name" and "match" + obj["type"] = m_playlistType; + obj["match"] = m_matchAllRules ? "all" : "one"; + + if (full) + obj["name"] = m_playlistName; + + // add "rules" + obj["rules"] = CVariant(CVariant::VariantTypeArray); + for (vector<CSmartPlaylistRule>::const_iterator it = m_playlistRules.begin(); it != m_playlistRules.end(); ++it) + it->Save(obj["rules"]); + + // add "limit" + if (full && m_limit) + obj["limit"] = m_limit; + + // add "order" + if (full && m_orderField != SortByNone) + { + obj["order"] = CVariant(CVariant::VariantTypeObject); + obj["order"]["method"] = CSmartPlaylistRule::TranslateOrder(m_orderField); + obj["order"]["direction"] = m_orderAscending ? "ascending" : "descending"; + } + + return true; +} + +bool CSmartPlaylist::SaveAsJson(CStdString &json, bool full /* = true */) const +{ + CVariant xsp(CVariant::VariantTypeObject); + if (!Save(xsp, full)) + return false; + + json = CJSONVariantWriter::Write(xsp, true); + return json.size() > 0; +} + void CSmartPlaylist::SetName(const CStdString &name) { m_playlistName = name; @@ -996,7 +1222,7 @@ void CSmartPlaylist::AddRule(const CSmartPlaylistRule &rule) m_playlistRules.push_back(rule); } -CStdString CSmartPlaylist::GetWhereClause(CDatabase &db, set<CStdString> &referencedPlaylists) const +CStdString CSmartPlaylist::GetWhereClause(const CDatabase &db, set<CStdString> &referencedPlaylists) const { CStdString rule, currentRule; for (vector<CSmartPlaylistRule>::const_iterator it = m_playlistRules.begin(); it != m_playlistRules.end(); ++it) @@ -1047,7 +1273,7 @@ const vector<CSmartPlaylistRule> &CSmartPlaylist::GetRules() const CStdString CSmartPlaylist::GetSaveLocation() const { - if (m_playlistType == "songs" || m_playlistType == "albums") + if (m_playlistType == "songs" || m_playlistType == "albums" || m_playlistType == "artists") return "music"; else if (m_playlistType == "mixed") return "mixed"; diff --git a/xbmc/playlists/SmartPlayList.h b/xbmc/playlists/SmartPlayList.h index 95a09b2abc..2f46ccac0f 100644 --- a/xbmc/playlists/SmartPlayList.h +++ b/xbmc/playlists/SmartPlayList.h @@ -28,6 +28,7 @@ #include "utils/XBMCTinyXML.h" class CDatabase; +class CVariant; class CSmartPlaylistRule { @@ -63,9 +64,11 @@ public: }; bool Load(TiXmlElement *element, const CStdString &encoding = "UTF-8"); + bool Load(const CVariant &obj); bool Save(TiXmlNode *parent) const; + bool Save(CVariant &obj) const; - CStdString GetWhereClause(CDatabase &db, const CStdString& strType) const; + CStdString GetWhereClause(const CDatabase &db, const CStdString& strType) const; static Field TranslateField(const char *field); static CStdString TranslateField(Field field); static SortBy TranslateOrder(const char *order); @@ -98,7 +101,12 @@ public: CSmartPlaylist(); bool Load(const CStdString &path); - bool Save(const CStdString &path); + bool Load(const CVariant &obj); + bool LoadFromXml(const CStdString &xml); + bool LoadFromJson(const CStdString &json); + bool Save(const CStdString &path) const; + bool Save(CVariant &obj, bool full = true) const; + bool SaveAsJson(CStdString &json, bool full = true) const; TiXmlElement *OpenAndReadName(const CStdString &path); bool LoadFromXML(TiXmlElement *root, const CStdString &encoding = "UTF-8"); @@ -130,7 +138,7 @@ public: \param referencedPlaylists a set of playlists to know when we reach a cycle \param needWhere whether we need to prepend the where clause with "WHERE " */ - CStdString GetWhereClause(CDatabase &db, std::set<CStdString> &referencedPlaylists) const; + CStdString GetWhereClause(const CDatabase &db, std::set<CStdString> &referencedPlaylists) const; const std::vector<CSmartPlaylistRule> &GetRules() const; @@ -138,6 +146,10 @@ public: private: friend class CGUIDialogSmartPlaylistEditor; + TiXmlElement* readName(); + TiXmlElement *readNameFromXml(const CStdString &xml); + bool load(TiXmlElement *root); + std::vector<CSmartPlaylistRule> m_playlistRules; CStdString m_playlistName; CStdString m_playlistType; diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp index 3dc15583e0..a68910ba58 100644 --- a/xbmc/powermanagement/PowerManager.cpp +++ b/xbmc/powermanagement/PowerManager.cpp @@ -39,6 +39,8 @@ #if defined(TARGET_DARWIN) #include "osx/CocoaPowerSyscall.h" +#elif defined(TARGET_ANDROID) +#include "android/AndroidPowerSyscall.h" #elif defined(_LINUX) && defined(HAS_DBUS) #include "linux/ConsoleUPowerSyscall.h" #include "linux/ConsoleDeviceKitPowerSyscall.h" @@ -68,6 +70,8 @@ void CPowerManager::Initialize() { #if defined(TARGET_DARWIN) m_instance = new CCocoaPowerSyscall(); +#elif defined(TARGET_ANDROID) + m_instance = new CAndroidPowerSyscall(); #elif defined(_LINUX) && defined(HAS_DBUS) if (CConsoleUPowerSyscall::HasDeviceConsoleKit()) m_instance = new CConsoleUPowerSyscall(); diff --git a/xbmc/powermanagement/android/AndroidPowerSyscall.cpp b/xbmc/powermanagement/android/AndroidPowerSyscall.cpp new file mode 100644 index 0000000000..7f4740d169 --- /dev/null +++ b/xbmc/powermanagement/android/AndroidPowerSyscall.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#if defined (TARGET_ANDROID) + +#include "AndroidPowerSyscall.h" +#include "android/activity/XBMCApp.h" + +CAndroidPowerSyscall::CAndroidPowerSyscall() +{ } + +CAndroidPowerSyscall::~CAndroidPowerSyscall() +{ } + +int CAndroidPowerSyscall::BatteryLevel(void) +{ + return CXBMCApp::GetBatteryLevel(); +} + +bool CAndroidPowerSyscall::PumpPowerEvents(IPowerEventsCallback *callback) +{ + return true; +} + +#endif diff --git a/xbmc/powermanagement/android/AndroidPowerSyscall.h b/xbmc/powermanagement/android/AndroidPowerSyscall.h new file mode 100644 index 0000000000..bfcb2bf681 --- /dev/null +++ b/xbmc/powermanagement/android/AndroidPowerSyscall.h @@ -0,0 +1,44 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#if defined (TARGET_ANDROID) +#include "powermanagement/IPowerSyscall.h" + +class CAndroidPowerSyscall : public CPowerSyscallWithoutEvents +{ +public: + CAndroidPowerSyscall(); + ~CAndroidPowerSyscall(); + + virtual bool Powerdown(void) { return false; } + virtual bool Suspend(void) { return false; } + virtual bool Hibernate(void) { return false; } + virtual bool Reboot(void) { return false; } + + virtual bool CanPowerdown(void) { return false; } + virtual bool CanSuspend(void) { return false; } + virtual bool CanHibernate(void) { return false; } + virtual bool CanReboot(void) { return false; } + virtual int BatteryLevel(void); + + virtual bool PumpPowerEvents(IPowerEventsCallback *callback); +}; +#endif diff --git a/xbmc/powermanagement/android/Makefile b/xbmc/powermanagement/android/Makefile new file mode 100644 index 0000000000..64313a5313 --- /dev/null +++ b/xbmc/powermanagement/android/Makefile @@ -0,0 +1,6 @@ +SRCS=AndroidPowerSyscall.cpp + +LIB=powermanagement_android.a + +include ../../../Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/powermanagement/linux/ConsoleDeviceKitPowerSyscall.cpp b/xbmc/powermanagement/linux/ConsoleDeviceKitPowerSyscall.cpp index fa8ac64151..69f5e04b58 100644 --- a/xbmc/powermanagement/linux/ConsoleDeviceKitPowerSyscall.cpp +++ b/xbmc/powermanagement/linux/ConsoleDeviceKitPowerSyscall.cpp @@ -24,7 +24,6 @@ #include "utils/log.h" #ifdef HAS_DBUS -#include "Application.h" #include "DBusUtil.h" CConsoleDeviceKitPowerSyscall::CConsoleDeviceKitPowerSyscall() diff --git a/xbmc/powermanagement/linux/ConsoleUPowerSyscall.cpp b/xbmc/powermanagement/linux/ConsoleUPowerSyscall.cpp index 69106265f1..6bdd995d5a 100644 --- a/xbmc/powermanagement/linux/ConsoleUPowerSyscall.cpp +++ b/xbmc/powermanagement/linux/ConsoleUPowerSyscall.cpp @@ -24,7 +24,6 @@ #include "utils/log.h" #ifdef HAS_DBUS -#include "Application.h" CUPowerSource::CUPowerSource(const char *powerSource) { diff --git a/xbmc/powermanagement/linux/HALPowerSyscall.cpp b/xbmc/powermanagement/linux/HALPowerSyscall.cpp index 480371cbd7..8083a1d1ac 100644 --- a/xbmc/powermanagement/linux/HALPowerSyscall.cpp +++ b/xbmc/powermanagement/linux/HALPowerSyscall.cpp @@ -24,7 +24,6 @@ #include "utils/log.h" #ifdef HAS_HAL -#include "Application.h" #include <dbus/dbus.h> #include <stdlib.h> diff --git a/xbmc/programs/GUIViewStatePrograms.cpp b/xbmc/programs/GUIViewStatePrograms.cpp index 59b0759a03..9dea6a206c 100644 --- a/xbmc/programs/GUIViewStatePrograms.cpp +++ b/xbmc/programs/GUIViewStatePrograms.cpp @@ -25,7 +25,6 @@ #include "settings/GUISettings.h" #include "settings/Settings.h" #include "filesystem/Directory.h" -#include "Util.h" #include "guilib/LocalizeStrings.h" #include "guilib/Key.h" @@ -64,6 +63,9 @@ CStdString CGUIViewStateWindowPrograms::GetExtensions() VECSOURCES& CGUIViewStateWindowPrograms::GetSources() { AddAddonsSource("executable", g_localizeStrings.Get(1043), "DefaultAddonProgram.png"); +#if defined(TARGET_ANDROID) + AddAndroidSource("apps", g_localizeStrings.Get(20244), "DefaultProgram.png"); +#endif AddOrReplace(g_settings.m_programSources,CGUIViewState::GetSources()); return g_settings.m_programSources; } diff --git a/xbmc/programs/GUIWindowPrograms.cpp b/xbmc/programs/GUIWindowPrograms.cpp index a7b5658e6e..21b9b971a3 100644 --- a/xbmc/programs/GUIWindowPrograms.cpp +++ b/xbmc/programs/GUIWindowPrograms.cpp @@ -25,7 +25,6 @@ #include "addons/GUIDialogAddonInfo.h" #include "Autorun.h" #include "guilib/GUIWindowManager.h" -#include "dialogs/GUIDialogKeyboard.h" #include "FileItem.h" #include "settings/Settings.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/rendering/dx/RenderSystemDX.cpp b/xbmc/rendering/dx/RenderSystemDX.cpp index df9a9e60bc..d069e12048 100644 --- a/xbmc/rendering/dx/RenderSystemDX.cpp +++ b/xbmc/rendering/dx/RenderSystemDX.cpp @@ -55,7 +55,10 @@ static HMODULE g_D3D9ExHandle; static bool LoadD3D9Ex() { - g_Direct3DCreate9Ex = (LPDIRECT3DCREATE9EX)GetProcAddress( GetModuleHandle("d3d9.dll"), "Direct3DCreate9Ex" ); + HMODULE hD3d9Dll = GetModuleHandle("d3d9.dll"); + if (!hD3d9Dll) + return false; + g_Direct3DCreate9Ex = (LPDIRECT3DCREATE9EX)GetProcAddress(hD3d9Dll, "Direct3DCreate9Ex" ); if(g_Direct3DCreate9Ex == NULL) return false; return true; @@ -620,7 +623,7 @@ bool CRenderSystemDX::BeginRender() if (!m_bRenderCreated) return false; - DWORD oldStatus = m_nDeviceStatus; + HRESULT oldStatus = m_nDeviceStatus; if (m_useD3D9Ex) { m_nDeviceStatus = ((IDirect3DDevice9Ex*)m_pD3DDevice)->CheckDeviceState(m_hDeviceWnd); diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp index 5b02a01ab2..da952ba1ec 100644 --- a/xbmc/rendering/gles/RenderSystemGLES.cpp +++ b/xbmc/rendering/gles/RenderSystemGLES.cpp @@ -373,6 +373,7 @@ void CRenderSystemGLES::ApplyStateBlock() glActiveTexture(GL_TEXTURE0); glEnable(GL_BLEND); glEnable(GL_SCISSOR_TEST); + glClear(GL_DEPTH_BUFFER_BIT); } void CRenderSystemGLES::SetCameraPosition(const CPoint &camera, int screenWidth, int screenHeight) diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp index 0416f79464..e91c90ccf5 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -129,10 +129,7 @@ void CAdvancedSettings::Initialize() m_lcdScrolldelay = 1; m_lcdHostName = "localhost"; - m_autoDetectPingTime = 30; - m_songInfoDuration = 10; - m_busyDialogDelay = 2000; m_cddbAddress = "freedb.freedb.org"; @@ -660,7 +657,6 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) pElement = pRootElement->FirstChildElement("network"); if (pElement) { - XMLUtils::GetInt(pElement, "autodetectpingtime", m_autoDetectPingTime, 1, 240); XMLUtils::GetInt(pElement, "curlclienttimeout", m_curlconnecttimeout, 1, 1000); XMLUtils::GetInt(pElement, "curllowspeedtime", m_curllowspeedtime, 1, 1000); XMLUtils::GetInt(pElement, "curlretries", m_curlretries, 0, 10); @@ -708,14 +704,13 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) g_advancedSettings.m_logLevel = std::max(g_advancedSettings.m_logLevel, g_advancedSettings.m_logLevelHint); CLog::SetLogLevel(g_advancedSettings.m_logLevel); } - + XMLUtils::GetString(pRootElement, "cddbaddress", m_cddbAddress); //airtunes + airplay XMLUtils::GetBoolean(pRootElement, "enableairtunesdebuglog", m_logEnableAirtunes); XMLUtils::GetInt(pRootElement, "airtunesport", m_airTunesPort); XMLUtils::GetInt(pRootElement, "airplayport", m_airPlayPort); - XMLUtils::GetBoolean(pRootElement, "handlemounting", m_handleMounting); @@ -727,7 +722,6 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) XMLUtils::GetBoolean(pRootElement, "canwindowed", m_canWindowed); XMLUtils::GetInt(pRootElement, "songinfoduration", m_songInfoDuration, 0, INT_MAX); - XMLUtils::GetInt(pRootElement, "busydialogdelay", m_busyDialogDelay, 0, 5000); XMLUtils::GetInt(pRootElement, "playlistretries", m_playlistRetries, -1, 5000); XMLUtils::GetInt(pRootElement, "playlisttimeout", m_playlistTimeout, 0, 5000); @@ -1128,3 +1122,21 @@ float CAdvancedSettings::GetDisplayLatency(float refreshrate) return delay; // in seconds } + +void CAdvancedSettings::SetDebugMode(bool debug) +{ + if (debug) + { + int level = std::max(m_logLevelHint, LOG_LEVEL_DEBUG_FREEMEM); + m_logLevel = level; + CLog::SetLogLevel(level); + CLog::Log(LOGNOTICE, "Enabled debug logging due to GUI setting. Level %d.", level); + } + else + { + int level = std::min(m_logLevelHint, LOG_LEVEL_DEBUG/*LOG_LEVEL_NORMAL*/); + CLog::Log(LOGNOTICE, "Disabled debug logging due to GUI setting. Level %d.", level); + m_logLevel = level; + CLog::SetLogLevel(level); + } +} diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h index 50b9de4c5f..f529f6bf2c 100644 --- a/xbmc/settings/AdvancedSettings.h +++ b/xbmc/settings/AdvancedSettings.h @@ -175,18 +175,15 @@ class CAdvancedSettings int m_lcdScrolldelay; CStdString m_lcdHostName; - int m_autoDetectPingTime; - int m_songInfoDuration; - int m_busyDialogDelay; int m_logLevel; int m_logLevelHint; CStdString m_cddbAddress; - + //airtunes + airplay bool m_logEnableAirtunes; int m_airTunesPort; - int m_airPlayPort; + int m_airPlayPort; bool m_handleMounting; @@ -290,7 +287,7 @@ class CAdvancedSettings bool m_fullScreen; bool m_startFullScreen; - bool m_showExitButton; /* Ideal for appliances to hide a 'useless' button */ + bool m_showExitButton; /* Ideal for appliances to hide a 'useless' button */ bool m_canWindowed; bool m_splashImage; bool m_alwaysOnTop; /* makes xbmc to run always on top .. osx/win32 only .. */ @@ -342,6 +339,8 @@ class CAdvancedSettings float GetDisplayLatency(float refreshrate); bool m_initialized; + + void SetDebugMode(bool debug); }; XBMC_GLOBAL(CAdvancedSettings,g_advancedSettings); diff --git a/xbmc/settings/AppParamParser.cpp b/xbmc/settings/AppParamParser.cpp index 0302105538..a29cdca0e6 100644 --- a/xbmc/settings/AppParamParser.cpp +++ b/xbmc/settings/AppParamParser.cpp @@ -25,6 +25,7 @@ #include "PlayListPlayer.h" #include "FileItem.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "utils/log.h" #ifdef TARGET_WINDOWS #include "WIN32Util.h" @@ -156,5 +157,5 @@ void CAppParamParser::PlayPlaylist() } ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PLAY, (DWORD) -1}; - g_application.getApplicationMessenger().SendMessage(tMsg, false); + CApplicationMessenger::Get().SendMessage(tMsg, false); } diff --git a/xbmc/settings/GUIDialogContentSettings.cpp b/xbmc/settings/GUIDialogContentSettings.cpp index 94e8dec5c6..2d42ef311c 100644 --- a/xbmc/settings/GUIDialogContentSettings.cpp +++ b/xbmc/settings/GUIDialogContentSettings.cpp @@ -32,6 +32,8 @@ #include "filesystem/AddonsDirectory.h" #include "dialogs/GUIDialogKaiToast.h" +#include <climits> + #define CONTROL_CONTENT_TYPE 3 #define CONTROL_SCRAPER_LIST 4 #define CONTROL_SCRAPER_SETTINGS 6 @@ -177,7 +179,10 @@ void CGUIDialogContentSettings::CreateSettings() case CONTENT_MUSICVIDEOS: { AddBool(1,20346,&m_bScanRecursive, m_bShowScanSettings); - AddBool(2,20432,&m_bNoUpdate, m_bShowScanSettings); + AddBool(2,20330,&m_bUseDirNames, m_bShowScanSettings); + AddBool(3,20346,&m_bScanRecursive, m_bShowScanSettings && ((m_bUseDirNames && !m_bSingleItem) || !m_bUseDirNames)); + AddBool(4,20383,&m_bSingleItem, m_bShowScanSettings && (m_bUseDirNames && !m_bScanRecursive)); + AddBool(5,20432,&m_bNoUpdate, m_bShowScanSettings); } break; case CONTENT_ALBUMS: @@ -398,7 +403,7 @@ bool CGUIDialogContentSettings::Show(ADDON::ScraperPtr& scraper, VIDEO::SScanSet dialog->m_bScanRecursive = (settings.recurse > 0 && !settings.parent_name) || (settings.recurse > 1 && settings.parent_name); dialog->m_bUseDirNames = settings.parent_name; - dialog->m_bExclude = settings.exclude; + dialog->m_bExclude = settings.exclude; dialog->m_bSingleItem = settings.parent_name_root; dialog->m_bNoUpdate = settings.noupdate; dialog->m_bNeedSave = false; @@ -412,7 +417,7 @@ bool CGUIDialogContentSettings::Show(ADDON::ScraperPtr& scraper, VIDEO::SScanSet scraper.reset(); settings.exclude = dialog->m_bExclude; } - else + else { settings.exclude = false; settings.noupdate = dialog->m_bNoUpdate; @@ -447,9 +452,24 @@ bool CGUIDialogContentSettings::Show(ADDON::ScraperPtr& scraper, VIDEO::SScanSet } else if (content == CONTENT_MUSICVIDEOS) { - settings.parent_name = false; - settings.parent_name_root = false; - settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 0; + if (dialog->m_bUseDirNames) + { + settings.parent_name = true; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 1; + + if (dialog->m_bSingleItem) + { + settings.parent_name_root = true; + settings.recurse = 0; + } + } + else + { + settings.parent_name = false; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 0; + } } } } diff --git a/xbmc/settings/GUIDialogLockSettings.cpp b/xbmc/settings/GUIDialogLockSettings.cpp index 14355722d9..91f77194e9 100644 --- a/xbmc/settings/GUIDialogLockSettings.cpp +++ b/xbmc/settings/GUIDialogLockSettings.cpp @@ -21,7 +21,7 @@ #include "GUIDialogLockSettings.h" #include "dialogs/GUIDialogNumeric.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "dialogs/GUIDialogGamepad.h" #include "dialogs/GUIDialogContextMenu.h" #include "guilib/GUIWindowManager.h" @@ -119,7 +119,7 @@ void CGUIDialogLockSettings::OnSettingChanged(SettingInfo &setting) CStdString strDecodeUrl = m_strURL; CURL::Decode(strDecodeUrl); strHeading.Format("%s %s",g_localizeStrings.Get(14062).c_str(),strDecodeUrl.c_str()); - if (CGUIDialogKeyboard::ShowAndGetInput(m_strUser,strHeading,true)) + if (CGUIKeyboardFactory::ShowAndGetInput(m_strUser,strHeading,true)) { m_bChanged = true; m_settings[0].name.Format("%s (%s)",g_localizeStrings.Get(20142).c_str(),m_strUser.c_str()); @@ -154,7 +154,7 @@ void CGUIDialogLockSettings::OnSettingChanged(SettingInfo &setting) break; case 4: iLockMode = LOCK_MODE_QWERTY; - bResult = CGUIDialogKeyboard::ShowAndVerifyNewPassword(newPassword); + bResult = CGUIKeyboardFactory::ShowAndVerifyNewPassword(newPassword); break; default: break; @@ -184,7 +184,7 @@ void CGUIDialogLockSettings::OnSettingChanged(SettingInfo &setting) CStdString strDecodeUrl = m_strURL; CURL::Decode(strDecodeUrl); strHeading.Format("%s %s",g_localizeStrings.Get(20143).c_str(),strDecodeUrl.c_str()); - if (CGUIDialogKeyboard::ShowAndGetInput(m_locks.code,strHeading,true,true)) + if (CGUIKeyboardFactory::ShowAndGetInput(m_locks.code,strHeading,true,true)) { m_settings[1].name.Format("%s (%s)",g_localizeStrings.Get(12326).c_str(),g_localizeStrings.Get(20141).c_str()); m_bChanged = true; diff --git a/xbmc/settings/GUIDialogProfileSettings.cpp b/xbmc/settings/GUIDialogProfileSettings.cpp index 73bf1a0b65..c28300dfb4 100644 --- a/xbmc/settings/GUIDialogProfileSettings.cpp +++ b/xbmc/settings/GUIDialogProfileSettings.cpp @@ -21,10 +21,7 @@ #include "GUIDialogProfileSettings.h" #include "dialogs/GUIDialogFileBrowser.h" -#include "dialogs/GUIDialogContextMenu.h" -#include "dialogs/GUIDialogNumeric.h" -#include "dialogs/GUIDialogKeyboard.h" -#include "dialogs/GUIDialogGamepad.h" +#include "guilib/GUIKeyboardFactory.h" #include "GUIDialogLockSettings.h" #include "guilib/GUIImage.h" #include "guilib/GUIWindowManager.h" @@ -146,7 +143,7 @@ void CGUIDialogProfileSettings::OnSettingChanged(SettingInfo &setting) // check and update anything that needs it if (setting.id == 1) { - if (CGUIDialogKeyboard::ShowAndGetInput(m_strName,g_localizeStrings.Get(20093),false)) + if (CGUIKeyboardFactory::ShowAndGetInput(m_strName,g_localizeStrings.Get(20093),false)) { m_bNeedSave = true; SET_CONTROL_LABEL(1000,m_strName); @@ -276,7 +273,7 @@ bool CGUIDialogProfileSettings::ShowForProfile(unsigned int iProfile, bool first dialog->m_strDirectory.Empty(); dialog->m_strThumb.Empty(); // prompt for a name - if (!CGUIDialogKeyboard::ShowAndGetInput(dialog->m_strName,g_localizeStrings.Get(20093),false) || dialog->m_strName.IsEmpty()) + if (!CGUIKeyboardFactory::ShowAndGetInput(dialog->m_strName,g_localizeStrings.Get(20093),false) || dialog->m_strName.IsEmpty()) return false; // create a default path CStdString defaultDir = URIUtils::AddFileToFolder("profiles",CUtil::MakeLegalFileName(dialog->m_strName)); @@ -385,7 +382,7 @@ bool CGUIDialogProfileSettings::ShowForProfile(unsigned int iProfile, bool first profile->setDatabases((dialog->m_iDbMode & 2) == 2); profile->setSources((dialog->m_iSourcesMode & 2) == 2); profile->SetLocks(dialog->m_locks); - + g_settings.SaveProfiles(PROFILES_FILE); return true; } diff --git a/xbmc/settings/GUIDialogSettings.cpp b/xbmc/settings/GUIDialogSettings.cpp index 609a299904..4c1f56321a 100644 --- a/xbmc/settings/GUIDialogSettings.cpp +++ b/xbmc/settings/GUIDialogSettings.cpp @@ -28,7 +28,7 @@ #include "guilib/LocalizeStrings.h" #include "GUISettings.h" #include "utils/log.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #define CONTROL_GROUP_LIST 5 #define CONTROL_SETTINGS_LABEL 2 @@ -262,7 +262,7 @@ void CGUIDialogSettings::OnClick(int iID) } else if (setting.type == SettingInfo::STRING) { - CGUIDialogKeyboard::ShowAndGetInput(*(CStdString *) setting.data, true); + CGUIKeyboardFactory::ShowAndGetInput(*(CStdString *) setting.data, true); string strNewValue = string(*(CStdString *)setting.data); if (strNewValue.empty()) strNewValue = "-"; diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp index d4b1893b70..41cce36283 100644 --- a/xbmc/settings/GUISettings.cpp +++ b/xbmc/settings/GUISettings.cpp @@ -414,7 +414,7 @@ void CGUISettings::Initialize() #endif AddBool(showSetting ? vs : NULL, "videoscreen.fakefullscreen", 14083, fakeFullScreen); #ifdef TARGET_DARWIN_IOS - AddBool(NULL, "videoscreen.blankdisplays", 13130, false); + AddBool(NULL, "videoscreen.blankdisplays", 13130, false); #else AddBool(vs, "videoscreen.blankdisplays", 13130, false); #endif @@ -683,11 +683,19 @@ void CGUISettings::Initialize() // FIXME: hide this setting until it is properly respected. In the meanwhile, default to AUTO. //AddInt(5, "videoplayer.displayresolution", 169, (int)RES_AUTORES, (int)RES_AUTORES, 1, (int)CUSTOM+MAX_RESOLUTIONS, SPIN_CONTROL_TEXT); AddInt(NULL, "videoplayer.displayresolution", 169, (int)RES_AUTORES, (int)RES_AUTORES, 1, (int)RES_AUTORES, SPIN_CONTROL_TEXT); + + map<int, int> adjustTypes; + adjustTypes.insert(make_pair(351, ADJUST_REFRESHRATE_OFF)); + adjustTypes.insert(make_pair(36035, ADJUST_REFRESHRATE_ALWAYS)); + adjustTypes.insert(make_pair(36036, ADJUST_REFRESHRATE_ON_STARTSTOP)); + #if !defined(TARGET_DARWIN_IOS) - AddBool(vp, "videoplayer.adjustrefreshrate", 170, false); + AddInt(vp, "videoplayer.adjustrefreshrate", 170, ADJUST_REFRESHRATE_OFF, adjustTypes, SPIN_CONTROL_TEXT); +// AddBool(vp, "videoplayer.adjustrefreshrate", 170, false); AddInt(vp, "videoplayer.pauseafterrefreshchange", 13550, 0, 0, 1, MAXREFRESHCHANGEDELAY, SPIN_CONTROL_TEXT); #else - AddBool(NULL, "videoplayer.adjustrefreshrate", 170, false); + AddInt(NULL, "videoplayer.adjustrefreshrate", 170, ADJUST_REFRESHRATE_OFF, adjustTypes, SPIN_CONTROL_TEXT); + //AddBool(NULL, "videoplayer.adjustrefreshrate", 170, false); AddInt(NULL, "videoplayer.pauseafterrefreshchange", 13550, 0, 0, 1, MAXREFRESHCHANGEDELAY, SPIN_CONTROL_TEXT); #endif //sync settings not available on windows gl build @@ -739,7 +747,7 @@ void CGUISettings::Initialize() myVideosSelectActions.insert(make_pair(208, SELECT_ACTION_PLAY_OR_RESUME)); myVideosSelectActions.insert(make_pair(13404, SELECT_ACTION_RESUME)); myVideosSelectActions.insert(make_pair(22081, SELECT_ACTION_INFO)); - + AddInt(vid, "myvideos.selectaction", 22079, SELECT_ACTION_PLAY_OR_RESUME, myVideosSelectActions, SPIN_CONTROL_TEXT); AddBool(vid, "myvideos.extractflags",20433, true); AddBool(vid, "myvideos.replacelabels", 20419, true); @@ -820,7 +828,7 @@ void CGUISettings::Initialize() CSettingsCategory* srvAirplay = AddCategory(6, "airplay", 1273); AddBool(srvAirplay, "services.airplay", 1270, false); AddBool(srvAirplay, "services.useairplaypassword", 1272, false); - AddString(srvAirplay, "services.airplaypassword", 733, "", EDIT_CONTROL_HIDDEN_INPUT, false, 733); + AddString(srvAirplay, "services.airplaypassword", 733, "", EDIT_CONTROL_HIDDEN_INPUT, false, 733); #endif #ifndef _WIN32 @@ -847,21 +855,23 @@ void CGUISettings::Initialize() AddString(loc, "locale.language",248,"english", SPIN_CONTROL_TEXT); AddString(loc, "locale.country", 20026, "USA", SPIN_CONTROL_TEXT); AddString(loc, "locale.charset", 14091, "DEFAULT", SPIN_CONTROL_TEXT); // charset is set by the language file - + bool use_timezone = false; - + #if defined(_LINUX) #if defined(TARGET_DARWIN) if (g_sysinfo.IsAppleTV2() && GetIOSVersion() < 4.3) #endif - use_timezone = true; - +#if !defined(TARGET_ANDROID) + use_timezone = true; +#endif + if (use_timezone) - { + { AddSeparator(loc, "locale.sep1"); AddString(loc, "locale.timezonecountry", 14079, g_timezone.GetCountryByTimezone(g_timezone.GetOSConfiguredTimezone()), SPIN_CONTROL_TEXT); AddString(loc, "locale.timezone", 14080, g_timezone.GetOSConfiguredTimezone(), SPIN_CONTROL_TEXT); - } + } #endif #ifdef HAS_TIME_SERVER AddSeparator(loc, "locale.sep2"); @@ -1259,24 +1269,26 @@ void CGUISettings::LoadXML(TiXmlElement *pRootElement, bool hideSettings /* = fa m_replayGain.iNoGainPreAmp = GetInt("musicplayer.replaygainnogainpreamp"); m_replayGain.iType = GetInt("musicplayer.replaygaintype"); m_replayGain.bAvoidClipping = GetBool("musicplayer.replaygainavoidclipping"); - + bool use_timezone = false; - + #if defined(_LINUX) -#if defined(TARGET_DARWIN) +#if defined(TARGET_DARWIN) if (g_sysinfo.IsAppleTV2() && GetIOSVersion() < 4.3) #endif +#if !defined(TARGET_ANDROID) use_timezone = true; - +#endif + if (use_timezone) - { + { CStdString timezone = GetString("locale.timezone"); if(timezone == "0" || timezone.IsEmpty()) { timezone = g_timezone.GetOSConfiguredTimezone(); SetString("locale.timezone", timezone); } - g_timezone.SetTimezone(timezone); + g_timezone.SetTimezone(timezone); } #endif diff --git a/xbmc/settings/GUISettings.h b/xbmc/settings/GUISettings.h index f994f15eed..350d7fcba2 100644 --- a/xbmc/settings/GUISettings.h +++ b/xbmc/settings/GUISettings.h @@ -163,6 +163,12 @@ class TiXmlElement; #define SYNC_SKIPDUP 1 #define SYNC_RESAMPLE 2 +//adjust refreshrate options +#define ADJUST_REFRESHRATE_OFF 0 +#define ADJUST_REFRESHRATE_ALWAYS 1 +#define ADJUST_REFRESHRATE_ON_STARTSTOP 2 + + //resampler quality #define RESAMPLE_LOW 0 #define RESAMPLE_MID 1 @@ -301,11 +307,11 @@ public: virtual CStdString ToString() const; void SetData(int iData) - { + { if (m_entries.empty()) { m_iData = iData; - if (m_iData < m_iMin) m_iData = m_iMin; + if (m_iData < m_iMin) m_iData = m_iMin; if (m_iData > m_iMax) m_iData = m_iMax; } else diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp index d982694409..7187063341 100644 --- a/xbmc/settings/GUIWindowSettingsCategory.cpp +++ b/xbmc/settings/GUIWindowSettingsCategory.cpp @@ -23,6 +23,7 @@ #include "GUIUserMessages.h" #include "GUIWindowSettingsCategory.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "interfaces/Builtins.h" #include "input/KeyboardLayoutConfiguration.h" #include "filesystem/Directory.h" @@ -44,13 +45,10 @@ #include "network/libscrobbler/lastfmscrobbler.h" #include "network/libscrobbler/librefmscrobbler.h" #include "GUIPassword.h" -#include "dialogs/GUIDialogGamepad.h" -#include "dialogs/GUIDialogNumeric.h" #include "dialogs/GUIDialogFileBrowser.h" #include "addons/GUIDialogAddonSettings.h" #include "addons/GUIWindowAddonBrowser.h" #include "dialogs/GUIDialogContextMenu.h" -#include "dialogs/GUIDialogKeyboard.h" #include "dialogs/GUIDialogYesNo.h" #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogProgress.h" @@ -71,7 +69,7 @@ #include "HALManager.h" #endif #endif -#if defined(TARGET_DARWIN_OSX) +#if defined(TARGET_DARWIN_OSX) #include "XBMCHelper.h" #endif #include "network/GUIDialogAccessPoints.h" @@ -233,6 +231,9 @@ bool CGUIWindowSettingsCategory::OnMessage(CGUIMessage &message) m_delayedSetting = NULL; return true; } + case GUI_MSG_UPDATE: + if (HasID(message.GetSenderId())) + UpdateSettings(); break; case GUI_MSG_NOTIFY_ALL: { @@ -692,7 +693,7 @@ void CGUIWindowSettingsCategory::UpdateSettings() else if (strSetting.Equals("audiocds.bitrate")) { // only visible if we are ripping to CBR CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_WAV && + if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_WAV && g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_FLAC && g_guiSettings.GetInt("audiocds.quality") == CDDARIP_QUALITY_CBR); } @@ -749,7 +750,7 @@ void CGUIWindowSettingsCategory::UpdateSettings() } #endif #ifdef HAS_AIRPLAY - else if ( strSetting.Equals("services.airplaypassword") || + else if ( strSetting.Equals("services.airplaypassword") || strSetting.Equals("services.useairplaypassword")) { if (strSetting.Equals("services.airplaypassword")) @@ -760,19 +761,19 @@ void CGUIWindowSettingsCategory::UpdateSettings() } else//useairplaypassword { - CGUIRadioButtonControl *pControl = (CGUIRadioButtonControl *)GetControl(pSettingControl->GetID()); + CGUIRadioButtonControl *pControl = (CGUIRadioButtonControl *)GetControl(pSettingControl->GetID()); if (pControl) - pControl->SetEnabled(g_guiSettings.GetBool("services.airplay")); + pControl->SetEnabled(g_guiSettings.GetBool("services.airplay")); } //set credentials to airplay server if (g_guiSettings.GetBool("services.airplay")) { CStdString password = g_guiSettings.GetString("services.airplaypassword"); - CAirPlayServer::SetCredentials(g_guiSettings.GetBool("services.useairplaypassword"), + CAirPlayServer::SetCredentials(g_guiSettings.GetBool("services.useairplaypassword"), password); - } - } + } + } #endif//HAS_AIRPLAY else if (strSetting.Equals("network.ipaddress") || strSetting.Equals("network.subnet") || strSetting.Equals("network.gateway") || strSetting.Equals("network.dns")) { @@ -918,7 +919,7 @@ void CGUIWindowSettingsCategory::UpdateSettings() else if (strSetting.Equals("videoplayer.pauseafterrefreshchange")) { CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetBool("videoplayer.adjustrefreshrate")); + if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF); } else if (strSetting.Equals("videoplayer.synctype")) { @@ -1065,20 +1066,7 @@ void CGUIWindowSettingsCategory::OnSettingChanged(CBaseSettingControl *pSettingC } else if (strSetting.Equals("debug.showloginfo")) { - if (g_guiSettings.GetBool("debug.showloginfo")) - { - int level = std::max(g_advancedSettings.m_logLevelHint, LOG_LEVEL_DEBUG_FREEMEM); - g_advancedSettings.m_logLevel = level; - CLog::SetLogLevel(level); - CLog::Log(LOGNOTICE, "Enabled debug logging due to GUI setting. Level %d.", level); - } - else - { - int level = std::min(g_advancedSettings.m_logLevelHint, LOG_LEVEL_DEBUG/*LOG_LEVEL_NORMAL*/); - CLog::Log(LOGNOTICE, "Disabled debug logging due to GUI setting. Level %d.", level); - g_advancedSettings.m_logLevel = level; - CLog::SetLogLevel(level); - } + g_advancedSettings.SetDebugMode(g_guiSettings.GetBool("debug.showloginfo")); } /*else if (strSetting.Equals("musicfiles.repeat")) { @@ -1254,8 +1242,8 @@ void CGUIWindowSettingsCategory::OnSettingChanged(CBaseSettingControl *pSettingC #endif } else if (strSetting.Equals("services.airplay")) - { -#ifdef HAS_AIRPLAY + { +#ifdef HAS_AIRPLAY if (g_guiSettings.GetBool("services.airplay")) { #ifdef HAS_ZEROCONF @@ -1270,8 +1258,8 @@ void CGUIWindowSettingsCategory::OnSettingChanged(CBaseSettingControl *pSettingC g_application.StartAirplayServer();//will stop the server before internal } else - g_application.StopAirplayServer(true);//will stop the server before internal -#endif//HAS_AIRPLAY + g_application.StopAirplayServer(true);//will stop the server before internal +#endif//HAS_AIRPLAY } else if (strSetting.Equals("network.ipaddress")) { @@ -1609,7 +1597,7 @@ void CGUIWindowSettingsCategory::OnSettingChanged(CBaseSettingControl *pSettingC if (CGUIDialogYesNo::ShowAndGetInput(14038, 14039, 14040, -1, -1)) { g_settings.Save(); - g_application.getApplicationMessenger().RestartApp(); + CApplicationMessenger::Get().RestartApp(); } } else if (strSetting.Equals("services.upnpserver")) @@ -1862,7 +1850,7 @@ void CGUIWindowSettingsCategory::OnSettingChanged(CBaseSettingControl *pSettingC g_guiSettings.SetString("audiooutput.passthroughdevice", m_DigitalAudioSinkMap[pControl->GetCurrentLabel()]); } #endif - + CAEFactory::OnSettingsChange(strSetting); } @@ -2125,9 +2113,9 @@ void CGUIWindowSettingsCategory::FillInSkinFonts(CSetting *pSetting) if (idAttr != NULL && isAllowed) { - if (idLocAttr) + if (idLocAttr) { - pControl->AddLabel(g_localizeStrings.Get(atoi(idLocAttr)), iSkinFontSet); + pControl->AddLabel(g_localizeStrings.Get(atoi(idLocAttr)), iSkinFontSet); m_SkinFontSetIDs[g_localizeStrings.Get(atoi(idLocAttr))] = idAttr; } else diff --git a/xbmc/settings/GUIWindowSettingsProfile.cpp b/xbmc/settings/GUIWindowSettingsProfile.cpp index 9b87b4c490..e3f517fa50 100644 --- a/xbmc/settings/GUIWindowSettingsProfile.cpp +++ b/xbmc/settings/GUIWindowSettingsProfile.cpp @@ -33,7 +33,6 @@ #include "guilib/GUIWindowManager.h" #include "filesystem/Directory.h" #include "FileItem.h" -#include "Util.h" #include "Settings.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/settings/GUIWindowSettingsScreenCalibration.cpp b/xbmc/settings/GUIWindowSettingsScreenCalibration.cpp index 6aaf61ba77..e1207444dc 100644 --- a/xbmc/settings/GUIWindowSettingsScreenCalibration.cpp +++ b/xbmc/settings/GUIWindowSettingsScreenCalibration.cpp @@ -117,6 +117,7 @@ bool CGUIWindowSettingsScreenCalibration::OnMessage(CGUIMessage& message) { case GUI_MSG_WINDOW_DEINIT: { + g_settings.UpdateCalibrations(); g_settings.Save(); g_graphicsContext.SetCalibrating(false); g_windowManager.ShowOverlay(OVERLAY_STATE_SHOWN); diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp index 35fd990910..3d6b19db37 100644 --- a/xbmc/settings/Settings.cpp +++ b/xbmc/settings/Settings.cpp @@ -35,7 +35,6 @@ #include "GUIInfoManager.h" #include "filesystem/MultiPathDirectory.h" #include "filesystem/SpecialProtocol.h" -#include "guilib/GUIBaseContainer.h" // for VIEW_TYPE enum #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogYesNo.h" #include "filesystem/Directory.h" @@ -102,7 +101,7 @@ void CSettings::Initialize() m_pictureExtensions = ".png|.jpg|.jpeg|.bmp|.gif|.ico|.tif|.tiff|.tga|.pcx|.cbz|.zip|.cbr|.rar|.m3u|.dng|.nef|.cr2|.crw|.orf|.arw|.erf|.3fr|.dcr|.x3f|.mef|.raf|.mrw|.pef|.sr2|.rss"; m_musicExtensions = ".nsv|.m4a|.flac|.aac|.strm|.pls|.rm|.rma|.mpa|.wav|.wma|.ogg|.mp3|.mp2|.m3u|.mod|.amf|.669|.dmf|.dsm|.far|.gdm|.imf|.it|.m15|.med|.okt|.s3m|.stm|.sfx|.ult|.uni|.xm|.sid|.ac3|.dts|.cue|.aif|.aiff|.wpl|.ape|.mac|.mpc|.mp+|.mpp|.shn|.zip|.rar|.wv|.nsf|.spc|.gym|.adx|.dsp|.adp|.ymf|.ast|.afc|.hps|.xsp|.xwav|.waa|.wvs|.wam|.gcm|.idsp|.mpdsp|.mss|.spt|.rsd|.mid|.kar|.sap|.cmc|.cmr|.dmc|.mpt|.mpd|.rmt|.tmc|.tm8|.tm2|.oga|.url|.pxml|.tta|.rss|.cm3|.cms|.dlt|.brstm|.wtv|.mka"; - m_videoExtensions = ".m4v|.3g2|.3gp|.nsv|.tp|.ts|.ty|.strm|.pls|.rm|.rmvb|.m3u|.ifo|.mov|.qt|.divx|.xvid|.bivx|.vob|.nrg|.img|.iso|.pva|.wmv|.asf|.asx|.ogm|.m2v|.avi|.bin|.dat|.mpg|.mpeg|.mp4|.mkv|.avc|.vp3|.svq3|.nuv|.viv|.dv|.fli|.flv|.rar|.001|.wpl|.zip|.vdr|.dvr-ms|.xsp|.mts|.m2t|.m2ts|.evo|.ogv|.sdp|.avs|.rec|.url|.pxml|.vc1|.h264|.rcv|.rss|.mpls|.webm|.bdmv|.wtv"; + m_videoExtensions = ".m4v|.3g2|.3gp|.nsv|.tp|.ts|.ty|.strm|.pls|.rm|.rmvb|.m3u|.m3u8|.ifo|.mov|.qt|.divx|.xvid|.bivx|.vob|.nrg|.img|.iso|.pva|.wmv|.asf|.asx|.ogm|.m2v|.avi|.bin|.dat|.mpg|.mpeg|.mp4|.mkv|.avc|.vp3|.svq3|.nuv|.viv|.dv|.fli|.flv|.rar|.001|.wpl|.zip|.vdr|.dvr-ms|.xsp|.mts|.m2t|.m2ts|.evo|.ogv|.sdp|.avs|.rec|.url|.pxml|.vc1|.h264|.rcv|.rss|.mpls|.webm|.bdmv|.wtv"; m_discStubExtensions = ".disc"; // internal music extensions m_musicExtensions += "|.sidstream|.oggstream|.nsfstream|.asapstream|.cdda"; @@ -489,60 +488,114 @@ bool CSettings::LoadCalibration(const TiXmlElement* pRoot, const CStdString& str const TiXmlElement *pResolution = pElement->FirstChildElement("resolution"); while (pResolution) { - // get the data for this resolution - CStdString mode; - XMLUtils::GetString(pResolution, "description", mode); - // find this resolution in our resolution vector - for (unsigned int res = 0; res < m_ResInfo.size(); res++) - { - if (res == RES_WINDOW) - continue; + // get the data for this calibration + RESOLUTION_INFO cal; - if (m_ResInfo[res].strMode == mode) - { // found, read in the rest of the information for this item - const TiXmlElement *pOverscan = pResolution->FirstChildElement("overscan"); - if (pOverscan) - { - GetInteger(pOverscan, "left", m_ResInfo[res].Overscan.left, 0, -m_ResInfo[res].iWidth / 4, m_ResInfo[res].iWidth / 4); - GetInteger(pOverscan, "top", m_ResInfo[res].Overscan.top, 0, -m_ResInfo[res].iHeight / 4, m_ResInfo[res].iHeight / 4); - GetInteger(pOverscan, "right", m_ResInfo[res].Overscan.right, m_ResInfo[res].iWidth, m_ResInfo[res].iWidth / 2, m_ResInfo[res].iWidth*3 / 2); - GetInteger(pOverscan, "bottom", m_ResInfo[res].Overscan.bottom, m_ResInfo[res].iHeight, m_ResInfo[res].iHeight / 2, m_ResInfo[res].iHeight*3 / 2); - } + XMLUtils::GetString(pResolution, "description", cal.strMode); + XMLUtils::GetInt(pResolution, "subtitles", cal.iSubtitles); + XMLUtils::GetFloat(pResolution, "pixelratio", cal.fPixelRatio); +#ifdef HAS_XRANDR + XMLUtils::GetFloat(pResolution, "refreshrate", cal.fRefreshRate); + XMLUtils::GetString(pResolution, "output", cal.strOutput); + XMLUtils::GetString(pResolution, "xrandrid", cal.strId); +#endif - // get the appropriate "safe graphics area" = 10% for 4x3, 3.5% for 16x9 - float fSafe; - if (res == RES_PAL_4x3 || res == RES_NTSC_4x3 || res == RES_PAL60_4x3 || res == RES_HDTV_480p_4x3) - fSafe = 0.1f; - else - fSafe = 0.035f; - - GetInteger(pResolution, "subtitles", m_ResInfo[res].iSubtitles, (int)((1 - fSafe)*m_ResInfo[res].iHeight), m_ResInfo[res].iHeight / 2, m_ResInfo[res].iHeight*5 / 4); - GetFloat(pResolution, "pixelratio", m_ResInfo[res].fPixelRatio, 128.0f / 117.0f, 0.5f, 2.0f); - /* CLog::Log(LOGDEBUG, " calibration for %s %ix%i", m_ResInfo[res].strMode, m_ResInfo[res].iWidth, m_ResInfo[res].iHeight); - CLog::Log(LOGDEBUG, " subtitle yposition:%i pixelratio:%03.3f offsets:(%i,%i)->(%i,%i)", - m_ResInfo[res].iSubtitles, m_ResInfo[res].fPixelRatio, - m_ResInfo[res].Overscan.left, m_ResInfo[res].Overscan.top, - m_ResInfo[res].Overscan.right, m_ResInfo[res].Overscan.bottom);*/ - } + const TiXmlElement *pOverscan = pResolution->FirstChildElement("overscan"); + if (pOverscan) + { + XMLUtils::GetInt(pOverscan, "left", cal.Overscan.left); + XMLUtils::GetInt(pOverscan, "top", cal.Overscan.top); + XMLUtils::GetInt(pOverscan, "right", cal.Overscan.right); + XMLUtils::GetInt(pOverscan, "bottom", cal.Overscan.bottom); } + + // mark calibration as not updated + // we must not delete those, resolution just might not be available + cal.iWidth = cal.iHeight = 0; + + // store calibration + m_Calibrations.push_back(cal); + // iterate around pResolution = pResolution->NextSiblingElement("resolution"); + } + ApplyCalibrations(); + return true; +} +void CSettings::ApplyCalibrations() +{ + // apply all calibrations to the resolutions + for (size_t i = 0; i < m_Calibrations.size(); ++i) + { + // find resolutions + for (size_t res = 0; res < m_ResInfo.size(); ++res) + { + if (res == RES_WINDOW) + continue; + if (m_Calibrations[i].strMode.Equals(m_ResInfo[res].strMode)) + { + // overscan + m_ResInfo[res].Overscan.left = m_Calibrations[i].Overscan.left; + if (m_ResInfo[res].Overscan.left < -m_ResInfo[res].iWidth/4) + m_ResInfo[res].Overscan.left = -m_ResInfo[res].iWidth/4; + if (m_ResInfo[res].Overscan.left > m_ResInfo[res].iWidth/4) + m_ResInfo[res].Overscan.left = m_ResInfo[res].iWidth/4; + + m_ResInfo[res].Overscan.top = m_Calibrations[i].Overscan.top; + if (m_ResInfo[res].Overscan.top < -m_ResInfo[res].iHeight/4) + m_ResInfo[res].Overscan.top = -m_ResInfo[res].iHeight/4; + if (m_ResInfo[res].Overscan.top > m_ResInfo[res].iHeight/4) + m_ResInfo[res].Overscan.top = m_ResInfo[res].iHeight/4; + + m_ResInfo[res].Overscan.right = m_Calibrations[i].Overscan.right; + if (m_ResInfo[res].Overscan.right < m_ResInfo[res].iWidth / 2) + m_ResInfo[res].Overscan.right = m_ResInfo[res].iWidth / 2; + if (m_ResInfo[res].Overscan.right > m_ResInfo[res].iWidth * 3/2) + m_ResInfo[res].Overscan.right = m_ResInfo[res].iWidth *3/2; + + m_ResInfo[res].Overscan.bottom = m_Calibrations[i].Overscan.bottom; + if (m_ResInfo[res].Overscan.bottom < m_ResInfo[res].iHeight / 2) + m_ResInfo[res].Overscan.bottom = m_ResInfo[res].iHeight / 2; + if (m_ResInfo[res].Overscan.bottom > m_ResInfo[res].iHeight * 3/2) + m_ResInfo[res].Overscan.bottom = m_ResInfo[res].iHeight * 3/2; + + m_ResInfo[res].iSubtitles = m_Calibrations[i].iSubtitles; + if (m_ResInfo[res].iSubtitles < m_ResInfo[res].iHeight / 2) + m_ResInfo[res].iSubtitles = m_ResInfo[res].iHeight / 2; + if (m_ResInfo[res].iSubtitles > m_ResInfo[res].iHeight* 5/4) + m_ResInfo[res].iSubtitles = m_ResInfo[res].iHeight* 5/4; + + m_ResInfo[res].fPixelRatio = m_Calibrations[i].fPixelRatio; + if (m_ResInfo[res].fPixelRatio < 0.5f) + m_ResInfo[res].fPixelRatio = 0.5f; + if (m_ResInfo[res].fPixelRatio > 2.0f) + m_ResInfo[res].fPixelRatio = 2.0f; + break; + } + } + } +} -/* Hmm, these stuff shouldn't be releaded, they should be used instead of our internal - id counter to select what resolution is affected by this settings -#ifdef HAS_XRANDR - const CStdString def(""); - CStdString val; - GetString(pResolution, "xrandrid", val, def); - strncpy(m_ResInfo[iRes].strId, val.c_str(), sizeof(m_ResInfo[iRes].strId)); - GetString(pResolution, "output", val, def); - strncpy(m_ResInfo[iRes].strOutput, val.c_str(), sizeof(m_ResInfo[iRes].strOutput)); - GetFloat(pResolution, "refreshrate", m_ResInfo[iRes].fRefreshRate, 0, 0, 200); -#endif -*/ +void CSettings::UpdateCalibrations() +{ + for (size_t res = RES_DESKTOP; res < m_ResInfo.size(); ++res) + { + // find calibration + bool found = false; + for (std::vector<RESOLUTION_INFO>::iterator it = m_Calibrations.begin(); it != m_Calibrations.end(); ++it) + { + if (it->strMode.Equals(m_ResInfo[res].strMode)) + { + // TODO: erase calibrations with default values + (*it) = m_ResInfo[res]; + found = true; + break; + } + } + if (!found) + m_Calibrations.push_back(m_ResInfo[res]); } - return true; } bool CSettings::SaveCalibration(TiXmlNode* pRootNode) const @@ -550,28 +603,28 @@ bool CSettings::SaveCalibration(TiXmlNode* pRootNode) const TiXmlElement xmlRootElement("resolutions"); TiXmlNode *pRoot = pRootNode->InsertEndChild(xmlRootElement); - // save WINDOW, DESKTOP and CUSTOM resolution - for (size_t i = RES_WINDOW ; i < m_ResInfo.size() ; i++) + // save calibrations + for (size_t i = 0 ; i < m_Calibrations.size() ; i++) { // Write the resolution tag TiXmlElement resElement("resolution"); TiXmlNode *pNode = pRoot->InsertEndChild(resElement); // Now write each of the pieces of information we need... - XMLUtils::SetString(pNode, "description", m_ResInfo[i].strMode); - XMLUtils::SetInt(pNode, "subtitles", m_ResInfo[i].iSubtitles); - XMLUtils::SetFloat(pNode, "pixelratio", m_ResInfo[i].fPixelRatio); + XMLUtils::SetString(pNode, "description", m_Calibrations[i].strMode); + XMLUtils::SetInt(pNode, "subtitles", m_Calibrations[i].iSubtitles); + XMLUtils::SetFloat(pNode, "pixelratio", m_Calibrations[i].fPixelRatio); #ifdef HAS_XRANDR - XMLUtils::SetFloat(pNode, "refreshrate", m_ResInfo[i].fRefreshRate); - XMLUtils::SetString(pNode, "output", m_ResInfo[i].strOutput); - XMLUtils::SetString(pNode, "xrandrid", m_ResInfo[i].strId); + XMLUtils::SetFloat(pNode, "refreshrate", m_Calibrations[i].fRefreshRate); + XMLUtils::SetString(pNode, "output", m_Calibrations[i].strOutput); + XMLUtils::SetString(pNode, "xrandrid", m_Calibrations[i].strId); #endif // create the overscan child TiXmlElement overscanElement("overscan"); TiXmlNode *pOverscanNode = pNode->InsertEndChild(overscanElement); - XMLUtils::SetInt(pOverscanNode, "left", m_ResInfo[i].Overscan.left); - XMLUtils::SetInt(pOverscanNode, "top", m_ResInfo[i].Overscan.top); - XMLUtils::SetInt(pOverscanNode, "right", m_ResInfo[i].Overscan.right); - XMLUtils::SetInt(pOverscanNode, "bottom", m_ResInfo[i].Overscan.bottom); + XMLUtils::SetInt(pOverscanNode, "left", m_Calibrations[i].Overscan.left); + XMLUtils::SetInt(pOverscanNode, "top", m_Calibrations[i].Overscan.top); + XMLUtils::SetInt(pOverscanNode, "right", m_Calibrations[i].Overscan.right); + XMLUtils::SetInt(pOverscanNode, "bottom", m_Calibrations[i].Overscan.bottom); } return true; } @@ -744,7 +797,7 @@ bool CSettings::LoadSettings(const CStdString& strSettingsFile) // Add the list of disc stub extensions (if any) to the list of video extensions if (!m_discStubExtensions.IsEmpty()) - g_settings.m_videoExtensions += "|" + m_discStubExtensions; + g_settings.m_videoExtensions += "|" + m_discStubExtensions; // Default players? CLog::Log(LOGNOTICE, "Default DVD Player: %s", g_advancedSettings.m_videoDefaultDVDPlayer.c_str()); diff --git a/xbmc/settings/Settings.h b/xbmc/settings/Settings.h index 82da646cbc..c526551783 100644 --- a/xbmc/settings/Settings.h +++ b/xbmc/settings/Settings.h @@ -335,6 +335,7 @@ public: int GetCurrentProfileId() const; std::vector<RESOLUTION_INFO> m_ResInfo; + std::vector<RESOLUTION_INFO> m_Calibrations; // utility functions for user data folders @@ -381,6 +382,9 @@ public: static bool GetString(const TiXmlElement* pRootElement, const char *strTagName, CStdString& strValue, const CStdString& strDefaultValue); bool GetString(const TiXmlElement* pRootElement, const char *strTagName, char *szValue, const CStdString& strDefaultValue); bool GetSource(const CStdString &category, const TiXmlNode *source, CMediaSource &share); + + void ApplyCalibrations(); + void UpdateCalibrations(); protected: void GetSources(const TiXmlElement* pRootElement, const CStdString& strTagName, VECSOURCES& items, CStdString& strDefault); bool SetSources(TiXmlNode *root, const char *section, const VECSOURCES &shares, const char *defaultPath); diff --git a/xbmc/settings/SettingsControls.cpp b/xbmc/settings/SettingsControls.cpp index a84630a280..760d8a78d5 100644 --- a/xbmc/settings/SettingsControls.cpp +++ b/xbmc/settings/SettingsControls.cpp @@ -23,10 +23,8 @@ #include "guilib/GUIRadioButtonControl.h" #include "guilib/GUISpinControlEx.h" #include "guilib/GUIEditControl.h" -#include "dialogs/GUIDialogNumeric.h" #include "Util.h" #include "dialogs/GUIDialogOK.h" -#include "dialogs/GUIDialogKeyboard.h" #include "GUISettings.h" #include "guilib/GUIImage.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/storage/IoSupport.cpp b/xbmc/storage/IoSupport.cpp index e5dc4ecca2..3f55710b2e 100644 --- a/xbmc/storage/IoSupport.cpp +++ b/xbmc/storage/IoSupport.cpp @@ -129,10 +129,14 @@ DWORD CIoSupport::GetTrayState() HRESULT CIoSupport::ToggleTray() { +#if defined(TARGET_WINDOWS) + return CWIN32Util::ToggleTray(); +#else if (GetTrayState() == TRAY_OPEN || GetTrayState() == DRIVE_OPEN) return CloseTray(); else return EjectTray(); +#endif } HANDLE CIoSupport::OpenCDROM() diff --git a/xbmc/storage/MediaManager.cpp b/xbmc/storage/MediaManager.cpp index c5db51b8f8..fa67be1da8 100644 --- a/xbmc/storage/MediaManager.cpp +++ b/xbmc/storage/MediaManager.cpp @@ -24,10 +24,10 @@ #include "guilib/LocalizeStrings.h" #include "IoSupport.h" #include "URL.h" -#include "Util.h" #include "utils/URIUtils.h" #ifdef _WIN32 #include "WIN32Util.h" +#include "utils/CharsetConverter.h" #endif #include "guilib/GUIWindowManager.h" #ifdef HAS_DVD_DRIVE @@ -56,6 +56,8 @@ #if defined(TARGET_DARWIN) #include "osx/DarwinStorageProvider.h" +#elif defined(TARGET_ANDROID) +#include "android/AndroidStorageProvider.h" #elif defined(_LINUX) #include "linux/LinuxStorageProvider.h" #elif _WIN32 @@ -89,6 +91,8 @@ void CMediaManager::Initialize() { #if defined(TARGET_DARWIN) m_platformStorage = new CDarwinStorageProvider(); + #elif defined(TARGET_ANDROID) + m_platformStorage = new CAndroidStorageProvider(); #elif defined(_LINUX) m_platformStorage = new CLinuxStorageProvider(); #elif _WIN32 @@ -463,12 +467,13 @@ CStdString CMediaManager::GetDiskLabel(const CStdString& devicePath) return ""; CStdString strDevice = TranslateDevicePath(devicePath); - char cVolumenName[128]; - char cFSName[128]; + WCHAR cVolumenName[128]; + WCHAR cFSName[128]; URIUtils::AddSlashAtEnd(strDevice); - if(GetVolumeInformation(strDevice.c_str(), cVolumenName, 127, NULL, NULL, NULL, cFSName, 127)==0) + if(GetVolumeInformationW(CStdStringW(strDevice).c_str(), cVolumenName, 127, NULL, NULL, NULL, cFSName, 127)==0) return ""; - return CStdString(cVolumenName).TrimRight(" "); + g_charsetConverter.wToUTF8(cVolumenName, strDevice); + return strDevice.TrimRight(" "); #else return MEDIA_DETECT::CDetectDVDMedia::GetDVDLabel(); #endif diff --git a/xbmc/storage/MediaManager.h b/xbmc/storage/MediaManager.h index 1b7ae821c3..90c3156ebe 100644 --- a/xbmc/storage/MediaManager.h +++ b/xbmc/storage/MediaManager.h @@ -25,7 +25,6 @@ #ifdef HAS_DVD_DRIVE #include "cdioSupport.h" #endif -#include "URL.h" #include "utils/Job.h" #include "IStorageProvider.h" #include "threads/CriticalSection.h" diff --git a/xbmc/storage/android/AndroidStorageProvider.cpp b/xbmc/storage/android/AndroidStorageProvider.cpp new file mode 100644 index 0000000000..7a215118cf --- /dev/null +++ b/xbmc/storage/android/AndroidStorageProvider.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "AndroidStorageProvider.h" +#include "android/activity/XBMCApp.h" +#include "guilib/LocalizeStrings.h" +#include "filesystem/File.h" + +//#include "utils/RegExp.h" +//#include "utils/StdString.h" +//#include "Util.h" + +void CAndroidStorageProvider::GetLocalDrives(VECSOURCES &localDrives) +{ + CMediaSource share; + + // external directory + std::string path; + if (CXBMCApp::GetExternalStorage(path) && !path.empty() && XFILE::CFile::Exists(path)) + { + share.strPath = path; + share.strName = g_localizeStrings.Get(21456); + share.m_ignore = true; + localDrives.push_back(share); + } + + // root directory + share.strPath = "/"; + share.strName = g_localizeStrings.Get(21453); + localDrives.push_back(share); +} + +void CAndroidStorageProvider::GetRemovableDrives(VECSOURCES &removableDrives) +{ + // TODO +} + +std::vector<CStdString> CAndroidStorageProvider::GetDiskUsage() +{ + std::vector<CStdString> result; + + std::string usage; + // add header + CXBMCApp::GetStorageUsage("", usage); + result.push_back(usage); + + usage.clear(); + // add rootfs + if (CXBMCApp::GetStorageUsage("/", usage) && !usage.empty()) + result.push_back(usage); + + usage.clear(); + // add external storage if available + std::string path; + if (CXBMCApp::GetExternalStorage(path) && !path.empty() && + CXBMCApp::GetStorageUsage(path, usage) && !usage.empty()) + result.push_back(usage); + + return result; +} + +bool CAndroidStorageProvider::Eject(CStdString mountpath) +{ + return false; +} + +bool CAndroidStorageProvider::PumpDriveChangeEvents(IStorageEventsCallback *callback) +{ + return false; +} diff --git a/xbmc/storage/android/AndroidStorageProvider.h b/xbmc/storage/android/AndroidStorageProvider.h new file mode 100644 index 0000000000..ea934c4145 --- /dev/null +++ b/xbmc/storage/android/AndroidStorageProvider.h @@ -0,0 +1,41 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "storage/IStorageProvider.h" + +class CAndroidStorageProvider : public IStorageProvider +{ +public: + CAndroidStorageProvider() { } + virtual ~CAndroidStorageProvider() { } + + virtual void Initialize() { } + virtual void Stop() { } + + virtual void GetLocalDrives(VECSOURCES &localDrives); + virtual void GetRemovableDrives(VECSOURCES &removableDrives); + + virtual bool Eject(CStdString mountpath); + + virtual std::vector<CStdString> GetDiskUsage(); + + virtual bool PumpDriveChangeEvents(IStorageEventsCallback *callback); +}; diff --git a/xbmc/storage/android/Makefile b/xbmc/storage/android/Makefile new file mode 100644 index 0000000000..3899cfcec3 --- /dev/null +++ b/xbmc/storage/android/Makefile @@ -0,0 +1,6 @@ +SRCS=AndroidStorageProvider.cpp + +LIB=storage_android.a + +include ../../../Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/storage/windows/Win32StorageProvider.cpp b/xbmc/storage/windows/Win32StorageProvider.cpp index a46e07c52e..af0c66882b 100644 --- a/xbmc/storage/windows/Win32StorageProvider.cpp +++ b/xbmc/storage/windows/Win32StorageProvider.cpp @@ -25,7 +25,7 @@ #include "storage/MediaManager.h" #include "utils/JobManager.h" -bool CWin32StorageProvider::event = false; +bool CWin32StorageProvider::xbevent = false; void CWin32StorageProvider::Initialize() { @@ -76,8 +76,8 @@ std::vector<CStdString> CWin32StorageProvider::GetDiskUsage() bool CWin32StorageProvider::PumpDriveChangeEvents(IStorageEventsCallback *callback) { - bool b = event; - event = false; + bool b = xbevent; + xbevent = false; return b; } diff --git a/xbmc/storage/windows/Win32StorageProvider.h b/xbmc/storage/windows/Win32StorageProvider.h index 088a060d99..9a60eec135 100644 --- a/xbmc/storage/windows/Win32StorageProvider.h +++ b/xbmc/storage/windows/Win32StorageProvider.h @@ -39,8 +39,8 @@ public: virtual bool PumpDriveChangeEvents(IStorageEventsCallback *callback); - static void SetEvent() { event = true; } - static bool event; + static void SetEvent() { xbevent = true; } + static bool xbevent; }; class CDetectDisc : public CJob diff --git a/xbmc/system.h b/xbmc/system.h index 918ccf4867..7104fc7072 100644 --- a/xbmc/system.h +++ b/xbmc/system.h @@ -228,6 +228,11 @@ #include "PlatformInclude.h" #endif +#if defined(TARGET_ANDROID) +#undef HAS_LIRC +#undef HAS_LCD +#endif + // EGL detected. Dont use GLX! #ifdef HAVE_LIBEGL #undef HAS_GLX diff --git a/xbmc/threads/Atomics.cpp b/xbmc/threads/Atomics.cpp index 2fc289a092..edf3d630d0 100644 --- a/xbmc/threads/Atomics.cpp +++ b/xbmc/threads/Atomics.cpp @@ -177,7 +177,7 @@ long AtomicIncrement(volatile long* pAddr) : "cc", "xer", "memory"); return val; -#elif defined(__arm__) +#elif defined(__arm__) && !defined(__ARM_ARCH_5__) register long val; asm volatile ( "dmb ish \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after @@ -255,7 +255,7 @@ long AtomicAdd(volatile long* pAddr, long amount) : "cc", "memory"); return val; -#elif defined(__arm__) +#elif defined(__arm__) && !defined(__ARM_ARCH_5__) register long val; asm volatile ( "dmb ish \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after diff --git a/xbmc/threads/Makefile b/xbmc/threads/Makefile index 2853248fe3..d0bd2951d7 100644 --- a/xbmc/threads/Makefile +++ b/xbmc/threads/Makefile @@ -2,6 +2,7 @@ SRCS=Atomics.cpp \ Event.cpp \ LockFree.cpp \ Thread.cpp \ + Timer.cpp \ SystemClock.cpp \ platform/Implementation.cpp diff --git a/xbmc/threads/Thread.cpp b/xbmc/threads/Thread.cpp index 0fe8daef16..9faac80e5f 100644 --- a/xbmc/threads/Thread.cpp +++ b/xbmc/threads/Thread.cpp @@ -97,7 +97,7 @@ void CThread::Create(bool bAutoDelete, unsigned stacksize) SpawnThread(stacksize); } -bool CThread::IsRunning() +bool CThread::IsRunning() const { return m_ThreadId ? true : false; } diff --git a/xbmc/threads/Thread.h b/xbmc/threads/Thread.h index c44e880a7c..e071a88049 100644 --- a/xbmc/threads/Thread.h +++ b/xbmc/threads/Thread.h @@ -64,7 +64,7 @@ public: bool SetPrioritySched_RR(int iPriority); bool IsAutoDelete() const; virtual void StopThread(bool bWait = true); - bool IsRunning(); + bool IsRunning() const; // ----------------------------------------------------------------------------------- // These are platform specific and can be found in ./platform/[platform]/ThreadImpl.cpp diff --git a/xbmc/threads/Timer.cpp b/xbmc/threads/Timer.cpp new file mode 100644 index 0000000000..4709ee1705 --- /dev/null +++ b/xbmc/threads/Timer.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <algorithm> + +#include "Timer.h" +#include "SystemClock.h" +#include "utils/log.h" + +CTimer::CTimer(ITimerCallback *callback) + : CThread("CTimer"), + m_callback(callback), + m_timeout(0), + m_interval(false), + m_endTime(0) +{ } + +CTimer::~CTimer() +{ + Stop(true); +} + +bool CTimer::Start(uint32_t timeout, bool interval /* = false */) +{ + if (m_callback == NULL || timeout == 0 || IsRunning()) + { + CLog::Log(LOGWARNING, "CTimer: can't start timer"); + return false; + } + + m_timeout = timeout; + m_interval = interval; + + CLog::Log(LOGDEBUG, "CTimer: starting for %d ms %s", m_timeout, m_interval ? "(interval)" : ""); + Create(); + return true; +} + +bool CTimer::Stop(bool wait /* = false */) +{ + if (!IsRunning()) + return false; + + CLog::Log(LOGDEBUG, "CTimer: stopping %s", wait ? "(wait)" : ""); + m_bStop = true; + m_eventTimeout.Set(); + StopThread(wait); + + return true; +} + +float CTimer::GetElapsedSeconds() const +{ + return GetElapsedMilliseconds() / 1000.0f; +} + +float CTimer::GetElapsedMilliseconds() const +{ + if (!IsRunning()) + return 0.0f; + + return (float)(XbmcThreads::SystemClockMillis() - (m_endTime - m_timeout)); +} + +void CTimer::Process() +{ + uint32_t currentTime = XbmcThreads::SystemClockMillis(); + m_endTime = currentTime + m_timeout; + + while (!m_bStop) + { + // wait the necessary time + if (!m_eventTimeout.WaitMSec(m_endTime - currentTime)) + { + currentTime = XbmcThreads::SystemClockMillis(); + if (m_endTime <= currentTime) + { + CLog::Log(LOGDEBUG, "CTimer: timeout"); + // execute OnTimeout() callback + m_callback->OnTimeout(); + + // stop if this is not an interval timer + if (!m_interval) + break; + + CLog::Log(LOGDEBUG, "CTimer: restart"); + m_endTime = currentTime + m_timeout; + } + } + } + + CLog::Log(LOGDEBUG, "CTimer: finished"); +}
\ No newline at end of file diff --git a/xbmc/threads/Timer.h b/xbmc/threads/Timer.h new file mode 100644 index 0000000000..e6c98b9065 --- /dev/null +++ b/xbmc/threads/Timer.h @@ -0,0 +1,56 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "Event.h" +#include "Thread.h" + +class ITimerCallback +{ +public: + virtual ~ITimerCallback() { } + + virtual void OnTimeout() = 0; +}; + +class CTimer : protected CThread +{ +public: + CTimer(ITimerCallback *callback); + virtual ~CTimer(); + + bool Start(uint32_t timeout, bool interval = false); + bool Stop(bool wait = false); + + bool IsRunning() const { return CThread::IsRunning(); } + + float GetElapsedSeconds() const; + float GetElapsedMilliseconds() const; + +protected: + virtual void Process(); + +private: + ITimerCallback *m_callback; + uint32_t m_timeout; + bool m_interval; + uint32_t m_endTime; + CEvent m_eventTimeout; +}; diff --git a/xbmc/threads/platform/pthreads/ThreadImpl.cpp b/xbmc/threads/platform/pthreads/ThreadImpl.cpp index 6e49f4fcad..0678d3020e 100644 --- a/xbmc/threads/platform/pthreads/ThreadImpl.cpp +++ b/xbmc/threads/platform/pthreads/ThreadImpl.cpp @@ -20,7 +20,11 @@ */ #include <limits.h> +#if defined(TARGET_ANDROID) +#include <unistd.h> +#else #include <sys/syscall.h> +#endif #include <sys/resource.h> #include <string.h> #ifdef __FreeBSD__ @@ -38,8 +42,10 @@ void CThread::SpawnThread(unsigned stacksize) { pthread_attr_t attr; pthread_attr_init(&attr); +#if !defined(TARGET_ANDROID) // http://code.google.com/p/android/issues/detail?id=7808 if (stacksize > PTHREAD_STACK_MIN) pthread_attr_setstacksize(&attr, stacksize); +#endif pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (pthread_create(&m_ThreadId, &attr, (void*(*)(void*))staticThread, this) != 0) { @@ -60,6 +66,8 @@ void CThread::SetThreadInfo() #else m_ThreadOpaque.LwpId = pthread_getthreadid_np(); #endif +#elif defined(TARGET_ANDROID) + m_ThreadOpaque.LwpId = gettid(); #else m_ThreadOpaque.LwpId = syscall(SYS_gettid); #endif @@ -70,10 +78,29 @@ void CThread::SetThreadInfo() #endif #endif - // start thread with nice level of appication - int appNice = getpriority(PRIO_PROCESS, getpid()); - if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, appNice) != 0) - if (logger) logger->Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno)); +#ifdef RLIMIT_NICE + // get user max prio + struct rlimit limit; + int userMaxPrio; + if (getrlimit(RLIMIT_NICE, &limit) == 0) + { + userMaxPrio = limit.rlim_cur - 20; + if (userMaxPrio < 0) + userMaxPrio = 0; + } + else + userMaxPrio = 0; + + // if the user does not have an entry in limits.conf the following + // call will fail + if (userMaxPrio > 0) + { + // start thread with nice level of appication + int appNice = getpriority(PRIO_PROCESS, getpid()); + if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, appNice) != 0) + if (logger) logger->Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno)); + } +#endif } ThreadIdentifier CThread::GetCurrentThreadId() @@ -129,6 +156,9 @@ bool CThread::SetPriority(const int iPriority) if (getrlimit(RLIMIT_NICE, &limit) == 0) { userMaxPrio = limit.rlim_cur - 20; + // is a user has no entry in limits.conf rlim_cur is zero + if (userMaxPrio < 0) + userMaxPrio = 0; } else userMaxPrio = 0; diff --git a/xbmc/utils/AlarmClock.cpp b/xbmc/utils/AlarmClock.cpp index 6ca327fe61..aff7da38c8 100644 --- a/xbmc/utils/AlarmClock.cpp +++ b/xbmc/utils/AlarmClock.cpp @@ -20,7 +20,7 @@ */ #include "AlarmClock.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "guilib/LocalizeStrings.h" #include "threads/SingleLock.h" #include "log.h" @@ -114,7 +114,7 @@ void CAlarmClock::Stop(const CStdString& strName, bool bSilent /* false */) } else { - g_application.getApplicationMessenger().ExecBuiltIn(iter->second.m_strCommand); + CApplicationMessenger::Get().ExecBuiltIn(iter->second.m_strCommand); if (iter->second.m_loop) { iter->second.watch.Reset(); diff --git a/xbmc/utils/AliasShortcutUtils.cpp b/xbmc/utils/AliasShortcutUtils.cpp index 0031deafc3..06070604bb 100644 --- a/xbmc/utils/AliasShortcutUtils.cpp +++ b/xbmc/utils/AliasShortcutUtils.cpp @@ -26,7 +26,6 @@ #else #endif -#include "Util.h" #include "AliasShortcutUtils.h" bool IsAliasShortcut(CStdString &path) diff --git a/xbmc/utils/AsyncFileCopy.cpp b/xbmc/utils/AsyncFileCopy.cpp index 44e7043b2a..4a5fb8a0a8 100644 --- a/xbmc/utils/AsyncFileCopy.cpp +++ b/xbmc/utils/AsyncFileCopy.cpp @@ -25,6 +25,7 @@ #include "guilib/GUIWindowManager.h" #include "log.h" #include "utils/TimeUtils.h" +#include "URL.h" CAsyncFileCopy::CAsyncFileCopy() : CThread("CAsyncFileCopy") { diff --git a/xbmc/utils/CPUInfo.cpp b/xbmc/utils/CPUInfo.cpp index 7be48907ed..88ba57c196 100644 --- a/xbmc/utils/CPUInfo.cpp +++ b/xbmc/utils/CPUInfo.cpp @@ -20,6 +20,7 @@ */ #include "CPUInfo.h" +#include "Temperature.h" #include <string> #include <string.h> @@ -31,6 +32,18 @@ #endif #endif +#if defined(TARGET_LINUX) && defined(__ARM_NEON__) && !defined(TARGET_ANDROID) +#include <fcntl.h> +#include <unistd.h> +#include <elf.h> +#include <linux/auxvec.h> +#include <asm/hwcap.h> +#endif + +#if defined(TARGET_ANDROID) +#include "android/activity/AndroidFeatures.h" +#endif + #ifdef _WIN32 #include <intrin.h> @@ -70,8 +83,8 @@ using namespace std; -// In seconds -#define MINIMUM_TIME_BETWEEN_READS 2 +// In milliseconds +#define MINIMUM_TIME_BETWEEN_READS 500 #ifdef _WIN32 /* replacement gettimeofday implementation, copy from dvdnav_internal.h */ @@ -238,8 +251,9 @@ CCPUInfo::CCPUInfo(void) m_cpuModel = "Unknown"; } - readProcStat(m_userTicks, m_niceTicks, m_systemTicks, m_idleTicks, m_ioTicks); #endif + readProcStat(m_userTicks, m_niceTicks, m_systemTicks, m_idleTicks, m_ioTicks); + m_nextUsedReadTime.Set(MINIMUM_TIME_BETWEEN_READS); ReadCPUFeatures(); @@ -247,6 +261,9 @@ CCPUInfo::CCPUInfo(void) if (m_cpuFeatures & CPU_FEATURE_SSE) m_cpuFeatures |= CPU_FEATURE_MMX2; + if (HasNeon()) + m_cpuFeatures |= CPU_FEATURE_NEON; + } CCPUInfo::~CCPUInfo() @@ -263,10 +280,8 @@ CCPUInfo::~CCPUInfo() int CCPUInfo::getUsedPercentage() { - if (m_lastReadTime + MINIMUM_TIME_BETWEEN_READS > time(NULL)) - { + if (!m_nextUsedReadTime.IsTimePast()) return m_lastUsedPercentage; - } unsigned long long userTicks; unsigned long long niceTicks; @@ -275,9 +290,7 @@ int CCPUInfo::getUsedPercentage() unsigned long long ioTicks; if (!readProcStat(userTicks, niceTicks, systemTicks, idleTicks, ioTicks)) - { - return 0; - } + return m_lastUsedPercentage; userTicks -= m_userTicks; niceTicks -= m_niceTicks; @@ -302,6 +315,7 @@ int CCPUInfo::getUsedPercentage() m_ioTicks += ioTicks; m_lastUsedPercentage = result; + m_nextUsedReadTime.Set(MINIMUM_TIME_BETWEEN_READS); return result; } @@ -323,9 +337,7 @@ float CCPUInfo::getCPUFrequency() ret = RegQueryValueEx(hKey,"~MHz", NULL, NULL, (LPBYTE)&dwMHz, &dwSize); RegCloseKey(hKey); if(ret == 0) - { return float(dwMHz); - } else return 0.f; #else @@ -347,7 +359,7 @@ float CCPUInfo::getCPUFrequency() #endif } -CTemperature CCPUInfo::getTemperature() +bool CCPUInfo::getTemperature(CTemperature& temperature) { int value = 0, ret = 0; @@ -355,8 +367,10 @@ CTemperature CCPUInfo::getTemperature() FILE *p = NULL; CStdString cmd = g_advancedSettings.m_cpuTempCmd; + temperature.SetState(CTemperature::invalid); + if (cmd.IsEmpty() && m_fProcTemperature == NULL) - return CTemperature(); + return false; if (!cmd.IsEmpty()) { @@ -388,13 +402,16 @@ CTemperature CCPUInfo::getTemperature() } if (ret != 2) - return CTemperature(); + return false; if (scale == 'C' || scale == 'c') - return CTemperature::CreateFromCelsius(value); - if (scale == 'F' || scale == 'f') - return CTemperature::CreateFromFahrenheit(value); - return CTemperature(); + temperature = CTemperature::CreateFromCelsius(value); + else if (scale == 'F' || scale == 'f') + temperature = CTemperature::CreateFromFahrenheit(value); + else + return false; + + return true; } bool CCPUInfo::HasCoreId(int nCoreId) const @@ -483,7 +500,10 @@ bool CCPUInfo::readProcStat(unsigned long long& user, unsigned long long& nice, coreIO -= iter->second.m_io; double total = (double)(coreUser + coreNice + coreSystem + coreIdle + coreIO); - iter->second.m_fPct = ((double)(coreUser + coreNice + coreSystem) * 100.0) / total; + if(total == 0.0f) + iter->second.m_fPct = 0.0f; + else + iter->second.m_fPct = ((double)(coreUser + coreNice + coreSystem) * 100.0) / total; iter->second.m_user += coreUser; iter->second.m_nice += coreNice; @@ -494,7 +514,6 @@ bool CCPUInfo::readProcStat(unsigned long long& user, unsigned long long& nice, } #endif - m_lastReadTime = time(NULL); return true; } @@ -604,8 +623,44 @@ void CCPUInfo::ReadCPUFeatures() #endif } -CCPUInfo g_cpuInfo; +bool CCPUInfo::HasNeon() +{ + static int has_neon = -1; +#if defined (TARGET_ANDROID) + if (has_neon == -1) + has_neon = (CAndroidFeatures::HasNeon()) ? 1 : 0; + +#elif defined(TARGET_DARWIN_IOS) + has_neon = 1; + +#elif defined(TARGET_LINUX) && defined(__ARM_NEON__) + if (has_neon == -1) + { + has_neon = 0; + // why are we not looking at the Features in + // /proc/cpuinfo for neon ? + int fd = open("/proc/self/auxv", O_RDONLY); + if (fd >= 0) + { + Elf32_auxv_t auxv; + while (read(fd, &auxv, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t)) + { + if (auxv.a_type == AT_HWCAP) + { + has_neon = (auxv.a_un.a_val & HWCAP_NEON) ? 1 : 0; + break; + } + } + close(fd); + } + } +#endif + + return has_neon == 1; +} + +CCPUInfo g_cpuInfo; /* int main() { diff --git a/xbmc/utils/CPUInfo.h b/xbmc/utils/CPUInfo.h index 18a5928049..4efc1bdb9c 100644 --- a/xbmc/utils/CPUInfo.h +++ b/xbmc/utils/CPUInfo.h @@ -25,9 +25,11 @@ #include <stdio.h> #include <time.h> #include "Archive.h" -#include "Temperature.h" #include <string> #include <map> +#include "threads/SystemClock.h" + +class CTemperature; #define CPU_FEATURE_MMX 1 << 0 #define CPU_FEATURE_MMX2 1 << 1 @@ -40,6 +42,7 @@ #define CPU_FEATURE_3DNOW 1 << 8 #define CPU_FEATURE_3DNOWEXT 1 << 9 #define CPU_FEATURE_ALTIVEC 1 << 10 +#define CPU_FEATURE_NEON 1 << 11 struct CoreInfo { @@ -65,7 +68,7 @@ public: int getUsedPercentage(); int getCPUCount() { return m_cpuCount; } float getCPUFrequency(); - CTemperature getTemperature(); + bool getTemperature(CTemperature& temperature); std::string& getCPUModel() { return m_cpuModel; } const CoreInfo &GetCoreInfo(int nCoreId); @@ -79,6 +82,7 @@ private: bool readProcStat(unsigned long long& user, unsigned long long& nice, unsigned long long& system, unsigned long long& idle, unsigned long long& io); void ReadCPUFeatures(); + bool HasNeon(); FILE* m_fProcStat; FILE* m_fProcTemperature; @@ -91,7 +95,7 @@ private: unsigned long long m_ioTicks; int m_lastUsedPercentage; - time_t m_lastReadTime; + XbmcThreads::EndTime m_nextUsedReadTime; std::string m_cpuModel; int m_cpuCount; unsigned int m_cpuFeatures; diff --git a/xbmc/utils/CharsetConverter.cpp b/xbmc/utils/CharsetConverter.cpp index 150e198735..b9e0deb713 100644 --- a/xbmc/utils/CharsetConverter.cpp +++ b/xbmc/utils/CharsetConverter.cpp @@ -41,6 +41,13 @@ #define UTF8_SOURCE "UTF-8" #pragma comment(lib, "libfribidi.lib") #pragma comment(lib, "libiconv.lib") +#elif defined(TARGET_ANDROID) + #define UTF8_SOURCE "UTF-8" +#ifdef __BIG_ENDIAN__ + #define WCHAR_CHARSET "UTF-32BE" +#else + #define WCHAR_CHARSET "UTF-32LE" +#endif #else #define WCHAR_CHARSET "WCHAR_T" #define UTF8_SOURCE "UTF-8" diff --git a/xbmc/utils/DatabaseUtils.cpp b/xbmc/utils/DatabaseUtils.cpp index d194e75926..d9c838b100 100644 --- a/xbmc/utils/DatabaseUtils.cpp +++ b/xbmc/utils/DatabaseUtils.cpp @@ -125,6 +125,20 @@ std::string DatabaseUtils::GetField(Field field, MediaType mediaType, DatabaseQu else if (field == FieldGenre) return "songview.strGenre"; else if (field == FieldDateAdded && queryPart == DatabaseQueryPartOrderBy) return "songview.idSong"; // only used for order clauses } + else if (mediaType == MediaTypeArtist) + { + if (field == FieldId) return "artistview.idArtist"; + else if (field == FieldArtist) return "artistview.strArtist"; + else if (field == FieldGenre) return "artistview.strGenres"; + else if (field == FieldMoods) return "artistview.strMoods"; + else if (field == FieldStyles) return "artistview.strStyles"; + else if (field == FieldInstruments) return "artistview.strInstruments"; + else if (field == FieldBiography) return "artistview.strBiography"; + else if (field == FieldBorn) return "artistview.strBorn"; + else if (field == FieldBandFormed) return "artistview.strFormed"; + else if (field == FieldDisbanded) return "artistview.strDisbanded"; + else if (field == FieldDied) return "artistview.strDied"; + } else if (mediaType == MediaTypeMusicVideo) { CStdString result; @@ -177,6 +191,7 @@ std::string DatabaseUtils::GetField(Field field, MediaType mediaType, DatabaseQu else if (field == FieldTime) result.Format("movieview.c%02d", VIDEODB_ID_RUNTIME); else if (field == FieldMPAA) result.Format("movieview.c%02d", VIDEODB_ID_MPAA); else if (field == FieldTop250) result.Format("movieview.c%02d", VIDEODB_ID_TOP250); + else if (field == FieldSet) return "movieview.strSet"; else if (field == FieldGenre) result.Format("movieview.c%02d", VIDEODB_ID_GENRE); else if (field == FieldDirector) result.Format("movieview.c%02d", VIDEODB_ID_DIRECTOR); else if (field == FieldStudio) result.Format("movieview.c%02d", VIDEODB_ID_STUDIOS); @@ -235,6 +250,8 @@ std::string DatabaseUtils::GetField(Field field, MediaType mediaType, DatabaseQu else if (field == FieldDirector) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_DIRECTOR); else if (field == FieldSeason) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_SEASON); else if (field == FieldEpisodeNumber) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_EPISODE); + else if (field == FieldEpisodeNumberSpecialSort) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_SORTEPISODE); + else if (field == FieldSeasonSpecialSort) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_SORTSEASON); else if (field == FieldFilename) return "episodeview.strFilename"; else if (field == FieldPath) return "episodeview.strPath"; else if (field == FieldPlaycount) return "episodeview.playCount"; @@ -296,6 +313,20 @@ int DatabaseUtils::GetFieldIndex(Field field, MediaType mediaType) else if (field == FieldGenre) return CMusicDatabase::song_strGenres; else if (field == FieldArtist || field == FieldAlbumArtist) return CMusicDatabase::song_strArtists; } + else if (mediaType == MediaTypeArtist) + { + if (field == FieldId) return CMusicDatabase::artist_idArtist; + else if (field == FieldArtist) return CMusicDatabase::artist_strArtist; + else if (field == FieldGenre) return CMusicDatabase::artist_strGenres; + else if (field == FieldMoods) return CMusicDatabase::artist_strMoods; + else if (field == FieldStyles) return CMusicDatabase::artist_strStyles; + else if (field == FieldInstruments) return CMusicDatabase::artist_strInstruments; + else if (field == FieldBiography) return CMusicDatabase::artist_strBiography; + else if (field == FieldBorn) return CMusicDatabase::artist_strBorn; + else if (field == FieldBandFormed) return CMusicDatabase::artist_strFormed; + else if (field == FieldDisbanded) return CMusicDatabase::artist_strDisbanded; + else if (field == FieldDied) return CMusicDatabase::artist_strDied; + } else if (mediaType == MediaTypeMusicVideo) { if (field == FieldId) return 0; @@ -309,11 +340,11 @@ int DatabaseUtils::GetFieldIndex(Field field, MediaType mediaType) else if (field == FieldArtist) index = VIDEODB_ID_MUSICVIDEO_ARTIST; else if (field == FieldGenre) index = VIDEODB_ID_MUSICVIDEO_GENRE; else if (field == FieldTrackNumber) index = VIDEODB_ID_MUSICVIDEO_TRACK; - else if (field == FieldFilename) return VIDEODB_DETAILS_FILE; - else if (field == FieldPath) return VIDEODB_DETAILS_PATH; - else if (field == FieldPlaycount) return VIDEODB_DETAILS_PLAYCOUNT; - else if (field == FieldLastPlayed) return VIDEODB_DETAILS_LASTPLAYED; - else if (field == FieldDateAdded) return VIDEODB_DETAILS_DATEADDED; + else if (field == FieldFilename) return VIDEODB_DETAILS_MUSICVIDEO_FILE; + else if (field == FieldPath) return VIDEODB_DETAILS_MUSICVIDEO_PATH; + else if (field == FieldPlaycount) return VIDEODB_DETAILS_MUSICVIDEO_PLAYCOUNT; + else if (field == FieldLastPlayed) return VIDEODB_DETAILS_MUSICVIDEO_LASTPLAYED; + else if (field == FieldDateAdded) return VIDEODB_DETAILS_MUSICVIDEO_DATEADDED; if (index < 0) return index; @@ -322,8 +353,7 @@ int DatabaseUtils::GetFieldIndex(Field field, MediaType mediaType) // the first field is the item's ID and the second is the item's file ID index += 2; } - else - if (mediaType == MediaTypeMovie) + else if (mediaType == MediaTypeMovie) { if (field == FieldId) return 0; else if (field == FieldTitle) index = VIDEODB_ID_TITLE; @@ -335,20 +365,20 @@ int DatabaseUtils::GetFieldIndex(Field field, MediaType mediaType) else if (field == FieldRating) index = VIDEODB_ID_RATING; else if (field == FieldWriter) index = VIDEODB_ID_CREDITS; else if (field == FieldYear) index = VIDEODB_ID_YEAR; - else if (field == FieldSortTitle) index = VIDEODB_ID_SORTTITLE; else if (field == FieldTime) index = VIDEODB_ID_RUNTIME; else if (field == FieldMPAA) index = VIDEODB_ID_MPAA; else if (field == FieldTop250) index = VIDEODB_ID_TOP250; + else if (field == FieldSet) return VIDEODB_DETAILS_MOVIE_SET_NAME; else if (field == FieldGenre) index = VIDEODB_ID_GENRE; else if (field == FieldDirector) index = VIDEODB_ID_DIRECTOR; else if (field == FieldStudio) index = VIDEODB_ID_STUDIOS; else if (field == FieldTrailer) index = VIDEODB_ID_TRAILER; else if (field == FieldCountry) index = VIDEODB_ID_COUNTRY; - else if (field == FieldFilename) index = VIDEODB_DETAILS_FILE; - else if (field == FieldPath) return VIDEODB_DETAILS_PATH; - else if (field == FieldPlaycount) return VIDEODB_DETAILS_PLAYCOUNT; - else if (field == FieldLastPlayed) return VIDEODB_DETAILS_LASTPLAYED; - else if (field == FieldDateAdded) return VIDEODB_DETAILS_DATEADDED; + else if (field == FieldFilename) index = VIDEODB_DETAILS_MOVIE_FILE; + else if (field == FieldPath) return VIDEODB_DETAILS_MOVIE_PATH; + else if (field == FieldPlaycount) return VIDEODB_DETAILS_MOVIE_PLAYCOUNT; + else if (field == FieldLastPlayed) return VIDEODB_DETAILS_MOVIE_LASTPLAYED; + else if (field == FieldDateAdded) return VIDEODB_DETAILS_MOVIE_DATEADDED; if (index < 0) return index; @@ -370,7 +400,6 @@ int DatabaseUtils::GetFieldIndex(Field field, MediaType mediaType) else if (field == FieldGenre) index = VIDEODB_ID_TV_GENRE; else if (field == FieldMPAA) index = VIDEODB_ID_TV_MPAA; else if (field == FieldStudio) index = VIDEODB_ID_TV_STUDIOS; - else if (field == FieldSortTitle) index = VIDEODB_ID_TV_SORTTITLE; else if (field == FieldPath) return VIDEODB_DETAILS_TVSHOW_PATH; else if (field == FieldDateAdded) return VIDEODB_DETAILS_TVSHOW_DATEADDED; else if (field == FieldNumberOfEpisodes) return VIDEODB_DETAILS_TVSHOW_NUM_EPISODES; @@ -397,6 +426,8 @@ int DatabaseUtils::GetFieldIndex(Field field, MediaType mediaType) else if (field == FieldDirector) index = VIDEODB_ID_EPISODE_DIRECTOR; else if (field == FieldSeason) index = VIDEODB_ID_EPISODE_SEASON; else if (field == FieldEpisodeNumber) index = VIDEODB_ID_EPISODE_EPISODE; + else if (field == FieldEpisodeNumberSpecialSort) index = VIDEODB_ID_EPISODE_SORTEPISODE; + else if (field == FieldSeasonSpecialSort) index = VIDEODB_ID_EPISODE_SORTSEASON; else if (field == FieldFilename) return VIDEODB_DETAILS_EPISODE_FILE; else if (field == FieldPath) return VIDEODB_DETAILS_EPISODE_PATH; else if (field == FieldPlaycount) return VIDEODB_DETAILS_EPISODE_PLAYCOUNT; @@ -436,6 +467,8 @@ bool DatabaseUtils::GetSelectFields(const Fields &fields, MediaType mediaType, F sortFields.insert(FieldAlbum); else if (mediaType == MediaTypeSong) sortFields.insert(FieldTrackNumber); + else if (mediaType == MediaTypeArtist) + sortFields.insert(FieldArtist); selectFields.clear(); for (Fields::const_iterator it = sortFields.begin(); it != sortFields.end(); it++) @@ -599,6 +632,10 @@ bool DatabaseUtils::GetDatabaseResults(MediaType mediaType, const FieldList &fie break; } + case MediaTypeArtist: + result[FieldLabel] = result.at(FieldArtist).asString(); + break; + default: break; } diff --git a/xbmc/utils/DatabaseUtils.h b/xbmc/utils/DatabaseUtils.h index 3fb8457c6e..6b384ad176 100644 --- a/xbmc/utils/DatabaseUtils.h +++ b/xbmc/utils/DatabaseUtils.h @@ -53,7 +53,6 @@ typedef enum { FieldBitrate, FieldListeners, FieldPlaylist, - FieldSet, FieldRandom, // fields retrievable from the database @@ -87,6 +86,7 @@ typedef enum { FieldCountry, FieldMPAA, FieldTop250, + FieldSet, FieldNumberOfEpisodes, FieldNumberOfWatchedEpisodes, FieldWriter, @@ -110,7 +110,13 @@ typedef enum { FieldAudioLanguage, FieldSubtitleLanguage, FieldProductionCode, - FieldTag + FieldTag, + FieldInstruments, + FieldBiography, + FieldBorn, + FieldBandFormed, + FieldDisbanded, + FieldDied } Field; typedef std::set<Field> Fields; diff --git a/xbmc/utils/FileOperationJob.cpp b/xbmc/utils/FileOperationJob.cpp index 9aba05c59d..06a9a6fe81 100644 --- a/xbmc/utils/FileOperationJob.cpp +++ b/xbmc/utils/FileOperationJob.cpp @@ -29,6 +29,7 @@ #include "log.h" #include "Util.h" #include "URIUtils.h" +#include "URL.h" #include "guilib/LocalizeStrings.h" #ifdef HAS_FILESYSTEM_RAR #include "filesystem/RarManager.h" @@ -298,9 +299,9 @@ bool CFileOperationJob::CFileOperation::OnFileCallback(void* pContext, int iperc double current = data->current + ((double)ipercent * data->opWeight * (double)m_time)/ 100.0; if (avgSpeed > 1000000.0f) - data->base->m_avgSpeed.Format("%.1f Mb/s", avgSpeed / 1000000.0f); + data->base->m_avgSpeed.Format("%.1f MB/s", avgSpeed / 1000000.0f); else - data->base->m_avgSpeed.Format("%.1f Kb/s", avgSpeed / 1000.0f); + data->base->m_avgSpeed.Format("%.1f KB/s", avgSpeed / 1000.0f); return !data->base->ShouldCancel((unsigned)current, 100); } diff --git a/xbmc/utils/FileUtils.cpp b/xbmc/utils/FileUtils.cpp index 4bf17f5500..74f1d81fc2 100644 --- a/xbmc/utils/FileUtils.cpp +++ b/xbmc/utils/FileUtils.cpp @@ -1,7 +1,7 @@ #include "FileUtils.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogYesNo.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "utils/log.h" #include "guilib/LocalizeStrings.h" #include "JobManager.h" @@ -57,7 +57,7 @@ bool CFileUtils::RenameFile(const CStdString &strFile) URIUtils::RemoveSlashAtEnd(strFileAndPath); CStdString strFileName = URIUtils::GetFileName(strFileAndPath); CStdString strPath = strFile.Left(strFileAndPath.size() - strFileName.size()); - if (CGUIDialogKeyboard::ShowAndGetInput(strFileName, g_localizeStrings.Get(16013), false)) + if (CGUIKeyboardFactory::ShowAndGetInput(strFileName, g_localizeStrings.Get(16013), false)) { strPath += strFileName; CLog::Log(LOGINFO,"FileUtils: rename %s->%s\n", strFileAndPath.c_str(), strPath.c_str()); diff --git a/xbmc/utils/GlobalsHandling.h b/xbmc/utils/GlobalsHandling.h index 785533a358..e1f8373384 100644 --- a/xbmc/utils/GlobalsHandling.h +++ b/xbmc/utils/GlobalsHandling.h @@ -21,7 +21,7 @@ #pragma once -#include "boost/shared_ptr.hpp" +#include <boost/shared_ptr.hpp> /** * This file contains the pattern for moving "globals" from the BSS Segment to the heap. diff --git a/xbmc/utils/Makefile b/xbmc/utils/Makefile index 7130ab2a3e..af362eb857 100644 --- a/xbmc/utils/Makefile +++ b/xbmc/utils/Makefile @@ -3,7 +3,7 @@ SRCS=AlarmClock.cpp \ Archive.cpp \ AsyncFileCopy.cpp \ AutoPtrHandle.cpp \ - Base64.cpp \ + Base64.cpp \ BitstreamStats.cpp \ CharsetConverter.cpp \ CPUInfo.cpp \ @@ -25,7 +25,7 @@ SRCS=AlarmClock.cpp \ HTMLUtil.cpp \ HttpHeader.cpp \ HttpParser.cpp \ - HttpResponse.cpp \ + HttpResponse.cpp \ InfoLoader.cpp \ JobManager.cpp \ JSONVariantParser.cpp \ @@ -58,7 +58,9 @@ SRCS=AlarmClock.cpp \ TimeUtils.cpp \ TuxBoxUtil.cpp \ URIUtils.cpp \ + UrlOptions.cpp \ Variant.cpp \ + Vector.cpp \ Weather.cpp \ XBMCTinyXML.cpp \ XMLUtils.cpp \ diff --git a/xbmc/utils/MathUtils.h b/xbmc/utils/MathUtils.h index c3674f6b40..90a87d40ea 100644 --- a/xbmc/utils/MathUtils.h +++ b/xbmc/utils/MathUtils.h @@ -35,13 +35,15 @@ #if defined(__ppc__) || \ defined(__powerpc__) || \ - (defined(__APPLE__) && defined(__arm__) && defined(__llvm__)) + (defined(__APPLE__) && defined(__arm__) && defined(__llvm__)) || \ + (defined(__ANDROID__) && defined(__arm__)) #define DISABLE_MATHUTILS_ASM_ROUND_INT #endif #if defined(__ppc__) || \ defined(__powerpc__) || \ - (defined(__APPLE__) && defined(__llvm__)) + (defined(__APPLE__) && defined(__llvm__)) || \ + (defined(__ANDROID__) && defined(__arm__)) #define DISABLE_MATHUTILS_ASM_TRUNCATE_INT #endif diff --git a/xbmc/utils/RecentlyAddedJob.cpp b/xbmc/utils/RecentlyAddedJob.cpp index f1b26f8337..b9b2d3a1ca 100644 --- a/xbmc/utils/RecentlyAddedJob.cpp +++ b/xbmc/utils/RecentlyAddedJob.cpp @@ -214,7 +214,7 @@ bool CRecentlyAddedJob::UpdateMusic() musicdatabase.Open(); - if (musicdatabase.GetRecentlyAddedAlbumSongs("musicdb://", musicItems, NUM_ITEMS)) + if (musicdatabase.GetRecentlyAddedAlbumSongs("musicdb://4/", musicItems, NUM_ITEMS)) { long idAlbum = -1; CStdString strAlbumThumb; diff --git a/xbmc/utils/ScraperParser.cpp b/xbmc/utils/ScraperParser.cpp index 1624cea2aa..a8aa6abf1c 100644 --- a/xbmc/utils/ScraperParser.cpp +++ b/xbmc/utils/ScraperParser.cpp @@ -84,14 +84,14 @@ bool CScraperParser::Load(const CStdString& strXMLFile) { Clear(); - m_document = new CXBMCTinyXML(strXMLFile); + m_document = new CXBMCTinyXML(); if (!m_document) return false; m_strFile = strXMLFile; - if (m_document->LoadFile()) + if (m_document->LoadFile(strXMLFile)) return LoadFromXML(); delete m_document; diff --git a/xbmc/utils/SortUtils.cpp b/xbmc/utils/SortUtils.cpp index 3cefa2f324..ec5e152cba 100644 --- a/xbmc/utils/SortUtils.cpp +++ b/xbmc/utils/SortUtils.cpp @@ -278,7 +278,7 @@ string ByEpisodeNumber(SortAttribute attributes, const SortItem &values) const CVariant &episodeSpecial = values.at(FieldEpisodeNumberSpecialSort); const CVariant &seasonSpecial = values.at(FieldSeasonSpecialSort); if (!episodeSpecial.isNull() && !seasonSpecial.isNull() && - episodeSpecial.asInteger() > 0) + (episodeSpecial.asInteger() > 0 || seasonSpecial.asInteger() > 0)) num = ((uint64_t)seasonSpecial.asInteger() << 32) + (episodeSpecial.asInteger() << 16) - ((2 << 15) - values.at(FieldEpisodeNumber).asInteger()); else num = ((uint64_t)values.at(FieldSeason).asInteger() << 32) + (values.at(FieldEpisodeNumber).asInteger() << 16); diff --git a/xbmc/utils/StdString.h b/xbmc/utils/StdString.h index 1c870b38dd..00f53bf1ac 100644 --- a/xbmc/utils/StdString.h +++ b/xbmc/utils/StdString.h @@ -864,7 +864,7 @@ inline const Type& SSMAX(const Type& arg1, const Type& arg2) PWSTR pNextDstW = pDstW; SSCodeCvt::result res = SSCodeCvt::ok; const SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt); -#if defined(TARGET_DARWIN) || defined(__FreeBSD__) +#if defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(TARGET_ANDROID) SSCodeCvt::state_type st= { { 0 } }; #else SSCodeCvt::state_type st= { 0 }; @@ -911,7 +911,7 @@ inline const Type& SSMAX(const Type& arg1, const Type& arg2) PCWSTR pNextSrcW = pSrcW; SSCodeCvt::result res = SSCodeCvt::ok; const SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt); -#if defined(TARGET_DARWIN) || defined(__FreeBSD__) +#if defined(TARGET_DARWIN) || defined(__FreeBSD__) || defined(TARGET_ANDROID) SSCodeCvt::state_type st= { { 0 } }; #else SSCodeCvt::state_type st= { 0 }; diff --git a/xbmc/utils/StringUtils.cpp b/xbmc/utils/StringUtils.cpp index d64bbbe5cb..75b11aef70 100644 --- a/xbmc/utils/StringUtils.cpp +++ b/xbmc/utils/StringUtils.cpp @@ -33,7 +33,6 @@ #include "StringUtils.h" #include "utils/RegExp.h" #include "utils/fstrcmp.h" -#include "LangInfo.h" #include <locale> #include <math.h> @@ -295,13 +294,13 @@ bool StringUtils::IsNaturalNumber(const CStdString& str) { size_t i = 0, n = 0; // allow whitespace,digits,whitespace - while (i < str.size() && isspace(str[i])) + while (i < str.size() && isspace((unsigned char) str[i])) i++; - while (i < str.size() && isdigit(str[i])) + while (i < str.size() && isdigit((unsigned char) str[i])) { i++; n++; } - while (i < str.size() && isspace(str[i])) + while (i < str.size() && isspace((unsigned char) str[i])) i++; return i == str.size() && n > 0; } @@ -310,15 +309,15 @@ bool StringUtils::IsInteger(const CStdString& str) { size_t i = 0, n = 0; // allow whitespace,-,digits,whitespace - while (i < str.size() && isspace(str[i])) + while (i < str.size() && isspace((unsigned char) str[i])) i++; if (i < str.size() && str[i] == '-') i++; - while (i < str.size() && isdigit(str[i])) + while (i < str.size() && isdigit((unsigned char) str[i])) { i++; n++; } - while (i < str.size() && isspace(str[i])) + while (i < str.size() && isspace((unsigned char) str[i])) i++; return i == str.size() && n > 0; } @@ -338,6 +337,7 @@ bool StringUtils::Test() ret |= !IsNaturalNumber("120 h"); ret |= !IsNaturalNumber(" "); ret |= !IsNaturalNumber(""); + ret |= !IsNaturalNumber("ééčč"); ret |= IsInteger("10"); ret |= IsInteger(" -10"); @@ -350,6 +350,7 @@ bool StringUtils::Test() ret |= !IsInteger("120 h"); ret |= !IsInteger(" "); ret |= !IsInteger(""); + ret |= !IsInteger("ééčč"); return ret; } diff --git a/xbmc/utils/SystemInfo.cpp b/xbmc/utils/SystemInfo.cpp index e60de25eeb..98cf7a9c5d 100644 --- a/xbmc/utils/SystemInfo.cpp +++ b/xbmc/utils/SystemInfo.cpp @@ -496,6 +496,9 @@ CStdString CSysInfo::GetHddSpaceInfo(int& percent, int drive, bool shortText) #if defined(_LINUX) && !defined(TARGET_DARWIN) && !defined(__FreeBSD__) CStdString CSysInfo::GetLinuxDistro() { +#if defined(TARGET_ANDROID) + return "Android"; +#endif static const char* release_file[] = { "/etc/debian_version", "/etc/SuSE-release", "/etc/mandrake-release", @@ -546,6 +549,14 @@ CStdString CSysInfo::GetUnameVersion() { CStdString result = ""; +#if defined(TARGET_ANDROID) + struct utsname name; + if (uname(&name) == -1) + result = "Android"; + result += name.release; + result += " "; + result += name.machine; +#else FILE* pipe = popen("uname -rm", "r"); if (pipe) { @@ -563,6 +574,7 @@ CStdString CSysInfo::GetUnameVersion() CLog::Log(LOGWARNING, "Unable to determine Uname version"); pclose(pipe); } +#endif//else !TARGET_ANDROID return result.Trim(); } diff --git a/xbmc/utils/TuxBoxUtil.cpp b/xbmc/utils/TuxBoxUtil.cpp index 7b2d362d94..8121e7fcf7 100644 --- a/xbmc/utils/TuxBoxUtil.cpp +++ b/xbmc/utils/TuxBoxUtil.cpp @@ -28,6 +28,7 @@ #include "filesystem/CurlFile.h" #include "dialogs/GUIDialogContextMenu.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "GUIInfoManager.h" #include "video/VideoInfoTag.h" #include "guilib/GUIWindowManager.h" @@ -120,7 +121,7 @@ void CTuxBoxService::Process() if (strCurrentServiceName != g_tuxbox.sCurSrvData.service_name && g_application.IsPlaying() && !g_tuxbox.sZapstream.available) { CLog::Log(LOGDEBUG," - ERROR: Non controlled channel change detected! Stopping current playing stream!"); - g_application.getApplicationMessenger().MediaStop(); + CApplicationMessenger::Get().MediaStop(); break; } } @@ -579,7 +580,7 @@ bool CTuxBoxUtil::GetZapUrl(const CStdString& strPath, CFileItem &items ) } if (g_application.IsPlaying() && !g_tuxbox.sZapstream.available) - g_application.getApplicationMessenger().MediaStop(); + CApplicationMessenger::Get().MediaStop(); strLabel.Format("%s: %s %s-%s",items.GetLabel().c_str(), sCurSrvData.current_event_date.c_str(),sCurSrvData.current_event_start.c_str(), sCurSrvData.current_event_start.c_str()); strLabel2.Format("%s", sCurSrvData.current_event_description.c_str()); @@ -1439,7 +1440,7 @@ bool CTuxBoxUtil::GetVideoSubChannels(CStdString& strVideoSubChannelName, CStdSt // IsPlaying, Stop it.. if(g_application.IsPlaying()) - g_application.getApplicationMessenger().MediaStop(); + CApplicationMessenger::Get().MediaStop(); // popup the context menu CContextButtons buttons; diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp index 54400af33a..376d2d7b78 100644 --- a/xbmc/utils/URIUtils.cpp +++ b/xbmc/utils/URIUtils.cpp @@ -565,7 +565,14 @@ bool URIUtils::IsRAR(const CStdString& strFile) bool URIUtils::IsInArchive(const CStdString &strFile) { - return IsInZIP(strFile) || IsInRAR(strFile); + return IsInZIP(strFile) || IsInRAR(strFile) || IsInAPK(strFile); +} + +bool URIUtils::IsInAPK(const CStdString& strFile) +{ + CURL url(strFile); + + return url.GetProtocol() == "apk" && url.GetFileName() != ""; } bool URIUtils::IsInZIP(const CStdString& strFile) @@ -582,6 +589,17 @@ bool URIUtils::IsInRAR(const CStdString& strFile) return url.GetProtocol() == "rar" && url.GetFileName() != ""; } +bool URIUtils::IsAPK(const CStdString& strFile) +{ + CStdString strExtension; + GetExtension(strFile,strExtension); + + if (strExtension.CompareNoCase(".apk") == 0) + return true; + + return false; +} + bool URIUtils::IsZIP(const CStdString& strFile) // also checks for comic books! { CStdString strExtension; @@ -794,6 +812,11 @@ bool URIUtils::IsBluray(const CStdString& strFile) return strFile.Left(7).Equals("bluray:"); } +bool URIUtils::IsAndroidApp(const CStdString &path) +{ + return path.Left(11).Equals("androidapp:"); +} + bool URIUtils::IsDOSPath(const CStdString &path) { if (path.size() > 1 && path[1] == ':' && isalpha(path[0])) diff --git a/xbmc/utils/URIUtils.h b/xbmc/utils/URIUtils.h index 656b6e797e..33c9b53732 100644 --- a/xbmc/utils/URIUtils.h +++ b/xbmc/utils/URIUtils.h @@ -64,6 +64,7 @@ public: static bool IsInArchive(const CStdString& strFile); static bool IsInRAR(const CStdString& strFile); static bool IsInternetStream(const CURL& url, bool bStrictCheck = false); + static bool IsInAPK(const CStdString& strFile); static bool IsInZIP(const CStdString& strFile); static bool IsISO9660(const CStdString& strFile); static bool IsLastFM(const CStdString& strFile); @@ -87,8 +88,10 @@ public: static bool IsURL(const CStdString& strFile); static bool IsVideoDb(const CStdString& strFile); static bool IsVTP(const CStdString& strFile); + static bool IsAPK(const CStdString& strFile); static bool IsZIP(const CStdString& strFile); static bool IsBluray(const CStdString& strFile); + static bool IsAndroidApp(const CStdString& strFile); static void AddSlashAtEnd(CStdString& strFolder); static bool HasSlashAtEnd(const CStdString& strFile); diff --git a/xbmc/utils/UrlOptions.cpp b/xbmc/utils/UrlOptions.cpp new file mode 100644 index 0000000000..c189a089a8 --- /dev/null +++ b/xbmc/utils/UrlOptions.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <sstream> + +#include "UrlOptions.h" +#include "URL.h" +#include "utils/StringUtils.h" + +using namespace std; + +CUrlOptions::CUrlOptions() +{ } + +CUrlOptions::~CUrlOptions() +{ } + +std::string CUrlOptions::GetOptionsString() const +{ + std::string options; + for (UrlOptions::const_iterator opt = m_options.begin(); opt != m_options.end(); opt++) + { + if (opt != m_options.begin()) + options += "&"; + + options += CURL::Encode(opt->first) + "=" + CURL::Encode(opt->second.asString()); + } + + return options; +} + +void CUrlOptions::AddOption(const std::string &key, const std::string &value) +{ + if (key.empty()) + return; + + UrlOptions::iterator option = m_options.find(key); + if (!value.empty()) + m_options[key] = value; + else if (option != m_options.end()) + m_options.erase(option); +} + +void CUrlOptions::AddOption(const std::string &key, int value) +{ + if (key.empty()) + return; + + m_options[key] = value; +} + +void CUrlOptions::AddOption(const std::string &key, float value) +{ + if (key.empty()) + return; + + m_options[key] = value; +} + +void CUrlOptions::AddOption(const std::string &key, double value) +{ + if (key.empty()) + return; + + m_options[key] = value; +} + +void CUrlOptions::AddOption(const std::string &key, bool value) +{ + if (key.empty()) + return; + + m_options[key] = value; +} + +void CUrlOptions::AddOptions(const std::string &options) +{ + if (options.empty()) + return; + + string strOptions = options; + + // remove leading ? if present + if (strOptions.at(0) == '?') + strOptions.erase(0, 1); + + // split the options by & and process them one by one + vector<string> optionList = StringUtils::Split(strOptions, "&"); + for (vector<string>::const_iterator option = optionList.begin(); option != optionList.end(); option++) + { + if (option->empty()) + continue; + + // every option must have the format key=value + size_t pos = option->find('='); + if (pos == string::npos || pos == 0 || pos >= option->size() - 1) + continue; + + string key = CURL::Decode(option->substr(0, pos)); + string value = CURL::Decode(option->substr(pos + 1)); + + // the key cannot be empty + if (!key.empty()) + AddOption(key, value); + } +} diff --git a/xbmc/utils/UrlOptions.h b/xbmc/utils/UrlOptions.h new file mode 100644 index 0000000000..47c6e511ef --- /dev/null +++ b/xbmc/utils/UrlOptions.h @@ -0,0 +1,46 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <map> +#include <string> + +#include "utils/Variant.h" + +class CUrlOptions +{ +public: + typedef std::map<std::string, CVariant> UrlOptions; + + CUrlOptions(); + virtual ~CUrlOptions(); + + virtual const UrlOptions& GetOptions() const { return m_options; } + virtual std::string GetOptionsString() const; + + virtual void AddOption(const std::string &key, const std::string &value); + virtual void AddOption(const std::string &key, int value); + virtual void AddOption(const std::string &key, float value); + virtual void AddOption(const std::string &key, double value); + virtual void AddOption(const std::string &key, bool value); + virtual void AddOptions(const std::string &options); + +protected: + UrlOptions m_options; +}; diff --git a/xbmc/utils/Vector.cpp b/xbmc/utils/Vector.cpp new file mode 100644 index 0000000000..1657c78ae0 --- /dev/null +++ b/xbmc/utils/Vector.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <math.h> + +#include "Vector.h" + +CVector::CVector() +{ + reset(); +} + +CVector::CVector(float xCoord, float yCoord) + : x(xCoord), + y(yCoord) +{ } + +void CVector::reset() +{ + x = 0.0f; + y = 0.0f; +} + +const CVector CVector::operator+(const CVector &other) const +{ + return CVector(x + other.x, y + other.y); +} + +const CVector CVector::operator-(const CVector &other) const +{ + return CVector(x - other.x, y - other.y); +} + +CVector& CVector::operator+=(const CVector &other) +{ + x += other.x; + y += other.y; + + return *this; +} + +CVector& CVector::operator-=(const CVector &other) +{ + x -= other.x; + y -= other.y; + + return *this; +} + +float CVector::scalar(const CVector &other) const +{ + return x * other.x + y * other.y; +} + +float CVector::length() const +{ + return sqrt(pow(x, 2) + pow(y, 2)); +} diff --git a/xbmc/utils/Vector.h b/xbmc/utils/Vector.h new file mode 100644 index 0000000000..75405c918b --- /dev/null +++ b/xbmc/utils/Vector.h @@ -0,0 +1,41 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +class CVector +{ +public: + CVector(); + CVector(float xCoord, float yCoord); + virtual ~CVector() { } + + virtual void reset(); + + const CVector operator+(const CVector &other) const; + const CVector operator-(const CVector &other) const; + CVector& operator+=(const CVector &other); + CVector& operator-=(const CVector &other); + + float scalar(const CVector &other) const; + float length() const; + + float x; + float y; +};
\ No newline at end of file diff --git a/xbmc/utils/XBMCTinyXML.cpp b/xbmc/utils/XBMCTinyXML.cpp index 4d2472a325..ac5d2accc5 100644 --- a/xbmc/utils/XBMCTinyXML.cpp +++ b/xbmc/utils/XBMCTinyXML.cpp @@ -30,20 +30,18 @@ CXBMCTinyXML::CXBMCTinyXML() } CXBMCTinyXML::CXBMCTinyXML(const char *documentName) -: TiXmlDocument() +: TiXmlDocument(documentName) { - LoadFile(documentName); } CXBMCTinyXML::CXBMCTinyXML(const CStdString &documentName) -: TiXmlDocument() +: TiXmlDocument(documentName) { - LoadFile(documentName); } bool CXBMCTinyXML::LoadFile(TiXmlEncoding encoding) { - return TiXmlDocument::LoadFile(encoding); + return LoadFile(value, encoding); } bool CXBMCTinyXML::LoadFile(const char *_filename, TiXmlEncoding encoding) diff --git a/xbmc/utils/XBMCTinyXML.h b/xbmc/utils/XBMCTinyXML.h index c6b4fe22f2..9a3a4de424 100644 --- a/xbmc/utils/XBMCTinyXML.h +++ b/xbmc/utils/XBMCTinyXML.h @@ -24,11 +24,19 @@ #endif #ifdef TARGET_WINDOWS #define TIXML_USE_STL +#if _MSC_VER < 1700 #ifdef _DEBUG #pragma comment(lib, "tinyxmlSTLd.lib") #else #pragma comment(lib, "tinyxmlSTL.lib") #endif +#else // _MSC_VER < 1700 +#ifdef _DEBUG +#pragma comment(lib, "tinyxmlSTL11d.lib") +#else +#pragma comment(lib, "tinyxmlSTL11.lib") +#endif +#endif // _MSC_VER < 1700 #else //compile fix for TinyXml < 2.6.0 #define DOCUMENT TINYXML_DOCUMENT diff --git a/xbmc/utils/fastmemcpy-arm.S b/xbmc/utils/fastmemcpy-arm.S index 3d77c68b75..bf60c20ad0 100644 --- a/xbmc/utils/fastmemcpy-arm.S +++ b/xbmc/utils/fastmemcpy-arm.S @@ -26,7 +26,7 @@ * SUCH DAMAGE. */ -#if defined(__arm__) +#if defined(__arm__) && !defined(TARGET_ANDROID) #if defined(__ARM_NEON__) .text diff --git a/xbmc/utils/fastmemcpy.h b/xbmc/utils/fastmemcpy.h index d7dd93645e..209f03c6f7 100644 --- a/xbmc/utils/fastmemcpy.h +++ b/xbmc/utils/fastmemcpy.h @@ -22,7 +22,7 @@ extern "C" { #endif -#if !defined(_WIN32) && !defined(__ppc__) && !defined(__powerpc__) +#if !defined(_WIN32) && !defined(__ppc__) && !defined(__powerpc__) && !defined(TARGET_ANDROID) void * fast_memcpy(void * to, const void * from, size_t len); //#define fast_memcpy memcpy #else diff --git a/xbmc/utils/log.cpp b/xbmc/utils/log.cpp index 6f660dbaaf..674140e1aa 100644 --- a/xbmc/utils/log.cpp +++ b/xbmc/utils/log.cpp @@ -27,6 +27,9 @@ #include "threads/SingleLock.h" #include "threads/Thread.h" #include "utils/StdString.h" +#if defined(TARGET_ANDROID) +#include "android/activity/XBMCApp.h" +#endif #define critSec XBMC_GLOBAL_USE(CLog::CLogGlobals).critSec #define m_file XBMC_GLOBAL_USE(CLog::CLogGlobals).m_file @@ -119,6 +122,11 @@ void CLog::Log(int loglevel, const char *format, ... ) strPrefix.Format(prefixFormat, time.wHour, time.wMinute, time.wSecond, (uint64_t)CThread::GetCurrentThreadId(), levelNames[loglevel]); +//print to adb +#if defined(TARGET_ANDROID) && defined(_DEBUG) + CXBMCApp::android_printf("%s%s",strPrefix.c_str(), strData.c_str()); +#endif + fputs(strPrefix.c_str(), m_file); fputs(strData.c_str(), m_file); fflush(m_file); @@ -205,7 +213,18 @@ int CLog::GetLogLevel() void CLog::OutputDebugString(const std::string& line) { #if defined(_DEBUG) || defined(PROFILE) - ::OutputDebugString(line.c_str()); +#if defined(TARGET_WINDOWS) + // we can't use charsetconverter here as it's initialized later than CLog and deinitialized early + int bufSize = MultiByteToWideChar(CP_UTF8, 0, line.c_str(), -1, NULL, 0); + CStdStringW wstr (L"", bufSize); + if ( MultiByteToWideChar(CP_UTF8, 0, line.c_str(), -1, wstr.GetBuf(bufSize), bufSize) == bufSize ) + { + wstr.RelBuf(); + ::OutputDebugStringW(wstr.c_str()); + } + else +#endif // TARGET_WINDOWS + ::OutputDebugString(line.c_str()); ::OutputDebugString("\n"); #endif } diff --git a/xbmc/video/Bookmark.cpp b/xbmc/video/Bookmark.cpp index b312d17e55..195622de02 100644 --- a/xbmc/video/Bookmark.cpp +++ b/xbmc/video/Bookmark.cpp @@ -36,3 +36,12 @@ void CBookmark::Reset() type = STANDARD; } +bool CBookmark::IsSet() const +{ + return totalTimeInSeconds > 0.0f; +} + +bool CBookmark::IsPartWay() const +{ + return totalTimeInSeconds > 0.0f && timeInSeconds > 0.0f; +} diff --git a/xbmc/video/Bookmark.h b/xbmc/video/Bookmark.h index b49ae584fa..159b4da9dc 100644 --- a/xbmc/video/Bookmark.h +++ b/xbmc/video/Bookmark.h @@ -29,6 +29,17 @@ class CBookmark public: CBookmark(); void Reset(); + + /*! \brief returns true if this bookmark has been set. + \return true if totalTimeInSeconds is positive. + */ + bool IsSet() const; + + /*! \brief returns true if this bookmark is part way through the video file + \return true if both totalTimeInSeconds and timeInSeconds are positive. + */ + bool IsPartWay() const; + double timeInSeconds; double totalTimeInSeconds; long partNumber; diff --git a/xbmc/video/GUIViewStateVideo.cpp b/xbmc/video/GUIViewStateVideo.cpp index 536d83e8ad..d3cd0aeb34 100644 --- a/xbmc/video/GUIViewStateVideo.cpp +++ b/xbmc/video/GUIViewStateVideo.cpp @@ -23,13 +23,11 @@ #include "PlayListPlayer.h" #include "filesystem/VideoDatabaseDirectory.h" #include "filesystem/Directory.h" -#include "guilib/GUIBaseContainer.h" #include "VideoDatabase.h" #include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" #include "settings/Settings.h" #include "FileItem.h" -#include "Util.h" #include "guilib/Key.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/video/Makefile b/xbmc/video/Makefile index f98e11b756..65122a7c6a 100644 --- a/xbmc/video/Makefile +++ b/xbmc/video/Makefile @@ -2,6 +2,7 @@ SRCS=Bookmark.cpp \ GUIViewStateVideo.cpp \ Teletext.cpp \ VideoDatabase.cpp \ + VideoDbUrl.cpp \ VideoInfoDownloader.cpp \ VideoInfoScanner.cpp \ VideoInfoTag.cpp \ diff --git a/xbmc/video/Teletext.cpp b/xbmc/video/Teletext.cpp index 97d7c8977f..97776865f0 100644 --- a/xbmc/video/Teletext.cpp +++ b/xbmc/video/Teletext.cpp @@ -1384,7 +1384,7 @@ void CTeletextDecoder::DoFlashing(int startrow) case 3: if (flashphase>=500 && flashphase<750) doflash = true; } break; - case 0x11 : // decremental flash + case 0x14 : // decremental flash decflash--; if (decflash<1) decflash = 3; switch (decflash) diff --git a/xbmc/video/TeletextDefines.h b/xbmc/video/TeletextDefines.h index 373d4c90cc..8fc2ca5dff 100644 --- a/xbmc/video/TeletextDefines.h +++ b/xbmc/video/TeletextDefines.h @@ -24,7 +24,6 @@ #include "utils/StdString.h" #define FLOFSIZE 4 -#define PAGESIZE (40*25) #define SUBTITLE_CACHESIZE 50 #define number2char(c) ((c) + (((c) <= 9) ? '0' : ('A' - 10))) diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp index 358ba917b1..8fd330a8cc 100644 --- a/xbmc/video/VideoDatabase.cpp +++ b/xbmc/video/VideoDatabase.cpp @@ -52,6 +52,9 @@ #include "dbwrappers/dataset.h" #include "utils/LabelFormatter.h" #include "XBDateTime.h" +#include "URL.h" +#include "video/VideoDbUrl.h" +#include "playlists/SmartPlayList.h" using namespace std; using namespace dbiplus; @@ -133,7 +136,7 @@ bool CVideoDatabase::CreateTables() column.Format(",c%02d text", i); columns += column; } - columns += ")"; + columns += ", idSet integer)"; m_pDS->exec(columns.c_str()); m_pDS->exec("CREATE UNIQUE INDEX ix_movie_file_1 ON movie (idFile, idMovie)"); m_pDS->exec("CREATE UNIQUE INDEX ix_movie_file_2 ON movie (idMovie, idFile)"); @@ -295,11 +298,6 @@ bool CVideoDatabase::CreateTables() CLog::Log(LOGINFO, "create sets table"); m_pDS->exec("CREATE TABLE sets ( idSet integer primary key, strSet text)\n"); - CLog::Log(LOGINFO, "create setlinkmovie table"); - m_pDS->exec("CREATE TABLE setlinkmovie ( idSet integer, idMovie integer)\n"); - m_pDS->exec("CREATE UNIQUE INDEX ix_setlinkmovie_1 ON setlinkmovie ( idSet, idMovie)\n"); - m_pDS->exec("CREATE UNIQUE INDEX ix_setlinkmovie_2 ON setlinkmovie ( idMovie, idSet)\n"); - // create basepath indices m_pDS->exec("CREATE INDEX ixMovieBasePath ON movie ( c23(12) )"); m_pDS->exec("CREATE INDEX ixMusicVideoBasePath ON musicvideo ( c14(12) )"); @@ -420,6 +418,7 @@ void CVideoDatabase::CreateViews() m_pDS->exec("DROP VIEW IF EXISTS movieview"); m_pDS->exec("CREATE VIEW movieview AS SELECT" " movie.*," + " sets.strSet AS strSet," " files.strFileName AS strFileName," " path.strPath AS strPath," " files.playCount AS playCount," @@ -428,6 +427,8 @@ void CVideoDatabase::CreateViews() " bookmark.timeInSeconds AS resumeTimeInSeconds, " " bookmark.totalTimeInSeconds AS totalTimeInSeconds " "FROM movie" + " LEFT JOIN sets ON" + " sets.idSet = movie.idSet" " JOIN files ON" " files.idFile=movie.idFile" " JOIN path ON" @@ -1272,6 +1273,9 @@ int CVideoDatabase::AddToTable(const CStdString& table, const CStdString& firstF int CVideoDatabase::AddSet(const CStdString& strSet) { + if (strSet.empty()) + return -1; + return AddToTable("sets", "idSet", "strSet", strSet); } @@ -1410,11 +1414,6 @@ void CVideoDatabase::RemoveFromLinkTable(const char *table, const char *firstFie } } -//****Sets**** -void CVideoDatabase::AddSetToMovie(int idMovie, int idSet) -{ - AddToLinkTable("setlinkmovie", "idSet", idSet, "idMovie", idMovie); -} //****Tags**** void CVideoDatabase::AddTagToItem(int idMovie, int idTag, const std::string &type) { @@ -1944,16 +1943,12 @@ int CVideoDatabase::SetDetailsForMovie(const CStdString& strFilenameAndPath, con AddActorToMovie(idMovie, idActor, it->strRole, order++); } - // add sets... - for (unsigned int i = 0; i < details.m_set.size(); i++) - { - int idSet = AddSet(details.m_set[i]); - // add art if not available - map<string, string> setArt; - if (!GetArtForItem(idSet, "set", setArt)) - SetArtForItem(idSet, "set", artwork); - AddSetToMovie(idMovie, idSet); - } + // add set... + int idSet = AddSet(details.m_strSet); + // add art if not available + map<string, string> setArt; + if (!GetArtForItem(idSet, "set", setArt)) + SetArtForItem(idSet, "set", artwork); // add tags... for (unsigned int i = 0; i < details.m_tags.size(); i++) @@ -1974,6 +1969,10 @@ int CVideoDatabase::SetDetailsForMovie(const CStdString& strFilenameAndPath, con // update our movie table (we know it was added already above) // and insert the new row CStdString sql = "update movie set " + GetValueString(details, VIDEODB_ID_MIN, VIDEODB_ID_MAX, DbMovieOffsets); + if (idSet > 0) + sql += PrepareSQL(", idSet = %i", idSet); + else + sql += ", idSet = NULL"; sql += PrepareSQL(" where idMovie=%i", idMovie); m_pDS->exec(sql.c_str()); CommitTransaction(); @@ -2050,7 +2049,7 @@ int CVideoDatabase::SetDetailsForTvShow(const CStdString& strPath, const CVideoI // and insert the new row CStdString sql = "update tvshow set " + GetValueString(details, VIDEODB_ID_TV_MIN, VIDEODB_ID_TV_MAX, DbTvShowOffsets); - sql += PrepareSQL("where idShow=%i", idTvShow); + sql += PrepareSQL(" where idShow=%i", idTvShow); m_pDS->exec(sql.c_str()); CommitTransaction(); @@ -2125,7 +2124,7 @@ int CVideoDatabase::SetDetailsForEpisode(const CStdString& strFilenameAndPath, c // and insert the new row CStdString sql = "update episode set " + GetValueString(details, VIDEODB_ID_EPISODE_MIN, VIDEODB_ID_EPISODE_MAX, DbEpisodeOffsets); - sql += PrepareSQL("where idEpisode=%i", idEpisode); + sql += PrepareSQL(" where idEpisode=%i", idEpisode); m_pDS->exec(sql.c_str()); CommitTransaction(); @@ -2651,9 +2650,6 @@ void CVideoDatabase::DeleteMovie(const CStdString& strFilenameAndPath, bool bKee strSQL=PrepareSQL("delete from studiolinkmovie where idMovie=%i", idMovie); m_pDS->exec(strSQL.c_str()); - strSQL=PrepareSQL("delete from setlinkmovie where idMovie=%i", idMovie); - m_pDS->exec(strSQL.c_str()); - strSQL=PrepareSQL("delete from countrylinkmovie where idMovie=%i", idMovie); m_pDS->exec(strSQL.c_str()); @@ -2891,9 +2887,9 @@ void CVideoDatabase::DeleteSet(int idSet) if (NULL == m_pDS.get()) return ; CStdString strSQL; - strSQL=PrepareSQL("delete from sets where idSet=%i", idSet); + strSQL=PrepareSQL("delete from sets where idSet = %i", idSet); m_pDS->exec(strSQL.c_str()); - strSQL=PrepareSQL("delete from setlinkmovie where idSet=%i", idSet); + strSQL=PrepareSQL("update movie set idSet = null where idSet = %i", idSet); m_pDS->exec(strSQL.c_str()); } catch (...) @@ -3126,7 +3122,20 @@ CVideoInfoTag CVideoDatabase::GetDetailsForMovie(const dbiplus::sql_record* cons details.m_iDbId = idMovie; details.m_type = "movie"; - GetCommonDetails(record, details); + + details.m_iSetId = record->at(VIDEODB_DETAILS_MOVIE_SET_ID).get_asInt(); + details.m_strSet = record->at(VIDEODB_DETAILS_MOVIE_SET_NAME).get_asString(); + details.m_iFileId = record->at(VIDEODB_DETAILS_FILEID).get_asInt(); + details.m_strPath = record->at(VIDEODB_DETAILS_MOVIE_PATH).get_asString(); + CStdString strFileName = record->at(VIDEODB_DETAILS_MOVIE_FILE).get_asString(); + ConstructPath(details.m_strFileNameAndPath,details.m_strPath,strFileName); + details.m_playCount = record->at(VIDEODB_DETAILS_MOVIE_PLAYCOUNT).get_asInt(); + details.m_lastPlayed.SetFromDBDateTime(record->at(VIDEODB_DETAILS_MOVIE_LASTPLAYED).get_asString()); + details.m_dateAdded.SetFromDBDateTime(record->at(VIDEODB_DETAILS_MOVIE_DATEADDED).get_asString()); + details.m_resumePoint.timeInSeconds = record->at(VIDEODB_DETAILS_MOVIE_RESUME_TIME).get_asInt(); + details.m_resumePoint.totalTimeInSeconds = record->at(VIDEODB_DETAILS_MOVIE_TOTAL_TIME).get_asInt(); + details.m_resumePoint.type = CBookmark::RESUME; + movieTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis(); if (needsCast) @@ -3136,19 +3145,8 @@ CVideoInfoTag CVideoDatabase::GetDetailsForMovie(const dbiplus::sql_record* cons castTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis(); details.m_strPictureURL.Parse(); - // create sets string - CStdString strSQL = PrepareSQL("SELECT sets.idSet, sets.strSet FROM sets,setlinkmovie WHERE setlinkmovie.idMovie=%i AND setlinkmovie.idSet=sets.idSet ORDER BY sets.idSet",idMovie); - m_pDS2->query(strSQL.c_str()); - while (!m_pDS2->eof()) - { - details.m_set.push_back(m_pDS2->fv("sets.strSet").get_asString()); - details.m_setId.push_back(m_pDS2->fv("sets.idSet").get_asInt()); - - m_pDS2->next(); - } - // get tags - strSQL = PrepareSQL("SELECT tag.strTag FROM tag, taglinks WHERE taglinks.idMedia = %i AND taglinks.media_type = 'movie' AND taglinks.idTag = tag.idTag ORDER BY tag.idTag", idMovie); + CStdString strSQL = PrepareSQL("SELECT tag.strTag FROM tag, taglinks WHERE taglinks.idMedia = %i AND taglinks.media_type = 'movie' AND taglinks.idTag = tag.idTag ORDER BY tag.idTag", idMovie); m_pDS2->query(strSQL.c_str()); while (!m_pDS2->eof()) { @@ -3161,7 +3159,7 @@ CVideoInfoTag CVideoDatabase::GetDetailsForMovie(const dbiplus::sql_record* cons GetLinksToTvShow(idMovie,links); for (unsigned int i=0;i<links.size();++i) { - strSQL = PrepareSQL("select c%02d from tvshow where idShow=%i", + CStdString strSQL = PrepareSQL("select c%02d from tvshow where idShow=%i", VIDEODB_ID_TV_TITLE,links[i]); m_pDS2->query(strSQL.c_str()); if (!m_pDS2->eof()) @@ -3279,32 +3277,24 @@ CVideoInfoTag CVideoDatabase::GetDetailsForMusicVideo(const dbiplus::sql_record* GetDetailsFromDB(record, VIDEODB_ID_MUSICVIDEO_MIN, VIDEODB_ID_MUSICVIDEO_MAX, DbMusicVideoOffsets, details); details.m_iDbId = idMovie; details.m_type = "musicvideo"; - GetCommonDetails(record, details); + + details.m_iFileId = record->at(VIDEODB_DETAILS_FILEID).get_asInt(); + details.m_strPath = record->at(VIDEODB_DETAILS_MUSICVIDEO_PATH).get_asString(); + CStdString strFileName = record->at(VIDEODB_DETAILS_MUSICVIDEO_FILE).get_asString(); + ConstructPath(details.m_strFileNameAndPath,details.m_strPath,strFileName); + details.m_playCount = record->at(VIDEODB_DETAILS_MUSICVIDEO_PLAYCOUNT).get_asInt(); + details.m_lastPlayed.SetFromDBDateTime(record->at(VIDEODB_DETAILS_MUSICVIDEO_LASTPLAYED).get_asString()); + details.m_dateAdded.SetFromDBDateTime(record->at(VIDEODB_DETAILS_MUSICVIDEO_DATEADDED).get_asString()); + details.m_resumePoint.timeInSeconds = record->at(VIDEODB_DETAILS_MUSICVIDEO_RESUME_TIME).get_asInt(); + details.m_resumePoint.totalTimeInSeconds = record->at(VIDEODB_DETAILS_MUSICVIDEO_TOTAL_TIME).get_asInt(); + details.m_resumePoint.type = CBookmark::RESUME; + movieTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis(); details.m_strPictureURL.Parse(); return details; } -void CVideoDatabase::GetCommonDetails(auto_ptr<Dataset> &pDS, CVideoInfoTag &details) -{ - GetCommonDetails(pDS->get_sql_record(), details); -} - -void CVideoDatabase::GetCommonDetails(const dbiplus::sql_record* const record, CVideoInfoTag &details) -{ - details.m_iFileId = record->at(VIDEODB_DETAILS_FILEID).get_asInt(); - details.m_strPath = record->at(VIDEODB_DETAILS_PATH).get_asString(); - CStdString strFileName = record->at(VIDEODB_DETAILS_FILE).get_asString(); - ConstructPath(details.m_strFileNameAndPath,details.m_strPath,strFileName); - details.m_playCount = record->at(VIDEODB_DETAILS_PLAYCOUNT).get_asInt(); - details.m_lastPlayed.SetFromDBDateTime(record->at(VIDEODB_DETAILS_LASTPLAYED).get_asString()); - details.m_dateAdded.SetFromDBDateTime(record->at(VIDEODB_DETAILS_DATEADDED).get_asString()); - details.m_resumePoint.timeInSeconds = record->at(VIDEODB_DETAILS_RESUME_TIME).get_asInt(); - details.m_resumePoint.totalTimeInSeconds = record->at(VIDEODB_DETAILS_TOTAL_TIME).get_asInt(); - details.m_resumePoint.type = CBookmark::RESUME; -} - void CVideoDatabase::GetCast(const CStdString &table, const CStdString &table_id, int type_id, vector<SActorInfo> &cast) { try @@ -4008,6 +3998,19 @@ bool CVideoDatabase::UpdateOldVersion(int iVersion) m_pDS->exec("CREATE UNIQUE INDEX ix_taglinks_2 ON taglinks (idMedia, media_type(20), idTag)"); m_pDS->exec("CREATE INDEX ix_taglinks_3 ON taglinks (media_type(20))"); } + if (iVersion < 68) + { // add idSet to movie table + m_pDS->exec("ALTER TABLE movie ADD idSet integer"); + m_pDS->query("SELECT idMovie FROM movie"); + while (!m_pDS->eof()) + { + int idMovie = m_pDS->fv(0).get_asInt(); + CStdString sql = PrepareSQL("UPDATE movie SET idSet=(SELECT idSet FROM setlinkmovie WHERE idMovie = %d LIMIT 1) WHERE idMovie = %d", idMovie, idMovie); + m_pDS2->exec(sql.c_str()); + m_pDS->next(); + } + m_pDS->exec("DROP TABLE IF EXISTS setlinkmovie"); + } // always recreate the view after any table change CreateViews(); return true; @@ -4129,9 +4132,12 @@ bool CVideoDatabase::GetPlayCounts(const CStdString &strPath, CFileItemList &ite if (item) { item->GetVideoInfoTag()->m_playCount = m_pDS->fv(1).get_asInt(); - item->GetVideoInfoTag()->m_resumePoint.timeInSeconds = m_pDS->fv(2).get_asInt(); - item->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds = m_pDS->fv(3).get_asInt(); - item->GetVideoInfoTag()->m_resumePoint.type = CBookmark::RESUME; + if (!item->GetVideoInfoTag()->m_resumePoint.IsSet()) + { + item->GetVideoInfoTag()->m_resumePoint.timeInSeconds = m_pDS->fv(2).get_asInt(); + item->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds = m_pDS->fv(3).get_asInt(); + item->GetVideoInfoTag()->m_resumePoint.type = CBookmark::RESUME; + } } m_pDS->next(); } @@ -4332,22 +4338,22 @@ void CVideoDatabase::EraseVideoSettings() } } -bool CVideoDatabase::GetGenresNav(const CStdString& strBaseDir, CFileItemList& items, int idContent) +bool CVideoDatabase::GetGenresNav(const CStdString& strBaseDir, CFileItemList& items, int idContent /* = -1 */, const Filter &filter /* = Filter() */) { - return GetNavCommon(strBaseDir, items, "genre", idContent); + return GetNavCommon(strBaseDir, items, "genre", idContent, filter); } -bool CVideoDatabase::GetCountriesNav(const CStdString& strBaseDir, CFileItemList& items, int idContent) +bool CVideoDatabase::GetCountriesNav(const CStdString& strBaseDir, CFileItemList& items, int idContent /* = -1 */, const Filter &filter /* = Filter() */) { - return GetNavCommon(strBaseDir, items, "country", idContent); + return GetNavCommon(strBaseDir, items, "country", idContent, filter); } -bool CVideoDatabase::GetStudiosNav(const CStdString& strBaseDir, CFileItemList& items, int idContent) +bool CVideoDatabase::GetStudiosNav(const CStdString& strBaseDir, CFileItemList& items, int idContent /* = -1 */, const Filter &filter /* = Filter() */) { - return GetNavCommon(strBaseDir, items, "studio", idContent); + return GetNavCommon(strBaseDir, items, "studio", idContent, filter); } -bool CVideoDatabase::GetNavCommon(const CStdString& strBaseDir, CFileItemList& items, const CStdString &type, int idContent) +bool CVideoDatabase::GetNavCommon(const CStdString& strBaseDir, CFileItemList& items, const CStdString &type, int idContent /* = -1 */, const Filter &filter /* = Filter() */) { try { @@ -4355,31 +4361,60 @@ bool CVideoDatabase::GetNavCommon(const CStdString& strBaseDir, CFileItemList& i if (NULL == m_pDS.get()) return false; CStdString strSQL; + Filter extFilter = filter; if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && !g_passwordManager.bMasterUser) { if (idContent == VIDEODB_CONTENT_MOVIES) - strSQL = PrepareSQL("select %s.id%s,%s.str%s,path.strPath,files.playCount from %s join %slinkmovie on %s.id%s=%slinkmovie.id%s join movie on %slinkmovie.idMovie = movie.idMovie join files on files.idFile=movie.idFile join path on path.idPath=files.idPath", - type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str()); + { + strSQL = PrepareSQL("select %s.id%s, %s.str%s, path.strPath, files.playCount from %s ", type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str()); + extFilter.AppendJoin(PrepareSQL("join %slinkmovie on %s.id%s = %slinkmovie.id%s join movieview on %slinkmovie.idMovie = movieview.idMovie join files on files.idFile = movieview.idFile join path on path.idPath = files.idPath", + type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str())); + } else if (idContent == VIDEODB_CONTENT_TVSHOWS) //this will not get tvshows with 0 episodes - strSQL = PrepareSQL("select %s.id%s,%s.str%s,path.strPath from %s join %slinktvshow on %s.id%s=%slinktvshow.id%s join episode on %slinktvshow.idShow=episode.idShow join files on files.idFile=episode.idFile join path on path.idPath=files.idPath", - type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str()); + { + strSQL = PrepareSQL("select %s.id%s, %s.str%s, path.strPath from %s ", type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str()); + extFilter.AppendJoin(PrepareSQL("join %slinktvshow on %s.id%s = %slinktvshow.id%s join episodeview on %slinktvshow.idShow = episodeview.idShow join files on files.idFile = episodeview.idFile join path on path.idPath = files.idPath", + type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str())); + } else if (idContent == VIDEODB_CONTENT_MUSICVIDEOS) - strSQL = PrepareSQL("select %s.id%s,%s.str%s,path.strPath,files.playCount from %s join %slinkmusicvideo on %s.id%s=%slinkmusicvideo.id%s join musicvideo on %slinkmusicvideo.idMVideo = musicvideo.idMVideo join files on files.idFile=musicvideo.idFile join path on path.idPath=files.idPath", - type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str()); + { + strSQL = PrepareSQL("select %s.id%s, %s.str%s, path.strPath, files.playCount from %s ", type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str()); + extFilter.AppendJoin(PrepareSQL("join %slinkmusicvideo on %s.id%s = %slinkmusicvideo.id%s join musicvideoview on %slinkmusicvideo.idMVideo = musicvideoview.idMVideo join files on files.idFile = musicvideoview.idFile join path on path.idPath = files.idPath", + type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str())); + } + else + return false; } else { if (idContent == VIDEODB_CONTENT_MOVIES) - strSQL = PrepareSQL("select %s.id%s,%s.str%s,count(1),count(files.playCount) from %s join %slinkmovie on %s.id%s=%slinkmovie.id%s join movie on %slinkmovie.idMovie=movie.idMovie join files on files.idFile=movie.idFile group by %s.id%s", - type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str()); + { + strSQL = PrepareSQL("select %s.id%s, %s.str%s, count(1), count(files.playCount) from %s ", type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str()); + extFilter.AppendJoin(PrepareSQL("join %slinkmovie on %s.id%s = %slinkmovie.id%s join movieview on %slinkmovie.idMovie = movieview.idMovie join files on files.idFile = movieview.idFile", + type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str())); + extFilter.AppendGroup(PrepareSQL("%s.id%s", type.c_str(), type.c_str())); + } else if (idContent == VIDEODB_CONTENT_TVSHOWS) - strSQL = PrepareSQL("select distinct %s.id%s,%s.str%s from %s join %slinktvshow on %s.id%s=%slinktvshow.id%s join tvshow on %slinktvshow.idShow=tvshow.idShow", - type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str()); + { + strSQL = PrepareSQL("select distinct %s.id%s, %s.str%s from %s ", type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str()); + extFilter.AppendJoin(PrepareSQL("join %slinktvshow on %s.id%s = %slinktvshow.id%s join tvshowview on %slinktvshow.idShow = tvshowview.idShow", + type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str())); + } else if (idContent == VIDEODB_CONTENT_MUSICVIDEOS) - strSQL = PrepareSQL("select %s.id%s,%s.str%s,count(1),count(files.playCount) from %s join %slinkmusicvideo on %s.id%s=%slinkmusicvideo.id%s join musicvideo on %slinkmusicvideo.idMVideo=musicvideo.idMVideo join files on files.idFile=musicvideo.idFile group by %s.id%s", - type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str()); + { + strSQL = PrepareSQL("select %s.id%s, %s.str%s, count(1), count(files.playCount) from %s ", type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str()); + extFilter.AppendJoin(PrepareSQL("join %slinkmusicvideo on %s.id%s = %slinkmusicvideo.id%s join musicvideoview on %slinkmusicvideo.idMVideo = musicvideoview.idMVideo join files on files.idFile = musicvideoview.idFile", + type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str(), type.c_str())); + extFilter.AppendGroup(PrepareSQL("%s.id%s", type.c_str(), type.c_str())); + } + else + return false; } + CVideoDbUrl videoUrl; + if (!BuildSQL(strBaseDir, strSQL, extFilter, strSQL, videoUrl)) + return false; + int iRowsFound = RunQuery(strSQL); if (iRowsFound <= 0) return iRowsFound == 0; @@ -4415,9 +4450,12 @@ bool CVideoDatabase::GetNavCommon(const CStdString& strBaseDir, CFileItemList& i CFileItemPtr pItem(new CFileItem(it->second.first)); pItem->GetVideoInfoTag()->m_iDbId = it->first; pItem->GetVideoInfoTag()->m_type = type; - CStdString strDir; - strDir.Format("%ld/", it->first); - pItem->SetPath(strBaseDir + strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString path; path.Format("%ld/", it->first); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder = true; if (idContent == VIDEODB_CONTENT_MOVIES || idContent == VIDEODB_CONTENT_MUSICVIDEOS) pItem->GetVideoInfoTag()->m_playCount = it->second.second; @@ -4435,9 +4473,12 @@ bool CVideoDatabase::GetNavCommon(const CStdString& strBaseDir, CFileItemList& i CFileItemPtr pItem(new CFileItem(m_pDS->fv(1).get_asString())); pItem->GetVideoInfoTag()->m_iDbId = m_pDS->fv(0).get_asInt(); pItem->GetVideoInfoTag()->m_type = type; - CStdString strDir; - strDir.Format("%ld/", m_pDS->fv(0).get_asInt()); - pItem->SetPath(strBaseDir + strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString path; path.Format("%ld/", m_pDS->fv(0).get_asInt()); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder = true; pItem->SetLabelPreformated(true); if (idContent == VIDEODB_CONTENT_MOVIES || idContent == VIDEODB_CONTENT_MUSICVIDEOS) @@ -4459,7 +4500,7 @@ bool CVideoDatabase::GetNavCommon(const CStdString& strBaseDir, CFileItemList& i return false; } -bool CVideoDatabase::GetTagsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent) +bool CVideoDatabase::GetTagsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent /* = -1 */, const Filter &filter /* = Filter() */) { CStdString mediaType; if (idContent == VIDEODB_CONTENT_MOVIES) @@ -4472,7 +4513,19 @@ bool CVideoDatabase::GetTagsNav(const CStdString& strBaseDir, CFileItemList& ite if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; - int iRowsFound = RunQuery(PrepareSQL("SELECT tag.idTag, tag.strTag FROM taglinks JOIN tag ON tag.idTag = taglinks.idTag WHERE taglinks.media_type = '%s' GROUP BY taglinks.idTag", mediaType.c_str())); + CStdString strSQL = "SELECT tag.idTag, tag.strTag FROM taglinks "; + + Filter extFilter = filter; + extFilter.AppendJoin("JOIN tag ON tag.idTag = taglinks.idTag"); + extFilter.AppendWhere(PrepareSQL("taglinks.media_type = '%s'", mediaType.c_str())); + extFilter.AppendGroup("taglinks.idTag"); + + // parse the base path to get additional filters + CVideoDbUrl videoUrl; + if (!BuildSQL(strBaseDir, strSQL, extFilter, strSQL, videoUrl)) + return false; + + int iRowsFound = RunQuery(strSQL); if (iRowsFound <= 0) return iRowsFound == 0; @@ -4485,8 +4538,10 @@ bool CVideoDatabase::GetTagsNav(const CStdString& strBaseDir, CFileItemList& ite pItem->GetVideoInfoTag()->m_iDbId = idTag; pItem->GetVideoInfoTag()->m_type = "tag"; - CStdString strDir; strDir.Format("%ld/", idTag); - pItem->SetPath(strBaseDir + strDir); + CVideoDbUrl itemUrl = videoUrl; + CStdString path; path.Format("%ld/", idTag); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); if (!items.Contains(pItem->GetPath())) { @@ -4523,10 +4578,12 @@ bool CVideoDatabase::GetSetsByWhere(const CStdString& strBaseDir, const Filter & if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; - CStdString strSQL = "SELECT movieview.*, sets.idSet, sets.strSet FROM movieview" - " JOIN setlinkmovie ON movieview.idMovie = setlinkmovie.idMovie" - " JOIN sets ON setlinkmovie.idSet = sets.idSet" - " JOIN (SELECT idSet, COUNT(1) AS c FROM setlinkmovie GROUP BY idSet HAVING c>1) s2 ON s2.idSet = sets.idSet "; + CVideoDbUrl videoUrl; + if (!videoUrl.FromString(strBaseDir)) + return false; + + CStdString strSQL = "SELECT movieview.*, sets.strSet FROM movieview" + " JOIN sets ON movieview.idSet = sets.idSet "; if (!filter.join.empty()) strSQL += filter.join; if (!filter.where.empty()) @@ -4550,7 +4607,7 @@ bool CVideoDatabase::GetSetsByWhere(const CStdString& strBaseDir, const Filter & continue; // get the setid and check if we already have this set - int idSet = m_pDS->fv("sets.idSet").get_asInt(); + int idSet = m_pDS->fv("movieview.idSet").get_asInt(); if ((it = mapSets.find(idSet)) == mapSets.end()) { // add the set to the list of sets @@ -4577,9 +4634,12 @@ bool CVideoDatabase::GetSetsByWhere(const CStdString& strBaseDir, const Filter & CFileItemPtr pItem(new CFileItem(it->second.name)); pItem->GetVideoInfoTag()->m_iDbId = it->first; pItem->GetVideoInfoTag()->m_type = "set"; - CStdString strDir; - strDir.Format("%s%ld/", strBaseDir.c_str(), it->first); - pItem->SetPath(strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString strDir; strDir.Format("%ld/", it->first); + itemUrl.AppendPath(strDir); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder = true; pItem->GetVideoInfoTag()->m_strPath = pItem->GetPath(); pItem->GetVideoInfoTag()->m_strTitle = pItem->GetLabel(); @@ -4636,7 +4696,7 @@ bool CVideoDatabase::GetSetsByWhere(const CStdString& strBaseDir, const Filter & return false; } -bool CVideoDatabase::GetMusicVideoAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idArtist) +bool CVideoDatabase::GetMusicVideoAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idArtist /* = -1 */, const Filter &filter /* = Filter() */) { try { @@ -4644,18 +4704,25 @@ bool CVideoDatabase::GetMusicVideoAlbumsNav(const CStdString& strBaseDir, CFileI if (NULL == m_pDS.get()) return false; CStdString strSQL; + Filter extFilter = filter; if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && !g_passwordManager.bMasterUser) { - strSQL=PrepareSQL("select musicvideo.c%02d,musicvideo.idMVideo,actors.strActor,path.strPath from musicvideo join artistlinkmusicvideo on artistlinkmusicvideo.idMVideo=musicvideo.idMVideo join actors on actors.idActor=artistlinkmusicvideo.idArtist join files on files.idFile=musicvideo.idFile join path on path.idPath=files.idPath",VIDEODB_ID_MUSICVIDEO_ALBUM); + strSQL = PrepareSQL("select musicvideoview.c%02d, musicvideoview.idMVideo, actors.strActor, path.strPath from musicvideoview ", VIDEODB_ID_MUSICVIDEO_ALBUM); + extFilter.AppendJoin("join artistlinkmusicvideo on artistlinkmusicvideo.idMVideo = musicvideoview.idMVideo join actors on actors.idActor = artistlinkmusicvideo.idArtist join files on files.idFile = musicvideoview.idFile join path on path.idPath = files.idPath"); } else { - strSQL=PrepareSQL("select musicvideo.c%02d,musicvideo.idMVideo,actors.strActor from musicvideo join artistlinkmusicvideo on artistlinkmusicvideo.idMVideo=musicvideo.idMVideo join actors on actors.idActor=artistlinkmusicvideo.idArtist",VIDEODB_ID_MUSICVIDEO_ALBUM); + strSQL = PrepareSQL("select musicvideoview.c%02d, musicvideoview.idMVideo, actors.strActor from musicvideoview ", VIDEODB_ID_MUSICVIDEO_ALBUM); + extFilter.AppendJoin("join artistlinkmusicvideo on artistlinkmusicvideo.idMVideo = musicvideoview.idMVideo join actors on actors.idActor = artistlinkmusicvideo.idArtist"); } if (idArtist > -1) - strSQL += PrepareSQL(" where artistlinkmusicvideo.idArtist=%i",idArtist); + extFilter.AppendWhere(PrepareSQL("artistlinkmusicvideo.idArtist = %i", idArtist)); + + extFilter.AppendGroup(PrepareSQL("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_ALBUM)); - strSQL += PrepareSQL(" group by musicvideo.c%02d",VIDEODB_ID_MUSICVIDEO_ALBUM); + CVideoDbUrl videoUrl; + if (!BuildSQL(strBaseDir, strSQL, extFilter, strSQL, videoUrl)) + return false; int iRowsFound = RunQuery(strSQL); if (iRowsFound <= 0) @@ -4686,9 +4753,12 @@ bool CVideoDatabase::GetMusicVideoAlbumsNav(const CStdString& strBaseDir, CFileI if (!it->second.first.IsEmpty()) { CFileItemPtr pItem(new CFileItem(it->second.first)); - CStdString strDir; - strDir.Format("%ld/", it->first); - pItem->SetPath(strBaseDir + strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString path; path.Format("%ld/", it->first); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder=true; pItem->SetLabelPreformated(true); if (!items.Contains(pItem->GetPath())) @@ -4706,9 +4776,12 @@ bool CVideoDatabase::GetMusicVideoAlbumsNav(const CStdString& strBaseDir, CFileI if (!m_pDS->fv(0).get_asString().empty()) { CFileItemPtr pItem(new CFileItem(m_pDS->fv(0).get_asString())); - CStdString strDir; - strDir.Format("%ld/", m_pDS->fv(1).get_asInt()); - pItem->SetPath(strBaseDir + strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString path; path.Format("%ld/", m_pDS->fv(1).get_asInt()); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder=true; pItem->SetLabelPreformated(true); if (!items.Contains(pItem->GetPath())) @@ -4732,19 +4805,19 @@ bool CVideoDatabase::GetMusicVideoAlbumsNav(const CStdString& strBaseDir, CFileI return false; } -bool CVideoDatabase::GetWritersNav(const CStdString& strBaseDir, CFileItemList& items, int idContent) +bool CVideoDatabase::GetWritersNav(const CStdString& strBaseDir, CFileItemList& items, int idContent /* = -1 */, const Filter &filter /* = Filter() */) { - return GetPeopleNav(strBaseDir, items, "writer", idContent); + return GetPeopleNav(strBaseDir, items, "writer", idContent, filter); } -bool CVideoDatabase::GetDirectorsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent) +bool CVideoDatabase::GetDirectorsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent /* = -1 */, const Filter &filter /* = Filter() */) { - return GetPeopleNav(strBaseDir, items, "director", idContent); + return GetPeopleNav(strBaseDir, items, "director", idContent, filter); } -bool CVideoDatabase::GetActorsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent) +bool CVideoDatabase::GetActorsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent /* = -1 */, const Filter &filter /* = Filter() */) { - if (GetPeopleNav(strBaseDir, items, (idContent == VIDEODB_CONTENT_MUSICVIDEOS) ? "artist" : "actor", idContent)) + if (GetPeopleNav(strBaseDir, items, (idContent == VIDEODB_CONTENT_MUSICVIDEOS) ? "artist" : "actor", idContent, filter)) { // set thumbs - ideally this should be in the normal thumb setting routines for (int i = 0; i < items.Size(); i++) { @@ -4759,7 +4832,7 @@ bool CVideoDatabase::GetActorsNav(const CStdString& strBaseDir, CFileItemList& i return false; } -bool CVideoDatabase::GetPeopleNav(const CStdString& strBaseDir, CFileItemList& items, const CStdString &type, int idContent) +bool CVideoDatabase::GetPeopleNav(const CStdString& strBaseDir, CFileItemList& items, const CStdString &type, int idContent /* = -1 */, const Filter &filter /* = Filter() */) { if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; @@ -4777,35 +4850,73 @@ bool CVideoDatabase::GetPeopleNav(const CStdString& strBaseDir, CFileItemList& i // get primary genres for movies CStdString strSQL; + Filter extFilter = filter; if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && !g_passwordManager.bMasterUser) { if (idContent == VIDEODB_CONTENT_MOVIES) - strSQL=PrepareSQL("select actors.idActor,actors.strActor,actors.strThumb,path.strPath,files.playCount from actors join %slinkmovie on actors.idActor=%slinkmovie.id%s join movie on %slinkmovie.idMovie=movie.idMovie join files on files.idFile=movie.idFile join path on path.idPath=files.idPath", type.c_str(), type.c_str(), type.c_str(), type.c_str()); + { + strSQL = PrepareSQL("select actors.idActor, actors.strActor, actors.strThumb, path.strPath, files.playCount from actors "); + extFilter.AppendJoin(PrepareSQL("join %slinkmovie on actors.idActor = %slinkmovie.id%s join movieview on %slinkmovie.idMovie = movieview.idMovie join files on files.idFile = movieview.idFile join path on path.idPath = files.idPath", + type.c_str(), type.c_str(), type.c_str(), type.c_str())); + } else if (idContent == VIDEODB_CONTENT_TVSHOWS) - strSQL=PrepareSQL("select actors.idActor,actors.strActor,actors.strThumb,path.strPath from actors join %slinktvshow on actors.idActor=%slinktvshow.id%s join episode on %slinktvshow.idShow = episode.idShow join files on files.idFile=episode.idFile join path on path.idPath = files.idPath", type.c_str(), type.c_str(), type.c_str(), type.c_str()); + { + strSQL = PrepareSQL("select actors.idActor, actors.strActor, actors.strThumb, path.strPath from actors "); + extFilter.AppendJoin(PrepareSQL("join %slinktvshow on actors.idActor = %slinktvshow.id%s join episodeview on %slinktvshow.idShow = episodeview.idShow join files on files.idFile = episodeview.idFile join path on path.idPath = files.idPath", + type.c_str(), type.c_str(), type.c_str(), type.c_str())); + } else if (idContent == VIDEODB_CONTENT_EPISODES) - strSQL=PrepareSQL("select actors.idActor,actors.strActor,actors.strThumb,path.strPath,files.playCount from actors join %slinkepisode on actors.idActor=%slinkepisode.id%s join episode on %slinkepisode.idEpisode = episode.idEpisode join files on files.idFile=episode.idFile join path on path.idPath = files.idPath", type.c_str(), type.c_str(), type.c_str(), type.c_str()); + { + strSQL = PrepareSQL("select actors.idActor, actors.strActor, actors.strThumb, path.strPath, files.playCount from actors "); + extFilter.AppendJoin(PrepareSQL("join %slinkepisode on actors.idActor = %slinkepisode.id%s join episodeview on %slinkepisode.idEpisode = episodeview.idEpisode join files on files.idFile = episodeview.idFile join path on path.idPath = files.idPath", + type.c_str(), type.c_str(), type.c_str(), type.c_str())); + } else if (idContent == VIDEODB_CONTENT_MUSICVIDEOS) - strSQL=PrepareSQL("select actors.idActor,actors.strActor,actors.strThumb,path.strPath,files.playCount from actors join %slinkmusicvideo on actors.idActor=%slinkmusicvideo.id%s join musicvideo on %slinkmusicvideo.idMVideo = musicvideo.idMVideo join files on files.idFile=musicvideo.idFile join path on path.idPath = files.idPath", type.c_str(), type.c_str(), type.c_str(), type.c_str()); + { + strSQL = PrepareSQL("select actors.idActor, actors.strActor, actors.strThumb, path.strPath, files.playCount from actors "); + extFilter.AppendJoin(PrepareSQL("join %slinkmusicvideo on actors.idActor = %slinkmusicvideo.id%s join musicvideoview on %slinkmusicvideo.idMVideo = musicvideoview.idMVideo join files on files.idFile = musicvideoview.idFile join path on path.idPath = files.idPath", + type.c_str(), type.c_str(), type.c_str(), type.c_str())); + } + else + return false; } else { if (idContent == VIDEODB_CONTENT_MOVIES) { - strSQL=PrepareSQL("select actors.idActor,actors.strActor,actors.strThumb,count(1),count(files.playCount) from actors join %slinkmovie on actors.idActor=%slinkmovie.id%s join movie on %slinkmovie.idMovie=movie.idMovie join files on files.idFile=movie.idFile", type.c_str(), type.c_str(), type.c_str(), type.c_str()); - strSQL += " group by actors.idActor"; + strSQL = PrepareSQL("select actors.idActor, actors.strActor, actors.strThumb, count(1), count(files.playCount) from actors "); + extFilter.AppendJoin(PrepareSQL("join %slinkmovie on actors.idActor = %slinkmovie.id%s join movieview on %slinkmovie.idMovie = movieview.idMovie join files on files.idFile = movieview.idFile", + type.c_str(), type.c_str(), type.c_str(), type.c_str())); + extFilter.AppendGroup("actors.idActor"); } else if (idContent == VIDEODB_CONTENT_TVSHOWS) - strSQL=PrepareSQL("select distinct actors.idActor,actors.strActor,actors.strThumb from actors,%slinktvshow,tvshow where actors.idActor=%slinktvshow.id%s and %slinktvshow.idShow=tvshow.idShow", type.c_str(), type.c_str(), type.c_str(), type.c_str()); + { + strSQL = PrepareSQL("select distinct actors.idActor, actors.strActor, actors.strThumb from actors, %slinktvshow, tvshowview ", type.c_str()); + extFilter.AppendWhere(PrepareSQL("actors.idActor = %slinktvshow.id%s and %slinktvshow.idShow = tvshowview.idShow", + type.c_str(), type.c_str(), type.c_str())); + } else if (idContent == VIDEODB_CONTENT_EPISODES) - strSQL=PrepareSQL("select actors.idActor,actors.strActor,actors.strThumb,count(1),count(files.playCount) from %slinkepisode,actors,episode,files where actors.idActor=%slinkepisode.id%s and %slinkepisode.idEpisode=episode.idEpisode and files.idFile=episode.idFile group by actors.idActor", type.c_str(), type.c_str(), type.c_str(), type.c_str()); + { + strSQL = PrepareSQL("select actors.idActor, actors.strActor, actors.strThumb, count(1), count(files.playCount) from %slinkepisode, actors, episodeview, files ", type.c_str()); + extFilter.AppendWhere(PrepareSQL("actors.idActor = %slinkepisode.id%s and %slinkepisode.idEpisode = episodeview.idEpisode and files.idFile = episodeview.idFile", + type.c_str(), type.c_str(), type.c_str())); + extFilter.AppendGroup("actors.idActor"); + } else if (idContent == VIDEODB_CONTENT_MUSICVIDEOS) { - strSQL=PrepareSQL("select actors.idActor,actors.strActor,actors.strThumb,count(1),count(files.playCount) from actors join %slinkmusicvideo on actors.idActor=%slinkmusicvideo.id%s join musicvideo on %slinkmusicvideo.idMVideo=musicvideo.idMVideo join files on files.idFile=musicvideo.idFile", type.c_str(), type.c_str(), type.c_str(), type.c_str()); - strSQL += " group by actors.idActor"; + strSQL = PrepareSQL("select actors.idActor, actors.strActor, actors.strThumb, count(1), count(files.playCount) from actors "); + extFilter.AppendJoin(PrepareSQL("join %slinkmusicvideo on actors.idActor = %slinkmusicvideo.id%s join musicvideoview on %slinkmusicvideo.idMVideo = musicvideoview.idMVideo join files on files.idFile = musicvideoview.idFile", + type.c_str(), type.c_str(), type.c_str(), type.c_str())); + extFilter.AppendGroup("actors.idActor"); } + else + return false; } + CVideoDbUrl videoUrl; + if (!BuildSQL(strBaseDir, strSQL, extFilter, strSQL, videoUrl)) + return false; + // run query unsigned int time = XbmcThreads::SystemClockMillis(); if (!m_pDS->query(strSQL.c_str())) return false; @@ -4846,9 +4957,12 @@ bool CVideoDatabase::GetPeopleNav(const CStdString& strBaseDir, CFileItemList& i for (it=mapActors.begin();it != mapActors.end();++it) { CFileItemPtr pItem(new CFileItem(it->second.name)); - CStdString strDir; - strDir.Format("%ld/", it->first); - pItem->SetPath(strBaseDir + strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString path; path.Format("%ld/", it->first); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder=true; pItem->GetVideoInfoTag()->m_playCount = it->second.playcount; pItem->GetVideoInfoTag()->m_strPictureURL.ParseString(it->second.thumb); @@ -4864,9 +4978,12 @@ bool CVideoDatabase::GetPeopleNav(const CStdString& strBaseDir, CFileItemList& i try { CFileItemPtr pItem(new CFileItem(m_pDS->fv(1).get_asString())); - CStdString strDir; - strDir.Format("%ld/", m_pDS->fv(0).get_asInt()); - pItem->SetPath(strBaseDir + strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString path; path.Format("%ld/", m_pDS->fv(0).get_asInt()); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder=true; pItem->GetVideoInfoTag()->m_strPictureURL.ParseString(m_pDS->fv(2).get_asString()); pItem->GetVideoInfoTag()->m_iDbId = m_pDS->fv(0).get_asInt(); @@ -4904,9 +5021,7 @@ bool CVideoDatabase::GetPeopleNav(const CStdString& strBaseDir, CFileItemList& i return false; } - - -bool CVideoDatabase::GetYearsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent) +bool CVideoDatabase::GetYearsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent /* = -1 */, const Filter &filter /* = Filter() */) { try { @@ -4914,33 +5029,52 @@ bool CVideoDatabase::GetYearsNav(const CStdString& strBaseDir, CFileItemList& it if (NULL == m_pDS.get()) return false; CStdString strSQL; + Filter extFilter = filter; if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && !g_passwordManager.bMasterUser) { if (idContent == VIDEODB_CONTENT_MOVIES) - strSQL = PrepareSQL("select movie.c%02d,path.strPath,files.playCount from movie join files on files.idFile=movie.idFile join path on files.idPath = path.idPath", VIDEODB_ID_YEAR); + { + strSQL = PrepareSQL("select movieview.c%02d, path.strPath, files.playCount from movieview ", VIDEODB_ID_YEAR); + extFilter.AppendJoin("join files on files.idFile = movieview.idFile join path on files.idPath = path.idPath"); + } else if (idContent == VIDEODB_CONTENT_TVSHOWS) - strSQL = PrepareSQL("select tvshow.c%02d,path.strPath from tvshow join files on files.idFile=episode.idFile join episode on episode.idShow=tvshow.idShow join path on files.idPath = path.idPath", VIDEODB_ID_TV_PREMIERED); + { + strSQL = PrepareSQL("select tvshowview.c%02d, path.strPath from tvshowview ", VIDEODB_ID_TV_PREMIERED); + extFilter.AppendJoin("join episodeview on episodeview.idShow = tvshowview.idShow join files on files.idFile = episodeview.idFile join path on files.idPath = path.idPath"); + } else if (idContent == VIDEODB_CONTENT_MUSICVIDEOS) - strSQL = PrepareSQL("select musicvideo.c%02d,path.strPath,files.playCount from musicvideo join files on files.idFile=musicvideo.idFile join path on files.idPath = path.idPath", VIDEODB_ID_MUSICVIDEO_YEAR); + { + strSQL = PrepareSQL("select musicvideoview.c%02d, path.strPath, files.playCount from musicvideoview ", VIDEODB_ID_MUSICVIDEO_YEAR); + extFilter.AppendJoin("join files on files.idFile = musicvideoview.idFile join path on files.idPath = path.idPath"); + } + else + return false; } else { CStdString group; if (idContent == VIDEODB_CONTENT_MOVIES) { - strSQL = PrepareSQL("select movie.c%02d,count(1),count(files.playCount) from movie join files on files.idFile=movie.idFile", VIDEODB_ID_YEAR); - group = PrepareSQL(" group by movie.c%02d", VIDEODB_ID_YEAR); + strSQL = PrepareSQL("select movieview.c%02d, count(1), count(files.playCount) from movieview ", VIDEODB_ID_YEAR); + extFilter.AppendJoin("join files on files.idFile = movieview.idFile"); + extFilter.AppendGroup(PrepareSQL("movieview.c%02d", VIDEODB_ID_YEAR)); } else if (idContent == VIDEODB_CONTENT_TVSHOWS) - strSQL = PrepareSQL("select distinct tvshow.c%02d from tvshow", VIDEODB_ID_TV_PREMIERED); + strSQL = PrepareSQL("select distinct tvshowview.c%02d from tvshowview", VIDEODB_ID_TV_PREMIERED); else if (idContent == VIDEODB_CONTENT_MUSICVIDEOS) { - strSQL = PrepareSQL("select musicvideo.c%02d,count(1),count(files.playCount) from musicvideo join files on files.idFile=musicvideo.idFile", VIDEODB_ID_MUSICVIDEO_YEAR); - group = PrepareSQL(" group by musicvideo.c%02d", VIDEODB_ID_MUSICVIDEO_YEAR); + strSQL = PrepareSQL("select musicvideoview.c%02d, count(1), count(files.playCount) from musicvideoview ", VIDEODB_ID_MUSICVIDEO_YEAR); + extFilter.AppendJoin("join files on files.idFile = musicvideoview.idFile"); + extFilter.AppendGroup(PrepareSQL("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_YEAR)); } - strSQL += group; + else + return false; } + CVideoDbUrl videoUrl; + if (!BuildSQL(strBaseDir, strSQL, extFilter, strSQL, videoUrl)) + return false; + int iRowsFound = RunQuery(strSQL); if (iRowsFound <= 0) return iRowsFound == 0; @@ -4983,9 +5117,12 @@ bool CVideoDatabase::GetYearsNav(const CStdString& strBaseDir, CFileItemList& it if (it->first == 0) continue; CFileItemPtr pItem(new CFileItem(it->second.first)); - CStdString strDir; - strDir.Format("%ld/", it->first); - pItem->SetPath(strBaseDir + strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString path; path.Format("%ld/", it->first); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder=true; if (idContent == VIDEODB_CONTENT_MOVIES || idContent == VIDEODB_CONTENT_MUSICVIDEOS) pItem->GetVideoInfoTag()->m_playCount = it->second.second; @@ -5016,9 +5153,12 @@ bool CVideoDatabase::GetYearsNav(const CStdString& strBaseDir, CFileItemList& it continue; } CFileItemPtr pItem(new CFileItem(strLabel)); - CStdString strDir; - strDir.Format("%ld/", lYear); - pItem->SetPath(strBaseDir + strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString path; path.Format("%ld/", lYear); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder=true; if (idContent == VIDEODB_CONTENT_MOVIES || idContent == VIDEODB_CONTENT_MUSICVIDEOS) { @@ -5045,7 +5185,7 @@ bool CVideoDatabase::GetYearsNav(const CStdString& strBaseDir, CFileItemList& it return false; } -bool CVideoDatabase::GetStackedTvShowList(int idShow, CStdString& strIn) +bool CVideoDatabase::GetStackedTvShowList(int idShow, CStdString& strIn) const { try { @@ -5087,51 +5227,43 @@ bool CVideoDatabase::GetSeasonsNav(const CStdString& strBaseDir, CFileItemList& if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; + // parse the base path to get additional filters + CVideoDbUrl videoUrl; + if (!videoUrl.FromString(strBaseDir)) + return false; + CStdString strIn = PrepareSQL("= %i", idShow); GetStackedTvShowList(idShow, strIn); - CStdString strSQL = PrepareSQL("SELECT episode.c%02d," - " path.strPath," - " tvshow.c%02d," - " tvshow.c%02d," - " tvshow.c%02d," - " tvshow.c%02d," - " seasons.idSeason," - " count(1)," - " count(files.playCount) " - "FROM episode" - " JOIN tvshow ON" - " tvshow.idShow=episode.idShow" - " JOIN seasons ON" - " (seasons.idShow=tvshow.idShow AND seasons.season=episode.c%02d)" - " JOIN files ON" - " files.idFile=episode.idFile ", VIDEODB_ID_EPISODE_SEASON, VIDEODB_ID_TV_TITLE, VIDEODB_ID_TV_GENRE, VIDEODB_ID_TV_STUDIOS, VIDEODB_ID_TV_MPAA, VIDEODB_ID_EPISODE_SEASON); - CStdString joins = PrepareSQL(" JOIN tvshowlinkpath ON" - " tvshowlinkpath.idShow = tvshow.idShow" - " JOIN path ON" - " path.idPath = tvshowlinkpath.idPath " - "WHERE tvshow.idShow %s ", strIn.c_str()); - CStdString extraJoins, extraWhere; + CStdString strSQL = PrepareSQL("SELECT episodeview.c%02d, " + "path.strPath, " + "tvshowview.c%02d, tvshowview.c%02d, tvshowview.c%02d, tvshowview.c%02d, " + "seasons.idSeason, " + "count(1), count(files.playCount) " + "FROM episodeview ", VIDEODB_ID_EPISODE_SEASON, VIDEODB_ID_TV_TITLE, VIDEODB_ID_TV_GENRE, VIDEODB_ID_TV_STUDIOS, VIDEODB_ID_TV_MPAA); + + Filter filter; + filter.join = PrepareSQL("JOIN tvshowview ON tvshowview.idShow = episodeview.idShow " + "JOIN seasons ON (seasons.idShow = tvshowview.idShow AND seasons.season = episodeview.c%02d) " + "JOIN files ON files.idFile = episodeview.idFile " + "JOIN tvshowlinkpath ON tvshowlinkpath.idShow = tvshowview.idShow " + "JOIN path ON path.idPath = tvshowlinkpath.idPath", VIDEODB_ID_EPISODE_SEASON); + filter.where = PrepareSQL("tvshowview.idShow %s", strIn.c_str()); + filter.group = PrepareSQL("episodeview.c%02d", VIDEODB_ID_EPISODE_SEASON); + + videoUrl.AddOption("tvshowid", idShow); + if (idActor != -1) - { - extraJoins = "join actorlinktvshow on actorlinktvshow.idShow=tvshow.idShow"; - extraWhere = PrepareSQL("and actorlinktvshow.idActor=%i", idActor); - } + videoUrl.AddOption("actorid", idActor); else if (idDirector != -1) - { - extraJoins = "join directorlinktvshow on directorlinktvshow.idShow=tvshow.idShow"; - extraWhere = PrepareSQL("and directorlinktvshow.idDirector=%i",idDirector); - } + videoUrl.AddOption("directorid", idDirector); else if (idGenre != -1) - { - extraJoins = "join genrelinktvshow on genrelinktvshow.idShow=tvshow.idShow"; - extraWhere = PrepareSQL("and genrelinktvshow.idGenre=%i", idGenre); - } + videoUrl.AddOption("genreid", idGenre); else if (idYear != -1) - { - extraWhere = PrepareSQL("and tvshow.c%02d like '%%%i%%'", VIDEODB_ID_TV_PREMIERED, idYear); - } - strSQL += extraJoins + joins + extraWhere + PrepareSQL(" group by episode.c%02d", VIDEODB_ID_EPISODE_SEASON); + videoUrl.AddOption("year", idYear); + + if (!BuildSQL(strBaseDir, strSQL, filter, strSQL, videoUrl)) + return false; int iRowsFound = RunQuery(strSQL); if (iRowsFound <= 0) @@ -5179,9 +5311,12 @@ bool CVideoDatabase::GetSeasonsNav(const CStdString& strBaseDir, CFileItemList& else strLabel.Format(g_localizeStrings.Get(20358),iSeason); CFileItemPtr pItem(new CFileItem(strLabel)); - CStdString strDir; - strDir.Format("%ld/", it->first); - pItem->SetPath(strBaseDir + strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString strDir; strDir.Format("%ld/", it->first); + itemUrl.AppendPath(strDir); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder=true; pItem->GetVideoInfoTag()->m_strTitle = strLabel; pItem->GetVideoInfoTag()->m_iSeason = iSeason; @@ -5215,9 +5350,12 @@ bool CVideoDatabase::GetSeasonsNav(const CStdString& strBaseDir, CFileItemList& else strLabel.Format(g_localizeStrings.Get(20358),iSeason); CFileItemPtr pItem(new CFileItem(strLabel)); - CStdString strDir; - strDir.Format("%ld/", iSeason); - pItem->SetPath(strBaseDir + strDir); + + CVideoDbUrl itemUrl = videoUrl; + CStdString strDir; strDir.Format("%ld/", iSeason); + itemUrl.AppendPath(strDir); + pItem->SetPath(itemUrl.ToString()); + pItem->m_bIsFolder=true; pItem->GetVideoInfoTag()->m_strTitle = strLabel; pItem->GetVideoInfoTag()->m_iSeason = iSeason; @@ -5244,11 +5382,13 @@ bool CVideoDatabase::GetSeasonsNav(const CStdString& strBaseDir, CFileItemList& } m_pDS->close(); } + // now add any linked movies - Filter filter; - filter.join = PrepareSQL("join movielinktvshow on movielinktvshow.idMovie=movieview.idMovie"); - filter.where = PrepareSQL("movielinktvshow.idShow %s", strIn.c_str()); - GetMoviesByWhere("videodb://1/2/", filter, items); + Filter movieFilter; + movieFilter.join = PrepareSQL("join movielinktvshow on movielinktvshow.idMovie=movieview.idMovie"); + movieFilter.where = PrepareSQL("movielinktvshow.idShow %s", strIn.c_str()); + GetMoviesByWhere("videodb://1/2/", movieFilter, items); + return true; } catch (...) @@ -5307,48 +5447,32 @@ bool CVideoDatabase::GetSortedVideos(MediaType mediaType, const CStdString& strB bool CVideoDatabase::GetMoviesNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre /* = -1 */, int idYear /* = -1 */, int idActor /* = -1 */, int idDirector /* = -1 */, - int idStudio /* = -1 */, int idCountry /* = -1 */, int idSet /* = -1 */, int idTag /* = -1 */) + int idStudio /* = -1 */, int idCountry /* = -1 */, int idSet /* = -1 */, int idTag /* = -1 */, + const SortDescription &sortDescription /* = SortDescription() */) { - Filter filter; - if (idGenre != -1) - { - filter.join = PrepareSQL("join genrelinkmovie on genrelinkmovie.idMovie=movieview.idMovie"); - filter.where = PrepareSQL("genrelinkmovie.idGenre=%i", idGenre); - } - else if (idCountry != -1) - { - filter.join = PrepareSQL("join countrylinkmovie on countrylinkmovie.idMovie=movieview.idMovie"); - filter.where = PrepareSQL("countrylinkmovie.idCountry=%i", idCountry); - } - else if (idStudio != -1) - { - filter.join = PrepareSQL("join studiolinkmovie on studiolinkmovie.idMovie=movieview.idMovie"); - filter.where = PrepareSQL("studiolinkmovie.idStudio=%i", idStudio); - } - else if (idDirector != -1) - { - filter.join = PrepareSQL("join directorlinkmovie on directorlinkmovie.idMovie=movieview.idMovie"); - filter.where = PrepareSQL("directorlinkmovie.idDirector=%i", idDirector); - } - else if (idYear !=-1) - filter.where = PrepareSQL("c%02d='%i'",VIDEODB_ID_YEAR,idYear); - else if (idActor != -1) - { - filter.join = PrepareSQL("join actorlinkmovie on actorlinkmovie.idMovie=movieview.idMovie join actors on actors.idActor=actorlinkmovie.idActor"); - filter.where = PrepareSQL("actors.idActor=%i",idActor); - } - else if (idSet != -1) - { - filter.join = PrepareSQL("join setlinkmovie on setlinkmovie.idMovie=movieview.idMovie"); - filter.where = PrepareSQL("setlinkmovie.idSet=%u",idSet); - } - else if (idTag != -1) - { - filter.join = PrepareSQL("join taglinks on taglinks.idMedia = movieview.idMovie AND taglinks.media_type = 'movie'"); - filter.where = PrepareSQL("taglinks.idTag = %u", idTag); - } + CVideoDbUrl videoUrl; + if (!videoUrl.FromString(strBaseDir)) + return false; - return GetMoviesByWhere(strBaseDir, filter, items, idSet == -1); + if (idGenre > 0) + videoUrl.AddOption("genreid", idGenre); + else if (idCountry > 0) + videoUrl.AddOption("countryid", idCountry); + else if (idStudio > 0) + videoUrl.AddOption("studioid", idStudio); + else if (idDirector > 0) + videoUrl.AddOption("directorid", idDirector); + else if (idYear > 0) + videoUrl.AddOption("year", idYear); + else if (idActor > 0) + videoUrl.AddOption("actorid", idActor); + else if (idSet > 0) + videoUrl.AddOption("setid", idSet); + else if (idTag > 0) + videoUrl.AddOption("tagid", idTag); + + Filter filter; + return GetMoviesByWhere(videoUrl.ToString(), filter, items, idSet == -1, sortDescription); } bool CVideoDatabase::GetMoviesByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, bool fetchSets /* = false */, const SortDescription &sortDescription /* = SortDescription() */) @@ -5361,6 +5485,12 @@ bool CVideoDatabase::GetMoviesByWhere(const CStdString& strBaseDir, const Filter if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; + // parse the base path to get additional filters + CVideoDbUrl videoUrl; + Filter extFilter = filter; + if (!videoUrl.FromString(strBaseDir) || !GetFilter(videoUrl, extFilter)) + return false; + int total = -1; CStdString strSQL = "select %s from movieview "; @@ -5370,57 +5500,46 @@ bool CVideoDatabase::GetMoviesByWhere(const CStdString& strBaseDir, const Filter { // user wants sets (and we're not fetching a particular set node), so grab all sets that match this where clause first Filter setsFilter; - if (!filter.where.empty() || !filter.join.empty()) + if (!extFilter.where.empty() || !extFilter.join.empty()) { setsFilter.where = "movieview.idMovie in (select movieview.idMovie from movieview "; - if (!filter.join.empty()) - setsFilter.where += filter.join; - if (!filter.where.empty()) - setsFilter.where += " WHERE " + filter.where; + if (!extFilter.join.empty()) + setsFilter.where += extFilter.join; + if (!extFilter.where.empty()) + setsFilter.where += " WHERE " + extFilter.where; setsFilter.where += ")"; } - GetSetsByWhere("videodb://1/7/", setsFilter, setItems); + + CVideoDbUrl setUrl; + setUrl.FromString("videodb://1/7/"); + setUrl.AddOptions(videoUrl.GetOptionsString()); + GetSetsByWhere(setUrl.ToString(), setsFilter, setItems); + CStdString movieSetsWhere; if (setItems.Size() > 0) { - movieSetsWhere = "movieview.idMovie NOT IN (SELECT idMovie FROM setlinkmovie s1 JOIN(SELECT idSet, COUNT(1) AS c FROM setlinkmovie GROUP BY idSet HAVING c>1) s2 ON s2.idSet=s1.idSet WHERE s1.idSet IN ("; + movieSetsWhere = "movieview.idMovie NOT IN (SELECT idMovie FROM movieview WHERE movieview.idSet IN ("; for (int index = 0; index < setItems.Size(); index++) movieSetsWhere.AppendFormat("%s%d", index > 0 ? "," : "", setItems[index]->GetVideoInfoTag()->m_iDbId); movieSetsWhere += "))"; + + extFilter.AppendWhere(movieSetsWhere); } - if (!filter.join.empty()) - strSQLExtra += filter.join; - if (!filter.where.empty()) - { - strSQLExtra += " WHERE (" + filter.where + ")"; - if (!movieSetsWhere.empty()) - strSQLExtra += " AND " + movieSetsWhere; - } - else if (!movieSetsWhere.empty()) - strSQLExtra += " WHERE " + movieSetsWhere; - } - else - { - if (!filter.join.empty()) - strSQLExtra += filter.join; - if (!filter.where.empty()) - strSQLExtra += " WHERE " + filter.where; } - if (!filter.group.empty()) - strSQLExtra += " GROUP BY " + filter.group; - if (filter.order.size()) - strSQLExtra += " ORDER BY " + filter.order; - if (!filter.limit.empty()) - strSQLExtra += " LIMIT " + filter.limit; - else if (sortDescription.sortBy == SortByNone && - (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) + if (!CDatabase::BuildSQL(strSQLExtra, extFilter, strSQLExtra)) + return false; + + // Apply the limiting directly here if there's no special sorting but limiting + if (extFilter.limit.empty() && + sortDescription.sortBy == SortByNone && + (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) { total = (int)strtol(GetSingleValue(PrepareSQL(strSQL, "COUNT(1)") + strSQLExtra, m_pDS).c_str(), NULL, 10); strSQLExtra += DatabaseUtils::BuildLimitClause(sortDescription.limitEnd, sortDescription.limitStart); } - strSQL = PrepareSQL(strSQL, !filter.fields.empty() ? filter.fields.c_str() : "*") + strSQLExtra; + strSQL = PrepareSQL(strSQL, !extFilter.fields.empty() ? extFilter.fields.c_str() : "*") + strSQLExtra; int iRowsFound = RunQuery(strSQL); if (iRowsFound <= 0 && setItems.Size() == 0) @@ -5468,8 +5587,12 @@ bool CVideoDatabase::GetMoviesByWhere(const CStdString& strBaseDir, const Filter g_passwordManager.IsDatabasePathUnlocked(movie.m_strPath, g_settings.m_videoSources)) { CFileItemPtr pItem(new CFileItem(movie)); - CStdString path; path.Format("%s%ld", strBaseDir.c_str(), movie.m_iDbId); - pItem->SetPath(path); + + CVideoDbUrl itemUrl = videoUrl; + CStdString path; path.Format("%ld", movie.m_iDbId); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); + pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED,movie.m_playCount > 0); items.Add(pItem); } @@ -5486,33 +5609,27 @@ bool CVideoDatabase::GetMoviesByWhere(const CStdString& strBaseDir, const Filter return false; } -bool CVideoDatabase::GetTvShowsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idYear, int idActor, int idDirector, int idStudio) +bool CVideoDatabase::GetTvShowsNav(const CStdString& strBaseDir, CFileItemList& items, + int idGenre /* = -1 */, int idYear /* = -1 */, int idActor /* = -1 */, int idDirector /* = -1 */, int idStudio /* = -1 */, + const SortDescription &sortDescription /* = SortDescription() */) { - Filter filter; + CVideoDbUrl videoUrl; + if (!videoUrl.FromString(strBaseDir)) + return false; + if (idGenre != -1) - { - filter.join = PrepareSQL("join genrelinktvshow on genrelinktvshow.idShow=tvshowview.idShow"); - filter.where = PrepareSQL("genrelinktvshow.idGenre=%i ", idGenre); - } + videoUrl.AddOption("genreid", idGenre); else if (idStudio != -1) - { - filter.join = PrepareSQL("join studiolinktvshow on studiolinktvshow.idShow=tvshowview.idShow"); - filter.where = PrepareSQL("studiolinktvshow.idStudio=%i", idStudio); - } + videoUrl.AddOption("studioid", idStudio); else if (idDirector != -1) - { - filter.join = PrepareSQL("join directorlinktvshow on directorlinktvshow.idShow=tvshowview.idShow"); - filter.where = PrepareSQL("directorlinktvshow.idDirector=%i", idDirector); - } + videoUrl.AddOption("directorid", idDirector); else if (idYear != -1) - filter.where = PrepareSQL("c%02d like '%%%i%%'", VIDEODB_ID_TV_PREMIERED,idYear); + videoUrl.AddOption("year", idYear); else if (idActor != -1) - { - filter.join = PrepareSQL("join actorlinktvshow on actorlinktvshow.idShow=tvshowview.idShow join actors on actors.idActor=actorlinktvshow.idActor"); - filter.where = PrepareSQL("actors.idActor=%i",idActor); - } + videoUrl.AddOption("actorid", idActor); - return GetTvShowsByWhere(strBaseDir, filter, items); + Filter filter; + return GetTvShowsByWhere(videoUrl.ToString(), filter, items, sortDescription); } bool CVideoDatabase::GetTvShowsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription /* = SortDescription() */) @@ -5525,28 +5642,24 @@ bool CVideoDatabase::GetTvShowsByWhere(const CStdString& strBaseDir, const Filte if (NULL == m_pDS.get()) return false; int total = -1; - + CStdString strSQL = "SELECT %s FROM tvshowview "; + CVideoDbUrl videoUrl; CStdString strSQLExtra; - if (!filter.join.empty()) - strSQLExtra += filter.join; - if (!filter.where.empty()) - strSQLExtra += " WHERE " + filter.where; - if (!filter.group.empty()) - strSQLExtra += " GROUP BY " + filter.group; - if (!filter.order.empty()) - strSQLExtra += " ORDER BY " + filter.order; - if (!filter.limit.empty()) - strSQLExtra += " LIMIT " + filter.limit; + Filter extFilter = filter; + if (!BuildSQL(strBaseDir, strSQLExtra, extFilter, strSQLExtra, videoUrl)) + return false; + // Apply the limiting directly here if there's no special sorting but limiting - else if (sortDescription.sortBy == SortByNone && - (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) + if (extFilter.limit.empty() && + sortDescription.sortBy == SortByNone && + (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) { total = (int)strtol(GetSingleValue(PrepareSQL(strSQL, "COUNT(1)") + strSQLExtra, m_pDS).c_str(), NULL, 10); strSQLExtra += DatabaseUtils::BuildLimitClause(sortDescription.limitEnd, sortDescription.limitStart); } - strSQL = PrepareSQL(strSQL, !filter.fields.empty() ? filter.fields.c_str() : "*") + strSQLExtra; + strSQL = PrepareSQL(strSQL, !extFilter.fields.empty() ? extFilter.fields.c_str() : "*") + strSQLExtra; int iRowsFound = RunQuery(strSQL); if (iRowsFound <= 0) @@ -5577,8 +5690,12 @@ bool CVideoDatabase::GetTvShowsByWhere(const CStdString& strBaseDir, const Filte (!g_advancedSettings.m_bVideoLibraryHideEmptySeries || movie.m_iEpisode > 0)) { CFileItemPtr pItem(new CFileItem(movie)); - CStdString path; path.Format("%s%ld/", strBaseDir.c_str(), record->at(0).get_asInt()); - pItem->SetPath(path); + + CVideoDbUrl itemUrl = videoUrl; + CStdString path; path.Format("%ld/", record->at(0).get_asInt()); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); + pItem->m_dateTime = movie.m_premiered; pItem->GetVideoInfoTag()->m_iYear = pItem->m_dateTime.GetYear(); pItem->SetProperty("totalseasons", record->at(VIDEODB_DETAILS_TVSHOW_NUM_SEASONS).get_asInt()); @@ -5783,60 +5900,44 @@ void CVideoDatabase::Stack(CFileItemList& items, VIDEODB_CONTENT_TYPE type, bool bool CVideoDatabase::GetEpisodesNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idYear, int idActor, int idDirector, int idShow, int idSeason, const SortDescription &sortDescription /* = SortDescription() */) { - Filter filter; + CVideoDbUrl videoUrl; + if (!videoUrl.FromString(strBaseDir)) + return false; + CStdString strIn; if (idShow != -1) { strIn = PrepareSQL("= %i", idShow); GetStackedTvShowList(idShow, strIn); + videoUrl.AddOption("tvshowid", idShow); + if (idSeason >= 0) + videoUrl.AddOption("season", idSeason); + if (idGenre != -1) - { - filter.join = PrepareSQL("join genrelinktvshow on genrelinktvshow.idShow=episodeview.idShow"); - filter.where = PrepareSQL("episodeview.idShow=%i and genrelinktvshow.idGenre=%i",idShow,idGenre); - } - else if (idDirector != -1) - { - filter.join = PrepareSQL("join directorlinktvshow on directorlinktvshow.idShow=episodeview.idShow"); - filter.where = PrepareSQL("episodeview.idShow=%i and directorlinktvshow.idDirector=%i",idShow,idDirector); - } + videoUrl.AddOption("genreid", idGenre); else if (idYear !=-1) - { - filter.where = PrepareSQL("idShow=%i and premiered like '%%%i%%'", idShow, idYear); - } + videoUrl.AddOption("year", idYear); else if (idActor != -1) - { - filter.join = PrepareSQL("join actorlinktvshow on actorlinktvshow.idShow=episodeview.idShow"); - filter.where = PrepareSQL("episodeview.idShow=%i and actorlinktvshow.idActor=%i",idShow,idActor); - } - else - filter.where = PrepareSQL("idShow %s",strIn.c_str()); - - if (idSeason != -1) - { - if (idSeason == 0) // season = 0 indicates a special - we grab all specials here (see below) - filter.where += PrepareSQL(" and c%02d=%i",VIDEODB_ID_EPISODE_SEASON,idSeason); - else - filter.where += PrepareSQL(" and (c%02d=%i or (c%02d=0 and (c%02d=0 or c%02d=%i)))",VIDEODB_ID_EPISODE_SEASON,idSeason,VIDEODB_ID_EPISODE_SEASON, VIDEODB_ID_EPISODE_SORTSEASON, VIDEODB_ID_EPISODE_SORTSEASON,idSeason); - } + videoUrl.AddOption("actorid", idActor); } - else if (idYear !=-1) - filter.where = PrepareSQL("premiered like '%%%i%%'", idYear); - - // we always append show, season + episode in GetEpisodesByWhere - CStdString parent, grandParent; - URIUtils::GetParentPath(strBaseDir,parent); - URIUtils::GetParentPath(parent,grandParent); + else if (idYear != -1) + videoUrl.AddOption("year", idYear); + + if (idDirector != -1) + videoUrl.AddOption("directorid", idDirector); - bool ret = GetEpisodesByWhere(grandParent, filter, items, true, sortDescription); + Filter filter; + bool ret = GetEpisodesByWhere(videoUrl.ToString(), filter, items, false, sortDescription); if (idSeason == -1 && idShow != -1) { // add any linked movies - Filter filter; - filter.join = PrepareSQL("join movielinktvshow on movielinktvshow.idMovie=movieview.idMovie"); - filter.where = PrepareSQL("movielinktvshow.idShow %s", strIn.c_str()); - GetMoviesByWhere("videodb://1/2/", filter, items); + Filter movieFilter; + movieFilter.join = PrepareSQL("join movielinktvshow on movielinktvshow.idMovie=movieview.idMovie"); + movieFilter.where = PrepareSQL("movielinktvshow.idShow %s", strIn.c_str()); + GetMoviesByWhere("videodb://1/2/", movieFilter, items); } + return ret; } @@ -5851,28 +5952,24 @@ bool CVideoDatabase::GetEpisodesByWhere(const CStdString& strBaseDir, const Filt if (NULL == m_pDS.get()) return false; int total = -1; - + CStdString strSQL = "select %s from episodeview "; + CVideoDbUrl videoUrl; CStdString strSQLExtra; - if (!filter.join.empty()) - strSQLExtra += filter.join; - if (!filter.where.empty()) - strSQLExtra += " WHERE " + filter.where; - if (!filter.group.empty()) - strSQLExtra += " GROUP BY " + filter.group; - if (!filter.order.empty()) - strSQLExtra += " ORDER BY " + filter.order; - if (!filter.limit.empty()) - strSQLExtra += " LIMIT " + filter.limit; + Filter extFilter = filter; + if (!BuildSQL(strBaseDir, strSQLExtra, extFilter, strSQLExtra, videoUrl)) + return false; + // Apply the limiting directly here if there's no special sorting but limiting - else if (sortDescription.sortBy == SortByNone && - (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) + if (extFilter.limit.empty() && + sortDescription.sortBy == SortByNone && + (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) { total = (int)strtol(GetSingleValue(PrepareSQL(strSQL, "COUNT(1)") + strSQLExtra, m_pDS).c_str(), NULL, 10); strSQLExtra += DatabaseUtils::BuildLimitClause(sortDescription.limitEnd, sortDescription.limitStart); } - strSQL = PrepareSQL(strSQL, !filter.fields.empty() ? filter.fields.c_str() : "*") + strSQLExtra; + strSQL = PrepareSQL(strSQL, !extFilter.fields.empty() ? extFilter.fields.c_str() : "*") + strSQLExtra; int iRowsFound = RunQuery(strSQL); if (iRowsFound <= 0) @@ -5908,12 +6005,15 @@ bool CVideoDatabase::GetEpisodesByWhere(const CStdString& strBaseDir, const Filt int idEpisode = record->at(0).get_asInt(); + CVideoDbUrl itemUrl = videoUrl; CStdString path; if (appendFullShowPath) - path.Format("%s%ld/%ld/%ld", strBaseDir.c_str(), record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_ID).get_asInt(), movie.m_iSeason, idEpisode); + path.Format("%ld/%ld/%ld", record->at(VIDEODB_DETAILS_EPISODE_TVSHOW_ID).get_asInt(), movie.m_iSeason, idEpisode); else - path.Format("%s%ld", strBaseDir.c_str(), idEpisode); - pItem->SetPath(path); + path.Format("%ld", idEpisode); + itemUrl.AppendPath(path); + pItem->SetPath(itemUrl.ToString()); + pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, movie.m_playCount > 0); pItem->m_dateTime = movie.m_firstAired; pItem->GetVideoInfoTag()->m_iYear = pItem->m_dateTime.GetYear(); @@ -5934,39 +6034,25 @@ bool CVideoDatabase::GetEpisodesByWhere(const CStdString& strBaseDir, const Filt bool CVideoDatabase::GetMusicVideosNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idYear, int idArtist, int idDirector, int idStudio, int idAlbum, const SortDescription &sortDescription /* = SortDescription() */) { - Filter filter; + CVideoDbUrl videoUrl; + if (!videoUrl.FromString(strBaseDir)) + return false; + if (idGenre != -1) - { - filter.join = PrepareSQL("join genrelinkmusicvideo on genrelinkmusicvideo.idMVideo=musicvideoview.idMVideo"); - filter.where = PrepareSQL("genrelinkmusicvideo.idGenre=%i", idGenre); - } + videoUrl.AddOption("genreid", idGenre); else if (idStudio != -1) - { - filter.join = PrepareSQL("join studiolinkmusicvideo on studiolinkmusicvideo.idMVideo=musicvideoview.idMVideo"); - filter.where = PrepareSQL("studiolinkmusicvideo.idStudio=%i", idStudio); - } + videoUrl.AddOption("studioid", idStudio); else if (idDirector != -1) - { - filter.join = PrepareSQL("join directorlinkmusicvideo on directorlinkmusicvideo.idMVideo=musicvideoview.idMVideo"); - filter.where = PrepareSQL("directorlinkmusicvideo.idDirector=%i", idDirector); - } + videoUrl.AddOption("directorid", idDirector); else if (idYear !=-1) - filter.where = PrepareSQL("c%02d='%i'",VIDEODB_ID_MUSICVIDEO_YEAR,idYear); + videoUrl.AddOption("year", idYear); else if (idArtist != -1) - { - filter.join = PrepareSQL("join artistlinkmusicvideo on artistlinkmusicvideo.idMVideo=musicvideoview.idMVideo join actors on actors.idActor=artistlinkmusicvideo.idArtist"); - filter.where = PrepareSQL("actors.idActor=%i",idArtist); - } + videoUrl.AddOption("artistid", idArtist); if (idAlbum != -1) - { - CStdString str2 = PrepareSQL("musicvideoview.c%02d=(select c%02d from musicvideo where idMVideo=%i)",VIDEODB_ID_MUSICVIDEO_ALBUM,VIDEODB_ID_MUSICVIDEO_ALBUM,idAlbum); - if (filter.where.empty()) - filter.where = str2; - else - filter.where += " and " + str2; - } + videoUrl.AddOption("albumid", idAlbum); - return GetMusicVideosByWhere(strBaseDir, filter, items, true, sortDescription); + Filter filter; + return GetMusicVideosByWhere(videoUrl.ToString(), filter, items, true, sortDescription); } bool CVideoDatabase::GetRecentlyAddedMoviesNav(const CStdString& strBaseDir, CFileItemList& items, unsigned int limit) @@ -6040,10 +6126,9 @@ bool CVideoDatabase::HasSets() const if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; - m_pDS->query("SELECT sets.idSet,COUNT(1) AS c FROM sets " - "JOIN setlinkmovie ON sets.idSet=setlinkmovie.idSet " - "JOIN movie ON setlinkmovie.idMovie=movie.idMovie " - "GROUP BY sets.idSet HAVING c>1"); + m_pDS->query("SELECT movieview.idSet,COUNT(1) AS c FROM movieview " + "JOIN sets ON sets.idSet = movieview.idSet " + "GROUP BY movieview.idSet HAVING c>1"); bool bResult = (m_pDS->num_rows() > 0); m_pDS->close(); @@ -6716,28 +6801,24 @@ bool CVideoDatabase::GetMusicVideosByWhere(const CStdString &baseDir, const Filt if (NULL == m_pDS.get()) return false; int total = -1; - + CStdString strSQL = "select %s from musicvideoview "; + CVideoDbUrl videoUrl; CStdString strSQLExtra; - if (!filter.join.empty()) - strSQLExtra += filter.join; - if (!filter.where.empty()) - strSQLExtra += " WHERE " + filter.where; - if (!filter.group.empty()) - strSQLExtra += PrepareSQL(" GROUP BY " + filter.group); - if (!filter.order.empty()) - strSQLExtra += " ORDER BY " + filter.order; - if (!filter.limit.empty()) - strSQLExtra += PrepareSQL(" LIMIT " + filter.limit); + Filter extFilter = filter; + if (!BuildSQL(baseDir, strSQLExtra, extFilter, strSQLExtra, videoUrl)) + return false; + // Apply the limiting directly here if there's no special sorting but limiting - else if (sortDescription.sortBy == SortByNone && - (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) + if (extFilter.limit.empty() && + sortDescription.sortBy == SortByNone && + (sortDescription.limitStart > 0 || sortDescription.limitEnd > 0)) { total = (int)strtol(GetSingleValue(PrepareSQL(strSQL, "COUNT(1)") + strSQLExtra, m_pDS).c_str(), NULL, 10); strSQLExtra += DatabaseUtils::BuildLimitClause(sortDescription.limitEnd, sortDescription.limitStart); } - strSQL = PrepareSQL(strSQL, !filter.fields.empty() ? filter.fields.c_str() : "*") + strSQLExtra; + strSQL = PrepareSQL(strSQL, !extFilter.fields.empty() ? extFilter.fields.c_str() : "*") + strSQLExtra; int iRowsFound = RunQuery(strSQL); if (iRowsFound <= 0) @@ -6767,8 +6848,12 @@ bool CVideoDatabase::GetMusicVideosByWhere(const CStdString &baseDir, const Filt g_passwordManager.IsDatabasePathUnlocked(musicvideo.m_strPath, g_settings.m_videoSources)) { CFileItemPtr item(new CFileItem(musicvideo)); - CStdString path; path.Format("%s%ld", baseDir, record->at(0).get_asInt()); - item->SetPath(path); + + CVideoDbUrl itemUrl = videoUrl; + CStdString path; path.Format("%ld", record->at(0).get_asInt()); + itemUrl.AppendPath(path); + item->SetPath(itemUrl.ToString()); + item->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, musicvideo.m_playCount > 0); items.Add(item); } @@ -6913,9 +6998,9 @@ void CVideoDatabase::GetMoviesByName(const CStdString& strSearch, CFileItemList& if (NULL == m_pDS.get()) return; if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && !g_passwordManager.bMasterUser) - strSQL = PrepareSQL("select movie.idMovie,movie.c%02d,path.strPath from movie,files,path where files.idFile=movie.idFile and files.idPath=path.idPath and movie.c%02d like '%%%s%%'",VIDEODB_ID_TITLE,VIDEODB_ID_TITLE,strSearch.c_str()); + strSQL = PrepareSQL("select movie.idMovie,movie.c%02d,path.strPath, movie.idSet from movie,files,path where files.idFile=movie.idFile and files.idPath=path.idPath and movie.c%02d like '%%%s%%'",VIDEODB_ID_TITLE,VIDEODB_ID_TITLE,strSearch.c_str()); else - strSQL = PrepareSQL("select movie.idMovie,movie.c%02d from movie where movie.c%02d like '%%%s%%'",VIDEODB_ID_TITLE,VIDEODB_ID_TITLE,strSearch.c_str()); + strSQL = PrepareSQL("select movie.idMovie,movie.c%02d, movie.idSet from movie where movie.c%02d like '%%%s%%'",VIDEODB_ID_TITLE,VIDEODB_ID_TITLE,strSearch.c_str()); m_pDS->query( strSQL.c_str() ); while (!m_pDS->eof()) @@ -6928,18 +7013,16 @@ void CVideoDatabase::GetMoviesByName(const CStdString& strSearch, CFileItemList& } int movieId = m_pDS->fv("movie.idMovie").get_asInt(); - CStdString strSQL2 = PrepareSQL("select idSet from setlinkmovie where idMovie=%i",movieId); - m_pDS2->query(strSQL2.c_str()); + int setId = m_pDS->fv("movie.idSet").get_asInt(); CFileItemPtr pItem(new CFileItem(m_pDS->fv(1).get_asString())); CStdString path; - if (m_pDS2->eof()) - path.Format("videodb://1/2/%i",movieId); + if (setId <= 0) + path.Format("videodb://1/2/%i", movieId); else - path.Format("videodb://1/7/%i/%i",m_pDS2->fv(0).get_asInt(),movieId); + path.Format("videodb://1/7/%i/%i", setId, movieId); pItem->SetPath(path); pItem->m_bIsFolder=false; items.Add(pItem); - m_pDS2->close(); m_pDS->next(); } m_pDS->close(); @@ -7515,10 +7598,6 @@ void CVideoDatabase::CleanDatabase(IVideoInfoScannerObserver* pObserver, const s CLog::Log(LOGDEBUG, "%s: Cleaning studiolinkmovie table", __FUNCTION__); sql = "delete from studiolinkmovie where idMovie in " + moviesToDelete; m_pDS->exec(sql.c_str()); - - CLog::Log(LOGDEBUG, "%s: Cleaning setlinkmovie table", __FUNCTION__); - sql = "delete from setlinkmovie where idMovie in " + moviesToDelete; - m_pDS->exec(sql.c_str()); } if ( ! episodesToDelete.IsEmpty() ) @@ -7661,7 +7740,7 @@ void CVideoDatabase::CleanDatabase(IVideoInfoScannerObserver* pObserver, const s m_pDS->exec(sql.c_str()); CLog::Log(LOGDEBUG, "%s: Cleaning set table", __FUNCTION__); - sql = "delete from sets where idSet not in (select distinct idSet from setlinkmovie)"; + sql = "delete from sets where idSet not in (select distinct idSet from movie)"; m_pDS->exec(sql.c_str()); CommitTransaction(); @@ -8679,24 +8758,417 @@ bool CVideoDatabase::GetItemsForPath(const CStdString &content, const CStdString if (content == "movies") { Filter filter(PrepareSQL("c%02d=%d", VIDEODB_ID_PARENTPATHID, pathID)); - GetMoviesByWhere("", filter, items); + GetMoviesByWhere("videodb://1/2/", filter, items); } else if (content == "episodes") { Filter filter(PrepareSQL("c%02d=%d", VIDEODB_ID_EPISODE_PARENTPATHID, pathID)); - GetEpisodesByWhere("", filter, items); + GetEpisodesByWhere("videodb://2/2/", filter, items); } else if (content == "tvshows") { Filter filter(PrepareSQL("c%02d=%d", VIDEODB_ID_TV_PARENTPATHID, pathID)); - GetTvShowsByWhere("", filter, items); + GetTvShowsByWhere("videodb://2/2/", filter, items); } else if (content == "musicvideos") { Filter filter(PrepareSQL("c%02d=%d", VIDEODB_ID_MUSICVIDEO_PARENTPATHID, pathID)); - GetMusicVideosByWhere("", filter, items); + GetMusicVideosByWhere("videodb://3/2/", filter, items); } for (int i = 0; i < items.Size(); i++) items[i]->SetPath(items[i]->GetVideoInfoTag()->m_basePath); return items.Size() > 0; } + +bool CVideoDatabase::GetFilter(const CDbUrl &videoUrl, Filter &filter) +{ + if (!videoUrl.IsValid()) + return false; + + std::string type = videoUrl.GetType(); + std::string itemType = ((const CVideoDbUrl &)videoUrl).GetItemType(); + const CUrlOptions::UrlOptions& options = videoUrl.GetOptions(); + CUrlOptions::UrlOptions::const_iterator option; + + if (type == "movies") + { + option = options.find("genreid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join genrelinkmovie on genrelinkmovie.idMovie = movieview.idMovie")); + filter.AppendWhere(PrepareSQL("genrelinkmovie.idGenre = %i", (int)option->second.asInteger())); + } + + option = options.find("genre"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join genrelinkmovie on genrelinkmovie.idMovie = movieview.idMovie join genre on genre.idGenre = genrelinkmovie.idGenre")); + filter.AppendWhere(PrepareSQL("genre.strGenre like '%s'", option->second.asString().c_str())); + } + + option = options.find("countryid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join countrylinkmovie on countrylinkmovie.idMovie = movieview.idMovie")); + filter.AppendWhere(PrepareSQL("countrylinkmovie.idCountry = %i", (int)option->second.asInteger())); + } + + option = options.find("country"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join countrylinkmovie on countrylinkmovie.idMovie = movieview.idMovie join country on country.idCountry = countrylinkmovie.idCountry")); + filter.AppendWhere(PrepareSQL("country.strCountry like '%s'", option->second.asString().c_str())); + } + + option = options.find("studioid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join studiolinkmovie on studiolinkmovie.idMovie = movieview.idMovie")); + filter.AppendWhere(PrepareSQL("studiolinkmovie.idStudio = %i", (int)option->second.asInteger())); + } + + option = options.find("studio"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join studiolinkmovie on studiolinkmovie.idMovie = movieview.idMovie join studio on studio.idStudio = studiolinkmovie.idStudio")); + filter.AppendWhere(PrepareSQL("studio.strStudio like '%s'", option->second.asString().c_str())); + } + + option = options.find("directorid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join directorlinkmovie on directorlinkmovie.idMovie = movieview.idMovie")); + filter.AppendWhere(PrepareSQL("directorlinkmovie.idDirector = %i", (int)option->second.asInteger())); + } + + option = options.find("director"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join directorlinkmovie on directorlinkmovie.idMovie = movieview.idMovie join actors on actors.idActor = directorlinkmovie.idDirector")); + filter.AppendWhere(PrepareSQL("actors.strActor like '%s'", option->second.asString().c_str())); + } + + option = options.find("year"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("movieview.c%02d = '%i'", VIDEODB_ID_YEAR, (int)option->second.asInteger())); + + option = options.find("actorid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join actorlinkmovie on actorlinkmovie.idMovie = movieview.idMovie")); + filter.AppendWhere(PrepareSQL("actorlinkmovie.idActor = %i", (int)option->second.asInteger())); + } + + option = options.find("actor"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join actorlinkmovie on actorlinkmovie.idMovie = movieview.idMovie join actors on actors.idActor = actorlinkmovie.idActor")); + filter.AppendWhere(PrepareSQL("actors.strActor like '%s'", option->second.asString().c_str())); + } + + option = options.find("setid"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("movieview.idSet = %i", (int)option->second.asInteger())); + + option = options.find("set"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join setlinkmovie on setlinkmovie.idMovie = movieview.idMovie join sets on sets.idSet = setlinkmovie.idSet")); + filter.AppendWhere(PrepareSQL("sets.strSet like '%s'", option->second.asString().c_str())); + } + + option = options.find("tagid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join taglinks on taglinks.idMedia = movieview.idMovie AND taglinks.media_type = 'movie'")); + filter.AppendWhere(PrepareSQL("taglinks.idTag = %i", (int)option->second.asInteger())); + } + + option = options.find("tag"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join taglinks on taglinks.idMedia = movieview.idMovie AND taglinks.media_type = 'movie' join tag on tag.idTag = taglinks.idTag")); + filter.AppendWhere(PrepareSQL("tag.strTag like '%s'", option->second.asString().c_str())); + } + } + else if (type == "tvshows") + { + if (itemType == "tvshows") + { + option = options.find("genreid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join genrelinktvshow on genrelinktvshow.idShow = tvshowview.idShow")); + filter.AppendWhere(PrepareSQL("genrelinktvshow.idGenre = %i", (int)option->second.asInteger())); + } + + option = options.find("genre"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join genrelinktvshow on genrelinktvshow.idShow = tvshowview.idShow join genre on genre.idGenre = genrelinktvshow.idGenre")); + filter.AppendWhere(PrepareSQL("genre.strGenre like '%s'", option->second.asString().c_str())); + } + + option = options.find("studioid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join studiolinktvshow on studiolinktvshow.idShow = tvshowview.idShow")); + filter.AppendWhere(PrepareSQL("studiolinktvshow.idStudio = %i", (int)option->second.asInteger())); + } + + option = options.find("studio"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join studiolinktvshow on studiolinktvshow.idShow = tvshowview.idShow join studio on studio.idStudio = studiolinktvshow.idStudio")); + filter.AppendWhere(PrepareSQL("studio.strStudio like '%s'", option->second.asString().c_str())); + } + + option = options.find("directorid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join directorlinktvshow on directorlinktvshow.idShow = tvshowview.idShow")); + filter.AppendWhere(PrepareSQL("directorlinktvshow.idDirector = %i", (int)option->second.asInteger())); + } + + option = options.find("year"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("tvshowview.c%02d like '%%%i%%'", VIDEODB_ID_TV_PREMIERED, (int)option->second.asInteger())); + + option = options.find("actorid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join actorlinktvshow on actorlinktvshow.idShow = tvshowview.idShow")); + filter.AppendWhere(PrepareSQL("actorlinktvshow.idActor = %i", (int)option->second.asInteger())); + } + + option = options.find("actor"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join actorlinktvshow on actorlinktvshow.idShow = tvshowview.idShow join actors on actors.idActor = actorlinktvshow.idActor")); + filter.AppendWhere(PrepareSQL("actors.strActor like '%s'", option->second.asString().c_str())); + } + } + else if (itemType == "seasons") + { + option = options.find("genreid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join genrelinktvshow on genrelinktvshow.idShow = tvshowview.idShow")); + filter.AppendWhere(PrepareSQL("genrelinktvshow.idGenre = %i", (int)option->second.asInteger())); + } + + option = options.find("directorid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join directorlinktvshow on directorlinktvshow.idShow = tvshowview.idShow")); + filter.AppendWhere(PrepareSQL("directorlinktvshow.idDirector = %i", (int)option->second.asInteger())); + } + + option = options.find("year"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("tvshowview.c%02d like '%%%i%%'", VIDEODB_ID_TV_PREMIERED, (int)option->second.asInteger())); + + option = options.find("actorid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join actorlinktvshow on actorlinktvshow.idShow = tvshowview.idShow")); + filter.AppendWhere(PrepareSQL("actorlinktvshow.idActor = %i", (int)option->second.asInteger())); + } + } + else if (itemType == "episodes") + { + int idShow = -1; + option = options.find("tvshowid"); + if (option != options.end()) + idShow = (int)option->second.asInteger(); + + int season = -1; + option = options.find("season"); + if (option != options.end()) + season = (int)option->second.asInteger(); + + CStdString strIn = PrepareSQL("= %i", idShow); + GetStackedTvShowList(idShow, strIn); + + if (idShow > -1) + { + bool condition = false; + + option = options.find("genreid"); + if (option != options.end()) + { + condition = true; + filter.AppendJoin(PrepareSQL("join genrelinktvshow on genrelinktvshow.idShow = episodeview.idShow")); + filter.AppendWhere(PrepareSQL("episodeview.idShow = %i and genrelinktvshow.idGenre = %i", idShow, (int)option->second.asInteger())); + } + + option = options.find("genre"); + if (option != options.end()) + { + condition = true; + filter.AppendJoin(PrepareSQL("join genrelinktvshow on genrelinktvshow.idShow = episodeview.idShow join genre on genre.idGenre = genrelinktvshow.idGenre")); + filter.AppendWhere(PrepareSQL("episodeview.idShow = %i and genre.strGenre like '%s'", idShow, option->second.asString().c_str())); + } + + option = options.find("directorid"); + if (option != options.end()) + { + condition = true; + filter.AppendJoin(PrepareSQL("join directorlinktvshow on directorlinktvshow.idShow = episodeview.idShow")); + filter.AppendWhere(PrepareSQL("episodeview.idShow = %i and directorlinktvshow.idDirector = %i", idShow, (int)option->second.asInteger())); + } + + option = options.find("director"); + if (option != options.end()) + { + condition = true; + filter.AppendJoin(PrepareSQL("join directorlinktvshow on directorlinktvshow.idShow = episodeview.idShow join actors on actors.idActor = directorlinktvshow.idDirector")); + filter.AppendWhere(PrepareSQL("episodeview.idShow = %i and actors.strActor like '%s'", idShow, option->second.asString().c_str())); + } + + option = options.find("year"); + if (option != options.end()) + { + condition = true; + filter.AppendWhere(PrepareSQL("episodeview.idShow = %i and episodeview.premiered like '%%%i%%'", idShow, (int)option->second.asInteger())); + } + + option = options.find("actorid"); + if (option != options.end()) + { + condition = true; + filter.AppendJoin(PrepareSQL("join actorlinktvshow on actorlinktvshow.idShow = episodeview.idShow")); + filter.AppendWhere(PrepareSQL("episodeview.idShow = %i and actorlinktvshow.idActor = %s", idShow, (int)option->second.asInteger())); + } + + option = options.find("actor"); + if (option != options.end()) + { + condition = true; + filter.AppendJoin(PrepareSQL("join actorlinktvshow on actorlinktvshow.idShow = episodeview.idShow join actors on actors.idActor = actorlinktvshow.idActor")); + filter.AppendWhere(PrepareSQL("episodeview.idShow = %i and actors.strActor = '%s'", idShow, option->second.asString().c_str())); + } + + if (!condition) + filter.AppendWhere(PrepareSQL("episodeview.idShow %s", strIn.c_str())); + + if (season > -1) + { + if (season == 0) // season = 0 indicates a special - we grab all specials here (see below) + filter.AppendWhere(PrepareSQL("episodeview.c%02d = %i", VIDEODB_ID_EPISODE_SEASON, season)); + else + filter.AppendWhere(PrepareSQL("(episodeview.c%02d = %i or (episodeview.c%02d = 0 and (episodeview.c%02d = 0 or episodeview.c%02d = %i)))", + VIDEODB_ID_EPISODE_SEASON, season, VIDEODB_ID_EPISODE_SEASON, VIDEODB_ID_EPISODE_SORTSEASON, VIDEODB_ID_EPISODE_SORTSEASON, season)); + } + } + else + { + option = options.find("year"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("episodeview.premiered like '%%%i%%'", (int)option->second.asInteger())); + + option = options.find("directorid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join directorlinkepisode on directorlinkepisode.idEpisode = episodeview.idEpisode")); + filter.AppendWhere(PrepareSQL("directorlinkepisode.idDirector = %i", (int)option->second.asInteger())); + } + + option = options.find("director"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join directorlinkepisode on directorlinkepisode.idEpisode = episodeview.idEpisode join actors on actors.idActor = directorlinktvshow.idDirector")); + filter.AppendWhere(PrepareSQL("actors.strActor = %s", option->second.asString().c_str())); + } + } + } + } + else if (type == "musicvideos") + { + option = options.find("genreid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join genrelinkmusicvideo on genrelinkmusicvideo.idMVideo = musicvideoview.idMVideo")); + filter.AppendWhere(PrepareSQL("genrelinkmusicvideo.idGenre = %i", (int)option->second.asInteger())); + } + + option = options.find("genre"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join genrelinkmusicvideo on genrelinkmusicvideo.idMVideo = musicvideoview.idMVideo join genre on genre.idGenre = genrelinkmusicvideo.idGenre")); + filter.AppendWhere(PrepareSQL("genre.strGenre like '%s'", option->second.asString().c_str())); + } + + option = options.find("studioid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join studiolinkmusicvideo on studiolinkmusicvideo.idMVideo = musicvideoview.idMVideo")); + filter.AppendWhere(PrepareSQL("studiolinkmusicvideo.idStudio = %i", (int)option->second.asInteger())); + } + + option = options.find("studio"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join studiolinkmusicvideo on studiolinkmusicvideo.idMVideo = musicvideoview.idMVideo join studio on studio.idStudio = studiolinkmusicvideo.idStudio")); + filter.AppendWhere(PrepareSQL("studio.strStudio like '%s'", option->second.asString().c_str())); + } + + option = options.find("directorid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join directorlinkmusicvideo on directorlinkmusicvideo.idMVideo = musicvideoview.idMVideo")); + filter.AppendWhere(PrepareSQL("directorlinkmusicvideo.idDirector = %i", (int)option->second.asInteger())); + } + + option = options.find("director"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join directorlinkmusicvideo on directorlinkmusicvideo.idMVideo = musicvideoview.idMVideo join actors on actors.idActor = directorlinkmusicvideo.idDirector")); + filter.AppendWhere(PrepareSQL("actors.strActor like '%s'", option->second.asString().c_str())); + } + + option = options.find("year"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("musicvideoview.c%02d = '%i'",VIDEODB_ID_MUSICVIDEO_YEAR, (int)option->second.asInteger())); + + option = options.find("artistid"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join artistlinkmusicvideo on artistlinkmusicvideo.idMVideo = musicvideoview.idMVideo")); + filter.AppendWhere(PrepareSQL("artistlinkmusicvideo.idArtist = %i", (int)option->second.asInteger())); + } + + option = options.find("artist"); + if (option != options.end()) + { + filter.AppendJoin(PrepareSQL("join artistlinkmusicvideo on artistlinkmusicvideo.idMVideo = musicvideoview.idMVideo join actors on actors.idActor = artistlinkmusicvideo.idArtist")); + filter.AppendWhere(PrepareSQL("actors.strActor like '%s'", option->second.asString().c_str())); + } + + option = options.find("albumid"); + if (option != options.end()) + filter.AppendWhere(PrepareSQL("musicvideoview.c%02d = (select c%02d from musicvideo where idMVideo = %i)", VIDEODB_ID_MUSICVIDEO_ALBUM, VIDEODB_ID_MUSICVIDEO_ALBUM, (int)option->second.asInteger())); + } + else + return false; + + option = options.find("xsp"); + if (option != options.end()) + { + CSmartPlaylist xsp; + if (!xsp.LoadFromJson(option->second.asString())) + return false; + + // check if the filter playlist matches the item type + if (xsp.GetType() == itemType || + // handle episode listings with videodb://2/2/ which get the rest + // of the path (season and episodeid) appended later + (xsp.GetType() == "episodes" && itemType == "tvshows")) + { + std::set<CStdString> playlists; + filter.AppendWhere(xsp.GetWhereClause(*this, playlists)); + } + } + + return true; +} diff --git a/xbmc/video/VideoDatabase.h b/xbmc/video/VideoDatabase.h index 9cb16e0ad0..87d0d5d210 100644 --- a/xbmc/video/VideoDatabase.h +++ b/xbmc/video/VideoDatabase.h @@ -24,6 +24,7 @@ #include "addons/Scraper.h" #include "Bookmark.h" #include "utils/SortUtils.h" +#include "video/VideoDbUrl.h" #include <memory> #include <set> @@ -68,13 +69,16 @@ namespace VIDEO // when we do GetDetailsForMovie() #define VIDEODB_MAX_COLUMNS 24 #define VIDEODB_DETAILS_FILEID 1 -#define VIDEODB_DETAILS_FILE VIDEODB_MAX_COLUMNS + 2 -#define VIDEODB_DETAILS_PATH VIDEODB_MAX_COLUMNS + 3 -#define VIDEODB_DETAILS_PLAYCOUNT VIDEODB_MAX_COLUMNS + 4 -#define VIDEODB_DETAILS_LASTPLAYED VIDEODB_MAX_COLUMNS + 5 -#define VIDEODB_DETAILS_DATEADDED VIDEODB_MAX_COLUMNS + 6 -#define VIDEODB_DETAILS_RESUME_TIME VIDEODB_MAX_COLUMNS + 7 -#define VIDEODB_DETAILS_TOTAL_TIME VIDEODB_MAX_COLUMNS + 8 + +#define VIDEODB_DETAILS_MOVIE_SET_ID VIDEODB_MAX_COLUMNS + 2 +#define VIDEODB_DETAILS_MOVIE_SET_NAME VIDEODB_MAX_COLUMNS + 3 +#define VIDEODB_DETAILS_MOVIE_FILE VIDEODB_MAX_COLUMNS + 4 +#define VIDEODB_DETAILS_MOVIE_PATH VIDEODB_MAX_COLUMNS + 5 +#define VIDEODB_DETAILS_MOVIE_PLAYCOUNT VIDEODB_MAX_COLUMNS + 6 +#define VIDEODB_DETAILS_MOVIE_LASTPLAYED VIDEODB_MAX_COLUMNS + 7 +#define VIDEODB_DETAILS_MOVIE_DATEADDED VIDEODB_MAX_COLUMNS + 8 +#define VIDEODB_DETAILS_MOVIE_RESUME_TIME VIDEODB_MAX_COLUMNS + 9 +#define VIDEODB_DETAILS_MOVIE_TOTAL_TIME VIDEODB_MAX_COLUMNS + 10 #define VIDEODB_DETAILS_EPISODE_TVSHOW_ID VIDEODB_MAX_COLUMNS + 2 #define VIDEODB_DETAILS_EPISODE_FILE VIDEODB_MAX_COLUMNS + 3 @@ -97,6 +101,13 @@ namespace VIDEO #define VIDEODB_DETAILS_TVSHOW_NUM_WATCHED VIDEODB_MAX_COLUMNS + 4 #define VIDEODB_DETAILS_TVSHOW_NUM_SEASONS VIDEODB_MAX_COLUMNS + 5 +#define VIDEODB_DETAILS_MUSICVIDEO_FILE VIDEODB_MAX_COLUMNS + 2 +#define VIDEODB_DETAILS_MUSICVIDEO_PATH VIDEODB_MAX_COLUMNS + 3 +#define VIDEODB_DETAILS_MUSICVIDEO_PLAYCOUNT VIDEODB_MAX_COLUMNS + 4 +#define VIDEODB_DETAILS_MUSICVIDEO_LASTPLAYED VIDEODB_MAX_COLUMNS + 5 +#define VIDEODB_DETAILS_MUSICVIDEO_DATEADDED VIDEODB_MAX_COLUMNS + 6 +#define VIDEODB_DETAILS_MUSICVIDEO_RESUME_TIME VIDEODB_MAX_COLUMNS + 7 +#define VIDEODB_DETAILS_MUSICVIDEO_TOTAL_TIME VIDEODB_MAX_COLUMNS + 8 #define VIDEODB_TYPE_STRING 1 #define VIDEODB_TYPE_INT 2 @@ -321,20 +332,6 @@ class CVideoDatabase : public CDatabase { public: - class Filter - { - public: - Filter() : fields("*") {}; - Filter(const char *w) : fields("*"), where(w) {}; - Filter(const std::string &w) : fields("*"), where(w) {}; - std::string fields; - std::string join; - std::string where; - std::string order; - std::string group; - std::string limit; - }; - class CActor // used for actor retrieval for non-master users { public: @@ -402,6 +399,7 @@ public: void UpdateLastPlayed(const CFileItem &item); /*! \brief Get the playcount and resume point of a list of items + Note that if the resume point is already set on an item, it won't be overridden. \param path the path to fetch videos from \param items CFileItemList to fetch the playcounts for \sa GetPlayCount, SetPlayCount, IncrementPlayCount @@ -578,19 +576,19 @@ public: bool ArbitraryExec(const CStdString& strExec); // general browsing - bool GetGenresNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1); - bool GetCountriesNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1); - bool GetStudiosNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1); - bool GetYearsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1); - bool GetActorsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1); - bool GetDirectorsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1); - bool GetWritersNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1); + bool GetGenresNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter()); + bool GetCountriesNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter()); + bool GetStudiosNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter()); + bool GetYearsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter()); + bool GetActorsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter()); + bool GetDirectorsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter()); + bool GetWritersNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter()); bool GetSetsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1); - bool GetTagsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1); - bool GetMusicVideoAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idArtist); + bool GetTagsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1, const Filter &filter = Filter()); + bool GetMusicVideoAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idArtist, const Filter &filter = Filter()); - bool GetMoviesNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idStudio=-1, int idCountry=-1, int idSet=-1, int idTag=-1); - bool GetTvShowsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idStudio=-1); + bool GetMoviesNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idStudio=-1, int idCountry=-1, int idSet=-1, int idTag=-1, const SortDescription &sortDescription = SortDescription()); + bool GetTvShowsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idStudio=-1, const SortDescription &sortDescription = SortDescription()); bool GetSeasonsNav(const CStdString& strBaseDir, CFileItemList& items, int idActor=-1, int idDirector=-1, int idGenre=-1, int idYear=-1, int idShow=-1); bool GetEpisodesNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idShow=-1, int idSeason=-1, const SortDescription &sortDescription = SortDescription()); bool GetMusicVideosNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idArtist=-1, int idDirector=-1, int idStudio=-1, int idAlbum=-1, const SortDescription &sortDescription = SortDescription()); @@ -687,6 +685,8 @@ public: void AddTagToItem(int idItem, int idTag, const std::string &type); void RemoveTagFromItem(int idItem, int idTag, const std::string &type); + virtual bool GetFilter(const CDbUrl &videoUrl, Filter &filter); + protected: int GetMovieId(const CStdString& strFilenameAndPath); int GetMusicVideoId(const CStdString& strFilenameAndPath); @@ -720,8 +720,6 @@ protected: void AddToLinkTable(const char *table, const char *firstField, int firstID, const char *secondField, int secondID, const char *typeField = NULL, const char *type = NULL); void RemoveFromLinkTable(const char *table, const char *firstField, int firstID, const char *secondField, int secondID, const char *typeField = NULL, const char *type = NULL); - void AddSetToMovie(int idMovie, int idSet); - void AddActorToMovie(int idMovie, int idActor, const CStdString& strRole, int order); void AddActorToTvShow(int idTvShow, int idActor, const CStdString& strRole, int order); void AddActorToEpisode(int idEpisode, int idActor, const CStdString& strRole, int order); @@ -756,10 +754,8 @@ protected: CVideoInfoTag GetDetailsForEpisode(const dbiplus::sql_record* const record, bool needsCast = false); CVideoInfoTag GetDetailsForMusicVideo(std::auto_ptr<dbiplus::Dataset> &pDS); CVideoInfoTag GetDetailsForMusicVideo(const dbiplus::sql_record* const record); - void GetCommonDetails(std::auto_ptr<dbiplus::Dataset> &pDS, CVideoInfoTag &details); - void GetCommonDetails(const dbiplus::sql_record* const record, CVideoInfoTag &details); - bool GetPeopleNav(const CStdString& strBaseDir, CFileItemList& items, const CStdString& type, int idContent=-1); - bool GetNavCommon(const CStdString& strBaseDir, CFileItemList& items, const CStdString& type, int idContent=-1); + bool GetPeopleNav(const CStdString& strBaseDir, CFileItemList& items, const CStdString& type, int idContent=-1, const Filter &filter = Filter()); + bool GetNavCommon(const CStdString& strBaseDir, CFileItemList& items, const CStdString& type, int idContent=-1, const Filter &filter = Filter()); void GetCast(const CStdString &table, const CStdString &table_id, int type_id, std::vector<SActorInfo> &cast); void GetDetailsFromDB(std::auto_ptr<dbiplus::Dataset> &pDS, int min, int max, const SDbTableOffsets *offsets, CVideoInfoTag &details, int idxOffset = 2); @@ -807,7 +803,7 @@ private: */ bool LookupByFolders(const CStdString &path, bool shows = false); - virtual int GetMinVersion() const { return 67; }; + virtual int GetMinVersion() const { return 68; }; virtual int GetExportVersion() const { return 1; }; const char *GetBaseDBName() const { return "MyVideos"; }; @@ -815,7 +811,7 @@ private: void SplitPath(const CStdString& strFileNameAndPath, CStdString& strPath, CStdString& strFileName); void InvalidatePathHash(const CStdString& strPath); - bool GetStackedTvShowList(int idShow, CStdString& strIn); + bool GetStackedTvShowList(int idShow, CStdString& strIn) const; void Stack(CFileItemList& items, VIDEODB_CONTENT_TYPE type, bool maintainSortOrder = false); /*! \brief Get a safe filename from a given string diff --git a/xbmc/video/VideoDbUrl.cpp b/xbmc/video/VideoDbUrl.cpp new file mode 100644 index 0000000000..78d3dcdb5e --- /dev/null +++ b/xbmc/video/VideoDbUrl.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "VideoDbUrl.h" +#include "filesystem/VideoDatabaseDirectory.h" +#include "utils/StringUtils.h" +#include "utils/Variant.h" + +using namespace std; +using namespace XFILE; + +CVideoDbUrl::CVideoDbUrl() + : CDbUrl() +{ } + +CVideoDbUrl::~CVideoDbUrl() +{ } + +bool CVideoDbUrl::parse() +{ + // the URL must start with videodb:// + if (m_url.GetProtocol() != "videodb" || m_url.GetFileName().empty()) + return false; + + CStdString path = m_url.Get(); + VIDEODATABASEDIRECTORY::NODE_TYPE dirType = CVideoDatabaseDirectory::GetDirectoryType(path); + VIDEODATABASEDIRECTORY::NODE_TYPE childType = CVideoDatabaseDirectory::GetDirectoryChildType(path); + + switch (dirType) + { + case VIDEODATABASEDIRECTORY::NODE_TYPE_MOVIES_OVERVIEW: + case VIDEODATABASEDIRECTORY::NODE_TYPE_RECENTLY_ADDED_MOVIES: + case VIDEODATABASEDIRECTORY::NODE_TYPE_TITLE_MOVIES: + case VIDEODATABASEDIRECTORY::NODE_TYPE_SETS: + m_type = "movies"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_TVSHOWS_OVERVIEW: + case VIDEODATABASEDIRECTORY::NODE_TYPE_TITLE_TVSHOWS: + case VIDEODATABASEDIRECTORY::NODE_TYPE_SEASONS: + case VIDEODATABASEDIRECTORY::NODE_TYPE_EPISODES: + case VIDEODATABASEDIRECTORY::NODE_TYPE_RECENTLY_ADDED_EPISODES: + m_type = "tvshows"; + break; + + + case VIDEODATABASEDIRECTORY::NODE_TYPE_MUSICVIDEOS_OVERVIEW: + case VIDEODATABASEDIRECTORY::NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS: + case VIDEODATABASEDIRECTORY::NODE_TYPE_TITLE_MUSICVIDEOS: + case VIDEODATABASEDIRECTORY::NODE_TYPE_MUSICVIDEOS_ALBUM: + m_type = "musicvideos"; + + default: + break; + } + + switch (childType) + { + case VIDEODATABASEDIRECTORY::NODE_TYPE_MOVIES_OVERVIEW: + case VIDEODATABASEDIRECTORY::NODE_TYPE_TITLE_MOVIES: + case VIDEODATABASEDIRECTORY::NODE_TYPE_RECENTLY_ADDED_MOVIES: + m_type = "movies"; + m_itemType = "movies"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_TVSHOWS_OVERVIEW: + case VIDEODATABASEDIRECTORY::NODE_TYPE_TITLE_TVSHOWS: + m_type = "tvshows"; + m_itemType = "tvshows"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_SEASONS: + m_type = "tvshows"; + m_itemType = "seasons"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_EPISODES: + case VIDEODATABASEDIRECTORY::NODE_TYPE_RECENTLY_ADDED_EPISODES: + m_type = "tvshows"; + m_itemType = "episodes"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_MUSICVIDEOS_OVERVIEW: + case VIDEODATABASEDIRECTORY::NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS: + case VIDEODATABASEDIRECTORY::NODE_TYPE_TITLE_MUSICVIDEOS: + m_type = "musicvideos"; + m_itemType = "musicvideos"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_GENRE: + m_itemType = "genres"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_ACTOR: + m_itemType = "actors"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_YEAR: + m_itemType = "years"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_DIRECTOR: + m_itemType = "directors"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_STUDIO: + m_itemType = "studios"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_COUNTRY: + m_itemType = "countries"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_SETS: + m_itemType = "sets"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_MUSICVIDEOS_ALBUM: + m_type = "musicvideos"; + m_itemType = "albums"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_TAGS: + m_itemType = "tags"; + break; + + case VIDEODATABASEDIRECTORY::NODE_TYPE_ROOT: + case VIDEODATABASEDIRECTORY::NODE_TYPE_OVERVIEW: + default: + return false; + } + + if (m_type.empty() || m_itemType.empty()) + return false; + + // parse query params + VIDEODATABASEDIRECTORY::CQueryParams queryParams; + if (!CVideoDatabaseDirectory::GetQueryParams(path, queryParams)) + return false; + + // retrieve and parse all options + AddOptions(m_url.GetOptions()); + + // add options based on the QueryParams + if (queryParams.GetActorId() != -1) + AddOption("actorid", (int)queryParams.GetActorId()); + if (queryParams.GetAlbumId() != -1) + AddOption("albumid", (int)queryParams.GetAlbumId()); + if (queryParams.GetCountryId() != -1) + AddOption("countryid", (int)queryParams.GetCountryId()); + if (queryParams.GetDirectorId() != -1) + AddOption("directorid", (int)queryParams.GetDirectorId()); + if (queryParams.GetEpisodeId() != -1) + AddOption("episodeid", (int)queryParams.GetEpisodeId()); + if (queryParams.GetGenreId() != -1) + AddOption("genreid", (int)queryParams.GetGenreId()); + if (queryParams.GetMovieId() != -1) + AddOption("movieid", (int)queryParams.GetMovieId()); + if (queryParams.GetMVideoId() != -1) + AddOption("musicvideoid", (int)queryParams.GetMVideoId()); + if (queryParams.GetSeason() != -1 && queryParams.GetSeason() >= -2) + AddOption("season", (int)queryParams.GetSeason()); + if (queryParams.GetSetId() != -1) + AddOption("setid", (int)queryParams.GetSetId()); + if (queryParams.GetStudioId() != -1) + AddOption("studioid", (int)queryParams.GetStudioId()); + if (queryParams.GetTvShowId() != -1) + AddOption("tvshowid", (int)queryParams.GetTvShowId()); + if (queryParams.GetYear() != -1) + AddOption("year", (int)queryParams.GetYear()); + + return true; +} diff --git a/xbmc/video/VideoDbUrl.h b/xbmc/video/VideoDbUrl.h new file mode 100644 index 0000000000..4f888c9cc5 --- /dev/null +++ b/xbmc/video/VideoDbUrl.h @@ -0,0 +1,36 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "DbUrl.h" + +class CVideoDbUrl : public CDbUrl +{ +public: + CVideoDbUrl(); + virtual ~CVideoDbUrl(); + + const std::string& GetItemType() const { return m_itemType; } + +protected: + virtual bool parse(); + +private: + std::string m_itemType; +}; diff --git a/xbmc/video/VideoInfoDownloader.cpp b/xbmc/video/VideoInfoDownloader.cpp index 5a460349e3..65fe6c0efb 100644 --- a/xbmc/video/VideoInfoDownloader.cpp +++ b/xbmc/video/VideoInfoDownloader.cpp @@ -20,13 +20,12 @@ */ #include "VideoInfoDownloader.h" -#include "Util.h" #include "utils/XMLUtils.h" #include "utils/RegExp.h" #include "NfoFile.h" #include "dialogs/GUIDialogProgress.h" #include "dialogs/GUIDialogOK.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" #include "utils/log.h" @@ -38,6 +37,17 @@ using namespace std; #pragma warning (disable:4018) #endif +CVideoInfoDownloader::CVideoInfoDownloader(const ADDON::ScraperPtr &scraper) : + CThread("CVideoInfoDownloader"), m_info(scraper) +{ + m_http = new XFILE::CCurlFile; +} + +CVideoInfoDownloader::~CVideoInfoDownloader() +{ + delete m_http; +} + // return value: 0 = we failed, -1 = we failed and reported an error, 1 = success int CVideoInfoDownloader::InternalFindMovie(const CStdString &strMovie, MOVIELIST& movielist, @@ -45,7 +55,7 @@ int CVideoInfoDownloader::InternalFindMovie(const CStdString &strMovie, { try { - movielist = m_info->FindMovie(m_http, strMovie, cleanChars); + movielist = m_info->FindMovie(*m_http, strMovie, cleanChars); } catch (const ADDON::CScraperError &sce) { @@ -62,7 +72,7 @@ void CVideoInfoDownloader::ShowErrorDialog(const ADDON::CScraperError &sce) CGUIDialogOK *pdlg = (CGUIDialogOK *)g_windowManager.GetWindow(WINDOW_DIALOG_OK); pdlg->SetHeading(sce.Title()); pdlg->SetLine(0, sce.Message()); - g_application.getApplicationMessenger().DoModal(pdlg, WINDOW_DIALOG_OK); + CApplicationMessenger::Get().DoModal(pdlg, WINDOW_DIALOG_OK); } } @@ -178,7 +188,7 @@ bool CVideoInfoDownloader::GetDetails(const CScraperUrl &url, return true; } else // unthreaded - return m_info->GetVideoDetails(m_http, url, true/*fMovie*/, movieDetails); + return m_info->GetVideoDetails(*m_http, url, true/*fMovie*/, movieDetails); } bool CVideoInfoDownloader::GetEpisodeDetails(const CScraperUrl &url, @@ -213,7 +223,7 @@ bool CVideoInfoDownloader::GetEpisodeDetails(const CScraperUrl &url, return true; } else // unthreaded - return m_info->GetVideoDetails(m_http, url, false/*fMovie*/, movieDetails); + return m_info->GetVideoDetails(*m_http, url, false/*fMovie*/, movieDetails); } bool CVideoInfoDownloader::GetEpisodeList(const CScraperUrl& url, @@ -248,14 +258,14 @@ bool CVideoInfoDownloader::GetEpisodeList(const CScraperUrl& url, return true; } else // unthreaded - return !(movieDetails = m_info->GetEpisodeList(m_http, url)).empty(); + return !(movieDetails = m_info->GetEpisodeList(*m_http, url)).empty(); } void CVideoInfoDownloader::CloseThread() { - m_http.Cancel(); + m_http->Cancel(); StopThread(); - m_http.Reset(); + m_http->Reset(); m_state = DO_NOTHING; m_found = 0; } diff --git a/xbmc/video/VideoInfoDownloader.h b/xbmc/video/VideoInfoDownloader.h index a1a19d366c..5db04e757d 100644 --- a/xbmc/video/VideoInfoDownloader.h +++ b/xbmc/video/VideoInfoDownloader.h @@ -42,8 +42,8 @@ typedef std::vector<CScraperUrl> MOVIELIST; class CVideoInfoDownloader : public CThread { public: - CVideoInfoDownloader(const ADDON::ScraperPtr &scraper) : CThread("CVideoInfoDownloader"), m_info(scraper) {} - virtual ~CVideoInfoDownloader() {} + CVideoInfoDownloader(const ADDON::ScraperPtr &scraper); + virtual ~CVideoInfoDownloader(); // threaded lookup functions @@ -67,7 +67,7 @@ protected: GET_EPISODE_LIST = 3, GET_EPISODE_DETAILS = 4 }; - XFILE::CCurlFile m_http; + XFILE::CCurlFile* m_http; CStdString m_strMovie; MOVIELIST m_movieList; CVideoInfoTag m_movieDetails; diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp index f311495427..797ce7359b 100644 --- a/xbmc/video/VideoInfoScanner.cpp +++ b/xbmc/video/VideoInfoScanner.cpp @@ -47,6 +47,7 @@ #include "utils/Variant.h" #include "ThumbLoader.h" #include "TextureCache.h" +#include "URL.h" using namespace std; using namespace XFILE; @@ -1105,7 +1106,7 @@ namespace VIDEO m_database.SetPlayCount(*pItem, movieDetails.m_playCount, movieDetails.m_lastPlayed); if ((g_advancedSettings.m_bVideoLibraryImportResumePoint || libraryImport) && - movieDetails.m_resumePoint.timeInSeconds > 0.0f && movieDetails.m_resumePoint.totalTimeInSeconds > 0.0f) + movieDetails.m_resumePoint.IsSet()) m_database.AddBookMarkToFile(pItem->GetPath(), movieDetails.m_resumePoint, CBookmark::RESUME); m_database.Close(); diff --git a/xbmc/video/VideoInfoScanner.h b/xbmc/video/VideoInfoScanner.h index 0a16140234..16ade45c81 100644 --- a/xbmc/video/VideoInfoScanner.h +++ b/xbmc/video/VideoInfoScanner.h @@ -23,7 +23,6 @@ #include "VideoDatabase.h" #include "addons/Scraper.h" #include "NfoFile.h" -#include "VideoInfoDownloader.h" #include "XBDateTime.h" class CRegExp; diff --git a/xbmc/video/VideoInfoTag.cpp b/xbmc/video/VideoInfoTag.cpp index bb352dbcf0..6be9f6dafa 100644 --- a/xbmc/video/VideoInfoTag.cpp +++ b/xbmc/video/VideoInfoTag.cpp @@ -51,8 +51,8 @@ void CVideoInfoTag::Reset() m_strSortTitle.clear(); m_strVotes.clear(); m_cast.clear(); - m_set.clear(); - m_setId.clear(); + m_strSet.clear(); + m_iSetId = -1; m_tags.clear(); m_strFile.clear(); m_strPath.clear(); @@ -174,7 +174,7 @@ bool CVideoInfoTag::Save(TiXmlNode *node, const CStdString &tag, bool savePathIn XMLUtils::SetString(movie, "id", m_strIMDBNumber); XMLUtils::SetStringArray(movie, "genre", m_genre); XMLUtils::SetStringArray(movie, "country", m_country); - XMLUtils::SetStringArray(movie, "set", m_set); + XMLUtils::SetString(movie, "set", m_strSet); XMLUtils::SetStringArray(movie, "tag", m_tags); XMLUtils::SetStringArray(movie, "credits", m_writingCredits); XMLUtils::SetStringArray(movie, "director", m_director); @@ -291,8 +291,8 @@ void CVideoInfoTag::Archive(CArchive& ar) ar << m_cast[i].thumbUrl.m_xml; } - ar << m_set; - ar << m_setId; + ar << m_strSet; + ar << m_iSetId; ar << m_tags; ar << m_strRuntime; ar << m_strFile; @@ -368,8 +368,8 @@ void CVideoInfoTag::Archive(CArchive& ar) m_cast.push_back(info); } - ar >> m_set; - ar >> m_setId; + ar >> m_strSet; + ar >> m_iSetId; ar >> m_tags; ar >> m_strRuntime; ar >> m_strFile; @@ -419,19 +419,16 @@ void CVideoInfoTag::Archive(CArchive& ar) void CVideoInfoTag::Serialize(CVariant& value) { - /* TODO: - All the StringUtils::Join() calls can be removed once backwards-compatibility to - JSON-RPC v4 can be broken */ - value["director"] = StringUtils::Join(m_director, " / "); - value["writer"] = StringUtils::Join(m_writingCredits, " / "); - value["genre"] = StringUtils::Join(m_genre, " / "); - value["country"] = StringUtils::Join(m_country, " / "); + value["director"] = m_director; + value["writer"] = m_writingCredits; + value["genre"] = m_genre; + value["country"] = m_country; value["tagline"] = m_strTagLine; value["plotoutline"] = m_strPlotOutline; value["plot"] = m_strPlot; value["title"] = m_strTitle; value["votes"] = m_strVotes; - value["studio"] = StringUtils::Join(m_studio, " / "); + value["studio"] = m_studio; value["trailer"] = m_strTrailer; value["cast"] = CVariant(CVariant::VariantTypeArray); for (unsigned int i = 0; i < m_cast.size(); ++i) @@ -443,11 +440,9 @@ void CVideoInfoTag::Serialize(CVariant& value) actor["thumbnail"] = CTextureCache::GetWrappedImageURL(m_cast[i].thumb); value["cast"].push_back(actor); } - value["set"] = m_set; - value["setid"] = CVariant(CVariant::VariantTypeArray); - for (unsigned int i = 0; i < m_setId.size(); i++) - value["setid"].push_back(m_setId[i]); - value["tags"] = m_tags; + value["set"] = m_strSet; + value["setid"] = m_iSetId; + value["tag"] = m_tags; value["runtime"] = m_strRuntime; value["file"] = m_strFile; value["path"] = m_strPath; @@ -463,7 +458,7 @@ void CVideoInfoTag::Serialize(CVariant& value) value["firstaired"] = m_firstAired.IsValid() ? m_firstAired.GetAsDBDate() : StringUtils::EmptyString; value["showtitle"] = m_strShowTitle; value["album"] = m_strAlbum; - value["artist"] = StringUtils::Join(m_artist, " / "); + value["artist"] = m_artist; value["playcount"] = m_playCount; value["lastplayed"] = m_lastPlayed.IsValid() ? m_lastPlayed.GetAsDBDateTime() : StringUtils::EmptyString; value["top250"] = m_iTop250; @@ -474,7 +469,7 @@ void CVideoInfoTag::Serialize(CVariant& value) value["dbid"] = m_iDbId; value["fileid"] = m_iFileId; value["track"] = m_iTrack; - value["showlink"] = StringUtils::Join(m_showLink, " / "); + value["showlink"] = m_showLink; m_streamDetails.Serialize(value["streamdetails"]); CVariant resume = CVariant(CVariant::VariantTypeObject); resume["position"] = (float)m_resumePoint.timeInSeconds; @@ -500,7 +495,7 @@ void CVideoInfoTag::ToSortable(SortItem& sortable) sortable[FieldVotes] = m_strVotes; sortable[FieldStudio] = m_studio; sortable[FieldTrailer] = m_strTrailer; - sortable[FieldSet] = m_set; + sortable[FieldSet] = m_strSet; sortable[FieldTime] = m_strRuntime; sortable[FieldFilename] = m_strFile; sortable[FieldMPAA] = m_strMPAARating; @@ -518,9 +513,12 @@ void CVideoInfoTag::ToSortable(SortItem& sortable) sortable[FieldYear] = m_iYear; sortable[FieldSeason] = m_iSeason; sortable[FieldEpisodeNumber] = m_iEpisode; + sortable[FieldEpisodeNumberSpecialSort] = m_iSpecialSortEpisode; + sortable[FieldSeasonSpecialSort] = m_iSpecialSortSeason; sortable[FieldRating] = m_fRating; sortable[FieldId] = m_iDbId; sortable[FieldTrackNumber] = m_iTrack; + sortable[FieldTag] = m_tags; sortable[FieldTime] = m_streamDetails.GetVideoDuration(); sortable[FieldVideoResolution] = m_streamDetails.GetVideoHeight(); @@ -533,7 +531,7 @@ void CVideoInfoTag::ToSortable(SortItem& sortable) sortable[FieldSubtitleLanguage] = m_streamDetails.GetSubtitleLanguage(); - sortable[FieldInProgress] = m_resumePoint.timeInSeconds > 0 && m_resumePoint.totalTimeInSeconds > 0; + sortable[FieldInProgress] = m_resumePoint.IsPartWay(); sortable[FieldDateAdded] = m_dateAdded.IsValid() ? m_dateAdded.GetAsDBDateTime() : StringUtils::EmptyString; sortable[FieldMediaType] = DatabaseUtils::MediaTypeFromString(m_type); } @@ -660,7 +658,7 @@ void CVideoInfoTag::ParseNative(const TiXmlElement* movie, bool prioritise) node = node->NextSiblingElement("actor"); } - XMLUtils::GetStringArray(movie, "set", m_set, prioritise, g_advancedSettings.m_videoItemSeparator); + XMLUtils::GetString(movie, "set", m_strSet); XMLUtils::GetStringArray(movie, "tag", m_tags, prioritise, g_advancedSettings.m_videoItemSeparator); XMLUtils::GetStringArray(movie, "studio", m_studio, prioritise, g_advancedSettings.m_videoItemSeparator); // artists diff --git a/xbmc/video/VideoInfoTag.h b/xbmc/video/VideoInfoTag.h index 06c99b6e15..ef3028d92e 100644 --- a/xbmc/video/VideoInfoTag.h +++ b/xbmc/video/VideoInfoTag.h @@ -95,8 +95,8 @@ public: std::vector<std::string> m_artist; std::vector< SActorInfo > m_cast; typedef std::vector< SActorInfo >::const_iterator iCast; - std::vector<std::string> m_set; - std::vector<int> m_setId; + CStdString m_strSet; + int m_iSetId; std::vector<std::string> m_tags; CStdString m_strRuntime; CStdString m_strFile; diff --git a/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp b/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp index def694f10e..031be11a39 100644 --- a/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp +++ b/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp @@ -23,7 +23,6 @@ #include "GUIDialogAudioSubtitleSettings.h" #include "dialogs/GUIDialogFileBrowser.h" #include "GUIPassword.h" -#include "Util.h" #include "utils/URIUtils.h" #include "Application.h" #include "video/VideoDatabase.h" diff --git a/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp b/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp index b69310c4ca..01f86a600d 100644 --- a/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp @@ -41,6 +41,7 @@ #include "threads/SingleLock.h" #include "utils/log.h" #include "utils/Variant.h" +#include "Util.h" using namespace std; diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp index 0d1f63b442..40a6803d7e 100644 --- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp @@ -28,7 +28,7 @@ #include "video/windows/GUIWindowVideoNav.h" #include "dialogs/GUIDialogFileBrowser.h" #include "video/VideoInfoScanner.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "video/VideoInfoTag.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogOK.h" @@ -46,6 +46,7 @@ #include "GUIUserMessages.h" #include "TextureCache.h" #include "music/MusicDatabase.h" +#include "URL.h" using namespace std; using namespace XFILE; @@ -791,9 +792,9 @@ void CGUIDialogVideoInfo::PlayTrailer() Close(true); if (item.IsPlayList()) - g_application.getApplicationMessenger().MediaPlay(item); + CApplicationMessenger::Get().MediaPlay(item); else - g_application.getApplicationMessenger().PlayFile(item); + CApplicationMessenger::Get().PlayFile(item); } void CGUIDialogVideoInfo::SetLabel(int iControl, const CStdString &strLabel) diff --git a/xbmc/video/dialogs/GUIDialogVideoOverlay.cpp b/xbmc/video/dialogs/GUIDialogVideoOverlay.cpp index 5baaec47b3..e78b65fbc4 100644 --- a/xbmc/video/dialogs/GUIDialogVideoOverlay.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoOverlay.cpp @@ -20,7 +20,6 @@ */ #include "GUIDialogVideoOverlay.h" -#include "GUIInfoManager.h" #include "guilib/GUIWindowManager.h" #define CONTROL_PLAYTIME 2 diff --git a/xbmc/video/dialogs/GUIDialogVideoScan.cpp b/xbmc/video/dialogs/GUIDialogVideoScan.cpp index 989da9a386..6ecb69cb7a 100644 --- a/xbmc/video/dialogs/GUIDialogVideoScan.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoScan.cpp @@ -25,9 +25,10 @@ #include "Util.h" #include "guilib/GUIWindowManager.h" #include "settings/GUISettings.h" -#include "Application.h" +#include "ApplicationMessenger.h" #include "threads/SingleLock.h" #include "utils/log.h" +#include "URL.h" #define CONTROL_LABELSTATUS 401 #define CONTROL_LABELDIRECTORY 402 @@ -141,7 +142,7 @@ void CGUIDialogVideoScan::OnFinished() if (!g_guiSettings.GetBool("videolibrary.backgroundupdate")) { - g_application.getApplicationMessenger().Close(this,false,false); + CApplicationMessenger::Get().Close(this,false,false); } } diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp index 3c35e6639a..025186c01f 100644 --- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp @@ -23,7 +23,6 @@ #include "GUIDialogVideoSettings.h" #include "guilib/GUIWindowManager.h" #include "GUIPassword.h" -#include "Util.h" #include "utils/MathUtils.h" #include "settings/GUISettings.h" #ifdef HAS_VIDEO_PLAYBACK diff --git a/xbmc/video/windows/GUIWindowFullScreen.cpp b/xbmc/video/windows/GUIWindowFullScreen.cpp index 6f9989e681..1f0fc6c5c1 100644 --- a/xbmc/video/windows/GUIWindowFullScreen.cpp +++ b/xbmc/video/windows/GUIWindowFullScreen.cpp @@ -975,7 +975,11 @@ void CGUIWindowFullScreen::Render() void CGUIWindowFullScreen::RenderTTFSubtitles() { - if ((g_application.GetCurrentPlayer() == EPC_MPLAYER || g_application.GetCurrentPlayer() == EPC_DVDPLAYER) && + if ((g_application.GetCurrentPlayer() == EPC_MPLAYER || +#if defined(HAS_AMLPLAYER) + g_application.GetCurrentPlayer() == EPC_AMLPLAYER || +#endif + g_application.GetCurrentPlayer() == EPC_DVDPLAYER) && CUtil::IsUsingTTFSubtitles() && (g_application.m_pPlayer->GetSubtitleVisible())) { CSingleLock lock (m_fontLock); diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp index 1bfa29a723..00c12890f2 100644 --- a/xbmc/video/windows/GUIWindowVideoBase.cpp +++ b/xbmc/video/windows/GUIWindowVideoBase.cpp @@ -30,7 +30,6 @@ #include "addons/IAddon.h" #include "video/dialogs/GUIDialogVideoInfo.h" #include "GUIWindowVideoNav.h" -#include "dialogs/GUIDialogFileBrowser.h" #include "video/dialogs/GUIDialogVideoScan.h" #include "dialogs/GUIDialogSmartPlaylistEditor.h" #include "dialogs/GUIDialogProgress.h" @@ -51,7 +50,7 @@ #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogSelect.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "filesystem/Directory.h" #include "playlists/PlayList.h" #include "settings/Settings.h" @@ -67,6 +66,7 @@ #include "addons/Skin.h" #include "storage/MediaManager.h" #include "Autorun.h" +#include "URL.h" using namespace std; using namespace XFILE; @@ -569,7 +569,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const ScraperPtr &info2) int iString = 16009; if (info->Content() == CONTENT_TVSHOWS) iString = 20357; - if (!CGUIDialogKeyboard::ShowAndGetInput(movieName, g_localizeStrings.Get(iString), false)) + if (!CGUIKeyboardFactory::ShowAndGetInput(movieName, g_localizeStrings.Get(iString), false)) { m_database.Close(); return listNeedsUpdating; // user backed out @@ -827,7 +827,7 @@ void CGUIWindowVideoBase::GetResumeItemOffset(const CFileItem *item, int& starto if (!item->IsNFO() && !item->IsPlayList()) { - if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_resumePoint.timeInSeconds > 0.0) + if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_resumePoint.IsSet()) { startoffset = (int)(item->GetVideoInfoTag()->m_resumePoint.timeInSeconds*75); partNumber = item->GetVideoInfoTag()->m_resumePoint.partNumber; @@ -857,7 +857,7 @@ void CGUIWindowVideoBase::GetResumeItemOffset(const CFileItem *item, int& starto bool CGUIWindowVideoBase::HasResumeItemOffset(const CFileItem *item) { - int startoffset, partNumber = 0; + int startoffset = 0, partNumber = 0; GetResumeItemOffset(item, startoffset, partNumber); return startoffset > 0; } @@ -895,7 +895,6 @@ bool CGUIWindowVideoBase::OnFileAction(int iItem, int action) case SELECT_ACTION_CHOOSE: { CContextButtons choices; - bool resume = false; if (item->IsVideoDb()) { @@ -905,17 +904,13 @@ bool CGUIWindowVideoBase::OnFileAction(int iItem, int action) choices.Add(SELECT_ACTION_PLAYPART, 20324); // Play Part } - if (!item->IsLiveTV()) + CStdString resumeString = GetResumeString(*item); + if (!resumeString.IsEmpty()) { - CStdString resumeString = GetResumeString(*item); - if (!resumeString.IsEmpty()) - { - resume = true; - choices.Add(SELECT_ACTION_RESUME, resumeString); - choices.Add(SELECT_ACTION_PLAY, 12021); // Start from beginning - } + choices.Add(SELECT_ACTION_RESUME, resumeString); + choices.Add(SELECT_ACTION_PLAY, 12021); // Start from beginning } - if (!resume) + else choices.Add(SELECT_ACTION_PLAY, 208); // Play choices.Add(SELECT_ACTION_INFO, 22081); // Info @@ -1003,28 +998,20 @@ void CGUIWindowVideoBase::OnRestartItem(int iItem) CGUIMediaWindow::OnClick(iItem); } -CStdString CGUIWindowVideoBase::GetResumeString(CFileItem item) +CStdString CGUIWindowVideoBase::GetResumeString(const CFileItem &item) { CStdString resumeString; - CStdString partString; - CVideoDatabase db; - if (db.Open()) + int startOffset = 0, startPart = 0; + GetResumeItemOffset(&item, startOffset, startPart); + if (startOffset > 0) { - CBookmark bookmark; - CStdString itemPath(item.GetPath()); - if (item.IsVideoDb() || item.IsDVD()) - itemPath = item.GetVideoInfoTag()->m_strFileNameAndPath; - - if (db.GetResumeBookMark(itemPath, bookmark)) + resumeString.Format(g_localizeStrings.Get(12022).c_str(), StringUtils::SecondsToTimeString(startOffset/75).c_str()); + if (startPart > 0) { - resumeString.Format(g_localizeStrings.Get(12022).c_str(), StringUtils::SecondsToTimeString(lrint(bookmark.timeInSeconds)).c_str()); - if (bookmark.partNumber > 0) - { - partString.Format(g_localizeStrings.Get(23051).c_str(), bookmark.partNumber); - resumeString.append(" (").append(partString).append(")"); - } + CStdString partString; + partString.Format(g_localizeStrings.Get(23051).c_str(), startPart); + resumeString += " (" + partString + ")"; } - db.Close(); } return resumeString; } @@ -1637,7 +1624,7 @@ void CGUIWindowVideoBase::UpdateVideoTitle(const CFileItem* pItem) strInput = detail.m_strTitle; //Get the new title - if (!CGUIDialogKeyboard::ShowAndGetInput(strInput, g_localizeStrings.Get(16105), false)) + if (!CGUIKeyboardFactory::ShowAndGetInput(strInput, g_localizeStrings.Get(16105), false)) return; database.UpdateMovieTitle(iDbId, strInput, iType); @@ -1790,7 +1777,7 @@ void CGUIWindowVideoBase::AddToDatabase(int iItem) // prompt for data // enter a new title CStdString strTitle = pItem->GetLabel(); - if (!CGUIDialogKeyboard::ShowAndGetInput(strTitle, g_localizeStrings.Get(528), false)) // Enter Title + if (!CGUIKeyboardFactory::ShowAndGetInput(strTitle, g_localizeStrings.Get(528), false)) // Enter Title return; // pick genre @@ -1817,7 +1804,7 @@ void CGUIWindowVideoBase::AddToDatabase(int iItem) if (strGenre.IsEmpty()) { strGenre = g_localizeStrings.Get(532); // Manual Addition - if (!CGUIDialogKeyboard::ShowAndGetInput(strGenre, g_localizeStrings.Get(533), false)) // Enter Genre + if (!CGUIKeyboardFactory::ShowAndGetInput(strGenre, g_localizeStrings.Get(533), false)) // Enter Genre return; // user backed out if (strGenre.IsEmpty()) return; // no genre string @@ -1845,7 +1832,7 @@ void CGUIWindowVideoBase::AddToDatabase(int iItem) void CGUIWindowVideoBase::OnSearch() { CStdString strSearch; - if (!CGUIDialogKeyboard::ShowAndGetInput(strSearch, g_localizeStrings.Get(16017), false)) + if (!CGUIKeyboardFactory::ShowAndGetInput(strSearch, g_localizeStrings.Get(16017), false)) return ; strSearch.ToLower(); diff --git a/xbmc/video/windows/GUIWindowVideoBase.h b/xbmc/video/windows/GUIWindowVideoBase.h index cadba663ed..7f7d6e3d91 100644 --- a/xbmc/video/windows/GUIWindowVideoBase.h +++ b/xbmc/video/windows/GUIWindowVideoBase.h @@ -50,7 +50,10 @@ public: /*! \brief Show the resume menu for this item (if it has a resume bookmark) - If a resume bookmark is found, we set the item's m_lStartOffset to STARTOFFSET_RESUME + If a resume bookmark is found, we set the item's m_lStartOffset to STARTOFFSET_RESUME. + Note that we do this in favour of setting the resume point, as we need additional + information from the database (in particular, the playerState) when resuming some items + (eg ISO/VIDEO_TS). \param item item to check for a resume bookmark \return true if an option was chosen, false if the resume menu was cancelled. */ @@ -77,7 +80,7 @@ public: \param item selected item \return string containing the resume position or an empty string if there is no resume position */ - static CStdString GetResumeString(CFileItem item); + static CStdString GetResumeString(const CFileItem &item); protected: void OnScan(const CStdString& strPath, bool scanAll = false); diff --git a/xbmc/video/windows/GUIWindowVideoNav.cpp b/xbmc/video/windows/GUIWindowVideoNav.cpp index 2f2e8391dc..7757d2370e 100644 --- a/xbmc/video/windows/GUIWindowVideoNav.cpp +++ b/xbmc/video/windows/GUIWindowVideoNav.cpp @@ -42,6 +42,7 @@ #include "filesystem/File.h" #include "FileItem.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "settings/Settings.h" #include "settings/AdvancedSettings.h" #include "settings/GUISettings.h" @@ -51,7 +52,7 @@ #include "utils/URIUtils.h" #include "utils/StringUtils.h" #include "TextureCache.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" using namespace XFILE; using namespace VIDEODATABASEDIRECTORY; @@ -402,8 +403,8 @@ void CGUIWindowVideoNav::LoadVideoInfo(CFileItemList &items) Similarly, we assign the "clean" library labels to the item only if the "Replace filenames with library titles" setting is enabled. */ - bool stackItems = items.GetProperty("isstacked").asBoolean() || (StackingAvailable(items) && g_settings.m_videoStacking); - bool replaceLabels = g_guiSettings.GetBool("myvideos.replacelabels"); + const bool stackItems = items.GetProperty("isstacked").asBoolean() || (StackingAvailable(items) && g_settings.m_videoStacking); + const bool replaceLabels = g_guiSettings.GetBool("myvideos.replacelabels"); CFileItemList dbItems; /* NOTE: In the future when GetItemsForPath returns all items regardless of whether they're "in the library" @@ -521,9 +522,9 @@ void CGUIWindowVideoNav::UpdateButtons() bool CGUIWindowVideoNav::GetFilteredItems(const CStdString &filter, CFileItemList &items) { - bool result = CGUIMediaWindow::GetFilteredItems(filter, items); - ApplyWatchedFilter(items); - return result || g_settings.GetWatchMode(m_vecItems->GetContent()) != VIDEO_SHOW_ALL; + bool listchanged = CGUIMediaWindow::GetFilteredItems(filter, items); + listchanged |= ApplyWatchedFilter(items); + return listchanged; } /// \brief Search for names, genres, artists, directors, and plots with search string \e strSearch in the @@ -1356,7 +1357,7 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strTitle), song)) { - g_application.getApplicationMessenger().PlayFile(song); + CApplicationMessenger::Get().PlayFile(song); } return true; } @@ -1461,7 +1462,7 @@ bool CGUIWindowVideoNav::OnClick(int iItem) //Get the new title CStdString strTag; - if (!CGUIDialogKeyboard::ShowAndGetInput(strTag, g_localizeStrings.Get(20462), false)) + if (!CGUIKeyboardFactory::ShowAndGetInput(strTag, g_localizeStrings.Get(20462), false)) return true; CVideoDatabase videodb; @@ -1563,8 +1564,9 @@ CStdString CGUIWindowVideoNav::GetStartFolder(const CStdString &dir) return CGUIWindowVideoBase::GetStartFolder(dir); } -void CGUIWindowVideoNav::ApplyWatchedFilter(CFileItemList &items) +bool CGUIWindowVideoNav::ApplyWatchedFilter(CFileItemList &items) { + bool listchanged = false; CVideoDatabaseDirectory dir; NODE_TYPE node = dir.GetDirectoryChildType(items.GetPath()); @@ -1598,7 +1600,10 @@ void CGUIWindowVideoNav::ApplyWatchedFilter(CFileItemList &items) item->GetVideoInfoTag()->m_iEpisode = (int)item->GetProperty("unwatchedepisodes").asInteger(); if (watchMode == VIDEO_SHOW_WATCHED) item->GetVideoInfoTag()->m_iEpisode = (int)item->GetProperty("watchedepisodes").asInteger(); + if (watchMode == VIDEO_SHOW_ALL) + item->GetVideoInfoTag()->m_iEpisode = (int)item->GetProperty("totalepisodes").asInteger(); item->SetProperty("numepisodes", item->GetVideoInfoTag()->m_iEpisode); + listchanged = true; } if (filterWatched) @@ -1608,9 +1613,20 @@ void CGUIWindowVideoNav::ApplyWatchedFilter(CFileItemList &items) { items.Remove(i); i--; + listchanged = true; } } } + + if(node == NODE_TYPE_TITLE_TVSHOWS || node == NODE_TYPE_SEASONS) + { + // the watched filter may change the "numepisodes" property which is reflected in the TV_SHOWS and SEASONS nodes + // therefore, the items labels have to be refreshed, and possibly the list needs resorting as well. + items.ClearSortState(); // this is needed to force resorting even if sort method did not change + FormatAndSort(items); + } + + return listchanged; } bool CGUIWindowVideoNav::GetItemsForTag(const CStdString &strHeading, const std::string &type, CFileItemList &items, int idTag /* = -1 */, bool showAll /* = true */) diff --git a/xbmc/video/windows/GUIWindowVideoNav.h b/xbmc/video/windows/GUIWindowVideoNav.h index 631851ba4b..e7b2256177 100644 --- a/xbmc/video/windows/GUIWindowVideoNav.h +++ b/xbmc/video/windows/GUIWindowVideoNav.h @@ -49,7 +49,7 @@ protected: */ void LoadVideoInfo(CFileItemList &items); - void ApplyWatchedFilter(CFileItemList &items); + bool ApplyWatchedFilter(CFileItemList &items); virtual bool GetFilteredItems(const CStdString &filter, CFileItemList &items); virtual void OnItemLoaded(CFileItem* pItem) {}; diff --git a/xbmc/video/windows/GUIWindowVideoPlaylist.cpp b/xbmc/video/windows/GUIWindowVideoPlaylist.cpp index 12d4a7b5ef..b653eda9b1 100644 --- a/xbmc/video/windows/GUIWindowVideoPlaylist.cpp +++ b/xbmc/video/windows/GUIWindowVideoPlaylist.cpp @@ -28,7 +28,7 @@ #include "PartyModeManager.h" #include "dialogs/GUIDialogSmartPlaylistEditor.h" #include "guilib/GUIWindowManager.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "GUIUserMessages.h" #include "Favourites.h" #include "settings/Settings.h" @@ -364,7 +364,7 @@ void CGUIWindowVideoPlaylist::RemovePlayListItem(int iItem) void CGUIWindowVideoPlaylist::SavePlayList() { CStdString strNewFileName; - if (CGUIDialogKeyboard::ShowAndGetInput(strNewFileName, g_localizeStrings.Get(16012), false)) + if (CGUIKeyboardFactory::ShowAndGetInput(strNewFileName, g_localizeStrings.Get(16012), false)) { // need 2 rename it CStdString strPath, strFolder; diff --git a/xbmc/visualizations/DirectXSpectrum/directx_spectrum.vcxproj b/xbmc/visualizations/DirectXSpectrum/directx_spectrum.vcxproj index daa08f5181..b81bfbc993 100644 --- a/xbmc/visualizations/DirectXSpectrum/directx_spectrum.vcxproj +++ b/xbmc/visualizations/DirectXSpectrum/directx_spectrum.vcxproj @@ -67,6 +67,7 @@ <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <PrecompiledHeader>NotUsing</PrecompiledHeader> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Link> <AdditionalDependencies>d3dx9.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/xbmc/visualizations/EGLHelpers/Makefile.in b/xbmc/visualizations/EGLHelpers/Makefile.in new file mode 100644 index 0000000000..e82fa58bd8 --- /dev/null +++ b/xbmc/visualizations/EGLHelpers/Makefile.in @@ -0,0 +1,8 @@ +SRCS=VisGUIShader.cpp \ + VisMatrixGLES.cpp \ + VisShader.cpp + +LIB=eglhelpers.a + +include @abs_top_srcdir@/Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS)))
\ No newline at end of file diff --git a/xbmc/visualizations/Milkdrop/MilkdropXBMC.cpp b/xbmc/visualizations/Milkdrop/MilkdropXBMC.cpp index bd4f370e09..8cc7942ac7 100644 --- a/xbmc/visualizations/Milkdrop/MilkdropXBMC.cpp +++ b/xbmc/visualizations/Milkdrop/MilkdropXBMC.cpp @@ -93,7 +93,8 @@ extern "C" ADDON_STATUS ADDON_Create(void* hdl, void* props) _mkdir(visprops->profile); Preinit(); - g_plugin->PluginInitialize((LPDIRECT3DDEVICE9)visprops->device, visprops->x, visprops->y, visprops->width, visprops->height, visprops->pixelRatio); + if(!g_plugin || !g_plugin->PluginInitialize((LPDIRECT3DDEVICE9)visprops->device, visprops->x, visprops->y, visprops->width, visprops->height, visprops->pixelRatio)) + return ADDON_STATUS_UNKNOWN; return ADDON_STATUS_NEED_SAVEDSETTINGS; // We need some settings to be saved later before we quit this plugin } @@ -264,7 +265,7 @@ extern "C" void ADDON_FreeSettings() //----------------------------------------------------------------------------- extern "C" ADDON_STATUS ADDON_SetSetting(const char* id, const void* value) { - if (!id || !value) + if (!id || !value || !g_plugin) return ADDON_STATUS_UNKNOWN; if (strcmp(id, "###GetSavedSettings") == 0) // We have some settings to be saved in the settings.xml file diff --git a/xbmc/visualizations/Milkdrop/Plugin.vcxproj b/xbmc/visualizations/Milkdrop/Plugin.vcxproj index 1d91a5b972..574f6f939b 100644 --- a/xbmc/visualizations/Milkdrop/Plugin.vcxproj +++ b/xbmc/visualizations/Milkdrop/Plugin.vcxproj @@ -69,6 +69,7 @@ <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Link> <AdditionalDependencies>D3dx9.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/xbmc/visualizations/OpenGLSpectrum/Makefile.in b/xbmc/visualizations/OpenGLSpectrum/Makefile.in index 09b39593ae..b9f290330f 100644 --- a/xbmc/visualizations/OpenGLSpectrum/Makefile.in +++ b/xbmc/visualizations/OpenGLSpectrum/Makefile.in @@ -1,15 +1,16 @@ ARCH=@ARCH@ CXXFLAGS=-fPIC - +ifeq (@USE_ANDROID@,1) +SLIB = @abs_top_srcdir@/system/libvisopengl_spectrum.so +else SLIB = @abs_top_srcdir@/addons/visualization.glspectrum/opengl_spectrum.vis +endif OBJS = opengl_spectrum.o ifeq (@USE_OPENGLES@,1) DEFINES += -DHAS_GLES=2 INCLUDES+= -I@abs_top_srcdir@/xbmc/visualizations/EGLHelpers - OBJS += @abs_top_srcdir@/xbmc/visualizations/EGLHelpers/VisMatrixGLES.o - OBJS += @abs_top_srcdir@/xbmc/visualizations/EGLHelpers/VisGUIShader.o - OBJS += @abs_top_srcdir@/xbmc/visualizations/EGLHelpers/VisShader.o + OBJS += @abs_top_srcdir@/xbmc/visualizations/EGLHelpers/eglhelpers.a ifeq ($(findstring osx,$(ARCH)), osx) LDFLAGS += -framework OpenGLES else diff --git a/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp b/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp index fcfebf25b5..031aa1a20d 100644 --- a/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp +++ b/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp @@ -367,8 +367,8 @@ extern "C" void AudioData(const float* pAudioData, int iAudioDataLength, float * { if (c<iAudioDataLength) { - if(pAudioData[c] > y) - y = (int)(pAudioData[c] * (INT16_MAX+.5f)); + if((int)(pAudioData[c] * (INT16_MAX)) > y) + y = (int)(pAudioData[c] * (INT16_MAX)); } else continue; diff --git a/xbmc/visualizations/WaveForm/Main_gles.cpp b/xbmc/visualizations/WaveForm/Main_gles.cpp index 530346a333..75668cdb40 100644 --- a/xbmc/visualizations/WaveForm/Main_gles.cpp +++ b/xbmc/visualizations/WaveForm/Main_gles.cpp @@ -150,7 +150,7 @@ extern "C" void Render() //ver[i][0] = g_viewport.X + ((i / 255.0f) * g_viewport.Width); //ver[i][1] = g_viewport.Y + g_viewport.Height * 0.33f + (g_fWaveform[0][i] * g_viewport.Height * 0.15f); ver[i][0] = -1.0f + ((i / 255.0f) * 2.0f); - ver[i][1] = 0.5f + (g_fWaveform[0][i] * 0.000015f); + ver[i][1] = 0.5f + g_fWaveform[0][i]; ver[i][2] = 1.0f; idx[i] = i; } @@ -166,7 +166,7 @@ extern "C" void Render() //ver[i][0] = g_viewport.X + ((i / 255.0f) * g_viewport.Width); //ver[i][1] = g_viewport.Y + g_viewport.Height * 0.66f + (g_fWaveform[1][i] * g_viewport.Height * 0.15f); ver[i][0] = -1.0f + ((i / 255.0f) * 2.0f); - ver[i][1] = -0.5f + (g_fWaveform[1][i] * 0.000015f); + ver[i][1] = -0.5f + g_fWaveform[1][i]; ver[i][2] = 1.0f; idx[i] = i; diff --git a/xbmc/visualizations/WaveForm/Makefile.in b/xbmc/visualizations/WaveForm/Makefile.in index 20e9711a56..98117cfffc 100644 --- a/xbmc/visualizations/WaveForm/Makefile.in +++ b/xbmc/visualizations/WaveForm/Makefile.in @@ -1,15 +1,17 @@ ARCH=@ARCH@ CXXFLAGS=-fPIC +ifeq (@USE_ANDROID@,1) +SLIB = @abs_top_srcdir@/system/libvisWaveform.so +else SLIB = @abs_top_srcdir@/addons/visualization.waveform/Waveform.vis +endif ifeq (@USE_OPENGLES@,1) DEFINES += -DHAS_GLES=2 INCLUDES+= -I@abs_top_srcdir@/xbmc/visualizations/EGLHelpers OBJS = Main_gles.o - OBJS += @abs_top_srcdir@/xbmc/visualizations/EGLHelpers/VisMatrixGLES.o - OBJS += @abs_top_srcdir@/xbmc/visualizations/EGLHelpers/VisGUIShader.o - OBJS += @abs_top_srcdir@/xbmc/visualizations/EGLHelpers/VisShader.o + OBJS += @abs_top_srcdir@/xbmc/visualizations/EGLHelpers/eglhelpers.a ifeq ($(findstring osx,$(ARCH)), osx) LDFLAGS += -framework OpenGLES else diff --git a/xbmc/visualizations/WaveForm/Waveform.vcxproj b/xbmc/visualizations/WaveForm/Waveform.vcxproj index 966a8d4032..8d28076fa7 100644 --- a/xbmc/visualizations/WaveForm/Waveform.vcxproj +++ b/xbmc/visualizations/WaveForm/Waveform.vcxproj @@ -157,6 +157,7 @@ </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet> </ClCompile> <Link> <AdditionalDependencies> diff --git a/xbmc/visualizations/XBMCProjectM/Main.cpp b/xbmc/visualizations/XBMCProjectM/Main.cpp index 63dc8ac806..79070cdd09 100644 --- a/xbmc/visualizations/XBMCProjectM/Main.cpp +++ b/xbmc/visualizations/XBMCProjectM/Main.cpp @@ -78,7 +78,7 @@ bool g_UserPackFolder; char lastPresetDir[1024]; bool lastLockStatus; int lastPresetIdx; -int lastLoggedPresetIdx; +unsigned int lastLoggedPresetIdx; //-- Create ------------------------------------------------------------------- // Called once when the visualisation is created by XBMC. Do any setup here. @@ -381,6 +381,10 @@ extern "C" ADDON_STATUS ADDON_SetSetting(const char* id, const void* value) if (strcmp(id, "###GetSavedSettings") == 0) // We have some settings to be saved in the settings.xml file { + if (!globalPM) + { + return ADDON_STATUS_UNKNOWN; + } if (strcmp((char*)value, "0") == 0) { strcpy((char*)id, "lastpresetfolder"); diff --git a/xbmc/win32/WIN32Util.cpp b/xbmc/win32/WIN32Util.cpp index a32393833d..6b06f2e0e5 100644 --- a/xbmc/win32/WIN32Util.cpp +++ b/xbmc/win32/WIN32Util.cpp @@ -107,14 +107,14 @@ CStdString CWIN32Util::URLEncode(const CURL &url) return flat; } -int CWIN32Util::GetDriveStatus(const CStdString &strPath) +int CWIN32Util::GetDriveStatus(const CStdString &strPath, bool bStatusEx) { HANDLE hDevice; // handle to the drive to be examined int iResult; // results flag ULONG ulChanges=0; DWORD dwBytesReturned; T_SPDT_SBUF sptd_sb; //SCSI Pass Through Direct variable. - byte DataBuf[16]; //Buffer for holding data to/from drive. + byte DataBuf[8]; //Buffer for holding data to/from drive. hDevice = CreateFile( strPath.c_str(), // drive 0, // no access to the drive @@ -129,6 +129,7 @@ int CWIN32Util::GetDriveStatus(const CStdString &strPath) return -1; } + CLog::Log(LOGDEBUG, __FUNCTION__": Requesting media status for drive %s.", strPath.c_str()); iResult = DeviceIoControl((HANDLE) hDevice, // handle to device IOCTL_STORAGE_CHECK_VERIFY2, // dwIoControlCode NULL, // lpInBuffer @@ -143,6 +144,10 @@ int CWIN32Util::GetDriveStatus(const CStdString &strPath) if(iResult == 1) return 2; + // don't request the tray status as we often doesn't need it + if(!bStatusEx) + return 0; + hDevice = CreateFile( strPath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, @@ -163,8 +168,8 @@ int CWIN32Util::GetDriveStatus(const CStdString &strPath) sptd_sb.sptd.CdbLength=10; sptd_sb.sptd.SenseInfoLength=MAX_SENSE_LEN; sptd_sb.sptd.DataIn=SCSI_IOCTL_DATA_IN; - sptd_sb.sptd.DataTransferLength=8; - sptd_sb.sptd.TimeOutValue=108000; + sptd_sb.sptd.DataTransferLength=sizeof(DataBuf); + sptd_sb.sptd.TimeOutValue=2; sptd_sb.sptd.DataBuffer=(PVOID)&(DataBuf); sptd_sb.sptd.SenseInfoOffset=sizeof(SCSI_PASS_THROUGH_DIRECT); @@ -185,9 +190,11 @@ int CWIN32Util::GetDriveStatus(const CStdString &strPath) sptd_sb.sptd.Cdb[14]=0; sptd_sb.sptd.Cdb[15]=0; + ZeroMemory(DataBuf, 8); ZeroMemory(sptd_sb.SenseBuf, MAX_SENSE_LEN); //Send the command to drive + CLog::Log(LOGDEBUG, __FUNCTION__": Requesting tray status for drive %s.", strPath.c_str()); iResult = DeviceIoControl((HANDLE) hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, (PVOID)&sptd_sb, (DWORD)sizeof(sptd_sb), @@ -207,6 +214,7 @@ int CWIN32Util::GetDriveStatus(const CStdString &strPath) else return 2; // tray closed, media present } + CLog::Log(LOGERROR, __FUNCTION__": Could not determine tray status %d", GetLastError()); return -1; } @@ -493,7 +501,7 @@ void CWIN32Util::ExtendDllPath() HRESULT CWIN32Util::ToggleTray(const char cDriveLetter) { BOOL bRet= FALSE; - DWORD dwReq; + DWORD dwReq = 0; char cDL = cDriveLetter; if( !cDL ) { @@ -513,7 +521,7 @@ HRESULT CWIN32Util::ToggleTray(const char cDriveLetter) ( GetDriveType( strRootFormat ) == DRIVE_CDROM ) ) { DWORD dwDummy; - dwReq = (GetDriveStatus(strVolFormat) == 1) ? IOCTL_STORAGE_LOAD_MEDIA : IOCTL_STORAGE_EJECT_MEDIA; + dwReq = (GetDriveStatus(strVolFormat, true) == 1) ? IOCTL_STORAGE_LOAD_MEDIA : IOCTL_STORAGE_EJECT_MEDIA; bRet = DeviceIoControl( hDrive, dwReq, NULL, 0, NULL, 0, &dwDummy, NULL); CloseHandle( hDrive ); } @@ -544,7 +552,7 @@ HRESULT CWIN32Util::EjectTray(const char cDriveLetter) CStdString strVolFormat; strVolFormat.Format( _T("\\\\.\\%c:" ), cDL); - if(GetDriveStatus(strVolFormat) != 1) + if(GetDriveStatus(strVolFormat, true) != 1) return ToggleTray(cDL); else return S_OK; @@ -564,7 +572,7 @@ HRESULT CWIN32Util::CloseTray(const char cDriveLetter) CStdString strVolFormat; strVolFormat.Format( _T("\\\\.\\%c:" ), cDL); - if(GetDriveStatus(strVolFormat) == 1) + if(GetDriveStatus(strVolFormat, true) == 1) return ToggleTray(cDL); else return S_OK; diff --git a/xbmc/win32/WIN32Util.h b/xbmc/win32/WIN32Util.h index 18133666df..9a8f7686f8 100644 --- a/xbmc/win32/WIN32Util.h +++ b/xbmc/win32/WIN32Util.h @@ -50,7 +50,7 @@ public: static CStdString URLEncode(const CURL &url); static CStdString GetLocalPath(const CStdString &strPath); static char FirstDriveFromMask (ULONG unitmask); - static int GetDriveStatus(const CStdString &strPath); + static int GetDriveStatus(const CStdString &strPath, bool bStatusEx=false); static bool PowerManagement(PowerState State); static int BatteryLevel(); static bool XBMCShellExecute(const CStdString &strPath, bool bWaitForScriptExit=false); diff --git a/xbmc/win32/XBMC_PC.cpp b/xbmc/win32/XBMC_PC.cpp index 8841f11f92..2cf9f4b72a 100644 --- a/xbmc/win32/XBMC_PC.cpp +++ b/xbmc/win32/XBMC_PC.cpp @@ -44,7 +44,7 @@ LONG WINAPI CreateMiniDump( EXCEPTION_POINTERS* pEp ) CStdString errorMsg; CStdString dumpFile; CDateTime now(CDateTime::GetCurrentDateTime()); - dumpFile.Format("%s\\xbmc_crashlog-%04i%02i%02i-%02i%02i%02i.dmp", CWIN32Util::GetProfilePath().c_str(), now.GetYear(), now.GetMonth(), now.GetDay(), now.GetHour(), now.GetMinute(), now.GetSecond()); + dumpFile.Format("%s\\xbmc_crashlog-%s-%04i%02i%02i-%02i%02i%02i.dmp", CWIN32Util::GetProfilePath().c_str(), GIT_REV, now.GetYear(), now.GetMonth(), now.GetDay(), now.GetHour(), now.GetMinute(), now.GetSecond()); HANDLE hFile = CreateFile(dumpFile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); // Call MiniDumpWriteDump api with the dump file diff --git a/xbmc/win32/XBMC_PC.rc b/xbmc/win32/XBMC_PC.rc index 9f496743ee..be282f25f2 100644 --- a/xbmc/win32/XBMC_PC.rc +++ b/xbmc/win32/XBMC_PC.rc @@ -71,12 +71,12 @@ BEGIN BEGIN VALUE "CompanyName", "Team XBMC" VALUE "FileDescription", "XBMC" - VALUE "FileVersion", "12.0-ALPHA4" + VALUE "FileVersion", "12.0-ALPHA5" VALUE "InternalName", "XBMC.exe" VALUE "LegalCopyright", "Copyright (c) Team XBMC. All rights reserved." VALUE "OriginalFilename", "XBMC.exe" VALUE "ProductName", "XBMC for Windows" - VALUE "ProductVersion", "12.0-ALPHA4" + VALUE "ProductVersion", "12.0-ALPHA5" END END BLOCK "VarFileInfo" diff --git a/xbmc/windowing/WinEvents.h b/xbmc/windowing/WinEvents.h index 09a36f027c..e2eb3e993f 100644 --- a/xbmc/windowing/WinEvents.h +++ b/xbmc/windowing/WinEvents.h @@ -47,6 +47,10 @@ public: #include "osx/WinEventsIOS.h" #define CWinEvents CWinEventsIOS +#elif defined(TARGET_ANDROID) +#include "android/WinEventsAndroid.h" +#define CWinEvents CWinEventsAndroid + #elif defined(TARGET_FREEBSD) && defined(HAS_SDL_WIN_EVENTS) #include "WinEventsSDL.h" #define CWinEvents CWinEventsSDL diff --git a/xbmc/windowing/WinEventsSDL.cpp b/xbmc/windowing/WinEventsSDL.cpp index 6bc9109424..27e62c8d51 100644 --- a/xbmc/windowing/WinEventsSDL.cpp +++ b/xbmc/windowing/WinEventsSDL.cpp @@ -25,6 +25,7 @@ #include "WinEvents.h" #include "WinEventsSDL.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "guilib/GUIWindowManager.h" #ifdef HAS_SDL_JOYSTICK #include "input/SDLJoystick.h" @@ -35,7 +36,7 @@ #include "osx/CocoaInterface.h" #endif -#if defined(_LINUX) && !defined(__APPLE__) +#if defined(_LINUX) && !defined(__APPLE__) && !defined(__ANDROID__) #include <X11/Xlib.h> #include <X11/XKBlib.h> #include "input/XBMC_keysym.h" @@ -222,7 +223,8 @@ bool CWinEventsSDL::MessagePump() switch(event.type) { case SDL_QUIT: - if (!g_application.m_bStop) g_application.getApplicationMessenger().Quit(); + if (!g_application.m_bStop) + CApplicationMessenger::Get().Quit(); break; #ifdef HAS_SDL_JOYSTICK @@ -402,7 +404,7 @@ bool CWinEventsSDL::ProcessOSXShortcuts(SDL_Event& event) { case SDLK_q: // CMD-q to quit if (!g_application.m_bStop) - g_application.getApplicationMessenger().Quit(); + CApplicationMessenger::Get().Quit(); return true; case SDLK_f: // CMD-f to toggle fullscreen @@ -415,7 +417,7 @@ bool CWinEventsSDL::ProcessOSXShortcuts(SDL_Event& event) case SDLK_h: // CMD-h to hide (but we minimize for now) case SDLK_m: // CMD-m to minimize - g_application.getApplicationMessenger().Minimize(); + CApplicationMessenger::Get().Minimize(); return true; default: diff --git a/xbmc/windowing/WinSystem.cpp b/xbmc/windowing/WinSystem.cpp index 30c24e7928..303a5fe71e 100644 --- a/xbmc/windowing/WinSystem.cpp +++ b/xbmc/windowing/WinSystem.cpp @@ -45,7 +45,7 @@ CWinSystemBase::~CWinSystemBase() bool CWinSystemBase::InitWindowSystem() { UpdateResolutions(); - + g_settings.ApplyCalibrations(); return true; } diff --git a/xbmc/windowing/WinSystem.h b/xbmc/windowing/WinSystem.h index 1af91c65da..e6b08e28e0 100644 --- a/xbmc/windowing/WinSystem.h +++ b/xbmc/windowing/WinSystem.h @@ -33,7 +33,8 @@ typedef enum _WindowSystemType WINDOW_SYSTEM_IOS, WINDOW_SYSTEM_X11, WINDOW_SYSTEM_SDL, - WINDOW_SYSTEM_EGL + WINDOW_SYSTEM_EGL, + WINDOW_SYSTEM_ANDROID } WindowSystemType; struct RESOLUTION_WHR @@ -86,6 +87,7 @@ public: virtual void EnableSystemScreenSaver(bool bEnable) {}; virtual bool IsSystemScreenSaverEnabled() {return false;} virtual void ResetOSScreensaver() {}; + virtual bool EnableFrameLimiter() {return false;}; // resolution interfaces unsigned int GetWidth() { return m_nWidth; } diff --git a/xbmc/windowing/WindowingFactory.h b/xbmc/windowing/WindowingFactory.h index d36f683ab1..f4f918dc5c 100644 --- a/xbmc/windowing/WindowingFactory.h +++ b/xbmc/windowing/WindowingFactory.h @@ -36,7 +36,7 @@ #elif defined(TARGET_LINUX) && defined(HAS_GLES) && defined(HAVE_X11) #include "X11/WinSystemX11GLES.h" -#elif defined(TARGET_LINUX) && defined(HAS_GLES) && defined(HAS_EGL) +#elif defined(TARGET_LINUX) && defined(HAS_GLES) && defined(HAS_EGL) #include "egl/WinSystemGLES.h" #elif defined(TARGET_FREEBSD) && defined(HAS_GL) && defined(HAVE_X11) diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp index 201b0ad45a..36f369309a 100644 --- a/xbmc/windowing/X11/WinSystemX11.cpp +++ b/xbmc/windowing/X11/WinSystemX11.cpp @@ -51,6 +51,7 @@ CWinSystemX11::CWinSystemX11() : CWinSystemBase() m_glWindow = 0; m_wmWindow = 0; m_bWasFullScreenBeforeMinimize = false; + m_minimized = false; m_dpyLostTime = 0; XSetErrorHandler(XErrorHandler); @@ -132,11 +133,12 @@ bool CWinSystemX11::CreateNewWindow(const CStdString& name, bool fullScreen, RES if(!SetFullScreen(fullScreen, res, false)) return false; - CTexture iconTexture; - iconTexture.LoadFromFile("special://xbmc/media/icon.png"); + CBaseTexture* iconTexture = CTexture::LoadFromFile("special://xbmc/media/icon.png"); - SDL_WM_SetIcon(SDL_CreateRGBSurfaceFrom(iconTexture.GetPixels(), iconTexture.GetWidth(), iconTexture.GetHeight(), 32, iconTexture.GetPitch(), 0xff0000, 0x00ff00, 0x0000ff, 0xff000000L), NULL); + if (iconTexture) + SDL_WM_SetIcon(SDL_CreateRGBSurfaceFrom(iconTexture->GetPixels(), iconTexture->GetWidth(), iconTexture->GetHeight(), 32, iconTexture->GetPitch(), 0xff0000, 0x00ff00, 0x0000ff, 0xff000000L), NULL); SDL_WM_SetCaption("XBMC Media Center", NULL); + delete iconTexture; // register XRandR Events #if defined(HAS_XRANDR) @@ -440,6 +442,8 @@ void CWinSystemX11::NotifyAppActiveChange(bool bActivated) { if (bActivated && m_bWasFullScreenBeforeMinimize && !g_graphicsContext.IsFullScreenRoot()) g_graphicsContext.ToggleFullScreenRoot(); + + m_minimized = !bActivated; } bool CWinSystemX11::Minimize() { @@ -448,6 +452,7 @@ bool CWinSystemX11::Minimize() g_graphicsContext.ToggleFullScreenRoot(); SDL_WM_IconifyWindow(); + m_minimized = true; return true; } bool CWinSystemX11::Restore() @@ -464,6 +469,7 @@ bool CWinSystemX11::Show(bool raise) { XMapWindow(m_dpy, m_wmWindow); XSync(m_dpy, False); + m_minimized = false; return true; } @@ -546,4 +552,9 @@ int CWinSystemX11::XErrorHandler(Display* dpy, XErrorEvent* error) return 0; } +bool CWinSystemX11::EnableFrameLimiter() +{ + return m_minimized; +} + #endif diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h index a69aec1b28..5cc1199341 100644 --- a/xbmc/windowing/X11/WinSystemX11.h +++ b/xbmc/windowing/X11/WinSystemX11.h @@ -50,6 +50,7 @@ public: virtual int GetNumScreens() { return 1; } virtual void ShowOSMouse(bool show); virtual void ResetOSScreensaver(); + virtual bool EnableFrameLimiter(); virtual void NotifyAppActiveChange(bool bActivated); @@ -75,6 +76,7 @@ protected: Window m_wmWindow; Display* m_dpy; bool m_bWasFullScreenBeforeMinimize; + bool m_minimized; int m_RREventBase; CCriticalSection m_resourceSection; std::vector<IDispResource*> m_resources; diff --git a/xbmc/windowing/android/Makefile b/xbmc/windowing/android/Makefile new file mode 100644 index 0000000000..48c73b1d83 --- /dev/null +++ b/xbmc/windowing/android/Makefile @@ -0,0 +1,7 @@ +SRCS= \ + WinEventsAndroid.cpp \ + +LIB=windowing_android.a + +include ../../../Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/windowing/android/WinEventsAndroid.cpp b/xbmc/windowing/android/WinEventsAndroid.cpp new file mode 100644 index 0000000000..502f56649b --- /dev/null +++ b/xbmc/windowing/android/WinEventsAndroid.cpp @@ -0,0 +1,71 @@ +/* +* Copyright (C) 2010 Team XBMC +* http://www.xbmc.org +* +* This Program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This Program 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. +* +* You should have received a copy of the GNU General Public License +* along with XBMC; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* http://www.gnu.org/copyleft/gpl.html +* +*/ + +#include "system.h" +#include "windowing/WinEvents.h" +#include "WinEventsAndroid.h" +#include "input/XBMC_vkeys.h" +#include "Application.h" +#include "windowing/WindowingFactory.h" +#include "threads/CriticalSection.h" +#include "utils/log.h" +#include "guilib/GUIWindowManager.h" + +static CCriticalSection g_inputCond; + +PHANDLE_EVENT_FUNC CWinEventsBase::m_pEventFunc = NULL; + +static std::vector<XBMC_Event> events; + +void CWinEventsAndroid::DeInit() +{ +} + +void CWinEventsAndroid::Init() +{ +} + +void CWinEventsAndroid::MessagePush(XBMC_Event *newEvent) +{ + CSingleLock lock(g_inputCond); + events.push_back(*newEvent); +} + +bool CWinEventsAndroid::MessagePump() +{ + bool ret = false; + std::vector<XBMC_Event> copy_events; + { // double-buffered events to avoid constant locking for OnEvent(). + CSingleLock lock(g_inputCond); + copy_events = events; + events.clear(); + } + + for (std::vector<XBMC_Event>::iterator iter = copy_events.begin(); iter != copy_events.end(); iter++) + { + ret |= g_application.OnEvent(*iter); + + if (iter->type == XBMC_MOUSEBUTTONUP) + g_windowManager.SendMessage(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0); + } + + return ret; +} diff --git a/xbmc/windowing/android/WinEventsAndroid.h b/xbmc/windowing/android/WinEventsAndroid.h new file mode 100644 index 0000000000..6dd80da2f5 --- /dev/null +++ b/xbmc/windowing/android/WinEventsAndroid.h @@ -0,0 +1,42 @@ +/* +* Copyright (C) 2010 Team XBMC +* http://www.xbmc.org +* +* This Program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This Program 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. +* +* You should have received a copy of the GNU General Public License +* along with XBMC; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* http://www.gnu.org/copyleft/gpl.html +* +*/ + +#pragma once + +#ifndef WINDOW_EVENTS_ANDROID_H +#define WINDOW_EVENTS_ANDROID_H + +#include "windowing/WinEvents.h" +#include "input/MouseStat.h" + +class CWinEventsAndroid : public CWinEventsBase +{ +public: + static void Init(); + static void DeInit(); + static void MessagePush(XBMC_Event *newEvent); + static bool MessagePump(); + +protected: + +}; + +#endif // WINDOW_EVENTS_ANDROID_H diff --git a/xbmc/windowing/egl/Makefile b/xbmc/windowing/egl/Makefile index 01b27652a5..2a42d859fc 100644 --- a/xbmc/windowing/egl/Makefile +++ b/xbmc/windowing/egl/Makefile @@ -1,9 +1,10 @@ -INCLUDES=-I. -I../.. -I../../linux +INCLUDES=-I. -SRCS=WinBindingEGL.cpp \ - WinSystemGLES.cpp \ +SRCS = WinSystemGLES.cpp +SRCS+= WinEGLPlatformGeneric.cpp +SRCS+= WinEGLPlatformAndroid.cpp -LIB=windowing_egl.a +LIB = windowing_egl.a include ../../../Makefile.include -include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/windowing/egl/WinEGLPlatform.h b/xbmc/windowing/egl/WinEGLPlatform.h new file mode 100644 index 0000000000..4715c8ce88 --- /dev/null +++ b/xbmc/windowing/egl/WinEGLPlatform.h @@ -0,0 +1,39 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#ifdef HAS_EGL + +#include "system.h" + +#if defined(TARGET_ANDROID) + #include "xbmc/windowing/egl/WinEGLPlatformAndroid.h" + class CWinEGLPlatformAndroid; + #define CWinEGLPlatform CWinEGLPlatformAndroid + +#else + #include "xbmc/windowing/egl/WinEGLPlatformGeneric.h" + class CWinEGLPlatformGeneric; + #define CWinEGLPlatform CWinEGLPlatformGeneric + +#endif + +#endif
\ No newline at end of file diff --git a/xbmc/windowing/egl/WinEGLPlatformAndroid.cpp b/xbmc/windowing/egl/WinEGLPlatformAndroid.cpp new file mode 100644 index 0000000000..7f0add58bc --- /dev/null +++ b/xbmc/windowing/egl/WinEGLPlatformAndroid.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <linux/fb.h> +#include <sys/ioctl.h> + +#include "WinEGLPlatformAndroid.h" +#include "android/activity/XBMCApp.h" +//////////////////////////////////////////////////////////////////////////////////////////// +EGLNativeWindowType CWinEGLPlatformAndroid::InitWindowSystem(EGLNativeDisplayType nativeDisplay, int width, int height, int bpp) +{ + if (CXBMCApp::GetNativeWindow() == NULL) + return 0; + + CWinEGLPlatformGeneric::InitWindowSystem(nativeDisplay, width, height, bpp); + + return getNativeWindow(); +} + +void CWinEGLPlatformAndroid::DestroyWindowSystem(EGLNativeWindowType native_window) +{ + CWinEGLPlatformGeneric::DestroyWindowSystem(native_window); +} + +bool CWinEGLPlatformAndroid::ClampToGUIDisplayLimits(int &width, int &height) +{ + return false; +} + +bool CWinEGLPlatformAndroid::CreateWindow() +{ + EGLint format; + // EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is + // guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). + // As soon as we picked a EGLConfig, we can safely reconfigure the + // ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. + eglGetConfigAttrib(m_display, m_config, EGL_NATIVE_VISUAL_ID, &format); + + CXBMCApp::SetBuffersGeometry(0, 0, format); + + CWinEGLPlatformGeneric::CreateWindow(); + return true; +} + +EGLNativeWindowType CWinEGLPlatformAndroid::getNativeWindow() +{ + return (EGLNativeWindowType)CXBMCApp::GetNativeWindow(); +} diff --git a/xbmc/windowing/egl/WinEGLPlatformAndroid.h b/xbmc/windowing/egl/WinEGLPlatformAndroid.h new file mode 100644 index 0000000000..4e34471bb2 --- /dev/null +++ b/xbmc/windowing/egl/WinEGLPlatformAndroid.h @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#if defined(TARGET_ANDROID) + +#include "WinEGLPlatformGeneric.h" + +class CWinEGLPlatformAndroid : public CWinEGLPlatformGeneric +{ +public: + virtual EGLNativeWindowType InitWindowSystem(EGLNativeDisplayType nativeDisplay, int width, int height, int bpp); + virtual void DestroyWindowSystem(EGLNativeWindowType native_window); + virtual bool ClampToGUIDisplayLimits(int &width, int &height); + + virtual bool CreateWindow(); + +protected: + virtual EGLNativeWindowType getNativeWindow(); +}; + +#endif diff --git a/xbmc/windowing/egl/WinBindingEGL.cpp b/xbmc/windowing/egl/WinEGLPlatformGeneric.cpp index 0bf2c6cf0b..2f2a83bc55 100644 --- a/xbmc/windowing/egl/WinBindingEGL.cpp +++ b/xbmc/windowing/egl/WinEGLPlatformGeneric.cpp @@ -25,62 +25,80 @@ #ifdef HAS_EGL -#include "WinBindingEGL.h" +#include "WinEGLPlatformGeneric.h" #include "utils/log.h" #include <string> -CWinBindingEGL::CWinBindingEGL() +CWinEGLPlatformGeneric::CWinEGLPlatformGeneric() { m_surface = EGL_NO_SURFACE; m_context = EGL_NO_CONTEXT; m_display = EGL_NO_DISPLAY; + + // most egl platforms cannot render 1080p + // default to 720p + m_width = 1280; + m_height = 720; } -CWinBindingEGL::~CWinBindingEGL() +CWinEGLPlatformGeneric::~CWinEGLPlatformGeneric() { - DestroyWindow(); + UninitializeDisplay(); } -bool CWinBindingEGL::ReleaseSurface() +EGLNativeWindowType CWinEGLPlatformGeneric::InitWindowSystem(EGLNativeDisplayType nativeDisplay, int width, int height, int bpp) { - EGLBoolean eglStatus; + m_nativeDisplay = nativeDisplay; + m_width = width; + m_height = height; - if (m_surface == EGL_NO_SURFACE) - { - return true; - } + return getNativeWindow(); +} - eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +void CWinEGLPlatformGeneric::DestroyWindowSystem(EGLNativeWindowType native_window) +{ + UninitializeDisplay(); +} - eglStatus = eglDestroySurface(m_display, m_surface); - if (!eglStatus) - { - CLog::Log(LOGERROR, "Error destroying EGL surface"); - return false; - } +bool CWinEGLPlatformGeneric::SetDisplayResolution(int width, int height, float refresh, bool interlace) +{ + return false; +} - m_surface = EGL_NO_SURFACE; +bool CWinEGLPlatformGeneric::ClampToGUIDisplayLimits(int &width, int &height) +{ + width = m_width; + height = m_height; + return true; +} +bool CWinEGLPlatformGeneric::ProbeDisplayResolutions(std::vector<CStdString> &resolutions) +{ + resolutions.clear(); + + CStdString resolution; + resolution.Format("%dx%dp60Hz", m_width, m_height); + resolutions.push_back(resolution); return true; } -bool CWinBindingEGL::CreateWindow(EGLNativeDisplayType nativeDisplay, EGLNativeWindowType nativeWindow) +bool CWinEGLPlatformGeneric::InitializeDisplay() { + if (m_display != EGL_NO_DISPLAY && m_config != NULL) + return true; + EGLBoolean eglStatus; EGLint configCount; - EGLConfig* configList = NULL; + EGLConfig* configList = NULL; - m_nativeDisplay = nativeDisplay; - m_nativeWindow = nativeWindow; - - m_display = eglGetDisplay(nativeDisplay); + m_display = eglGetDisplay(m_nativeDisplay); if (m_display == EGL_NO_DISPLAY) { CLog::Log(LOGERROR, "EGL failed to obtain display"); return false; } - + if (!eglInitialize(m_display, 0, 0)) { CLog::Log(LOGERROR, "EGL failed to initialize"); @@ -91,6 +109,7 @@ bool CWinBindingEGL::CreateWindow(EGLNativeDisplayType nativeDisplay, EGLNativeW EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 16, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, @@ -107,7 +126,7 @@ bool CWinBindingEGL::CreateWindow(EGLNativeDisplayType nativeDisplay, EGLNativeW CLog::Log(LOGERROR, "EGL failed to return any matching configurations: %d", eglStatus); return false; } - + // Allocate room for the list of matching configurations configList = (EGLConfig*)malloc(configCount * sizeof(EGLConfig)); if (!configList) @@ -124,22 +143,108 @@ bool CWinBindingEGL::CreateWindow(EGLNativeDisplayType nativeDisplay, EGLNativeW CLog::Log(LOGERROR, "EGL failed to populate configuration list: %d", eglStatus); return false; } - + // Select an EGL configuration that matches the native window m_config = configList[0]; if (m_surface != EGL_NO_SURFACE) - { ReleaseSurface(); + + free(configList); + return true; +} + +bool CWinEGLPlatformGeneric::UninitializeDisplay() +{ + EGLBoolean eglStatus; + + DestroyWindow(); + + if (m_display != EGL_NO_DISPLAY) + { + eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + eglStatus = eglTerminate(m_display); + if (!eglStatus) + CLog::Log(LOGERROR, "Error terminating EGL"); + m_display = EGL_NO_DISPLAY; } + return true; +} + +bool CWinEGLPlatformGeneric::CreateWindow() +{ + if (m_display == EGL_NO_DISPLAY || m_config == NULL) + { + if (!InitializeDisplay()) + return false; + } + + if (m_surface != EGL_NO_SURFACE) + return true; + + m_nativeWindow = getNativeWindow(); + m_surface = eglCreateWindowSurface(m_display, m_config, m_nativeWindow, NULL); if (!m_surface) - { + { CLog::Log(LOGERROR, "EGL couldn't create window surface"); return false; } + // Let's get the current width and height + EGLint width, height; + if (!eglQuerySurface(m_display, m_surface, EGL_WIDTH, &width) || !eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &height) || + width <= 0 || height <= 0) + { + CLog::Log(LOGERROR, "EGL couldn't provide the surface's width and/or height"); + return false; + } + + m_width = width; + m_height = height; + + return true; +} + +bool CWinEGLPlatformGeneric::DestroyWindow() +{ + EGLBoolean eglStatus; + + ReleaseSurface(); + + if (m_surface == EGL_NO_SURFACE) + return true; + + eglStatus = eglDestroySurface(m_display, m_surface); + if (!eglStatus) + { + CLog::Log(LOGERROR, "Error destroying EGL surface"); + return false; + } + + m_surface = EGL_NO_SURFACE; + m_width = 0; + m_height = 0; + + return true; +} + +bool CWinEGLPlatformGeneric::BindSurface() +{ + EGLBoolean eglStatus; + + if (m_display == EGL_NO_DISPLAY || m_surface == EGL_NO_SURFACE || m_config == NULL) + { + CLog::Log(LOGINFO, "EGL not configured correctly. Let's try to do that now..."); + if (!CreateWindow()) + { + CLog::Log(LOGERROR, "EGL not configured correctly to create a surface"); + return false; + } + } + eglStatus = eglBindAPI(EGL_OPENGL_ES_API); if (!eglStatus) { @@ -171,8 +276,6 @@ bool CWinBindingEGL::CreateWindow(EGLNativeDisplayType nativeDisplay, EGLNativeW CLog::Log(LOGERROR, "EGL couldn't make context/surface current: %d", eglStatus); return false; } - - free(configList); eglSwapInterval(m_display, 0); @@ -203,9 +306,10 @@ bool CWinBindingEGL::CreateWindow(EGLNativeDisplayType nativeDisplay, EGLNativeW return true; } -bool CWinBindingEGL::DestroyWindow() +bool CWinEGLPlatformGeneric::ReleaseSurface() { EGLBoolean eglStatus; + if (m_context != EGL_NO_CONTEXT) { eglStatus = eglDestroyContext(m_display, m_context); @@ -214,40 +318,30 @@ bool CWinBindingEGL::DestroyWindow() m_context = EGL_NO_CONTEXT; } - if (m_surface != EGL_NO_SURFACE) - { - eglStatus = eglDestroySurface(m_display, m_surface); - if (!eglStatus) - CLog::Log(LOGERROR, "Error destroying EGL surface"); - m_surface = EGL_NO_SURFACE; - } - if (m_display != EGL_NO_DISPLAY) - { eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglStatus = eglTerminate(m_display); - if (!eglStatus) - CLog::Log(LOGERROR, "Error terminating EGL"); - m_display = EGL_NO_DISPLAY; - } + return true; +} +bool CWinEGLPlatformGeneric::ShowWindow(bool show) +{ return true; } -void CWinBindingEGL::SwapBuffers() +void CWinEGLPlatformGeneric::SwapBuffers() { eglSwapBuffers(m_display, m_surface); } -bool CWinBindingEGL::SetVSync(bool enable) +bool CWinEGLPlatformGeneric::SetVSync(bool enable) { // depending how buffers are setup, eglSwapInterval // might fail so let caller decide if this is an error. return eglSwapInterval(m_display, enable ? 1 : 0); } -bool CWinBindingEGL::IsExtSupported(const char* extension) +bool CWinEGLPlatformGeneric::IsExtSupported(const char* extension) { CStdString name; @@ -258,27 +352,18 @@ bool CWinBindingEGL::IsExtSupported(const char* extension) return m_eglext.find(name) != std::string::npos; } -EGLNativeWindowType CWinBindingEGL::GetNativeWindow() -{ - return m_nativeWindow; -} - -EGLNativeDisplayType CWinBindingEGL::GetNativeDisplay() +EGLNativeWindowType CWinEGLPlatformGeneric::getNativeWindow() { - return m_nativeDisplay; + // most egl platforms can handle EGLNativeWindowType == 0 + return 0; } -EGLDisplay CWinBindingEGL::GetDisplay() +EGLDisplay CWinEGLPlatformGeneric::GetEGLDisplay() { return m_display; } -EGLSurface CWinBindingEGL::GetSurface() -{ - return m_surface; -} - -EGLContext CWinBindingEGL::GetContext() +EGLContext CWinEGLPlatformGeneric::GetEGLContext() { return m_context; } diff --git a/xbmc/windowing/egl/WinBindingEGL.h b/xbmc/windowing/egl/WinEGLPlatformGeneric.h index c7b80f2a9e..5aa657cabf 100644 --- a/xbmc/windowing/egl/WinBindingEGL.h +++ b/xbmc/windowing/egl/WinEGLPlatformGeneric.h @@ -1,3 +1,4 @@ +#pragma once /* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org @@ -19,9 +20,6 @@ * */ -#ifndef WINDOW_BINDING_EGL_H -#define WINDOW_BINDING_EGL_H - #include "utils/StringUtils.h" #include <EGL/egl.h> @@ -29,26 +27,36 @@ #include <EGL/eglext.h> #endif -class CWinBindingEGL +class CWinEGLPlatformGeneric { public: - CWinBindingEGL(); - ~CWinBindingEGL(); + CWinEGLPlatformGeneric(); + virtual ~CWinEGLPlatformGeneric(); - bool CreateWindow(EGLNativeDisplayType nativeDisplay, EGLNativeWindowType nativeWindow); - bool DestroyWindow(); - bool ReleaseSurface(); - void SwapBuffers(); - bool SetVSync(bool enable); - bool IsExtSupported(const char* extension); + virtual EGLNativeWindowType InitWindowSystem(EGLNativeDisplayType nativeDisplay, int width, int height, int bpp); + virtual void DestroyWindowSystem(EGLNativeWindowType native_window); + virtual bool SetDisplayResolution(int width, int height, float refresh, bool interlace); + virtual bool ClampToGUIDisplayLimits(int &width, int &height); + virtual bool ProbeDisplayResolutions(std::vector<CStdString> &resolutions); + + virtual bool InitializeDisplay(); + virtual bool UninitializeDisplay(); + virtual bool CreateWindow(); + virtual bool DestroyWindow(); + virtual bool BindSurface(); + virtual bool ReleaseSurface(); + + virtual bool ShowWindow(bool show); + virtual void SwapBuffers(); + virtual bool SetVSync(bool enable); + virtual bool IsExtSupported(const char* extension); - EGLNativeWindowType GetNativeWindow(); - EGLNativeDisplayType GetNativeDisplay(); - EGLDisplay GetDisplay(); - EGLSurface GetSurface(); - EGLContext GetContext(); + virtual EGLDisplay GetEGLDisplay(); + virtual EGLContext GetEGLContext(); protected: + virtual EGLNativeWindowType getNativeWindow(); + EGLNativeWindowType m_nativeWindow; EGLNativeDisplayType m_nativeDisplay; EGLDisplay m_display; @@ -56,7 +64,6 @@ protected: EGLConfig m_config; EGLContext m_context; CStdString m_eglext; + int m_width; + int m_height; }; - -#endif // WINDOW_BINDING_EGL_H - diff --git a/xbmc/windowing/egl/WinSystemGLES.cpp b/xbmc/windowing/egl/WinSystemGLES.cpp index cc6c27f2d0..b090ff526c 100644 --- a/xbmc/windowing/egl/WinSystemGLES.cpp +++ b/xbmc/windowing/egl/WinSystemGLES.cpp @@ -27,7 +27,6 @@ #include "settings/Settings.h" #include "guilib/Texture.h" #include "utils/log.h" -#include "WinBindingEGL.h" #include <vector> @@ -35,29 +34,32 @@ CWinSystemGLES::CWinSystemGLES() : CWinSystemBase() { m_window = NULL; - m_eglBinding = new CWinBindingEGL(); + m_eglplatform = new CWinEGLPlatform(); m_eWindowSystem = WINDOW_SYSTEM_EGL; } CWinSystemGLES::~CWinSystemGLES() { DestroyWindowSystem(); - delete m_eglBinding; + delete m_eglplatform; } bool CWinSystemGLES::InitWindowSystem() { - m_fb_width = 1280; - m_fb_height = 720; - m_fb_bpp = 8; - - CLog::Log(LOGDEBUG, "Video mode: %dx%d with %d bits per pixel.", - m_fb_width, m_fb_height, m_fb_bpp); - m_display = EGL_DEFAULT_DISPLAY; - m_window = (fbdev_window*)calloc(1, sizeof(fbdev_window)); - m_window->width = m_fb_width; - m_window->height = m_fb_height; + m_window = m_eglplatform->InitWindowSystem(m_display, 1920, 1080, 8); + + // Initialize the display + // This needs to happen before the call to CWinSystemBase::InitWindowSystem() + // (at least for Android) + if (!m_eglplatform->InitializeDisplay()) + return false; + + // Create a window to get valid width and height values + // This needs to happen before the call to CWinSystemBase::InitWindowSystem() + // (at least for Android) + if (!m_eglplatform->CreateWindow()) + return false; if (!CWinSystemBase::InitWindowSystem()) return false; @@ -67,7 +69,7 @@ bool CWinSystemGLES::InitWindowSystem() bool CWinSystemGLES::DestroyWindowSystem() { - free(m_window); + m_eglplatform->DestroyWindowSystem(m_window); m_window = NULL; return true; @@ -75,12 +77,35 @@ bool CWinSystemGLES::DestroyWindowSystem() bool CWinSystemGLES::CreateNewWindow(const CStdString& name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction) { + if (m_bWindowCreated && m_nWidth == res.iWidth && m_nHeight == res.iHeight && m_bFullScreen == fullScreen) + { + CLog::Log(LOGDEBUG, "CWinSystemGLES::CreateNewWindow: No need to create a new window"); + return true; + } + m_nWidth = res.iWidth; m_nHeight = res.iHeight; m_bFullScreen = fullScreen; - - if (!m_eglBinding->CreateWindow((EGLNativeDisplayType)m_display, (EGLNativeWindowType)m_window)) + + // Destroy any existing window + if (m_bWindowCreated) + m_eglplatform->DestroyWindow(); + + // temp until split gui/display res comes in + //m_eglplatform->SetDisplayResolution(res.iScreenWidth, res.iScreenHeight, + m_eglplatform->SetDisplayResolution(res.iWidth, res.iHeight, + res.fRefreshRate, res.dwFlags & D3DPRESENTFLAG_INTERLACED); + + // If we previously destroyed an existing window we need to create a new one + // (otherwise this is taken care of by InitWindowSystem()) + if (m_bWindowCreated) + m_eglplatform->CreateWindow(); + + if (!m_eglplatform->BindSurface()) + { + m_eglplatform->DestroyWindow(); return false; + } m_bWindowCreated = true; @@ -89,7 +114,7 @@ bool CWinSystemGLES::CreateNewWindow(const CStdString& name, bool fullScreen, RE bool CWinSystemGLES::DestroyWindow() { - if (!m_eglBinding->DestroyWindow()) + if (!m_eglplatform->DestroyWindow()) return false; m_bWindowCreated = false; @@ -105,12 +130,7 @@ bool CWinSystemGLES::ResizeWindow(int newWidth, int newHeight, int newLeft, int bool CWinSystemGLES::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) { - CLog::Log(LOGDEBUG, "CWinSystemDFB::SetFullScreen"); - m_nWidth = res.iWidth; - m_nHeight = res.iHeight; - m_bFullScreen = fullScreen; - - m_eglBinding->ReleaseSurface(); + CLog::Log(LOGDEBUG, "CWinSystemGLES::SetFullScreen"); CreateNewWindow("", fullScreen, res, NULL); CRenderSystemGLES::ResetRenderSystem(res.iWidth, res.iHeight, true, 0); @@ -120,11 +140,77 @@ bool CWinSystemGLES::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool b void CWinSystemGLES::UpdateResolutions() { - CWinSystemBase::UpdateResolutions(); - - int w = 1280; - int h = 720; - UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, 0.0); + std::vector<CStdString> resolutions; + + m_eglplatform->ProbeDisplayResolutions(resolutions); + + bool got_display_rez = false; + RESOLUTION Res720p60 = RES_INVALID; + RESOLUTION res_index = RES_DESKTOP; + + for (size_t i = 0; i < resolutions.size(); i++) + { + // 1280x720p50Hz + // 1280x720p60Hz + // 1920x1080i50Hz + // 1920x1080i60Hz + // 1920x1080p24Hz + // 1920x1080p50Hz + // 1920x1080p60Hz + + char interlacing; + int refresh, width, height; + if (sscanf(resolutions[i].c_str(), "%dx%d%c%dHz", &width, &height, &interlacing, &refresh) == 4) + { + got_display_rez = true; + // if this is a new setting, + // create a new empty setting to fill in. + if ((int)g_settings.m_ResInfo.size() <= res_index) + { + RESOLUTION_INFO res; + g_settings.m_ResInfo.push_back(res); + } + int gui_width = width; + int gui_height = height; + float gui_refresh = refresh; + m_eglplatform->ClampToGUIDisplayLimits(gui_width, gui_height); + + g_settings.m_ResInfo[res_index].iScreen = 0; + g_settings.m_ResInfo[res_index].bFullScreen = true; + g_settings.m_ResInfo[res_index].iSubtitles = (int)(0.965 * gui_height); + g_settings.m_ResInfo[res_index].dwFlags = D3DPRESENTFLAG_PROGRESSIVE; + g_settings.m_ResInfo[res_index].fRefreshRate = gui_refresh; + g_settings.m_ResInfo[res_index].fPixelRatio = 1.0f; + g_settings.m_ResInfo[res_index].iWidth = gui_width; + g_settings.m_ResInfo[res_index].iHeight = gui_height; + // temp until split gui/display res comes in + //g_settings.m_ResInfo[res_index].iScreenWidth = width; + //g_settings.m_ResInfo[res_index].iScreenHeight = height; + g_settings.m_ResInfo[res_index].strMode.Format("%dx%d @ %.2f - Full Screen", width, height, gui_refresh); + g_graphicsContext.ResetOverscan(g_settings.m_ResInfo[res_index]); + /* + CLog::Log(LOGINFO, "Found possible resolution for display %d with %d x %d @ %f Hz\n", + g_settings.m_ResInfo[res_index].iScreen, + g_settings.m_ResInfo[res_index].iScreenWidth, + g_settings.m_ResInfo[res_index].iScreenHeight, + g_settings.m_ResInfo[res_index].fRefreshRate); + */ + + if (width == 1280 && height == 720 && refresh == 60) + Res720p60 = res_index; + + res_index = (RESOLUTION)((int)res_index + 1); + } + } + // swap desktop index for 720p if available + if (Res720p60 != RES_INVALID) + { + CLog::Log(LOGINFO, "Found 720p at %d, setting to RES_DESKTOP at %d", (int)Res720p60, (int)RES_DESKTOP); + + RESOLUTION_INFO desktop = g_settings.m_ResInfo[RES_DESKTOP]; + g_settings.m_ResInfo[RES_DESKTOP] = g_settings.m_ResInfo[Res720p60]; + g_settings.m_ResInfo[Res720p60] = desktop; + } } bool CWinSystemGLES::IsExtSupported(const char* extension) @@ -132,12 +218,12 @@ bool CWinSystemGLES::IsExtSupported(const char* extension) if(strncmp(extension, "EGL_", 4) != 0) return CRenderSystemGLES::IsExtSupported(extension); - return m_eglBinding->IsExtSupported(extension); + return m_eglplatform->IsExtSupported(extension); } bool CWinSystemGLES::PresentRenderImpl(const CDirtyRegionList &dirty) { - m_eglBinding->SwapBuffers(); + m_eglplatform->SwapBuffers(); return true; } @@ -145,7 +231,7 @@ bool CWinSystemGLES::PresentRenderImpl(const CDirtyRegionList &dirty) void CWinSystemGLES::SetVSyncImpl(bool enable) { m_iVSyncMode = enable ? 10 : 0; - if (m_eglBinding->SetVSync(enable) == FALSE) + if (m_eglplatform->SetVSync(enable) == FALSE) CLog::Log(LOGERROR, "CWinSystemDFB::SetVSyncImpl: Could not set egl vsync"); } @@ -153,6 +239,15 @@ void CWinSystemGLES::ShowOSMouse(bool show) { } +bool CWinSystemGLES::HasCursor() +{ +#ifdef TARGET_ANDROID + return false; +#else + return true; +#endif +} + void CWinSystemGLES::NotifyAppActiveChange(bool bActivated) { } @@ -171,12 +266,22 @@ bool CWinSystemGLES::Restore() bool CWinSystemGLES::Hide() { - return true; + return m_eglplatform->ShowWindow(false); } bool CWinSystemGLES::Show(bool raise) { - return true; + return m_eglplatform->ShowWindow(true); +} + +EGLDisplay CWinSystemGLES::GetEGLDisplay() +{ + return m_eglplatform->GetEGLDisplay(); +} + +EGLContext CWinSystemGLES::GetEGLContext() +{ + return m_eglplatform->GetEGLContext(); } #endif diff --git a/xbmc/windowing/egl/WinSystemGLES.h b/xbmc/windowing/egl/WinSystemGLES.h index cd89803792..ff3959af63 100644 --- a/xbmc/windowing/egl/WinSystemGLES.h +++ b/xbmc/windowing/egl/WinSystemGLES.h @@ -26,12 +26,9 @@ #include "rendering/gles/RenderSystemGLES.h" #include "utils/GlobalsHandling.h" +#include "windowing/egl/WinEGLPlatform.h" #include "windowing/WinSystem.h" -class CWinBindingEGL; - -typedef struct fbdev_window fbdev_window; - class CWinSystemGLES : public CWinSystemBase, public CRenderSystemGLES { public: @@ -48,6 +45,7 @@ public: virtual bool IsExtSupported(const char* extension); virtual void ShowOSMouse(bool show); + virtual bool HasCursor(); virtual void NotifyAppActiveChange(bool bActivated); @@ -56,15 +54,15 @@ public: virtual bool Hide(); virtual bool Show(bool raise = true); + EGLDisplay GetEGLDisplay(); + EGLContext GetEGLContext(); + protected: virtual bool PresentRenderImpl(const CDirtyRegionList &dirty); virtual void SetVSyncImpl(bool enable); void *m_display; - fbdev_window *m_window; - CWinBindingEGL *m_eglBinding; - int m_fb_width; - int m_fb_height; - int m_fb_bpp; + EGLNativeWindowType m_window; + CWinEGLPlatform *m_eglplatform; }; XBMC_GLOBAL_REF(CWinSystemGLES,g_Windowing); diff --git a/xbmc/windowing/osx/WinEventsIOS.mm b/xbmc/windowing/osx/WinEventsIOS.mm index 6f2be4f667..9bbd2f49ec 100644 --- a/xbmc/windowing/osx/WinEventsIOS.mm +++ b/xbmc/windowing/osx/WinEventsIOS.mm @@ -53,22 +53,18 @@ void CWinEventsIOS::MessagePush(XBMC_Event *newEvent) bool CWinEventsIOS::MessagePump() { bool ret = false; - bool gotEvent = false; - XBMC_Event pumpEvent; + std::vector<XBMC_Event> copy_events; - CSingleLock lock(g_inputCond); - for (vector<XBMC_Event>::iterator it = events.begin(); it!=events.end(); ++it) - { - memcpy(&pumpEvent, (XBMC_Event *)&*it, sizeof(XBMC_Event)); - events.erase (events.begin(),events.begin()+1); - gotEvent = true; - break; - } - lock.Leave(); - - if (gotEvent) + { // double-buffered events to avoid constant locking for OnEvent(). + CSingleLock lock(g_inputCond); + copy_events = events; + events.clear(); + } + + for (vector<XBMC_Event>::iterator it = copy_events.begin(); it!=copy_events.end(); ++it) { - if (pumpEvent.type == XBMC_USEREVENT) + XBMC_Event *pumpEvent = (XBMC_Event *)&*it; + if (pumpEvent->type == XBMC_USEREVENT) { // On ATV2, we push in events as a XBMC_USEREVENT, // the jbutton.which will be the keyID to translate using joystick.AppleRemote.xml @@ -76,18 +72,18 @@ bool CWinEventsIOS::MessagePump() std::string joystickName = "AppleRemote"; bool isAxis = false; float fAmount = 1.0; - unsigned char wKeyID = pumpEvent.jbutton.which; - unsigned int holdTime = pumpEvent.jbutton.holdTime; + unsigned char wKeyID = pumpEvent->jbutton.which; + unsigned int holdTime = pumpEvent->jbutton.holdTime; CLog::Log(LOGDEBUG,"CWinEventsIOS: Button press keyID = %i", wKeyID); ret |= g_application.ProcessJoystickEvent(joystickName, wKeyID, isAxis, fAmount, holdTime); } else - ret |= g_application.OnEvent(pumpEvent); + ret |= g_application.OnEvent(*it); //on ios touch devices - unfocus controls on finger lift #if !defined(TARGET_DARWIN_IOS_ATV2) - if (pumpEvent.type == XBMC_MOUSEBUTTONUP) + if (pumpEvent->type == XBMC_MOUSEBUTTONUP) { g_windowManager.SendMessage(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0); } diff --git a/xbmc/windowing/osx/WinSystemOSX.h b/xbmc/windowing/osx/WinSystemOSX.h index a40c112a2c..8f4581c75d 100644 --- a/xbmc/windowing/osx/WinSystemOSX.h +++ b/xbmc/windowing/osx/WinSystemOSX.h @@ -56,6 +56,7 @@ public: virtual void EnableSystemScreenSaver(bool bEnable); virtual bool IsSystemScreenSaverEnabled(); virtual void ResetOSScreensaver(); + virtual bool EnableFrameLimiter(); virtual void Register(IDispResource *resource); virtual void Unregister(IDispResource *resource); @@ -74,11 +75,15 @@ protected: bool SwitchToVideoMode(int width, int height, double refreshrate, int screenIdx); void FillInVideoModes(); bool FlushBuffer(void); + bool IsObscured(void); void* m_glContext; static void* m_lastOwnedContext; SDL_Surface* m_SDLSurface; CWinEventsOSX *m_osx_events; + bool m_obscured; + unsigned int m_obscured_timecheck; + bool m_use_system_screensaver; bool m_can_display_switch; void *m_windowDidMove; diff --git a/xbmc/windowing/osx/WinSystemOSX.mm b/xbmc/windowing/osx/WinSystemOSX.mm index 815fae0a49..338af237a4 100644 --- a/xbmc/windowing/osx/WinSystemOSX.mm +++ b/xbmc/windowing/osx/WinSystemOSX.mm @@ -23,7 +23,7 @@ //hack around problem with xbmc's typedef int BOOL // and obj-c's typedef unsigned char BOOL -#define BOOL XBMC_BOOL +#define BOOL XBMC_BOOL #include "WinSystemOSX.h" #include "WinEventsOSX.h" #include "Application.h" @@ -154,6 +154,17 @@ static NSWindow* blankingWindows[MAX_DISPLAYS]; void* CWinSystemOSX::m_lastOwnedContext = 0; //------------------------------------------------------------------------------------------ +CRect CGRectToCRect(CGRect cgrect) +{ + CRect crect = CRect( + cgrect.origin.x, + cgrect.origin.y, + cgrect.origin.x + cgrect.size.width, + cgrect.origin.y + cgrect.size.height); + return crect; +} + +//------------------------------------------------------------------------------------------ Boolean GetDictionaryBoolean(CFDictionaryRef theDict, const void* key) { // get a boolean from the dictionary @@ -214,17 +225,17 @@ void SetMenuBarVisible(bool visible) { if(visible) { - [[NSApplication sharedApplication] - setPresentationOptions: NSApplicationPresentationDefault]; + [[NSApplication sharedApplication] + setPresentationOptions: NSApplicationPresentationDefault]; } else { - [[NSApplication sharedApplication] - setPresentationOptions: NSApplicationPresentationHideMenuBar | - NSApplicationPresentationHideDock]; + [[NSApplication sharedApplication] + setPresentationOptions: NSApplicationPresentationHideMenuBar | + NSApplicationPresentationHideDock]; } } -//--------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------- CGDirectDisplayID GetDisplayID(int screen_index) { CGDirectDisplayID displayArray[MAX_DISPLAYS]; @@ -239,7 +250,7 @@ CGDirectDisplayID GetDisplayIDFromScreen(NSScreen *screen) { NSDictionary* screenInfo = [screen deviceDescription]; NSNumber* screenID = [screenInfo objectForKey:@"NSScreenNumber"]; - + return (CGDirectDisplayID)[screenID longValue]; } @@ -262,13 +273,13 @@ void BlankOtherDisplays(int screen_index) { int i; int numDisplays = [[NSScreen screens] count]; - + // zero out blankingWindows for debugging for (i=0; i<MAX_DISPLAYS; i++) { blankingWindows[i] = 0; } - + // Blank. for (i=0; i<numDisplays; i++) { @@ -277,20 +288,20 @@ void BlankOtherDisplays(int screen_index) // Get the size. NSScreen* pScreen = [[NSScreen screens] objectAtIndex:i]; NSRect screenRect = [pScreen frame]; - + // Build a blanking window. screenRect.origin = NSZeroPoint; blankingWindows[i] = [[NSWindow alloc] initWithContentRect:screenRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered - defer:NO + defer:NO screen:pScreen]; - + [blankingWindows[i] setBackgroundColor:[NSColor blackColor]]; [blankingWindows[i] setLevel:CGShieldingWindowLevel()]; [blankingWindows[i] makeKeyAndOrderFront:nil]; } - } + } } void UnblankDisplays(void) @@ -323,7 +334,7 @@ CGDisplayFadeReservationToken DisplayFadeToBlack(bool fade) void DisplayFadeFromBlack(CGDisplayFadeReservationToken fade_token, bool fade) { - if (fade_token != kCGDisplayFadeReservationInvalidToken) + if (fade_token != kCGDisplayFadeReservationInvalidToken) { if (fade) CGDisplayFade(fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); @@ -421,19 +432,19 @@ CFDictionaryRef GetMode(int width, int height, double refreshrate, int screenIdx { if ( screenIdx >= (signed)[[NSScreen screens] count]) return NULL; - + Boolean stretched; Boolean interlaced; Boolean safeForHardware; Boolean televisionoutput; int w, h, bitsperpixel; double rate; - RESOLUTION_INFO res; - + RESOLUTION_INFO res; + CLog::Log(LOGDEBUG, "GetMode looking for suitable mode with %d x %d @ %f Hz on display %d\n", width, height, refreshrate, screenIdx); CFArrayRef displayModes = CGDisplayAvailableModes(GetDisplayID(screenIdx)); - + if (NULL == displayModes) { CLog::Log(LOGERROR, "GetMode - no displaymodes found!"); @@ -450,13 +461,13 @@ CFDictionaryRef GetMode(int width, int height, double refreshrate, int screenIdx safeForHardware = GetDictionaryBoolean(displayMode, kCGDisplayModeIsSafeForHardware); televisionoutput = GetDictionaryBoolean(displayMode, kCGDisplayModeIsTelevisionOutput); w = GetDictionaryInt(displayMode, kCGDisplayWidth); - h = GetDictionaryInt(displayMode, kCGDisplayHeight); + h = GetDictionaryInt(displayMode, kCGDisplayHeight); rate = GetDictionaryDouble(displayMode, kCGDisplayRefreshRate); - if ((bitsperpixel == 32) && - (safeForHardware == YES) && - (stretched == NO) && + if ((bitsperpixel == 32) && + (safeForHardware == YES) && + (stretched == NO) && (interlaced == NO) && (w == width) && (h == height) && @@ -471,7 +482,7 @@ CFDictionaryRef GetMode(int width, int height, double refreshrate, int screenIdx } //--------------------------------------------------------------------------------- -static void DisplayReconfigured(CGDirectDisplayID display, +static void DisplayReconfigured(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void* userData) { CWinSystemOSX *winsys = (CWinSystemOSX*)userData; @@ -482,9 +493,12 @@ static void DisplayReconfigured(CGDirectDisplayID display, { // pre/post-reconfiguration changes RESOLUTION res = g_graphicsContext.GetVideoResolution(); + if (res == RES_INVALID) + return; + NSScreen* pScreen = nil; unsigned int screenIdx = g_settings.m_ResInfo[res].iScreen; - + if ( screenIdx < [[NSScreen screens] count] ) { pScreen = [[NSScreen screens] objectAtIndex:screenIdx]; @@ -511,6 +525,8 @@ CWinSystemOSX::CWinSystemOSX() : CWinSystemBase() m_glContext = 0; m_SDLSurface = NULL; m_osx_events = NULL; + m_obscured = false; + m_obscured_timecheck = XbmcThreads::SystemClockMillis() + 1000; m_use_system_screensaver = true; // check runtime, we only allow this on 10.5+ m_can_display_switch = (floor(NSAppKitVersionNumber) >= 949); @@ -527,10 +543,10 @@ bool CWinSystemOSX::InitWindowSystem() // set repeat to 10ms to ensure repeat time < frame time // so that hold times can be reliably detected SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, 10); - + if (!CWinSystemBase::InitWindowSystem()) return false; - + m_osx_events = new CWinEventsOSX(); if (m_can_display_switch) @@ -556,7 +572,7 @@ bool CWinSystemOSX::InitWindowSystem() } bool CWinSystemOSX::DestroyWindowSystem() -{ +{ NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center removeObserver:(windowDidMoveNoteClass*)m_windowDidMove name:NSWindowDidMoveNotification object:nil]; [center removeObserver:(windowDidReSizeNoteClass*)m_windowDidReSize name:NSWindowDidResizeNotification object:nil]; @@ -590,7 +606,7 @@ bool CWinSystemOSX::CreateNewWindow(const CStdString& name, bool fullScreen, RES SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Enable vertical sync to avoid any tearing. - SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); + SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); m_SDLSurface = SDL_SetVideoMode(m_nWidth, m_nHeight, 0, SDL_OPENGL | SDL_RESIZABLE); if (!m_SDLSurface) @@ -602,7 +618,7 @@ bool CWinSystemOSX::CreateNewWindow(const CStdString& name, bool fullScreen, RES NSView* view = [cur_context view]; if (!view) return false; - + // if we are not starting up windowed, then hide the initial SDL window // so we do not see it flash before the fade-out and switch to fullscreen. if (g_guiSettings.m_LookAndFeelResolution != RES_WINDOW) @@ -610,7 +626,7 @@ bool CWinSystemOSX::CreateNewWindow(const CStdString& name, bool fullScreen, RES // disassociate view from context [cur_context clearDrawable]; - + // release the context if (m_lastOwnedContext == cur_context) { @@ -618,12 +634,12 @@ bool CWinSystemOSX::CreateNewWindow(const CStdString& name, bool fullScreen, RES [ cur_context clearDrawable ]; [ cur_context release ]; } - + // create a new context NSOpenGLContext* new_context = (NSOpenGLContext*)CreateWindowedContext(nil); if (!new_context) return false; - + // associate with current view [new_context setView:view]; [new_context makeCurrentContext]; @@ -645,17 +661,17 @@ bool CWinSystemOSX::DestroyWindow() { return true; } - + extern "C" void SDL_SetWidthHeight(int w, int h); bool CWinSystemOSX::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop) { if (!m_glContext) return false; - + NSOpenGLContext* context = [NSOpenGLContext currentContext]; NSView* view; NSWindow* window; - + view = [context view]; if (view && (newWidth > 0) && (newHeight > 0)) { @@ -675,33 +691,36 @@ bool CWinSystemOSX::ResizeWindow(int newWidth, int newHeight, int newLeft, int n SDL_SetWidthHeight(newWidth, newHeight); [context makeCurrentContext]; - + m_nWidth = newWidth; m_nHeight = newHeight; m_glContext = context; - + return true; } static bool needtoshowme = true; bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) -{ - static NSWindow* windowedFullScreenwindow = NULL; +{ + static NSWindow* windowedFullScreenwindow = NULL; static NSScreen* last_window_screen = NULL; static NSPoint last_window_origin; static NSView* last_view = NULL; static NSSize last_view_size; static NSPoint last_view_origin; bool was_fullscreen = m_bFullScreen; + static int lastDisplayNr = res.iScreen; NSOpenGLContext* cur_context; - + // Fade to black to hide resolution-switching flicker and garbage. CGDisplayFadeReservationToken fade_token = DisplayFadeToBlack(needtoshowme); - + // If we're already fullscreen then we must be moving to a different display. + // or if we are still on the same display - it might be only a refreshrate/resolution + // change request. // Recurse to reset fullscreen mode and then continue. - if (was_fullscreen && fullScreen) + if (was_fullscreen && fullScreen && lastDisplayNr != res.iScreen) { needtoshowme = false; ShowHideNSWindow([last_view window], needtoshowme); @@ -709,15 +728,34 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl CWinSystemOSX::SetFullScreen(false, window, blankOtherDisplays); needtoshowme = true; } - + m_nWidth = res.iWidth; m_nHeight = res.iHeight; m_bFullScreen = fullScreen; cur_context = [NSOpenGLContext currentContext]; + + //handle resolution/refreshrate switching early here + if (m_bFullScreen) + { + if (m_can_display_switch) + { + // send pre-configuration change now and do not + // wait for switch videomode callback. This gives just + // a little more advanced notice of the display pre-change. + if (g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF) + CheckDisplayChanging(kCGDisplayBeginConfigurationFlag); + + // switch videomode + SwitchToVideoMode(res.iWidth, res.iHeight, res.fRefreshRate, res.iScreen); + lastDisplayNr = res.iScreen; + } + } + + //no context? done. if (!cur_context) { - DisplayFadeFromBlack(fade_token, needtoshowme); + DisplayFadeFromBlack(fade_token, needtoshowme); return false; } @@ -728,53 +766,41 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl [windowedFullScreenwindow release]; windowedFullScreenwindow = NULL; } - + if (m_bFullScreen) { // FullScreen Mode NSOpenGLContext* newContext = NULL; - if (m_can_display_switch) - { - // send pre-configuration change now and do not - // wait for switch videomode callback. This gives just - // a little more advanced notice of the display pre-change. - if (g_guiSettings.GetBool("videoplayer.adjustrefreshrate")) - CheckDisplayChanging(kCGDisplayBeginConfigurationFlag); - - // switch videomode - SwitchToVideoMode(res.iWidth, res.iHeight, res.fRefreshRate, res.iScreen); - } - // Save info about the windowed context so we can restore it when returning to windowed. last_view = [cur_context view]; last_view_size = [last_view frame].size; last_view_origin = [last_view frame].origin; last_window_screen = [[last_view window] screen]; last_window_origin = [[last_view window] frame].origin; - + if (g_guiSettings.GetBool("videoscreen.fakefullscreen")) { // This is Cocca Windowed FullScreen Mode - // Get the screen rect of our current display + // Get the screen rect of our current display NSScreen* pScreen = [[NSScreen screens] objectAtIndex:res.iScreen]; NSRect screenRect = [pScreen frame]; - + // remove frame origin offset of orginal display screenRect.origin = NSZeroPoint; - + // make a new window to act as the windowedFullScreen windowedFullScreenwindow = [[NSWindow alloc] initWithContentRect:screenRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered - defer:NO + defer:NO screen:pScreen]; - + [windowedFullScreenwindow setBackgroundColor:[NSColor blackColor]]; [windowedFullScreenwindow makeKeyAndOrderFront:nil]; - + // make our window the same level as the rest to enable cmd+tab switching - [windowedFullScreenwindow setLevel:NSNormalWindowLevel]; + [windowedFullScreenwindow setLevel:NSNormalWindowLevel]; // this will make our window topmost and hide all system messages //[windowedFullScreenwindow setLevel:CGShieldingWindowLevel()]; @@ -784,21 +810,21 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl // expand the mouse bounds in SDL view to fullscreen [ last_view setFrameOrigin:NSMakePoint(0.0, 0.0)]; [ last_view setFrameSize:NSMakeSize(m_nWidth, m_nHeight) ]; - + NSView* blankView = [[NSView alloc] init]; [windowedFullScreenwindow setContentView:blankView]; [windowedFullScreenwindow setContentSize:NSMakeSize(m_nWidth, m_nHeight)]; [windowedFullScreenwindow update]; [blankView setFrameSize:NSMakeSize(m_nWidth, m_nHeight)]; - + // Obtain windowed pixel format and create a new context. newContext = (NSOpenGLContext*)CreateWindowedContext((void* )cur_context); [newContext setView:blankView]; - + // Hide the menu bar. if (GetDisplayID(res.iScreen) == kCGDirectMainDisplay) SetMenuBarVisible(false); - + // Blank other displays if requested. if (blankOtherDisplays) BlankOtherDisplays(res.iScreen); @@ -816,13 +842,13 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl newContext = (NSOpenGLContext*)CreateFullScreenContext(res.iScreen, (void*)cur_context); if (!newContext) return false; - + // clear the current context [NSOpenGLContext clearCurrentContext]; - + // set fullscreen [newContext setFullScreen]; - + // Capture the display before going fullscreen. if (blankOtherDisplays == true) CGCaptureAllDisplays(); @@ -836,7 +862,7 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl // Hide the mouse. [NSCursor hide]; - + // Release old context if we created it. if (m_lastOwnedContext == cur_context) { @@ -844,7 +870,7 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl [ cur_context clearDrawable ]; [ cur_context release ]; } - + // activate context [newContext makeCurrentContext]; m_lastOwnedContext = newContext; @@ -854,9 +880,9 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl // Windowed Mode // exit fullscreen [cur_context clearDrawable]; - + [NSCursor unhide]; - + // Show menubar. if (GetDisplayID(res.iScreen) == kCGDirectMainDisplay) SetMenuBarVisible(true); @@ -865,7 +891,7 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl { // restore the windowed window level [[last_view window] setLevel:NSNormalWindowLevel]; - + // Get rid of the new window we created. if (windowedFullScreenwindow != NULL) { @@ -874,7 +900,7 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl [windowedFullScreenwindow release]; windowedFullScreenwindow = NULL; } - + // Unblank. // Force the unblank when returning from fullscreen, we get called with blankOtherDisplays set false. //if (blankOtherDisplays) @@ -885,12 +911,12 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl // release displays CGReleaseAllDisplays(); } - + // create our new context (sharing with the current one) NSOpenGLContext* newContext = (NSOpenGLContext*)CreateWindowedContext((void* )cur_context); if (!newContext) return false; - + // Assign view from old context, move back to original screen. [newContext setView:last_view]; [[last_view window] setFrameOrigin:last_window_origin]; @@ -899,7 +925,7 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl [ last_view setFrameOrigin:last_view_origin ]; // done with restoring windowed window, don't set last_view to NULL as we can lose it under dual displays. //last_window_screen = NULL; - + // Release the fullscreen context. if (m_lastOwnedContext == cur_context) { @@ -907,13 +933,13 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl [ cur_context clearDrawable ]; [ cur_context release ]; } - + // Activate context. [newContext makeCurrentContext]; m_lastOwnedContext = newContext; } - DisplayFadeFromBlack(fade_token, needtoshowme); + DisplayFadeFromBlack(fade_token, needtoshowme); ShowHideNSWindow([last_view window], needtoshowme); // need to make sure SDL tracks any window size changes @@ -931,21 +957,21 @@ void CWinSystemOSX::UpdateResolutions() double fps; // first screen goes into the current desktop mode - GetScreenResolution(&w, &h, &fps, 0); + GetScreenResolution(&w, &h, &fps, 0); UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, fps); - + // see resolution.h enum RESOLUTION for how the resolutions // have to appear in the g_settings.m_ResInfo vector // add the desktop resolutions of the other screens for(int i = 1; i < GetNumScreens(); i++) { - RESOLUTION_INFO res; + RESOLUTION_INFO res; // get current resolution of screen i - GetScreenResolution(&w, &h, &fps, i); + GetScreenResolution(&w, &h, &fps, i); UpdateDesktopResolution(res, i, w, h, fps); g_settings.m_ResInfo.push_back(res); } - + if (m_can_display_switch) { // now just fill in the possible reolutions for the attached screens @@ -959,7 +985,7 @@ void* Cocoa_GL_CreateContext(void* pixFmt, void* shareCtx) { if (!pixFmt) return nil; - + NSOpenGLContext* newContext = [[NSOpenGLContext alloc] initWithFormat:(NSOpenGLPixelFormat*)pixFmt shareContext:(NSOpenGLContext*)shareCtx]; @@ -971,7 +997,7 @@ void* Cocoa_GL_CreateContext(void* pixFmt, void* shareCtx) // the cache size by issuing the following calls right after you create // the OpenGL context. The default cache size is 16." --ryan. // - + #ifndef GLI_ARRAY_FUNC_CACHE_MAX #define GLI_ARRAY_FUNC_CACHE_MAX 284 #endif @@ -986,7 +1012,7 @@ void* Cocoa_GL_CreateContext(void* pixFmt, void* shareCtx) CGLSetParameter(ctx, (CGLContextParameter)GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max); CGLSetParameter(ctx, (CGLContextParameter)GLI_ARRAY_FUNC_CACHE_MAX, &cache_max); } - + // End Wisdom from Apple Engineer section. --ryan. return newContext; } @@ -1007,7 +1033,7 @@ void* CWinSystemOSX::CreateWindowedContext(void* shareCtx) }; NSOpenGLPixelFormat* pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:wattrs]; - + newContext = [[NSOpenGLContext alloc] initWithFormat:(NSOpenGLPixelFormat*)pixFmt shareContext:(NSOpenGLContext*)shareCtx]; [pixFmt release]; @@ -1053,11 +1079,11 @@ void* CWinSystemOSX::CreateFullScreenContext(int screen_index, void* shareCtx) NSOpenGLPFAScreenMask, (NSOpenGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(displayID), (NSOpenGLPixelFormatAttribute)0 }; - + NSOpenGLPixelFormat* pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:fsattrs]; if (!pixFmt) return nil; - + NSOpenGLContext* newContext = [[NSOpenGLContext alloc] initWithFormat:(NSOpenGLPixelFormat*)pixFmt shareContext:(NSOpenGLContext*)shareCtx]; [pixFmt release]; @@ -1071,23 +1097,23 @@ void CWinSystemOSX::GetScreenResolution(int* w, int* h, double* fps, int screenI if (screenIdx >= GetNumScreens()) return; CGDirectDisplayID display_id = (CGDirectDisplayID)GetDisplayID(screenIdx); - + NSOpenGLContext* context = [NSOpenGLContext currentContext]; if (context) { NSView* view; - + view = [context view]; if (view) { NSWindow* window; window = [view window]; if (window) - display_id = GetDisplayIDFromScreen( [window screen] ); + display_id = GetDisplayIDFromScreen( [window screen] ); } } - CGDisplayModeRef mode = CGDisplayCopyDisplayMode(display_id); - *w = CGDisplayModeGetWidth(mode); + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(display_id); + *w = CGDisplayModeGetWidth(mode); *h = CGDisplayModeGetHeight(mode); *fps = CGDisplayModeGetRefreshRate(mode); CGDisplayModeRelease(mode); @@ -1100,7 +1126,7 @@ void CWinSystemOSX::GetScreenResolution(int* w, int* h, double* fps, int screenI void CWinSystemOSX::EnableVSync(bool enable) { - // OpenGL Flush synchronised with vertical retrace + // OpenGL Flush synchronised with vertical retrace GLint swapInterval = enable ? 1 : 0; [[NSOpenGLContext currentContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; } @@ -1112,7 +1138,7 @@ bool CWinSystemOSX::SwitchToVideoMode(int width, int height, double refreshrate, if( screenIdx >= GetNumScreens()) return false; - boolean_t match = false; + boolean_t match = false; CFDictionaryRef dispMode = NULL; // Figure out the screen size. (default to main screen) CGDirectDisplayID display_id = GetDisplayID(screenIdx); @@ -1142,7 +1168,7 @@ bool CWinSystemOSX::SwitchToVideoMode(int width, int height, double refreshrate, CGConfigureDisplayMode(cfg, display_id, dispMode); CGError err = CGCompleteDisplayConfiguration(cfg, kCGConfigureForAppOnly); CGDisplayRelease(display_id); - + Cocoa_CVDisplayLinkUpdate(); return (err == kCGErrorSuccess); @@ -1161,12 +1187,12 @@ void CWinSystemOSX::FillInVideoModes() Boolean televisionoutput; int w, h, bitsperpixel; double refreshrate; - RESOLUTION_INFO res; + RESOLUTION_INFO res; CFArrayRef displayModes = CGDisplayAvailableModes(GetDisplayID(disp)); NSString *dispName = screenNameForDisplay(GetDisplayID(disp)); CLog::Log(LOGNOTICE, "Display %i has name %s", disp, [dispName UTF8String]); - + if (NULL == displayModes) continue; @@ -1180,13 +1206,13 @@ void CWinSystemOSX::FillInVideoModes() safeForHardware = GetDictionaryBoolean(displayMode, kCGDisplayModeIsSafeForHardware); televisionoutput = GetDictionaryBoolean(displayMode, kCGDisplayModeIsTelevisionOutput); - if ((bitsperpixel == 32) && - (safeForHardware == YES) && - (stretched == NO) && + if ((bitsperpixel == 32) && + (safeForHardware == YES) && + (stretched == NO) && (interlaced == NO)) { w = GetDictionaryInt(displayMode, kCGDisplayWidth); - h = GetDictionaryInt(displayMode, kCGDisplayHeight); + h = GetDictionaryInt(displayMode, kCGDisplayHeight); refreshrate = GetDictionaryDouble(displayMode, kCGDisplayRefreshRate); if ((int)refreshrate == 0) // LCD display? { @@ -1194,7 +1220,7 @@ void CWinSystemOSX::FillInVideoModes() refreshrate = 60.0; } CLog::Log(LOGNOTICE, "Found possible resolution for display %d with %d x %d @ %f Hz\n", disp, w, h, refreshrate); - + UpdateDesktopResolution(res, disp, w, h, refreshrate); // overwrite the mode str because UpdateDesktopResolution adds a @@ -1222,10 +1248,142 @@ bool CWinSystemOSX::FlushBuffer(void) return true; } +bool CWinSystemOSX::IsObscured(void) +{ + // check once a second if we are obscured. + unsigned int now_time = XbmcThreads::SystemClockMillis(); + if (m_obscured_timecheck > now_time) + return m_obscured; + else + m_obscured_timecheck = now_time + 1000; + + NSOpenGLContext* cur_context = [NSOpenGLContext currentContext]; + NSView* view = [cur_context view]; + if (!view) + { + // sanity check, we should always have a view + m_obscured = true; + return m_obscured; + } + + NSWindow *window = [view window]; + if (!window) + { + // sanity check, we should always have a window + m_obscured = true; + return m_obscured; + } + + if ([window isVisible] == NO) + { + // not visable means the window is not showing. + // this should never really happen as we are always visable + // even when minimized in dock. + m_obscured = true; + return m_obscured; + } + + // check if we are minimized (to an icon in the Dock). + if ([window isMiniaturized] == YES) + { + m_obscured = true; + return m_obscured; + } + + // check if we are showing on the active workspace. + if ([window isOnActiveSpace] == NO) + { + m_obscured = true; + return m_obscured; + } + + // default to false before we start parsing though the windows. + // if we are are obscured by any windows, then set true. + m_obscured = false; + + CGWindowListOption opts; + opts = kCGWindowListOptionOnScreenAboveWindow | kCGWindowListExcludeDesktopElements; + CFArrayRef windowIDs =CGWindowListCreate(opts, (CGWindowID)[window windowNumber]); if (!windowIDs) + return m_obscured; + + CFArrayRef windowDescs = CGWindowListCreateDescriptionFromArray(windowIDs); + if (!windowDescs) + { + CFRelease(windowIDs); + return m_obscured; + } + + CGRect bounds = NSRectToCGRect([window frame]); + // kCGWindowBounds measures the origin as the top-left corner of the rectangle + // relative to the top-left corner of the screen. + // NSWindow’s frame property measures the origin as the bottom-left corner + // of the rectangle relative to the bottom-left corner of the screen. + // convert bounds from NSWindow to CGWindowBounds here. + bounds.origin.y = [[window screen] frame].size.height - bounds.origin.y - bounds.size.height; + + std::vector<CRect> partialOverlaps; + CRect ourBounds = CGRectToCRect(bounds); + + for (CFIndex idx=0; idx < CFArrayGetCount(windowDescs); idx++) + { + // walk the window list of windows that are above us and are not desktop elements + CFDictionaryRef windowDictionary = (CFDictionaryRef)CFArrayGetValueAtIndex(windowDescs, idx); + + // skip the Dock window, it actually covers the entire screen. + CFStringRef ownerName = (CFStringRef)CFDictionaryGetValue(windowDictionary, kCGWindowOwnerName); + if (CFStringCompare(ownerName, CFSTR("Dock"), 0) == kCFCompareEqualTo) + continue; + + // Shades is a tool for dimming the screen. It also claims to cover + // the whole XBMC window and therefore would make the framerate limiter + // kicking in. Unfortunatly even the alpha of this window is 1.0 so + // we have to check the ownerName. + if (CFStringCompare(ownerName, CFSTR("Shades"), 0) == kCFCompareEqualTo) + continue; + + CFDictionaryRef rectDictionary = (CFDictionaryRef)CFDictionaryGetValue(windowDictionary, kCGWindowBounds); + if (!rectDictionary) + continue; + + CGRect windowBounds; + if (CGRectMakeWithDictionaryRepresentation(rectDictionary, &windowBounds)) + { + if (CGRectContainsRect(windowBounds, bounds)) + { + // if the windowBounds completely encloses our bounds, we are obscured. + m_obscured = true; + break; + } + + // handle overlaping windows above us that combine + // to obscure by collecting any partial overlaps, + // then subtract them from our bounds and check + // for any remaining area. + CRect intersection = CGRectToCRect(windowBounds); + intersection.Intersect(ourBounds); + if (!intersection.IsEmpty()) + partialOverlaps.push_back(intersection); + } + } + + if (!m_obscured) + { + std::vector<CRect> rects = ourBounds.SubtractRects(partialOverlaps); + // they got us covered + if (rects.size() == 0) + m_obscured = true; + } + + CFRelease(windowDescs); + CFRelease(windowIDs); + + return m_obscured; +} + void CWinSystemOSX::NotifyAppFocusChange(bool bGaining) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - + if (m_bFullScreen && bGaining) { // find the window @@ -1233,7 +1391,7 @@ void CWinSystemOSX::NotifyAppFocusChange(bool bGaining) if (context) { NSView* view; - + view = [context view]; if (view) { @@ -1264,7 +1422,7 @@ void CWinSystemOSX::ShowOSMouse(bool show) bool CWinSystemOSX::Minimize() { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - + [[NSApplication sharedApplication] miniaturizeAll:nil]; [pool release]; @@ -1274,7 +1432,7 @@ bool CWinSystemOSX::Minimize() bool CWinSystemOSX::Restore() { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - + [[NSApplication sharedApplication] unhide:nil]; [pool release]; @@ -1284,9 +1442,9 @@ bool CWinSystemOSX::Restore() bool CWinSystemOSX::Hide() { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - + [[NSApplication sharedApplication] hide:nil]; - + [pool release]; return true; } @@ -1305,7 +1463,7 @@ void CWinSystemOSX::EnableSystemScreenSaver(bool bEnable) { CFStringRef reasonForActivity= CFSTR("XBMC requested disable system screen saver"); IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, - kIOPMAssertionLevelOn, reasonForActivity, &assertionID); + kIOPMAssertionLevelOn, reasonForActivity, &assertionID); } else if (assertionID != 0) { @@ -1326,6 +1484,11 @@ void CWinSystemOSX::ResetOSScreensaver() EnableSystemScreenSaver(!m_bFullScreen); } +bool CWinSystemOSX::EnableFrameLimiter() +{ + return IsObscured(); +} + void CWinSystemOSX::Register(IDispResource *resource) { CSingleLock lock(m_resourceSection); @@ -1354,7 +1517,7 @@ bool CWinSystemOSX::Show(bool raise) { [[NSApplication sharedApplication] unhideWithoutActivation]; } - + [pool release]; return true; } diff --git a/xbmc/windowing/windows/WinEventsWin32.cpp b/xbmc/windowing/windows/WinEventsWin32.cpp index ada0fcb535..05b9a7ef54 100644 --- a/xbmc/windowing/windows/WinEventsWin32.cpp +++ b/xbmc/windowing/windows/WinEventsWin32.cpp @@ -48,6 +48,8 @@ using namespace PERIPHERALS; +HWND g_hWnd = NULL; + #define XBMC_arraysize(array) (sizeof(array)/sizeof(array[0])) /* Masks for processing the windows KEYDOWN and KEYUP messages */ @@ -363,6 +365,7 @@ LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, L if (uMsg == WM_CREATE) { + g_hWnd = hWnd; SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)(((LPCREATESTRUCT)lParam)->lpCreateParams)); DIB_InitOSKeymap(); g_uQueryCancelAutoPlay = RegisterWindowMessage(TEXT("QueryCancelAutoPlay")); @@ -374,6 +377,9 @@ LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, L return 0; } + if (uMsg == WM_DESTROY) + g_hWnd = NULL; + m_pEventFunc = (PHANDLE_EVENT_FUNC)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (!m_pEventFunc) return DefWindowProc(hWnd, uMsg, wParam, lParam); @@ -440,6 +446,14 @@ LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, L CLog::Log(LOGDEBUG, __FUNCTION__": Focus switched to process %s", procfile.c_str()); } break; + case WM_SYSCOMMAND: + switch( wParam&0xFFF0 ) + { + case SC_MONITORPOWER: + case SC_SCREENSAVE: + return 0; + } + break; case WM_SYSKEYDOWN: switch (wParam) { @@ -630,9 +644,12 @@ LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, L return(0); case WM_MEDIA_CHANGE: { - // There may be multiple notifications for one event - // There are also a few events we're not interested in, but they cause no harm - // For example SD card reader insertion/removal + // This event detects media changes of usb, sd card and optical media. + // It only works if the explorer.exe process is started. Because this + // isn't the case for all setups we use WM_DEVICECHANGE for usb and + // optical media because this event is also triggered without the + // explorer process. Since WM_DEVICECHANGE doesn't detect sd card changes + // we still use this event only for sd. long lEvent; PIDLIST_ABSOLUTE *ppidl; HANDLE hLock = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &ppidl, &lEvent); @@ -647,25 +664,20 @@ LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, L { case SHCNE_DRIVEADD: case SHCNE_MEDIAINSERTED: - CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media has arrived.", drivePath); - if (GetDriveType(drivePath) == DRIVE_CDROM) - CJobManager::GetInstance().AddJob(new CDetectDisc(drivePath, true), NULL); - else + if (GetDriveType(drivePath) != DRIVE_CDROM) + { + CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media has arrived.", drivePath); CWin32StorageProvider::SetEvent(); + } break; case SHCNE_DRIVEREMOVED: case SHCNE_MEDIAREMOVED: - CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media was removed.", drivePath); - if (GetDriveType(drivePath) == DRIVE_CDROM) + if (GetDriveType(drivePath) != DRIVE_CDROM) { - CMediaSource share; - share.strPath = drivePath; - share.strName = share.strPath; - g_mediaManager.RemoveAutoSource(share); - } - else + CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media was removed.", drivePath); CWin32StorageProvider::SetEvent(); + } break; } SHChangeNotification_Unlock(hLock); @@ -698,6 +710,32 @@ LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, L g_peripherals.TriggerDeviceScan(PERIPHERAL_BUS_USB); g_Joystick.Reinitialize(); } + // check if an usb or optical media was inserted or removed + if (((_DEV_BROADCAST_HEADER*) lParam)->dbcd_devicetype == DBT_DEVTYP_VOLUME) + { + PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)((_DEV_BROADCAST_HEADER*) lParam); + // optical medium + if (lpdbv -> dbcv_flags & DBTF_MEDIA) + { + CStdString strdrive; + strdrive.Format("%c:\\", CWIN32Util::FirstDriveFromMask(lpdbv ->dbcv_unitmask)); + if(wParam == DBT_DEVICEARRIVAL) + { + CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media has arrived.", strdrive.c_str()); + CJobManager::GetInstance().AddJob(new CDetectDisc(strdrive, true), NULL); + } + else + { + CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media was removed.", strdrive.c_str()); + CMediaSource share; + share.strPath = strdrive; + share.strName = share.strPath; + g_mediaManager.RemoveAutoSource(share); + } + } + else + CWin32StorageProvider::SetEvent(); + } } break; } @@ -829,7 +867,8 @@ void CWinEventsWin32::OnGesture(HWND hWnd, LPARAM lParam) // You have encountered an unknown gesture break; } - g_Windowing.PtrCloseGestureInfoHandle((HGESTUREINFO)lParam); + if(g_Windowing.PtrCloseGestureInfoHandle) + g_Windowing.PtrCloseGestureInfoHandle((HGESTUREINFO)lParam); } #endif diff --git a/xbmc/windowing/windows/WinSystemWin32.cpp b/xbmc/windowing/windows/WinSystemWin32.cpp index cba2f0a0e5..27ad90cab3 100644 --- a/xbmc/windowing/windows/WinSystemWin32.cpp +++ b/xbmc/windowing/windows/WinSystemWin32.cpp @@ -30,8 +30,6 @@ #ifdef _WIN32 #include <tpcshrd.h> -HWND g_hWnd = NULL; - CWinSystemWin32::CWinSystemWin32() : CWinSystemBase() { @@ -71,37 +69,6 @@ bool CWinSystemWin32::DestroyWindowSystem() return true; } -bool CWinSystemWin32::IsSystemScreenSaverEnabled() -{ - // Check if system screen saver is enabled - // We are checking registry due to bug with SPI_GETSCREENSAVEACTIVE - HKEY hKeyScreenSaver = NULL; - long lReturn = NULL; - long lScreenSaver = NULL; - DWORD dwData = NULL; - bool result = false; - - lReturn = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"),0,KEY_QUERY_VALUE,&hKeyScreenSaver); - if(lReturn == ERROR_SUCCESS) - { - lScreenSaver = RegQueryValueEx(hKeyScreenSaver,TEXT("SCRNSAVE.EXE"),NULL,NULL,NULL,&dwData); - - // ScreenSaver is active - if(lScreenSaver == ERROR_SUCCESS) - result = true; - } - RegCloseKey(hKeyScreenSaver); - - return result; -} - -void CWinSystemWin32::EnableSystemScreenSaver(bool bEnable) -{ - SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,bEnable,0,0); - if(!bEnable) - SetThreadExecutionState(ES_DISPLAY_REQUIRED|ES_CONTINUOUS); -} - bool CWinSystemWin32::CreateNewWindow(const CStdString& name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction) { m_hInstance = ( HINSTANCE )GetModuleHandle( NULL ); @@ -146,12 +113,15 @@ bool CWinSystemWin32::CreateNewWindow(const CStdString& name, bool fullScreen, R SetProp(hWnd, MICROSOFT_TABLETPENSERVICE_PROPERTY, reinterpret_cast<HANDLE>(dwHwndTabletProperty)); // setup our touch pointers - PtrGetGestureInfo = (pGetGestureInfo) GetProcAddress( GetModuleHandle( TEXT( "user32" ) ), "GetGestureInfo" ); - PtrSetGestureConfig = (pSetGestureConfig) GetProcAddress( GetModuleHandle( TEXT( "user32" ) ), "SetGestureConfig" ); - PtrCloseGestureInfoHandle = (pCloseGestureInfoHandle) GetProcAddress( GetModuleHandle( TEXT( "user32" ) ), "CloseGestureInfoHandle" ); + HMODULE hUser32 = GetModuleHandleA( "user32" ); + if (hUser32) + { + PtrGetGestureInfo = (pGetGestureInfo) GetProcAddress( hUser32, "GetGestureInfo" ); + PtrSetGestureConfig = (pSetGestureConfig) GetProcAddress( hUser32, "SetGestureConfig" ); + PtrCloseGestureInfoHandle = (pCloseGestureInfoHandle) GetProcAddress( hUser32, "CloseGestureInfoHandle" ); + } m_hWnd = hWnd; - g_hWnd = hWnd; m_hDC = GetDC(m_hWnd); m_bWindowCreated = true; @@ -303,6 +273,7 @@ bool CWinSystemWin32::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool { // save position of windowed mode WINDOWINFO wi; + wi.cbSize = sizeof(WINDOWINFO); GetWindowInfo(m_hWnd, &wi); m_nLeft = wi.rcClient.left; m_nTop = wi.rcClient.top; @@ -419,6 +390,7 @@ bool CWinSystemWin32::ResizeInternal(bool forceRefresh) } WINDOWINFO wi; + wi.cbSize = sizeof (WINDOWINFO); GetWindowInfo(m_hWnd, &wi); RECT wr = wi.rcWindow; @@ -701,8 +673,8 @@ bool CWinSystemWin32::Show(bool raise) UpdateWindow(m_hWnd); if (raise) { - SetForegroundWindow(g_hWnd); - SetFocus(g_hWnd); + SetForegroundWindow(m_hWnd); + SetFocus(m_hWnd); } return true; } diff --git a/xbmc/windowing/windows/WinSystemWin32.h b/xbmc/windowing/windows/WinSystemWin32.h index 0df7a10e29..8a2a837e08 100644 --- a/xbmc/windowing/windows/WinSystemWin32.h +++ b/xbmc/windowing/windows/WinSystemWin32.h @@ -146,10 +146,6 @@ public: virtual bool Hide(); virtual bool Show(bool raise = true); - // OS System screensaver - virtual void EnableSystemScreenSaver(bool bEnable); - virtual bool IsSystemScreenSaverEnabled(); - // CWinSystemWin32 HWND GetHwnd() { return m_hWnd; } bool IsAlteringWindow() { return m_IsAlteringWindow; } diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp index 02a2c361e2..59d592797b 100644 --- a/xbmc/windows/GUIMediaWindow.cpp +++ b/xbmc/windows/GUIMediaWindow.cpp @@ -30,6 +30,7 @@ #include "filesystem/MultiPathDirectory.h" #include "GUIPassword.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "network/Network.h" #include "utils/RegExp.h" #include "PartyModeManager.h" @@ -40,6 +41,7 @@ #include "dialogs/GUIDialogProgress.h" #include "settings/AdvancedSettings.h" #include "settings/GUISettings.h" +#include "URL.h" #include "dialogs/GUIDialogSmartPlaylistEditor.h" #include "addons/GUIDialogAddonSettings.h" @@ -57,11 +59,14 @@ #include "utils/log.h" #include "utils/FileUtils.h" #include "guilib/GUIEditControl.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #ifdef HAS_PYTHON #include "interfaces/python/XBPython.h" #endif #include "interfaces/Builtins.h" +#if defined(TARGET_ANDROID) +#include "xbmc/android/activity/XBMCApp.h" +#endif #define CONTROL_BTNVIEWASICONS 2 #define CONTROL_BTNSORTBY 3 @@ -277,7 +282,7 @@ bool CGUIMediaWindow::OnMessage(CGUIMessage& message) if (GetProperty("filter").empty()) { CStdString filter = GetProperty("filter").asString(); - CGUIDialogKeyboard::ShowAndGetFilter(filter, false); + CGUIKeyboardFactory::ShowAndGetFilter(filter, false); SetProperty("filter", filter); } else @@ -851,6 +856,7 @@ void CGUIMediaWindow::OnPrepareFileItems(CFileItemList &items) // to modify the fileitems. Eg. to modify the item label void CGUIMediaWindow::OnFinalizeFileItems(CFileItemList &items) { + m_unfilteredItems->SetPath(items.GetPath()); // use the original path - it'll likely be relied on for other things later. m_unfilteredItems->Append(items); CStdString filter(GetProperty("filter").asString()); @@ -945,6 +951,14 @@ bool CGUIMediaWindow::OnClick(int iItem) { return XFILE::CPluginDirectory::RunScriptWithParams(pItem->GetPath()); } +#if defined(TARGET_ANDROID) + else if (pItem->IsAndroidApp()) + { + CStdString appName = URIUtils::GetFileName(pItem->GetPath()); + CLog::Log(LOGDEBUG, "CGUIMediaWindow::OnClick Trying to run: %s",appName.c_str()); + return CXBMCApp::StartActivity(appName); + } +#endif else { m_iSelectedItem = m_viewControl.GetSelectedItem(); @@ -1466,7 +1480,7 @@ bool CGUIMediaWindow::OnContextButton(int itemNumber, CONTEXT_BUTTON button) { CStdString action; action.Format("contextmenuaction(%i)", button - CONTEXT_BUTTON_USER1); - g_application.getApplicationMessenger().ExecBuiltIn(m_vecItems->Get(itemNumber)->GetProperty(action).asString()); + CApplicationMessenger::Get().ExecBuiltIn(m_vecItems->Get(itemNumber)->GetProperty(action).asString()); return true; } default: @@ -1521,7 +1535,7 @@ void CGUIMediaWindow::OnFilterItems(const CStdString &filter) m_viewControl.Clear(); - CFileItemList items; + CFileItemList items(m_unfilteredItems->GetPath()); // use the original path - it'll likely be relied on for other things later. items.Append(*m_unfilteredItems); if (GetFilteredItems(filter, items)) { @@ -1544,7 +1558,7 @@ bool CGUIMediaWindow::GetFilteredItems(const CStdString &filter, CFileItemList & if (trimmedFilter.IsEmpty()) return true; - CFileItemList filteredItems; + CFileItemList filteredItems(items.GetPath()); // use the original path - it'll likely be relied on for other things later. bool numericMatch = StringUtils::IsNaturalNumber(trimmedFilter); for (int i = 0; i < items.Size(); i++) { diff --git a/xbmc/windows/GUIWindowDebugInfo.cpp b/xbmc/windows/GUIWindowDebugInfo.cpp index 916b032c8e..91772b377e 100644 --- a/xbmc/windows/GUIWindowDebugInfo.cpp +++ b/xbmc/windows/GUIWindowDebugInfo.cpp @@ -35,6 +35,8 @@ #include "GUIInfoManager.h" #include "utils/Variant.h" +#include <climits> + CGUIWindowDebugInfo::CGUIWindowDebugInfo(void) : CGUIDialog(98, "") { diff --git a/xbmc/windows/GUIWindowFileManager.cpp b/xbmc/windows/GUIWindowFileManager.cpp index 9596cec898..abdcb86cce 100644 --- a/xbmc/windows/GUIWindowFileManager.cpp +++ b/xbmc/windows/GUIWindowFileManager.cpp @@ -39,7 +39,7 @@ #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogYesNo.h" -#include "dialogs/GUIDialogKeyboard.h" +#include "guilib/GUIKeyboardFactory.h" #include "dialogs/GUIDialogProgress.h" #include "Favourites.h" #include "playlists/PlayList.h" @@ -58,6 +58,7 @@ #include "utils/FileUtils.h" #include "utils/URIUtils.h" #include "Autorun.h" +#include "URL.h" using namespace std; using namespace XFILE; @@ -769,7 +770,7 @@ void CGUIWindowFileManager::OnSelectAll(int iList) void CGUIWindowFileManager::OnNewFolder(int iList) { CStdString strNewFolder = ""; - if (CGUIDialogKeyboard::ShowAndGetInput(strNewFolder, g_localizeStrings.Get(16014), false)) + if (CGUIKeyboardFactory::ShowAndGetInput(strNewFolder, g_localizeStrings.Get(16014), false)) { CStdString strNewPath = m_Directory[iList]->GetPath(); URIUtils::AddSlashAtEnd(strNewPath); diff --git a/xbmc/windows/GUIWindowLoginScreen.cpp b/xbmc/windows/GUIWindowLoginScreen.cpp index 119d9c7d5c..9752c88d5f 100644 --- a/xbmc/windows/GUIWindowLoginScreen.cpp +++ b/xbmc/windows/GUIWindowLoginScreen.cpp @@ -21,6 +21,7 @@ #include "system.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "GUIWindowLoginScreen.h" #include "settings/GUIWindowSettingsProfile.h" #include "dialogs/GUIDialogContextMenu.h" @@ -228,7 +229,7 @@ bool CGUIWindowLoginScreen::OnPopupMenu(int iItem) if (g_passwordManager.CheckLock(g_settings.GetMasterProfile().getLockMode(),g_settings.GetMasterProfile().getLockCode(),20075)) g_passwordManager.iMasterLockRetriesLeft = g_guiSettings.GetInt("masterlock.maxretries"); else // be inconvenient - g_application.getApplicationMessenger().Shutdown(); + CApplicationMessenger::Get().Shutdown(); return true; } diff --git a/xbmc/windows/GUIWindowSystemInfo.cpp b/xbmc/windows/GUIWindowSystemInfo.cpp index dcd1feff4d..0e6e6f4226 100644 --- a/xbmc/windows/GUIWindowSystemInfo.cpp +++ b/xbmc/windows/GUIWindowSystemInfo.cpp @@ -56,7 +56,7 @@ bool CGUIWindowSystemInfo::OnMessage(CGUIMessage& message) CGUIWindow::OnMessage(message); ResetLabels(); SET_CONTROL_LABEL(52, "XBMC " + g_infoManager.GetLabel(SYSTEM_BUILD_VERSION) + - " (Compiled : " + g_infoManager.GetLabel(SYSTEM_BUILD_DATE)+")"); + " (Compiled: " + g_infoManager.GetLabel(SYSTEM_BUILD_DATE)+")"); return true; } break; diff --git a/xbmc/xbmc.cpp b/xbmc/xbmc.cpp index 9632f6aad3..75c6677b13 100644 --- a/xbmc/xbmc.cpp +++ b/xbmc/xbmc.cpp @@ -26,7 +26,16 @@ extern "C" int XBMC_Run(bool renderGUI) int status = -1; if (!g_advancedSettings.Initialized()) + { +#ifdef _DEBUG + g_advancedSettings.m_logLevel = LOG_LEVEL_DEBUG; + g_advancedSettings.m_logLevelHint = LOG_LEVEL_DEBUG; +#else + g_advancedSettings.m_logLevel = LOG_LEVEL_NORMAL; + g_advancedSettings.m_logLevelHint = LOG_LEVEL_NORMAL; +#endif g_advancedSettings.Initialize(); + } if (!g_application.Create()) { |