Example #1
0
def _cameras():
    """
    Get a list of ParamDicts for all cameras currently attached.
    """
    cams = []
    num = INT()
    if lib.is_GetNumberOfCameras(byref(num)) == IS_SUCCESS:
        if num >= 1:
            cam_list = create_camera_list(num)()
            cam_list.dwCount = ULONG(num.value)  # This is stupid

            if lib.is_GetCameraList(pointer(cam_list)) == IS_SUCCESS:
                ids = []
                repeated = []
                for info in cam_list.ci:
                    id = info.dwCameraID
                    if id in ids:
                        repeated.append(id)
                    ids.append(id)

                if not repeated:
                    for info in cam_list.ci:
                        params = _ParamDict("<UC480_Camera '{}'>".format(
                            info.SerNo))
                        params.module = 'cameras.uc480'
                        params['cam_serial'] = info.SerNo
                        params['cam_model'] = info.Model
                        params['ueye_cam_id'] = int(info.dwCameraID)
                        cams.append(params)
                else:
                    log.info(
                        "Some cameras have duplicate IDs. Uniquifying IDs now..."
                    )
                    # Choose IDs that haven't been used yet
                    potential_ids = [
                        i for i in range(1,
                                         len(ids) + 1) if i not in ids
                    ]
                    for id in repeated:
                        new_id = potential_ids.pop(0)
                        log.info("Trying to set id from {} to {}".format(
                            id, new_id))
                        _id = HCAM(id)
                        ret = lib.is_InitCamera(pointer(_id), NULL)
                        if not ret == IS_SUCCESS:
                            log.error(
                                "Error connecting to camera {}".format(id))
                            return None  # Avoid infinite recursion
                        else:
                            ret = lib.is_SetCameraID(_id, INT(new_id))
                            if not ret == IS_SUCCESS:
                                log.error("Error setting the camera id")
                                return None  # Avoid infinite recursion
                    # All IDs should be fixed now, let's retry
                    cams = _cameras()
            else:
                raise Error("Error getting camera list")
    else:
        raise Error("Error getting number of attached cameras")
    return cams
Example #2
0
def inet_ntop(AddressFamily, PackedIP):
    if AddressFamily not in (socket.AF_INET, socket.AF_INET6):
        raise socket.error('unknown address family')

    lpsaAddress = SOCKADDR()
    dwAddressLength = INT(ctypes.sizeof(lpsaAddress))
    lpProtocolInfo = NULL

    lpsaAddress.sa_family = ADDRESS_FAMILY(AddressFamily)

    lpszAddressString = ctypes.create_unicode_buffer(128)
    lpdwAddressStringLength = INT(ctypes.sizeof(lpszAddressString))

    if AddressFamily == socket.AF_INET:
        if len(PackedIP) != ctypes.sizeof(lpsaAddress.ipv4_addr):
            raise socket.error('packed IP wrong length for inet_ntoa')
        ctypes.memmove(lpsaAddress.ipv4_addr, PackedIP, 4)
    elif AddressFamily == socket.AF_INET6:
        if len(PackedIP) != ctypes.sizeof(lpsaAddress.ipv6_addr):
            raise socket.error('packed IP wrong length for inet_ntoa')
        ctypes.memmove(lpsaAddress.ipv6_addr, PackedIP, 16)

    res = WSAAddressToStringW(
        ctypes.byref(lpsaAddress),
        dwAddressLength,
        lpProtocolInfo,
        lpszAddressString,
        ctypes.byref(lpdwAddressStringLength)
    )

    if res == 0:
        return lpszAddressString[:lpdwAddressStringLength.value - 1]

    raise socket.error(ctypes.FormatError())
