<commit_before># Y axis is elevation
import os
import quaternion as q
import numpy as np
import pykitti
import matplotlib.pyplot as plt
from scipy.misc import imread

def load_images(sequences=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], img_root='processed_imgs_128', path=''):
    '''
    Load images from KITTI dataset. Pass in dir to change the images to use.
    Gets images from:
        deep-visual-odometry/dataset/<img_root>/sequence(0-11)
    args:
        sequences:
            sequences to grab images from (defaults 0-11)

        img_root:
            folder to grab images from

    returns:
        list of 11 lists,

        if i in sequences:
            list[i] = np.array(<images in sequence i>,x,y,image_channels)

        if i not in sequences:
            list[i] = #empty list

    Ex: dir = 'processed_imgs_128'
    gets data from:

        deep-visual-odometry/dataset/processed_imgs_128/sequence#
    '''

    #origional: images_directory = "/home/sexy/Documents/dataset/processed_imgs_128/sequence"
    if path:
        images_directory = os.path.join(path, img_root, 'sequence')
    else:
        PATH = os.path.dirname(os.path.abspath(__file__))
        images_directory = os.path.join(PATH, '..', '..', 'dataset', img_root, 'sequence')

    list_x = []

    #read number of channels in image
    test_image_dim = imread(os.path.join(images_directory+'0', os.listdir(images_directory+'0')[0])).shape
    image_channels = test_image_dim[2]
    image_x = test_image_dim[0]
    image_y = test_image_dim[1]

    for i in range(11):
        if i in sequences:
            #get and append image data
            dirs = os.listdir(images_directory+str(i))
            dirs.sort()
            array = np.zeros((len(dirs), image_x, image_y, image_channels), dtype='uint8')
            for j, dirj in enumerate(dirs):
                array[j, :, :, :] = imread(os.path.join(images_directory+str(i), dirj))
            list_x.append(array)
        else:
            #append empty array if not in sequences
            list_x.append([])
    return list_x

def load_poses(sequences=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], global_trans=False, path=''):
    '''
    Load poses from KITTI dataset.

    Directory Structure (kitta dataset):
        deep-visual-odometry/dataset/

    args:
        sequences:
            sequences to grab poses from (defaults 0-11)

    returns:
        list of 2 list, each containing 11 lists (list[0,1][1,...,11],

        if i in sequences:
            list[0][i] = relative delta translation (numpy array (1x3))
            list[1][i] = relative quaternion rotation (numpy array (1x4))

        if i not in sequences:
            list[0][i] = empty list
            list[1][i] = empty list
    '''
    # original: poses_directory = "/home/sexy/Documents/dataset/"
    PATH = os.path.dirname(os.path.abspath(__file__))
    if path:
        poses_directory = path
    else:
        poses_directory = os.path.join(PATH, '..', '..', 'dataset')
    poses = [[], []]
    for i in range(11):
        if i in sequences:
            #Get and append odometry data
            data = pykitti.odometry(poses_directory, str(i).zfill(2))
            data.load_poses()

            #Empty arrays to hold data
            translations = np.zeros((len(data.T_w_cam0), 3))
            quaternions = np.zeros(len(data.T_w_cam0), dtype=q.quaternion)
            delta_trans = np.zeros((len(data.T_w_cam0), 3))
            relative_delta_trans = np.zeros((len(data.T_w_cam0), 3))
            delta_quat = np.zeros(len(data.T_w_cam0), dtype=q.quaternion)

            #store quaternions and translations
            for j in range(len(data.T_w_cam0)):
                translations[j, :] = data.T_w_cam0[j][:-1, -1]
                quaternions[j] = (q.from_rotation_matrix(data.T_w_cam0[j][:-1, :-1])).normalized()

            #Get translations between frames
            delta_trans[:-1, :] = translations[1:, :]-translations[:-1, :]

            if global_trans:
                poses[0].append(delta_trans[:-1])
                poses[1].append([])
                continue

            #Correct translations to provide relative motion from car's perspective
            for k in range(len(delta_trans)-1):
                relative_delta_trans[k] = (quaternions[k]* q.quaternion(0., *delta_trans[k])
                                           *quaternions[k].conj()).vec

            #get rotations between frames
            delta_quat[:-1] = quaternions[1:]/quaternions[:-1]

            poses[0].append(relative_delta_trans[:-1])
            poses[1].append(q.as_float_array(delta_quat[:-1]))
        else:
            #append empty sequence if not in sequences
            poses[0].append([])
            poses[1].append([])
    return poses

def get_training_data(sequences=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], training_ratio=(1.0), image_dir='', seperate_images=False, no_quaternions=False, global_trans=False, data_path='', no_test=False):
    '''
    get training data from the KITTI dataset
    args:
        sequences:
            List of training sequences to use

        training_ratio:
            fraction of available data to include in train (default 1.0),
            function will not return test data if it is set to 1.0

        image_dir:
            directory to load images from

        seperate_images:
            True: format the x_tr and x_te as a list of two images
            False: format the x_tr and x_te as a stacked image of RGBRGB

        no_quaternions:
            True: returns only a y_tr and y_te of translations
            False: returns y_tr and y_te of translations and rotations

        no_test:
            True: return only x_tr and y_tr
            False: returns all x_tr, y_tr, x_te, y_te

        path:
            provides the path to the dataset directory
            defaults to Alec's Windows configurations

        seperate_images:
            bool wheteher to have first and second images

        no_quaternions:
            bool whether to include quaternions as second list of output

        no_test:
            do not retrun test sequences

    returns:
        x_tr:
            train imput data

        y_tr:
            train output data: [0]=translations, [1]=rotations

        x_te: (if training ratio is not 1.0)
            test inputs

        y_te: (if training ratio is not 1.0)
            test outputs: [0]=translations, [1]=rotations
    '''

    ind = []
    ind_total = []

    if no_test:
        training_ratio = 1.0

    if global_trans:
        no_quaternions = True

    #load data
    if data_path:
        if image_dir:
            images = load_images(sequences, image_dir, path=data_path)
        else:
            images = load_images(sequences, path=data_path)
        poses = load_poses(sequences, data_path)
    else:
        if image_dir:
            images = load_images(sequences, image_dir)
        else:
            images = load_images(sequences)
        poses = load_poses(sequences, global_trans=global_trans)

    #set dimenstions of images
    image_channels = images[sequences[0]].shape[3]
    image_size_y = images[sequences[0]].shape[2]
    image_size_x = images[sequences[0]].shape[1]
    #get indices for data slicing
    for i in range(11):
        if i in sequences:
            ind_total.append(np.size(images[i], axis=0))
            ind.append(int(ind_total[i]*training_ratio))
        else:
            ind_total.append(0)
            ind.append(0)

    #Init with empty matrices
    if seperate_images:
        x_tr = [[],[]]
        x_te = [[],[]]
        x_tr[0] = np.zeros((sum(ind)-len(sequences), image_size_x,
                        image_size_y, image_channels), dtype="uint8")
        x_tr[1] = np.zeros((sum(ind)-len(sequences), image_size_x,
                        image_size_y, image_channels), dtype="uint8")
        x_te[0] = np.zeros((sum(ind_total)-sum(ind), image_size_x,
                        image_size_y, image_channels), dtype="uint8")
        x_te[1] = np.zeros((sum(ind_total)-sum(ind), image_size_x,
                        image_size_y, image_channels), dtype="uint8")
    else:
        x_tr = np.zeros((sum(ind)-len(sequences), image_size_x,
                        image_size_y, image_channels*2), dtype="uint8")
        x_te = np.zeros((sum(ind_total)-sum(ind), image_size_x,
                        image_size_y, image_channels*2), dtype="uint8")

    if no_quaternions:
        y_tr = np.zeros((sum(ind)-len(sequences), 3))
        y_te = np.zeros((sum(ind_total)-sum(ind), 3))
    else:
        y_tr = [[], []]
        y_te = [[], []]
        y_tr[0] = np.zeros((sum(ind)-len(sequences), 3))
        y_tr[1] = np.zeros((sum(ind)-len(sequences), 4))
        y_te[0] = np.zeros((sum(ind_total)-sum(ind), 3))
        y_te[1] = np.zeros((sum(ind_total)-sum(ind), 4))

    count_tr = 0
    count_te = 0
    for i in sequences:

        #Get training data for sequence i
        if seperate_images:
            x_tr[0][count_tr:count_tr+ind[i]-1, :, :, :] = images[i][:ind[i]-1, :, :, :]
            x_tr[1][count_tr:count_tr+ind[i]-1, :, :, :] = images[i][1:ind[i], :, :, :]
        else:
            x_tr[count_tr:count_tr+ind[i]-1, :, :, :image_channels] = images[i][:ind[i]-1, :, :, :]
            x_tr[count_tr:count_tr+ind[i]-1, :, :, image_channels:] = images[i][1:ind[i], :, :, :]
        if no_quaternions:
            y_tr[count_tr:count_tr+ind[i]-1, :] = poses[0][i][:ind[i]-1, :]
        else:
            y_tr[0][count_tr:count_tr+ind[i]-1, :] = poses[0][i][:ind[i]-1, :]
            y_tr[1][count_tr:count_tr+ind[i]-1, :] = poses[1][i][:ind[i]-1, :]

        #Get testing data for sequence i
        if seperate_images:
            x_te[0][count_te:count_te+(ind_total[i]-ind[i]),
                :, :, :] = images[i][(ind[i]-1):-1, :, :, :]

            x_te[1][count_te:count_te+(ind_total[i]-ind[i]),
                :, :, :] = images[i][ind[i]:, :, :, :]
        else:
            x_te[count_te:count_te+(ind_total[i]-ind[i]),
                :, :, :image_channels] = images[i][(ind[i]-1):-1, :, :, :]

            x_te[count_te:count_te+(ind_total[i]-ind[i]),
                :, :, image_channels:] = images[i][ind[i]:, :, :, :]

        if no_quaternions:
            y_te[count_te:count_te+(ind_total[i]-ind[i]), :] = poses[0][i][ind[i]-1:, :]
        else:
            y_te[0][count_te:count_te+(ind_total[i]-ind[i]), :] = poses[0][i][ind[i]-1:, :]
            y_te[1][count_te:count_te+(ind_total[i]-ind[i]), :] = poses[1][i][ind[i]-1:, :]

        count_tr += ind[i]-1
        count_te += (ind_total[i]-ind[i])

    if training_ratio == 1.0:
        return x_tr, y_tr
    else:
        return x_tr, y_tr, x_te, y_te

