Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: aballier/xbmc
...
head fork: aballier/xbmc
  • 15 commits
  • 30 files changed
  • 0 commit comments
  • 11 contributors
Commits on Apr 03, 2012
Voyager-xbmc allow resume on selected part of stack & stacking issues fix
stacking dialog in GUIWindowVideoBase - code generalization in CApp::PlayStack
clean up GetResumeItemString to use offset value from GetResumeItemOffset (for iso stacks)
0107c01
Commits on Apr 05, 2012
@xbmcfanboy xbmcfanboy [cosmetic] ': %s' instead of ':%s' bf7cf87
@elupus elupus Merge pull request #851 from aballier/master
Bring av_read_frame_flush in line with ffmpeg git.
b58bd19
@Memphiz Memphiz [fix] - deadloop in libavfilter.h 6ab7a79
@Memphiz Memphiz [nfs] - fix special case where "/" root is exported from server. In t…
…hat case no exports where accessable. This won't enable access to the exported root dir "/". This is was never planned and is not supported [tm]
fc6564d
Commits on Apr 06, 2012
Jonathan Marshall GetCast query was screwed up 04ebeeb
@CrystalP CrystalP Merge pull request #847 from xbmcfanboy/formatting
[cosmetic] ': %s' instead of ':%s'
79b700b
@xbmcfanboy xbmcfanboy Fix for ticket #12724: External cuesheet issue e9c288b
@jmarshallnz jmarshallnz Merge pull request #855 from xbmcfanboy/ticket-12724
Fix for ticket #12724: External cuesheet issue
a0cca30
Jonathan Marshall don't read from a m_pDS field after close fc06513
@amet amet Callback function for xbmc module (xbmc.Monitor)
monitors for:
- onSettingsChanged
- onScreensaverDeactivated
- onScreensaverActivated
- onDatabaseUpdated, will return the database that has been updated (video/music)
0ef8e70
@arnova arnova Merge pull request #226 from Voyager-xbmc/trac_11673
Stacked ISO (boxset) movies - fix inconsistency and resume issues
4ab0f1b
@amet amet Merge pull request #856 from amet/xbmc_monitor
Callback function for xbmc module (xbmc.Monitor)
dd793a9
@amet amet send "OnSettingsChanged" from CAddon::SaveSettings, it works when cha…
…nging settings from python as well. thx pieh
180d20b
@elupus elupus fixed: still frames at the start of a VTS in dvd could end up not sho…
…wing

This occured due to a change in behavior in updated ffmpeg. Old code would
return EOF once after a VTS change to trigger demuxer flush, however
updated ffmpeg will read multiple times causing demuxer reset actions
to get executed after actual data having been processed by demuxer.
4979418
Showing with 840 additions and 226 deletions.
  1. +12 −0 XBMC-ATV2.xcodeproj/project.pbxproj
  2. +12 −0 XBMC-IOS.xcodeproj/project.pbxproj
  3. +16 −0 XBMC.xcodeproj/project.pbxproj
  4. +1 −1  lib/DllAvFilter.h
  5. +8 −0 project/VS2010Express/XBMC.vcxproj
  6. +12 −0 project/VS2010Express/XBMC.vcxproj.filters
  7. +104 −69 xbmc/Application.cpp
  8. +12 −4 xbmc/FileItem.cpp
  9. +4 −2 xbmc/GUIInfoManager.cpp
  10. +1 −1  xbmc/TextureDatabase.cpp
  11. +2 −0  xbmc/addons/Addon.cpp
  12. +2 −0  xbmc/addons/GUIDialogAddonSettings.cpp
  13. +5 −2 xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp
  14. +7 −1 xbmc/filesystem/NFSFile.cpp
  15. +104 −0 xbmc/interfaces/python/XBPython.cpp
  16. +14 −1 xbmc/interfaces/python/XBPython.h
  17. +2 −0  xbmc/interfaces/python/xbmcmodule/Makefile.in
  18. +131 −0 xbmc/interfaces/python/xbmcmodule/PythonMonitor.cpp
  19. +51 −0 xbmc/interfaces/python/xbmcmodule/PythonMonitor.h
  20. +150 −0 xbmc/interfaces/python/xbmcmodule/monitor.cpp
  21. +43 −0 xbmc/interfaces/python/xbmcmodule/monitor.h
  22. +20 −1 xbmc/interfaces/python/xbmcmodule/pyutil.cpp
  23. +2 −0  xbmc/interfaces/python/xbmcmodule/pyutil.h
  24. +6 −1 xbmc/interfaces/python/xbmcmodule/xbmcmodule.cpp
  25. +1 −1  xbmc/playlists/PlayList.cpp
  26. +0 −1  xbmc/settings/GUISettings.cpp
  27. +2 −1  xbmc/settings/GUISettings.h
  28. +2 −2 xbmc/video/VideoDatabase.cpp
  29. +112 −137 xbmc/video/windows/GUIWindowVideoBase.cpp
  30. +2 −1  xbmc/video/windows/GUIWindowVideoBase.h