Example #3
0
    def __init__(self, id=None, serial=None):
        """Create a UC480_Camera object.

        A camera can be identified by its id, serial number, or both. If no
        arguments are given, returns the first camera it finds.

        The constructor automatically opens a connection to the camera, and the
        user is responsible for closing it. You can do this via ``close()`` or
        by using the constructor as a context manager, e.g.

            >>> with UC480_Camera(id=1) as cam:
            >>>     cam.save_image('image.jpg')

        Parameters
        ----------
        id : int, optional
            The uEye camera ID
        serial : str, optional
            The serial number string of the camera.
        """
        params = {}
        if id is not None:
            params['ueye_cam_id'] = id
        if serial is not None:
            params['cam_serial'] = serial

        if params:
            params = _get_legit_params(params)
        else:
            # If given no args, just choose the 'first' camera
            param_list = _cameras()
            if not param_list:
                raise Exception("No uEye cameras attached!")
            params = param_list[0]

        # For saving
        self._param_dict = params
        self._param_dict.module = 'cameras.uc480'
        self._param_dict['module'] = 'cameras.uc480'

        self._id = int(params['ueye_cam_id'])
        self._serial = params['cam_serial']
        self._model = params['cam_model']

        self._in_use = False
        self._width, self._height = INT(), INT()
        self._color_depth = INT()
        self._color_mode = INT()
        self._list_p_img_mem = None
        self._list_memid = None

        self._buffers = []
        self._queue_enabled = False
        self._trigger_mode = IS_SET_TRIGGER_OFF

        self._open()
Example #4
0
 def __init__(self):
     HCAM.__init__(self)
     err = initLib(serialNum)
     self.cam = createGrabber()
     self.count = getDeviceCount()
     self.device = getDevice(INT(0))
     self.name = getUniqueNameFromList(INT(0))
     self.width = 0
     self.height = 0
     self.bpp = 0
     self.buffer = []
     openDevice(self.cam, self.device)
     startLive(self.cam, INT(0)) #{param: 1: show video, 0: do not show} [prepareLive has same param]
Example #5
0
def inet_pton(AddressFamily, AddressString):
    if AddressFamily not in (socket.AF_INET, socket.AF_INET6):
        raise socket.error('unknown address family')

    if isinstance(AddressString, basestring):
        AddressString = ctypes.create_unicode_buffer(AddressString)

    lpProtocolInfo = NULL

    lpAddress = SOCKADDR()
    lpAddress.sa_family = ADDRESS_FAMILY(AddressFamily)
    lpAddressLength = INT(ctypes.sizeof(lpAddress))

    res = WSAStringToAddressW(
        AddressString,
        AddressFamily,
        lpProtocolInfo,
        ctypes.byref(lpAddress),
        ctypes.byref(lpAddressLength)
    )

    if res:
        if AddressFamily == socket.AF_INET:
            return ctypes.string_at(lpAddress.ipv4_addr, 4)
        if AddressFamily == socket.AF_INET6:
            return ctypes.string_at(lpAddress.ipv6_addr, 16)

    raise socket.error(ctypes.FormatError())
Example #6
0
def LCIDToLocaleName(lcid):
    if not isinstance(lcid, LCID):
        lcid = LCID(lcid)

    lpName = (ctypes.c_wchar * 0)()
    cchName = INT(0)
    dwFlags = DWORD(0)

    cchName = _LCIDToLocaleName(lcid, lpName, cchName, dwFlags)

    if not cchName:
        return

    lpName = (ctypes.c_wchar * cchName)()
    _LCIDToLocaleName(lcid, lpName, cchName, dwFlags)

    output = ''
    for i in range(cchName):
        char = lpName[i]
        if char in ('\x00', 0x0):
            break

        output += char

    return output
Example #7
0
 def _bytes_per_line(self):
     num = INT()
     ret = lib.is_GetImageMemPitch(self._hcam, pointer(num))
     if ret == IS_SUCCESS:
         log.debug('bytes_per_line=%d', num.value)
         return num.value
     raise Exception("Return code {}".format(ret))
Example #8
0
    def get_token_error(self) -> str:
        # Get any token error. Create a TOKENERRORINFO struct
        token_error: token_error_info = token_error_info()

        # get a pointer to use in the dll call
        lp_token_error = pointer(token_error)

        # Call the dll function, pass in the struct pointer to get filled. > 0 is success
        if self.process.GetTokenError(self.lTokenServiceHandle,
                                      lp_token_error) > 0:
            if lp_token_error and token_error:
                # Dereference the pointer/get contents
                content: token_error_info = lp_token_error.contents
                if content.error != 0:
                    err_number: int = INT(content.error).value
                    err_string: str = content.error_string.decode('utf-8')
                    detailed_error_string: str = content.detailed_error_string.decode(
                        'utf-8')
                    err_msg = f"Last Token Error from SDProcess: {err_number}: {TokenError(err_number).name}"
                    f"\n{err_string}\n{detailed_error_string}"
                    logger.debug(err_msg)
                    return err_msg
                else:
                    logger.debug("No errors reported from SDProcess.")
                    return "No error"
            else:
                logger.debug(
                    "SDProcess Returned NULL pointer for last token error.")
                return "SD Error: No handle to token error"
        else:
            logger.debug("SD Process last token error has no content.")
            return "No content"
