コード例 #1
0
ファイル: main.py プロジェクト: Cymatium/piKam
 def directSnapshotTask(self, parameters, preview, *args):
     # running on a Raspberry Pi
     #print parameters, preview, args
     try:
         if self.directCamera == None:
             try:
                 print "Using picam directly"
                 self.usingDirectPicam = True
                 from piKamPicamServer import PiKamPicamServerProtocal
                 self.directCamera = PiKamPicamServerProtocal()
             except:
                 self.usingDirectPicam = False
                 print "Using raspistill directly"
                 from piKamServer import PiKamServerProtocal
                 self.directCamera = PiKamServerProtocal()
         imageFilename, image, imageType, replyMessageType = self.directCamera.takePhoto(parameters)
         # Schedule to show image in main event thread
         # Do slow as much image manipulation as possible in this thread to prevent the GUI blocking
         if preview:
             # raspistill will have already saved the image, just display it.
             from functools import partial
             #self.displayPreview(textureFromPyImage(borderPyImage(image)))
             Clock.schedule_once(partial(self.displayPreview, borderPyImage(image)))
         else:
             if self.usingDirectPicam:
                 # Need to write the image out.
                 image.save(imageFilename, imageType)
             from functools import partial
             Clock.schedule_once(partial(self.displayImage, downsizePyImage(image)))
     except Exception, error:
         print str(error)
         self.displayError('No remote hostname set, you need to be running this on a Raspberry Pi. ' + str(error) )
コード例 #2
0
 def directSnapshotTask(self, parameters, preview, *args):
     # running on a Raspberry Pi
     #print parameters, preview, args
     try:
         if self.directCamera == None:
             try:
                 print "Using picam directly"
                 self.usingDirectPicam = True
                 from piKamPicamServer import PiKamPicamServerProtocal
                 self.directCamera = PiKamPicamServerProtocal()
             except:
                 self.usingDirectPicam = False
                 print "Using raspistill directly"
                 from piKamServer import PiKamServerProtocal
                 self.directCamera = PiKamServerProtocal()
         imageFilename, image, imageType, replyMessageType = self.directCamera.takePhoto(
             parameters)
         # Schedule to show image in main event thread
         # Do slow as much image manipulation as possible in this thread to prevent the GUI blocking
         if preview:
             # raspistill will have already saved the image, just display it.
             from functools import partial
             #self.displayPreview(textureFromPyImage(borderPyImage(image)))
             Clock.schedule_once(
                 partial(self.displayPreview, borderPyImage(image)))
         else:
             if self.usingDirectPicam:
                 # Need to write the image out.
                 image.save(imageFilename, imageType)
             from functools import partial
             Clock.schedule_once(
                 partial(self.displayImage, downsizePyImage(image)))
     except Exception, error:
         print str(error)
         self.displayError(
             'No remote hostname set, you need to be running this on a Raspberry Pi. '
             + str(error))
