예제 #1
0
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)
예제 #2
0
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
예제 #3
0
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))
예제 #4
0
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)
예제 #7
0
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)
예제 #10
0
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)
예제 #11
0
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)