Example #9
0
 def _last_img_mem(self):
     """ Returns a ctypes char-pointer to the starting address of the image memory
     last used for image capturing """
     nNum = INT()
     pcMem = POINTER(c_char)()
     pcMemLast = POINTER(c_char)()
     lib.is_GetActSeqBuf(self._hcam, pointer(nNum), pointer(pcMem),
                         pointer(pcMemLast))
     return pcMemLast
Example #10
0
 def latest_frame(self, copy=True):
     nNum = INT()
     pcMem = POINTER(c_char)()
     pcMemLast = POINTER(c_char)()
     lib.is_GetActSeqBuf(self._hcam, pointer(nNum), pointer(pcMem),
                         pointer(pcMemLast))
     buf_ptr = cast(pcMemLast,
                    POINTER(c_char * (self.bytes_per_line * self.height)))
     array = self._array_from_buffer(buffer(buf_ptr.contents))
     return np.copy(array) if copy else array
Example #11
0
    def load_params(self, filename=None):
        """Load camera parameters from file or EEPROM.

        Parameters
        ----------
        filename : str, optional
            By default, loads the parameters from the camera's EEPROM. Otherwise,
            loads it from the specified parameter file. If filename is the empty
            string '', will open a 'Load' dialog to select the file.
        """
        if filename is None:
            cmd = IS_PARAMETERSET_CMD_LOAD_EEPROM
            param = c_char_p("/cam/set1")
            size = len(param.value)
        else:
            cmd = IS_PARAMETERSET_CMD_LOAD_FILE
            param = c_wchar_p(filename)
            size = len(param.value)

        ret = lib.is_ParameterSet(self._hcam, cmd, param, size)
        if ret == IS_INVALID_CAMERA_TYPE:
            raise Exception(".ini file does not match the camera model")
        elif ret != IS_SUCCESS:
            if filename != '':
                raise Exception("Failed to load parameter file")
        else:
            # Make sure memory is set up for right color depth
            depth_map = {
                IS_CM_MONO8: 8,
                IS_CM_RGBA8_PACKED: 32,
                IS_CM_BGRA8_PACKED: 32
            }
            mode = lib.is_SetColorMode(self._hcam, IS_GET_COLOR_MODE)
            depth = depth_map[mode]
            if depth != self._color_depth.value:
                log.debug("Color depth changed from %s to %s",
                          self._color_depth.value, depth)
                self._free_image_mem_seq()
                self._color_depth = INT(depth)
                self._allocate_image_mem_seq()
            self._color_mode = INT(mode)
Example #12
0
 def getImage(self, delay):
     '''
     delay: timeout in ms; no timeout if delay = -1
     '''
     err = snapImage(self.cam, INT(delay))
     xdim,ydim = self.width,self.height
     if err!=1:
         print "Error in snapImage."
         return 0
     d = getImagePtr(self.cam)
     dp = ctypes.cast(d,ctypes.c_void_p)
     ctypes.memmove(self.buffer_temp.ctypes.data,dp,xdim*ydim*ctypes.sizeof(ctypes.c_ubyte)*3)
     self.image = np.frombuffer(self.buffer_temp, dtype=np.uint8).reshape(ydim,xdim,3).sum(axis=-1)
Example #13
0
    def _allocate_mem_seq(self, num_bufs):
        """
        Create and setup the image memory for live capture
        """
        for i in range(num_bufs):
            p_img_mem = POINTER(c_char)()
            memid = INT()
            lib.is_AllocImageMem(self._hcam, self._width, self._height,
                                 self._color_depth, pointer(p_img_mem),
                                 pointer(memid))
            lib.is_AddToSequence(self._hcam, p_img_mem, memid)
            self._buffers.append(BufferInfo(p_img_mem, memid))

        # Initialize display
        lib.is_SetImageSize(self._hcam, self._width, self._height)
        lib.is_SetDisplayMode(self._hcam, IS_SET_DM_DIB)