def test_datatool():
    '''
    Test function for datatool
    uses sequence 1 (the smallest sequence)
    '''
    get_training_data([1])
    get_training_data([1], seperate_images=False, no_quaternions=True)
    get_training_data([1], seperate_images=True, global_trans=True)
test_datatool()

<commit_msg>update datatool<commit_after># Y axis is elevation
import os
import quaternion as q
import numpy as np
import pykitti
import matplotlib.pyplot as plt
from scipy.misc import imread

def load_images(sequences=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], img_root='processed_imgs_128', path=''):
    '''
    Load images from KITTI dataset. Pass in dir to change the images to use.
    Gets images from:
        deep-visual-odometry/dataset/<img_root>/sequence(0-11)
    args:
        sequences:
            sequences to grab images from (defaults 0-11)

        img_root:
            folder to grab images from

    returns:
        list of 11 lists,

        if i in sequences:
            list[i] = np.array(<images in sequence i>,x,y,image_channels)

        if i not in sequences:
            list[i] = #empty list

    Ex: dir = 'processed_imgs_128'
    gets data from:

        deep-visual-odometry/dataset/processed_imgs_128/sequence#
    '''

    #origional: images_directory = "/home/sexy/Documents/dataset/processed_imgs_128/sequence"
    if path:
        images_directory = os.path.join(path, img_root, 'sequence')
    else:
        PATH = os.path.dirname(os.path.abspath(__file__))
        images_directory = os.path.join(PATH, '..', '..', 'dataset', img_root, 'sequence')

    list_x = []

    #read number of channels in image
    test_image_dim = imread(os.path.join(images_directory+'0', os.listdir(images_directory+'0')[0])).shape
    image_channels = test_image_dim[2]
    image_x = test_image_dim[0]
    image_y = test_image_dim[1]

    for i in range(11):
        if i in sequences:
            #get and append image data
            dirs = os.listdir(images_directory+str(i))
            dirs.sort()
            array = np.zeros((len(dirs), image_x, image_y, image_channels), dtype='uint8')
            for j, dirj in enumerate(dirs):
                array[j, :, :, :] = imread(os.path.join(images_directory+str(i), dirj))
            list_x.append(array)
        else:
            #append empty array if not in sequences
            list_x.append([])
    return list_x

def load_poses(sequences=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], global_trans=False, path=''):
    '''
    Load poses from KITTI dataset.

    Directory Structure (kitta dataset):
        deep-visual-odometry/dataset/

    args:
        sequences:
            sequences to grab poses from (defaults 0-11)

    returns:
        list of 2 list, each containing 11 lists (list[0,1][1,...,11],

        if i in sequences:
            list[0][i] = relative delta translation (numpy array (1x3))
            list[1][i] = relative quaternion rotation (numpy array (1x4))

        if i not in sequences:
            list[0][i] = empty list
            list[1][i] = empty list
    '''
    # original: poses_directory = "/home/sexy/Documents/dataset/"
    PATH = os.path.dirname(os.path.abspath(__file__))
    if path:
        poses_directory = path
    else:
        poses_directory = os.path.join(PATH, '..', '..', 'dataset')
    poses = [[], []]
    for i in range(11):
        if i in sequences:
            #Get and append odometry data
            data = pykitti.odometry(poses_directory, str(i).zfill(2))
            data.load_poses()

            #Empty arrays to hold data
            translations = np.zeros((len(data.T_w_cam0), 3))
            quaternions = np.zeros(len(data.T_w_cam0), dtype=q.quaternion)
            delta_trans = np.zeros((len(data.T_w_cam0), 3))
            relative_delta_trans = np.zeros((len(data.T_w_cam0), 3))
            delta_quat = np.zeros(len(data.T_w_cam0), dtype=q.quaternion)

            #store quaternions and translations
            for j in range(len(data.T_w_cam0)):
                translations[j, :] = data.T_w_cam0[j][:-1, -1]
                quaternions[j] = (q.from_rotation_matrix(data.T_w_cam0[j][:-1, :-1])).normalized()

            #Get translations between frames
            delta_trans[:-1, :] = translations[1:, :]-translations[:-1, :]

            if global_trans:
                poses[0].append(delta_trans[:-1])
                poses[1].append([])
                continue

            #Correct translations to provide relative motion from car's perspective
            for k in range(len(delta_trans)-1):
                relative_delta_trans[k] = (quaternions[k]* q.quaternion(0., *delta_trans[k])
                                           *quaternions[k].conj()).vec

            #get rotations between frames
            delta_quat[:-1] = quaternions[1:]/quaternions[:-1]

            poses[0].append(relative_delta_trans[:-1])
            poses[1].append(q.as_float_array(delta_quat[:-1]))
        else:
            #append empty sequence if not in sequences
            poses[0].append([])
            poses[1].append([])
    return poses

