📄 videodisplay.py
字号:
import timefrom objc import YES, NO, nilfrom AppKit import *from Foundation import *from PyObjCTools import NibClassBuilderimport appimport eventloopimport platformutilsfrom QuicktimeRenderer import QuicktimeRendererfrom QTKit import QTMovieDidEndNotification################################################################################### Dynamically link some specific Carbon functions which we need but ####### which are not available in the default MacPython ###################################################################################import objckUIModeNormal = 0kUIModeAllHidden = 3carbonPath = objc.pathForFramework('/System/Library/Frameworks/Carbon.framework')carbonBundle = NSBundle.bundleWithPath_(carbonPath)objc.loadBundleFunctions(carbonBundle, globals(), ((u'SetSystemUIMode', 'III'),))OverallActivity = 0coreServicesPath = objc.pathForFramework('/System/Library/Frameworks/CoreServices.framework')coreServicesBundle = NSBundle.bundleWithPath_(coreServicesPath)objc.loadBundleFunctions(coreServicesBundle, globals(), ((u'UpdateSystemActivity', 'IC'),))###############################################################################class PlaybackController (app.PlaybackControllerBase): def playItemExternally(self, itemID): item = app.PlaybackControllerBase.playItemExternally(self, itemID) moviePath = item.getVideoFilename() ws = NSWorkspace.sharedWorkspace() ok, externalApp, movieType = ws.getInfoForFile_application_type_(moviePath) if ok: if externalApp == NSBundle.mainBundle().bundlePath(): print 'DTV: WARNING, trying to play movie externally with Democracy.' ok = False else: ok = ws.openFile_withApplication_andDeactivate_(moviePath, nil, YES) if not ok: print "DTV: movie %s could not be externally opened" % moviePath###############################################################################class VideoDisplay (app.VideoDisplayBase): "Video player shown in a MainFrame's right-hand pane." def __init__(self): app.VideoDisplayBase.__init__(self) self.controller = VideoDisplayController.getInstance() self.controller.videoDisplay = self def initRenderers(self): self.renderers.append(QuicktimeRenderer(self.controller)) def selectItem(self, item, renderer): app.VideoDisplayBase.selectItem(self, item, renderer) self.controller.selectItem(item, renderer) def play(self): app.VideoDisplayBase.play(self) self.controller.play() def pause(self): app.VideoDisplayBase.pause(self) self.controller.pause() def stop(self): app.VideoDisplayBase.stop(self) self.controller.stop() def goFullScreen(self): app.VideoDisplayBase.goFullScreen(self) self.controller.goFullScreen() def exitFullScreen(self): app.VideoDisplayBase.exitFullScreen(self) self.controller.exitFullScreen() def setVolume(self, level): app.VideoDisplayBase.setVolume(self, level) self.controller.setVolume(level) def muteVolume(self): app.VideoDisplayBase.muteVolume(self) self.controller.volumeSlider.setEnabled_(NO) def restoreVolume(self): app.VideoDisplayBase.restoreVolume(self) self.controller.volumeSlider.setEnabled_(YES) def onSelected(self, frame): app.VideoDisplayBase.onSelected(self, frame) self.controller.onSelected() def onDeselected(self, frame): app.VideoDisplayBase.onDeselected(self, frame) self.controller.onDeselected() def getView(self): return self.controller.rootView###############################################################################class VideoDisplayController (NibClassBuilder.AutoBaseClass): _instance = nil @classmethod def getInstance(self): assert VideoDisplayController._instance is not nil return VideoDisplayController._instance def awakeFromNib(self): VideoDisplayController._instance = self self.forwardButton.setCell_(SkipSeekButtonCell.cellFromButtonCell_direction_delay_(self.forwardButton.cell(), 1, 0.5)) self.backwardButton.setCell_(SkipSeekButtonCell.cellFromButtonCell_direction_delay_(self.backwardButton.cell(), -1, 0.5)) self.muteButton.setEnabled_(YES) self.volumeSlider.setEnabled_(YES) nc = NSNotificationCenter.defaultCenter() nc.addObserver_selector_name_object_( self, 'handleWatchableDisplayNotification:', 'notifyPlayable', nil) nc.addObserver_selector_name_object_( self, 'handleNonWatchableDisplayNotification:', 'notifyNotPlayable', nil) self.systemActivityUpdaterTimer = nil self.reset() @platformutils.onMainThread def onSelected(self): self.enableSecondaryControls(YES) self.preventSystemSleep(True) @platformutils.onMainThread def onDeselected(self): self.enableSecondaryControls(NO) self.preventSystemSleep(False) self.videoAreaView.teardown() self.progressDisplayer.teardown() self.reset() def selectItem(self, item, renderer): self.videoAreaView.setup(item, renderer) self.progressDisplayer.setup(renderer) def reset(self): self.currentWatchableDisplay = None def preventSystemSleep(self, prevent): if prevent and self.systemActivityUpdaterTimer is nil: print "DTV: Launching system activity updater timer" self.systemActivityUpdaterTimer = NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(30, self, 'updateSystemActivity:', nil, YES) elif self.systemActivityUpdaterTimer is not nil: print "DTV: Stopping system activity updater timer" self.systemActivityUpdaterTimer.invalidate() self.systemActivityUpdaterTimer = nil def updateSystemActivity_(self, timer): UpdateSystemActivity(OverallActivity) def enablePrimaryControls(self, enabled): self.playPauseButton.setEnabled_(enabled) self.fullscreenButton.setEnabled_(enabled) def enableSecondaryControls(self, enabled, allowFastSeeking=YES): self.backwardButton.setEnabled_(enabled) self.backwardButton.cell().setAllowsFastSeeking(allowFastSeeking) self.stopButton.setEnabled_(enabled) self.forwardButton.setEnabled_(enabled) self.forwardButton.cell().setAllowsFastSeeking(allowFastSeeking) def updatePlayPauseButton(self, prefix): self.playPauseButton.setImage_(NSImage.imageNamed_('%s' % prefix)) self.playPauseButton.setAlternateImage_(NSImage.imageNamed_('%s_blue' % prefix)) def playPause_(self, sender): eventloop.addUrgentCall(lambda:app.controller.playbackController.playPause(), "Play Video") @platformutils.onMainThread def play(self): nc = NSNotificationCenter.defaultCenter() nc.postNotificationName_object_('videoWillPlay', nil) self.enablePrimaryControls(YES) self.enableSecondaryControls(YES) self.updatePlayPauseButton('pause') @platformutils.onMainThread def pause(self): nc = NSNotificationCenter.defaultCenter() nc.postNotificationName_object_('videoWillPause', nil) self.updatePlayPauseButton('play') def stop_(self, sender): eventloop.addUrgentCall(lambda:app.controller.playbackController.stop(), "Stop Video") @platformutils.onMainThread def stop(self): nc = NSNotificationCenter.defaultCenter() nc.postNotificationName_object_('videoWillStop', nil) self.updatePlayPauseButton('play') def playFullScreen_(self, sender): def performInEventLoop(): if not app.controller.videoDisplay.isPlaying: app.controller.playbackController.playPause() self.videoDisplay.goFullScreen() eventloop.addUrgentCall(lambda:performInEventLoop(), "Play Video Fullscreen") @platformutils.onMainThread def goFullScreen(self): self.videoAreaView.enterFullScreen() def exitFullScreen_(self, sender): self.exitFullScreen() @platformutils.onMainThread def exitFullScreen(self): self.videoAreaView.exitFullScreen() def skipForward_(self, sender): eventloop.addUrgentCall(lambda:app.controller.playbackController.skip(1), "Skip Forward") def fastForward_(self, sender): self.fastSeek(1) def skipBackward_(self, sender): eventloop.addUrgentCall(lambda:app.controller.playbackController.skip(-1), "Skip Backward") def fastBackward_(self, sender): self.fastSeek(-1) def fastSeek(self, direction): if not self.videoDisplay.isPlaying: self.updatePlayPauseButton('pause') rate = 3 * direction self.videoDisplay.activeRenderer.setRate(rate) def stopSeeking(self): rate = 1.0 if not self.videoDisplay.isPlaying: rate = 0.0 self.updatePlayPauseButton('play') if self.videoDisplay.activeRenderer is not None: self.videoDisplay.activeRenderer.setRate(rate) def setVolume_(self, sender): self.videoDisplay.setVolume(sender.floatValue()) @platformutils.onMainThread def setVolume(self, level): if self.muteButton.state() == NSOnState: self.volumeSlider.setFloatValue_(level) def muteUnmuteVolume_(self, sender): if sender.state() is NSOffState: self.videoDisplay.muteVolume() else: self.videoDisplay.restoreVolume() def handleWatchableDisplayNotification_(self, notification): self.enablePrimaryControls(YES) self.enableSecondaryControls(self.videoDisplay.isPlaying) def handleNonWatchableDisplayNotification_(self, notification): self.enablePrimaryControls(NO) self.enableSecondaryControls(NO) def handleMovieNotification_(self, notification): renderer = self.videoDisplay.activeRenderer if notification.name() == QTMovieDidEndNotification and not renderer.interactivelySeeking: eventloop.addUrgentCall(lambda:app.controller.playbackController.onMovieFinished(), "Movie Finished Callback")###############################################################################class VideoAreaView (NibClassBuilder.AutoBaseClass): def setup(self, item, renderer): if not self.videoWindow.isFullScreen: self.adjustVideoWindowFrame() self.videoWindow.setup(renderer, item) self.activateVideoWindow() nc = NSNotificationCenter.defaultCenter() nc.addObserver_selector_name_object_(self, 'handleWindowNotifications:', NSWindowDidMoveNotification, self.window()) def teardown(self): platformutils.warnIfNotOnMainThread('VideoAreaView.teardown') nc = NSNotificationCenter.defaultCenter() nc.removeObserver_name_object_(self, NSWindowDidMoveNotification, nil) if self.videoWindow.isFullScreen: self.videoWindow.exitFullScreen() self.window().removeChildWindow_(self.videoWindow) self.videoWindow.orderOut_(nil) self.videoWindow.teardown() @platformutils.onMainThreadWaitingUntilDone def activateVideoWindow(self): self.videoWindow.orderFront_(nil) if self.videoWindow.parentWindow() is nil: self.window().addChildWindow_ordered_(self.videoWindow, NSWindowAbove) def drawRect_(self, rect): NSColor.blackColor().set() NSRectFill(rect) @platformutils.onMainThreadWaitingUntilDone def adjustVideoWindowFrame(self): if self.window() is nil: return frame = self.frame() frame.origin = self.convertPoint_toView_(NSZeroPoint, nil) frame.origin = self.window().convertBaseToScreen_(frame.origin) self.videoWindow.setFrame_display_(frame, YES) def setFrame_(self, frame): super(VideoAreaView, self).setFrame_(frame) self.adjustVideoWindowFrame() def handleWindowNotifications_(self, notification): self.adjustVideoWindowFrame() @platformutils.onMainThread def enterFullScreen(self): self.adjustVideoWindowFrame() if self.window() is not nil: self.videoWindow.enterFullScreen(self.window().screen()) self.window().removeChildWindow_(self.videoWindow) self.window().orderOut_(nil)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -