def _via_immediate(self, user_cb):
     if self.immediate:
         self.immediate.cancel()
     else:
         self.immediate = AoImmediate()
         self.immediate.open()
     self.immediate.complete(self._imm_completed, user_cb)
 def __init__(self, config):
     """
     apid: Initial access point ID to use.
     """
     self.config = config
     self.gsm_scanner = GsmScanner()
     self.btprox_scanner = None
     self.positioner = None
     self.uploader = Uploader(config)
     self.immediate = AoImmediate()
     self.immediate.open()
     self.btprox_scan_error_shown = False
     self.active = False
class GsmScanner:
    def __init__(self):
        self.immediate = AoImmediate()
        self.immediate.open()

    def close(self):
        self.immediate.close()

    def cancel(self):
        self.immediate.cancel()

    def scan(self, user_cb):
        """
        user_cb:: A callable that takes one argument, namely the GSM
                  cell ID data.
        """
        self.gsm = get_gsm()
        self.immediate.complete(self._imm_completed, user_cb)

    def _imm_completed(self, code, user_cb):
        user_cb(self.gsm)
class ScannerSender:
    """
    The task of an object of this type is to add context data and send
    it, reporting on success or failure with a callback.
    """
    def __init__(self, config):
        """
        apid: Initial access point ID to use.
        """
        self.config = config
        self.gsm_scanner = GsmScanner()
        self.btprox_scanner = None
        self.positioner = None
        self.uploader = Uploader(config)
        self.immediate = AoImmediate()
        self.immediate.open()
        self.btprox_scan_error_shown = False
        self.active = False

    def cancel(self):
        """
        Cancels any operation(s) in progress, whether finished or not.
        """
        self.immediate.cancel()
        self.gsm_scanner.cancel()
        if self.btprox_scanner:
            self.btprox_scanner.cancel()
        if self.positioner:
            self.positioner.cancel()
        self.uploader.cancel()
        self.active = False

    def close(self):
        """
        Does cleanup.
        """
        self.immediate.close()
        self.gsm_scanner.close()
        if self.btprox_scanner:
            self.btprox_scanner.close()
        if self.positioner:
            self.positioner.close()
        self.uploader.close()

    def scan_and_send(self, card, cb):
        """
        The caller of this method should check the "active" flag to
        ensure that no send is already in progress.
        
        card:: Card to which to add context data and to send.
        cb:: Status reporting callback.
        """
        if self.active: raise "assertion failure"

        self.card = card
        self.cb = cb

        self._clear_context()
        if self.config.get_noscan():
            self._send_card()
        else:
            self._scan_gsm()

    def _clear_context(self):
        """
        Note that it is important to set values to None when scanning
        fails so that we never end up sending a card with an old
        value.
        """
        self.card.set_gsm(None)
        self.card.set_btprox(None)

    def _scan_gsm(self):
        ut.report("_scan_gsm")
        def f():
            self.gsm_scanner.scan(self._gsm_done)
            self.active = True
        self.cb("progress", u"Scanning context")
        self._via_immediate(f)

    def _gsm_done(self, gsm):
        """
        Note that it is important to set values to None when scanning
        fails so that we never end up sending a card with an old
        value.
        """
        ut.report("_gsm_done")
        self.active = False
        self.card.set_gsm(gsm)
        self._scan_btprox()

    def init_btprox_scanner(self):
        try:
            self.btprox_scanner = BtproxScanner()
        except:
            self.btprox_scanner = None

    def _scan_btprox(self):
        ut.report("_scan_btprox")
        try:
            if not self.config.get_btprox_scan():
                self._btprox_done(None)
                return
            if not self.btprox_scanner:
                self.init_btprox_scanner()
            if not self.btprox_scanner:
                if not self.btprox_scan_error_shown:
                    self.btprox_scan_error_shown = True
                    appuifw.note(u"Could not scan proximity: Is Bluetooth enabled?", "error")
                self._btprox_done(None)
                return
            self.btprox_scanner.scan(self._btprox_done)
            self.active = True
        except:
            ut.print_exception()
            self._btprox_done(None)

    def _btprox_done(self, btdata):
        """
        btdata:: Has value None if there was a scanning error.
        """
        ut.report("_btprox_done")
        self.active = False
        if btdata is None:
            self.btprox_scanner = None
        self.card.set_btprox(btdata)
        if self.card.gps is None:
            # Our positioning hack no longer appears to work, so disabling for now.
            #self._scan_position()
            self._send_card()
        else:
            self._send_card()

    def _scan_position(self):
        ut.report("_scan_position")

        def f():
            if self.positioner:
                self.positioner.close()
                self.positioner = None
            try:
                from pytwink import Positioner

                modlist = positioning.modules()
                module_id = None
                for entry in modlist:
                    if entry["name"] == u"Network based" and \
                       entry["available"]:
                        module_id = entry["id"]
                        break
                if not module_id:
                    raise "no network positioning module"

                updatetimeout = 15000000
                maxupdateage =  30000000
                self.positioner = Positioner(module_id, updatetimeout, maxupdateage)
                self.positioner.ask_position(self._positioner_done)
                return
            except:
                self._send_card()

            self.active = True

        self.cb("progress", u"Querying position")
        self._via_immediate(f)

    def _positioner_done(self, code):
        ut.report("_positioner_done (%d)" % code)
        self.active = False
        if not code:
            self.card.gps = {"position": self.positioner.get_position()}
        self._send_card()

    def _send_card(self):
        if self.config.get_store_on():
            self.cb("progress", u"Storing card")
            def f():
                try:
                    self.card.prepare_for_sending()
                    data = serialize_card(self.card)
                    save_unsent_card(data)
                    self.cb("ok", u"Card stored")
                except:
                    ut.print_exception()
                    self.cb("fail", u"Storing failed")
        else:
            self.cb("progress", u"Sending card")
            def f():
                try:
                    self.card.prepare_for_sending()
                    self.uploader.send(serialize_card(self.card), self._send_done)
                    self.active = True
                except:
                    self.config.set_apid(None)
                    ut.print_exception()
                    #appuifw.note(u"Sending failed", "error")
                    self.cb("fail", u"Sending failed")
        self._via_immediate(f)

    def _send_done(self, serr, equ):
        self.active = False
        if serr:
            ut.report("send error (Symbian %d)" % serr)
            self.cb("fail", u"Sending failed")
        elif equ == "refused":
            self.cb("fail", u"Server did not accept card")
        elif equ == "accepted":
            self.cb("ok", u"Card sent")
        else:
            self.cb("fail", u"Unexpected response from server")

    def _via_immediate(self, cb):
        def this_cb(code, dummy):
            self.active = False
            cb()
        self.immediate.complete(this_cb, None)
        self.active = True
 def __init__(self):
     self.immediate = AoImmediate()
     self.immediate.open()
class PicFile:
    def __init__(self, path, fn, tn_width):
        # We want to have the image width encoded in the name, so that if
        # we should end up changing "tn_width", we know to have new
        # thumbnails generated.
        tn_dir = u"_galthumb_%d" % tn_width

        self.path = path
        self.fn = fn
        self.pn = self.path + u"\\" + self.fn

        self.tn_path = path + u"\\" + tn_dir
        # .txt here seems to be one of the few things we can use to
        # fool the recognizer so that the thumbnails are _not_
        # displayed in Gallery, which would involve generating
        # thumbnails for the thumbnails. And we do not want any
        # duplicates in the gallery.
        self.tn_pn = self.tn_path + u"\\" + fn + "thumb.txt"

        self.tn_fail = False
        self.tn_image = None

        self.image = None
        self.immediate = None

    def makedirs(self):
        try:
            os.makedirs(ut.to_str(self.tn_path))
        except:
            # Strangely throws an exception if the path already exists.
            pass

    def stop(self):
        """
        Stops any outstanding "create_tn_image" request processing.
        """
        if self.image:
            self.image.stop()
            self.image = None

        if self.tn_image:
            self.tn_image.stop()
            self.tn_image = None

        if self.immediate:
            self.immediate.close()
            self.immediate = None

    def _check_code(self, code):
        if code != 0:
            # A typical error would be -4, or KErrNoMemory.
            # Note that cannot raise a unicode object, hence the "str".
            raise ("failed to load image %s (%d)" % (str(self.fn), code))

    def _try(self, action):
        try:
            action()
        except:
            self.tn_fail = True
            self.image = self.tn_image = None
            ut.print_exception()
            self.cb("fail")
            return True
        return False

    def _imm_completed(self, code, user_cb):
        def action():
            self._check_code(code)
            user_cb()

        self._try(action)

    def _via_immediate(self, user_cb):
        if self.immediate:
            self.immediate.cancel()
        else:
            self.immediate = AoImmediate()
            self.immediate.open()
        self.immediate.complete(self._imm_completed, user_cb)

    def _saved(self, code):
        #print ["saved", code]

        def finish():
            self.cb("ok")
            self.tn_image = None # clear from cache

        def action():
            self._via_immediate(finish)

        self._try(action)

    def _resized(self, tn_image):
        #print ["resized", tn_image]

        self.tn_image = tn_image
        self.image = None

        def req_save():
            self.makedirs()
            self.tn_image.save(self.tn_pn, callback = self._saved, format = "JPEG")
        def action():
            # We pass to the caller already, but this does not yet
            # complete the request.
            self.cb(self.tn_image)

            self._via_immediate(req_save)

        self._try(action)

    def _loaded(self, code):
        #print ["loaded", code]

        def req_resize():
            #print "resizing %s" % repr(self.pn)
            #print "resizing %s" % repr(self.image)
            #print "resizing to %s" % repr(self.tn_size)
            self.image.resize(self.tn_size, keepaspect = 1,
                              callback = self._resized)
            #print "resize request made"

        def action():
            self._check_code(code)
            self._via_immediate(req_resize)

        self._try(action)
            
    def create_tn_image(self, tn_size, cb):
        #print "create tn"
        
        try:
            info = graphics.Image.inspect(self.pn)
            #print repr(info)
            img_size = info["size"]
            img = graphics.Image.new(img_size)
            self.tn_size = tn_size
            self.cb = cb
            img.load(self.pn, callback = self._loaded)
            self.image = img
        except:
            ut.print_exception()
            self.tn_fail = True
            raise # re-raise

    def get_tn_image(self):
        # This ought to be fast enough so that we can do without
        # asynch loading. Note that it is legal to blit even just
        # partially loaded images onto the screen, but that probably
        # will not be necessary here.
        return graphics.Image.open(self.tn_pn)