def get_training_data(sequences=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], training_ratio=(1.0), image_dir='', seperate_images=False, no_quaternions=False, global_trans=False, data_path='', no_test=False):
    '''
    get training data from the KITTI dataset
    args:
        sequences:
            List of training sequences to use

        training_ratio:
            fraction of available data to include in train (default 1.0),
            function will not return test data if it is set to 1.0

        image_dir:
            directory to load images from

        seperate_images:
            True: format the x_tr and x_te as a list of two images
            False: format the x_tr and x_te as a stacked image of RGBRGB

        no_quaternions:
            True: returns only a y_tr and y_te of translations
            False: returns y_tr and y_te of translations and rotations

        no_test:
            True: return only x_tr and y_tr
            False: returns all x_tr, y_tr, x_te, y_te

        path:
            provides the path to the dataset directory
            defaults to Alec's Windows configurations

        seperate_images:
            bool wheteher to have first and second images

        no_quaternions:
            bool whether to include quaternions as second list of output

        no_test:
            do not retrun test sequences

    returns:
        x_tr:
            train imput data

        y_tr:
            train output data: [0]=translations, [1]=rotations

        x_te: (if training ratio is not 1.0)
            test inputs

        y_te: (if training ratio is not 1.0)
            test outputs: [0]=translations, [1]=rotations
    '''

    ind = []
    ind_total = []

    if no_test:
        training_ratio = 1.0

    if global_trans:
        no_quaternions = True

    #load data
    if data_path:
        if image_dir:
            images = load_images(sequences, image_dir, path=data_path)
        else:
            images = load_images(sequences, path=data_path)
        poses = load_poses(sequences, data_path)
    else:
        if image_dir:
            images = load_images(sequences, image_dir)
        else:
            images = load_images(sequences)
        poses = load_poses(sequences, global_trans=global_trans)

    #set dimenstions of images
    image_channels = images[sequences[0]].shape[3]
    image_size_y = images[sequences[0]].shape[2]
    image_size_x = images[sequences[0]].shape[1]
    #get indices for data slicing
    for i in range(11):
        if i in sequences:
            ind_total.append(np.size(images[i], axis=0))
            ind.append(int(ind_total[i]*training_ratio))
        else:
            ind_total.append(0)
            ind.append(0)

    #Init with empty matrices
    if seperate_images:
        x_tr = [[],[]]
        x_te = [[],[]]
        x_tr[0] = np.zeros((sum(ind)-len(sequences), image_size_x,
                        image_size_y, image_channels), dtype="uint8")
        x_tr[1] = np.zeros((sum(ind)-len(sequences), image_size_x,
                        image_size_y, image_channels), dtype="uint8")
        x_te[0] = np.zeros((sum(ind_total)-sum(ind), image_size_x,
                        image_size_y, image_channels), dtype="uint8")
        x_te[1] = np.zeros((sum(ind_total)-sum(ind), image_size_x,
                        image_size_y, image_channels), dtype="uint8")
    else:
        x_tr = np.zeros((sum(ind)-len(sequences), image_size_x,
                        image_size_y, image_channels*2), dtype="uint8")
        x_te = np.zeros((sum(ind_total)-sum(ind), image_size_x,
                        image_size_y, image_channels*2), dtype="uint8")

    if no_quaternions:
        y_tr = np.zeros((sum(ind)-len(sequences), 3))
        y_te = np.zeros((sum(ind_total)-sum(ind), 3))
    else:
        y_tr = [[], []]
        y_te = [[], []]
        y_tr[0] = np.zeros((sum(ind)-len(sequences), 3))
        y_tr[1] = np.zeros((sum(ind)-len(sequences), 4))
        y_te[0] = np.zeros((sum(ind_total)-sum(ind), 3))
        y_te[1] = np.zeros((sum(ind_total)-sum(ind), 4))

    count_tr = 0
    count_te = 0
    for i in sequences:

        #Get training data for sequence i
        if seperate_images:
            x_tr[0][count_tr:count_tr+ind[i]-1, :, :, :] = images[i][:ind[i]-1, :, :, :]
            x_tr[1][count_tr:count_tr+ind[i]-1, :, :, :] = images[i][1:ind[i], :, :, :]
        else:
            x_tr[count_tr:count_tr+ind[i]-1, :, :, :image_channels] = images[i][:ind[i]-1, :, :, :]
            x_tr[count_tr:count_tr+ind[i]-1, :, :, image_channels:] = images[i][1:ind[i], :, :, :]
        if no_quaternions:
            y_tr[count_tr:count_tr+ind[i]-1, :] = poses[0][i][:ind[i]-1, :]
        else:
            y_tr[0][count_tr:count_tr+ind[i]-1, :] = poses[0][i][:ind[i]-1, :]
            y_tr[1][count_tr:count_tr+ind[i]-1, :] = poses[1][i][:ind[i]-1, :]

        #Get testing data for sequence i
        if seperate_images:
            x_te[0][count_te:count_te+(ind_total[i]-ind[i]),
                :, :, :] = images[i][(ind[i]-1):-1, :, :, :]

            x_te[1][count_te:count_te+(ind_total[i]-ind[i]),
                :, :, :] = images[i][ind[i]:, :, :, :]
        else:
            x_te[count_te:count_te+(ind_total[i]-ind[i]),
                :, :, :image_channels] = images[i][(ind[i]-1):-1, :, :, :]

            x_te[count_te:count_te+(ind_total[i]-ind[i]),
                :, :, image_channels:] = images[i][ind[i]:, :, :, :]

        if no_quaternions:
            y_te[count_te:count_te+(ind_total[i]-ind[i]), :] = poses[0][i][ind[i]-1:, :]
        else:
            y_te[0][count_te:count_te+(ind_total[i]-ind[i]), :] = poses[0][i][ind[i]-1:, :]
            y_te[1][count_te:count_te+(ind_total[i]-ind[i]), :] = poses[1][i][ind[i]-1:, :]

        count_tr += ind[i]-1
        count_te += (ind_total[i]-ind[i])

    if training_ratio == 1.0:
        return x_tr, y_tr
    else:
        return x_tr, y_tr, x_te, y_te

def test_datatool():
    '''
    Test function for datatool
    uses sequence 1 (the smallest sequence)
    '''
    get_training_data([1])
    get_training_data([1], seperate_images=False, no_quaternions=True)
    get_training_data([1], seperate_images=True, global_trans=True)
#test_datatool()
<|endoftext|>


<commit_before>#!/usr/bin/env python
#
# Copyright 2012 Fairwaves
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
import struct, socket
# pylint: disable = C0301, C0103, C0111, R0903, R0913

UDP_CONTROL_PORT = 49152
UDP_MAX_XFER_BYTES = 1024
UDP_TIMEOUT = 1
UDP_POLL_INTERVAL = 0.10 #in seconds
USRP2_CONTROL_PROTO_VERSION = 11 # Must match firmware proto. We're setting it in detect()
supported_control_proto_versions = [11, 12]

# see fw_common.h
CONTROL_FMT = '!LLL24x'
CONTROL_IP_FMT = '!LLLL20x'
SPI_FMT = '!LLLLLBBBB12x'
ZPU_ACTION_FMT = '!LLLLL16x'

n2xx_revs = {
  0x0a00: ["n200_r3", "n200_r2"],
  0x0a10: ["n200_r4"],
  0x0a01: ["n210_r3", "n210_r2"],
  0x0a11: ["n210_r4"],
  0xfa00: ["umtrx"],
  }

# remember kids: drugs are bad...
USRP2_CTRL_ID_HUH_WHAT = ord(' ')
USRP2_CTRL_ID_WAZZUP_BRO = ord('a')
USRP2_CTRL_ID_WAZZUP_DUDE = ord('A')
UMTRX_CTRL_ID_REQUEST = ord('u')
UMTRX_CTRL_ID_RESPONSE = ord('U')
USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO = ord('s')
USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE = ord('S')
USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO = ord('i')
USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE = ord('I')
USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO = ord('h')
USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE = ord('H')
USRP2_CTRL_ID_GET_THIS_REGISTER_FOR_ME_BRO = ord('r')
USRP2_CTRL_ID_OMG_GOT_REGISTER_SO_BAD_DUDE = ord('R')
USRP2_CTRL_ID_HOLLER_AT_ME_BRO = ord('l')
USRP2_CTRL_ID_HOLLER_BACK_DUDE = ord('L')
UMTRX_CTRL_ID_ZPU_REQUEST  = ord('z')
UMTRX_CTRL_ID_ZPU_RESPONSE = ord('Z')
USRP2_CTRL_ID_PEACE_OUT = ord('~')
SPI_EDGE_RISE = ord('r')
SPI_EDGE_FALL = ord('f')
UMTRX_ZPU_REQUEST_GET_VCTCXO_DAC = 1
UMTRX_ZPU_REQUEST_SET_VCTCXO_DAC = 2

def unpack_format(_str, fmt):
    return struct.unpack(fmt, _str)

def pack_control_fmt(proto_ver, pktid, seq):
    return struct.pack(CONTROL_FMT, proto_ver, pktid, seq)

def pack_spi_fmt(proto_ver, pktid, seq, dev, data, miso, mosi, bits, read):
    return struct.pack(SPI_FMT, proto_ver, pktid, seq, dev, data, miso, mosi, bits, read)

def pack_zpu_action_fmt(proto_ver, pktid, seq, action, data):
    return struct.pack(ZPU_ACTION_FMT, proto_ver, pktid, seq, action, data)

def recv_item(skt, fmt, chk, ind):
    try:
        pkt = skt.recv(UDP_MAX_XFER_BYTES)
        pkt_list = unpack_format(pkt, fmt)
#        print("Received %d bytes: %x, '%c', %x" % (len(pkt), pkt_list[0], pkt_list[1], pkt_list[2]))
        if pkt_list[1] != chk:
            return (None,None)
        return (pkt_list[ind],pkt_list[0])
    except socket.timeout:
        return (None,None)

def ping(skt, addr):
    skt.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    out_pkt = pack_control_fmt(USRP2_CONTROL_PROTO_VERSION, UMTRX_CTRL_ID_REQUEST, 0)
    skt.sendto(out_pkt, (addr, UDP_CONTROL_PORT))
    return recv_item(skt, CONTROL_FMT, UMTRX_CTRL_ID_RESPONSE, 1)

def detect(skt, bcast_addr):
    global USRP2_CONTROL_PROTO_VERSION
#    print('Detecting UmTRX over %s:' % bcast_addr)
    skt.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    out_pkt = pack_control_fmt(USRP2_CONTROL_PROTO_VERSION, UMTRX_CTRL_ID_REQUEST, 0)
#    print(" Sending %d bytes: %x, '%c',.." % (len(out_pkt), USRP2_CONTROL_PROTO_VERSION, UMTRX_CTRL_ID_REQUEST))
    skt.sendto(out_pkt, (bcast_addr, UDP_CONTROL_PORT))
    response,version = recv_item(skt, CONTROL_IP_FMT, UMTRX_CTRL_ID_RESPONSE, 3)
    if version is None or response is None:
        return None
    if not version in supported_control_proto_versions:
        print("Error: You Firmware is too old! Your protocol ver: %d. Protocol ver required: [%s]\n"
              % (version, ", ".join([str(x) for x in supported_control_proto_versions])))
    # If we support this version - use it
    USRP2_CONTROL_PROTO_VERSION = version
    return socket.inet_ntoa(struct.pack("<L", socket.ntohl(response)))