def SetWindowPos(hwnd, pos=None, size=None):
    if pos is None:
        uFlags = SWP_NOMOVE
        width, height = size
        x = INT(0)
        y = INT(0)
        cx = INT(width)
        cy = INT(height)
    else:
        uFlags = SWP_NOSIZE
        x, y = pos
        x = INT(x)
        y = INT(y)
        cx = INT(0)
        cy = INT(0)

    hWndInsertAfter = HWND_TOP

    if not IsWindowVisible(hwnd):
        uFlags |= SWP_SHOWWINDOW

    return _SetWindowPos(hwnd, hWndInsertAfter, x, y, cx, cy, uFlags)
Example #15
0
    def save_image(self, filename=None, filetype=None, freeze=None):
        """Save the current video image to disk.

        If no filename is given, this will display the 'Save as' dialog. If no
        filetype is given, it will be determined by the extension of the
        filename, if available.  If neither exists, the image will be saved as
        a bitmap (BMP) file.

        Parameters
        ----------
        filename : str, optional
            Filename to save image as. If not given, 'Save as' dialog will open.
        filetype : str, optional
            Filetype to save image as, e.g. 'bmp'. Useful for setting the
            default filetype in the 'Save as' dialog.
        freeze : bool, optional
            Freeze a frame before copying data. By default, freezes when not in
            live capture mode.
        """
        if freeze is None:
            freeze = not self.is_live

        # Strip extension from filename, clear extension if it is invalid
        if filename is not None:
            filename, ext = os.path.splitext(filename)
            if ext.lower() not in ['.bmp', '.jpg', '.png']:
                ext = '.bmp'
        else:
            filename, ext = '', '.bmp'

        # 'filetype' flag overrides the extension. Default is .bmp
        if filetype:
            ext = '.' + filetype.lower()

        fdict = {'.bmp': IS_IMG_BMP, '.jpg': IS_IMG_JPG, '.png': IS_IMG_PNG}
        ftype_flag = fdict[ext.lower()]
        filename = filename + ext if filename else None

        if freeze:
            lib.is_FreezeVideo(self._hcam, self._width, self._height)
        lib.is_SaveImageEx(self._hcam, filename, ftype_flag, INT(0))
Example #16
0
def GetIntSystemParametersInfo(key):
    rv = INT()
    r = SystemParametersInfoA(key, 0, byref(rv), 0)
    if r == 0:
        return None
    return rv.value
Example #17
0
 def disableAuto(self):
     for i in range(0,10):
         enableAutoVideoProperty(self.cam, INT(i), INT(0))
Example #18
0
 def getVideoProps(self):
     vidprop = c_long()
     for i in range(0,10):
         getVideoProperty(self.cam, INT(i), byref(vidprop))
         print vidprop.value
Example #19
0
 def setContinuousMode(self):
     return setContinuousMode(self.cam, INT(0))
Example #20
0
 def shutDown(self):
     stopLive(self.cam)
     releaseGrabber(ctypes.byref(INT(self.cam)))
