153a5a1b3Sopenharmony_ci/***
253a5a1b3Sopenharmony_ci  This file is part of PulseAudio.
353a5a1b3Sopenharmony_ci
453a5a1b3Sopenharmony_ci  Copyright 2004-2006 Lennart Poettering
553a5a1b3Sopenharmony_ci
653a5a1b3Sopenharmony_ci  PulseAudio is free software; you can redistribute it and/or modify
753a5a1b3Sopenharmony_ci  it under the terms of the GNU Lesser General Public License as published
853a5a1b3Sopenharmony_ci  by the Free Software Foundation; either version 2.1 of the License,
953a5a1b3Sopenharmony_ci  or (at your option) any later version.
1053a5a1b3Sopenharmony_ci
1153a5a1b3Sopenharmony_ci  PulseAudio is distributed in the hope that it will be useful, but
1253a5a1b3Sopenharmony_ci  WITHOUT ANY WARRANTY; without even the implied warranty of
1353a5a1b3Sopenharmony_ci  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1453a5a1b3Sopenharmony_ci  General Public License for more details.
1553a5a1b3Sopenharmony_ci
1653a5a1b3Sopenharmony_ci  You should have received a copy of the GNU Lesser General Public License
1753a5a1b3Sopenharmony_ci  along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
1853a5a1b3Sopenharmony_ci***/
1953a5a1b3Sopenharmony_ci
2053a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H
2153a5a1b3Sopenharmony_ci#include <config.h>
2253a5a1b3Sopenharmony_ci#endif
2353a5a1b3Sopenharmony_ci
2453a5a1b3Sopenharmony_ci#include <string.h>
2553a5a1b3Sopenharmony_ci
2653a5a1b3Sopenharmony_ci#include "x11prop.h"
2753a5a1b3Sopenharmony_ci
2853a5a1b3Sopenharmony_ci#include <pulsecore/macro.h>
2953a5a1b3Sopenharmony_ci
3053a5a1b3Sopenharmony_ci#include <xcb/xproto.h>
3153a5a1b3Sopenharmony_ci
3253a5a1b3Sopenharmony_ci#define PA_XCB_FORMAT 8
3353a5a1b3Sopenharmony_ci
3453a5a1b3Sopenharmony_cistatic xcb_screen_t *screen_of_display(xcb_connection_t *xcb, int screen) {
3553a5a1b3Sopenharmony_ci    const xcb_setup_t *s;
3653a5a1b3Sopenharmony_ci    xcb_screen_iterator_t iter;
3753a5a1b3Sopenharmony_ci
3853a5a1b3Sopenharmony_ci    if ((s = xcb_get_setup(xcb))) {
3953a5a1b3Sopenharmony_ci        iter = xcb_setup_roots_iterator(s);
4053a5a1b3Sopenharmony_ci        for (; iter.rem; --screen, xcb_screen_next(&iter))
4153a5a1b3Sopenharmony_ci            if (0 == screen)
4253a5a1b3Sopenharmony_ci                return iter.data;
4353a5a1b3Sopenharmony_ci    }
4453a5a1b3Sopenharmony_ci    return NULL;
4553a5a1b3Sopenharmony_ci}
4653a5a1b3Sopenharmony_ci
4753a5a1b3Sopenharmony_civoid pa_x11_set_prop(xcb_connection_t *xcb, int screen, const char *name, const char *data) {
4853a5a1b3Sopenharmony_ci    xcb_screen_t *xs;
4953a5a1b3Sopenharmony_ci    xcb_intern_atom_reply_t *reply;
5053a5a1b3Sopenharmony_ci
5153a5a1b3Sopenharmony_ci    pa_assert(xcb);
5253a5a1b3Sopenharmony_ci    pa_assert(name);
5353a5a1b3Sopenharmony_ci    pa_assert(data);
5453a5a1b3Sopenharmony_ci
5553a5a1b3Sopenharmony_ci    if ((xs = screen_of_display(xcb, screen))) {
5653a5a1b3Sopenharmony_ci        reply = xcb_intern_atom_reply(xcb,
5753a5a1b3Sopenharmony_ci                                      xcb_intern_atom(xcb, 0, strlen(name), name),
5853a5a1b3Sopenharmony_ci                                      NULL);
5953a5a1b3Sopenharmony_ci
6053a5a1b3Sopenharmony_ci        if (reply) {
6153a5a1b3Sopenharmony_ci            xcb_change_property(xcb, XCB_PROP_MODE_REPLACE, xs->root, reply->atom,
6253a5a1b3Sopenharmony_ci                                XCB_ATOM_STRING, PA_XCB_FORMAT,
6353a5a1b3Sopenharmony_ci                                (int) strlen(data), (const void*) data);
6453a5a1b3Sopenharmony_ci
6553a5a1b3Sopenharmony_ci            free(reply);
6653a5a1b3Sopenharmony_ci        }
6753a5a1b3Sopenharmony_ci    }
6853a5a1b3Sopenharmony_ci}
6953a5a1b3Sopenharmony_ci
7053a5a1b3Sopenharmony_civoid pa_x11_del_prop(xcb_connection_t *xcb, int screen, const char *name) {
7153a5a1b3Sopenharmony_ci    xcb_screen_t *xs;
7253a5a1b3Sopenharmony_ci    xcb_intern_atom_reply_t *reply;
7353a5a1b3Sopenharmony_ci
7453a5a1b3Sopenharmony_ci    pa_assert(xcb);
7553a5a1b3Sopenharmony_ci    pa_assert(name);
7653a5a1b3Sopenharmony_ci
7753a5a1b3Sopenharmony_ci    if ((xs = screen_of_display(xcb, screen))) {
7853a5a1b3Sopenharmony_ci        reply = xcb_intern_atom_reply(xcb,
7953a5a1b3Sopenharmony_ci                                      xcb_intern_atom(xcb, 0, strlen(name), name),
8053a5a1b3Sopenharmony_ci                                      NULL);
8153a5a1b3Sopenharmony_ci
8253a5a1b3Sopenharmony_ci        if (reply) {
8353a5a1b3Sopenharmony_ci            xcb_delete_property(xcb, xs->root, reply->atom);
8453a5a1b3Sopenharmony_ci            free(reply);
8553a5a1b3Sopenharmony_ci        }
8653a5a1b3Sopenharmony_ci    }
8753a5a1b3Sopenharmony_ci}
8853a5a1b3Sopenharmony_ci
8953a5a1b3Sopenharmony_cichar* pa_x11_get_prop(xcb_connection_t *xcb, int screen, const char *name, char *p, size_t l) {
9053a5a1b3Sopenharmony_ci    char *ret = NULL;
9153a5a1b3Sopenharmony_ci    int len;
9253a5a1b3Sopenharmony_ci    xcb_get_property_cookie_t req;
9353a5a1b3Sopenharmony_ci    xcb_get_property_reply_t* prop = NULL;
9453a5a1b3Sopenharmony_ci    xcb_screen_t *xs;
9553a5a1b3Sopenharmony_ci    xcb_intern_atom_reply_t *reply;
9653a5a1b3Sopenharmony_ci
9753a5a1b3Sopenharmony_ci    pa_assert(xcb);
9853a5a1b3Sopenharmony_ci    pa_assert(name);
9953a5a1b3Sopenharmony_ci    pa_assert(p);
10053a5a1b3Sopenharmony_ci
10153a5a1b3Sopenharmony_ci    xs = screen_of_display(xcb, screen);
10253a5a1b3Sopenharmony_ci    /*
10353a5a1b3Sopenharmony_ci     * Also try and get the settings from the first screen.
10453a5a1b3Sopenharmony_ci     * This allows for e.g. a Media Center to run on screen 1 (e.g. HDMI) and have
10553a5a1b3Sopenharmony_ci     * different defaults (e.g. prefer the HDMI sink) than the primary screen 0
10653a5a1b3Sopenharmony_ci     * which uses the Internal Audio sink.
10753a5a1b3Sopenharmony_ci     */
10853a5a1b3Sopenharmony_ci    if (!xs && 0 != screen)
10953a5a1b3Sopenharmony_ci        xs = screen_of_display(xcb, 0);
11053a5a1b3Sopenharmony_ci
11153a5a1b3Sopenharmony_ci    if (xs) {
11253a5a1b3Sopenharmony_ci        reply = xcb_intern_atom_reply(xcb,
11353a5a1b3Sopenharmony_ci                                      xcb_intern_atom(xcb, 0, strlen(name), name),
11453a5a1b3Sopenharmony_ci                                      NULL);
11553a5a1b3Sopenharmony_ci
11653a5a1b3Sopenharmony_ci        if (!reply)
11753a5a1b3Sopenharmony_ci            goto finish;
11853a5a1b3Sopenharmony_ci
11953a5a1b3Sopenharmony_ci        req = xcb_get_property(xcb, 0, xs->root, reply->atom, XCB_ATOM_STRING, 0, (uint32_t)(l-1));
12053a5a1b3Sopenharmony_ci        free(reply);
12153a5a1b3Sopenharmony_ci        prop = xcb_get_property_reply(xcb, req, NULL);
12253a5a1b3Sopenharmony_ci
12353a5a1b3Sopenharmony_ci        if (!prop)
12453a5a1b3Sopenharmony_ci            goto finish;
12553a5a1b3Sopenharmony_ci
12653a5a1b3Sopenharmony_ci        if (PA_XCB_FORMAT != prop->format)
12753a5a1b3Sopenharmony_ci            goto finish;
12853a5a1b3Sopenharmony_ci
12953a5a1b3Sopenharmony_ci        len = xcb_get_property_value_length(prop);
13053a5a1b3Sopenharmony_ci        if (len < 1 || len >= (int)l)
13153a5a1b3Sopenharmony_ci            goto finish;
13253a5a1b3Sopenharmony_ci
13353a5a1b3Sopenharmony_ci        memcpy(p, xcb_get_property_value(prop), len);
13453a5a1b3Sopenharmony_ci        p[len] = 0;
13553a5a1b3Sopenharmony_ci
13653a5a1b3Sopenharmony_ci        ret = p;
13753a5a1b3Sopenharmony_ci    }
13853a5a1b3Sopenharmony_ci
13953a5a1b3Sopenharmony_cifinish:
14053a5a1b3Sopenharmony_ci
14153a5a1b3Sopenharmony_ci    if (prop)
14253a5a1b3Sopenharmony_ci        free(prop);
14353a5a1b3Sopenharmony_ci
14453a5a1b3Sopenharmony_ci    return ret;
14553a5a1b3Sopenharmony_ci}
146