View
12 XBMC-ATV2.xcodeproj/project.pbxproj
@@ -29,6 +29,8 @@
7CCFD9AA1514952700211D82 /* PCMCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CCFD9A81514952700211D82 /* PCMCodec.cpp */; };
7CEE2E6D13D6B7A8000ABF2A /* TimeSmoother.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CEE2E6B13D6B7A8000ABF2A /* TimeSmoother.cpp */; };
C807119F135DB842002F601B /* InputOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C807119D135DB842002F601B /* InputOperations.cpp */; };
+ C8936060152C86EC00812418 /* PythonMonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C893605E152C86EC00812418 /* PythonMonitor.cpp */; };
+ C8936063152C86F500812418 /* monitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C8936061152C86F500812418 /* monitor.cpp */; };
C8EC5D51136954E400CCC10D /* XBMC_keytable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C8EC5D4F136954E400CCC10D /* XBMC_keytable.cpp */; };
DF0DF16D13A3AF82008ED511 /* NFSDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0DF16A13A3AF82008ED511 /* NFSDirectory.cpp */; };
DF34890913FD96390026A711 /* GUIAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF34890713FD96390026A711 /* GUIAction.cpp */; };
@@ -1013,6 +1015,10 @@
A192FD47135E46C800D92E9B /* IOSAudioRingBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IOSAudioRingBuffer.h; path = AudioRenderers/IOSAudioRingBuffer.h; sourceTree = "<group>"; };
C807119D135DB842002F601B /* InputOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InputOperations.cpp; sourceTree = "<group>"; };
C807119E135DB842002F601B /* InputOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InputOperations.h; sourceTree = "<group>"; };
+ C893605E152C86EC00812418 /* PythonMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PythonMonitor.cpp; sourceTree = "<group>"; };
+ C893605F152C86EC00812418 /* PythonMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PythonMonitor.h; sourceTree = "<group>"; };
+ C8936061152C86F500812418 /* monitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = monitor.cpp; sourceTree = "<group>"; };
+ C8936062152C86F500812418 /* monitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = monitor.h; sourceTree = "<group>"; };
C8EC5D4F136954E400CCC10D /* XBMC_keytable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XBMC_keytable.cpp; sourceTree = "<group>"; };
C8EC5D50136954E400CCC10D /* XBMC_keytable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBMC_keytable.h; sourceTree = "<group>"; };
DF0DF16A13A3AF82008ED511 /* NFSDirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NFSDirectory.cpp; sourceTree = "<group>"; };
@@ -4707,6 +4713,8 @@
F56C758A131EC152000AD0F6 /* keyboard.h */,
F56C758B131EC152000AD0F6 /* listitem.cpp */,
F56C758C131EC152000AD0F6 /* listitem.h */,
+ C8936061152C86F500812418 /* monitor.cpp */,
+ C8936062152C86F500812418 /* monitor.h */,
F56C758D131EC152000AD0F6 /* player.cpp */,
F56C758E131EC152000AD0F6 /* player.h */,
F56C758F131EC152000AD0F6 /* pyplaylist.cpp */,
@@ -4715,6 +4723,8 @@
F5E113AE1435882900175026 /* pyrendercapture.h */,
F56C7568131EC152000AD0F6 /* PythonAddon.cpp */,
F56C7569131EC152000AD0F6 /* PythonAddon.h */,
+ C893605E152C86EC00812418 /* PythonMonitor.cpp */,
+ C893605F152C86EC00812418 /* PythonMonitor.h */,
F56C7591131EC152000AD0F6 /* PythonPlayer.cpp */,
F56C7592131EC152000AD0F6 /* PythonPlayer.h */,
F56C7593131EC152000AD0F6 /* pyutil.cpp */,
@@ -7066,6 +7076,8 @@
DFDB004B1516408F005079A4 /* FileCache.cpp in Sources */,
DFDB004C1516408F005079A4 /* MemBufferCache.cpp in Sources */,
7C1A89BB152671FB00C63311 /* TextureCacheJob.cpp in Sources */,
+ C8936060152C86EC00812418 /* PythonMonitor.cpp in Sources */,
+ C8936063152C86F500812418 /* monitor.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
12 XBMC-IOS.xcodeproj/project.pbxproj
@@ -30,6 +30,8 @@
7CCFD9991514950700211D82 /* PCMCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CCFD9971514950700211D82 /* PCMCodec.cpp */; };
7CEE2E7F13D6B7D4000ABF2A /* TimeSmoother.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CEE2E7D13D6B7D4000ABF2A /* TimeSmoother.cpp */; };
C80711AD135DB85F002F601B /* InputOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C80711AB135DB85F002F601B /* InputOperations.cpp */; };
+ 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 */; };
DF0DF18013A3AF9F008ED511 /* NFSDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0DF17D13A3AF9F008ED511 /* NFSDirectory.cpp */; };
DF3488F813FD961A0026A711 /* GUIAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF3488F613FD961A0026A711 /* GUIAction.cpp */; };
@@ -1012,6 +1014,10 @@
8D576316048677EA00EA77CD /* XBMC.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XBMC.app; sourceTree = BUILT_PRODUCTS_DIR; };
C80711AB135DB85F002F601B /* InputOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InputOperations.cpp; sourceTree = "<group>"; };
C80711AC135DB85F002F601B /* InputOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InputOperations.h; sourceTree = "<group>"; };
+ C893606D152C870600812418 /* monitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = monitor.cpp; sourceTree = "<group>"; };
+ C893606E152C870600812418 /* monitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = monitor.h; sourceTree = "<group>"; };
+ C8936070152C871400812418 /* PythonMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PythonMonitor.cpp; sourceTree = "<group>"; };
+ 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>"; };
DF0DF17D13A3AF9F008ED511 /* NFSDirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NFSDirectory.cpp; sourceTree = "<group>"; };
@@ -5063,6 +5069,8 @@
F56C856D131F42EA000AD0F6 /* keyboard.h */,
F56C856E131F42EA000AD0F6 /* listitem.cpp */,
F56C856F131F42EA000AD0F6 /* listitem.h */,
+ C893606D152C870600812418 /* monitor.cpp */,
+ C893606E152C870600812418 /* monitor.h */,
F56C8570131F42EA000AD0F6 /* player.cpp */,
F56C8571131F42EA000AD0F6 /* player.h */,
F56C8572131F42EA000AD0F6 /* pyplaylist.cpp */,
@@ -5071,6 +5079,8 @@
F5E1127C14356C4D00175026 /* pyrendercapture.h */,
F56C854B131F42E9000AD0F6 /* PythonAddon.cpp */,
F56C854C131F42E9000AD0F6 /* PythonAddon.h */,
+ C8936070152C871400812418 /* PythonMonitor.cpp */,
+ C8936071152C871400812418 /* PythonMonitor.h */,
F56C8574131F42EA000AD0F6 /* PythonPlayer.cpp */,
F56C8575131F42EA000AD0F6 /* PythonPlayer.h */,
F56C8576131F42EA000AD0F6 /* pyutil.cpp */,
@@ -7077,6 +7087,8 @@
DFDB00261516403A005079A4 /* FileCache.cpp in Sources */,
DFDB00271516403A005079A4 /* MemBufferCache.cpp in Sources */,
7C1A89CE1526722200C63311 /* TextureCacheJob.cpp in Sources */,
+ C893606F152C870600812418 /* monitor.cpp in Sources */,
+ C8936072152C871400812418 /* PythonMonitor.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
16 XBMC.xcodeproj/project.pbxproj
@@ -616,6 +616,10 @@
C84BF7341349BB74006D6FC9 /* JSONServiceDescription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C84BF7321349BB74006D6FC9 /* JSONServiceDescription.cpp */; };
C85EB75C1174614E0008E5A5 /* Repository.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C85EB75A1174614E0008E5A5 /* Repository.cpp */; };
C85EB75D1174614E0008E5A5 /* Repository.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C85EB75A1174614E0008E5A5 /* Repository.cpp */; };
+ C8936052152C86CF00812418 /* monitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C8936050152C86CF00812418 /* monitor.cpp */; };
+ C8936053152C86CF00812418 /* monitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C8936050152C86CF00812418 /* monitor.cpp */; };
+ C8936056152C86D800812418 /* PythonMonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C8936054152C86D800812418 /* PythonMonitor.cpp */; };
+ C8936057152C86D800812418 /* PythonMonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C8936054152C86D800812418 /* PythonMonitor.cpp */; };
C8D0B2AF1265A9A800F0C0AC /* SystemGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C8D0B2AE1265A9A800F0C0AC /* SystemGlobals.cpp */; };
C8D0B2B01265A9A800F0C0AC /* SystemGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C8D0B2AE1265A9A800F0C0AC /* SystemGlobals.cpp */; };
C8EC5D0E1369519D00CCC10D /* XBMC_keytable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C8EC5D0C1369519D00CCC10D /* XBMC_keytable.cpp */; };
@@ -2627,6 +2631,10 @@
C84BF7331349BB74006D6FC9 /* JSONServiceDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONServiceDescription.h; sourceTree = "<group>"; };
C85EB75A1174614E0008E5A5 /* Repository.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Repository.cpp; sourceTree = "<group>"; };
C85EB75B1174614E0008E5A5 /* Repository.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Repository.h; sourceTree = "<group>"; };
+ C8936050152C86CF00812418 /* monitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = monitor.cpp; sourceTree = "<group>"; };
+ C8936051152C86CF00812418 /* monitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = monitor.h; sourceTree = "<group>"; };
+ C8936054152C86D800812418 /* PythonMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PythonMonitor.cpp; sourceTree = "<group>"; };
+ C8936055152C86D800812418 /* PythonMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PythonMonitor.h; sourceTree = "<group>"; };
C8D0B2AE1265A9A800F0C0AC /* SystemGlobals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SystemGlobals.cpp; sourceTree = "<group>"; };
C8EC5D0C1369519D00CCC10D /* XBMC_keytable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XBMC_keytable.cpp; sourceTree = "<group>"; };
C8EC5D0D1369519D00CCC10D /* XBMC_keytable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBMC_keytable.h; sourceTree = "<group>"; };
@@ -6164,6 +6172,8 @@
E38E19F80D25F9FB00618676 /* keyboard.h */,
E38E25920D263CE000618676 /* listitem.cpp */,
E38E19FA0D25F9FB00618676 /* listitem.h */,
+ C8936050152C86CF00812418 /* monitor.cpp */,
+ C8936051152C86CF00812418 /* monitor.h */,
E38E25930D263CE000618676 /* player.cpp */,
E38E19FE0D25F9FB00618676 /* player.h */,
E38E25940D263CE000618676 /* pyplaylist.cpp */,
@@ -6172,6 +6182,8 @@
F5E1125D14356B2400175026 /* pyrendercapture.h */,
7CD2CCFE11B38B000009EFC1 /* PythonAddon.cpp */,
7CD2CCFF11B38B000009EFC1 /* PythonAddon.h */,
+ C8936054152C86D800812418 /* PythonMonitor.cpp */,
+ C8936055152C86D800812418 /* PythonMonitor.h */,
E38E25950D263CE000618676 /* PythonPlayer.cpp */,
E38E1A020D25F9FB00618676 /* PythonPlayer.h */,
E38E25960D263CE000618676 /* pyutil.cpp */,
@@ -8195,6 +8207,8 @@
DF93D7F21444B54A007C6459 /* HDHomeRunFile.cpp in Sources */,
DF93D7F61444B568007C6459 /* HDHomeRunDirectory.cpp in Sources */,
7C1A85661520522500C63311 /* TextureCacheJob.cpp in Sources */,
+ C8936052152C86CF00812418 /* monitor.cpp in Sources */,
+ C8936056152C86D800812418 /* PythonMonitor.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -9133,6 +9147,8 @@
DF93D7F31444B54A007C6459 /* HDHomeRunFile.cpp in Sources */,
DF93D7F71444B568007C6459 /* HDHomeRunDirectory.cpp in Sources */,
7C1A85651520522500C63311 /* TextureCacheJob.cpp in Sources */,
+ C8936053152C86CF00812418 /* monitor.cpp in Sources */,
+ C8936057152C86D800812418 /* PythonMonitor.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
2  lib/DllAvFilter.h
@@ -140,7 +140,7 @@ class DllAvFilter : public DllDynamic, DllAvFilterInterface
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); }
virtual AVBufferSinkParams *av_buffersink_params_alloc() { return ::av_buffersink_params_alloc(); }
- virtual int av_buffersink_poll_frame(AVFilterContext *ctx) { return av_buffersink_poll_frame(ctx); }
+ virtual int av_buffersink_poll_frame(AVFilterContext *ctx) { return ::av_buffersink_poll_frame(ctx); }
// DLL faking.
virtual bool ResolveExports() { return true; }
virtual bool Load() {
View
8 project/VS2010Express/XBMC.vcxproj
@@ -650,6 +650,9 @@
<ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\listitem.cpp">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">..\..\project\BuildDependencies\include\python;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\monitor.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">..\..\project\BuildDependencies\include\python;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
<ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\player.cpp">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">..\..\project\BuildDependencies\include\python;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
@@ -663,6 +666,9 @@
<ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonPlayer.cpp">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">..\..\project\BuildDependencies\include\python;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonMonitor.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">..\..\project\BuildDependencies\include\python;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
<ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\pyutil.cpp">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">..\..\project\BuildDependencies\include\python;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
@@ -1604,11 +1610,13 @@
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\infotagvideo.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\keyboard.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\listitem.h" />
+ <ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\monitor.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\player.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\pyjsonrpc.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\pyplaylist.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\pyrendercapture.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonAddon.h" />
+ <ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonMonitor.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonPlayer.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\pyutil.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\window.h" />
View
12 project/VS2010Express/XBMC.vcxproj.filters
@@ -1925,6 +1925,9 @@
<ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\listitem.cpp">
<Filter>interfaces\python\xbmcmodule</Filter>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\monitor.cpp">
+ <Filter>interfaces\python\xbmcmodule</Filter>
+ </ClCompile>
<ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\player.cpp">
<Filter>interfaces\python\xbmcmodule</Filter>
</ClCompile>
@@ -1934,6 +1937,9 @@
<ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonAddon.cpp">
<Filter>interfaces\python\xbmcmodule</Filter>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonMonitor.cpp">
+ <Filter>interfaces\python\xbmcmodule</Filter>
+ </ClCompile>
<ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonPlayer.cpp">
<Filter>interfaces\python\xbmcmodule</Filter>
</ClCompile>
@@ -4534,6 +4540,9 @@
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\listitem.h">
<Filter>interfaces\python\xbmcmodule</Filter>
</ClInclude>
+ <ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\monitor.h">
+ <Filter>interfaces\python\xbmcmodule</Filter>
+ </ClInclude>
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\player.h">
<Filter>interfaces\python\xbmcmodule</Filter>
</ClInclude>
@@ -4546,6 +4555,9 @@
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonAddon.h">
<Filter>interfaces\python\xbmcmodule</Filter>
</ClInclude>
+ <ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonMonitor.h">
+ <Filter>interfaces\python\xbmcmodule</Filter>
+ </ClInclude>
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonPlayer.h">
<Filter>interfaces\python\xbmcmodule</Filter>
</ClInclude>
View
173 xbmc/Application.cpp
@@ -709,8 +709,8 @@ bool CApplication::Create()
CLog::Log(LOGINFO, "creating subdirectories");
CLog::Log(LOGINFO, "userdata folder: %s", g_settings.GetProfileUserDataFolder().c_str());
- CLog::Log(LOGINFO, "recording folder:%s", g_guiSettings.GetString("audiocds.recordingpath",false).c_str());
- CLog::Log(LOGINFO, "screenshots folder:%s", g_guiSettings.GetString("debug.screenshotpath",false).c_str());
+ CLog::Log(LOGINFO, "recording folder: %s", g_guiSettings.GetString("audiocds.recordingpath",false).c_str());
+ CLog::Log(LOGINFO, "screenshots folder: %s", g_guiSettings.GetString("debug.screenshotpath",false).c_str());
CDirectory::Create(g_settings.GetUserDataFolder());
CDirectory::Create(g_settings.GetProfileUserDataFolder());
g_settings.CreateProfileFolders();
@@ -733,7 +733,7 @@ bool CApplication::Create()
CStdString strLanguagePath;
strLanguagePath.Format("special://xbmc/language/%s/strings.xml", strLanguage.c_str());
- CLog::Log(LOGINFO, "load language file:%s", strLanguagePath.c_str());
+ CLog::Log(LOGINFO, "load language file: %s", strLanguagePath.c_str());
if (!g_localizeStrings.Load(strLanguagePath))
FatalErrorHandler(false, false, true);
@@ -1721,7 +1721,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", skin->Path().c_str());
g_SkinInfo = skin;
g_SkinInfo->Start();
@@ -1770,7 +1770,7 @@ void CApplication::LoadSkin(const SkinPtr& skin)
// fallback to default skin
if ( strcmpi(skin->ID().c_str(), DEFAULT_SKIN) != 0)
{
- CLog::Log(LOGERROR, "failed to load home.xml for skin:%s, fallback to \"%s\" skin", skin->ID().c_str(), DEFAULT_SKIN);
+ CLog::Log(LOGERROR, "failed to load home.xml for skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), DEFAULT_SKIN);
g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN);
LoadSkin(DEFAULT_SKIN);
return ;
@@ -1878,7 +1878,7 @@ bool CApplication::LoadUserWindows()
TiXmlDocument xmlDoc;
if (!xmlDoc.LoadFile(items[i]->GetPath()))
{
- CLog::Log(LOGERROR, "unable to load:%s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
+ CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
continue;
}
@@ -1887,7 +1887,7 @@ bool CApplication::LoadUserWindows()
CStdString strValue = pRootElement->Value();
if (!strValue.Equals("window"))
{
- CLog::Log(LOGERROR, "file :%s doesnt contain <window>", skinFile.c_str());
+ CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
continue;
}
@@ -3556,88 +3556,123 @@ bool CApplication::PlayStack(const CFileItem& item, bool bRestart)
if (!item.IsStack())
return false;
- // see if we have the info in the database
- // TODO: If user changes the time speed (FPS via framerate conversion stuff)
- // then these times will be wrong.
- // Also, this is really just a hack for the slow load up times we have
- // A much better solution is a fast reader of FPS and fileLength
- // that we can use on a file to get it's time.
- vector<int> times;
- bool haveTimes(false);
CVideoDatabase dbs;
- if (dbs.Open())
+
+ // case 1: stacked ISOs
+ if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
{
- dbs.GetVideoSettings(item.GetPath(), g_settings.m_currentVideoSettings);
- haveTimes = dbs.GetStackTimes(item.GetPath(), times);
- dbs.Close();
- }
+ CStackDirectory dir;
+ CFileItemList movieList;
+ dir.GetDirectory(item.GetPath(), movieList);
+ int selectedFile = 1; // if playing from beginning, play file 1.
+ long startoffset = item.m_lStartOffset;
- // calculate the total time of the stack
- CStackDirectory dir;
- dir.GetDirectory(item.GetPath(), *m_currentStack);
- long totalTime = 0;
- for (int i = 0; i < m_currentStack->Size(); i++)
- {
- if (haveTimes)
- (*m_currentStack)[i]->m_lEndOffset = times[i];
- else
+ // We instructed the stack to resume.
+ if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
+ startoffset = CGUIWindowVideoBase::GetResumeItemOffset(&item);
+
+ if (startoffset & 0xF0000000) /* selected part is specified as a flag */
{
- int duration;
- if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
- {
- m_currentStack->Clear();
- return false;
- }
- totalTime += duration / 1000;
- (*m_currentStack)[i]->m_lEndOffset = totalTime;
- times.push_back(totalTime);
- }
- }
+ selectedFile = (startoffset>>28);
+ startoffset = startoffset & ~0xF0000000;
- double seconds = item.m_lStartOffset / 75.0;
+ // set startoffset in movieitem. The remaining startoffset is either 0 (just play part from beginning) or positive (then we use STARTOFFSET_RESUME).
+ if (selectedFile > 0 && selectedFile <= (int)movieList.Size())
+ movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
+ }
- if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
- { // have our times now, so update the dB
+ // finally play selected item
+ if (selectedFile > 0 && selectedFile <= (int)movieList.Size())
+ return PlayFile(*(movieList[selectedFile - 1]));
+ }
+ // case 2: all other stacks
+ else
+ {
+ // see if we have the info in the database
+ // TODO: If user changes the time speed (FPS via framerate conversion stuff)
+ // then these times will be wrong.
+ // Also, this is really just a hack for the slow load up times we have
+ // A much better solution is a fast reader of FPS and fileLength
+ // that we can use on a file to get it's time.
+ vector<int> times;
+ bool haveTimes(false);
+ CVideoDatabase dbs;
if (dbs.Open())
{
- if( !haveTimes )
- dbs.SetStackTimes(item.GetPath(), times);
+ dbs.GetVideoSettings(item.GetPath(), g_settings.m_currentVideoSettings);
+ haveTimes = dbs.GetStackTimes(item.GetPath(), times);
+ dbs.Close();
+ }
- if( item.m_lStartOffset == STARTOFFSET_RESUME )
+
+ // calculate the total time of the stack
+ CStackDirectory dir;
+ dir.GetDirectory(item.GetPath(), *m_currentStack);
+ long totalTime = 0;
+ for (int i = 0; i < m_currentStack->Size(); i++)
+ {
+ if (haveTimes)
+ (*m_currentStack)[i]->m_lEndOffset = times[i];
+ else
{
- // can only resume seek here, not dvdstate
- CBookmark bookmark;
- if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
- seconds = bookmark.timeInSeconds;
- else
- seconds = 0.0f;
+ int duration;
+ if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
+ {
+ m_currentStack->Clear();
+ return false;
+ }
+ totalTime += duration / 1000;
+ (*m_currentStack)[i]->m_lEndOffset = totalTime;
+ times.push_back(totalTime);
}
- dbs.Close();
}
- }
- *m_itemCurrentFile = item;
- m_currentStackPosition = 0;
- m_eCurrentPlayer = EPC_NONE; // must be reset on initial play otherwise last player will be used
+ double seconds = item.m_lStartOffset / 75.0;
- if (seconds > 0)
- {
- // work out where to seek to
- for (int i = 0; i < m_currentStack->Size(); i++)
+ if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
+ { // have our times now, so update the dB
+ if (dbs.Open())
+ {
+ if( !haveTimes )
+ dbs.SetStackTimes(item.GetPath(), times);
+
+ if( item.m_lStartOffset == STARTOFFSET_RESUME )
+ {
+ // can only resume seek here, not dvdstate
+ CBookmark bookmark;
+ if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
+ seconds = bookmark.timeInSeconds;
+ else
+ seconds = 0.0f;
+ }
+ dbs.Close();
+ }
+ }
+
+ *m_itemCurrentFile = item;
+ m_currentStackPosition = 0;
+ m_eCurrentPlayer = EPC_NONE; // must be reset on initial play otherwise last player will be used
+
+ if (seconds > 0)
{
- if (seconds < (*m_currentStack)[i]->m_lEndOffset)
+ // work out where to seek to
+ for (int i = 0; i < m_currentStack->Size(); i++)
{
- CFileItem item(*(*m_currentStack)[i]);
- long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
- item.m_lStartOffset = (long)(seconds - start) * 75;
- m_currentStackPosition = i;
- return PlayFile(item, true);
+ if (seconds < (*m_currentStack)[i]->m_lEndOffset)
+ {
+ CFileItem item(*(*m_currentStack)[i]);
+ long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
+ item.m_lStartOffset = (long)(seconds - start) * 75;
+ m_currentStackPosition = i;
+ return PlayFile(item, true);
+ }
}
}
- }
- return PlayFile(*(*m_currentStack)[0], true);
+ return PlayFile(*(*m_currentStack)[0], true);
+ }
+ return false;
}
bool CApplication::PlayFile(const CFileItem& item, bool bRestart)
View
16 xbmc/FileItem.cpp
@@ -3033,10 +3033,18 @@ void CFileItemList::Swap(unsigned int item1, unsigned int item2)
bool CFileItemList::UpdateItem(const CFileItem *item)
{
if (!item) return false;
- CFileItemPtr oldItem = Get(item->GetPath());
- if (oldItem)
- *oldItem = *item;
- return oldItem;
+
+ CSingleLock lock(m_lock);
+ for (unsigned int i = 0; i < m_items.size(); i++)
+ {
+ CFileItemPtr pItem = m_items[i];
+ if (pItem->IsSamePath(item))
+ {
+ *pItem = *item;
+ return true;
+ }
+ }
+ return false;
}
void CFileItemList::AddSortMethod(SORT_METHOD sortMethod, int buttonLabel, const LABEL_MASKS &labelMasks)
View
6 xbmc/GUIInfoManager.cpp
@@ -118,9 +118,11 @@ bool CGUIInfoManager::OnMessage(CGUIMessage &message)
if (message.GetParam1() == GUI_MSG_UPDATE_ITEM && message.GetItem())
{
CFileItemPtr item = boost::static_pointer_cast<CFileItem>(message.GetItem());
- if (item && m_currentFile->GetPath().Equals(item->GetPath()))
+ if (m_currentFile->IsSamePath(item.get()))
+ {
*m_currentFile = *item;
- return true;
+ return true;
+ }
}
}
return false;
View
2  xbmc/TextureDatabase.cpp
@@ -181,9 +181,9 @@ bool CTextureDatabase::AddCachedTexture(const CStdString &url, const CStdString
if (!m_pDS->eof())
{ // update
int textureID = m_pDS->fv(0).get_asInt();
- m_pDS->close();
if (cacheURL.IsEmpty())
cacheURL = m_pDS->fv(1).get_asString();
+ m_pDS->close();
if (!imageHash.IsEmpty())
sql = PrepareSQL("update texture set cachedurl='%s', usecount=1, lastusetime=CURRENT_TIMESTAMP, imagehash='%s', lasthashcheck='%s' where id=%u", cacheURL.c_str(), imageHash.c_str(), date.c_str(), textureID);
else
View
2  xbmc/addons/Addon.cpp
@@ -25,6 +25,7 @@
#include "settings/GUISettings.h"
#include "filesystem/Directory.h"
#include "filesystem/File.h"
+#include "interfaces/python/XBPython.h"
#ifdef __APPLE__
#include "../osx/OSXGNUReplacements.h"
#endif
@@ -443,6 +444,7 @@ void CAddon::SaveSettings(void)
doc.SaveFile(m_userSettingsPath);
CAddonMgr::Get().ReloadSettings(ID());//push the settings changes to the running addon instance
+ g_pythonParser.OnSettingsChanged(ID());
}
CStdString CAddon::GetSetting(const CStdString& key)
View
2  xbmc/addons/GUIDialogAddonSettings.cpp
@@ -534,7 +534,9 @@ void CGUIDialogAddonSettings::SaveSettings(void)
m_addon->UpdateSetting(i->first, i->second);
if (m_saveToDisk)
+ {
m_addon->SaveSettings();
+ }
}
void CGUIDialogAddonSettings::FreeSections()
View
7 xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp
@@ -419,9 +419,12 @@ int CDVDInputStreamNavigator::ProcessBlock(BYTE* dest_buffer, int* read)
iNavresult = NAVRESULT_HOLD;
}
else
+ {
iNavresult = m_pDVDPlayer->OnDVDNavResult(buf, DVDNAV_VTS_CHANGE);
-
- m_bInMenu = (0 == m_dll.dvdnav_is_domain_vts(m_dvdnav));
+ m_holdmode = HOLDMODE_HELD;
+ m_lastevent = DVDNAV_NOP;
+ m_bInMenu = (0 == m_dll.dvdnav_is_domain_vts(m_dvdnav));
+ }
}
break;
View
8 xbmc/filesystem/NFSFile.cpp
@@ -236,7 +236,13 @@ bool CNfsConnection::splitUrlIntoExportAndPath(const CURL& url, CStdString &expo
if( path.Find(*it) == 0 )
{
exportPath = *it;
- relativePath = "//" + path.Right((path.length()-1) - exportPath.length());
+ //handle special case where root is exported
+ //in that case we don't want to stripp off to
+ //much from the path
+ if( exportPath == "/" )
+ relativePath = "//" + path.Right((path.length()) - exportPath.length());
+ else
+ relativePath = "//" + path.Right((path.length()-1) - exportPath.length());
ret = true;
break;
}
View
104 xbmc/interfaces/python/XBPython.cpp
@@ -41,6 +41,10 @@
#include "threads/SystemClock.h"
#include "addons/Addon.h"
+#include "interfaces/AnnouncementManager.h"
+#include "interfaces/python/xbmcmodule/PythonMonitor.h"
+
+using namespace ANNOUNCEMENT;
extern "C" HMODULE __stdcall dllLoadLibraryA(LPCSTR file);
extern "C" BOOL __stdcall dllFreeLibrary(HINSTANCE hLibModule);
@@ -71,10 +75,13 @@ XBPython::XBPython()
m_ThreadId = CThread::GetCurrentThreadId();
m_iDllScriptCounter = 0;
m_vecPlayerCallbackList.clear();
+ m_vecMonitorCallbackList.clear();
+ CAnnouncementManager::AddAnnouncer(this);
}
XBPython::~XBPython()
{
+ CAnnouncementManager::RemoveAnnouncer(this);
}
// message all registered callbacks that xbmc stopped playing
@@ -92,6 +99,27 @@ void XBPython::OnPlayBackEnded()
}
}
+void XBPython::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data)
+{
+ if (flag & VideoLibrary)
+ {
+ if (strcmp(message, "OnScanFinished") == 0)
+ OnDatabaseUpdated("video");
+ }
+ else if (flag & AudioLibrary)
+ {
+ if (strcmp(message, "OnScanFinished") == 0)
+ OnDatabaseUpdated("music");
+ }
+ else if (flag & GUI)
+ {
+ if (strcmp(message, "OnScreensaverDeactivated") == 0)
+ OnScreensaverDeactivated();
+ else if (strcmp(message, "OnScreensaverActivated") == 0)
+ OnScreensaverActivated();
+ }
+}
+
// message all registered callbacks that we started playing
void XBPython::OnPlayBackStarted()
{
@@ -171,6 +199,82 @@ void XBPython::UnregisterPythonPlayerCallBack(IPlayerCallback* pCallback)
}
}
+void XBPython::RegisterPythonMonitorCallBack(CPythonMonitor* pCallback)
+{
+ CSingleLock lock(m_critSection);
+ m_vecMonitorCallbackList.push_back(pCallback);
+}
+
+void XBPython::UnregisterPythonMonitorCallBack(CPythonMonitor* pCallback)
+{
+ CSingleLock lock(m_critSection);
+ MonitorCallbackList::iterator it = m_vecMonitorCallbackList.begin();
+ while (it != m_vecMonitorCallbackList.end())
+ {
+ if (*it == pCallback)
+ it = m_vecMonitorCallbackList.erase(it);
+ else
+ it++;
+ }
+}
+
+void XBPython::OnSettingsChanged(const CStdString &ID)
+{
+ CSingleLock lock(m_critSection);
+ if (m_bInitialized)
+ {
+ MonitorCallbackList::iterator it = m_vecMonitorCallbackList.begin();
+ while (it != m_vecMonitorCallbackList.end())
+ {
+ if (((CPythonMonitor*)(*it))->Id == ID)
+ ((CPythonMonitor*)(*it))->OnSettingsChanged();
+ it++;
+ }
+ }
+}
+
+void XBPython::OnScreensaverActivated()
+{
+ CSingleLock lock(m_critSection);
+ if (m_bInitialized)
+ {
+ MonitorCallbackList::iterator it = m_vecMonitorCallbackList.begin();
+ while (it != m_vecMonitorCallbackList.end())
+ {
+ ((CPythonMonitor*)(*it))->OnScreensaverActivated();
+ it++;
+ }
+ }
+}
+
+void XBPython::OnScreensaverDeactivated()
+{
+ CSingleLock lock(m_critSection);
+ if (m_bInitialized)
+ {
+ MonitorCallbackList::iterator it = m_vecMonitorCallbackList.begin();
+ while (it != m_vecMonitorCallbackList.end())
+ {
+ ((CPythonMonitor*)(*it))->OnScreensaverDeactivated();
+ it++;
+ }
+ }
+}
+
+void XBPython::OnDatabaseUpdated(const std::string &database)
+{
+ CSingleLock lock(m_critSection);
+ if (m_bInitialized)
+ {
+ MonitorCallbackList::iterator it = m_vecMonitorCallbackList.begin();
+ while (it != m_vecMonitorCallbackList.end())
+ {
+ ((CPythonMonitor*)(*it))->OnDatabaseUpdated(database);
+ it++;
+ }
+ }
+}
+
/**
* Check for file and print an error if needed
*/
View
15 xbmc/interfaces/python/XBPython.h
@@ -24,6 +24,7 @@
#include "XBPyThread.h"
#include "cores/IPlayer.h"
#include "threads/CriticalSection.h"
+#include "interfaces/IAnnouncer.h"
#include "addons/IAddon.h"
#include <vector>
@@ -36,12 +37,16 @@ typedef struct {
}PyElem;
class LibraryLoader;
+class CPythonMonitor;
typedef std::vector<PyElem> PyList;
typedef std::vector<PVOID> PlayerCallbackList;
+typedef std::vector<PVOID> MonitorCallbackList;
typedef std::vector<LibraryLoader*> PythonExtensionLibraries;
-class XBPython : public IPlayerCallback
+class XBPython :
+ public IPlayerCallback,
+ public ANNOUNCEMENT::IAnnouncer
{
public:
XBPython();
@@ -52,8 +57,15 @@ class XBPython : public IPlayerCallback
virtual void OnPlayBackResumed();
virtual void OnPlayBackStopped();
virtual void OnQueueNextItem() {};
+ virtual void Announce(ANNOUNCEMENT::AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data);
void RegisterPythonPlayerCallBack(IPlayerCallback* pCallback);
void UnregisterPythonPlayerCallBack(IPlayerCallback* pCallback);
+ void RegisterPythonMonitorCallBack(CPythonMonitor* pCallback);
+ void UnregisterPythonMonitorCallBack(CPythonMonitor* pCallback);
+ void OnSettingsChanged(const CStdString &strings);
+ void OnScreensaverActivated();
+ void OnScreensaverDeactivated();
+ void OnDatabaseUpdated(const std::string &database);
void Initialize();
void Finalize();
void FinalizeScript();
@@ -117,6 +129,7 @@ class XBPython : public IPlayerCallback
//Vector with list of threads used for running scripts
PyList m_vecPyList;
PlayerCallbackList m_vecPlayerCallbackList;
+ MonitorCallbackList m_vecMonitorCallbackList;
LibraryLoader* m_pDll;
// any global events that scripts should be using
View
2  xbmc/interfaces/python/xbmcmodule/Makefile.in
@@ -22,10 +22,12 @@ SRCS=action.cpp \
infotagvideo.cpp \
keyboard.cpp \
listitem.cpp \
+ monitor.cpp \
player.cpp \
pyplaylist.cpp \
pyrendercapture.cpp \
PythonAddon.cpp \
+ PythonMonitor.cpp \
PythonPlayer.cpp \
pyutil.cpp \
window.cpp \
View
131 xbmc/interfaces/python/xbmcmodule/PythonMonitor.cpp
@@ -0,0 +1,131 @@
+/*
+ * 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
+ *
+ */
+
+#include "PythonMonitor.h"
+#include "pyutil.h"
+#include "pythreadstate.h"
+#include "../XBPython.h"
+#include "threads/Atomics.h"
+
+using namespace PYXBMC;
+
+struct SPyEvent
+{
+ SPyEvent(CPythonMonitor* monitor
+ , const std::string &function, const std::string &arg = "")
+ {
+ m_monitor = monitor;
+ m_monitor->Acquire();
+ m_function = function;
+ m_arg = arg;
+ }
+
+ ~SPyEvent()
+ {
+ m_monitor->Release();
+ }
+
+ std::string m_function;
+ std::string m_arg;
+ CPythonMonitor* m_monitor;
+};
+
+/*
+ * called from python library!
+ */
+static int SPyEvent_Function(void* e)
+{
+ SPyEvent* object = (SPyEvent*)e;
+ PyObject* ret = NULL;
+
+ if(object->m_monitor->m_callback)
+ {
+ if (!object->m_arg.empty())
+ ret = PyObject_CallMethod(object->m_monitor->m_callback, (char*)object->m_function.c_str(), "(s)", object->m_arg.c_str());
+ else
+ ret = PyObject_CallMethod(object->m_monitor->m_callback, (char*)object->m_function.c_str(), NULL);
+ }
+
+ if(ret)
+ {
+ Py_DECREF(ret);
+ }
+
+ CPyThreadState pyState;
+ delete object;
+
+ return 0;
+
+}
+
+CPythonMonitor::CPythonMonitor()
+{
+ m_callback = NULL;
+ m_refs = 1;
+ g_pythonParser.RegisterPythonMonitorCallBack(this);
+}
+
+void CPythonMonitor::Release()
+{
+ if(AtomicDecrement(&m_refs) == 0)
+ delete this;
+}
+
+void CPythonMonitor::Acquire()
+{
+ AtomicIncrement(&m_refs);
+}
+
+CPythonMonitor::~CPythonMonitor(void)
+{
+ g_pythonParser.UnregisterPythonMonitorCallBack(this);
+}
+
+void CPythonMonitor::OnSettingsChanged()
+{
+ PyXBMC_AddPendingCall(m_state, SPyEvent_Function, new SPyEvent(this, "onSettingsChanged"));
+ g_pythonParser.PulseGlobalEvent();
+}
+
+void CPythonMonitor::OnScreensaverActivated()
+{
+ PyXBMC_AddPendingCall(m_state, SPyEvent_Function, new SPyEvent(this, "onScreensaverActivated"));
+ g_pythonParser.PulseGlobalEvent();
+}
+
+void CPythonMonitor::OnScreensaverDeactivated()
+{
+ PyXBMC_AddPendingCall(m_state, SPyEvent_Function, new SPyEvent(this, "onScreensaverDeactivated"));
+ g_pythonParser.PulseGlobalEvent();
+}
+
+void CPythonMonitor::OnDatabaseUpdated(const std::string &database)
+{
+ PyXBMC_AddPendingCall(m_state, SPyEvent_Function, new SPyEvent(this, "onDatabaseUpdated", database));
+ g_pythonParser.PulseGlobalEvent();
+}
+
+void CPythonMonitor::SetCallback(PyThreadState *state, PyObject *object)
+{
+ /* python lock should be held */
+ m_callback = object;
+ m_state = state;
+}
View
51 xbmc/interfaces/python/xbmcmodule/PythonMonitor.h
@@ -0,0 +1,51 @@
+/*
+ * 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
+
+#include <Python.h>
+#include <string>
+
+int Py_XBMC_Event_OnSettingsChanged(void* arg);
+int Py_XBMC_Event_OnScreensaverActivated(void* arg);
+int Py_XBMC_Event_OnScreensaverDeactivated(void* arg);
+int Py_XBMC_Event_OnDatabaseUpdated(void* arg);
+
+class CPythonMonitor
+{
+public:
+ CPythonMonitor();
+ void SetCallback(PyThreadState *state, PyObject *object);
+ void OnSettingsChanged();
+ void OnScreensaverActivated();
+ void OnScreensaverDeactivated();
+ void OnDatabaseUpdated(const std::string &database);
+
+ void Acquire();
+ void Release();
+
+ PyObject* m_callback;
+ PyThreadState *m_state;
+ std::string Id;
+protected:
+ ~CPythonMonitor(void);
+ long m_refs;
+};
View
150 xbmc/interfaces/python/xbmcmodule/monitor.cpp
@@ -0,0 +1,150 @@
+/*
+ * 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
+ *
+ */
+
+#include "monitor.h"
+#include "pyutil.h"
+#include "pythreadstate.h"
+#include "PythonMonitor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+namespace PYXBMC
+{
+ PyObject* Monitor_New(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+ Monitor *self;
+
+ self = (Monitor*)type->tp_alloc(type, 0);
+ if (!self) return NULL;
+ std::string addonId;
+ if (!PyXBMCGetAddonId(addonId) || addonId.empty())
+ {
+ PyErr_SetString((PyObject*)self, "Unable to identify addon");
+ return NULL;
+ }
+ CPyThreadState pyState;
+ self->pMonitor = new CPythonMonitor();
+ pyState.Restore();
+ self->pMonitor->Id = addonId;
+ self->pMonitor->SetCallback(PyThreadState_Get(), (PyObject*)self);
+
+ return (PyObject*)self;
+ }
+
+ void Monitor_Dealloc(Monitor* self)
+ {
+ self->pMonitor->SetCallback(NULL, NULL);
+
+ CPyThreadState pyState;
+ self->pMonitor->Release();
+ pyState.Restore();
+
+ self->pMonitor = NULL;
+ self->ob_type->tp_free((PyObject*)self);
+ }
+
+
+ // Monitor_onSettingsChanged
+ PyDoc_STRVAR(onSettingsChanged__doc__,
+ "onSettingsChanged() -- onSettingsChanged method.\n"
+ "\n"
+ "Will be called when addon settings are changed");
+
+ PyObject* Monitor_OnSettingsChanged(PyObject *self, PyObject *args)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ // Monitor_onScreensaverActivated
+ PyDoc_STRVAR(onScreensaverActivated__doc__,
+ "onScreenSaverStarted() -- onScreensaverActivated method.\n"
+ "\n"
+ "Will be called when screensaver kicks in");
+
+ PyObject* Monitor_OnScreensaverActivated(PyObject *self, PyObject *args)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ // Monitor_onScreensaverDeactivated
+ PyDoc_STRVAR(onScreensaverDeactivated__doc__,
+ "onScreensaverDeactivated() -- onScreensaverDeactivated method.\n"
+ "\n"
+ "Will be called when screensaver goes off");
+
+ PyObject* Monitor_OnScreensaverDeactivated(PyObject *self, PyObject *args)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ // Monitor_onDatabaseUpdated
+ PyDoc_STRVAR(onDatabaseUpdated__doc__,
+ "onDatabaseUpdated(database) -- onDatabaseUpdated method.\n"
+ "\n"
+ "database - video/music as string"
+ "\n"
+ "Will be called when database gets updated and return video or music to indicate which DB has been changed");
+
+ PyObject* Monitor_OnDatabaseUpdated(PyObject *self, PyObject *args)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ PyMethodDef Monitor_methods[] = {
+ {(char*)"onSettingsChanged", (PyCFunction)Monitor_OnSettingsChanged, METH_VARARGS, onSettingsChanged__doc__},
+ {(char*)"onScreensaverActivated", (PyCFunction)Monitor_OnScreensaverActivated, METH_VARARGS, onScreensaverActivated__doc__},
+ {(char*)"onScreensaverDeactivated", (PyCFunction)Monitor_OnScreensaverDeactivated, METH_VARARGS, onScreensaverDeactivated__doc__},
+ {(char*)"onDatabaseUpdated", (PyCFunction)Monitor_OnDatabaseUpdated, METH_VARARGS , onDatabaseUpdated__doc__},
+ {NULL, NULL, 0, NULL}
+ };
+
+ PyDoc_STRVAR(monitor__doc__,
+ "Monitor class.\n"
+ "\n"
+ "Monitor() -- Creates a new Monitor to notify addon about changes.\n"
+ "\n");
+
+ PyTypeObject Monitor_Type;
+
+ void initMonitor_Type()
+ {
+ PyXBMCInitializeTypeObject(&Monitor_Type);
+
+ Monitor_Type.tp_name = (char*)"xbmc.Monitor";
+ Monitor_Type.tp_basicsize = sizeof(Monitor);
+ Monitor_Type.tp_dealloc = (destructor)Monitor_Dealloc;
+ Monitor_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
+ Monitor_Type.tp_doc = monitor__doc__;
+ Monitor_Type.tp_methods = Monitor_methods;
+ Monitor_Type.tp_base = 0;
+ Monitor_Type.tp_new = Monitor_New;
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
View
43 xbmc/interfaces/python/xbmcmodule/monitor.h
@@ -0,0 +1,43 @@
+/*
+ * 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
+
+#include <Python.h>
+#include "PythonMonitor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+namespace PYXBMC
+{
+ typedef struct {
+ PyObject_HEAD
+ CPythonMonitor* pMonitor;
+ } Monitor;
+
+ extern PyTypeObject Monitor_Type;
+ void initMonitor_Type();
+}
+
+#ifdef __cplusplus
+}
+#endif
View
21 xbmc/interfaces/python/xbmcmodule/pyutil.cpp
@@ -140,8 +140,27 @@ namespace PYXBMC
memset(type_object, 0, sizeof(PyTypeObject));
memcpy(type_object, &py_type_object_header, size);
}
-}
+ bool PyXBMCGetAddonId(std::string &addonId)
+ {
+ // we need to retrieve the addon's ID from python using
+ // __xbmcaddonid__ so let's get a reference to the main
+ // module and global dictionary
+ PyObject* main_module = PyImport_AddModule((char*)"__main__");
+ PyObject* global_dict = PyModule_GetDict(main_module);
+
+ // extract a reference to the function "func_name"
+ // from the global dictionary
+ PyObject* pyid = PyDict_GetItemString(global_dict, "__xbmcaddonid__");
+
+ // if we were unable to retrieve the addon's ID return false
+ if (pyid == NULL)
+ return false;
+
+ addonId = PyString_AsString(pyid);
+ return true;
+ }
+}
struct SPending
{
View
2  xbmc/interfaces/python/xbmcmodule/pyutil.h
@@ -42,6 +42,8 @@ namespace PYXBMC
void PyXBMCInitializeTypeObject(PyTypeObject* type_object);
void PyXBMCWaitForThreadMessage(int message, int param1, int param2);
+
+ bool PyXBMCGetAddonId(std::string &addonId);
}
// Python doesn't play nice with PyXBMC_AddPendingCall
View
7 xbmc/interfaces/python/xbmcmodule/xbmcmodule.cpp
@@ -54,6 +54,7 @@
#include "pythreadstate.h"
#include "utils/log.h"
#include "pyrendercapture.h"
+#include "monitor.h"
// include for constants
#include "pyutil.h"
@@ -1029,6 +1030,7 @@ namespace PYXBMC
initPlayListItem_Type();
initInfoTagMusic_Type();
initInfoTagVideo_Type();
+ initMonitor_Type();
#ifdef HAS_PYRENDERCAPTURE
initRenderCapture_Type();
@@ -1039,7 +1041,8 @@ namespace PYXBMC
PyType_Ready(&PlayList_Type) < 0 ||
PyType_Ready(&PlayListItem_Type) < 0 ||
PyType_Ready(&InfoTagMusic_Type) < 0 ||
- PyType_Ready(&InfoTagVideo_Type) < 0) return;
+ PyType_Ready(&InfoTagVideo_Type) < 0 ||
+ PyType_Ready(&Monitor_Type) < 0) return;
#ifdef HAS_PYRENDERCAPTURE
if (PyType_Ready(&RenderCapture_Type) < 0)
@@ -1066,6 +1069,7 @@ namespace PYXBMC
Py_INCREF(&PlayListItem_Type);
Py_INCREF(&InfoTagMusic_Type);
Py_INCREF(&InfoTagVideo_Type);
+ Py_INCREF(&Monitor_Type);
#ifdef HAS_PYRENDERCAPTURE
Py_INCREF(&RenderCapture_Type);
@@ -1080,6 +1084,7 @@ namespace PYXBMC
PyModule_AddObject(pXbmcModule, (char*)"PlayListItem", (PyObject*)&PlayListItem_Type);
PyModule_AddObject(pXbmcModule, (char*)"InfoTagMusic", (PyObject*)&InfoTagMusic_Type);
PyModule_AddObject(pXbmcModule, (char*)"InfoTagVideo", (PyObject*)&InfoTagVideo_Type);
+ PyModule_AddObject(pXbmcModule, (char*)"Monitor", (PyObject*)&Monitor_Type);
// constants
PyModule_AddStringConstant(pXbmcModule, (char*)"__author__", (char*)PY_XBMC_AUTHOR);
View
2  xbmc/playlists/PlayList.cpp
@@ -450,7 +450,7 @@ void CPlayList::UpdateItem(const CFileItem *item)
for (ivecItems it = m_vecItems.begin(); it != m_vecItems.end(); ++it)
{
CFileItemPtr playlistItem = *it;
- if (playlistItem->GetPath() == item->GetPath())
+ if (playlistItem->IsSamePath(item))
{
*playlistItem = *item;
break;
View
1  xbmc/settings/GUISettings.cpp
@@ -713,7 +713,6 @@ void CGUISettings::Initialize()
myVideosSelectActions.insert(make_pair(22081, SELECT_ACTION_INFO));
AddInt(vid, "myvideos.selectaction", 22079, SELECT_ACTION_PLAY_OR_RESUME, myVideosSelectActions, SPIN_CONTROL_TEXT);
- AddBool(NULL, "myvideos.treatstackasfile", 20051, true);
AddBool(vid, "myvideos.extractflags",20433, true);
AddBool(vid, "myvideos.replacelabels", 20419, true);
AddBool(NULL, "myvideos.extractthumb",20433, true);
View
3  xbmc/settings/GUISettings.h
@@ -191,7 +191,8 @@ enum VideoSelectAction
SELECT_ACTION_RESUME,
SELECT_ACTION_INFO,
SELECT_ACTION_MORE,
- SELECT_ACTION_PLAY
+ SELECT_ACTION_PLAY,
+ SELECT_ACTION_PLAYPART
};
enum SubtitleAlign
View
4 xbmc/video/VideoDatabase.cpp
@@ -2966,10 +2966,10 @@ void CVideoDatabase::GetCast(const CStdString &table, const CStdString &table_id
CStdString sql = PrepareSQL("SELECT actors.strActor,"
" actorlink%s.strRole,"
- " actors.strThumb, "
+ " actors.strThumb "
"FROM actorlink%s"
" JOIN actors ON"
- " actorlink%s.idActor=actors.idActor"
+ " actorlink%s.idActor=actors.idActor "
"WHERE actorlink%s.%s=%i "
"ORDER BY actorlink%s.iOrder",table.c_str(), table.c_str(), table.c_str(), table.c_str(), table_id.c_str(), type_id, table.c_str());
m_pDS2->query(sql.c_str());
View
249 xbmc/video/windows/GUIWindowVideoBase.cpp
@@ -821,26 +821,7 @@ int CGUIWindowVideoBase::GetResumeItemOffset(const CFileItem *item)
db.Open();
long startoffset = 0;
- if (item->IsStack() && (!g_guiSettings.GetBool("myvideos.treatstackasfile") ||
- CFileItem(CStackDirectory::GetFirstStackedFile(item->GetPath()),false).IsDVDImage()) )
- {
-
- CStdStringArray movies;
- GetStackedFiles(item->GetPath(), movies);
-
- /* check if any of the stacked files have a resume bookmark */
- for (unsigned i = 0; i<movies.size();i++)
- {
- CBookmark bookmark;
- if (db.GetResumeBookMark(movies[i], bookmark))
- {
- startoffset = (long)(bookmark.timeInSeconds*75);
- startoffset += 0x10000000 * (i+1); /* store file number in here */
- break;
- }
- }
- }
- else if (!item->IsNFO() && !item->IsPlayList())
+ if (!item->IsNFO() && !item->IsPlayList())
{
if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_resumePoint.timeInSeconds > 0.0)
startoffset = (long)(item->GetVideoInfoTag()->m_resumePoint.timeInSeconds*75);
@@ -853,6 +834,25 @@ int CGUIWindowVideoBase::GetResumeItemOffset(const CFileItem *item)
if (db.GetResumeBookMark(strPath, bookmark))
startoffset = (long)(bookmark.timeInSeconds*75);
+
+ if (URIUtils::IsStack(strPath) && CFileItem(CStackDirectory::GetFirstStackedFile(strPath),false).IsDVDImage())
+ {
+ CStackDirectory dir;
+ CFileItemList movies;
+ dir.GetDirectory(strPath, movies);
+
+ /* check if any of the stacked files have a resume bookmark */
+ for (int i = 0; i < movies.Size(); i++)
+ {
+ CBookmark bookmark;
+ if (db.GetResumeBookMark(movies[i]->GetPath(), bookmark))
+ {
+ startoffset = (long)(bookmark.timeInSeconds);
+ startoffset += 0x10000000 * (i+1); /* store file number in here */
+ // don't break, we take the last one!
+ }
+ }
+ }
}
}
db.Close();
@@ -894,6 +894,14 @@ bool CGUIWindowVideoBase::OnFileAction(int iItem, int action)
CContextButtons choices;
bool resume = false;
+ if (item->IsVideoDb())
+ {
+ CStdString itemPath(item->GetPath());
+ itemPath = item->GetVideoInfoTag()->m_strFileNameAndPath;
+ if (URIUtils::IsStack(itemPath) && CFileItem(CStackDirectory::GetFirstStackedFile(itemPath),false).IsDVDImage())
+ choices.Add(SELECT_ACTION_PLAYPART, 20324); // Play Part
+ }
+
if (!item->IsLiveTV())
{
CStdString resumeString = GetResumeString(*item);
@@ -928,6 +936,10 @@ bool CGUIWindowVideoBase::OnFileAction(int iItem, int action)
case SELECT_ACTION_RESUME:
item->m_lStartOffset = STARTOFFSET_RESUME;
break;
+ case SELECT_ACTION_PLAYPART:
+ if (!OnPlayStackPart(iItem))
+ return false;
+ break;
case SELECT_ACTION_PLAY:
default:
break;
@@ -988,6 +1000,7 @@ void CGUIWindowVideoBase::OnRestartItem(int iItem)
CStdString CGUIWindowVideoBase::GetResumeString(CFileItem item)
{
CStdString resumeString;
+ CStdString partString;
CVideoDatabase db;
if (db.Open())
{
@@ -995,7 +1008,20 @@ CStdString CGUIWindowVideoBase::GetResumeString(CFileItem item)
CStdString itemPath(item.GetPath());
if (item.IsVideoDb() || item.IsDVD())
itemPath = item.GetVideoInfoTag()->m_strFileNameAndPath;
- if (db.GetResumeBookMark(itemPath, bookmark) )
+
+ if (URIUtils::IsStack(itemPath) && CFileItem(CStackDirectory::GetFirstStackedFile(itemPath),false).IsDVDImage())
+ {
+ int startoffset = GetResumeItemOffset(&item);
+ if (startoffset > 0)
+ {
+ int selectedPart = (startoffset>>28);
+ startoffset = startoffset & ~0xF0000000;
+ partString.Format(g_localizeStrings.Get(23051).c_str(), selectedPart);
+ resumeString.Format(g_localizeStrings.Get(12022).c_str(), StringUtils::SecondsToTimeString(lrint(startoffset)).c_str());
+ resumeString.append(" (").append(partString).append(")");
+ }
+ }
+ else if (db.GetResumeBookMark(itemPath, bookmark) )
resumeString.Format(g_localizeStrings.Get(12022).c_str(), StringUtils::SecondsToTimeString(lrint(bookmark.timeInSeconds)).c_str());
db.Close();
}
@@ -1084,7 +1110,7 @@ void CGUIWindowVideoBase::GetContextButtons(int itemNumber, CContextButtons &but
if (URIUtils::IsStack(path))
{
vector<int> times;
- if (m_database.GetStackTimes(path,times))
+ if (m_database.GetStackTimes(path,times) || CFileItem(CStackDirectory::GetFirstStackedFile(path),false).IsDVDImage())
buttons.Add(CONTEXT_BUTTON_PLAY_PART, 20324);
}
@@ -1143,6 +1169,64 @@ void CGUIWindowVideoBase::GetNonContextButtons(int itemNumber, CContextButtons &
buttons.Add(CONTEXT_BUTTON_NOW_PLAYING, 13350);
}
+bool CGUIWindowVideoBase::OnPlayStackPart(int iItem)
+{
+ if (iItem < 0 || iItem >= m_vecItems->Size())
+ return false;
+
+ CFileItemPtr stack = m_vecItems->Get(iItem);
+ CStdString path(stack->GetPath());
+ if (stack->IsVideoDb())
+ path = stack->GetVideoInfoTag()->m_strFileNameAndPath;
+
+ if (!URIUtils::IsStack(path))
+ return false;
+
+ CFileItemList parts;
+ CDirectory::GetDirectory(path,parts);
+ CGUIDialogFileStacking* dlg = (CGUIDialogFileStacking*)g_windowManager.GetWindow(WINDOW_DIALOG_FILESTACKING);
+ if (!dlg) return true;
+ dlg->SetNumberOfFiles(parts.Size());
+ dlg->DoModal();
+ int selectedFile = dlg->GetSelectedFile();
+ if (selectedFile > 0)
+ {
+ // ISO stack
+ if (CFileItem(CStackDirectory::GetFirstStackedFile(path),false).IsDVDImage())
+ {
+ CStdString resumeString = CGUIWindowVideoBase::GetResumeString(*(parts[selectedFile - 1].get()));
+ stack->m_lStartOffset = 0x10000000 * (selectedFile); /* store file number in here */
+ if (!resumeString.IsEmpty())
+ {
+ CContextButtons choices;
+ choices.Add(SELECT_ACTION_RESUME, resumeString);
+ choices.Add(SELECT_ACTION_PLAY, 12021); // Start from beginning
+ int value = CGUIDialogContextMenu::ShowAndGetChoice(choices);
+ if (value == SELECT_ACTION_RESUME)
+ stack->m_lStartOffset += (long)CGUIWindowVideoBase::GetResumeItemOffset(parts[selectedFile - 1].get());
+ else if (value != SELECT_ACTION_PLAY)
+ return false; // if not selected PLAY, then we changed our mind so return
+ }
+ }
+ // regular stack
+ else
+ {
+ if (selectedFile > 1)
+ {
+ vector<int> times;
+ if (m_database.GetStackTimes(path,times))
+ stack->m_lStartOffset = times[selectedFile-2]*75; // wtf?
+ }
+ else
+ stack->m_lStartOffset = 0;
+ }
+
+
+ }
+
+ return true;
+}
+
bool CGUIWindowVideoBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
{
CFileItemPtr item;
@@ -1157,32 +1241,14 @@ bool CGUIWindowVideoBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
}
case CONTEXT_BUTTON_PLAY_PART:
{
- CFileItemList items;
- CStdString path(item->GetPath());
- if (item->IsVideoDb())
- path = item->GetVideoInfoTag()->m_strFileNameAndPath;
-
- CDirectory::GetDirectory(path,items);
- CGUIDialogFileStacking* dlg = (CGUIDialogFileStacking*)g_windowManager.GetWindow(WINDOW_DIALOG_FILESTACKING);
- if (!dlg) return true;
- dlg->SetNumberOfFiles(items.Size());
- dlg->DoModal();
- int btn2 = dlg->GetSelectedFile();
- if (btn2 > 0)
+ if (OnPlayStackPart(itemNumber))
{
- if (btn2 > 1)
- {
- vector<int> times;
- if (m_database.GetStackTimes(path,times))
- item->m_lStartOffset = times[btn2-2]*75; // wtf?
- }
- else
- item->m_lStartOffset = 0;
-
// call CGUIMediaWindow::OnClick() as otherwise autoresume will kick in
CGUIMediaWindow::OnClick(itemNumber);
+ return true;
}
- return true;
+ else
+ return false;
}
case CONTEXT_BUTTON_QUEUE_ITEM:
OnQueueItem(itemNumber);
@@ -1301,25 +1367,6 @@ bool CGUIWindowVideoBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
return CGUIMediaWindow::OnContextButton(itemNumber, button);
}
-void CGUIWindowVideoBase::GetStackedFiles(const CStdString &strFilePath1, vector<CStdString> &movies)
-{
- CStdString strFilePath = strFilePath1; // we're gonna be altering it
-
- movies.clear();
-
- CURL url(strFilePath);
- if (url.GetProtocol() == "stack")
- {
- CStackDirectory dir;
- CFileItemList items;
- dir.GetDirectory(strFilePath, items);
- for (int i = 0; i < items.Size(); ++i)
- movies.push_back(items[i]->GetPath());
- }
- if (movies.empty())
- movies.push_back(strFilePath);
-}
-
bool CGUIWindowVideoBase::OnPlayMedia(int iItem)
{
if ( iItem < 0 || iItem >= (int)m_vecItems->Size() )
@@ -1368,85 +1415,13 @@ bool CGUIWindowVideoBase::OnPlayAndQueueMedia(const CFileItemPtr &item)
void CGUIWindowVideoBase::PlayMovie(const CFileItem *item)
{
- CFileItemList movieList;
- int selectedFile = 1;
- long startoffset = item->m_lStartOffset;
-
- if (item->IsStack() && (!g_guiSettings.GetBool("myvideos.treatstackasfile") ||
- CFileItem(CStackDirectory::GetFirstStackedFile(item->GetPath()),false).IsDVDImage()) )
- {
- CStdStringArray movies;
- GetStackedFiles(item->GetPath(), movies);
-
- if (item->m_lStartOffset == STARTOFFSET_RESUME)
- {
- startoffset = GetResumeItemOffset(item);
-
- if (startoffset & 0xF0000000) /* file is specified as a flag */
- {
- selectedFile = (startoffset>>28);
- startoffset = startoffset & ~0xF0000000;
- }
- else
- {
- /* attempt to start on a specific time in a stack */
- /* if we are lucky, we might have stored timings for */
- /* this stack at some point */
-
- m_database.Open();
-
- /* figure out what file this time offset is */
- vector<int> times;
- m_database.GetStackTimes(item->GetPath(), times);
- long totaltime = 0;
- for (unsigned i = 0; i < times.size(); i++)
- {
- totaltime += times[i]*75;
- if (startoffset < totaltime )
- {
- selectedFile = i+1;
- startoffset -= totaltime - times[i]*75; /* rebase agains selected file */
- break;
- }
- }
- m_database.Close();
- }
- }
- else
- { // show file stacking dialog
- CGUIDialogFileStacking* dlg = (CGUIDialogFileStacking*)g_windowManager.GetWindow(WINDOW_DIALOG_FILESTACKING);
- if (dlg)
- {
- dlg->SetNumberOfFiles(movies.size());
- dlg->DoModal();
- selectedFile = dlg->GetSelectedFile();
- if (selectedFile < 1)
- return;
- }
- }
- // add to our movie list
- for (unsigned int i = 0; i < movies.size(); i++)
- {
- CFileItemPtr movieItem(new CFileItem(movies[i], false));
- movieList.Add(movieItem);
- }
- }
- else
- {
- CFileItemPtr movieItem(new CFileItem(*item));
- movieList.Add(movieItem);
- }
+ CFileItemPtr movieItem(new CFileItem(*item));
g_playlistPlayer.Reset();
g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO);
CPlayList& playlist = g_playlistPlayer.GetPlaylist(PLAYLIST_VIDEO);
playlist.Clear();
- for (int i = selectedFile - 1; i < (int)movieList.Size(); ++i)
- {
- if (i == selectedFile - 1)
- movieList[i]->m_lStartOffset = startoffset;
- playlist.Add(movieList[i]);
- }
+ playlist.Add(movieItem);
if(m_thumbLoader.IsLoading())
m_thumbLoader.StopAsync();
View
3  xbmc/video/windows/GUIWindowVideoBase.h
@@ -114,7 +114,6 @@ class CGUIWindowVideoBase : public CGUIMediaWindow, public IBackgroundLoaderObse
bool ShowIMDB(CFileItem *item, const ADDON::ScraperPtr& content);
void AddItemToPlayList(const CFileItemPtr &pItem, CFileItemList &queuedItems);
- static void GetStackedFiles(const CStdString &strFileName, std::vector<CStdString> &movies);
void OnSearch();
void OnSearchItemFound(const CFileItem* pSelItem);
@@ -124,6 +123,8 @@ class CGUIWindowVideoBase : public CGUIMediaWindow, public IBackgroundLoaderObse
bool StackingAvailable(const CFileItemList &items) const;
+ bool OnPlayStackPart(int item);
+
CGUIDialogProgress* m_dlgProgress;
CVideoDatabase m_database;

No commit comments for this range