Example #21
0
def _io_control(ioControlCode,
                hDevice,
                inBuffer,
                outBuffer,
                outBufferSize=None):
    dwIoControlCode = DWORD(ioControlCode)

    if inBuffer is NULL:
        lpInBuffer = NULL
        nInBufferSize = INT(0)
    elif 'PyCPointerType' in str(type(inBuffer)):
        lpInBuffer = inBuffer
        nInBufferSize = INT(ctypes.sizeof(inBuffer.contents.__class__))
    else:
        lpInBuffer = ctypes.byref(inBuffer)
        nInBufferSize = INT(ctypes.sizeof(inBuffer.__class__))

    if outBuffer is NULL:
        lpOutBuffer = NULL
        nOutBufferSize = INT(0)

    elif 'PyCPointerType' in str(type(outBuffer)):
        lpOutBuffer = outBuffer
        if outBufferSize is None:
            nOutBufferSize = INT(ctypes.sizeof(outBuffer.contents.__class__))
        else:
            nOutBufferSize = INT(outBufferSize)
    else:
        lpOutBuffer = ctypes.byref(outBuffer)

        if outBufferSize is None:
            nOutBufferSize = INT(ctypes.sizeof(outBuffer.__class__))
        else:
            nOutBufferSize = INT(outBufferSize)

    lpNumberOfBytesTransferred = DWORD()
    lpOverlapped = OVERLAPPED()

    lpEventAttributes = NULL
    bManualReset = BOOL(False)
    bInitialState = BOOL(False)
    lpName = NULL

    lpOverlapped.hEvent = CreateEvent(lpEventAttributes, bManualReset,
                                      bInitialState, lpName)

    if not DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize,
                           lpOutBuffer, nOutBufferSize,
                           ctypes.byref(lpNumberOfBytesTransferred),
                           ctypes.byref(lpOverlapped)):
        err = ctypes.GetLastError()

        if err != ERROR_IO_PENDING:
            CancelIo(hDevice)
            CloseHandle(lpOverlapped.hEvent)
            return 0
        nCount = DWORD(1)
        bWaitAll = BOOL(False)
        dwMilliseconds = DWORD(INFINITE)

        lpHandles = (HANDLE * 1)(lpOverlapped.hEvent)

        response = WaitForMultipleObjects(nCount, lpHandles, bWaitAll,
                                          dwMilliseconds)

        if response == WAIT_OBJECT_0:
            bWait = BOOL(True)
            lpNumberOfBytesTransferred = DWORD()

            if not GetOverlappedResult(
                    hDevice, ctypes.byref(lpOverlapped),
                    ctypes.byref(lpNumberOfBytesTransferred), bWait):
                CancelIo(hDevice)
                CloseHandle(lpOverlapped.hEvent)
                raise ctypes.WinError()

            CloseHandle(lpOverlapped.hEvent)

            return lpNumberOfBytesTransferred.value

        CancelIo(hDevice)
        CloseHandle(lpOverlapped.hEvent)
        raise ctypes.WinError()

    CloseHandle(lpOverlapped.hEvent)
    return lpNumberOfBytesTransferred.value