コード例 #3
0
ファイル: main.py プロジェクト: Cymatium/piKam
class PiKamApp(App):
    chdkConnection = None
    model = PiKamModel()
    ndFilter = False
    exposureComp = 0 # TODO
    previewImage = None
    waitingForImage = False
    previewTask  = None    
    screenMgr = None
    directCamera = None
    mark = None
    mark2 = None
    runningOnPi = False
    usingDirectPicam = False
    
    def build(self):
        self.runningOnPi = self.config.get('Server', 'hostname').strip() == ''
        self.screenMgr = ScreenManager()
        horzScreen = PiKamHorizontalScreen(name='horz')
        vertScreen = PiKamVerticalScreen(name='vert')    
        x,y = Window.system_size
        detectedLandscape = x > y and False # Not working on Android - darn!
        for screenWidget in ( horzScreen, vertScreen ) if (detectedLandscape or self.config.get('Misc', 'horizontalLayout') == '1') else ( vertScreen, horzScreen ):
            self.screenMgr.add_widget(screenWidget) 
 
        if self.config.get('Misc', 'splash') != '0' and os.path.exists('piKamSplash.jpg'):
            self.displayImage(PyImage.open('piKamSplash.jpg'))
        self.reconnect()
        print vars(self)
        if self.runningOnPi:
            Window.bind(on_motion=self.plot_click_pos)
            Clock.schedule_interval(self.plot_motion, .5)
        #Window.rotation = Window.rotation + 90
        Window.on_rotate(self.rotate)
        return self.screenMgr
        
    def plot_click_pos(self, x, etype, motionevent):
       if self.runningOnPi:
            # Cannot see where mouse is on Raspberry Pi Kivy - provide some
            # indicator.                 
            if self.mark2:
                 self.screenMgr.current_screen.canvas.remove(self.mark2)
            self.mark2 = Rectangle(pos=motionevent.pos, size=(5, 5))
            self.screenMgr.current_screen.canvas.add(self.mark2)

    def plot_motion(self, *args):
        # Cannot see where mouse is on Raspberry Pi Kivy - provide some
        # indicator. 
        if self.mark:
            if self.mark.pos == Window.mouse_pos:
                return
            self.screenMgr.current_screen.canvas.remove(self.mark)
        #print 'mouse at', Window.mouse_pos
        self.mark = Rectangle(pos=Window.mouse_pos, size=(5, 5))
        self.screenMgr.current_screen.canvas.add(self.mark)
        
    def rotate(self, screenName=None):
        print "rotate"
        if self.screenMgr.current == 'horz':
            self.screenMgr.current = 'vert'
        else:
            self.screenMgr.current = 'horz'
        #Window.rotation = Window.rotation + 90
    
    def build_config(self, config):
        config.setdefaults('Server', {'hostname': '', 'port': '8000'}) 
        config.setdefaults('Camera', {'encoding': 'jpg', 'quality': 0, 'sharpness': 0, 'hflip': 0, 'vflip': 0})
        config.setdefaults('Misc',   {'carousel': 1, 'splash': 1, 'preview': 1, 'horizontalLayout':1, 'numSlides': 10, 'previewQuality':5, 'previewRefresh':1.5})
        
    def build_settings(self, settings):
        # Javascript Object Notation
        settings.add_json_panel('PiKam App', self.config, data=SETTINGS_JSON_DATA)
            
    def on_config_change(self, config, section, key, value):
        if config is self.config:
            if section == 'Server':
                self.reconnect()
            if key == 'preview' or key == 'previewQuality' or key == 'previewRefresh':
                self.disablePreview()
                self.enablePreview()
            if key == 'horizontalLayout':
                self.screenMgr.current = 'horz' if self.config.get('Misc', 'horizontalLayout') != '0' else 'vert'
                # Force image to be regenerated and reparented in new widget hierarchy
                self.previewImage = None
                
    def displayInfo(self, message, title='Info'):
        popContent = BoxLayout(orientation='vertical')
        popContent.add_widget(Label(text=message))
        popup = Popup(title=title,
                    content=popContent,
                    text_size=(len(message), None),
                    size_hint=(.8, .33))
        popContent.add_widget(Button(text='Close', size_hint=(1,.33), on_press=popup.dismiss))
        popup.open()

    def currentTop(self):
        return self.screenMgr.current_screen

    def displayError(self, message, title='Error'):
        self.displayInfo(message, title)
        
    def displayProgress(self, value):
        # If zero then we don't want progress for this op.
        if self.currentTop().downloadProgress.value > 0:
            self.currentTop().downloadProgress.value += value
        
    def displayBusyWaiting(self, dt=None):
        if dt == None:
            #print "schedule"
            self.busyWaiting = True
            Clock.schedule_interval(self.displayBusyWaiting, 1 / 10.)
            return
        # Fake progress updates until the real updates happen
        
        if self.busyWaiting:
            self.currentTop().downloadProgress.value += 30000
            return True
        else:
            # If the values differ, then 
            #print "stop"
            return False
    
    def stopBusyWaiting(self):
        self.busyWaiting = False
        self.currentTop().downloadProgress.value = 0
        
    def displayImage(self, pyImg, *args):
        try:
            useCarousel = self.config.get('Misc', 'carousel') != '0'
                # Load Kivy Image from PyImage without going to disk
            image = Image(texture=textureFromPyImage(pyImg))
            if useCarousel:
                self.currentTop().imageCarousel.add_widget(image)
                # Set the carousel to display the new image (could exhaust memory - perhaps only display last N)
                self.currentTop().imageCarousel.index = len(self.currentTop().imageCarousel.slides) - 1
                numSlides = int(self.config.get('Misc', 'numSlides'))
                if len(self.currentTop().imageCarousel.slides) > numSlides:
                    self.currentTop().imageCarousel.remove_widget(self.currentTop().imageCarousel.slides[0])
            else:
                self.currentTop().imageLayout.clear_widgets()
                self.currentTop().imageLayout.add_widget(image)
                
        finally:
            self.stopBusyWaiting()
            self.waitingForImage = False

    def displayPreview(self, pyImg, *args):
        try:
            useCarousel = self.config.get('Misc', 'carousel') != '0'
            if self.previewImage:
                self.previewImage.texture = textureFromPyImage(pyImg)
                if useCarousel:
                    # Shuffle to end
                    oldIndex = self.currentTop().imageCarousel.index
                    self.currentTop().imageCarousel.remove_widget(self.previewImage)
                    self.currentTop().imageCarousel.add_widget(self.previewImage)
                    if oldIndex == len(self.currentTop().imageCarousel.slides) - 1:
                        self.currentTop().imageCarousel.index = len(self.currentTop().imageCarousel.slides) - 1
            else:
                self.previewImage =  Image(texture=textureFromPyImage(pyImg))
                self.previewImage.nocache = True
                if useCarousel:
                    oldIndex = self.currentTop().imageCarousel.index
                    self.currentTop().imageCarousel.add_widget(self.previewImage)
                    # Set the carousel to display the new image (could exhaust memory - perhaps only display last N)
                    if oldIndex == len(self.currentTop().imageCarousel.slides) - 1:
                        self.currentTop().imageCarousel.index = len(self.currentTop().imageCarousel.slides) - 1
                else:
                    self.currentTop().imageLayout.clear_widgets()
                    self.currentTop().imageLayout.add_widget(self.previewImage)
        finally:
            self.waitingForImage = False


    def on_connection(self, connection):
        self.displayInfo('Connected succesfully!')
        self.chdkConnection = connection  
        self.prepareCamera()
        self.enablePreview()
        
    def on_start(self):
        if self.runningOnPi:
            # On a Raspberry Pi - start preview - if remote it
            # will be started by on_connection
            self.enablePreview()

    def on_pause(self):
        #reactor._mainLoopShutdown()
        self.disablePreview()
        return True

    def on_resume(self):
        self.reconnect()
        return True
   
    def sendRemoteCommand(self, message):
        if self.chdkConnection:
            # Compose Netstring format message and send it (might be able to call sendString but is undocumented)
            self.chdkConnection.write(str(len(message)) + ':' + message + ',')
        else:
            self.displayError('No connection to server')
            
    def processRemoteResponse(self, message):
        # Turn the response string back nto a dictionary and see what it is
        result = cPickle.loads(message)
        if result['type'] == 'image':
            # Save the image and add an internal copy to the GUI carousel.
            filename = result['name']
            with open(filename, 'wb') as imageFile:
                imageFile.write(result['data'])
            self.displayImage(downsizePyImage(pyImageFromStr(result['data'])))
        elif result['type'] == 'preview':
            self.displayPreview(borderPyImage(pyImageFromStr(result['data'])))
        elif result['type'] == 'error':
            self.displayError(result['message'])
        else:
            self.displayError('Unexpected kind of message.')

    def takeSnapshot(self, preview = False):
        if self.waitingForImage and preview:
            print 'already waiting', self.waitingForImage
            return
        self.waitingForImage = True
        self.model.setConfig(self.config)
        command = {}
        command['cmd'] = 'shoot'
        args = self.model.toRequest()
        if preview:
            args.height = 480
            args.width = 640
            args.encoding = 'jpg'
            args.quality = self.config.get('Misc', 'previewQuality')
            args.replyMessageType = 'preview'
            
        if self.runningOnPi:
            # On a Raspberry Pi already
            self.directSnapshot(args, preview)
        else:
            command['args'] = args
            # Turn the request into a string so it can be sent in Netstring format
            self.sendRemoteCommand(cPickle.dumps(command))
            if not preview:
                self.displayBusyWaiting()
        
    def prepareCamera(self):
        command = {'cmd': 'prepareCamera'}
        args = self.model.toRequest()
        command['args'] = args
        self.sendRemoteCommand(cPickle.dumps(command))
        pass
        
    def reconnect(self):
        if self.runningOnPi:
            return
        hostname = self.config.get('Server', 'hostname')
        port = self.config.getint('Server', 'port')
        reactor.connectTCP(hostname, port, PiKamClientFactory(self))
    
    def requestPreview(self):
        #print 'pv'
        useCarousel = self.config.get('Misc', 'carousel') != '0'
        numSlides = len(self.currentTop().imageCarousel.slides)
        if useCarousel and numSlides != 0 and self.currentTop().imageCarousel.index != numSlides - 1:
            # Not looking at preview - don't refresh it
            return
        self.takeSnapshot(preview=True)

    def enablePreview(self):
        if self.config.get('Misc', 'preview') == '0' or self.previewTask:
            return
        print 'enablePreview'
        self.waitingForImage = False
        self.previewTask = task.LoopingCall(self.requestPreview)
        refresh = float(self.config.get('Misc', 'previewRefresh'))
        self.previewTask.start(refresh) 
        
    def directSnapshot(self, parameters, preview):
        if not preview:
            self.displayBusyWaiting()
        from threading import Thread
        # Perform in background - allow GUI to continue responding
        thread = Thread(target=self.directSnapshotTask, args=(parameters, preview))
        thread.start()
        
    def directSnapshotTask(self, parameters, preview, *args):
        # running on a Raspberry Pi
        #print parameters, preview, args
        try:
            if self.directCamera == None:
                try:
                    print "Using picam directly"
                    self.usingDirectPicam = True
                    from piKamPicamServer import PiKamPicamServerProtocal
                    self.directCamera = PiKamPicamServerProtocal()
                except:
                    self.usingDirectPicam = False
                    print "Using raspistill directly"
                    from piKamServer import PiKamServerProtocal
                    self.directCamera = PiKamServerProtocal()
            imageFilename, image, imageType, replyMessageType = self.directCamera.takePhoto(parameters)
            # Schedule to show image in main event thread
            # Do slow as much image manipulation as possible in this thread to prevent the GUI blocking
            if preview:
                # raspistill will have already saved the image, just display it.
                from functools import partial
                #self.displayPreview(textureFromPyImage(borderPyImage(image)))
                Clock.schedule_once(partial(self.displayPreview, borderPyImage(image)))
            else:
                if self.usingDirectPicam:
                    # Need to write the image out.
                    image.save(imageFilename, imageType)
                from functools import partial
                Clock.schedule_once(partial(self.displayImage, downsizePyImage(image)))
        except Exception, error:
            print str(error)
            self.displayError('No remote hostname set, you need to be running this on a Raspberry Pi. ' + str(error) )