class umtrx_dev_spi:
    """ A class for talking to a device sitting on the SPI bus of UmTRX """

    def __init__(self, umtrx_socket, net_address, spi_bus_number, out_edge=SPI_EDGE_RISE, in_edge=SPI_EDGE_RISE):
        """ spi_bus_number - a number of SPI bus to read/write """
        self.skt = umtrx_socket
        self.addr = net_address
        self.spi_num = spi_bus_number
        self.out_edge = out_edge
        self.in_edge = in_edge

    def spi_rw(self, data, num_bits, readback):
        """ Write data to SPI bus and optionally read some data back.
        data - data to write to the SPI bus
        num_bits - number of bits of data to read/write
        readback - 1 to read data from SPI bus, 0 to ignore data on the bus """
        self.skt.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 0)
        out_pkt = pack_spi_fmt(USRP2_CONTROL_PROTO_VERSION, USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO, \
                               0, self.spi_num, data, self.in_edge, self.out_edge, num_bits, readback)
        self.skt.sendto(out_pkt, (self.addr, UDP_CONTROL_PORT))
        ret,_ = recv_item(self.skt, SPI_FMT, USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE, 4)
        return ret

class umtrx_lms_device:

    def __init__(self, umtrx_socket, net_address, lms_number):
        self.spi = umtrx_dev_spi(umtrx_socket, net_address, lms_number)
        self.verbosity = 0

    def reg_read(self, reg):
        data = self.spi.spi_rw(reg << 8, 16, 1)
        if self.verbosity > 0: print("REG READ  0x%x -> 0x%x" % (reg, data,))
        return data

    def reg_write(self, reg, data):
        if self.verbosity > 0: print("REG WRITE 0x%x <- 0x%x" % (reg, data,))
        self.spi.spi_rw(((0x80 | reg) << 8) | data, 16, 0)

    def reg_rmw(self, reg, action):
        """ Read-Modify-Write for LMS register.
        'action' is a lambda(x) expression """
        reg_save = self.reg_read(reg)
        reg_val = action(reg_save)
        self.reg_write(reg, reg_val)
        return reg_save

    def reg_set_bits(self, reg, mask):
        return self.reg_rmw(reg, lambda x: x | int(mask))

    def reg_clear_bits(self, reg, mask):
        return self.reg_rmw(reg, lambda x: x & ~int(mask))

    def reg_write_bits(self, reg, mask, data):
        return self.reg_rmw(reg, lambda x: (x & ~int(mask)) | int(data))

    def reg_get_bits(self, reg, mask, shift):
        return (self.reg_read(reg)&int(mask)) >> shift

class umtrx_vcxo_dac:

    def __init__(self, umtrx_socket, net_address):
        self.skt = umtrx_socket
        self.addr = net_address
#        self.spi = umtrx_dev_spi(umtrx_socket, net_address, 4, out_edge=SPI_EDGE_FALL)

    def zpu_action(self, action, data=0):
        self.skt.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 0)
        out_pkt = pack_zpu_action_fmt(USRP2_CONTROL_PROTO_VERSION, UMTRX_CTRL_ID_ZPU_REQUEST, \
                                      0, action, data)
        self.skt.sendto(out_pkt, (self.addr, UDP_CONTROL_PORT))
        ret,_ = recv_item(self.skt, ZPU_ACTION_FMT, UMTRX_CTRL_ID_ZPU_RESPONSE, 4)
        return ret

    def set_dac(self, v):
        self.zpu_action(UMTRX_ZPU_REQUEST_SET_VCTCXO_DAC, v)

    def get_dac(self):
        return self.zpu_action(UMTRX_ZPU_REQUEST_GET_VCTCXO_DAC)

def create_umtrx_lms_device(lms_number, ip_address=None, bcast_addr="192.168.10.255"):
    ''' Fabric function to create UmTRX LMS device class '''
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.settimeout(UDP_TIMEOUT)
    umtrx_addr = detect(sock, ip_address if ip_address is not None else bcast_addr)
    umtrx_lms_dev = None
    if umtrx_addr is not None: # UmTRX address established
        if ping(sock, umtrx_addr): # UmTRX probed
            umtrx_lms_dev = umtrx_lms_device(sock, umtrx_addr, lms_number)
    return umtrx_lms_dev
<commit_msg>umtrx_ctrl: LMS registers are 8-bit - cut the junk bits.<commit_after>#!/usr/bin/env python
#
# Copyright 2012 Fairwaves
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
import struct, socket
# pylint: disable = C0301, C0103, C0111, R0903, R0913

UDP_CONTROL_PORT = 49152
UDP_MAX_XFER_BYTES = 1024
UDP_TIMEOUT = 1
UDP_POLL_INTERVAL = 0.10 #in seconds
USRP2_CONTROL_PROTO_VERSION = 11 # Must match firmware proto. We're setting it in detect()
supported_control_proto_versions = [11, 12]

# see fw_common.h
CONTROL_FMT = '!LLL24x'
CONTROL_IP_FMT = '!LLLL20x'
SPI_FMT = '!LLLLLBBBB12x'
ZPU_ACTION_FMT = '!LLLLL16x'

n2xx_revs = {
  0x0a00: ["n200_r3", "n200_r2"],
  0x0a10: ["n200_r4"],
  0x0a01: ["n210_r3", "n210_r2"],
  0x0a11: ["n210_r4"],
  0xfa00: ["umtrx"],
  }

# remember kids: drugs are bad...
USRP2_CTRL_ID_HUH_WHAT = ord(' ')
USRP2_CTRL_ID_WAZZUP_BRO = ord('a')
USRP2_CTRL_ID_WAZZUP_DUDE = ord('A')
UMTRX_CTRL_ID_REQUEST = ord('u')
UMTRX_CTRL_ID_RESPONSE = ord('U')
USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO = ord('s')
USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE = ord('S')
USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO = ord('i')
USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE = ord('I')
USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO = ord('h')
USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE = ord('H')
USRP2_CTRL_ID_GET_THIS_REGISTER_FOR_ME_BRO = ord('r')
USRP2_CTRL_ID_OMG_GOT_REGISTER_SO_BAD_DUDE = ord('R')
USRP2_CTRL_ID_HOLLER_AT_ME_BRO = ord('l')
USRP2_CTRL_ID_HOLLER_BACK_DUDE = ord('L')
UMTRX_CTRL_ID_ZPU_REQUEST  = ord('z')
UMTRX_CTRL_ID_ZPU_RESPONSE = ord('Z')
USRP2_CTRL_ID_PEACE_OUT = ord('~')
SPI_EDGE_RISE = ord('r')
SPI_EDGE_FALL = ord('f')
UMTRX_ZPU_REQUEST_GET_VCTCXO_DAC = 1
UMTRX_ZPU_REQUEST_SET_VCTCXO_DAC = 2

def unpack_format(_str, fmt):
    return struct.unpack(fmt, _str)

def pack_control_fmt(proto_ver, pktid, seq):
    return struct.pack(CONTROL_FMT, proto_ver, pktid, seq)

def pack_spi_fmt(proto_ver, pktid, seq, dev, data, miso, mosi, bits, read):
    return struct.pack(SPI_FMT, proto_ver, pktid, seq, dev, data, miso, mosi, bits, read)

def pack_zpu_action_fmt(proto_ver, pktid, seq, action, data):
    return struct.pack(ZPU_ACTION_FMT, proto_ver, pktid, seq, action, data)

def recv_item(skt, fmt, chk, ind):
    try:
        pkt = skt.recv(UDP_MAX_XFER_BYTES)
        pkt_list = unpack_format(pkt, fmt)
#        print("Received %d bytes: %x, '%c', %x" % (len(pkt), pkt_list[0], pkt_list[1], pkt_list[2]))
        if pkt_list[1] != chk:
            return (None,None)
        return (pkt_list[ind],pkt_list[0])
    except socket.timeout:
        return (None,None)

def ping(skt, addr):
    skt.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    out_pkt = pack_control_fmt(USRP2_CONTROL_PROTO_VERSION, UMTRX_CTRL_ID_REQUEST, 0)
    skt.sendto(out_pkt, (addr, UDP_CONTROL_PORT))
    return recv_item(skt, CONTROL_FMT, UMTRX_CTRL_ID_RESPONSE, 1)

def detect(skt, bcast_addr):
    global USRP2_CONTROL_PROTO_VERSION
#    print('Detecting UmTRX over %s:' % bcast_addr)
    skt.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    out_pkt = pack_control_fmt(USRP2_CONTROL_PROTO_VERSION, UMTRX_CTRL_ID_REQUEST, 0)
#    print(" Sending %d bytes: %x, '%c',.." % (len(out_pkt), USRP2_CONTROL_PROTO_VERSION, UMTRX_CTRL_ID_REQUEST))
    skt.sendto(out_pkt, (bcast_addr, UDP_CONTROL_PORT))
    response,version = recv_item(skt, CONTROL_IP_FMT, UMTRX_CTRL_ID_RESPONSE, 3)
    if version is None or response is None:
        return None
    if not version in supported_control_proto_versions:
        print("Error: You Firmware is too old! Your protocol ver: %d. Protocol ver required: [%s]\n"
              % (version, ", ".join([str(x) for x in supported_control_proto_versions])))
    # If we support this version - use it
    USRP2_CONTROL_PROTO_VERSION = version
    return socket.inet_ntoa(struct.pack("<L", socket.ntohl(response)))