Example #22
0
    def __receive_loop(self):
        with self.handle as hDevice:
            if self.use_alternate_receive:
                port = self.__get_first_rx_port()

                if port is None:
                    del self._process_queue[:]
                    self._process_event.set()
                    self._process_thread.join(1.0)
                    self._receive_thread = None
                    return

                with self._learn_lock:
                    inBuffer = IOCTL_IR_ENTER_PRIORITY_RECEIVE_PARAMS()
                    inBuffer.Receiver = port
                    inBuffer.TimeOut = self._packet_timeout

                    _io_control(IOCTL_IR_ENTER_PRIORITY_RECEIVE, hDevice,
                                inBuffer, NULL)

            self._process_thread = threading.Thread(target=self.__process_loop)
            self._process_thread.daemon = True
            self._process_thread.start()

            while not self._end_event.is_set():
                with self._learn_lock:
                    if self.use_alternate_receive:
                        dwIoControlCode = IOCTL_IR_PRIORITY_RECEIVE
                        outBuffer = IR_PRIORITY_RECEIVE_PARAMS()
                        outBuffer.ByteCount = 36
                        outBufferSize = ctypes.sizeof(
                            IR_PRIORITY_RECEIVE_PARAMS)
                        offset = ctypes.sizeof(ULONG)
                    else:
                        dwIoControlCode = IOCTL_IR_RECEIVE
                        outBuffer = IR_RECEIVE_PARAMS()
                        outBuffer.ByteCount = 36
                        outBufferSize = ctypes.sizeof(IR_RECEIVE_PARAMS)
                        offset = 0

                    offset += ctypes.sizeof(IR_ULONG_PTR) * 2

                    lpNumberOfBytesTransferred = DWORD()
                    lpOverlapped = OVERLAPPED()

                    lpEventAttributes = NULL
                    bManualReset = BOOL(False)
                    bInitialState = BOOL(False)
                    lpName = NULL

                    lpOverlapped.hEvent = CreateEvent(lpEventAttributes,
                                                      bManualReset,
                                                      bInitialState, lpName)

                    if not DeviceIoControl(
                            hDevice, DWORD(dwIoControlCode), NULL, INT(0),
                            ctypes.byref(outBuffer), INT(outBufferSize),
                            ctypes.byref(lpNumberOfBytesTransferred),
                            ctypes.byref(lpOverlapped)):
                        err = ctypes.GetLastError()

                        if err != ERROR_IO_PENDING:
                            CancelIo(hDevice)
                            CloseHandle(lpOverlapped.hEvent)
                            raise ctypes.WinError()

                        bWaitAll = BOOL(False)
                        dwMilliseconds = DWORD(INFINITE)

                        if dwIoControlCode == IOCTL_IR_PRIORITY_RECEIVE:
                            lpEventAttributes = NULL
                            bManualReset = BOOL(False)
                            bInitialState = BOOL(False)
                            lpName = NULL

                            hEvent = self.hEvent = CreateEvent(
                                lpEventAttributes, bManualReset, bInitialState,
                                lpName)

                            nCount = DWORD(2)
                            lpHandles = (HANDLE * 2)(lpOverlapped.hEvent,
                                                     hEvent)
                        else:
                            nCount = DWORD(1)
                            lpHandles = (HANDLE * 1)(lpOverlapped.hEvent)

                        response = WaitForMultipleObjects(
                            nCount, lpHandles, bWaitAll, dwMilliseconds)

                        if response == WAIT_OBJECT_0:
                            bWait = BOOL(True)

                            if not GetOverlappedResult(
                                    hDevice, ctypes.byref(lpOverlapped),
                                    ctypes.byref(lpNumberOfBytesTransferred),
                                    bWait):
                                err = ctypes.GetLastError()

                                if self.hEvent is not None:
                                    CloseHandle(self.hEvent)
                                    self.hEvent = None

                                CancelIo(hDevice)
                                CloseHandle(lpOverlapped.hEvent)
                                raise ctypes.WinError(err)

                        else:
                            if self.hEvent is not None:
                                CloseHandle(self.hEvent)
                                self.hEvent = None

                            CancelIo(hDevice)
                            CloseHandle(lpOverlapped.hEvent)

                            if self.hEvent is not None:
                                CloseHandle(self.hEvent)
                                self.hEvent = None

                            break

                    if self.hEvent is not None:
                        CloseHandle(self.hEvent)
                        self.hEvent = None

                    CloseHandle(lpOverlapped.hEvent)

                    byte_count = lpNumberOfBytesTransferred.value

                    data = []

                    byte_count -= offset
                    byte_count //= ctypes.sizeof(LONG)

                    if not byte_count:
                        continue

                    if dwIoControlCode == IOCTL_IR_PRIORITY_RECEIVE:
                        freq = outBuffer.CarrierFrequency
                    else:
                        freq = None

                    for i in range(byte_count):
                        data += [outBuffer.Data[i]]

                    self._process_queue.append((freq, data[:]))
                    self._process_event.set()

            if self.use_alternate_receive:
                _io_control(IOCTL_IR_EXIT_PRIORITY_RECEIVE, hDevice, NULL,
                            NULL)

        del self._process_queue[:]
        self._process_event.set()
        self._process_thread.join(1.0)
        self._receive_thread = None
Example #23
0
 def set_auto_exposure(self, enable=True):
     """Enable or disable the auto exposure shutter."""
     ret = lib.is_SetAutoParameter(self._hcam, IS_SET_ENABLE_AUTO_SHUTTER,
                                   pointer(INT(enable)), NULL)
     if ret != IS_SUCCESS:
         raise Error("Failed to set auto exposure property")
 def FreezeVideo(self, wait=IS_WAIT):
     CALL("FreezeVideo", self, INT(wait))
