class HorizontalSlideScreensaver(ScreensaverBase): MODE = 'slideLeftx' BACKGROUND_IMAGE = 'srr_blackbg.jpg' IMAGE_CONTROL_COUNT = 35 FAST_IMAGE_COUNT = 0 DISTANCE_RATIO = 0.7 SPEED = 1.0 CONCURRENCY = 1.0 #SCREEN = 0 IMAGE_ANIMATIONS = [ ] TEXT_ANIMATIONS= [ ] def load_settings(self): self.SPEED = float(addon.getSetting('slideshow_speed')) self.SHOW_TITLE = addon.getSetting('show_title') == 'true' self.CONCURRENCY = 1.0 #float(addon.getSetting('appletvlike_concurrency')) self.MAX_TIME = int(8000 / self.SPEED) #int(15000 / self.SPEED) self.NEXT_IMAGE_TIME = int(12000.0 / self.SPEED) self.TEXT_ANIMATIONS= [ ('conditional', 'condition=true effect=fade delay=0 time=500 start=0 end=100 ' ), ('conditional', 'condition=true effect=fade delay=%s time=500 start=100 end=0 tween=circle easing=in' % self.NEXT_IMAGE_TIME ) ] #using WindowXMLDialog(ScreensaverXMLWindow) instead of WindowDialog. the image used in text background does not load when using WindowDialog (???) some images load, most don't def init_xbmc_window(self): #self.xbmc_window = ScreensaverWindow( exit_callback=self.stop ) self.xbmc_window = ScreensaverXMLWindow( "slideshow01.xml", addon_path, defaultSkin='Default', exit_callback=self.action_id_handler ) #self.xbmc_window.setCoordinateResolution(5) self.xbmc_window.show() def stack_cycle_controls(self): for txt_ctl, img_ctl in self.tni_controls: self.xbmc_window.addControl(img_ctl) if self.SHOW_TITLE: self.txt_background=ControlImage(0, 685, 1280, 40, 'srr_dialog-bg.png', aspectRatio=1) self.xbmc_window.addControl( self.txt_background ) #ControlLabel(x, y, width, height, label, font=None, textColor=None, disabledColor=None, alignment=0, hasPath=False, angle=0) self.image_label=ControlLabel(10,688,1280,30,'',font='font16', textColor='', disabledColor='', alignment=6, hasPath=False, angle=0) self.xbmc_window.addControl( self.image_label ) #for txt_ctl, img_ctl in self.tni_controls: # self.xbmc_window.addControl(txt_ctl) def process_image(self, tni_control, desc_and_image): image_control=tni_control[1] text_control=tni_control[0] image_control.setVisible(False) image_control.setImage('') text_control.setVisible(False) text_control.setText('') direction=random.choice([1,0]) sx=1280;ex=-1280 if direction: sx,ex=ex,sx t=self.MAX_TIME self.IMAGE_ANIMATIONS = [ ('conditional', 'effect=slide start=%d,0 end=0,0 center=auto time=%s tween=cubic easing=out delay=0 condition=true' %(sx, t) ), ('conditional', 'effect=fade start=0 end=100 time=%s tween=cubic easing=out delay=0 condition=true' % t ), ('conditional', 'effect=slide start=0,0 end=%d,0 center=auto time=%s tween=cubic easing=in delay=%s condition=true' %(ex, t, (0.8*t)) ), ('conditional', 'effect=fade start=100 end=0 time=%s tween=cubic easing=in delay=%s condition=true' %(t, (0.8*t)) ), ] #self.image_label.setVisible(False) #self.image_label.setLabel('') if self.SHOW_TITLE: self.txt_background.setVisible(False) self.txt_background.setImage('') #time = self.MAX_TIME #/ zoom * self.DISTANCE_RATIO * 100 #30000 # set all parameters and properties #labels can have text centered but can't have multiline #textbox can have multiline but not centered text... what to do... #setLabel(self, label='', font=None, textColor=None, disabledColor=None, shadowColor=None, focusedColor=None, label2=''): if self.SHOW_TITLE: if self.image_label.getLabel() == desc_and_image[0]: #avoid animating the same text label if previous one is the same self.image_label.setAnimations( [ ('conditional', 'condition=true effect=fade delay=0 time=0 start=100 end=100 ' ) ] ) else: self.image_label.setAnimations( self.TEXT_ANIMATIONS ) if desc_and_image[0]: self.image_label.setLabel(desc_and_image[0]) self.image_label.setVisible(True) self.txt_background.setImage('srr_dlg-bg.png') self.txt_background.setVisible(True) else: #don't show text and text_background if no text self.image_label.setVisible(False) self.txt_background.setVisible(False) image_control.setImage(desc_and_image[1]) image_control.setPosition(0, 0) image_control.setWidth(1280) #16:9 #image_control.setWidth(1680) #21:9 image_control.setHeight(720) image_control.setAnimations(self.IMAGE_ANIMATIONS) # show the image image_control.setVisible(True)
class HorizontalSlideScreensaver(ScreensaverBase): MODE = 'slideLeftx' BACKGROUND_IMAGE = 'srr_blackbg.jpg' IMAGE_CONTROL_COUNT = 35 FAST_IMAGE_COUNT = 0 DISTANCE_RATIO = 0.7 SPEED = 1.0 CONCURRENCY = 1.0 #SCREEN = 0 IMAGE_ANIMATIONS = [] TEXT_ANIMATIONS = [] def load_settings(self): self.SPEED = float(addon.getSetting('slideshow_speed')) self.SHOW_TITLE = addon.getSetting('show_title') == 'true' self.CONCURRENCY = 1.0 #float(addon.getSetting('appletvlike_concurrency')) self.MAX_TIME = int(8000 / self.SPEED) #int(15000 / self.SPEED) self.NEXT_IMAGE_TIME = int(12000.0 / self.SPEED) self.TEXT_ANIMATIONS = [ ('conditional', 'condition=true effect=fade delay=0 time=500 start=0 end=100 '), ('conditional', 'condition=true effect=fade delay=%s time=500 start=100 end=0 tween=circle easing=in' % self.NEXT_IMAGE_TIME) ] #using WindowXMLDialog(ScreensaverXMLWindow) instead of WindowDialog. the image used in text background does not load when using WindowDialog (???) some images load, most don't def init_xbmc_window(self): #self.xbmc_window = ScreensaverWindow( exit_callback=self.stop ) self.xbmc_window = ScreensaverXMLWindow( "slideshow01.xml", addon_path, defaultSkin='Default', exit_callback=self.action_id_handler) self.xbmc_window.setCoordinateResolution(5) self.xbmc_window.show() def stack_cycle_controls(self): for txt_ctl, img_ctl in self.tni_controls: self.xbmc_window.addControl(img_ctl) if self.SHOW_TITLE: self.txt_background = ControlImage(0, 685, 1280, 40, 'srr_dialog-bg.png', aspectRatio=1) self.xbmc_window.addControl(self.txt_background) #ControlLabel(x, y, width, height, label, font=None, textColor=None, disabledColor=None, alignment=0, hasPath=False, angle=0) self.image_label = ControlLabel(10, 688, 1280, 30, '', font='font16', textColor='', disabledColor='', alignment=6, hasPath=False, angle=0) self.xbmc_window.addControl(self.image_label) #for txt_ctl, img_ctl in self.tni_controls: # self.xbmc_window.addControl(txt_ctl) def process_image(self, tni_control, desc_and_image): image_control = tni_control[1] text_control = tni_control[0] image_control.setVisible(False) image_control.setImage('') text_control.setVisible(False) text_control.setText('') direction = random.choice([1, 0]) sx = 1280 ex = -1280 if direction: sx, ex = ex, sx t = self.MAX_TIME self.IMAGE_ANIMATIONS = [ ('conditional', 'effect=slide start=%d,0 end=0,0 center=auto time=%s tween=cubic easing=out delay=0 condition=true' % (sx, t)), ('conditional', 'effect=fade start=0 end=100 time=%s tween=cubic easing=out delay=0 condition=true' % t), ('conditional', 'effect=slide start=0,0 end=%d,0 center=auto time=%s tween=cubic easing=in delay=%s condition=true' % (ex, t, (0.8 * t))), ('conditional', 'effect=fade start=100 end=0 time=%s tween=cubic easing=in delay=%s condition=true' % (t, (0.8 * t))), ] #self.image_label.setVisible(False) #self.image_label.setLabel('') if self.SHOW_TITLE: self.txt_background.setVisible(False) self.txt_background.setImage('') #time = self.MAX_TIME #/ zoom * self.DISTANCE_RATIO * 100 #30000 # set all parameters and properties #labels can have text centered but can't have multiline #textbox can have multiline but not centered text... what to do... #setLabel(self, label='', font=None, textColor=None, disabledColor=None, shadowColor=None, focusedColor=None, label2=''): if self.SHOW_TITLE: if self.image_label.getLabel() == desc_and_image[ 0]: #avoid animating the same text label if previous one is the same self.image_label.setAnimations([( 'conditional', 'condition=true effect=fade delay=0 time=0 start=100 end=100 ' )]) else: self.image_label.setAnimations(self.TEXT_ANIMATIONS) if desc_and_image[0]: self.image_label.setLabel(desc_and_image[0]) self.image_label.setVisible(True) self.txt_background.setImage('srr_dlg-bg.png') self.txt_background.setVisible(True) else: #don't show text and text_background if no text self.image_label.setVisible(False) self.txt_background.setVisible(False) image_control.setImage(desc_and_image[1]) image_control.setPosition(0, 0) image_control.setWidth(1280) #16:9 #image_control.setWidth(1680) #21:9 image_control.setHeight(720) image_control.setAnimations(self.IMAGE_ANIMATIONS) # show the image image_control.setVisible(True)
class ScreensaverBase(object): MODE = None IMAGE_CONTROL_COUNT = 10 FAST_IMAGE_COUNT = 0 NEXT_IMAGE_TIME = 2000 def __init__(self): self.log('__init__ start') self.exit_requested = False self.background_control = None self.preload_control = None self.image_count = 0 self.image_controls = [] self.global_controls = [] self.exit_monitor = ExitMonitor(self.stop) self.xbmc_window = ScreensaverWindow(self.stop) self.xbmc_window.show() self.init_global_controls() self.load_settings() self.init_cycle_controls() self.stack_cycle_controls() self.log('__init__ end') def init_global_controls(self): self.log('init_global_controls start') loading_img = xbmc.validatePath('/'.join( (ADDON_PATH, 'resources', 'media', 'loading.gif'))) logo_img = xbmc.validatePath('/'.join( (ADDON_PATH, 'resources', 'media', 'logo.png'))) self.loading_control = ControlImage(480, 250, 400, 219, loading_img) self.preload_control = ControlImage(-1, -1, 1, 1, '') self.background_control = ControlImage(0, 0, 1280, 720, '') self.logo_control = ControlImage(25, 625, 250, 65, logo_img) self.logo_label = ControlLabel(98, 680, 250, 25, '', textColor='FFFFFFFF') self.global_controls = [ self.preload_control, self.background_control, self.loading_control, self.logo_control, self.logo_label ] self.xbmc_window.addControls(self.global_controls) self.log('init_global_controls end') def init_cycle_controls(self): self.log('init_cycle_controls start') for i in xrange(self.IMAGE_CONTROL_COUNT): img_control = ControlImage(0, 0, 0, 0, '', aspectRatio=2) self.image_controls.append(img_control) self.log('init_cycle_controls end') def stack_cycle_controls(self): self.log('stack_cycle_controls start') # add controls to the window in same order as image_controls list # so any new image will be in front of all previous images self.xbmc_window.addControls(self.image_controls) self.log('stack_cycle_controls end') def start_loop(self): self.log('start_loop start') images = self.get_images() if len(images) == 0: xbmcgui.Dialog().notification(ADDON_NAME, LANGUAGE(32307), ICON, 4000) self.close() if REAL_SETTINGS.getSetting('random_order') == 'true': random.shuffle(images) image_url_cycle = cycle(images) image_controls_cycle = cycle(self.image_controls) self.hide_loading_indicator() image_url = image_url_cycle.next() while not self.exit_requested: self.log('using image: %s' % repr(image_url)) image_control = image_controls_cycle.next() self.process_image(image_control, image_url) image_url = image_url_cycle.next() if self.image_count < self.FAST_IMAGE_COUNT: self.image_count += 1 else: self.preload_image(image_url) self.wait() self.log('start_loop end') def get_images(self): self.log('get_images') count = 0 self.image_aspect_ratio = 16.0 / 9.0 self.background_image = '%d.jpg' % (random.randint(1, 13)) userlist = self.getTargets() user = userlist[random.randint(0, len(userlist) - 1)] filename = xbmc.translatePath( os.path.join(SETTINGS_LOC, '%s.json' % (user))) while not xbmcvfs.exists(filename) and count <= 10: count += 1 try: user = userlist[random.randint(0, len(userlist) - 1)] filename = xbmc.translatePath( os.path.join(SETTINGS_LOC, '%s.json' % (user))) except: pass if not xbmcvfs.exists(filename): user = '******' filename = xbmc.translatePath( os.path.join(ADDON_PATH, 'resources', '%s.json' % (user))) self.logo_label.setLabel(user) return list(self.prepareImages(filename)) def prepareImages(self, filename): for img in json.load(xbmcvfs.File(filename)): yield img['image'] def getTargets(self): userList = [] for i in range(1, 11): userList.append((REAL_SETTINGS.getSetting('USER%d' % i))) return filter(None, userList) def hide_loading_indicator(self): bg_img = xbmc.validatePath('/'.join( (ADDON_PATH, 'resources', 'media', self.background_image))) self.loading_control.setAnimations([ ('conditional', 'effect=fade start=100 end=0 time=500 condition=true') ]) self.background_control.setAnimations([ ('conditional', 'effect=fade start=0 end=100 time=500 delay=500 condition=true') ]) self.logo_control.setAnimations([ ('conditional', 'effect=fade start=0 end=100 time=500 delay=500 condition=true') ]) self.logo_label.setAnimations([ ('conditional', 'effect=fade start=0 end=100 time=500 delay=500 condition=true') ]) self.background_control.setImage(bg_img) def process_image(self, image_control, image_url): # Needs to be implemented in sub class raise NotImplementedError def preload_image(self, image_url): # set the next image to an unvisible image-control for caching self.log('preloading image: %s' % repr(image_url)) self.preload_control.setImage(image_url) self.log('preloading done') def wait(self): # wait in chunks of 500ms to react earlier on exit request chunk_wait_time = int(CHUNK_WAIT_TIME) remaining_wait_time = int(self.NEXT_IMAGE_TIME) while remaining_wait_time > 0: if self.exit_requested: self.log('wait aborted') return if remaining_wait_time < chunk_wait_time: chunk_wait_time = remaining_wait_time remaining_wait_time -= chunk_wait_time xbmc.sleep(chunk_wait_time) def stop(self): self.log('stop') self.exit_requested = True self.exit_monitor = None def close(self): self.del_controls() def del_controls(self): self.log('del_controls start') self.xbmc_window.removeControls(self.image_controls) self.xbmc_window.removeControls(self.global_controls) self.preload_control = None self.background_control = None self.loading_control = None self.image_controls = [] self.global_controls = [] self.xbmc_window.close() self.xbmc_window = None self.log('del_controls end') def log(self, msg, level=xbmc.LOGDEBUG): xbmc.log(ADDON_ID + '-' + ADDON_VERSION + '-' + msg, level)