class umtrx_dev_spi:
    """ A class for talking to a device sitting on the SPI bus of UmTRX """

    def __init__(self, umtrx_socket, net_address, spi_bus_number, out_edge=SPI_EDGE_RISE, in_edge=SPI_EDGE_RISE):
        """ spi_bus_number - a number of SPI bus to read/write """
        self.skt = umtrx_socket
        self.addr = net_address
        self.spi_num = spi_bus_number
        self.out_edge = out_edge
        self.in_edge = in_edge

    def spi_rw(self, data, num_bits, readback):
        """ Write data to SPI bus and optionally read some data back.
        data - data to write to the SPI bus
        num_bits - number of bits of data to read/write
        readback - 1 to read data from SPI bus, 0 to ignore data on the bus """
        self.skt.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 0)
        out_pkt = pack_spi_fmt(USRP2_CONTROL_PROTO_VERSION, USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO, \
                               0, self.spi_num, data, self.in_edge, self.out_edge, num_bits, readback)
        self.skt.sendto(out_pkt, (self.addr, UDP_CONTROL_PORT))
        ret,_ = recv_item(self.skt, SPI_FMT, USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE, 4)
        return ret

class umtrx_lms_device:

    def __init__(self, umtrx_socket, net_address, lms_number):
        self.spi = umtrx_dev_spi(umtrx_socket, net_address, lms_number)
        self.verbosity = 0

    def reg_read(self, reg):
        data = self.spi.spi_rw(reg << 8, 16, 1) & ((1<<8)-1)
        if self.verbosity > 0: print("REG READ  0x%x -> 0x%x" % (reg, data,))
        return data

    def reg_write(self, reg, data):
        if self.verbosity > 0: print("REG WRITE 0x%x <- 0x%x" % (reg, data,))
        self.spi.spi_rw(((0x80 | reg) << 8) | data, 16, 0)

    def reg_rmw(self, reg, action):
        """ Read-Modify-Write for LMS register.
        'action' is a lambda(x) expression """
        reg_save = self.reg_read(reg)
        reg_val = action(reg_save)
        self.reg_write(reg, reg_val)
        return reg_save

    def reg_set_bits(self, reg, mask):
        return self.reg_rmw(reg, lambda x: x | int(mask))

    def reg_clear_bits(self, reg, mask):
        return self.reg_rmw(reg, lambda x: x & ~int(mask))

    def reg_write_bits(self, reg, mask, data):
        return self.reg_rmw(reg, lambda x: (x & ~int(mask)) | int(data))

    def reg_get_bits(self, reg, mask, shift):
        return (self.reg_read(reg)&int(mask)) >> shift

class umtrx_vcxo_dac:

    def __init__(self, umtrx_socket, net_address):
        self.skt = umtrx_socket
        self.addr = net_address
#        self.spi = umtrx_dev_spi(umtrx_socket, net_address, 4, out_edge=SPI_EDGE_FALL)

    def zpu_action(self, action, data=0):
        self.skt.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 0)
        out_pkt = pack_zpu_action_fmt(USRP2_CONTROL_PROTO_VERSION, UMTRX_CTRL_ID_ZPU_REQUEST, \
                                      0, action, data)
        self.skt.sendto(out_pkt, (self.addr, UDP_CONTROL_PORT))
        ret,_ = recv_item(self.skt, ZPU_ACTION_FMT, UMTRX_CTRL_ID_ZPU_RESPONSE, 4)
        return ret

    def set_dac(self, v):
        self.zpu_action(UMTRX_ZPU_REQUEST_SET_VCTCXO_DAC, v)

    def get_dac(self):
        return self.zpu_action(UMTRX_ZPU_REQUEST_GET_VCTCXO_DAC)

def create_umtrx_lms_device(lms_number, ip_address=None, bcast_addr="192.168.10.255"):
    ''' Fabric function to create UmTRX LMS device class '''
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.settimeout(UDP_TIMEOUT)
    umtrx_addr = detect(sock, ip_address if ip_address is not None else bcast_addr)
    umtrx_lms_dev = None
    if umtrx_addr is not None: # UmTRX address established
        if ping(sock, umtrx_addr): # UmTRX probed
            umtrx_lms_dev = umtrx_lms_device(sock, umtrx_addr, lms_number)
    return umtrx_lms_dev
<|endoftext|>


<commit_before>import re

import ctypes

import win32functions
import win32structures
import handleprops

# currently commented out as finding the best match control
# requires that we know the Friendly class name - which is only
# known by the control wrappers - and I would prefer to keep
# this module from having that dependency.
#import findbestmatch

#=========================================================================
class WindowNotFoundError(Exception):
	pass

#=========================================================================
class WindowAmbiguousError(Exception):
	pass

#=========================================================================
def find_window(**kwargs):
	"Return the "
	windows = find_windows(**kwargs)

	if not windows:
		raise WindowNotFoundError()

	if len(windows) > 1:
		raise WindowAmbiguousError(
			"There are %d windows that match the criteria %s"% (
			len(windows),
			str(kwargs),
			)
		)

	return windows[0]

#=========================================================================
def find_windows(class_name = None,
				class_name_re = None,
				parent = None,
				process = None,
				title = None,
				title_re = None,
				top_level_only = True,
				visible_only = True,
				enabled_only = True,
				#best_match = None
	):
	"""Find windows based on criteria passed in

	Possible values are:
		class_name		Windows with this window class
		class_name_re	Windows whose class match this regular expression
		parent			Windows that are children of this
		process			Windows running in this process
		title			Windows with this Text
		title_re		Windows whose Text match this regular expression
		top_level_only	Top level windows only (default=True)
		visible_only	Visible windows only (default=True)
		enabled_only	Enabled windows only (default=True)
	"""

	if top_level_only:
		windows = enum_windows()

		if parent:
			windows = [win for win in windows if win.Parent == parent]

	else:
		if parent:
			windows = enum_child_windows(parent)
		else:
			# find all the children of the desktop
			parent = win32functions.GetDesktopWindow()
			windows = enum_child_windows(parent)

			windows = [win for win in windows if handleprops.parent(win) == parent]

	if class_name and windows:
		windows = [win for win in windows if class_name == handleprops.classname(win)]

	if class_name_re and windows:
		windows = [win for win in windows
			if re.match(class_name_re, handleprops.classname(win))]

	if process and windows:
		try:
			process_id = process.ProcessID
		except AttributeError:
			process_id = process

		windows = [win for win in windows if process == process_id]

	if title and windows:
		windows = [win for win in windows
			if title == handleprops.text(win)]

	elif title_re and windows:
		windows = [win for win in windows
			if re.match(title_re, handleprops.text(win))]

#	elif best_match and windows:
#		windows = [findbestmatch.find_best_control_match(best_match, wins),]

	if visible_only and windows:
		windows = [win for win in windows if handleprops.isvisible(win)]

	if enabled_only and windows:
		windows = [win for win in windows if handleprops.isenabled(win)]

	return windows

#=========================================================================
def enum_windows():
	"Return a list of handles of all the top level windows"
	windows = []

	# The callback function that will be called for each HWND
	# all we do is append the wrapped handle
	def enum_win_proc(hwnd, lparam):
		windows.append(hwnd)
		return True

	# define the type of the child procedure
	EnumWindowProc = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_long, ctypes.c_long)

	# 'construct' the callback with our function
	proc = EnumWindowProc(enum_win_proc)

	# loop over all the children (callback called for each)
	win32functions.EnumWindows(proc, 0)

	# return the collected wrapped windows
	return windows

#=========================================================================
def enum_child_windows(handle):
	"Return a list of handles of the child windows of this handle"

	# this will be filled in the callback function
	childWindows = []

	# callback function for EnumChildWindows
	def enumChildProc(hWnd, lparam):

		# append it to our list
		childWindows.append(hWnd)

		# return true to keep going
		return True

	# define the child proc type
	EnumChildProc = ctypes.WINFUNCTYPE(
		ctypes.c_int, 			# return type
		win32structures.HWND, 	# the window handle
		win32structures.LPARAM)	# extra information

	proc = EnumChildProc(enumChildProc)

	# loop over all the children (callback called for each)
	win32functions.EnumChildWindows(handle, proc, 0)

	return childWindows

#=========================================================================
def Main():
	windows = find_windows(
		class_name_re = "#32770",
		enabled_only = False,
		visible_only = False)

	for win in windows:
		print "==" * 20
		print handleprops.dumpwindow(win)

if __name__ == "__main__":
	Main()<commit_msg>Fixed the process restriction which had been broken<commit_after>import re

import ctypes

import win32functions
import win32structures
import handleprops

# currently commented out as finding the best match control
# requires that we know the Friendly class name - which is only
# known by the control wrappers - and I would prefer to keep
# this module from having that dependency.
#import findbestmatch

