Exemplo n.º 1
0
/**
 * Probes and initializes.
 */
static int Open (vlc_object_t *obj)
{
    services_discovery_t *sd = (services_discovery_t *)obj;
    services_discovery_sys_t *p_sys = malloc (sizeof (*p_sys));

    if (p_sys == NULL)
        return VLC_ENOMEM;
    sd->p_sys = p_sys;
    sd->description = _("Screen capture");

    /* Connect to X server */
    char *display = var_InheritString (obj, "x11-display");
    int snum;
    xcb_connection_t *conn = xcb_connect (display, &snum);
    free (display);
    if (xcb_connection_has_error (conn))
    {
        free (p_sys);
        return VLC_EGENERIC;
    }
    p_sys->conn = conn;

    /* Find configured screen */
    const xcb_setup_t *setup = xcb_get_setup (conn);
    const xcb_screen_t *scr = NULL;
    for (xcb_screen_iterator_t i = xcb_setup_roots_iterator (setup);
         i.rem > 0; xcb_screen_next (&i))
    {
        if (snum == 0)
        {
            scr = i.data;
            break;
        }
        snum--;
    }
    if (scr == NULL)
    {
        msg_Err (obj, "bad X11 screen number");
        goto error;
    }

    /* Add a permanent item for the entire desktop */
    AddDesktop (sd);

    p_sys->root_window = scr->root;
    xcb_change_window_attributes (conn, scr->root, XCB_CW_EVENT_MASK,
                               &(uint32_t) { XCB_EVENT_MASK_PROPERTY_CHANGE });

    /* TODO: check that _NET_CLIENT_LIST is in _NET_SUPPORTED
     * (and _NET_SUPPORTING_WM_CHECK) */
    xcb_intern_atom_reply_t *r;
    xcb_intern_atom_cookie_t ncl, nwn;

    ncl = xcb_intern_atom (conn, 1, strlen ("_NET_CLIENT_LIST"),
                          "_NET_CLIENT_LIST");
    nwn = xcb_intern_atom (conn, 0, strlen ("_NET_WM_NAME"), "_NET_WM_NAME");

    r = xcb_intern_atom_reply (conn, ncl, NULL);
    if (r == NULL || r->atom == 0)
    {
        vlc_dialog_display_error (sd, _("Screen capture"),
            _("Your window manager does not provide a list of applications."));
        msg_Err (sd, "client list not supported (_NET_CLIENT_LIST absent)");
    }
    p_sys->net_client_list = r ? r->atom : 0;
    free (r);
    r = xcb_intern_atom_reply (conn, nwn, NULL);
    if (r != NULL)
    {
        p_sys->net_wm_name = r->atom;
        free (r);
    }

    p_sys->apps = NULL;
    p_sys->apps_root = input_item_NewExt("vlc://nop", _("Applications"), -1,
                                         ITEM_TYPE_NODE, ITEM_LOCAL);
    if (likely(p_sys->apps_root != NULL))
        services_discovery_AddItem(sd, p_sys->apps_root);

    UpdateApps (sd);

    if (vlc_clone (&p_sys->thread, Run, sd, VLC_THREAD_PRIORITY_LOW))
        goto error;
    return VLC_SUCCESS;

error:
    xcb_disconnect (p_sys->conn);
    tdestroy (p_sys->apps, DelApp);
    if (p_sys->apps_root != NULL)
        input_item_Release(p_sys->apps_root);
    free (p_sys);
    return VLC_EGENERIC;
}
Exemplo n.º 2
0
int
randr_start(randr_state_t *state)
{
	xcb_generic_error_t *error;

	int screen_num = state->screen_num;
	if (screen_num < 0) screen_num = state->preferred_screen;

	/* Get screen */
	const xcb_setup_t *setup = xcb_get_setup(state->conn);
	xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
	state->screen = NULL;

	for (int i = 0; iter.rem > 0; i++) {
		if (i == screen_num) {
			state->screen = iter.data;
			break;
		}
		xcb_screen_next(&iter);
	}

	if (state->screen == NULL) {
		fprintf(stderr, _("Screen %i could not be found.\n"),
			screen_num);
		return -1;
	}

	/* Get list of CRTCs for the screen */
	xcb_randr_get_screen_resources_current_cookie_t res_cookie =
		xcb_randr_get_screen_resources_current(state->conn,
						       state->screen->root);
	xcb_randr_get_screen_resources_current_reply_t *res_reply =
		xcb_randr_get_screen_resources_current_reply(state->conn,
							     res_cookie,
							     &error);

	if (error) {
		fprintf(stderr, _("`%s' returned error %d\n"),
			"RANDR Get Screen Resources Current",
			error->error_code);
		return -1;
	}

	state->crtc_count = res_reply->num_crtcs;
	state->crtcs = calloc(state->crtc_count, sizeof(randr_crtc_state_t));
	if (state->crtcs == NULL) {
		perror("malloc");
		state->crtc_count = 0;
		return -1;
	}

	xcb_randr_crtc_t *crtcs =
		xcb_randr_get_screen_resources_current_crtcs(res_reply);

	/* Save CRTC identifier in state */
	for (int i = 0; i < state->crtc_count; i++) {
		state->crtcs[i].crtc = crtcs[i];
	}

	free(res_reply);

	/* Save size and gamma ramps of all CRTCs.
	   Current gamma ramps are saved so we can restore them
	   at program exit. */
	for (int i = 0; i < state->crtc_count; i++) {
		xcb_randr_crtc_t crtc = state->crtcs[i].crtc;

		/* Request size of gamma ramps */
		xcb_randr_get_crtc_gamma_size_cookie_t gamma_size_cookie =
			xcb_randr_get_crtc_gamma_size(state->conn, crtc);
		xcb_randr_get_crtc_gamma_size_reply_t *gamma_size_reply =
			xcb_randr_get_crtc_gamma_size_reply(state->conn,
							    gamma_size_cookie,
							    &error);

		if (error) {
			fprintf(stderr, _("`%s' returned error %d\n"),
				"RANDR Get CRTC Gamma Size",
				error->error_code);
			return -1;
		}

		unsigned int ramp_size = gamma_size_reply->size;
		state->crtcs[i].ramp_size = ramp_size;

		free(gamma_size_reply);

		if (ramp_size == 0) {
			fprintf(stderr, _("Gamma ramp size too small: %i\n"),
				ramp_size);
			return -1;
		}

		/* Request current gamma ramps */
		xcb_randr_get_crtc_gamma_cookie_t gamma_get_cookie =
			xcb_randr_get_crtc_gamma(state->conn, crtc);
		xcb_randr_get_crtc_gamma_reply_t *gamma_get_reply =
			xcb_randr_get_crtc_gamma_reply(state->conn,
						       gamma_get_cookie,
						       &error);

		if (error) {
			fprintf(stderr, _("`%s' returned error %d\n"),
				"RANDR Get CRTC Gamma", error->error_code);
			return -1;
		}

		uint16_t *gamma_r =
			xcb_randr_get_crtc_gamma_red(gamma_get_reply);
		uint16_t *gamma_g =
			xcb_randr_get_crtc_gamma_green(gamma_get_reply);
		uint16_t *gamma_b =
			xcb_randr_get_crtc_gamma_blue(gamma_get_reply);

		/* Allocate space for saved gamma ramps */
		state->crtcs[i].saved_ramps =
			malloc(3*ramp_size*sizeof(uint16_t));
		if (state->crtcs[i].saved_ramps == NULL) {
			perror("malloc");
			free(gamma_get_reply);
			return -1;
		}

		/* Copy gamma ramps into CRTC state */
		memcpy(&state->crtcs[i].saved_ramps[0*ramp_size], gamma_r,
		       ramp_size*sizeof(uint16_t));
		memcpy(&state->crtcs[i].saved_ramps[1*ramp_size], gamma_g,
		       ramp_size*sizeof(uint16_t));
		memcpy(&state->crtcs[i].saved_ramps[2*ramp_size], gamma_b,
		       ramp_size*sizeof(uint16_t));

		free(gamma_get_reply);
	}

	return 0;
}
Exemplo n.º 3
0
static void init_xcb()
{
    const xcb_query_extension_reply_t *qer;
    const xcb_setup_t *setup;
    xcb_screen_t *screen;
    xcb_screen_iterator_t screen_iter;
    xcb_drawable_t win;
    guint num_screens;
    guint i;
    xcb_generic_error_t *err = NULL;

    /* Open xcb connection */
    conn = xcb_connect(gdk_get_display_arg_name(), NULL);
    if (xcb_connection_has_error(conn)) {
        g_error("Failed to connect to display\n");
        exit(EXIT_FAILURE);
    }

    /* query the version to prevent error 16 when setting config */
    xcb_randr_query_version_unchecked(conn, 1, 5);

    qer = xcb_get_extension_data(conn, &xcb_randr_id);
    if (!qer || !qer->present) {
        g_error("RandR extension missing\n");
        exit(EXIT_FAILURE);
    }
    randr_base = qer->first_event;

    xcb_source = g_xcb_source_new_for_connection(NULL, conn);
    g_xcb_source_set_event_callback(xcb_source, on_xcb_event, NULL);

    /* get the screens */
    setup = xcb_get_setup(conn);
    screen_iter = xcb_setup_roots_iterator(setup);

    num_screens = setup->roots_len;

    /* Set up space for cookies */
    xcb_randr_get_screen_info_cookie_t get_screen_info_cookies[num_screens];

    for (i = 0; i < num_screens; i++) {
        /* Get root window */
        screen = screen_iter.data;
        win = screen->root;

        /* Register for screen change events */
        xcb_randr_select_input(conn, win, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);

        /* Get screen info */
        get_screen_info_cookies[i] =
            xcb_randr_get_screen_info_unchecked(conn, win);

        xcb_screen_next(&screen_iter);
    }
    /* TODO: detect adding and removal of screens */

    xcb_flush(conn);

    /* Get screen info replies */
    for (i = 0; i < num_screens; i++) {
        xcb_randr_get_screen_info_reply_t *reply =
            xcb_randr_get_screen_info_reply(conn,
                    get_screen_info_cookies[i], &err);
        if (err) {
            g_warning("Error getting info for screen %u\n", i);
            err = NULL;
            continue;
        }

        add_screen(reply);
        free(reply);
    }
    xcb_flush(conn);
}
Exemplo n.º 4
0
/* Get the number of outputs */
static unsigned CountMonitors( vlc_object_t *obj )
{
    char *psz_display = var_InheritString( obj, "x11-display" );
    int snum;
    xcb_connection_t *conn = xcb_connect( psz_display, &snum );
    free( psz_display );
    if( xcb_connection_has_error( conn ) )
        return 0;

    const xcb_setup_t *setup = xcb_get_setup( conn );
    xcb_screen_t *scr = NULL;
    for( xcb_screen_iterator_t i = xcb_setup_roots_iterator( setup );
         i.rem > 0; xcb_screen_next( &i ) )
    {
         if( snum == 0 )
         {
             scr = i.data;
             break;
         }
         snum--;
    }

    unsigned n = 0;
    if( scr == NULL )
        goto error;

    xcb_randr_query_version_reply_t *v =
        xcb_randr_query_version_reply( conn,
            xcb_randr_query_version( conn, 1, 2 ), NULL );
    if( v == NULL )
        goto error;
    msg_Dbg( obj, "using X RandR extension v%"PRIu32".%"PRIu32,
             v->major_version, v->minor_version );
    free( v );

    xcb_randr_get_screen_resources_reply_t *r =
        xcb_randr_get_screen_resources_reply( conn,
            xcb_randr_get_screen_resources( conn, scr->root ), NULL );
    if( r == NULL )
        goto error;

    const xcb_randr_output_t *outputs =
        xcb_randr_get_screen_resources_outputs( r );
    for( unsigned i = 0; i < r->num_outputs; i++ )
    {
        xcb_randr_get_output_info_reply_t *output =
            xcb_randr_get_output_info_reply( conn,
                xcb_randr_get_output_info( conn, outputs[i], 0 ), NULL );
        if( output == NULL )
            continue;
        /* FIXME: do not count cloned outputs multiple times */
        /* XXX: what to do with UNKNOWN state connections? */
        n += output->connection == XCB_RANDR_CONNECTION_CONNECTED;
        free( output );
    }
    free( r );
    msg_Dbg( obj, "X randr has %u outputs", n );

error:
    xcb_disconnect( conn );
    return n;
}
Exemplo n.º 5
0
int
main(int argc, char *argv[])
{
    int i;
    char *displayname = NULL;
    Bool all_screens = False;
    Bool verbose = False;
    xcb_connection_t *dpy;
    const xcb_setup_t *setup;
    int screen_number = 0;
    int maxcmdlen = 10000;

    ProgramName = argv[0];

    for (i = 1; i < argc; i++) {
	char *arg = argv[i];

	if (arg[0] == '-') {
	    char *cp;

	    switch (arg[1]) {
	      case 'd':			/* -display dpyname */
		if (++i >= argc) usage ();
		displayname = argv[i];
		continue;
	      case 'm':			/* -max maxcmdlen */
		if (++i >= argc) usage ();
		maxcmdlen = atoi (argv[i]);
		continue;
	      case 'v':			/* -version */
		printf("%s\n", PACKAGE_STRING);
		exit(0);
	    }

	    for (cp = &arg[1]; *cp; cp++) {
		switch (*cp) {
		  case 'a':		/* -all */
		    all_screens = True;
		    continue;
		  case 'l':		/* -long */
		    verbose = True;
		    continue;
		  default:
		    usage ();
		}
	    }
	} else {
	    usage ();
	}
    }

    dpy = xcb_connect(displayname, &screen_number);
    if (xcb_connection_has_error(dpy)) {
	const char *name = displayname;
	if (!name)
	    name = getenv("DISPLAY");
	if (!name)
	    name = "";
	fprintf (stderr, "%s:  unable to open display \"%s\"\r\n",
		 ProgramName, name);
	exit (1);
    }

    init_atoms(dpy);

    setup = xcb_get_setup(dpy);
    if (all_screens) {
	xcb_screen_iterator_t screen;

	screen = xcb_setup_roots_iterator(setup);
	do {
	    lookat(dpy, screen.data->root, verbose, maxcmdlen);
	    xcb_screen_next(&screen);
	} while (screen.rem);
    } else {
	xcb_screen_iterator_t screen;

	screen = xcb_setup_roots_iterator(setup);
	for (i = 0; i < screen_number; i++)
	    xcb_screen_next(&screen);

	lookat (dpy, screen.data->root, verbose, maxcmdlen);
    }

    run_queue();

    xcb_disconnect(dpy);
    exit (0);
}