Example #25
0
    def learn(self, timeout=10.0):
        import time

        if self._receive_thread is not None and self.hEvent is not None:
            SetEvent(self.hEvent)

        self._learn_lock.acquire()

        with self.handle as hDevice:

            def exit_learn():
                if not self.use_alternate_receive:
                    _io_control(IOCTL_IR_EXIT_PRIORITY_RECEIVE, hDevice, NULL,
                                NULL)

                self._learn_lock.release()

            if not self.use_alternate_receive:
                port = self.__get_first_learn_port()

                if port is None:
                    return

                inBuffer = IOCTL_IR_ENTER_PRIORITY_RECEIVE_PARAMS()
                inBuffer.Receiver = port
                inBuffer.TimeOut = self._packet_timeout

                _io_control(IOCTL_IR_ENTER_PRIORITY_RECEIVE, hDevice, inBuffer,
                            NULL)

            result = []
            frequency = None

            start_time = time.time()

            while time.time() - start_time < timeout:
                if self.can_flash_led:
                    port = self.__get_first_learn_port()

                    inBuffer = ULONG(0 | (1 << port))
                    _io_control(IOCTL_IR_FLASH_RECEIVER, hDevice, inBuffer,
                                NULL)

                dwIoControlCode = IOCTL_IR_PRIORITY_RECEIVE
                outBuffer = IR_PRIORITY_RECEIVE_PARAMS()
                outBuffer.ByteCount = 32
                outBufferSize = ctypes.sizeof(IR_PRIORITY_RECEIVE_PARAMS)

                lpNumberOfBytesTransferred = DWORD()
                lpOverlapped = OVERLAPPED()

                lpEventAttributes = NULL
                bManualReset = BOOL(False)
                bInitialState = BOOL(False)
                lpName = NULL

                lpOverlapped.hEvent = CreateEvent(lpEventAttributes,
                                                  bManualReset, bInitialState,
                                                  lpName)

                if not DeviceIoControl(
                        hDevice, DWORD(dwIoControlCode), NULL, INT(0),
                        ctypes.byref(outBuffer), INT(outBufferSize),
                        ctypes.byref(lpNumberOfBytesTransferred),
                        ctypes.byref(lpOverlapped)):
                    err = ctypes.GetLastError()

                    if err != ERROR_IO_PENDING:
                        CancelIo(hDevice)
                        CloseHandle(lpOverlapped.hEvent)
                        raise ctypes.WinError()

                    bWaitAll = BOOL(False)
                    dwMilliseconds = DWORD(INFINITE)

                    lpEventAttributes = NULL
                    bManualReset = BOOL(False)
                    bInitialState = BOOL(False)
                    lpName = NULL

                    hEvent = self.hEvent = CreateEvent(lpEventAttributes,
                                                       bManualReset,
                                                       bInitialState, lpName)

                    nCount = DWORD(2)
                    lpHandles = (HANDLE * 2)(lpOverlapped.hEvent, hEvent)

                    response = WaitForMultipleObjects(nCount, lpHandles,
                                                      bWaitAll, dwMilliseconds)

                    if response == WAIT_OBJECT_0:
                        bWait = BOOL(True)

                        if not GetOverlappedResult(
                                hDevice, ctypes.byref(lpOverlapped),
                                ctypes.byref(lpNumberOfBytesTransferred),
                                bWait):
                            CancelIo(hDevice)
                            CloseHandle(hEvent)
                            self.hEvent = None
                            CloseHandle(lpOverlapped.hEvent)
                            raise ctypes.WinError()

                        CloseHandle(hEvent)

                    else:
                        CancelIo(hDevice)
                        CloseHandle(hEvent)
                        self.hEvent = None
                        CloseHandle(lpOverlapped.hEvent)
                        raise ctypes.WinError()

                CloseHandle(lpOverlapped.hEvent)

                if self._end_event.is_set():
                    exit_learn()
                    return

                byte_count = lpNumberOfBytesTransferred.value
                byte_count -= ((ctypes.sizeof(IR_ULONG_PTR) * 2) +
                               ctypes.sizeof(ULONG))

                if not byte_count:
                    continue

                byte_count //= ctypes.sizeof(LONG)

                if frequency is None:
                    frequency = outBuffer.CarrierFrequency.value
                else:
                    frequency = max(frequency,
                                    outBuffer.CarrierFrequency.value)

                for i in range(byte_count):
                    item = outBuffer.Data[i]
                    result.append(item)

                    if item < -6500:
                        if len(result) > 5:
                            code = decoder.decode(frequency, result[:])
                            exit_learn()
                            return code

                        del result[:]
                        frequency = None

            exit_learn()