#=========================================================================
class WindowNotFoundError(Exception):
	pass

#=========================================================================
class WindowAmbiguousError(Exception):
	pass

#=========================================================================
def find_window(**kwargs):
	"Return the "
	windows = find_windows(**kwargs)

	if not windows:
		raise WindowNotFoundError()

	if len(windows) > 1:
		raise WindowAmbiguousError(
			"There are %d windows that match the criteria %s"% (
			len(windows),
			str(kwargs),
			)
		)

	return windows[0]

#=========================================================================
def find_windows(class_name = None,
				class_name_re = None,
				parent = None,
				process = None,
				title = None,
				title_re = None,
				top_level_only = True,
				visible_only = True,
				enabled_only = True,
				#best_match = None
	):
	"""Find windows based on criteria passed in

	Possible values are:
		class_name		Windows with this window class
		class_name_re	Windows whose class match this regular expression
		parent			Windows that are children of this
		process			Windows running in this process
		title			Windows with this Text
		title_re		Windows whose Text match this regular expression
		top_level_only	Top level windows only (default=True)
		visible_only	Visible windows only (default=True)
		enabled_only	Enabled windows only (default=True)
	"""

	if top_level_only:
		windows = enum_windows()

		if parent:
			windows = [win for win in windows if win.Parent == parent]

	else:
		if parent:
			windows = enum_child_windows(parent)
		else:
			# find all the children of the desktop
			parent = win32functions.GetDesktopWindow()
			windows = enum_child_windows(parent)

			windows = [win for win in windows if handleprops.parent(win) == parent]

	if class_name and windows:
		windows = [win for win in windows if class_name == handleprops.classname(win)]

	if class_name_re and windows:
		windows = [win for win in windows
			if re.match(class_name_re, handleprops.classname(win))]

	if process and windows:
		windows = [win for win in windows if handleprops.processid(win) == process]

	if title and windows:
		windows = [win for win in windows
			if title == handleprops.text(win)]

	elif title_re and windows:
		windows = [win for win in windows
			if re.match(title_re, handleprops.text(win))]

#	elif best_match and windows:
#		windows = [findbestmatch.find_best_control_match(best_match, wins),]

	if visible_only and windows:
		windows = [win for win in windows if handleprops.isvisible(win)]

	if enabled_only and windows:
		windows = [win for win in windows if handleprops.isenabled(win)]

	return windows

#=========================================================================
def enum_windows():
	"Return a list of handles of all the top level windows"
	windows = []

	# The callback function that will be called for each HWND
	# all we do is append the wrapped handle
	def enum_win_proc(hwnd, lparam):
		windows.append(hwnd)
		return True

	# define the type of the child procedure
	EnumWindowProc = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_long, ctypes.c_long)

	# 'construct' the callback with our function
	proc = EnumWindowProc(enum_win_proc)

	# loop over all the children (callback called for each)
	win32functions.EnumWindows(proc, 0)

	# return the collected wrapped windows
	return windows

#=========================================================================
def enum_child_windows(handle):
	"Return a list of handles of the child windows of this handle"

	# this will be filled in the callback function
	childWindows = []

	# callback function for EnumChildWindows
	def enumChildProc(hWnd, lparam):

		# append it to our list
		childWindows.append(hWnd)

		# return true to keep going
		return True

	# define the child proc type
	EnumChildProc = ctypes.WINFUNCTYPE(
		ctypes.c_int, 			# return type
		win32structures.HWND, 	# the window handle
		win32structures.LPARAM)	# extra information

	proc = EnumChildProc(enumChildProc)

	# loop over all the children (callback called for each)
	win32functions.EnumChildWindows(handle, proc, 0)

	return childWindows

#=========================================================================
def Main():
	windows = find_windows(
		class_name_re = "#32770",
		enabled_only = False,
		visible_only = False)

	for win in windows:
		print "==" * 20
		print handleprops.dumpwindow(win)

if __name__ == "__main__":
	Main()<|endoftext|>


<commit_before># GUI Application automation and testing library
# Copyright (C) 2006 Mark Mc Mahon
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation; either version 2.1
# of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
#    Free Software Foundation, Inc.,
#    59 Temple Place,
#    Suite 330,
#    Boston, MA 02111-1307 USA

"""Functions to retrieve properties from a window handle

These are implemented in a procedural way so as to to be
useful to other modules with the least conceptual overhead
"""
from __future__ import absolute_import

__revision__ = "$Revision$"

import ctypes

from . import win32functions
from . import win32defines
from . import win32structures

#=========================================================================
def text(handle):
    "Return the text of the window"

#    length = ctypes.c_long()
#    win32functions.SendMessageTimeout(
#        handle,
#        win32defines.WM_GETTEXTLENGTH,
#        0,
#        0,
#        win32defines.SMTO_ABORTIFHUNG,
#        100,  # .1 of a second
#        ctypes.byref(length))
#    length = length.value

    class_name = classname(handle)
    if class_name == 'IME':
        return 'Default IME'
    if class_name == 'MSCTFIME UI':
        return 'M'
    length = win32functions.SendMessage(handle, win32defines.WM_GETTEXTLENGTH, 0, 0)
    '''
    # XXX: there are some very rare cases when WM_GETTEXTLENGTH hangs!
    c_length = win32structures.DWORD(0)
    result = win32functions.SendMessageTimeout(handle, win32defines.WM_GETTEXTLENGTH, 0, 0, win32defines.SMTO_ABORTIFHUNG, 500, ctypes.byref(c_length))
    if result == 0:
        print('WARNING! Cannot retrieve text length for handle = ' + str(handle))
        return ''
    else:
        length = c_length.value
    '''
    textval = ''
    if length:
        length += 1

        buffer_ = ctypes.create_unicode_buffer(length)

        ret = win32functions.SendMessage(
            handle, win32defines.WM_GETTEXT, length, ctypes.byref(buffer_))

        if ret:
            textval = buffer_.value

    return textval

#=========================================================================
def classname(handle):
    "Return the class name of the window"
    class_name = (ctypes.c_wchar * 257)()
    win32functions.GetClassName (handle, ctypes.byref(class_name), 256)
    return class_name.value

#=========================================================================
def parent(handle):
    "Return the handle of the parent of the window"
    return win32functions.GetParent(handle)

#=========================================================================
def style(handle):
    "Return the style of the window"
    return win32functions.GetWindowLong (handle, win32defines.GWL_STYLE)

#=========================================================================
def exstyle(handle):
    "Return the extended style of the window"
    return win32functions.GetWindowLong (handle, win32defines.GWL_EXSTYLE)

#=========================================================================
def controlid(handle):
    "Return the ID of the control"
    return win32functions.GetWindowLong (handle, win32defines.GWL_ID)

#=========================================================================
def userdata(handle):
    "Return the value of any userdata associated with the window"
    return win32functions.GetWindowLong (handle, win32defines.GWL_USERDATA)

#=========================================================================
def contexthelpid(handle):
    "Return the context help id of the window"
    return win32functions.GetWindowContextHelpId (handle)

#=========================================================================
def iswindow(handle):
    "Return True if the handle is a window"
    return bool(win32functions.IsWindow(handle))

#=========================================================================
def isvisible(handle):
    "Return True if the window is visible"
    return bool(win32functions.IsWindowVisible(handle))

#=========================================================================
def isunicode(handle):
    "Return True if the window is a Unicode window"
    return bool(win32functions.IsWindowUnicode(handle))

#=========================================================================
def isenabled(handle):
    "Return True if the window is enabled"
    return bool(win32functions.IsWindowEnabled(handle))

#=========================================================================
def clientrect(handle):
    "Return the client rectangle of the control"
    client_rect = win32structures.RECT()
    win32functions.GetClientRect(handle, ctypes.byref(client_rect))
    return client_rect

#=========================================================================
def rectangle(handle):
    "Return the rectangle of the window"
    rect = win32structures.RECT()
    win32functions.GetWindowRect(handle, ctypes.byref(rect))
    return rect

