# -*- python -*- # Copyright © 2014 Mattias Andrée (maandree@member.fsf.org) # # 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/>. cimport cython from libc.stdlib cimport malloc, free cdef extern void blueshift_drm_close() cdef extern int blueshift_drm_card_count() cdef extern int blueshift_drm_open_card(int card_index) cdef extern void blueshift_drm_update_card(int connection) cdef extern void blueshift_drm_close_card(int connection) cdef extern int blueshift_drm_crtc_count(int connection) cdef extern int blueshift_drm_connector_count(int connection) cdef extern int blueshift_drm_gamma_size(int connection, int crtc_index) cdef extern int blueshift_drm_get_gamma_ramps(int connection, int crtc_index, int gamma_size, unsigned short int* red, unsigned short int* green, unsigned short int* blue) cdef extern int blueshift_drm_set_gamma_ramps(int connection, int crtc_index, int gamma_size, unsigned short int* red, unsigned short int* green, unsigned short int* blue) cdef extern void blueshift_drm_open_connector(int connection, int connector_index) cdef extern void blueshift_drm_close_connector(int connection, int connector_index) cdef extern int blueshift_drm_get_width(int connection, int connector_index) cdef extern int blueshift_drm_get_height(int connection, int connector_index) cdef extern int blueshift_drm_is_connected(int connection, int connector_index) cdef extern int blueshift_drm_get_crtc(int connection, int connector_index) cdef extern int blueshift_drm_get_connector_type_index(int connection, int connector_index) cdef extern const char* blueshift_drm_get_connector_type_name(int connection, int connector_index) cdef extern long int blueshift_drm_get_edid(int connection, int connector_index, char* edid, long int size, int hexadecimal) cdef unsigned short int* r_shared cdef unsigned short int* g_shared cdef unsigned short int* b_shared r_shared = NULL g_shared = NULL b_shared = NULL def drm_close(): ''' Free all resources, but you need to close all connections first ''' global r_shared, g_shared, b_shared if r_shared is not NULL: free(r_shared) r_shared = NULL if g_shared is not NULL: free(g_shared) g_shared = NULL if b_shared is not NULL: free(b_shared) b_shared = NULL blueshift_drm_close() def drm_card_count(): ''' Get the number of cards present on the system @return :int The number of cards present on the system ''' return blueshift_drm_card_count() def drm_open_card(int card_index): ''' Open connection to a graphics card @param card_index The index of the graphics card @return :int -1 on failure, otherwise an identifier for the connection to the card ''' return blueshift_drm_open_card(card_index) def drm_update_card(int connection): ''' Update the resource, required after `blueshift_drm_open_card` @param connection The identifier for the connection to the card ''' blueshift_drm_update_card(connection) def drm_close_card(int connection): ''' Close connection to the graphics card @param connection The identifier for the connection to the card ''' blueshift_drm_close_card(connection) def drm_crtc_count(int connection): ''' Return the number of CRTC:s on the opened card @param connection The identifier for the connection to the card @return :int The number of CRTC:s on the opened card ''' return blueshift_drm_crtc_count(connection) def drm_connector_count(int connection): ''' Return the number of connectors on the opened card @param connection The identifier for the connection to the card @return :int The number of connectors on the opened card ''' return blueshift_drm_connector_count(connection) def drm_gamma_size(int connection, int crtc_index): ''' Return the size of the gamma ramps on a CRTC @param connection The identifier for the connection to the card @param crtc_index The index of the CRTC @return :int The size of the gamma ramps on a CRTC ''' return blueshift_drm_gamma_size(connection, crtc_index) def drm_get_gamma_ramps(int connection, int crtc_index, int gamma_size, threadsafe = False): ''' Get the gamma ramps of the of a monitor @param connection The identifier for the connection to the card @param crtc_index The index of the CRTC to read from @param gamma_size The size a gamma ramp @param threadsafe:bool Whether to decrease memory efficiency and performace so multiple threads can use DRM concurrently @return :(r:list<int>, g:list<int>, b:list<int>)? The current red, green and blue colour curves ''' global r_shared, g_shared, b_shared cdef unsigned short int* r cdef unsigned short int* g cdef unsigned short int* b if not threadsafe: if r_shared is NULL: r_shared = <unsigned short int*>malloc(gamma_size * 2) if g_shared is NULL: g_shared = <unsigned short int*>malloc(gamma_size * 2) if b_shared is NULL: b_shared = <unsigned short int*>malloc(gamma_size * 2) r = <unsigned short int*>malloc(gamma_size * 2) if threadsafe else r_shared g = <unsigned short int*>malloc(gamma_size * 2) if threadsafe else g_shared b = <unsigned short int*>malloc(gamma_size * 2) if threadsafe else b_shared if (r is NULL) or (g is NULL) or (b is NULL): raise MemoryError() rc = blueshift_drm_get_gamma_ramps(connection, crtc_index, gamma_size, r, g, b) if rc == 0: rc_r, rc_g, rc_b = [], [], [] for i in range(gamma_size): rc_r.append(r[i]) rc_g.append(g[i]) rc_b.append(b[i]) if threadsafe: free(r) free(g) free(b) return (rc_r, rc_g, rc_b) else: if threadsafe: free(r) free(g) free(b) return None def drm_set_gamma_ramps(int connection, crtc_indices, int gamma_size, r_curve, g_curve, b_curve, threadsafe = False): ''' Set the gamma ramps of the of a monitor @param connection The identifier for the connection to the card @param crtc_index:list<int> The index of the CRTC to read from @param gamma_size The size a gamma ramp @param r_curve:list<unsigned short int> The red gamma ramp @param g_curve:list<unsigned short int> The green gamma ramp @param b_curve:list<unsigned short int> The blue gamma ramp @param threadsafe:bool Whether to decrease memory efficiency and performace so multiple threads can use DRM concurrently @return :int Zero on success ''' global r_shared, g_shared, b_shared cdef unsigned short int* r cdef unsigned short int* g cdef unsigned short int* b if not threadsafe: if r_shared is NULL: r_shared = <unsigned short int*>malloc(gamma_size * 2) if g_shared is NULL: g_shared = <unsigned short int*>malloc(gamma_size * 2) if b_shared is NULL: b_shared = <unsigned short int*>malloc(gamma_size * 2) r = <unsigned short int*>malloc(gamma_size * 2) if threadsafe else r_shared g = <unsigned short int*>malloc(gamma_size * 2) if threadsafe else g_shared b = <unsigned short int*>malloc(gamma_size * 2) if threadsafe else b_shared if (r is NULL) or (g is NULL) or (b is NULL): raise MemoryError() for i in range(gamma_size): r[i] = r_curve[i] & 0xFFFF g[i] = g_curve[i] & 0xFFFF b[i] = b_curve[i] & 0xFFFF rc = 0 for crtc_index in crtc_indices: rc |= blueshift_drm_set_gamma_ramps(connection, crtc_index, gamma_size, r, g, b) if threadsafe: free(r) free(g) free(b) return rc def drm_open_connector(int connection, int connector_index): ''' Acquire information about a connector @param connection The identifier for the connection to the card @param connector_index The index of the connector ''' blueshift_drm_open_connector(connection, connector_index) def drm_close_connector(int connection, int connector_index): ''' Release information about a connector @param connection The identifier for the connection to the card @param connector_index The index of the connector ''' blueshift_drm_close_connector(connection, connector_index) def drm_get_width(int connection, int connector_index): ''' Get the physical width the monitor connected to a connector @param connection The identifier for the connection to the card @param connector_index The index of the connector @return :int The physical width of the monitor in millimetres, 0 if unknown or not connected ''' return blueshift_drm_get_width(connection, connector_index) def drm_get_height(int connection, int connector_index): ''' Get the physical height the monitor connected to a connector @param connection The identifier for the connection to the card @param connector_index The index of the connector @return :int The physical height of the monitor in millimetres, 0 if unknown or not connected ''' return blueshift_drm_get_height(connection, connector_index) def drm_is_connected(int connection, int connector_index): ''' Get whether a monitor is connected to a connector @param connection The identifier for the connection to the card @param connector_index The index of the connector @return :int 1 if there is a connection, 0 otherwise, -1 if unknown ''' return blueshift_drm_is_connected(connection, connector_index) def drm_get_crtc(int connection, int connector_index): ''' Get the index of the CRTC of the monitor connected to a connector @param connection The identifier for the connection to the card @param connector_index The index of the connector @return :int The index of the CRTC ''' return blueshift_drm_get_crtc(connection, connector_index) def drm_get_connector_type_index(int connection, int connector_index): ''' Get the index of the type of a connector @param connection The identifier for the connection to the card @param connector_index The index of the connector @return :int The connector type by index, 0 for unknown ''' return blueshift_drm_get_connector_type_index(connection, connector_index) def drm_get_connector_type_name(int connection, int connector_index): ''' Get the name of the type of a connector @param connection The identifier for the connection to the card @param connector_index The index of the connector @return :str The connector type by name, "Unknown" if not identifiable, "Unrecognised" if Blueshift does not recognise it. ''' return (<bytes>blueshift_drm_get_connector_type_name(connection, connector_index)).decode('utf-8', 'replace') def drm_get_edid(int connection, int connector_index): ''' Get the extended display identification data for the monitor connected to a connector @param connection The identifier for the connection to the card @param connector_index The index of the connector @return :str? The extended display identification data for the monitor ''' global edid_shared cdef long int size cdef long int got cdef char* edid cdef bytes rc size = 256 edid = <char*>malloc(size + 1) if edid is NULL: raise MemoryError() got = blueshift_drm_get_edid(connection, connector_index, edid, size, 1) if got == 0: free(edid) return None if got * 2 > size: size = got blueshift_drm_get_edid(connection, connector_index, edid, size, 1) edid[got * 2] = 0 rc = edid free(edid) return rc.decode('utf-8', 'replace')