コード例 #4
0
class PiKamApp(App):
    chdkConnection = None
    model = PiKamModel()
    ndFilter = False
    exposureComp = 0  # TODO
    previewImage = None
    waitingForImage = False
    previewTask = None
    screenMgr = None
    directCamera = None
    mark = None
    mark2 = None
    runningOnPi = False
    usingDirectPicam = False

    def build(self):
        self.runningOnPi = self.config.get('Server', 'hostname').strip() == ''
        self.screenMgr = ScreenManager()
        horzScreen = PiKamHorizontalScreen(name='horz')
        vertScreen = PiKamVerticalScreen(name='vert')
        x, y = Window.system_size
        detectedLandscape = x > y and False  # Not working on Android - darn!
        for screenWidget in (horzScreen, vertScreen) if (
                detectedLandscape or self.config.get(
                    'Misc', 'horizontalLayout') == '1') else (vertScreen,
                                                              horzScreen):
            self.screenMgr.add_widget(screenWidget)

        if self.config.get(
                'Misc', 'splash') != '0' and os.path.exists('piKamSplash.jpg'):
            self.displayImage(PyImage.open('piKamSplash.jpg'))
        self.reconnect()
        print vars(self)
        if self.runningOnPi:
            Window.bind(on_motion=self.plot_click_pos)
            Clock.schedule_interval(self.plot_motion, .5)
        #Window.rotation = Window.rotation + 90
        Window.on_rotate(self.rotate)
        return self.screenMgr

    def plot_click_pos(self, x, etype, motionevent):
        if self.runningOnPi:
            # Cannot see where mouse is on Raspberry Pi Kivy - provide some
            # indicator.
            if self.mark2:
                self.screenMgr.current_screen.canvas.remove(self.mark2)
            self.mark2 = Rectangle(pos=motionevent.pos, size=(5, 5))
            self.screenMgr.current_screen.canvas.add(self.mark2)

    def plot_motion(self, *args):
        # Cannot see where mouse is on Raspberry Pi Kivy - provide some
        # indicator.
        if self.mark:
            if self.mark.pos == Window.mouse_pos:
                return
            self.screenMgr.current_screen.canvas.remove(self.mark)
        #print 'mouse at', Window.mouse_pos
        self.mark = Rectangle(pos=Window.mouse_pos, size=(5, 5))
        self.screenMgr.current_screen.canvas.add(self.mark)

    def rotate(self, screenName=None):
        print "rotate"
        if self.screenMgr.current == 'horz':
            self.screenMgr.current = 'vert'
        else:
            self.screenMgr.current = 'horz'
        #Window.rotation = Window.rotation + 90

    def build_config(self, config):
        config.setdefaults('Server', {'hostname': '', 'port': '8000'})
        config.setdefaults(
            'Camera', {
                'encoding': 'jpg',
                'quality': 0,
                'sharpness': 0,
                'hflip': 0,
                'vflip': 0
            })
        config.setdefaults(
            'Misc', {
                'carousel': 1,
                'splash': 1,
                'preview': 1,
                'horizontalLayout': 1,
                'numSlides': 10,
                'previewQuality': 5,
                'previewRefresh': 1.5
            })

    def build_settings(self, settings):
        # Javascript Object Notation
        settings.add_json_panel('PiKam App',
                                self.config,
                                data=SETTINGS_JSON_DATA)

    def on_config_change(self, config, section, key, value):
        if config is self.config:
            if section == 'Server':
                self.reconnect()
            if key == 'preview' or key == 'previewQuality' or key == 'previewRefresh':
                self.disablePreview()
                self.enablePreview()
            if key == 'horizontalLayout':
                self.screenMgr.current = 'horz' if self.config.get(
                    'Misc', 'horizontalLayout') != '0' else 'vert'
                # Force image to be regenerated and reparented in new widget hierarchy
                self.previewImage = None

    def displayInfo(self, message, title='Info'):
        popContent = BoxLayout(orientation='vertical')
        popContent.add_widget(Label(text=message))
        popup = Popup(title=title,
                      content=popContent,
                      text_size=(len(message), None),
                      size_hint=(.8, .33))
        popContent.add_widget(
            Button(text='Close', size_hint=(1, .33), on_press=popup.dismiss))
        popup.open()

    def currentTop(self):
        return self.screenMgr.current_screen

    def displayError(self, message, title='Error'):
        self.displayInfo(message, title)

    def displayProgress(self, value):
        # If zero then we don't want progress for this op.
        if self.currentTop().downloadProgress.value > 0:
            self.currentTop().downloadProgress.value += value

    def displayBusyWaiting(self, dt=None):
        if dt == None:
            #print "schedule"
            self.busyWaiting = True
            Clock.schedule_interval(self.displayBusyWaiting, 1 / 10.)
            return
        # Fake progress updates until the real updates happen

        if self.busyWaiting:
            self.currentTop().downloadProgress.value += 30000
            return True
        else:
            # If the values differ, then
            #print "stop"
            return False

    def stopBusyWaiting(self):
        self.busyWaiting = False
        self.currentTop().downloadProgress.value = 0

    def displayImage(self, pyImg, *args):
        try:
            useCarousel = self.config.get('Misc', 'carousel') != '0'
            # Load Kivy Image from PyImage without going to disk
            image = Image(texture=textureFromPyImage(pyImg))
            if useCarousel:
                self.currentTop().imageCarousel.add_widget(image)
                # Set the carousel to display the new image (could exhaust memory - perhaps only display last N)
                self.currentTop().imageCarousel.index = len(
                    self.currentTop().imageCarousel.slides) - 1
                numSlides = int(self.config.get('Misc', 'numSlides'))
                if len(self.currentTop().imageCarousel.slides) > numSlides:
                    self.currentTop().imageCarousel.remove_widget(
                        self.currentTop().imageCarousel.slides[0])
            else:
                self.currentTop().imageLayout.clear_widgets()
                self.currentTop().imageLayout.add_widget(image)

        finally:
            self.stopBusyWaiting()
            self.waitingForImage = False

    def displayPreview(self, pyImg, *args):
        try:
            useCarousel = self.config.get('Misc', 'carousel') != '0'
            if self.previewImage:
                self.previewImage.texture = textureFromPyImage(pyImg)
                if useCarousel:
                    # Shuffle to end
                    oldIndex = self.currentTop().imageCarousel.index
                    self.currentTop().imageCarousel.remove_widget(
                        self.previewImage)
                    self.currentTop().imageCarousel.add_widget(
                        self.previewImage)
                    if oldIndex == len(
                            self.currentTop().imageCarousel.slides) - 1:
                        self.currentTop().imageCarousel.index = len(
                            self.currentTop().imageCarousel.slides) - 1
            else:
                self.previewImage = Image(texture=textureFromPyImage(pyImg))
                self.previewImage.nocache = True
                if useCarousel:
                    oldIndex = self.currentTop().imageCarousel.index
                    self.currentTop().imageCarousel.add_widget(
                        self.previewImage)
                    # Set the carousel to display the new image (could exhaust memory - perhaps only display last N)
                    if oldIndex == len(
                            self.currentTop().imageCarousel.slides) - 1:
                        self.currentTop().imageCarousel.index = len(
                            self.currentTop().imageCarousel.slides) - 1
                else:
                    self.currentTop().imageLayout.clear_widgets()
                    self.currentTop().imageLayout.add_widget(self.previewImage)
        finally:
            self.waitingForImage = False

    def on_connection(self, connection):
        self.displayInfo('Connected succesfully!')
        self.chdkConnection = connection
        self.prepareCamera()
        self.enablePreview()

    def on_start(self):
        if self.runningOnPi:
            # On a Raspberry Pi - start preview - if remote it
            # will be started by on_connection
            self.enablePreview()

    def on_pause(self):
        #reactor._mainLoopShutdown()
        self.disablePreview()
        return True

    def on_resume(self):
        self.reconnect()
        return True

    def sendRemoteCommand(self, message):
        if self.chdkConnection:
            # Compose Netstring format message and send it (might be able to call sendString but is undocumented)
            self.chdkConnection.write(str(len(message)) + ':' + message + ',')
        else:
            self.displayError('No connection to server')

    def processRemoteResponse(self, message):
        # Turn the response string back nto a dictionary and see what it is
        result = cPickle.loads(message)
        if result['type'] == 'image':
            # Save the image and add an internal copy to the GUI carousel.
            filename = result['name']
            with open(filename, 'wb') as imageFile:
                imageFile.write(result['data'])
            self.displayImage(downsizePyImage(pyImageFromStr(result['data'])))
        elif result['type'] == 'preview':
            self.displayPreview(borderPyImage(pyImageFromStr(result['data'])))
        elif result['type'] == 'error':
            self.displayError(result['message'])
        else:
            self.displayError('Unexpected kind of message.')

    def takeSnapshot(self, preview=False):
        if self.waitingForImage and preview:
            print 'already waiting', self.waitingForImage
            return
        self.waitingForImage = True
        self.model.setConfig(self.config)
        command = {}
        command['cmd'] = 'shoot'
        args = self.model.toRequest()
        if preview:
            args.height = 480
            args.width = 640
            args.encoding = 'jpg'
            args.quality = self.config.get('Misc', 'previewQuality')
            args.replyMessageType = 'preview'

        if self.runningOnPi:
            # On a Raspberry Pi already
            self.directSnapshot(args, preview)
        else:
            command['args'] = args
            # Turn the request into a string so it can be sent in Netstring format
            self.sendRemoteCommand(cPickle.dumps(command))
            if not preview:
                self.displayBusyWaiting()

    def prepareCamera(self):
        command = {'cmd': 'prepareCamera'}
        args = self.model.toRequest()
        command['args'] = args
        self.sendRemoteCommand(cPickle.dumps(command))
        pass

    def reconnect(self):
        if self.runningOnPi:
            return
        hostname = self.config.get('Server', 'hostname')
        port = self.config.getint('Server', 'port')
        reactor.connectTCP(hostname, port, PiKamClientFactory(self))

    def requestPreview(self):
        #print 'pv'
        useCarousel = self.config.get('Misc', 'carousel') != '0'
        numSlides = len(self.currentTop().imageCarousel.slides)
        if useCarousel and numSlides != 0 and self.currentTop(
        ).imageCarousel.index != numSlides - 1:
            # Not looking at preview - don't refresh it
            return
        self.takeSnapshot(preview=True)

    def enablePreview(self):
        if self.config.get('Misc', 'preview') == '0' or self.previewTask:
            return
        print 'enablePreview'
        self.waitingForImage = False
        self.previewTask = task.LoopingCall(self.requestPreview)
        refresh = float(self.config.get('Misc', 'previewRefresh'))
        self.previewTask.start(refresh)

    def directSnapshot(self, parameters, preview):
        if not preview:
            self.displayBusyWaiting()
        from threading import Thread
        # Perform in background - allow GUI to continue responding
        thread = Thread(target=self.directSnapshotTask,
                        args=(parameters, preview))
        thread.start()

    def directSnapshotTask(self, parameters, preview, *args):
        # running on a Raspberry Pi
        #print parameters, preview, args
        try:
            if self.directCamera == None:
                try:
                    print "Using picam directly"
                    self.usingDirectPicam = True
                    from piKamPicamServer import PiKamPicamServerProtocal
                    self.directCamera = PiKamPicamServerProtocal()
                except:
                    self.usingDirectPicam = False
                    print "Using raspistill directly"
                    from piKamServer import PiKamServerProtocal
                    self.directCamera = PiKamServerProtocal()
            imageFilename, image, imageType, replyMessageType = self.directCamera.takePhoto(
                parameters)
            # Schedule to show image in main event thread
            # Do slow as much image manipulation as possible in this thread to prevent the GUI blocking
            if preview:
                # raspistill will have already saved the image, just display it.
                from functools import partial
                #self.displayPreview(textureFromPyImage(borderPyImage(image)))
                Clock.schedule_once(
                    partial(self.displayPreview, borderPyImage(image)))
            else:
                if self.usingDirectPicam:
                    # Need to write the image out.
                    image.save(imageFilename, imageType)
                from functools import partial
                Clock.schedule_once(
                    partial(self.displayImage, downsizePyImage(image)))
        except Exception, error:
            print str(error)
            self.displayError(
                'No remote hostname set, you need to be running this on a Raspberry Pi. '
                + str(error))