#=========================================================================
def font(handle):
    "Return the font as a LOGFONTW of the window"

    # get the font handle
    font_handle = win32functions.SendMessage(
        handle, win32defines.WM_GETFONT, 0, 0)

    # if the fondUsed is 0 then the control is using the
    # system font (well probably not - even though that is what the docs say)
    # instead we switch to the default GUI font - which is more likely correct.
    if not font_handle:

        # So just get the default system font
        font_handle = win32functions.GetStockObject(win32defines.DEFAULT_GUI_FONT)

        # if we still don't have a font!
        # ----- ie, we're on an antiquated OS, like NT 3.51
        if not font_handle:

            # ----- On Asian platforms, ANSI font won't show.
            if win32functions.GetSystemMetrics(win32defines.SM_DBCSENABLED):
                # ----- was...(SYSTEM_FONT)
                font_handle = win32functions.GetStockObject(
                    win32defines.SYSTEM_FONT)
            else:
                # ----- was...(SYSTEM_FONT)
                font_handle = win32functions.GetStockObject(
                    win32defines.ANSI_VAR_FONT)

    else:
        fontval = win32structures.LOGFONTW()
        ret = win32functions.GetObject(
            font_handle, ctypes.sizeof(fontval), ctypes.byref(fontval))

    # Get the Logfont structure of the font of the control
    fontval = win32structures.LOGFONTW()
    ret = win32functions.GetObject(
        font_handle, ctypes.sizeof(fontval), ctypes.byref(fontval))

    # The function could not get the font - this is probably
    # because the control does not have associated Font/Text
    # So we should make sure the elements of the font are zeroed.
    if not ret:
        fontval = win32structures.LOGFONTW()

    # if it is a main window
    if is_toplevel_window(handle):

        if "MS Shell Dlg" in fontval.lfFaceName or \
            fontval.lfFaceName == "System":
            # these are not usually the fonts actaully used in for
            # title bars so we need to get the default title bar font

            # get the title font based on the system metrics rather
            # than the font of the control itself
            ncms = win32structures.NONCLIENTMETRICSW()
            ncms.cbSize = ctypes.sizeof(ncms)
            win32functions.SystemParametersInfo(
                win32defines.SPI_GETNONCLIENTMETRICS,
                ctypes.sizeof(ncms),
                ctypes.byref(ncms),
                0)

            # with either of the following 2 flags set the font of the
            # dialog isthe small one (but there is normally no difference!
            if has_style(handle, win32defines.WS_EX_TOOLWINDOW) or \
               has_style(handle, win32defines.WS_EX_PALETTEWINDOW):

                fontval = ncms.lfSmCaptionFont
            else:
                fontval = ncms.lfCaptionFont

    return fontval

#=========================================================================
def processid(handle):
    "Return the ID of process that controls this window"
    if ctypes.sizeof(ctypes.POINTER(ctypes.c_int)) == 8:
        process_id = ctypes.c_ulonglong()
    else:
        process_id = ctypes.c_ulong()
    win32functions.GetWindowThreadProcessId(handle, ctypes.byref(process_id))

    return process_id.value

#=========================================================================
def children(handle):
    "Return a list of handles to the children of this window"

    # this will be filled in the callback function
    child_windows = []

    # callback function for EnumChildWindows
    def EnumChildProc(hwnd, lparam):
        "Called for each child - adds child hwnd to list"

        # append it to our list
        child_windows.append(hwnd)

        # return true to keep going
        return True

    # define the child proc type
    enum_child_proc = ctypes.WINFUNCTYPE(
        ctypes.c_int, 			# return type
        win32structures.HWND, 	# the window handle
        win32structures.LPARAM)	# extra information

    # update the proc to the correct type
    proc = enum_child_proc(EnumChildProc)

    # loop over all the children (callback called for each)
    win32functions.EnumChildWindows(handle, proc, 0)

    return child_windows

#=========================================================================
def has_style(handle, tocheck):
    "Return True if the control has style tocheck"
    hwnd_style = style(handle)
    return tocheck & hwnd_style == tocheck

#=========================================================================
def has_exstyle(handle, tocheck):
    "Return True if the control has extended style tocheck"
    hwnd_exstyle = exstyle(handle)
    return tocheck & hwnd_exstyle == tocheck

#=========================================================================
def is_toplevel_window(handle):
    "Return whether the window is a top level window or not"

    # only request the style once - this is an optimization over calling
    # (handle, style) for each style I wan to check!
    style_ = style(handle)

    if (style_ & win32defines.WS_OVERLAPPED == win32defines.WS_OVERLAPPED or \
        style_ & win32defines.WS_CAPTION == win32defines.WS_CAPTION) and \
        not (style_ & win32defines.WS_CHILD == win32defines.WS_CHILD):
        return True
    else:
        return False

#=========================================================================
#def get_button_friendlyclassname(handle):
#    "Return the friendly class name of a button control"
#
#    # get the least significant bit
#    style_lsb = style(handle) & 0xF
#
#    # default to "Button"
#    f_classname = "Button"
#
#    if style_lsb == win32defines.BS_3STATE or \
#        style_lsb == win32defines.BS_AUTO3STATE or \
#        style_lsb == win32defines.BS_AUTOCHECKBOX or \
#        style_lsb == win32defines.BS_CHECKBOX:
#        f_classname = "CheckBox"
#
#    elif style_lsb == win32defines.BS_RADIOBUTTON or \
#        style_lsb == win32defines.BS_AUTORADIOBUTTON:
#        f_classname = "RadioButton"
#
#    elif style_lsb == win32defines.BS_GROUPBOX:
#        f_classname = "GroupBox"
#
#    if style(handle) & win32defines.BS_PUSHLIKE:
#        f_classname = "Button"
#
#    return f_classname

#def friendlyclassname(handle):
#    """Return the friendly class name of the window
#
#    The friendly class name might be subjective, but it
#    tries to be what a normal user would call a window
#    rather then the windows class name for the window.
#    """
#
#    import warnings
#    warnings.warn("handleprops.friendlyclassname() is deprecated. Please use"
#        "FriendlyClassMethod() of HwndWrapper",
#        DeprecationWarning)
#
#    # if it's a dialog then return that
#    if is_toplevel_window(handle) and classname(handle) == "#32770":
#        return "Dialog"
#
#    # otherwise ask the wrapper class for the friendly class name
#    class_name = classname(handle)
#
#    from controls import wraphandle
#    info = wraphandle._find_wrapper(class_name)
#
#    if info:
#       return info.friendlyclassname
#
#    else:
#        return class_name

#
#
#    # Check if the class name is in the known classes
#    for cls_name, f_cls_name in _class_names.items():
#
#        # OK we found it
#        if re.match(cls_name, classname(handle)):
#            # If it is a string then just return it
#            if isinstance(f_cls_name, six.string_types):
#                return f_cls_name
#            # otherwise it is a function so call it
#            else:
#                return f_cls_name(handle)
#
#    # unknown class - just return it's classname
#    return classname(handle)

#=========================================================================
def dumpwindow(handle):
    "Dump a window to a set of properties"
    props = {}

    for func in (
        text,
        classname,
        rectangle,
        clientrect,
        style,
        exstyle,
        contexthelpid,
        controlid,
        userdata,
        font,
        parent,
        processid,
        isenabled,
        isunicode,
        isvisible,
        children,
        ):

        props[func.__name__] = func(handle)

    return props

<commit_msg>Old forgotten patch in handleprops.py.<commit_after># GUI Application automation and testing library
# Copyright (C) 2006 Mark Mc Mahon
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation; either version 2.1
# of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
#    Free Software Foundation, Inc.,
#    59 Temple Place,
#    Suite 330,
#    Boston, MA 02111-1307 USA

"""Functions to retrieve properties from a window handle

These are implemented in a procedural way so as to to be
useful to other modules with the least conceptual overhead
"""
from __future__ import absolute_import

__revision__ = "$Revision$"

import ctypes

from . import win32functions
from . import win32defines
from . import win32structures

#=========================================================================
def text(handle):
    "Return the text of the window"

#    length = ctypes.c_long()
#    win32functions.SendMessageTimeout(
#        handle,
#        win32defines.WM_GETTEXTLENGTH,
#        0,
#        0,
#        win32defines.SMTO_ABORTIFHUNG,
#        100,  # .1 of a second
#        ctypes.byref(length))
#    length = length.value

    class_name = classname(handle)
    if class_name == 'IME':
        return 'Default IME'
    if class_name == 'MSCTFIME UI':
        return 'M'
    length = win32functions.SendMessage(handle, win32defines.WM_GETTEXTLENGTH, 0, 0)
    '''
    # XXX: there are some very rare cases when WM_GETTEXTLENGTH hangs!
    c_length = win32structures.DWORD(0)
    result = win32functions.SendMessageTimeout(handle, win32defines.WM_GETTEXTLENGTH, 0, 0, win32defines.SMTO_ABORTIFHUNG, 500, ctypes.byref(c_length))
    if result == 0:
        print('WARNING! Cannot retrieve text length for handle = ' + str(handle))
        return ''
    else:
        length = c_length.value
    '''
    textval = ''
    # In some rare cases, the length returned by WM_GETTEXTLENGTH is <0.
    # Guard against this by checking it is >0 (==0 is not of interest):
    if length > 0:
        length += 1

        buffer_ = ctypes.create_unicode_buffer(length)

        ret = win32functions.SendMessage(
            handle, win32defines.WM_GETTEXT, length, ctypes.byref(buffer_))

        if ret:
            textval = buffer_.value

    return textval

#=========================================================================
def classname(handle):
    "Return the class name of the window"
    class_name = (ctypes.c_wchar * 257)()
    win32functions.GetClassName (handle, ctypes.byref(class_name), 256)
    return class_name.value

#=========================================================================
def parent(handle):
    "Return the handle of the parent of the window"
    return win32functions.GetParent(handle)

#=========================================================================
def style(handle):
    "Return the style of the window"
    return win32functions.GetWindowLong (handle, win32defines.GWL_STYLE)

