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 SpeedTest(Animation): def __init__(self, xmlFilename, scriptPath, defaultSkin='Default', defaultRes='720p'): self.button_close = None self.button_close_glow = None self.button_close_id = None self.button_run = None self.button_run_glow = None self.button_run_id = None self.dl_textbox = None self.dlul_prog_textbox = None self.image_dir = translatePath(os.path.join(addon_path(), 'resources', 'skins', 'Default', 'media')) self.image_background = None self.image_shadow = None self.image_progress = None self.image_ping = None self.image_ping_glow = None self.image_gauge = None self.image_gauge_arrow = None self.image_button_run = None self.image_button_run_glow = None self.image_speedtestresults = None self.image_centertext_testingping = None self.image_result = None self.img_centertext = None self.img_final_results = None self.img_gauge = None self.img_gauge_arrow = None self.img_ping = None self.img_ping_glow = None self.img_progress = None self.img_results = None self.ping_textbox = None self.please_wait_textbox = None self.rec_speed = None self.screenx = 1920 self.screeny = 1080 self.textbox = None self.ul_textbox = None if sys.version_info.major == 2: WindowXMLDialog.__init__(self, xmlFilename, scriptPath, defaultSkin, defaultRes) # pylint: disable=non-parent-init-called self.doModal() elif sys.version_info.major == 3: super().__init__(xmlFilename, scriptPath, defaultSkin, defaultRes) # pylint: disable=missing-super-argument def onInit(self): # pylint: disable=invalid-name self.screenx = 1920 self.screeny = 1080 self.image_background = os.path.join(self.image_dir, 'bg_screen.jpg') self.image_shadow = os.path.join(self.image_dir, 'shadowframe.png') self.image_progress = os.path.join(self.image_dir, 'ajax-loader-bar.gif') self.image_ping = os.path.join(self.image_dir, 'ping_progress_bg.png') self.image_ping_glow = os.path.join(self.image_dir, 'ping_progress_glow.png') self.image_gauge = os.path.join(self.image_dir, 'gauge_bg.png') self.image_gauge_arrow = os.path.join(self.image_dir, 'gauge_ic_arrow.png') self.image_button_run = os.path.join(self.image_dir, 'btn_start_bg.png') self.image_button_run_glow = os.path.join(self.image_dir, 'btn_start_glow_active.png') self.image_speedtestresults = os.path.join(self.image_dir, 'speedtest_results_wtext.png') self.image_centertext_testingping = os.path.join(self.image_dir, 'testing_ping.png') self.image_result = self.image_speedtestresults self.textbox = ControlTextBox(50, 50, 880, 500, textColor='0xFFFFFFFF') self.addControl(self.textbox) self.display_button_run() self.display_button_close() self.setFocus(self.button_run) def onAction(self, action): # pylint: disable=invalid-name if action in (10, 92): self.save_close() def display_button_run(self, function='true'): if function == 'true': button_run_glowx = int((self.screenx / 3) - (300 / 2)) button_run_glowy = int((self.screeny / 3) - (122 / 2) + 50) self.button_run_glow = ControlImage(button_run_glowx, button_run_glowy, 300, 122, '', aspectRatio=0) self.addControl(self.button_run_glow) self.button_run_glow.setVisible(False) self.button_run_glow.setImage(self.image_button_run_glow) self.button_run_glow.setAnimations([ ('conditional', 'effect=fade start=0 time=1000 condition=true pulse=true') ]) self.button_run = ControlButton(button_run_glowx, button_run_glowy, 300, 122, localize(30950), focusTexture=self.image_button_run, noFocusTexture=self.image_button_run, alignment=2 | 4, textColor='0xFF000000', focusedColor='0xFF000000', shadowColor='0xFFCCCCCC', disabledColor='0xFF000000') self.addControl(self.button_run) self.setFocus(self.button_run) self.button_run.setVisible(False) self.button_run.setAnimations([( 'conditional', 'effect=fade start=100 end=0 time=300 condition=!Control.IsEnabled(%d)' % self.button_run.getId() )]) self.button_run_id = self.button_run.getId() self.button_run.setEnabled(True) self.button_run.setVisible(True) self.button_run_glow.setEnabled(True) self.button_run_glow.setVisible(True) else: self.button_run.setEnabled(False) self.button_run.setVisible(False) self.button_run_glow.setEnabled(False) self.button_run_glow.setVisible(False) def display_button_close(self, function='true'): if function == 'true': self.button_close_glow = ControlImage(880, 418, 300, 122, '', aspectRatio=0) self.addControl(self.button_close_glow) self.button_close_glow.setVisible(False) self.button_close_glow.setImage(self.image_button_run_glow) self.button_close_glow.setAnimations([( 'conditional', 'effect=fade start=0 time=1000 delay=2000 pulse=true condition=Control.IsVisible(%d)' % self.button_close_glow.getId() )]) self.button_close = ControlButton(99999, 99999, 300, 122, localize(30951), focusTexture=self.image_button_run, noFocusTexture=self.image_button_run, alignment=2 | 4, textColor='0xFF000000', focusedColor='0xFF000000', shadowColor='0xFFCCCCCC', disabledColor='0xFF000000') self.addControl(self.button_close) self.button_close.setVisible(False) self.button_close.setPosition(880, 418) self.button_close_id = self.button_close.getId() self.button_close.setAnimations([( 'conditional', 'effect=fade start=0 end=100 delay=1000 time=1000 condition=Control.IsVisible(%d)' % self.button_close.getId() )]) elif function == 'visible': self.button_close.setVisible(True) self.button_close_glow.setVisible(True) self.setFocus(self.button_close) else: self.button_close.setVisible(False) self.button_close_glow.setVisible(False) def display_ping_test(self, function='true'): if function == 'true': img_centertextx = int((self.screenx / 3) - (320 / 2)) img_centertexty = int((self.screeny / 3) - (130 / 2) + 50) self.img_centertext = ControlImage(img_centertextx, img_centertexty, 320, 130, ' ', aspectRatio=0) self.addControl(self.img_centertext) img_pingx = int((self.screenx / 3) - (600 / 2)) img_pingy = int((self.screeny / 3) - (400 / 2)) self.img_ping = ControlImage(img_pingx, img_pingy, 600, 400, '', aspectRatio=1) self.img_ping_glow = ControlImage(img_pingx, img_pingy, 600, 400, '', aspectRatio=1) self.addControl(self.img_ping) self.addControl(self.img_ping_glow) self.img_ping.setVisible(False) self.img_ping_glow.setVisible(False) self.img_ping.setImage(self.image_ping) self.img_ping_glow.setImage(self.image_ping_glow) self.img_ping.setAnimations([( 'conditional', 'effect=fade start=0 end=100 delay=1000 time=1000 condition=Control.IsVisible(%d)' % self.img_ping.getId() ), ( 'conditional', 'effect=fade start=100 end=0 time=300 condition=!Control.IsEnabled(%d)' % self.img_ping.getId() )]) self.img_ping_glow.setAnimations([( 'conditional', 'effect=fade start=0 time=1000 pulse=true condition=Control.IsEnabled(%d)' % self.img_ping_glow.getId() ), ( 'conditional', 'effect=fade start=0 end=100 delay=1000 time=1000 condition=Control.IsVisible(%d)' % self.img_ping_glow.getId() ), ( 'conditional', 'effect=fade start=100 end=0 time=300 condition=!Control.IsEnabled(%d)' % self.img_ping_glow.getId() )]) self.img_centertext.setAnimations([( 'conditional', 'effect=fade start=70 time=1000 condition=true pulse=true' )]) elif function == 'visible': self.img_ping.setVisible(True) self.img_ping_glow.setVisible(True) else: self.img_ping.setVisible(False) self.img_ping_glow.setVisible(False) self.img_centertext.setVisible(False) def display_gauge_test(self, function='true'): if function == 'true': img_gaugex = int((self.screenx / 3) - (548 / 2)) img_gaugey = int((self.screeny / 3) - (400 / 2)) img_gauge_arrowx = int((self.screenx / 3) - (66 / 2) - 5) img_gauge_arrowy = int((self.screeny / 3) - (260 / 2) - 60) self.img_gauge = ControlImage(img_gaugex, img_gaugey, 548, 400, '', aspectRatio=0) self.img_gauge_arrow = ControlImage(img_gauge_arrowx, img_gauge_arrowy, 66, 260, '', aspectRatio=0) self.addControl(self.img_gauge) self.addControl(self.img_gauge_arrow) self.img_gauge.setVisible(False) self.img_gauge_arrow.setVisible(False) self.img_gauge.setImage(self.image_gauge) self.img_gauge_arrow.setImage(self.image_gauge_arrow) self.img_gauge.setAnimations([( 'conditional', 'effect=fade start=0 end=100 delay=1000 time=1000 condition=Control.IsVisible(%d)' % self.img_gauge.getId() ), ( 'conditional', 'effect=fade start=100 end=0 time=300 condition=!Control.IsEnabled(%d)' % self.img_gauge.getId() )]) self.img_gauge_arrow.setAnimations([( 'conditional', 'effect=fade start=0 end=100 time=1000 condition=Control.IsVisible(%d)' % self.img_gauge_arrow.getId() ), ( 'conditional', 'effect=fade start=100 end=0 time=300 condition=!Control.IsEnabled(%d)' % self.img_gauge_arrow.getId() )]) dlul_prog_textboxx = int((self.screenx / 3) - (200 / 2)) dlul_prog_textboxy = int((self.screeny / 3) - (50 / 2) + 170) self.dlul_prog_textbox = ControlLabel(dlul_prog_textboxx, dlul_prog_textboxy, 200, 50, label='', textColor='0xFFFFFFFF', font='font30', alignment=2 | 4) self.addControl(self.dlul_prog_textbox) elif function == 'visible': self.img_gauge.setEnabled(True) self.img_gauge.setVisible(True) self.img_gauge_arrow.setEnabled(True) self.img_gauge_arrow.setVisible(True) else: self.img_gauge.setEnabled(False) self.img_gauge.setVisible(False) self.img_gauge_arrow.setEnabled(False) self.img_gauge_arrow.setVisible(False) self.dlul_prog_textbox.setLabel('') def display_progress_bar(self, function='true'): if function == 'true': self.img_progress = ControlImage(340, 640, 600, 20, '', aspectRatio=0, colorDiffuse="0xFF00AACC") self.addControl(self.img_progress) self.img_progress.setVisible(False) self.img_progress.setImage(self.image_progress) self.img_progress.setAnimations([( 'conditional', 'effect=fade start=0 end=100 time=500 condition=Control.IsVisible(%d)' % self.img_progress.getId() ), ( 'conditional', 'effect=fade start=100 end=0 time=300 condition=!Control.IsEnabled(%d)' % self.img_progress.getId() )]) self.img_progress.setVisible(True) img_progressx = int((self.screenx / 3) - (200 / 2)) img_progressy = int((self.screeny / 3) - (50 / 2) + 270) self.please_wait_textbox = ControlLabel(img_progressx, img_progressy, 200, 50, label='Please wait...', textColor='0xFFFFFFFF', alignment=2 | 4) self.addControl(self.please_wait_textbox) elif function == 'visible': self.please_wait_textbox.setVisible(True) self.img_progress.setEnabled(True) self.img_progress.setVisible(True) else: self.please_wait_textbox.setVisible(False) self.img_progress.setEnabled(False) self.img_progress.setVisible(False) def display_results(self, function='true'): if function == 'true': self.img_results = ControlImage(932, 40, 320, 144, '', aspectRatio=0) self.addControl(self.img_results) self.img_results.setVisible(False) self.img_results.setImage(self.image_speedtestresults) self.img_results.setAnimations([( 'conditional', 'effect=fade start=100 end=0 time=300 delay=1000 condition=!Control.IsEnabled(%d)' % self.img_results.getId() )]) self.img_results.setVisible(True) self.ping_textbox = ControlLabel(955, 133, 75, 50, label='', textColor='0xFFFFFFFF') self.addControl(self.ping_textbox) self.dl_textbox = ControlLabel(1035, 133, 75, 50, label='', textColor='0xFFFFFFFF') self.addControl(self.dl_textbox) self.ul_textbox = ControlLabel(1153, 133, 75, 50, label='', textColor='0xFFFFFFFF') self.addControl(self.ul_textbox) elif function == 'visible': self.img_results.setEnabled(True) self.img_results.setVisible(True) else: self.img_results.setEnabled(False) self.dl_textbox.setLabel('') self.ul_textbox.setLabel('') self.ping_textbox.setLabel('') def show_end_result(self): self.img_final_results = ControlImage(932, 40, 320, 144, '', aspectRatio=0) self.addControl(self.img_final_results) self.img_final_results.setVisible(False) self.img_final_results.setEnabled(False) self.img_final_results.setImage(IMAGE_RESULT) self.img_final_results.setAnimations([( 'conditional', 'effect=fade start=0 end=100 time=1000 delay=100 condition=Control.IsVisible(%d)' % self.img_final_results.getId() ), ( 'conditional', 'effect=zoom end=175 start=100 center=%s time=2000 delay=3000 condition=Control.IsVisible(%d)' % ('auto', self.img_final_results.getId()) ), ( 'conditional', 'effect=slide end=-100,25 time=2000 delay=3000 tween=linear easing=in condition=Control.IsVisible(%d)' % self.img_final_results.getId() )]) self.img_final_results.setVisible(True) self.img_final_results.setEnabled(True) def show_end_result_sp(self): self.rec_speed = ControlTextBox(325, 475, 600, 300, textColor='0xFFFFFFFF') self.addControl(self.rec_speed) self.rec_speed.setVisible(False) self.rec_speed.setEnabled(False) self.rec_speed.setText('\n'.join([localize(30980), localize(30981), localize(30982), localize(30983), localize(30984), localize(30985)])) self.rec_speed.setAnimations([( 'conditional', 'effect=fade start=0 end=100 time=1000 delay=100 condition=Control.IsVisible(%d)' % self.rec_speed.getId() )]) self.rec_speed.setVisible(True) self.rec_speed.setEnabled(True) def onClick(self, control): # pylint: disable=invalid-name if control == self.button_run_id: self.display_button_run(False) self.display_results() self.display_progress_bar() self.display_ping_test() self.display_gauge_test() self.speedtest(share=True, simple=True) self.display_progress_bar(False) self.display_ping_test(False) self.display_gauge_test(False) self.display_results(False) self.show_end_result() self.show_end_result_sp() self.display_button_close('visible') if control == self.button_close_id: self.save_close() def save_close(self): self.close() def update_textbox(self, text): self.textbox.setText("\n".join(text)) def config_gauge(self, speed, last_speed=0, time=1000): if last_speed == 0: last_speed = 122 current_s = 0 if speed <= 1: current_s = 122 - float((float(speed) - float(0))) * float( (float(31) / float(1))) elif speed <= 2: current_s = 90 - float((float(speed) - float(1))) * float( (float(31) / float(1))) elif speed <= 3: current_s = 58 - float((float(speed) - float(2))) * float( (float(29) / float(1))) elif speed <= 5: current_s = 28 - float((float(speed) - float(3))) * float( (float(28) / float(2))) elif speed <= 10: current_s = float((float(speed) - float(5))) * float( (float(28) / float(5))) elif speed <= 20: current_s = 29 + float((float(speed) - float(10))) * float( (float(29) / float(10))) elif speed <= 30: current_s = 59 + float((float(speed) - float(20))) * float( (float(31) / float(10))) elif speed <= 50: current_s = 91 + float((float(speed) - float(30))) * float( (float(31) / float(20))) elif speed > 50: current_s = 122 speed_n = "%.0f" % float(current_s) if speed > 5: speed_n = '-' + str(speed_n) img_gauge_arrowx = (self.screenx / 3) - (66 / 2) + 28 img_gauge_arrowy = (self.screeny / 3) + (260 / 2) - 88 self.img_gauge_arrow.setAnimations([( 'conditional', 'effect=rotate start=%d end=%d center=%d,%d condition=Control.IsVisible(%d) time=%d' % ( int(last_speed), int(speed_n), img_gauge_arrowx, img_gauge_arrowy, self.img_gauge.getId(), time ) )]) return speed_n def download_speed(self, files, quiet=False): start = timeit.default_timer() def producer(queue, files): for filename in files: thread = FileGetter(filename, start) thread.start() queue.put(thread, True) if not quiet and not SHUTDOWN_EVENT.isSet(): sys.stdout.write('.') sys.stdout.flush() finished = [] def consumer(queue, total_files): speed_dl = 0 while len(finished) < total_files: thread = queue.get(True) while thread.isAlive(): thread.join(timeout=0.1) finished.append(sum(thread.result)) speed_f = ((sum(finished) / (timeit.default_timer() - start)) / 1000 / 1000) * 8 speed_dl = self.config_gauge(speed_f, speed_dl) self.dlul_prog_textbox.setLabel('%.02f Mbps' % speed_f) del thread queue = Queue(6) prod_thread = threading.Thread(target=producer, args=(queue, files)) cons_thread = threading.Thread(target=consumer, args=(queue, len(files))) start = timeit.default_timer() prod_thread.start() cons_thread.start() while prod_thread.isAlive(): prod_thread.join(timeout=0.1) while cons_thread.isAlive(): cons_thread.join(timeout=0.1) return sum(finished) / (timeit.default_timer() - start) def upload_speed(self, url, sizes, quiet=False): start = timeit.default_timer() def producer(queue, sizes): for size in sizes: thread = FilePutter(url, start, size) thread.start() queue.put(thread, True) if not quiet and not SHUTDOWN_EVENT.isSet(): sys.stdout.write('.') sys.stdout.flush() finished = [] def consumer(queue, total_sizes): speed_dl = 0 while len(finished) < total_sizes: thread = queue.get(True) while thread.isAlive(): thread.join(timeout=0.1) finished.append(thread.result) speed_f = ((sum(finished) / (timeit.default_timer() - start)) / 1000 / 1000) * 8 speed_dl = self.config_gauge(speed_f, speed_dl) self.dlul_prog_textbox.setLabel('%.02f Mbps' % speed_f) del thread queue = Queue(6) prod_thread = threading.Thread(target=producer, args=(queue, sizes)) cons_thread = threading.Thread(target=consumer, args=(queue, len(sizes))) start = timeit.default_timer() prod_thread.start() cons_thread.start() while prod_thread.isAlive(): prod_thread.join(timeout=0.1) while cons_thread.isAlive(): cons_thread.join(timeout=0.1) return sum(finished) / (timeit.default_timer() - start) def speedtest(self, share=False, simple=False, src=None, timeout=10): self.img_ping.setVisible(True) self.img_ping_glow.setVisible(True) start_st = [localize(30960)] # Running Speed Test add-on global SHUTDOWN_EVENT, SOURCE # pylint: disable=global-statement SHUTDOWN_EVENT = threading.Event() socket.setdefaulttimeout(timeout) if src: SOURCE = src socket.socket = bound_socket start_st.append(localize(30961)) # Retrieving speedtest.net configuration self.update_textbox(start_st) try: config = get_config() except URLError: return False start_st.append(localize(30962)) # Retrieving speedtest.net server list self.update_textbox(start_st) self.img_centertext.setImage(self.image_centertext_testingping) servers = closest_servers(config['client']) start_st.append(localize(30963, **config['client'])) # Testing from ISP self.update_textbox(start_st) best = get_best_server(servers) start_st.append(localize(30964)) # Selecting best server based on latency start_st.append(localize(30965, **best)) # Hosted by: {sponsor} start_st.append(localize(30966, **best)) # 'Host server: {host} start_st.append(localize(30967, **best)) # City, State: {name} start_st.append(localize(30968, **best)) # Country: {country} self.update_textbox(start_st) # km2mi = 0.62 # km = '%(d)0.2f ' % best # Distance = float(km) # miles = Distance * km2mi # start_st.append('Distance: %s mi' % miles) start_st.append(localize(30969, **best)) # Distance: {d} start_st.append(localize(30970, **best)) # Ping: {latency} self.update_textbox(start_st) self.ping_textbox.setLabel("%.0f" % float(best['latency'])) self.img_centertext.setImage(' ') self.img_ping.setEnabled(False) self.img_ping_glow.setEnabled(False) sizes = [350, 500, 750, 1000, 1500, 2000, 2500, 3000, 3500, 4000] urls = [] for size in sizes: for _ in range(0, 4): urls.append('%s/random%sx%s.jpg' % (os.path.dirname(best['url']), size, size)) self.img_gauge.setVisible(True) Monitor().waitForAbort(1) self.config_gauge(0) self.img_gauge_arrow.setVisible(True) start_st.append(localize(30971)) # Testing download speed... self.update_textbox(start_st) dlspeed = self.download_speed(urls, simple) start_st[-1] = localize(30972, speed=dlspeed * 8 / 1000 / 1000) # Download speed self.update_textbox(start_st) self.dl_textbox.setLabel('%0.2f' % float(dlspeed * 8 / 1000 / 1000)) sizesizes = [int(.25 * 1000 * 1000), int(.5 * 1000 * 1000)] sizes = [] for size in sizesizes: for _ in range(0, 25): sizes.append(size) start_st.append(localize(30973)) # Testing upload speed... self.update_textbox(start_st) ulspeed = self.upload_speed(best['url'], sizes, simple) start_st[-1] = localize(30974, speed=ulspeed * 8 / 1000 / 1000) # Upload speed self.update_textbox(start_st) self.ul_textbox.setLabel('%.2f' % float(ulspeed * 8 / 1000 / 1000)) self.config_gauge(0, ulspeed * 8 / 1000 / 1000, time=3000) Monitor().waitForAbort(2) if share: dlspeedk = int(round(dlspeed * 8 / 1000, 0)) ping = int(round(best['latency'], 0)) ulspeedk = int(round(ulspeed * 8 / 1000, 0)) api_data = [ 'download=%s' % dlspeedk, 'ping=%s' % ping, 'upload=%s' % ulspeedk, 'promo=', 'startmode=%s' % 'pingselect', 'recommendedserverid=%s' % best['id'], 'accuracy=%s' % 1, 'serverid=%s' % best['id'], 'hash=%s' % md5(('%s-%s-%s-%s' % (ping, ulspeedk, dlspeedk, '297aae72')).encode()).hexdigest()] headers = {'Referer': 'https://c.speedtest.net/flash/speedtest.swf'} request = build_request('https://www.speedtest.net/api/api.php', data='&'.join(api_data).encode(), headers=headers) fdesc = catch_request(request) if fdesc is False: log(0, 'Could not submit results to speedtest.net') return False response = fdesc.read() code = fdesc.code fdesc.close() if int(code) != 200: log(0, 'Could not submit results to speedtest.net') return False qsargs = parse_qs(response.decode()) # pylint: disable=deprecated-method resultid = qsargs.get('resultid') if not resultid or len(resultid) != 1: log(0, 'Could not submit results to speedtest.net') return False global IMAGE_RESULT # pylint: disable=global-statement IMAGE_RESULT = 'https://www.speedtest.net/result/%s.png' % resultid[0] return True
class ScreensaverBase(object): MODE = None IMAGE_CONTROL_COUNT = 10 FAST_IMAGE_COUNT = 0 NEXT_IMAGE_TIME = 2000 BACKGROUND_IMAGE = 'black.jpg' 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'))) self.loading_control = ControlImage(576, 296, 128, 128, loading_img) self.preload_control = ControlImage(-1, -1, 1, 1, '') self.background_control = ControlImage(0, 0, 1280, 720, '') self.global_controls = [ self.preload_control, self.background_control, self.loading_control ] self.xbmc_window.addControls(self.global_controls) self.log('init_global_controls end') def load_settings(self): pass 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=1) 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 addon.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') self.image_aspect_ratio = 16.0 / 9.0 source = SOURCES[int(addon.getSetting('source'))] prop = PROPS[int(addon.getSetting('prop'))] images = [] if source == 'movies': images = self._get_json_images('VideoLibrary.GetMovies', 'movies', prop) elif source == 'albums': images = self._get_json_images('AudioLibrary.GetAlbums', 'albums', prop) elif source == 'shows': images = self._get_json_images('VideoLibrary.GetTVShows', 'tvshows', prop) elif source == 'image_folder': path = addon.getSetting('image_path') if path: images = self._get_folder_images(path) if not images: cmd = 'XBMC.Notification("{header}", "{message}")'.format( header=addon.getLocalizedString(32500), message=addon.getLocalizedString(32501)) xbmc.executebuiltin(cmd) images = (self._get_json_images('VideoLibrary.GetMovies', 'movies', 'fanart') or self._get_json_images('AudioLibrary.GetArtists', 'artists', 'fanart')) if not images: raise NoImagesException return images def _get_json_images(self, method, key, prop): self.log('_get_json_images start') query = { 'jsonrpc': '2.0', 'id': 0, 'method': method, 'params': { 'properties': [prop], } } response = json.loads(xbmc.executeJSONRPC(json.dumps(query))) images = [ element[prop] for element in response.get('result', {}).get(key, []) if element.get(prop) ] self.log('_get_json_images end') return images def _get_folder_images(self, path): self.log('_get_folder_images started with path: %s' % repr(path)) dirs, files = xbmcvfs.listdir(path) pathtocheck = path.rstrip('/') images = [ xbmc.validatePath(pathtocheck + '/' + f) for f in files if f.lower()[-3:] in ('jpg', 'png') ] if addon.getSetting('recursive') == 'true': for directory in dirs: if directory.startswith('.'): continue images.extend( self._get_folder_images( xbmc.validatePath('/'.join((path, directory, ''))))) self.log('_get_folder_images ends') return images 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.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): xbmc.log(u'%s: %s' % (ADDON_NAME, msg))
class ScreensaverBase(object): MODE = None IMAGE_CONTROL_COUNT = 10 FAST_IMAGE_COUNT = 0 NEXT_IMAGE_TIME = 2000 BACKGROUND_IMAGE = 'srr_blackbg.jpg' pause_requested = False info_requested = False def __init__(self, thread_event, image_queue): #self.log('__init__ start') self.exit_requested = False self.toggle_info_display_requested = False self.background_control = None self.preload_control = None self.image_count = 0 #self.image_controls = [] self.tni_controls = [] self.global_controls = [] self.exit_monitor = ExitMonitor(self.stop) self.init_xbmc_window() # 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_xbmc_window(self): self.xbmc_window = ScreensaverXMLWindow( "slideshow02.xml", addon_path, defaultSkin='Default', exit_callback=self.action_id_handler) self.xbmc_window.show() def init_global_controls(self): #self.log(' init_global_controls start') loading_img = xbmc.validatePath('/'.join( (ADDON_PATH, 'resources', 'skins', 'Default', 'media', 'srr_busy.gif'))) self.loading_control = ControlImage(576, 296, 128, 128, loading_img) self.preload_control = ControlImage(-1, -1, 1, 1, '') self.background_control = ControlImage(0, 0, 1280, 720, '') self.global_controls = [ self.preload_control, self.background_control, self.loading_control ] self.xbmc_window.addControls(self.global_controls) #self.log(' init_global_controls end') def load_settings(self): pass def init_cycle_controls(self): #self.log(' init_cycle_controls start') for _ in xrange(self.IMAGE_CONTROL_COUNT): img_control = ControlImage( 0, 0, 0, 0, '', aspectRatio=2 ) #(values 0 = stretch (default), 1 = scale up (crops), 2 = scale down (black bars) txt_control = ControlTextBox(0, 0, 0, 0, font='font16') # xbfont_left = 0x00000000 # xbfont_right = 0x00000001 # xbfont_center_x = 0x00000002 # xbfont_center_y = 0x00000004 # xbfont_truncated = 0x00000008 #ControlLabel(x, y, width, height, label, font=None, textColor=None, disabledColor=None, alignment=0, hasPath=False, angle=0) #txt_control = ControlLabel(0, 0, 0, 0, '', font='font30', textColor='', disabledColor='', alignment=6, hasPath=False, angle=0) #self.image_controls.append(img_control) self.tni_controls.append([txt_control, 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.xbmc_window.addControls(self.text_controls) self.xbmc_window.addControls(self.tni_controls[1]) self.xbmc_window.addControls(self.tni_controls[0]) #self.log('stack_cycle_controls end') def start_loop(self): self.log('start_loop start') #images = self.get_images('q') desc_and_images = self.get_description_and_images('q') if random_image_order: #addon.getSetting('random_image_order') == 'true': random.shuffle(desc_and_images) desc_and_images_cycle = cycle(desc_and_images) #image_url_cycle = cycle(images) #image_controls_cycle = cycle(self.image_controls) tni_controls_cycle = cycle(self.tni_controls) #self.log(' image_url_cycle %s' % image_url_cycle) self.hide_loading_indicator() #pops the first one #image_url = image_url_cycle.next() desc_and_image = desc_and_images_cycle.next() #self.log(' image_url_cycle.next %s' % image_url) #get the current screen saver value #saver_mode = json.loads( xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "id": 0, "method": "Settings.getSettingValue", "params": {"setting":"screensaver.mode" } }') ) #saver_mode = saver_mode.get('result').get('value') #log('****screensavermode=' + repr(saver_mode) ) #set the screensaver to none #xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "id": 0, "method":"Settings.setSettingValue", "params": {"setting":"screensaver.mode", "value":""} } ' ) while not self.exit_requested: self.log(' using image: %s ' % (repr(desc_and_image))) if not self.pause_requested: #pops an image control #image_control = image_controls_cycle.next() tni_control = tni_controls_cycle.next() #process_image done by subclass( assign animation and stuff to image control ) #self.process_image(image_control, image_url) #self.process_image(image_control, desc_and_image) self.process_image(tni_control, desc_and_image) #image_url = image_url_cycle.next() desc_and_image = desc_and_images_cycle.next() #self.wait() if self.image_count < self.FAST_IMAGE_COUNT: self.image_count += 1 else: #self.preload_image(image_url) self.preload_image(desc_and_image[1]) self.wait() self.log('start_loop end') #return the screensaver back #xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "id": 0, "method":"Settings.setSettingValue", "params": {"setting":"screensaver.mode", "value" : "%s"} }' % saver_mode ) def get_description_and_images(self, source): #self.log('get_images2') self.image_aspect_ratio = 16.0 / 9.0 images = [] if source == 'image_folder': #image folder source not used path = '' #SlideshowCacheFolder #addon.getSetting('image_path') if path: images = self._get_folder_images(path) elif source == 'q': #implement width & height extract here. #images=[[item[0], item[1],item[2], item[3], ] for item in q.queue] #[title,media_url, width, height, len(entries), description]) images = [[ i.get('li_label'), i.get('DirectoryItem_url'), i.get('width'), i.get('height'), i.get('description') ] for i in q.queue] log("queue size:%d" % q.qsize()) #texts=[item[0] for item in q.queue] #for i in images: self.log(' image: %s' %i) #self.log(' %d images' % len(images)) return images #for movie, audio or tv shows def _get_folder_images(self, path): self.log('_get_folder_images started with path: %s' % repr(path)) _, files = xbmcvfs.listdir(path) images = [ xbmc.validatePath(path + f) for f in files if f.lower()[-3:] in ('jpg', 'png') ] #if addon.getSetting('recursive') == 'true': # for directory in dirs: # if directory.startswith('.'): # continue # images.extend( # self._get_folder_images( # xbmc.validatePath('/'.join((path, directory, ''))) # ) # ) self.log('_get_folder_images ends') return images def hide_loading_indicator(self): bg_img = xbmc.validatePath('/'.join( (ADDON_PATH, 'resources', 'skins', 'Default', 'media', self.BACKGROUND_IMAGE))) #bg_img = 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.background_control.setImage(bg_img) def process_image(self, image_control, desc_and_image): # 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 self.toggle_info_display_requested: #this value is set on specific keypress in action_id_handler #self.log('toggle_info_display_requested') self.toggle_info_display_requested = False self.toggle_info_display_handler() 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 action_id_handler(self, action_id): #log(' action ID:' + str(action_id) ) if action_id in ACTION_IDS_EXIT: #self.exit_callback() self.stop() if action_id in ACTION_IDS_PAUSE: self.pause() if action_id == 11: #xbmcgui.ACTION_SHOW_INFO: self.toggle_info_display_requested = True #not self.info_requested def toggle_info_display_handler(self): pass def stop(self, action_id=0): self.log('stop') self.exit_requested = True self.exit_monitor = None def pause(self): #pause disabled. too complicated(not possible?) to stop animation #self.pause_requested = not self.pause_requested #self.log('pause %s' %self.pause_requested ) pass def close(self): self.del_controls() def del_controls(self): #self.log('del_controls start') #self.xbmc_window.removeControls(self.img_controls) try: self.xbmc_window.removeControls( self.tni_controls[0]) #imageControls except: pass try: self.xbmc_window.removeControls(self.tni_controls[1]) #textBoxes except: pass self.xbmc_window.removeControls(self.global_controls) self.preload_control = None self.background_control = None self.loading_control = None self.tni_controls = [] self.global_controls = [] self.xbmc_window.close() self.xbmc_window = None #self.log('del_controls end') def log(self, msg): log(u'slideshow: %s' % msg)
class ScreensaverBase(object): MODE = None IMAGE_CONTROL_COUNT = 10 FAST_IMAGE_COUNT = 0 NEXT_IMAGE_TIME = 2000 BACKGROUND_IMAGE = 'srr_blackbg.jpg' pause_requested=False info_requested=False def __init__(self, thread_event, image_queue): #self.log('__init__ start') self.exit_requested = False self.toggle_info_display_requested=False self.background_control = None self.preload_control = None self.image_count = 0 #self.image_controls = [] self.tni_controls = [] self.global_controls = [] self.exit_monitor = ExitMonitor(self.stop) self.init_xbmc_window() # 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_xbmc_window(self): self.xbmc_window = ScreensaverXMLWindow( "slideshow02.xml", addon_path, defaultSkin='Default', exit_callback=self.action_id_handler ) self.xbmc_window.show() def init_global_controls(self): #self.log(' init_global_controls start') loading_img = xbmc.validatePath('/'.join((ADDON_PATH, 'resources', 'skins', 'Default', 'media', 'srr_busy.gif' ))) self.loading_control = ControlImage(576, 296, 128, 128, loading_img) self.preload_control = ControlImage(-1, -1, 1, 1, '') self.background_control = ControlImage(0, 0, 1280, 720, '') self.global_controls = [ self.preload_control, self.background_control, self.loading_control ] self.xbmc_window.addControls(self.global_controls) #self.log(' init_global_controls end') def load_settings(self): pass def init_cycle_controls(self): #self.log(' init_cycle_controls start') for _ in xrange(self.IMAGE_CONTROL_COUNT): img_control = ControlImage(0, 0, 0, 0, '', aspectRatio=2) #(values 0 = stretch (default), 1 = scale up (crops), 2 = scale down (black bars) txt_control = ControlTextBox(0, 0, 0, 0, font='font16') # xbfont_left = 0x00000000 # xbfont_right = 0x00000001 # xbfont_center_x = 0x00000002 # xbfont_center_y = 0x00000004 # xbfont_truncated = 0x00000008 #ControlLabel(x, y, width, height, label, font=None, textColor=None, disabledColor=None, alignment=0, hasPath=False, angle=0) #txt_control = ControlLabel(0, 0, 0, 0, '', font='font30', textColor='', disabledColor='', alignment=6, hasPath=False, angle=0) #self.image_controls.append(img_control) self.tni_controls.append([txt_control,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.xbmc_window.addControls(self.text_controls) self.xbmc_window.addControls(self.tni_controls[1]) self.xbmc_window.addControls(self.tni_controls[0]) #self.log('stack_cycle_controls end') def start_loop(self): self.log('start_loop start') #images = self.get_images('q') desc_and_images = self.get_description_and_images('q') if random_image_order: #addon.getSetting('random_image_order') == 'true': random.shuffle(desc_and_images) desc_and_images_cycle=cycle(desc_and_images) #image_url_cycle = cycle(images) #image_controls_cycle = cycle(self.image_controls) tni_controls_cycle= cycle(self.tni_controls) #self.log(' image_url_cycle %s' % image_url_cycle) self.hide_loading_indicator() #pops the first one #image_url = image_url_cycle.next() desc_and_image=desc_and_images_cycle.next() #self.log(' image_url_cycle.next %s' % image_url) #get the current screen saver value #saver_mode = json.loads( xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "id": 0, "method": "Settings.getSettingValue", "params": {"setting":"screensaver.mode" } }') ) #saver_mode = saver_mode.get('result').get('value') #log('****screensavermode=' + repr(saver_mode) ) #set the screensaver to none #xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "id": 0, "method":"Settings.setSettingValue", "params": {"setting":"screensaver.mode", "value":""} } ' ) while not self.exit_requested: self.log(' using image: %s ' % ( repr(desc_and_image ) ) ) if not self.pause_requested: #pops an image control #image_control = image_controls_cycle.next() tni_control = tni_controls_cycle.next() #process_image done by subclass( assign animation and stuff to image control ) #self.process_image(image_control, image_url) #self.process_image(image_control, desc_and_image) self.process_image(tni_control, desc_and_image) #image_url = image_url_cycle.next() desc_and_image=desc_and_images_cycle.next() #self.wait() if self.image_count < self.FAST_IMAGE_COUNT: self.image_count += 1 else: #self.preload_image(image_url) self.preload_image(desc_and_image[1]) self.wait() self.log('start_loop end') #return the screensaver back #xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "id": 0, "method":"Settings.setSettingValue", "params": {"setting":"screensaver.mode", "value" : "%s"} }' % saver_mode ) def get_description_and_images(self, source): #self.log('get_images2') self.image_aspect_ratio = 16.0 / 9.0 images = [] if source == 'image_folder': #image folder source not used path = '' #SlideshowCacheFolder #addon.getSetting('image_path') if path: images = self._get_folder_images(path) elif source == 'q': #implement width & height extract here. #images=[[item[0], item[1],item[2], item[3], ] for item in q.queue] #[title,media_url, width, height, len(entries), description]) images=[ [i.get('li_label'), i.get('DirectoryItem_url'),i.get('width'), i.get('height'), i.get('description') ] for i in q.queue] log( "queue size:%d" %q.qsize() ) #texts=[item[0] for item in q.queue] #for i in images: self.log(' image: %s' %i) #self.log(' %d images' % len(images)) return images #for movie, audio or tv shows def _get_folder_images(self, path): self.log('_get_folder_images started with path: %s' % repr(path)) _, files = xbmcvfs.listdir(path) images = [ xbmc.validatePath(path + f) for f in files if f.lower()[-3:] in ('jpg', 'png') ] #if addon.getSetting('recursive') == 'true': # for directory in dirs: # if directory.startswith('.'): # continue # images.extend( # self._get_folder_images( # xbmc.validatePath('/'.join((path, directory, ''))) # ) # ) self.log('_get_folder_images ends') return images def hide_loading_indicator(self): bg_img = xbmc.validatePath('/'.join(( ADDON_PATH, 'resources', 'skins', 'Default', 'media', self.BACKGROUND_IMAGE ))) #bg_img = 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.background_control.setImage(bg_img) def process_image(self, image_control, desc_and_image): # 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 self.toggle_info_display_requested: #this value is set on specific keypress in action_id_handler #self.log('toggle_info_display_requested') self.toggle_info_display_requested=False self.toggle_info_display_handler() 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 action_id_handler(self,action_id): #log(' action ID:' + str(action_id) ) if action_id in ACTION_IDS_EXIT: #self.exit_callback() self.stop() if action_id in ACTION_IDS_PAUSE: self.pause() if action_id == 11: #xbmcgui.ACTION_SHOW_INFO: self.toggle_info_display_requested=True #not self.info_requested def toggle_info_display_handler(self): pass def stop(self,action_id=0): self.log('stop') self.exit_requested = True self.exit_monitor = None def pause(self): #pause disabled. too complicated(not possible?) to stop animation #self.pause_requested = not self.pause_requested #self.log('pause %s' %self.pause_requested ) pass def close(self): self.del_controls() def del_controls(self): #self.log('del_controls start') #self.xbmc_window.removeControls(self.img_controls) try: self.xbmc_window.removeControls(self.tni_controls[0]) #imageControls except: pass try: self.xbmc_window.removeControls(self.tni_controls[1]) #textBoxes except: pass self.xbmc_window.removeControls(self.global_controls) self.preload_control = None self.background_control = None self.loading_control = None self.tni_controls = [] self.global_controls = [] self.xbmc_window.close() self.xbmc_window = None #self.log('del_controls end') def log(self, msg): log(u'slideshow: %s' % msg)
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)
class ScreensaverBase(object): MODE = None IMAGE_CONTROL_COUNT = 10 FAST_IMAGE_COUNT = 0 NEXT_IMAGE_TIME = 2000 BACKGROUND_IMAGE = 'black.jpg' 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' ))) self.loading_control = ControlImage(576, 296, 128, 128, loading_img) self.preload_control = ControlImage(-1, -1, 1, 1, '') self.background_control = ControlImage(0, 0, 1280, 720, '') self.global_controls = [ self.preload_control, self.background_control, self.loading_control ] self.xbmc_window.addControls(self.global_controls) self.log('init_global_controls end') def load_settings(self): pass 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=1) 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 addon.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') self.image_aspect_ratio = 16.0 / 9.0 source = SOURCES[int(addon.getSetting('source'))] prop = PROPS[int(addon.getSetting('prop'))] images = [] if source == 'movies': images = self._get_json_images('VideoLibrary.GetMovies', 'movies', prop) elif source == 'albums': images = self._get_json_images('AudioLibrary.GetAlbums', 'albums', prop) elif source == 'shows': images = self._get_json_images('VideoLibrary.GetTVShows', 'tvshows', prop) elif source == 'image_folder': path = addon.getSetting('image_path') if path: images = self._get_folder_images(path) if not images: cmd = 'XBMC.Notification("{header}", "{message}")'.format( header=addon.getLocalizedString(32500), message=addon.getLocalizedString(32501) ) xbmc.executebuiltin(cmd) images = ( self._get_json_images('VideoLibrary.GetMovies', 'movies', 'fanart') or self._get_json_images('AudioLibrary.GetArtists', 'artists', 'fanart') ) return images def _get_json_images(self, method, key, prop): self.log('_get_json_images start') query = { 'jsonrpc': '2.0', 'id': 0, 'method': method, 'params': { 'properties': [prop], } } response = json.loads(xbmc.executeJSONRPC(json.dumps(query))) images = [ element[prop] for element in response.get('result', {}).get(key, []) if element.get(prop) ] self.log('_get_json_images end') return images def _get_folder_images(self, path): self.log('_get_folder_images started with path: %s' % repr(path)) dirs, files = xbmcvfs.listdir(path) images = [ xbmc.validatePath(path + f) for f in files if f.lower()[-3:] in ('jpg', 'png') ] if addon.getSetting('recursive') == 'true': for directory in dirs: if directory.startswith('.'): continue images.extend( self._get_folder_images( xbmc.validatePath('/'.join((path, directory, ''))) ) ) self.log('_get_folder_images ends') return images 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.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): xbmc.log(u'%s: %s' % (ADDON_NAME, msg))
class ScreensaverBase(object): MODE = None IMAGE_CONTROL_COUNT = 10 FAST_IMAGE_COUNT = 0 NEXT_IMAGE_TIME = 2000 BACKGROUND_IMAGE = 'srr_blackbg.jpg' image_control_ids=[101,102,103,104,105] #control id's defined in ScreensaverXMLWindow xml file pause_requested=False info_requested=False #image_controls_cycle='' def __init__(self, thread_event, facts_queue, worker_thread): #self.log('__init__ start') self.exit_requested = False self.background_control = None self.preload_control = None self.image_count = 0 #self.image_controls = [] #self.tni_controls = [] self.global_controls = [] self.exit_monitor = ExitMonitor(self.stop) self.facts_queue=facts_queue self.worker_thread=worker_thread self.init_xbmc_window() self.init_global_controls() self.load_settings() self.init_cycle_controls() self.stack_cycle_controls() #self.log('__init__ end') def init_xbmc_window(self): self.xbmc_window = ScreensaverXMLWindow( "slideshow02.xml", ADDON_PATH, defaultSkin='Default', exit_callback=self.action_id_handler ) self.xbmc_window.setCoordinateResolution(5) self.xbmc_window.show() def init_global_controls(self): #self.log(' init_global_controls start') loading_img = xbmc.validatePath('/'.join((ADDON_PATH, 'resources', 'skins', 'Default', 'media', 'srr_busy.gif' ))) self.loading_control = ControlImage(576, 296, 128, 128, loading_img) self.preload_control = ControlImage(-1, -1, 1, 1, '') self.background_control = ControlImage(0, 0, 1280, 720, '') self.global_controls = [ self.preload_control, self.background_control, self.loading_control ] self.xbmc_window.addControls(self.global_controls) #self.log(' init_global_controls end') def load_settings(self): pass 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) #(values 0 = stretch (default), 1 = scale up (crops), 2 = scale down (black bars) # txt_control = ControlTextBox(0, 0, 0, 0, font='font16') # xbfont_left = 0x00000000 # xbfont_right = 0x00000001 # xbfont_center_x = 0x00000002 # xbfont_center_y = 0x00000004 # xbfont_truncated = 0x00000008 #ControlLabel(x, y, width, height, label, font=None, textColor=None, disabledColor=None, alignment=0, hasPath=False, angle=0) #txt_control = ControlLabel(0, 0, 0, 0, '', font='font30', textColor='', disabledColor='', alignment=6, hasPath=False, angle=0) #self.image_controls.append(img_control) # self.tni_controls.append([txt_control,img_control]) #self.log(' init_cycle_controls end') pass 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.xbmc_window.addControls(self.text_controls) #self.xbmc_window.addControls(self.tni_controls[1]) #self.xbmc_window.addControls(self.tni_controls[0]) #self.log('stack_cycle_controls end') pass def start_loop(self): self.log('screensaver start_loop') #tni_controls_cycle= cycle(self.tni_controls) self.image_controls_cycle= cycle(self.image_control_ids) self.hide_loading_indicator() #pops the first one #self.log('get queue item') #factlet=self.facts_queue.get(block=True,timeout=5000) log(' initial start: queue %d' %(self.facts_queue.qsize()) ) factlet=self.facts_queue.get() #self.log(' image_url_cycle.next %s' % image_url) while not self.exit_requested: #self.log(' using image: %s ' % ( repr(factlet) ) ) self.log( ' using:' + pprint.pformat(factlet, indent=1) ) #pops an image control image_control = self.image_controls_cycle.next() #if factlet: self.process_image(image_control, factlet) try: #if self.facts_queue.empty(): # self.wait() # log(' queue empty %d' %(self.facts_queue.qsize()) ) #else: factlet=self.facts_queue.get() #log(' got next item from queue ' + factlet['name']) #factlet=self.facts_queue.get(block=True,timeout=5000) #doesn't throw exception if empty! except Queue.Empty: self.log(' queue empty thrown') self.wait() self.wait() if self.image_count < self.FAST_IMAGE_COUNT: self.image_count += 1 else: #self.preload_image(image_url) self.preload_image(factlet['image']) self.wait() self.log('start_loop end') #return the screensaver back #xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "id": 0, "method":"Settings.setSettingValue", "params": {"setting":"screensaver.mode", "value" : "%s"} }' % saver_mode ) def get_description_and_images(self, source): #self.log('get_images2') self.image_aspect_ratio = 16.0 / 9.0 images = [] if source == 'image_folder': path = SlideshowCacheFolder #addon.getSetting('image_path') if path: images = self._get_folder_images(path) elif source == 'q': #implement width & height extract here. images=[[item[0], item[1],item[2], item[3], ] for item in self.facts_queue.queue] #texts=[item[0] for item in q.queue] #for i in images: self.log(' image: %s' %i) #self.log(' %d images' % len(images)) return images #for movie, audio or tv shows def _get_json_images(self, method, key, prop): self.log('_get_json_images start') query = { 'jsonrpc': '2.0', 'id': 0, 'method': method, 'params': { 'properties': [prop], } } response = json.loads(xbmc.executeJSONRPC(json.dumps(query))) images = [ element[prop] for element in response.get('result', {}).get(key, []) if element.get(prop) ] self.log('_get_json_images end') return images def _get_folder_images(self, path): self.log('_get_folder_images started with path: %s' % repr(path)) dirs, files = xbmcvfs.listdir(path) images = [ xbmc.validatePath(path + f) for f in files if f.lower()[-3:] in ('jpg', 'png') ] #if addon.getSetting('recursive') == 'true': # for directory in dirs: # if directory.startswith('.'): # continue # images.extend( # self._get_folder_images( # xbmc.validatePath('/'.join((path, directory, ''))) # ) # ) self.log('_get_folder_images ends') return images def hide_loading_indicator(self): bg_img = xbmc.validatePath('/'.join(( ADDON_PATH, 'resources', 'skins', 'Default', 'media', self.BACKGROUND_IMAGE ))) #bg_img = 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.background_control.setImage(bg_img) def process_image(self, image_control_id, 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, msec=0): # wait in chunks of 500ms to react earlier on exit request chunk_wait_time = int(CHUNK_WAIT_TIME) remaining_wait_time = msec if msec > 0 else int(self.NEXT_IMAGE_TIME) #self.log('waiting for %d' %remaining_wait_time ) while remaining_wait_time > 0: #self.log('waiting %d' %remaining_wait_time ) if not self.worker_thread.isAlive(): self.log('worker thread died') self.exit_requested=True 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 action_id_handler(self,action_id): #log(' action ID:' + str(action_id) ) if action_id in ACTION_IDS_EXIT: #self.exit_callback() self.stop() if action_id in ACTION_IDS_PAUSE: self.pause() if action_id == 11: #xbmcgui.ACTION_SHOW_INFO: self.info_requested=not self.info_requested def stop(self,action_id=0): self.log('stop') self.exit_requested = True self.exit_monitor = None def pause(self): #pause disabled. too complicated(not possible?) to stop animation #self.pause_requested = not self.pause_requested #self.log('pause %s' %self.pause_requested ) pass def close(self): self.log('close') self.del_controls() def del_controls(self): #self.log('del_controls start') #self.xbmc_window.removeControls(self.img_controls) #try: self.xbmc_window.removeControls(self.tni_controls[0]) #imageControls #except: pass #try: self.xbmc_window.removeControls(self.tni_controls[1]) #textBoxes #except: pass self.xbmc_window.removeControls(self.global_controls) self.preload_control = None self.background_control = None self.loading_control = None #self.tni_controls = [] self.global_controls = [] self.xbmc_window.close() self.xbmc_window = None #self.log('del_controls end') def log(self, msg): log(u'slideshow: %s' % msg)
class ScreensaverBase(object): MODE = None IMAGE_CONTROL_COUNT = 10 FAST_IMAGE_COUNT = 0 NEXT_IMAGE_TIME = 2000 BACKGROUND_IMAGE = 'srr_blackbg.jpg' pause_requested=False info_requested=False def __init__(self, thread_event, image_queue): self.exit_requested = False self.toggle_info_display_requested=False self.background_control = None self.preload_control = None self.image_count = 0 self.tni_controls = [] self.global_controls = [] self.exit_monitor = ExitMonitor(self.stop) self.init_xbmc_window() self.init_global_controls() self.load_settings() self.init_cycle_controls() self.stack_cycle_controls() def init_xbmc_window(self): self.xbmc_window = ScreensaverXMLWindow( "slideshow02.xml", addon_path, defaultSkin='Default', exit_callback=self.action_id_handler ) self.xbmc_window.show() def init_global_controls(self): loading_img = xbmc.validatePath('/'.join((ADDON_PATH, 'resources', 'skins', 'Default', 'media', 'srr_busy.gif' ))) self.loading_control = ControlImage(576, 296, 128, 128, loading_img) self.preload_control = ControlImage(-1, -1, 1, 1, '') self.background_control = ControlImage(0, 0, 1280, 720, '') self.global_controls = [ self.preload_control, self.background_control, self.loading_control ] self.xbmc_window.addControls(self.global_controls) def load_settings(self): pass def init_cycle_controls(self): for _ in xrange(self.IMAGE_CONTROL_COUNT): img_control = ControlImage(0, 0, 0, 0, '', aspectRatio=2) #(values 0 = stretch (default), 1 = scale up (crops), 2 = scale down (black bars) txt_control = ControlTextBox(0, 0, 0, 0, font='font16') self.tni_controls.append([txt_control,img_control]) def stack_cycle_controls(self): self.xbmc_window.addControls(self.tni_controls[1]) self.xbmc_window.addControls(self.tni_controls[0]) def start_loop(self): self.log('start_loop start') desc_and_images = self.get_description_and_images('q') if random_image_order: #addon.getSetting('random_image_order') == 'true': random.shuffle(desc_and_images) desc_and_images_cycle=cycle(desc_and_images) tni_controls_cycle= cycle(self.tni_controls) self.hide_loading_indicator() desc_and_image=desc_and_images_cycle.next() while not self.exit_requested: self.log(' using image: %s ' % ( repr(desc_and_image ) ) ) if not self.pause_requested: tni_control = tni_controls_cycle.next() self.process_image(tni_control, desc_and_image) desc_and_image=desc_and_images_cycle.next() if self.image_count < self.FAST_IMAGE_COUNT: self.image_count += 1 else: self.preload_image(desc_and_image[1]) self.wait() self.log('start_loop end') def get_description_and_images(self, source): self.image_aspect_ratio = 16.0 / 9.0 images = [] if source == 'image_folder': path = '' #SlideshowCacheFolder #addon.getSetting('image_path') if path: images = self._get_folder_images(path) elif source == 'q': images=[ [i.get('li_label'), i.get('DirectoryItem_url'),i.get('width'), i.get('height'), i.get('description') ] for i in q.queue] log( "queue size:%d" %q.qsize() ) return images def _get_folder_images(self, path): self.log('_get_folder_images started with path: %s' % repr(path)) _, files = xbmcvfs.listdir(path) images = [ xbmc.validatePath(path + f) for f in files if f.lower()[-3:] in ('jpg', 'png') ] self.log('_get_folder_images ends') return images def hide_loading_indicator(self): bg_img = xbmc.validatePath('/'.join(( ADDON_PATH, 'resources', 'skins', 'Default', '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.background_control.setImage(bg_img) def process_image(self, image_control, desc_and_image): raise NotImplementedError def preload_image(self, image_url): self.preload_control.setImage(image_url) def wait(self): 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 self.toggle_info_display_requested: #this value is set on specific keypress in action_id_handler self.toggle_info_display_requested=False self.toggle_info_display_handler() 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 action_id_handler(self,action_id): if action_id in ACTION_IDS_EXIT: self.stop() if action_id in ACTION_IDS_PAUSE: self.pause() if action_id == 11: #xbmcgui.ACTION_SHOW_INFO: self.toggle_info_display_requested=True #not self.info_requested def toggle_info_display_handler(self): pass def stop(self,action_id=0): self.log('stop') self.exit_requested = True self.exit_monitor = None def pause(self): pass def close(self): self.del_controls() def del_controls(self): try: self.xbmc_window.removeControls(self.tni_controls[0]) #imageControls except: pass try: self.xbmc_window.removeControls(self.tni_controls[1]) #textBoxes except: pass self.xbmc_window.removeControls(self.global_controls) self.preload_control = None self.background_control = None self.loading_control = None self.tni_controls = [] self.global_controls = [] self.xbmc_window.close() self.xbmc_window = None def log(self, msg): log(u'slideshow: %s' % msg)
class ScreensaverBase(object): MODE = None IMAGE_CONTROL_COUNT = 10 FAST_IMAGE_COUNT = 0 NEXT_IMAGE_TIME = 2000 BACKGROUND_IMAGE = 'srr_blackbg.jpg' pause_requested = False info_requested = False def __init__(self, thread_event, image_queue): self.exit_requested = False self.toggle_info_display_requested = False self.background_control = None self.preload_control = None self.image_count = 0 self.tni_controls = [] self.global_controls = [] self.exit_monitor = ExitMonitor(self.stop) self.init_xbmc_window() self.init_global_controls() self.load_settings() self.init_cycle_controls() self.stack_cycle_controls() def init_xbmc_window(self): self.xbmc_window = ScreensaverXMLWindow( "slideshow02.xml", addon_path, defaultSkin='Default', exit_callback=self.action_id_handler) self.xbmc_window.show() def init_global_controls(self): loading_img = xbmc.validatePath('/'.join( (ADDON_PATH, 'resources', 'skins', 'Default', 'media', 'srr_busy.gif'))) self.loading_control = ControlImage(576, 296, 128, 128, loading_img) self.preload_control = ControlImage(-1, -1, 1, 1, '') self.background_control = ControlImage(0, 0, 1280, 720, '') self.global_controls = [ self.preload_control, self.background_control, self.loading_control ] self.xbmc_window.addControls(self.global_controls) def load_settings(self): pass def init_cycle_controls(self): for _ in xrange(self.IMAGE_CONTROL_COUNT): img_control = ControlImage( 0, 0, 0, 0, '', aspectRatio=2 ) #(values 0 = stretch (default), 1 = scale up (crops), 2 = scale down (black bars) txt_control = ControlTextBox(0, 0, 0, 0, font='font16') self.tni_controls.append([txt_control, img_control]) def stack_cycle_controls(self): self.xbmc_window.addControls(self.tni_controls[1]) self.xbmc_window.addControls(self.tni_controls[0]) def start_loop(self): self.log('start_loop start') desc_and_images = self.get_description_and_images('q') if random_image_order: #addon.getSetting('random_image_order') == 'true': random.shuffle(desc_and_images) desc_and_images_cycle = cycle(desc_and_images) tni_controls_cycle = cycle(self.tni_controls) self.hide_loading_indicator() desc_and_image = desc_and_images_cycle.next() while not self.exit_requested: self.log(' using image: %s ' % (repr(desc_and_image))) if not self.pause_requested: tni_control = tni_controls_cycle.next() self.process_image(tni_control, desc_and_image) desc_and_image = desc_and_images_cycle.next() if self.image_count < self.FAST_IMAGE_COUNT: self.image_count += 1 else: self.preload_image(desc_and_image[1]) self.wait() self.log('start_loop end') def get_description_and_images(self, source): self.image_aspect_ratio = 16.0 / 9.0 images = [] if source == 'image_folder': path = '' #SlideshowCacheFolder #addon.getSetting('image_path') if path: images = self._get_folder_images(path) elif source == 'q': images = [[ i.get('li_label'), i.get('DirectoryItem_url'), i.get('width'), i.get('height'), i.get('description') ] for i in q.queue] log("queue size:%d" % q.qsize()) return images def _get_folder_images(self, path): self.log('_get_folder_images started with path: %s' % repr(path)) _, files = xbmcvfs.listdir(path) images = [ xbmc.validatePath(path + f) for f in files if f.lower()[-3:] in ('jpg', 'png') ] self.log('_get_folder_images ends') return images def hide_loading_indicator(self): bg_img = xbmc.validatePath('/'.join( (ADDON_PATH, 'resources', 'skins', 'Default', '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.background_control.setImage(bg_img) def process_image(self, image_control, desc_and_image): raise NotImplementedError def preload_image(self, image_url): self.preload_control.setImage(image_url) def wait(self): 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 self.toggle_info_display_requested: #this value is set on specific keypress in action_id_handler self.toggle_info_display_requested = False self.toggle_info_display_handler() 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 action_id_handler(self, action_id): if action_id in ACTION_IDS_EXIT: self.stop() if action_id in ACTION_IDS_PAUSE: self.pause() if action_id == 11: #xbmcgui.ACTION_SHOW_INFO: self.toggle_info_display_requested = True #not self.info_requested def toggle_info_display_handler(self): pass def stop(self, action_id=0): self.log('stop') self.exit_requested = True self.exit_monitor = None def pause(self): pass def close(self): self.del_controls() def del_controls(self): try: self.xbmc_window.removeControls( self.tni_controls[0]) #imageControls except: pass try: self.xbmc_window.removeControls(self.tni_controls[1]) #textBoxes except: pass self.xbmc_window.removeControls(self.global_controls) self.preload_control = None self.background_control = None self.loading_control = None self.tni_controls = [] self.global_controls = [] self.xbmc_window.close() self.xbmc_window = None def log(self, msg): log(u'slideshow: %s' % msg)