def getImagesMjpegInterlace(self, url, *args, **kwargs): """ Update camera position with interlaced mjpeg frames """ try: stream = requests.get(url, stream = True, timeout = TIMEOUT).raw except requests.RequestException as e: utils.log(3, e) self.img1.setImage(_error, useCache = False) return x = 0 while not self.monitor.abortRequested() and not self.monitor.stopped() and self.monitor.previewOpened(self.camera.number): filename = os.path.join(_datapath, '%s_%s.%d.jpg') %(self.prefix, self.camera.number, x) filename_exists = utils.get_mjpeg_frame(stream, filename) if filename_exists: if x % 2 == 0: #Interlacing for flicker reduction/elimination self.img1.setImage(filename, useCache = False) else: self.img2.setImage(filename, useCache = False) xbmcvfs.delete(os.path.join(_datapath, '%s_%s.%d.jpg') %(self.prefix, self.camera.number, x - 2)) x += 1 else: utils.log(3, 'Camera %s :: Error updating preview image on MJPEG' %self.camera.number) self.img1.setImage(_error, useCache = False) break if not not self.monitor.abortRequested() and not self.monitor.stopped(): utils.remove_leftover_images('%s_%s.' %(self.prefix, self.camera.number))
def getImagesMjpegInterlace(self, url, *args, **kwargs): """ Update camera position with interlaced mjpeg frames """ try: stream = requests.get(url, stream=True, timeout=TIMEOUT).raw except requests.RequestException as e: utils.log(3, e) self.img1.setImage(_error, useCache=False) return x = 0 while not self.monitor.abortRequested() and not self.monitor.stopped( ) and self.monitor.previewOpened(self.camera.number): filename = os.path.join(_datapath, '%s_%s.%d.jpg') % ( self.prefix, self.camera.number, x) filename_exists = utils.get_mjpeg_frame(stream, filename) if filename_exists: if x % 2 == 0: #Interlacing for flicker reduction/elimination self.img1.setImage(filename, useCache=False) else: self.img2.setImage(filename, useCache=False) xbmcvfs.delete( os.path.join(_datapath, '%s_%s.%d.jpg') % (self.prefix, self.camera.number, x - 2)) x += 1 else: utils.log( 3, 'Camera %s :: Error updating preview image on MJPEG' % self.camera.number) self.img1.setImage(_error, useCache=False) break if not not self.monitor.abortRequested() and not self.monitor.stopped( ): utils.remove_leftover_images('%s_%s.' % (self.prefix, self.camera.number))
def getImagesMjpeg(self, url): """ Update camera position with mjpeg frames """ try: # stream = requests.get(url, stream = True, timeout = TIMEOUT, auth=HTTPDigestAuth('USERNAME', 'PASSWORD')).raw #uncomment if you need digest support for mjpeg stream = requests.get(url, stream=True, timeout=TIMEOUT).raw except requests.RequestException as e: utils.log(3, e) self.img1.setImage(_error, useCache=False) return x = 0 while not self.monitor.abortRequested() and not self.monitor.stopped( ) and self.monitor.previewOpened(self.camera.number): filename = os.path.join(_datapath, '%s_%s.%d.jpg') % ( self.prefix, self.camera.number, x) filename_exists = utils.get_mjpeg_frame(stream, filename) if filename_exists: self.img1.setImage(filename, useCache=False) self.img2.setImage(filename, useCache=False) xbmcvfs.delete( os.path.join(_datapath, '%s_%s.%d.jpg') % (self.prefix, self.camera.number, x - 1)) x += 1 else: utils.log( 3, 'Camera %s :: Error updating preview image on MJPEG' % self.camera.number) self.img1.setImage(_error, useCache=False) break if not not self.monitor.abortRequested() and not self.monitor.stopped( ): utils.remove_leftover_images('%s_%s.' % (self.prefix, self.camera.number))
def __init__(self): self.isRunning = True # Black Background background_fade_animation = [ ("WindowOpen", ("effect=fade time=200")), ("WindowClose", ("effect=fade time=1500")), ] img = xbmcgui.ControlImage(0, 0, 1280, 720, filename=_black, aspectRatio=0) self.addControl(img) img.setAnimations(background_fade_animation) # Individual Camera positions setup urls = [] files = [] imgs = [] imgs2 = [] coords = [(0, 0, 640, 360), (640, 0, 640, 360), (0, 360, 640, 360), (640, 360, 640, 360)] effect = ["slide", "slide"] time = [1200, 1000] tween = ["back", "back"] easing = ["Out", "InOut"] animations = [ [ ( "WindowOpen", ("effect={0} start=-640,-360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0] ), ), ( "WindowClose", ("effect={0} end=-640,-360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] ), ), ], [ ( "WindowOpen", ("effect={0} start=640,-360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0] ), ), ( "WindowClose", ("effect={0} end=640,-360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] ), ), ], [ ( "WindowOpen", ("effect={0} start=-640,360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0] ), ), ( "WindowClose", ("effect={0} end=-640,360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] ), ), ], [ ( "WindowOpen", ("effect={0} start=640,360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0] ), ), ( "WindowClose", ("effect={0} end=640,360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] ), ), ], ] # Acquire all Enabled & Connected cameras enabled_cameras = settings.getAllEnabledCameras(monitor) # Logic to ensure enabled cameras are placed in the correct position threads = [] for window_position in "1234": position = int(window_position) - 1 # Sets the initial image to the loader gif img1 = xbmcgui.ControlImage(*coords[position], filename=_loader, aspectRatio=0) self.addControl( img1 ) # Bug was seen here previously, hence the 'try' and this will need to be investigated in future img1.setAnimations(animations[position]) # Connected and Enabled Camera if len(enabled_cameras) > position: img2 = xbmcgui.ControlImage(*coords[position], filename="", aspectRatio=0) self.addControl(img2) img2.setAnimations(animations[position]) control = [img1, img2] with Camera(enabled_cameras[position]) as camera: stream_type = camera.getStreamType(1) url = camera.getStreamUrl(1, stream_type) prefix = "AllCamera" if stream_type == 0: # MJPEG t = threading.Thread(target=self.getImagesMjpeg, args=(camera, url, control, prefix)) elif stream_type == 2: # MJPEG Interlaced t = threading.Thread(target=self.getImagesMjpegInterlace, args=(camera, url, control, prefix)) else: # Snapshot t = threading.Thread(target=self.getImagesSnapshot, args=(camera, url, control, prefix)) threads.append(t) t.start() # No Camera so set the place holder image else: img1.setImage(_holder, useCache=False) if len(threads) > 0: self.doModal() # while not monitor.abortRequested() and self.isRunning: # monitor.waitForAbort(1) monitor.maybe_resume_previous() monitor.waitForAbort(1) utils.remove_leftover_images("AllCamera") else: utils.log(2, "Unable to start All Camera Player") utils.notify("Player did not start. Check camera settings.")
class CameraPreviewWindow(xbmcgui.WindowDialog): """ Class is used to create the picture-in-picture window of the camera view """ def __init__(self, camera, monitor): self.camera = camera self.monitor = monitor self.cond_service = settings.getSetting_int('cond_service', self.camera.number) self.cond_manual = settings.getSetting_int('cond_manual', self.camera.number) self.dur_service = settings.getSetting_int('dur_service', self.camera.number) self.dur_manual = settings.getSetting_int('dur_manual', self.camera.number) self.prefix = 'Preview' self.buttons = [] # Positioning of the window WIDTH = 320 HEIGHT = 180 scaling = settings.getSetting_float('scaling', self.camera.number) width = int(float(WIDTH * scaling)) height = int(float(HEIGHT * scaling)) button_scaling = 0.5 * scaling button_width = int(round(Button.WIDTH * button_scaling)) position = settings.getSetting('position', self.camera.number).lower() if 'bottom' in position: y = 720 - height else: y = 0 if 'left' in position: x = 0 start = -width else: x = 1280 - width start = width animations = [ ('WindowOpen', ("effect=slide start={0:d} time=1300 tween=cubic easing=out" ).format(start)), ('WindowClose', ("effect=slide end={0:d} time=900 tween=back easing=inout" ).format(start)) ] self.black = xbmcgui.ControlImage(x, y, width, height, _black) self.addControl(self.black) self.black.setAnimations(animations) self.img1 = xbmcgui.ControlImage(x, y, width, height, '') self.img2 = xbmcgui.ControlImage(x, y, width, height, '') self.addControl(self.img1) self.addControl(self.img2) self.img1.setAnimations(animations) self.img2.setAnimations(animations) self.close_button = Button(self, 'close', x + width - button_width - 10, y + 10, scaling=button_scaling) self.addControl(self.close_button) self.close_button.setAnimations(animations) self.setProperty('zorder', "99") self.playFullscreen = False self.stop() #Initializes state and makes ready to be used def start(self): url = self.monitor.get_overrideURL( self.camera.number) #Request to test by @mrjd in forum stream_type = self.camera.getStreamType(2) if url == '': url = self.camera.getStreamUrl(2, stream_type) utils.log( 2, 'Camera %s :: Preview Window Opened - Manual: %s; Stream Type: %d; URL: %s' % (self.camera.number, self.monitor.openRequest_manual( self.camera.number), stream_type, url)) if stream_type == 0: t = threading.Thread(target=self.getImagesMjpeg, args=(url, )) elif stream_type == 1: t = threading.Thread(target=self.getImagesSnapshot, args=(url, )) elif stream_type == 2: t = threading.Thread(target=self.getImagesMjpegInterlace, args=(url, )) t.daemon = True self.monitor.openPreview(self.camera.number) t.start() self.show() self.wait_closeRequest() def stop(self, playFullscreen=False): self.monitor.closePreview(self.camera.number) self.close() utils.log(2, 'Camera %s :: Preview Window Closed' % self.camera.number) if not self.monitor.abortRequested() and not self.monitor.stopped(): if playFullscreen: self.monitor.maybe_stop_current() fullscreenplayer = settings.getSetting_int('fullscreen_player') if fullscreenplayer == CAMERAWITHCONTROLS: cameraplayer.play(self.camera.number) elif fullscreenplayer == CAMERAWITHOUTCONTROLS: cameraplayer.play(self.camera.number, show_controls=False) elif fullscreenplayer == ALLCAMERAPLAYER: allcameraplayer.play() self.wait_openRequest() def wait_openRequest(self): while not self.monitor.abortRequested() and not self.monitor.stopped( ) and not self.monitor.openRequested(self.camera.number): self.monitor.waitForAbort(.5) if not self.monitor.abortRequested() and not self.monitor.stopped(): self.openRequest_manual = self.monitor.openRequested_manual( self.camera.number) self.start() def wait_closeRequest(self): duration = 0 # Duration is 0 if Close Condition is Manual or Alarm only, otherwise set based on source if not self.monitor.openRequested_manual(self.camera.number): if self.cond_service == CONDITION_DURATION_NO_ALARM or self.cond_service == CONDITION_DURATION: duration = self.dur_service else: if self.cond_manual == CONDITION_DURATION_NO_ALARM or self.cond_manual == CONDITION_DURATION: duration = self.dur_manual openDuration = time.time() + duration #print 'Wait for close - duration: %d; openDuration: %d' %(duration, openDuration) # Loop Condition Checking while not self.monitor.abortRequested() and not self.monitor.stopped( ) and self.monitor.previewOpened( self.camera.number) and not self.monitor.closeRequested( self.camera.number): if ((self.cond_service == CONDITION_DURATION_NO_ALARM and not self.monitor.openRequested_manual(self.camera.number)) or \ (self.cond_manual == CONDITION_DURATION_NO_ALARM and self.monitor.openRequested_manual(self.camera.number))) \ and self.monitor.alarmActive(self.camera.number): openDuration = time.time() + duration #print '%s, %s, %s, %s' %(self.cond_service, self.cond_manual, self.monitor.openRequested_manual(self.camera.number), self.monitor.alarmActive(self.camera.number)) #print 'Wait for close Loop - duration: %d; openDuration: %d; time: %d' %(duration, openDuration, time.time()) # Duration Check if Close Condition is not Manual or Alarm only if (duration > 0 and time.time() > openDuration): self.monitor.closeRequest(self.camera.number) # Check if close Request if self.monitor.closeRequested(self.camera.number): break self.monitor.waitForAbort(.5) self.stop() def onControl(self, control): if control == self.close_button: utils.log( 2, 'Camera %s :: Closing Preview Manually - Mouse Request' % self.camera.number) self.monitor.dismissPreview(self.camera.number) self.stop() def onAction(self, action): if action in (ACTION_PREVIOUS_MENU, ACTION_BACKSPACE, ACTION_NAV_BACK): utils.log( 2, 'Camera %s :: Closing Preview Manually - Keyboard Request' % self.camera.number) self.monitor.dismissPreview(self.camera.number) self.stop() elif action == ACTION_SELECT_ITEM: utils.log( 2, 'Camera %s :: Playing Fullscreen from Preview.' % self.camera.number) self.monitor.dismissPreview(self.camera.number) self.stop(playFullscreen=True) def getImagesMjpeg(self, url): """ Update camera position with mjpeg frames """ try: stream = requests.get(url, stream=True, timeout=TIMEOUT).raw except requests.RequestException as e: utils.log(3, e) self.img1.setImage(_error, useCache=False) return x = 0 while not self.monitor.abortRequested() and not self.monitor.stopped( ) and self.monitor.previewOpened(self.camera.number): filename = os.path.join(_datapath, '%s_%s.%d.jpg') % ( self.prefix, self.camera.number, x) filename_exists = utils.get_mjpeg_frame(stream, filename) if filename_exists: self.img1.setImage(filename, useCache=False) self.img2.setImage(filename, useCache=False) xbmcvfs.delete( os.path.join(_datapath, '%s_%s.%d.jpg') % (self.prefix, self.camera.number, x - 1)) x += 1 else: utils.log( 3, 'Camera %s :: Error updating preview image on MJPEG' % self.camera.number) self.img1.setImage(_error, useCache=False) break if not not self.monitor.abortRequested() and not self.monitor.stopped( ): utils.remove_leftover_images('%s_%s.' % (self.prefix, self.camera.number)) def getImagesSnapshot(self, url, *args, **kwargs): """ Update camera position with snapshots """ x = 0 while not self.monitor.abortRequested() and not self.monitor.stopped( ) and self.monitor.previewOpened(self.camera.number): try: filename = os.path.join(_datapath, '%s_%s.%d.jpg') % ( self.prefix, self.camera.number, x) urlretrieve(url, filename) if os.path.exists(filename): self.img1.setImage(filename, useCache=False) xbmcvfs.delete( os.path.join(_datapath, '%s_%s.%d.jpg') % (self.prefix, self.camera.number, x - 1)) self.img2.setImage(filename, useCache=False) x += 1 except Exception, e: utils.log( 3, 'Camera %s :: Error updating preview image on Snapshot: %s' % (self.camera.number, e)) self.img1.setImage(_error, useCache=False) break if not not self.monitor.abortRequested() and not self.monitor.stopped( ): utils.remove_leftover_images('%s_%s.' % (self.prefix, self.camera.number))
def __init__(self): self.isRunning = True # Black Background background_fade_animation = [ ('WindowOpen', ("effect=fade time=200")), ('WindowClose', ("effect=fade time=1500")) ] img = xbmcgui.ControlImage(0, 0, 1280, 720, filename = _black, aspectRatio = 0) self.addControl(img) img.setAnimations(background_fade_animation) # Individual Camera positions setup urls = [] files = [] imgs = [] imgs2 = [] coords = [ (0, 0, 640, 360), (640, 0, 640, 360), (0, 360, 640, 360), (640, 360, 640, 360) ] # coords = [ (0, 480, 426, 240), # (0, 0, 850, 480), # (426, 480, 426, 240), # (850, 480, 426, 240), # (850, 240, 426, 240), # (850, 0, 426, 240) ] effect = ['slide', 'slide'] time = [1200, 1000] tween = ['back', 'back'] easing = ['Out', 'InOut'] animations = [ [ ('WindowOpen', ("effect={0} start=-640,-360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0])), ('WindowClose', ("effect={0} end=-640,-360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] )) ], [ ('WindowOpen', ("effect={0} start=640,-360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0] )), ('WindowClose', ("effect={0} end=640,-360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] )) ], [ ('WindowOpen', ("effect={0} start=-640,360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0] )), ('WindowClose', ("effect={0} end=-640,360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] )) ], [ ('WindowOpen', ("effect={0} start=640,360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0] )), ('WindowClose', ("effect={0} end=640,360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] )) ] ] # animations = [ # [ ('WindowOpen', ("effect={0} start=-640,-360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0])), # ('WindowClose', ("effect={0} end=-640,-360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] )) ], # [ ('WindowOpen', ("effect={0} start=640,-360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0] )), # ('WindowClose', ("effect={0} end=640,-360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] )) ], # [ ('WindowOpen', ("effect={0} start=-640,360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0] )), # ('WindowClose', ("effect={0} end=-640,360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] )) ], # [ ('WindowOpen', ("effect={0} start=640,360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0] )), # ('WindowClose', ("effect={0} end=640,360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] )) ], # [ ('WindowOpen', ("effect={0} start=640,360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0] )), # ('WindowClose', ("effect={0} end=640,360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] )) ], # [ ('WindowOpen', ("effect={0} start=640,360 time={1} tween={2} easing={3}").format( effect[0], time[0], tween[0], easing[0] )), # ('WindowClose', ("effect={0} end=640,360 time={1} tween={2} easing={3}").format( effect[1], time[1], tween[1], easing[1] )) ] # ] # Acquire all Enabled & Connected cameras enabled_cameras = settings.getAllEnabledCameras(monitor) # Logic to ensure enabled cameras are placed in the correct position threads = [] for window_position in '1234': # for window_position in '123456': position = int(window_position) - 1 # Sets the initial image to the loader gif img1 = xbmcgui.ControlImage(*coords[position], filename = _loader, aspectRatio = 0) self.addControl(img1) #Bug was seen here previously, hence the 'try' and this will need to be investigated in future img1.setAnimations(animations[position]) # Connected and Enabled Camera if len(enabled_cameras) > position: img2 = xbmcgui.ControlImage(*coords[position], filename = '', aspectRatio = 0) self.addControl(img2) img2.setAnimations(animations[position]) control = [img1, img2] with Camera(enabled_cameras[position]) as camera: stream_type = camera.getStreamType(1) url = camera.getStreamUrl(1, stream_type) prefix = 'AllCamera' if stream_type == 0: #MJPEG t = threading.Thread(target = self.getImagesMjpeg, args = (camera, url, control, prefix)) elif stream_type == 2: #MJPEG Interlaced t = threading.Thread(target = self.getImagesMjpegInterlace, args = (camera, url, control, prefix)) else: #Snapshot t = threading.Thread(target = self.getImagesSnapshot, args = (camera, url, control, prefix)) threads.append(t) t.start() # No Camera so set the place holder image else: img1.setImage(_holder, useCache = False) if len(threads) > 0: self.doModal() #while not monitor.abortRequested() and self.isRunning: # monitor.waitForAbort(1) monitor.maybe_resume_previous() monitor.waitForAbort(1) utils.remove_leftover_images('AllCamera') else: utils.log(2, 'Unable to start All Camera Player') utils.notify('Player did not start. Check camera settings.')