#=========================================================================
def exstyle(handle):
    "Return the extended style of the window"
    return win32functions.GetWindowLong (handle, win32defines.GWL_EXSTYLE)

#=========================================================================
def controlid(handle):
    "Return the ID of the control"
    return win32functions.GetWindowLong (handle, win32defines.GWL_ID)

#=========================================================================
def userdata(handle):
    "Return the value of any userdata associated with the window"
    return win32functions.GetWindowLong (handle, win32defines.GWL_USERDATA)

#=========================================================================
def contexthelpid(handle):
    "Return the context help id of the window"
    return win32functions.GetWindowContextHelpId (handle)

#=========================================================================
def iswindow(handle):
    "Return True if the handle is a window"
    return bool(win32functions.IsWindow(handle))

#=========================================================================
def isvisible(handle):
    "Return True if the window is visible"
    return bool(win32functions.IsWindowVisible(handle))

#=========================================================================
def isunicode(handle):
    "Return True if the window is a Unicode window"
    return bool(win32functions.IsWindowUnicode(handle))

#=========================================================================
def isenabled(handle):
    "Return True if the window is enabled"
    return bool(win32functions.IsWindowEnabled(handle))

#=========================================================================
def clientrect(handle):
    "Return the client rectangle of the control"
    client_rect = win32structures.RECT()
    win32functions.GetClientRect(handle, ctypes.byref(client_rect))
    return client_rect

#=========================================================================
def rectangle(handle):
    "Return the rectangle of the window"
    rect = win32structures.RECT()
    win32functions.GetWindowRect(handle, ctypes.byref(rect))
    return rect

#=========================================================================
def font(handle):
    "Return the font as a LOGFONTW of the window"

    # get the font handle
    font_handle = win32functions.SendMessage(
        handle, win32defines.WM_GETFONT, 0, 0)

    # if the fondUsed is 0 then the control is using the
    # system font (well probably not - even though that is what the docs say)
    # instead we switch to the default GUI font - which is more likely correct.
    if not font_handle:

        # So just get the default system font
        font_handle = win32functions.GetStockObject(win32defines.DEFAULT_GUI_FONT)

        # if we still don't have a font!
        # ----- ie, we're on an antiquated OS, like NT 3.51
        if not font_handle:

            # ----- On Asian platforms, ANSI font won't show.
            if win32functions.GetSystemMetrics(win32defines.SM_DBCSENABLED):
                # ----- was...(SYSTEM_FONT)
                font_handle = win32functions.GetStockObject(
                    win32defines.SYSTEM_FONT)
            else:
                # ----- was...(SYSTEM_FONT)
                font_handle = win32functions.GetStockObject(
                    win32defines.ANSI_VAR_FONT)

    else:
        fontval = win32structures.LOGFONTW()
        ret = win32functions.GetObject(
            font_handle, ctypes.sizeof(fontval), ctypes.byref(fontval))

    # Get the Logfont structure of the font of the control
    fontval = win32structures.LOGFONTW()
    ret = win32functions.GetObject(
        font_handle, ctypes.sizeof(fontval), ctypes.byref(fontval))

    # The function could not get the font - this is probably
    # because the control does not have associated Font/Text
    # So we should make sure the elements of the font are zeroed.
    if not ret:
        fontval = win32structures.LOGFONTW()

    # if it is a main window
    if is_toplevel_window(handle):

        if "MS Shell Dlg" in fontval.lfFaceName or \
            fontval.lfFaceName == "System":
            # these are not usually the fonts actaully used in for
            # title bars so we need to get the default title bar font

            # get the title font based on the system metrics rather
            # than the font of the control itself
            ncms = win32structures.NONCLIENTMETRICSW()
            ncms.cbSize = ctypes.sizeof(ncms)
            win32functions.SystemParametersInfo(
                win32defines.SPI_GETNONCLIENTMETRICS,
                ctypes.sizeof(ncms),
                ctypes.byref(ncms),
                0)

            # with either of the following 2 flags set the font of the
            # dialog isthe small one (but there is normally no difference!
            if has_style(handle, win32defines.WS_EX_TOOLWINDOW) or \
               has_style(handle, win32defines.WS_EX_PALETTEWINDOW):

                fontval = ncms.lfSmCaptionFont
            else:
                fontval = ncms.lfCaptionFont

    return fontval

#=========================================================================
def processid(handle):
    "Return the ID of process that controls this window"
    if ctypes.sizeof(ctypes.POINTER(ctypes.c_int)) == 8:
        process_id = ctypes.c_ulonglong()
    else:
        process_id = ctypes.c_ulong()
    win32functions.GetWindowThreadProcessId(handle, ctypes.byref(process_id))

    return process_id.value

#=========================================================================
def children(handle):
    "Return a list of handles to the children of this window"

    # this will be filled in the callback function
    child_windows = []

    # callback function for EnumChildWindows
    def EnumChildProc(hwnd, lparam):
        "Called for each child - adds child hwnd to list"

        # append it to our list
        child_windows.append(hwnd)

        # return true to keep going
        return True

    # define the child proc type
    enum_child_proc = ctypes.WINFUNCTYPE(
        ctypes.c_int, 			# return type
        win32structures.HWND, 	# the window handle
        win32structures.LPARAM)	# extra information

    # update the proc to the correct type
    proc = enum_child_proc(EnumChildProc)

    # loop over all the children (callback called for each)
    win32functions.EnumChildWindows(handle, proc, 0)

    return child_windows

#=========================================================================
def has_style(handle, tocheck):
    "Return True if the control has style tocheck"
    hwnd_style = style(handle)
    return tocheck & hwnd_style == tocheck

#=========================================================================
def has_exstyle(handle, tocheck):
    "Return True if the control has extended style tocheck"
    hwnd_exstyle = exstyle(handle)
    return tocheck & hwnd_exstyle == tocheck

#=========================================================================
def is_toplevel_window(handle):
    "Return whether the window is a top level window or not"

    # only request the style once - this is an optimization over calling
    # (handle, style) for each style I wan to check!
    style_ = style(handle)

    if (style_ & win32defines.WS_OVERLAPPED == win32defines.WS_OVERLAPPED or \
        style_ & win32defines.WS_CAPTION == win32defines.WS_CAPTION) and \
        not (style_ & win32defines.WS_CHILD == win32defines.WS_CHILD):
        return True
    else:
        return False

#=========================================================================
#def get_button_friendlyclassname(handle):
#    "Return the friendly class name of a button control"
#
#    # get the least significant bit
#    style_lsb = style(handle) & 0xF
#
#    # default to "Button"
#    f_classname = "Button"
#
#    if style_lsb == win32defines.BS_3STATE or \
#        style_lsb == win32defines.BS_AUTO3STATE or \
#        style_lsb == win32defines.BS_AUTOCHECKBOX or \
#        style_lsb == win32defines.BS_CHECKBOX:
#        f_classname = "CheckBox"
#
#    elif style_lsb == win32defines.BS_RADIOBUTTON or \
#        style_lsb == win32defines.BS_AUTORADIOBUTTON:
#        f_classname = "RadioButton"
#
#    elif style_lsb == win32defines.BS_GROUPBOX:
#        f_classname = "GroupBox"
#
#    if style(handle) & win32defines.BS_PUSHLIKE:
#        f_classname = "Button"
#
#    return f_classname

#def friendlyclassname(handle):
#    """Return the friendly class name of the window
#
#    The friendly class name might be subjective, but it
#    tries to be what a normal user would call a window
#    rather then the windows class name for the window.
#    """
#
#    import warnings
#    warnings.warn("handleprops.friendlyclassname() is deprecated. Please use"
#        "FriendlyClassMethod() of HwndWrapper",
#        DeprecationWarning)
#
#    # if it's a dialog then return that
#    if is_toplevel_window(handle) and classname(handle) == "#32770":
#        return "Dialog"
#
#    # otherwise ask the wrapper class for the friendly class name
#    class_name = classname(handle)
#
#    from controls import wraphandle
#    info = wraphandle._find_wrapper(class_name)
#
#    if info:
#       return info.friendlyclassname
#
#    else:
#        return class_name

#
#
#    # Check if the class name is in the known classes
#    for cls_name, f_cls_name in _class_names.items():
#
#        # OK we found it
#        if re.match(cls_name, classname(handle)):
#            # If it is a string then just return it
#            if isinstance(f_cls_name, six.string_types):
#                return f_cls_name
#            # otherwise it is a function so call it
#            else:
#                return f_cls_name(handle)
#
#    # unknown class - just return it's classname
#    return classname(handle)

#=========================================================================
def dumpwindow(handle):
    "Dump a window to a set of properties"
    props = {}

    for func in (
        text,
        classname,
        rectangle,
        clientrect,
        style,
        exstyle,
        contexthelpid,
        controlid,
        userdata,
        font,
        parent,
        processid,
        isenabled,
        isunicode,
        isvisible,
        children,
        ):

        props[func.__name__] = func(handle)

    return props

<|endoftext|>