コード例 #1
0
ファイル: backend-native.c プロジェクト: plbossart/pulseaudio
static void profile_init(pa_bluetooth_backend *b, pa_bluetooth_profile_t profile) {
    static const DBusObjectPathVTable vtable_profile = {
        .message_function = profile_handler,
    };
    const char *object_name;
    const char *uuid;

    pa_assert(b);

    switch (profile) {
        case PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT:
            object_name = HSP_AG_PROFILE;
            uuid = PA_BLUETOOTH_UUID_HSP_AG;
            break;
        case PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY:
            object_name = HSP_HS_PROFILE;
            uuid = PA_BLUETOOTH_UUID_HSP_HS;
            break;
        default:
            pa_assert_not_reached();
            break;
    }

    pa_assert_se(dbus_connection_register_object_path(pa_dbus_connection_get(b->connection), object_name, &vtable_profile, b));
    register_profile(b, object_name, uuid);
}
コード例 #2
0
ファイル: mime-type.c プロジェクト: Distrotech/pulseaudio
char *pa_sample_spec_to_mime_type(const pa_sample_spec *ss, const pa_channel_map *cm) {
    pa_assert(pa_channel_map_compatible(cm, ss));
    pa_assert(pa_sample_spec_valid(ss));

    if (!pa_sample_spec_is_mime(ss, cm))
        return NULL;

    switch (ss->format) {

        case PA_SAMPLE_S16BE:
        case PA_SAMPLE_S24BE:
        case PA_SAMPLE_U8:
            /* Stupid UPnP implementations (PS3...) choke on spaces in
             * the mime type, that's why we write only ';' here,
             * instead of '; '. */
            return pa_sprintf_malloc("audio/%s;rate=%u;channels=%u",
                                     ss->format == PA_SAMPLE_S16BE ? "L16" :
                                     (ss->format == PA_SAMPLE_S24BE ? "L24" : "L8"),
                                     ss->rate, ss->channels);

        case PA_SAMPLE_ULAW:
            return pa_xstrdup("audio/basic");

        default:
            pa_assert_not_reached();
    }
}
コード例 #3
0
static void get_service_data(struct service *s, pa_sample_spec *ret_ss, pa_channel_map *ret_map, const char **ret_name, pa_proplist **ret_proplist, enum service_subtype *ret_subtype) {
    pa_assert(s);
    pa_assert(ret_ss);
    pa_assert(ret_proplist);
    pa_assert(ret_subtype);

    if (pa_sink_isinstance(s->device)) {
        pa_sink *sink = PA_SINK(s->device);

        *ret_ss = sink->sample_spec;
        *ret_map = sink->channel_map;
        *ret_name = sink->name;
        *ret_proplist = sink->proplist;
        *ret_subtype = sink->flags & PA_SINK_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL;

    } else if (pa_source_isinstance(s->device)) {
        pa_source *source = PA_SOURCE(s->device);

        *ret_ss = source->sample_spec;
        *ret_map = source->channel_map;
        *ret_name = source->name;
        *ret_proplist = source->proplist;
        *ret_subtype = source->monitor_of ? SUBTYPE_MONITOR : (source->flags & PA_SOURCE_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL);

    } else
        pa_assert_not_reached();
}
コード例 #4
0
/* Runs in PA mainloop context */
static void get_service_data(struct service *s, pa_object *device) {
    pa_assert(s);

    if (pa_sink_isinstance(device)) {
        pa_sink *sink = PA_SINK(device);

        s->is_sink = true;
        s->service_type = SERVICE_TYPE_SINK;
        s->ss = sink->sample_spec;
        s->cm = sink->channel_map;
        s->name = pa_xstrdup(sink->name);
        s->proplist = pa_proplist_copy(sink->proplist);
        s->subtype = sink->flags & PA_SINK_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL;

    } else if (pa_source_isinstance(device)) {
        pa_source *source = PA_SOURCE(device);

        s->is_sink = false;
        s->service_type = SERVICE_TYPE_SOURCE;
        s->ss = source->sample_spec;
        s->cm = source->channel_map;
        s->name = pa_xstrdup(source->name);
        s->proplist = pa_proplist_copy(source->proplist);
        s->subtype = source->monitor_of ? SUBTYPE_MONITOR : (source->flags & PA_SOURCE_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL);

    } else
        pa_assert_not_reached();
}
コード例 #5
0
ファイル: server-lookup.c プロジェクト: Distrotech/pulseaudio
static DBusHandlerResult handle_get_address(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) {
    DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED;
    DBusMessage *reply = NULL;
    char *address = NULL;
    DBusMessageIter msg_iter;
    DBusMessageIter variant_iter;

    pa_assert(conn);
    pa_assert(msg);
    pa_assert(sl);

    switch (get_address(sl->core->server_type, &address)) {
        case SUCCESS:
            if (!(reply = dbus_message_new_method_return(msg))) {
                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
                goto finish;
            }
            dbus_message_iter_init_append(reply, &msg_iter);
            if (!dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_VARIANT, "s", &variant_iter)) {
                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
                goto finish;
            }
            if (!dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &address)) {
                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
                goto finish;
            }
            if (!dbus_message_iter_close_container(&msg_iter, &variant_iter)) {
                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
                goto finish;
            }
            if (!dbus_connection_send(conn, reply, NULL)) {
                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
                goto finish;
            }
            r = DBUS_HANDLER_RESULT_HANDLED;
            goto finish;

        case SERVER_FROM_TYPE_FAILED:
            if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "PulseAudio internal error: get_dbus_server_from_type() failed."))) {
                r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
                goto finish;
            }
            if (!dbus_connection_send(conn, reply, NULL)) {
                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
                goto finish;
            }
            r = DBUS_HANDLER_RESULT_HANDLED;
            goto finish;

        default:
            pa_assert_not_reached();
    }

finish:
    pa_xfree(address);
    if (reply)
        dbus_message_unref(reply);

    return r;
}
コード例 #6
0
int pa_conversion_parse_list(pa_conversion_string_t type, const char *separator,
                             const char *str, uint32_t *dst, char **unknown_entries) {
    switch (type) {
        case CONV_STRING_FORMAT:
            return parse_list(string_conversion_table_format, separator, str, dst, unknown_entries);

        case CONV_STRING_OUTPUT_CHANNELS:
            return parse_list(string_conversion_table_output_channels, separator, str, dst, unknown_entries);

        case CONV_STRING_INPUT_CHANNELS:
            return parse_list(string_conversion_table_input_channels, separator, str, dst, unknown_entries);

        case CONV_STRING_OUTPUT_DEVICE:
            return parse_list(string_conversion_table_output_device, separator, str, dst, unknown_entries);

        case CONV_STRING_INPUT_DEVICE:
            return parse_list(string_conversion_table_input_device, separator, str, dst, unknown_entries);

        case CONV_STRING_OUTPUT_FLAG:
            return parse_list(string_conversion_table_output_flag, separator, str, dst, unknown_entries);

        case CONV_STRING_INPUT_FLAG:
            return parse_list(string_conversion_table_input_flag, separator, str, dst, unknown_entries);
    }

    pa_assert_not_reached();
    return 0;
}
コード例 #7
0
ファイル: fdsem.c プロジェクト: felfert/pulseaudio
void pa_fdsem_wait(pa_fdsem *f) {
    pa_assert(f);

    flush(f);

    if (pa_atomic_cmpxchg(&f->data->signalled, 1, 0))
        return;

    pa_atomic_inc(&f->data->waiting);

    while (!pa_atomic_cmpxchg(&f->data->signalled, 1, 0)) {
        char x[10];
        ssize_t r;

#ifdef HAVE_SYS_EVENTFD_H
        if (f->efd >= 0) {
            uint64_t u;

            if ((r = pa_read(f->efd, &u, sizeof(u), NULL)) != sizeof(u)) {

                if (r >= 0 || errno != EINTR) {
                    pa_log_error("Invalid read from eventfd: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
                    pa_assert_not_reached();
                }

                continue;
            }

            r = (ssize_t) u;
        } else
#endif

            if ((r = pa_read(f->fds[0], &x, sizeof(x), NULL)) <= 0) {

                if (r >= 0 || errno != EINTR) {
                    pa_log_error("Invalid read from pipe: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
                    pa_assert_not_reached();
                }

                continue;
            }

        pa_atomic_sub(&f->data->in_pipe, (int) r);
    }

    pa_assert_se(pa_atomic_dec(&f->data->waiting) >= 1);
}
コード例 #8
0
pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length) {
    pa_memblock *b;
    size_t l;

    pa_assert(cache);
    pa_assert(pa_sample_spec_valid(spec));

    if (!(b = cache->blocks[spec->format]))

        switch (spec->format) {
            case PA_SAMPLE_U8:
                cache->blocks[PA_SAMPLE_U8] = b = silence_memblock_new(pool, 0x80);
                break;
            case PA_SAMPLE_S16LE:
            case PA_SAMPLE_S16BE:
            case PA_SAMPLE_S32LE:
            case PA_SAMPLE_S32BE:
            case PA_SAMPLE_S24LE:
            case PA_SAMPLE_S24BE:
            case PA_SAMPLE_S24_32LE:
            case PA_SAMPLE_S24_32BE:
            case PA_SAMPLE_FLOAT32LE:
            case PA_SAMPLE_FLOAT32BE:
                cache->blocks[PA_SAMPLE_S16LE] = b = silence_memblock_new(pool, 0);
                cache->blocks[PA_SAMPLE_S16BE] = pa_memblock_ref(b);
                cache->blocks[PA_SAMPLE_S32LE] = pa_memblock_ref(b);
                cache->blocks[PA_SAMPLE_S32BE] = pa_memblock_ref(b);
                cache->blocks[PA_SAMPLE_S24LE] = pa_memblock_ref(b);
                cache->blocks[PA_SAMPLE_S24BE] = pa_memblock_ref(b);
                cache->blocks[PA_SAMPLE_S24_32LE] = pa_memblock_ref(b);
                cache->blocks[PA_SAMPLE_S24_32BE] = pa_memblock_ref(b);
                cache->blocks[PA_SAMPLE_FLOAT32LE] = pa_memblock_ref(b);
                cache->blocks[PA_SAMPLE_FLOAT32BE] = pa_memblock_ref(b);
                break;
            case PA_SAMPLE_ALAW:
                cache->blocks[PA_SAMPLE_ALAW] = b = silence_memblock_new(pool, 0xd5);
                break;
            case PA_SAMPLE_ULAW:
                cache->blocks[PA_SAMPLE_ULAW] = b = silence_memblock_new(pool, 0xff);
                break;
            default:
                pa_assert_not_reached();
    }

    pa_assert(b);

    ret->memblock = pa_memblock_ref(b);

    l = pa_memblock_get_length(b);
    if (length > l || length == 0)
        length = l;

    ret->length = pa_frame_align(length, spec);
    ret->index = 0;

    return ret;
}
コード例 #9
0
ファイル: fdsem.c プロジェクト: felfert/pulseaudio
void pa_fdsem_post(pa_fdsem *f) {
    pa_assert(f);

    if (pa_atomic_cmpxchg(&f->data->signalled, 0, 1)) {

        if (pa_atomic_load(&f->data->waiting)) {
            ssize_t r;
            char x = 'x';

            pa_atomic_inc(&f->data->in_pipe);

            for (;;) {

#ifdef HAVE_SYS_EVENTFD_H
                if (f->efd >= 0) {
                    uint64_t u = 1;

                    if ((r = pa_write(f->efd, &u, sizeof(u), NULL)) != sizeof(u)) {
                        if (r >= 0 || errno != EINTR) {
                            pa_log_error("Invalid write to eventfd: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
                            pa_assert_not_reached();
                        }

                        continue;
                    }
                } else
#endif

                    if ((r = pa_write(f->fds[1], &x, 1, NULL)) != 1) {
                        if (r >= 0 || errno != EINTR) {
                            pa_log_error("Invalid write to pipe: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
                            pa_assert_not_reached();
                        }

                        continue;
                    }

                break;
            }
        }
    }
}
コード例 #10
0
static bool shall_ignore(pa_object *o) {
    pa_object_assert_ref(o);

    if (pa_sink_isinstance(o))
        return !!(PA_SINK(o)->flags & PA_SINK_NETWORK);

    if (pa_source_isinstance(o))
        return PA_SOURCE(o)->monitor_of || (PA_SOURCE(o)->flags & PA_SOURCE_NETWORK);

    pa_assert_not_reached();
}
コード例 #11
0
static void profile_done(pa_bluetooth_backend *b, pa_bluetooth_profile_t profile) {
    pa_assert(b);

    switch (profile) {
        case PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT:
            dbus_connection_unregister_object_path(pa_dbus_connection_get(b->connection), HSP_AG_PROFILE);
            break;
        default:
            pa_assert_not_reached();
            break;
    }
}
コード例 #12
0
ファイル: fdsem.c プロジェクト: felfert/pulseaudio
static void flush(pa_fdsem *f) {
    ssize_t r;
    pa_assert(f);

    if (pa_atomic_load(&f->data->in_pipe) <= 0)
        return;

    do {
        char x[10];

#ifdef HAVE_SYS_EVENTFD_H
        if (f->efd >= 0) {
            uint64_t u;

            if ((r = pa_read(f->efd, &u, sizeof(u), NULL)) != sizeof(u)) {

                if (r >= 0 || errno != EINTR) {
                    pa_log_error("Invalid read from eventfd: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
                    pa_assert_not_reached();
                }

                continue;
            }
            r = (ssize_t) u;
        } else
#endif

            if ((r = pa_read(f->fds[0], &x, sizeof(x), NULL)) <= 0) {

                if (r >= 0 || errno != EINTR) {
                    pa_log_error("Invalid read from pipe: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
                    pa_assert_not_reached();
                }

                continue;
            }

    } while (pa_atomic_sub(&f->data->in_pipe, (int) r) > (int) r);
}
コード例 #13
0
static inline const char *status_to_string(meego_parameter_status_t status) {
    switch (status) {
        case MEEGO_PARAM_ENABLE:
            return "MEEGO_PARAM_ENABLE";
        case MEEGO_PARAM_DISABLE:
            return "MEEGO_PARAM_DISABLE";
        case MEEGO_PARAM_UPDATE:
            return "MEEGO_PARAM_UPDATE";
        case MEEGO_PARAM_MODE_CHANGE:
            return "MEEGO_PARAM_MODE_CHANGE";
        default:
            pa_assert_not_reached();
    }
}
コード例 #14
0
ファイル: dbus-util.c プロジェクト: Klayv/pulseaudio
/* Note: returns sizeof(char*) for strings, object paths and signatures. */
static unsigned basic_type_size(int type) {
    switch (type) {
        case DBUS_TYPE_BOOLEAN: return sizeof(dbus_bool_t);
        case DBUS_TYPE_BYTE: return 1;
        case DBUS_TYPE_INT16: return sizeof(dbus_int16_t);
        case DBUS_TYPE_UINT16: return sizeof(dbus_uint16_t);
        case DBUS_TYPE_INT32: return sizeof(dbus_int32_t);
        case DBUS_TYPE_UINT32: return sizeof(dbus_uint32_t);
        case DBUS_TYPE_INT64: return sizeof(dbus_int64_t);
        case DBUS_TYPE_UINT64: return sizeof(dbus_uint64_t);
        case DBUS_TYPE_DOUBLE: return sizeof(double);
        case DBUS_TYPE_STRING:
        case DBUS_TYPE_OBJECT_PATH:
        case DBUS_TYPE_SIGNATURE: return sizeof(char*);
        default: pa_assert_not_reached();
    }
}
コード例 #15
0
ファイル: module-rtp-send.c プロジェクト: jprvita/pulseaudio
static pa_source_output_flags_t get_dont_inhibit_auto_suspend_flag(pa_source *source,
                                                                   enum inhibit_auto_suspend inhibit_auto_suspend) {
    pa_assert(source);

    switch (inhibit_auto_suspend) {
        case INHIBIT_AUTO_SUSPEND_ALWAYS:
            return 0;

        case INHIBIT_AUTO_SUSPEND_NEVER:
            return PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND;

        case INHIBIT_AUTO_SUSPEND_ONLY_WITH_NON_MONITOR_SOURCES:
            return source->monitor_of ? 0 : PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND;
    }

    pa_assert_not_reached();
}
コード例 #16
0
ファイル: dbus-util.c プロジェクト: Klayv/pulseaudio
static const char *signature_from_basic_type(int type) {
    switch (type) {
        case DBUS_TYPE_BOOLEAN: return DBUS_TYPE_BOOLEAN_AS_STRING;
        case DBUS_TYPE_BYTE: return DBUS_TYPE_BYTE_AS_STRING;
        case DBUS_TYPE_INT16: return DBUS_TYPE_INT16_AS_STRING;
        case DBUS_TYPE_UINT16: return DBUS_TYPE_UINT16_AS_STRING;
        case DBUS_TYPE_INT32: return DBUS_TYPE_INT32_AS_STRING;
        case DBUS_TYPE_UINT32: return DBUS_TYPE_UINT32_AS_STRING;
        case DBUS_TYPE_INT64: return DBUS_TYPE_INT64_AS_STRING;
        case DBUS_TYPE_UINT64: return DBUS_TYPE_UINT64_AS_STRING;
        case DBUS_TYPE_DOUBLE: return DBUS_TYPE_DOUBLE_AS_STRING;
        case DBUS_TYPE_STRING: return DBUS_TYPE_STRING_AS_STRING;
        case DBUS_TYPE_OBJECT_PATH: return DBUS_TYPE_OBJECT_PATH_AS_STRING;
        case DBUS_TYPE_SIGNATURE: return DBUS_TYPE_SIGNATURE_AS_STRING;
        default: pa_assert_not_reached();
    }
}
コード例 #17
0
ファイル: shm.c プロジェクト: UlrichEckhardt/pulseaudio
void pa_shm_free(pa_shm *m) {
    pa_assert(m);
    pa_assert(m->ptr);
    pa_assert(m->size > 0);

#ifdef MAP_FAILED
    pa_assert(m->ptr != MAP_FAILED);
#endif

    if (m->type == PA_MEM_TYPE_PRIVATE) {
        privatemem_free(m);
        goto finish;
    }

#if defined(HAVE_SHM_OPEN) || defined(HAVE_MEMFD)
    if (munmap(m->ptr, PA_PAGE_ALIGN(m->size)) < 0)
        pa_log("munmap() failed: %s", pa_cstrerror(errno));

#ifdef HAVE_SHM_OPEN
    if (m->type == PA_MEM_TYPE_SHARED_POSIX && m->do_unlink) {
        char fn[32];

        segment_name(fn, sizeof(fn), m->id);
        if (shm_unlink(fn) < 0)
            pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno));
    }
#endif
#ifdef HAVE_MEMFD
    if (m->type == PA_MEM_TYPE_SHARED_MEMFD && m->fd != -1)
        pa_assert_se(pa_close(m->fd) == 0);
#endif

#else
    /* We shouldn't be here without shm or memfd support */
    pa_assert_not_reached();
#endif

finish:
    pa_zero(*m);
}
コード例 #18
0
ファイル: shm.c プロジェクト: Elemecca/pulseaudio
void pa_shm_free(pa_shm *m) {
    pa_assert(m);
    pa_assert(m->ptr);
    pa_assert(m->size > 0);

#ifdef MAP_FAILED
    pa_assert(m->ptr != MAP_FAILED);
#endif

    if (!m->shared) {
#ifdef MAP_ANONYMOUS
        if (munmap(m->ptr, m->size) < 0)
            pa_log("munmap() failed: %s", pa_cstrerror(errno));
#elif defined(HAVE_POSIX_MEMALIGN)
        free(m->ptr);
#else
        pa_xfree(m->ptr);
#endif
    } else {
#ifdef HAVE_SHM_OPEN
        if (munmap(m->ptr, PA_PAGE_ALIGN(m->size)) < 0)
            pa_log("munmap() failed: %s", pa_cstrerror(errno));

        if (m->do_unlink) {
            char fn[32];

            segment_name(fn, sizeof(fn), m->id);

            if (shm_unlink(fn) < 0)
                pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno));
        }
#else
        /* We shouldn't be here without shm support */
        pa_assert_not_reached();
#endif
    }

    pa_zero(*m);
}
コード例 #19
0
static uint8_t silence_byte(pa_sample_format_t format) {
    switch (format) {
        case PA_SAMPLE_U8:
            return 0x80;
        case PA_SAMPLE_S16LE:
        case PA_SAMPLE_S16BE:
        case PA_SAMPLE_S32LE:
        case PA_SAMPLE_S32BE:
        case PA_SAMPLE_FLOAT32LE:
        case PA_SAMPLE_FLOAT32BE:
        case PA_SAMPLE_S24LE:
        case PA_SAMPLE_S24BE:
        case PA_SAMPLE_S24_32LE:
        case PA_SAMPLE_S24_32BE:
            return 0;
        case PA_SAMPLE_ALAW:
            return 0xd5;
        case PA_SAMPLE_ULAW:
            return 0xff;
        default:
            pa_assert_not_reached();
    }
}
コード例 #20
0
ファイル: mix-test.c プロジェクト: poljar/pulseaudio
static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) {
    pa_memblock *r;
    void *d;
    unsigned i;

    pa_assert_se(r = pa_memblock_new(pool, pa_frame_size(ss) * 10));
    d = pa_memblock_acquire(r);

    switch (ss->format) {

    case PA_SAMPLE_U8:
    case PA_SAMPLE_ULAW:
    case PA_SAMPLE_ALAW: {
        static const uint8_t u8_samples[] = {
            0x00, 0xFF, 0x7F, 0x80, 0x9f,
            0x3f, 0x01, 0xF0, 0x20, 0x21
        };

        memcpy(d, u8_samples, sizeof(u8_samples));
        break;
    }

    case PA_SAMPLE_S16NE:
    case PA_SAMPLE_S16RE: {
        static const uint16_t u16_samples[] = {
            0x0000, 0xFFFF, 0x7FFF, 0x8000, 0x9fff,
            0x3fff, 0x0001, 0xF000, 0x0020, 0x0021
        };

        memcpy(d, u16_samples, sizeof(u16_samples));
        break;
    }

    case PA_SAMPLE_S24_32NE:
    case PA_SAMPLE_S24_32RE:
    case PA_SAMPLE_S32NE:
    case PA_SAMPLE_S32RE: {
        static const uint32_t u32_samples[] = {
            0x00000001, 0xFFFF0002, 0x7FFF0003, 0x80000004, 0x9fff0005,
            0x3fff0006, 0x00010007, 0xF0000008, 0x00200009, 0x0021000A
        };

        memcpy(d, u32_samples, sizeof(u32_samples));
        break;
    }

    case PA_SAMPLE_S24NE:
    case PA_SAMPLE_S24RE: {
        /* Need to be on a byte array because they are not aligned */
        static const uint8_t u24_samples[] = {
            0x00, 0x00, 0x01,
            0xFF, 0xFF, 0x02,
            0x7F, 0xFF, 0x03,
            0x80, 0x00, 0x04,
            0x9f, 0xff, 0x05,
            0x3f, 0xff, 0x06,
            0x01, 0x00, 0x07,
            0xF0, 0x00, 0x08,
            0x20, 0x00, 0x09,
            0x21, 0x00, 0x0A
        };

        memcpy(d, u24_samples, sizeof(u24_samples));
        break;
    }

    case PA_SAMPLE_FLOAT32NE:
    case PA_SAMPLE_FLOAT32RE: {
        float *u = d;
        static const float float_samples[] = {
            0.0f, -1.0f, 1.0f, 4711.0f, 0.222f,
            0.33f, -.3f, 99.0f, -0.555f, -.123f
        };

        if (ss->format == PA_SAMPLE_FLOAT32RE) {
            for (i = 0; i < 10; i++)
                u[i] = PA_FLOAT32_SWAP(float_samples[i]);
        } else
            memcpy(d, float_samples, sizeof(float_samples));

        break;
    }

    default:
        pa_assert_not_reached();
    }

    pa_memblock_release(r);

    return r;
}
コード例 #21
0
ファイル: mix-test.c プロジェクト: poljar/pulseaudio
static void compare_block(const pa_sample_spec *ss, const pa_memchunk *chunk, int iter) {
    void *d;
    unsigned i;

    d = pa_memblock_acquire(chunk->memblock);

    switch (ss->format) {
    case PA_SAMPLE_U8: {
        const uint8_t *v = u8_result[iter];
        uint8_t *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            fail_unless(*u == *v, NULL);
            ++u;
            ++v;
        }
        break;
    }

    case PA_SAMPLE_ALAW: {
        const uint8_t *v = alaw_result[iter];
        uint8_t *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            fail_unless(*u == *v, NULL);
            ++u;
            ++v;
        }
        break;
    }

    case PA_SAMPLE_ULAW: {
        const uint8_t *v = ulaw_result[iter];
        uint8_t *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            fail_unless(*u == *v, NULL);
            ++u;
            ++v;
        }
        break;
    }

    case PA_SAMPLE_S16LE: {
        const uint16_t *v = s16le_result[iter];
        uint16_t *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            fail_unless(*u == *v, NULL);
            ++u;
            ++v;
        }
        break;
    }

    case PA_SAMPLE_S16BE: {
        const uint16_t *v = s16be_result[iter];
        uint16_t *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            fail_unless(*u == *v, NULL);
            ++u;
            ++v;
        }
        break;
    }

    case PA_SAMPLE_FLOAT32LE: {
        const float *v = float32le_result[iter];
        float *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            float uu = ss->format == PA_SAMPLE_FLOAT32NE ? *u : PA_FLOAT32_SWAP(*u);
            fail_unless(fabs(uu - *v) <= 1e-6, NULL);
            ++u;
            ++v;
        }
        break;
    }

    case PA_SAMPLE_FLOAT32BE: {
        const float *v = float32be_result[iter];
        float *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            float uu = ss->format == PA_SAMPLE_FLOAT32NE ? *u : PA_FLOAT32_SWAP(*u);
            fail_unless(fabs(uu - *v) <= 1e-6, NULL);
            ++u;
            ++v;
        }
        break;
    }

    case PA_SAMPLE_S32LE: {
        const uint32_t *v = s32le_result[iter];
        uint32_t *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            fail_unless(*u == *v, NULL);
            ++u;
            ++v;
        }
        break;
    }

    case PA_SAMPLE_S32BE: {
        const uint32_t *v = s32be_result[iter];
        uint32_t *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            fail_unless(*u == *v, NULL);
            ++u;
            ++v;
        }
        break;
    }

    case PA_SAMPLE_S24_32LE: {
        const uint32_t *v = s24_32le_result[iter];
        uint32_t *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            fail_unless(*u == *v, NULL);
            ++u;
            ++v;
        }
        break;
    }

    case PA_SAMPLE_S24_32BE: {
        const uint32_t *v = s24_32be_result[iter];
        uint32_t *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            fail_unless(*u == *v, NULL);
            ++u;
            ++v;
        }
        break;
    }

    case PA_SAMPLE_S24LE: {
        const uint8_t *v = s24le_result[iter];
        uint8_t *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            fail_unless(*u == *v, NULL);
            fail_unless(*(u+1) == *(v+1), NULL);
            fail_unless(*(u+2) == *(v+2), NULL);

            u += 3;
            v += 3;
        }
        break;
    }

    case PA_SAMPLE_S24BE: {
        const uint8_t *v = s24be_result[iter];
        uint8_t *u = d;

        for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
            fail_unless(*u == *v, NULL);
            fail_unless(*(u+1) == *(v+1), NULL);
            fail_unless(*(u+2) == *(v+2), NULL);

            u += 3;
            v += 3;
        }
        break;
    }

    default:
        pa_assert_not_reached();
    }

    pa_memblock_release(chunk->memblock);
}
コード例 #22
0
ファイル: main.c プロジェクト: Elemecca/pulseaudio
int main(int argc, char *argv[]) {
    pa_core *c = NULL;
    pa_strbuf *buf = NULL;
    pa_daemon_conf *conf = NULL;
    pa_mainloop *mainloop = NULL;
    char *s;
    char *configured_address;
    int r = 0, retval = 1, d = 0;
    bool valid_pid_file = false;
    bool ltdl_init = false;
    int passed_fd = -1;
    const char *e;
#ifdef HAVE_FORK
    int daemon_pipe[2] = { -1, -1 };
    int daemon_pipe2[2] = { -1, -1 };
#endif
    int autospawn_fd = -1;
    bool autospawn_locked = false;
#ifdef HAVE_DBUS
    pa_dbusobj_server_lookup *server_lookup = NULL; /* /org/pulseaudio/server_lookup */
    pa_dbus_connection *lookup_service_bus = NULL; /* Always the user bus. */
    pa_dbus_connection *server_bus = NULL; /* The bus where we reserve org.pulseaudio.Server, either the user or the system bus. */
    bool start_server;
#endif

    pa_log_set_ident("pulseaudio");
    pa_log_set_level(PA_LOG_NOTICE);
    pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET);

#if defined(__linux__) && defined(__OPTIMIZE__)
    /*
       Disable lazy relocations to make usage of external libraries
       more deterministic for our RT threads. We abuse __OPTIMIZE__ as
       a check whether we are a debug build or not. This all is
       admittedly a bit snake-oilish.
    */

    if (!getenv("LD_BIND_NOW")) {
        char *rp;
        char *canonical_rp;

        /* We have to execute ourselves, because the libc caches the
         * value of $LD_BIND_NOW on initialization. */

        pa_set_env("LD_BIND_NOW", "1");

        if ((canonical_rp = pa_realpath(PA_BINARY))) {

            if ((rp = pa_readlink("/proc/self/exe"))) {

                if (pa_streq(rp, canonical_rp))
                    pa_assert_se(execv(rp, argv) == 0);
                else
                    pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp);

                pa_xfree(rp);

            } else
                pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?");

            pa_xfree(canonical_rp);

        } else
            pa_log_warn("Couldn't canonicalize binary path, cannot self execute.");
    }
#endif

    if ((e = getenv("PULSE_PASSED_FD"))) {
        passed_fd = atoi(e);

        if (passed_fd <= 2)
            passed_fd = -1;
    }

    /* We might be autospawned, in which case have no idea in which
     * context we have been started. Let's cleanup our execution
     * context as good as possible */

    pa_reset_personality();
    pa_drop_root();
    pa_close_all(passed_fd, -1);
    pa_reset_sigs(-1);
    pa_unblock_sigs(-1);
    pa_reset_priority();

    setlocale(LC_ALL, "");
    pa_init_i18n();

    conf = pa_daemon_conf_new();

    if (pa_daemon_conf_load(conf, NULL) < 0)
        goto finish;

    if (pa_daemon_conf_env(conf) < 0)
        goto finish;

    if (pa_cmdline_parse(conf, argc, argv, &d) < 0) {
        pa_log(_("Failed to parse command line."));
        goto finish;
    }

    if (conf->log_target)
        pa_log_set_target(conf->log_target);
    else {
        pa_log_target target = { .type = PA_LOG_STDERR, .file = NULL };
        pa_log_set_target(&target);
    }

    pa_log_set_level(conf->log_level);
    if (conf->log_meta)
        pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET);
    if (conf->log_time)
        pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET);
    pa_log_set_show_backtrace(conf->log_backtrace);

#ifdef HAVE_DBUS
    /* conf->system_instance and conf->local_server_type control almost the
     * same thing; make them agree about what is requested. */
    switch (conf->local_server_type) {
        case PA_SERVER_TYPE_UNSET:
            conf->local_server_type = conf->system_instance ? PA_SERVER_TYPE_SYSTEM : PA_SERVER_TYPE_USER;
            break;
        case PA_SERVER_TYPE_USER:
        case PA_SERVER_TYPE_NONE:
            conf->system_instance = false;
            break;
        case PA_SERVER_TYPE_SYSTEM:
            conf->system_instance = true;
            break;
        default:
            pa_assert_not_reached();
    }

    start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (getuid() == 0 && conf->local_server_type == PA_SERVER_TYPE_SYSTEM);

    if (!start_server && conf->local_server_type == PA_SERVER_TYPE_SYSTEM) {
        pa_log_notice(_("System mode refused for non-root user. Only starting the D-Bus server lookup service."));
        conf->system_instance = false;
    }
#endif

    LTDL_SET_PRELOADED_SYMBOLS();
    pa_ltdl_init();
    ltdl_init = true;

    if (conf->dl_search_path)
        lt_dlsetsearchpath(conf->dl_search_path);

#ifdef OS_IS_WIN32
    {
        WSADATA data;
        WSAStartup(MAKEWORD(2, 0), &data);
    }
#endif

    pa_random_seed();

    switch (conf->cmd) {
        case PA_CMD_DUMP_MODULES:
            pa_dump_modules(conf, argc-d, argv+d);
            retval = 0;
            goto finish;

        case PA_CMD_DUMP_CONF: {

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            s = pa_daemon_conf_dump(conf);
            fputs(s, stdout);
            pa_xfree(s);
            retval = 0;
            goto finish;
        }

        case PA_CMD_DUMP_RESAMPLE_METHODS: {
            int i;

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            for (i = 0; i < PA_RESAMPLER_MAX; i++)
                if (pa_resample_method_supported(i))
                    printf("%s\n", pa_resample_method_to_string(i));

            retval = 0;
            goto finish;
        }

        case PA_CMD_HELP :
            pa_cmdline_help(argv[0]);
            retval = 0;
            goto finish;

        case PA_CMD_VERSION :

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");
            retval = 0;
            goto finish;

        case PA_CMD_CHECK: {
            pid_t pid;

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            if (pa_pid_file_check_running(&pid, "pulseaudio") < 0)
                pa_log_info(_("Daemon not running"));
            else {
                pa_log_info(_("Daemon running as PID %u"), pid);
                retval = 0;
            }

            goto finish;

        }
        case PA_CMD_KILL:

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0)
                pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno));
            else
                retval = 0;

            goto finish;

        case PA_CMD_CLEANUP_SHM:

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            if (pa_shm_cleanup() >= 0)
                retval = 0;

            goto finish;

        default:
            pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);
    }

    if (d < argc) {
        pa_log("Too many arguments.\n");
        goto finish;
    }

#ifdef HAVE_GETUID
    if (getuid() == 0 && !conf->system_instance)
        pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));
#ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */
    else if (getuid() != 0 && conf->system_instance) {
        pa_log(_("Root privileges required."));
        goto finish;
    }
#endif
#endif  /* HAVE_GETUID */

    if (conf->cmd == PA_CMD_START && conf->system_instance) {
        pa_log(_("--start not supported for system instances."));
        goto finish;
    }

    if (conf->cmd == PA_CMD_START && (configured_address = check_configured_address())) {
        /* There is an server address in our config, but where did it come from?
         * By default a standard X11 login will load module-x11-publish which will
         * inject PULSE_SERVER X11 property. If the PA daemon crashes, we will end
         * up hitting this code path. So we have to check to see if our configured_address
         * is the same as the value that would go into this property so that we can
         * recover (i.e. autospawn) from a crash.
         */
        char *ufn;
        bool start_anyway = false;

        if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) {
            char *id;

            if ((id = pa_machine_id())) {
                pa_strlist *server_list;
                char formatted_ufn[256];

                pa_snprintf(formatted_ufn, sizeof(formatted_ufn), "{%s}unix:%s", id, ufn);
                pa_xfree(id);

                if ((server_list = pa_strlist_parse(configured_address))) {
                    char *u = NULL;

                    /* We only need to check the first server */
                    server_list = pa_strlist_pop(server_list, &u);
                    pa_strlist_free(server_list);

                    start_anyway = (u && pa_streq(formatted_ufn, u));
                    pa_xfree(u);
                }
            }
            pa_xfree(ufn);
        }

        if (!start_anyway) {
            pa_log_notice(_("User-configured server at %s, refusing to start/autospawn."), configured_address);
            pa_xfree(configured_address);
            retval = 0;
            goto finish;
        }

        pa_log_notice(_("User-configured server at %s, which appears to be local. Probing deeper."), configured_address);
        pa_xfree(configured_address);
    }

    if (conf->system_instance && !conf->disallow_exit)
        pa_log_warn(_("Running in system mode, but --disallow-exit not set!"));

    if (conf->system_instance && !conf->disallow_module_loading)
        pa_log_warn(_("Running in system mode, but --disallow-module-loading not set!"));

    if (conf->system_instance && !conf->disable_shm) {
        pa_log_notice(_("Running in system mode, forcibly disabling SHM mode!"));
        conf->disable_shm = true;
    }

    if (conf->system_instance && conf->exit_idle_time >= 0) {
        pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!"));
        conf->exit_idle_time = -1;
    }

    if (conf->cmd == PA_CMD_START) {
        /* If we shall start PA only when it is not running yet, we
         * first take the autospawn lock to make things
         * synchronous. */

        if ((autospawn_fd = pa_autospawn_lock_init()) < 0) {
            pa_log("Failed to initialize autospawn lock");
            goto finish;
        }

        if ((pa_autospawn_lock_acquire(true) < 0)) {
            pa_log("Failed to acquire autospawn lock");
            goto finish;
        }

        autospawn_locked = true;
    }

    if (conf->daemonize) {
#ifdef HAVE_FORK
        pid_t child;
#endif

        if (pa_stdio_acquire() < 0) {
            pa_log(_("Failed to acquire stdio."));
            goto finish;
        }

#ifdef HAVE_FORK
        if (pipe(daemon_pipe) < 0) {
            pa_log(_("pipe() failed: %s"), pa_cstrerror(errno));
            goto finish;
        }

        if ((child = fork()) < 0) {
            pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
            pa_close_pipe(daemon_pipe);
            goto finish;
        }

        if (child != 0) {
            ssize_t n;
            /* Father */

            pa_assert_se(pa_close(daemon_pipe[1]) == 0);
            daemon_pipe[1] = -1;

            if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {

                if (n < 0)
                    pa_log(_("read() failed: %s"), pa_cstrerror(errno));

                retval = 1;
            }

            if (retval)
                pa_log(_("Daemon startup failed."));
            else
                pa_log_info(_("Daemon startup successful."));

            goto finish;
        }

        if (autospawn_fd >= 0) {
            /* The lock file is unlocked from the parent, so we need
             * to close it in the child */

            pa_autospawn_lock_release();
            pa_autospawn_lock_done(true);

            autospawn_locked = false;
            autospawn_fd = -1;
        }

        pa_assert_se(pa_close(daemon_pipe[0]) == 0);
        daemon_pipe[0] = -1;
#endif

        if (!conf->log_target) {
#ifdef HAVE_JOURNAL
            pa_log_target target = { .type = PA_LOG_JOURNAL, .file = NULL };
#else
            pa_log_target target = { .type = PA_LOG_SYSLOG, .file = NULL };
#endif
            pa_log_set_target(&target);
        }
コード例 #23
0
ファイル: resampler-test.c プロジェクト: KimT/pulseaudio_kt
static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) {
    void *d;
    unsigned i;

    d = pa_memblock_acquire(chunk->memblock);

    switch (ss->format) {

        case PA_SAMPLE_U8:
        case PA_SAMPLE_ULAW:
        case PA_SAMPLE_ALAW: {
            uint8_t *u = d;

            for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
                printf("      0x%02x ", *(u++));

            break;
        }

        case PA_SAMPLE_S16NE:
        case PA_SAMPLE_S16RE: {
            uint16_t *u = d;

            for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
                printf("    0x%04x ", *(u++));

            break;
        }

        case PA_SAMPLE_S32NE:
        case PA_SAMPLE_S32RE: {
            uint32_t *u = d;

            for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
                printf("0x%08x ", *(u++));

            break;
        }

        case PA_SAMPLE_S24_32NE:
        case PA_SAMPLE_S24_32RE: {
            uint32_t *u = d;

            for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
                printf("0x%08x ", *(u++));

            break;
        }

        case PA_SAMPLE_FLOAT32NE:
        case PA_SAMPLE_FLOAT32RE: {
            float *u = d;

            for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
                printf("%4.3g ", ss->format == PA_SAMPLE_FLOAT32NE ? *u : PA_FLOAT32_SWAP(*u));
                u++;
            }

            break;
        }

        case PA_SAMPLE_S24LE:
        case PA_SAMPLE_S24BE: {
            uint8_t *u = d;

            for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
                printf("  0x%06x ", PA_READ24NE(u));
                u += pa_frame_size(ss);
            }

            break;
        }

        default:
            pa_assert_not_reached();
    }

    printf("\n");

    pa_memblock_release(chunk->memblock);
}
コード例 #24
0
int pa__init(pa_module*m) {
    struct userdata *u;
    pa_sample_spec ss;
    pa_channel_map map;
    pa_modargs *ma;
    char *t;
    pa_sink *master;
    pa_sink_input_new_data sink_input_data;
    pa_sink_new_data sink_data;
    const char *plugin, *label;
    LADSPA_Descriptor_Function descriptor_func;
    const char *e, *cdata;
    const LADSPA_Descriptor *d;
    unsigned long input_port, output_port, p, j, n_control;
    unsigned c;
    pa_bool_t *use_default = NULL;

    pa_assert(m);

    pa_assert_cc(sizeof(LADSPA_Data) == sizeof(float));

    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
        pa_log("Failed to parse module arguments.");
        goto fail;
    }

    if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) {
        pa_log("Master sink not found");
        goto fail;
    }

    ss = master->sample_spec;
    ss.format = PA_SAMPLE_FLOAT32;
    map = master->channel_map;
    if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
        pa_log("Invalid sample format specification or channel map");
        goto fail;
    }

    if (!(plugin = pa_modargs_get_value(ma, "plugin", NULL))) {
        pa_log("Missing LADSPA plugin name");
        goto fail;
    }

    if (!(label = pa_modargs_get_value(ma, "label", NULL))) {
        pa_log("Missing LADSPA plugin label");
        goto fail;
    }

    cdata = pa_modargs_get_value(ma, "control", NULL);

    u = pa_xnew0(struct userdata, 1);
    u->module = m;
    m->userdata = u;
    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, NULL);

    if (!(e = getenv("LADSPA_PATH")))
        e = LADSPA_PATH;

    /* FIXME: This is not exactly thread safe */
    t = pa_xstrdup(lt_dlgetsearchpath());
    lt_dlsetsearchpath(e);
    m->dl = lt_dlopenext(plugin);
    lt_dlsetsearchpath(t);
    pa_xfree(t);

    if (!m->dl) {
        pa_log("Failed to load LADSPA plugin: %s", lt_dlerror());
        goto fail;
    }

    if (!(descriptor_func = (LADSPA_Descriptor_Function) pa_load_sym(m->dl, NULL, "ladspa_descriptor"))) {
        pa_log("LADSPA module lacks ladspa_descriptor() symbol.");
        goto fail;
    }

    for (j = 0;; j++) {

        if (!(d = descriptor_func(j))) {
            pa_log("Failed to find plugin label '%s' in plugin '%s'.", label, plugin);
            goto fail;
        }

        if (strcmp(d->Label, label) == 0)
            break;
    }

    u->descriptor = d;

    pa_log_debug("Module: %s", plugin);
    pa_log_debug("Label: %s", d->Label);
    pa_log_debug("Unique ID: %lu", d->UniqueID);
    pa_log_debug("Name: %s", d->Name);
    pa_log_debug("Maker: %s", d->Maker);
    pa_log_debug("Copyright: %s", d->Copyright);

    input_port = output_port = (unsigned long) -1;
    n_control = 0;

    for (p = 0; p < d->PortCount; p++) {

        if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) {

            if (strcmp(d->PortNames[p], "Input") == 0) {
                pa_assert(input_port == (unsigned long) -1);
                input_port = p;
            } else {
                pa_log("Found audio input port on plugin we cannot handle: %s", d->PortNames[p]);
                goto fail;
            }

        } else if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) {

            if (strcmp(d->PortNames[p], "Output") == 0) {
                pa_assert(output_port == (unsigned long) -1);
                output_port = p;
            } else {
                pa_log("Found audio output port on plugin we cannot handle: %s", d->PortNames[p]);
                goto fail;
            }

        } else if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
            n_control++;
        else {
            pa_assert(LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]));
            pa_log_debug("Ignored control output port \"%s\".", d->PortNames[p]);
        }
    }

    if ((input_port == (unsigned long) -1) || (output_port == (unsigned long) -1)) {
        pa_log("Failed to identify input and output ports. "
               "Right now this module can only deal with plugins which provide an 'Input' and an 'Output' audio port. "
               "Patches welcome!");
        goto fail;
    }

    u->block_size = pa_frame_align(pa_mempool_block_size_max(m->core->mempool), &ss);

    u->input = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size);
    if (LADSPA_IS_INPLACE_BROKEN(d->Properties))
        u->output = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size);
    else
        u->output = u->input;

    u->channels = ss.channels;

    for (c = 0; c < ss.channels; c++) {
        if (!(u->handle[c] = d->instantiate(d, ss.rate))) {
            pa_log("Failed to instantiate plugin %s with label %s for channel %i", plugin, d->Label, c);
            goto fail;
        }

        d->connect_port(u->handle[c], input_port, u->input);
        d->connect_port(u->handle[c], output_port, u->output);
    }

    if (!cdata && n_control > 0) {
        pa_log("This plugin requires specification of %lu control parameters.", n_control);
        goto fail;
    }

    if (n_control > 0) {
        const char *state = NULL;
        char *k;
        unsigned long h;

        u->control = pa_xnew(LADSPA_Data, (unsigned) n_control);
        use_default = pa_xnew(pa_bool_t, (unsigned) n_control);
        p = 0;

        while ((k = pa_split(cdata, ",", &state)) && p < n_control) {
            double f;

            if (*k == 0) {
                use_default[p++] = TRUE;
                pa_xfree(k);
                continue;
            }

            if (pa_atod(k, &f) < 0) {
                pa_log("Failed to parse control value '%s'", k);
                pa_xfree(k);
                goto fail;
            }

            pa_xfree(k);

            use_default[p] = FALSE;
            u->control[p++] = (LADSPA_Data) f;
        }

        /* The previous loop doesn't take the last control value into account
           if it is left empty, so we do it here. */
        if (*cdata == 0 || cdata[strlen(cdata) - 1] == ',') {
            if (p < n_control)
                use_default[p] = TRUE;
            p++;
        }

        if (p > n_control || k) {
            pa_log("Too many control values passed, %lu expected.", n_control);
            pa_xfree(k);
            goto fail;
        }

        if (p < n_control) {
            pa_log("Not enough control values passed, %lu expected, %lu passed.", n_control, p);
            goto fail;
        }

        h = 0;
        for (p = 0; p < d->PortCount; p++) {
            LADSPA_PortRangeHintDescriptor hint = d->PortRangeHints[p].HintDescriptor;

            if (!LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
                continue;

            if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p])) {
                for (c = 0; c < ss.channels; c++)
                    d->connect_port(u->handle[c], p, &u->control_out);
                continue;
            }

            pa_assert(h < n_control);

            if (use_default[h]) {
                LADSPA_Data lower, upper;

                if (!LADSPA_IS_HINT_HAS_DEFAULT(hint)) {
                    pa_log("Control port value left empty but plugin defines no default.");
                    goto fail;
                }

                lower = d->PortRangeHints[p].LowerBound;
                upper = d->PortRangeHints[p].UpperBound;

                if (LADSPA_IS_HINT_SAMPLE_RATE(hint)) {
                    lower *= (LADSPA_Data) ss.rate;
                    upper *= (LADSPA_Data) ss.rate;
                }

                switch (hint & LADSPA_HINT_DEFAULT_MASK) {

                    case LADSPA_HINT_DEFAULT_MINIMUM:
                        u->control[h] = lower;
                        break;

                    case LADSPA_HINT_DEFAULT_MAXIMUM:
                        u->control[h] = upper;
                        break;

                    case LADSPA_HINT_DEFAULT_LOW:
                        if (LADSPA_IS_HINT_LOGARITHMIC(hint))
                            u->control[h] = (LADSPA_Data) exp(log(lower) * 0.75 + log(upper) * 0.25);
                        else
                            u->control[h] = (LADSPA_Data) (lower * 0.75 + upper * 0.25);
                        break;

                    case LADSPA_HINT_DEFAULT_MIDDLE:
                        if (LADSPA_IS_HINT_LOGARITHMIC(hint))
                            u->control[h] = (LADSPA_Data) exp(log(lower) * 0.5 + log(upper) * 0.5);
                        else
                            u->control[h] = (LADSPA_Data) (lower * 0.5 + upper * 0.5);
                        break;

                    case LADSPA_HINT_DEFAULT_HIGH:
                        if (LADSPA_IS_HINT_LOGARITHMIC(hint))
                            u->control[h] = (LADSPA_Data) exp(log(lower) * 0.25 + log(upper) * 0.75);
                        else
                            u->control[h] = (LADSPA_Data) (lower * 0.25 + upper * 0.75);
                        break;

                    case LADSPA_HINT_DEFAULT_0:
                        u->control[h] = 0;
                        break;

                    case LADSPA_HINT_DEFAULT_1:
                        u->control[h] = 1;
                        break;

                    case LADSPA_HINT_DEFAULT_100:
                        u->control[h] = 100;
                        break;

                    case LADSPA_HINT_DEFAULT_440:
                        u->control[h] = 440;
                        break;

                    default:
                        pa_assert_not_reached();
                }
            }

            if (LADSPA_IS_HINT_INTEGER(hint))
                u->control[h] = roundf(u->control[h]);

            pa_log_debug("Binding %f to port %s", u->control[h], d->PortNames[p]);

            for (c = 0; c < ss.channels; c++)
                d->connect_port(u->handle[c], p, &u->control[h]);

            h++;
        }

        pa_assert(h == n_control);
    }

    if (d->activate)
        for (c = 0; c < u->channels; c++)
            d->activate(u->handle[c]);

    /* Create sink */
    pa_sink_new_data_init(&sink_data);
    sink_data.driver = __FILE__;
    sink_data.module = m;
    if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
        sink_data.name = pa_sprintf_malloc("%s.ladspa", master->name);
    pa_sink_new_data_set_sample_spec(&sink_data, &ss);
    pa_sink_new_data_set_channel_map(&sink_data, &map);
    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
    pa_proplist_sets(sink_data.proplist, "device.ladspa.module", plugin);
    pa_proplist_sets(sink_data.proplist, "device.ladspa.label", d->Label);
    pa_proplist_sets(sink_data.proplist, "device.ladspa.name", d->Name);
    pa_proplist_sets(sink_data.proplist, "device.ladspa.maker", d->Maker);
    pa_proplist_sets(sink_data.proplist, "device.ladspa.copyright", d->Copyright);
    pa_proplist_setf(sink_data.proplist, "device.ladspa.unique_id", "%lu", (unsigned long) d->UniqueID);

    if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
        pa_log("Invalid properties");
        pa_sink_new_data_done(&sink_data);
        goto fail;
    }

    if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
        const char *z;

        z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
        pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s", d->Name, z ? z : master->name);
    }

    u->sink = pa_sink_new(m->core, &sink_data,
                          PA_SINK_HW_MUTE_CTRL|PA_SINK_HW_VOLUME_CTRL|PA_SINK_DECIBEL_VOLUME|
                          (master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
    pa_sink_new_data_done(&sink_data);

    if (!u->sink) {
        pa_log("Failed to create sink.");
        goto fail;
    }

    u->sink->parent.process_msg = sink_process_msg_cb;
    u->sink->set_state = sink_set_state_cb;
    u->sink->update_requested_latency = sink_update_requested_latency_cb;
    u->sink->request_rewind = sink_request_rewind_cb;
    u->sink->set_volume = sink_set_volume_cb;
    u->sink->set_mute = sink_set_mute_cb;
    u->sink->userdata = u;

    pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);

    /* Create sink input */
    pa_sink_input_new_data_init(&sink_input_data);
    sink_input_data.driver = __FILE__;
    sink_input_data.module = m;
    sink_input_data.sink = master;
    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "LADSPA Stream");
    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
    pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
    pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);

    pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
    pa_sink_input_new_data_done(&sink_input_data);

    if (!u->sink_input)
        goto fail;

    u->sink_input->pop = sink_input_pop_cb;
    u->sink_input->process_rewind = sink_input_process_rewind_cb;
    u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
    u->sink_input->update_max_request = sink_input_update_max_request_cb;
    u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
    u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb;
    u->sink_input->kill = sink_input_kill_cb;
    u->sink_input->attach = sink_input_attach_cb;
    u->sink_input->detach = sink_input_detach_cb;
    u->sink_input->state_change = sink_input_state_change_cb;
    u->sink_input->may_move_to = sink_input_may_move_to_cb;
    u->sink_input->moving = sink_input_moving_cb;
    u->sink_input->volume_changed = sink_input_volume_changed_cb;
    u->sink_input->mute_changed = sink_input_mute_changed_cb;
    u->sink_input->userdata = u;

    pa_sink_put(u->sink);
    pa_sink_input_put(u->sink_input);

    pa_modargs_free(ma);

    pa_xfree(use_default);

    return 0;

fail:
    if (ma)
        pa_modargs_free(ma);

    pa_xfree(use_default);

    pa__done(m);

    return -1;
}
コード例 #25
0
ファイル: module-lirc.c プロジェクト: BYSTROSTREL/pulseaudio
static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) {
    struct userdata *u = userdata;
    char *name = NULL, *code = NULL;

    pa_assert(io);
    pa_assert(u);

    if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) {
        pa_log("Lost connection to LIRC daemon.");
        goto fail;
    }

    if (events & PA_IO_EVENT_INPUT) {
        char *c;

        if (lirc_nextcode(&code) != 0 || !code) {
            pa_log("lirc_nextcode() failed.");
            goto fail;
        }

        c = pa_xstrdup(code);
        c[strcspn(c, "\n\r")] = 0;
        pa_log_debug("Raw IR code '%s'", c);
        pa_xfree(c);

        while (lirc_code2char(u->config, code, &name) == 0 && name) {
            enum {
                INVALID,
                UP,
                DOWN,
                MUTE,
                RESET,
                MUTE_TOGGLE
            } volchange = INVALID;

            pa_log_info("Translated IR code '%s'", name);

            if (strcasecmp(name, "volume-up") == 0)
                volchange = UP;
            else if (strcasecmp(name, "volume-down") == 0)
                volchange = DOWN;
            else if (strcasecmp(name, "mute") == 0)
                volchange = MUTE;
            else if (strcasecmp(name, "mute-toggle") == 0)
                volchange = MUTE_TOGGLE;
            else if (strcasecmp(name, "reset") == 0)
                volchange = RESET;

            if (volchange == INVALID)
                pa_log_warn("Received unknown IR code '%s'", name);
            else {
                pa_sink *s;

                if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK)))
                    pa_log("Failed to get sink '%s'", u->sink_name);
                else {
                    pa_cvolume cv = *pa_sink_get_volume(s, FALSE);

                    switch (volchange) {
                        case UP:
                            pa_cvolume_inc_clamp(&cv, u->volume_step, u->volume_limit);
                            pa_sink_set_volume(s, &cv, TRUE, TRUE);
                            break;

                        case DOWN:
                            pa_cvolume_dec(&cv, u->volume_step);
                            pa_sink_set_volume(s, &cv, TRUE, TRUE);
                            break;

                        case MUTE:
                            pa_sink_set_mute(s, TRUE, TRUE);
                            break;

                        case RESET:
                            pa_sink_set_mute(s, FALSE, TRUE);
                            break;

                        case MUTE_TOGGLE:
                            pa_sink_set_mute(s, !pa_sink_get_mute(s, FALSE), TRUE);
                            break;

                        case INVALID:
                            pa_assert_not_reached();
                    }
                }
            }
        }
    }

    pa_xfree(code);

    return;

fail:
    u->module->core->mainloop->io_free(u->io);
    u->io = NULL;

    pa_module_unload_request(u->module, TRUE);

    pa_xfree(code);
}
コード例 #26
0
ファイル: memblock.c プロジェクト: DryakhlyyZlodey/pulseaudio
static void memblock_free(pa_memblock *b) {
    pa_assert(b);

    pa_assert(pa_atomic_load(&b->n_acquired) == 0);

    stat_remove(b);

    switch (b->type) {
        case PA_MEMBLOCK_USER :
            pa_assert(b->per_type.user.free_cb);
            b->per_type.user.free_cb(pa_atomic_ptr_load(&b->data));

            /* Fall through */

        case PA_MEMBLOCK_FIXED:
            if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0)
                pa_xfree(b);

            break;

        case PA_MEMBLOCK_APPENDED:

            /* We could attach it to unused_memblocks, but that would
             * probably waste some considerable amount of memory */
            pa_xfree(b);
            break;

        case PA_MEMBLOCK_IMPORTED: {
            pa_memimport_segment *segment;
            pa_memimport *import;

            /* FIXME! This should be implemented lock-free */

            pa_assert_se(segment = b->per_type.imported.segment);
            pa_assert_se(import = segment->import);

            pa_mutex_lock(import->mutex);

            pa_assert_se(pa_hashmap_remove(import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)));

            pa_assert(segment->n_blocks >= 1);
            if (-- segment->n_blocks <= 0)
                segment_detach(segment);

            pa_mutex_unlock(import->mutex);

            import->release_cb(import, b->per_type.imported.id, import->userdata);

            if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0)
                pa_xfree(b);

            break;
        }

        case PA_MEMBLOCK_POOL_EXTERNAL:
        case PA_MEMBLOCK_POOL: {
            struct mempool_slot *slot;
            bool call_free;

            pa_assert_se(slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data)));

            call_free = b->type == PA_MEMBLOCK_POOL_EXTERNAL;

/* #ifdef HAVE_VALGRIND_MEMCHECK_H */
/*             if (PA_UNLIKELY(pa_in_valgrind())) { */
/*                 VALGRIND_FREELIKE_BLOCK(slot, b->pool->block_size); */
/*             } */
/* #endif */

            /* The free list dimensions should easily allow all slots
             * to fit in, hence try harder if pushing this slot into
             * the free list fails */
            while (pa_flist_push(b->pool->free_slots, slot) < 0)
                ;

            if (call_free)
                if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0)
                    pa_xfree(b);

            break;
        }

        case PA_MEMBLOCK_TYPE_MAX:
        default:
            pa_assert_not_reached();
    }
}
コード例 #27
0
ファイル: resampler-test.c プロジェクト: KimT/pulseaudio_kt
static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) {
    pa_memblock *r;
    void *d;
    unsigned i;

    pa_assert_se(r = pa_memblock_new(pool, pa_frame_size(ss) * 10));
    d = pa_memblock_acquire(r);

    switch (ss->format) {

        case PA_SAMPLE_U8:
        case PA_SAMPLE_ULAW:
        case PA_SAMPLE_ALAW: {
            uint8_t *u = d;

            u[0] = 0x00;
            u[1] = 0xFF;
            u[2] = 0x7F;
            u[3] = 0x80;
            u[4] = 0x9f;
            u[5] = 0x3f;
            u[6] = 0x1;
            u[7] = 0xF0;
            u[8] = 0x20;
            u[9] = 0x21;
            break;
        }

        case PA_SAMPLE_S16NE:
        case PA_SAMPLE_S16RE: {
            uint16_t *u = d;

            u[0] = 0x0000;
            u[1] = 0xFFFF;
            u[2] = 0x7FFF;
            u[3] = 0x8000;
            u[4] = 0x9fff;
            u[5] = 0x3fff;
            u[6] = 0x1;
            u[7] = 0xF000;
            u[8] = 0x20;
            u[9] = 0x21;
            break;
        }

        case PA_SAMPLE_S32NE:
        case PA_SAMPLE_S32RE: {
            uint32_t *u = d;

            u[0] = 0x00000001;
            u[1] = 0xFFFF0002;
            u[2] = 0x7FFF0003;
            u[3] = 0x80000004;
            u[4] = 0x9fff0005;
            u[5] = 0x3fff0006;
            u[6] =    0x10007;
            u[7] = 0xF0000008;
            u[8] =   0x200009;
            u[9] =   0x21000A;
            break;
        }

        case PA_SAMPLE_S24_32NE:
        case PA_SAMPLE_S24_32RE: {
            uint32_t *u = d;

            u[0] = 0x000001;
            u[1] = 0xFF0002;
            u[2] = 0x7F0003;
            u[3] = 0x800004;
            u[4] = 0x9f0005;
            u[5] = 0x3f0006;
            u[6] =    0x107;
            u[7] = 0xF00008;
            u[8] =   0x2009;
            u[9] =   0x210A;
            break;
        }

        case PA_SAMPLE_FLOAT32NE:
        case PA_SAMPLE_FLOAT32RE: {
            float *u = d;

            u[0] = 0.0f;
            u[1] = -1.0f;
            u[2] = 1.0f;
            u[3] = 4711.0f;
            u[4] = 0.222f;
            u[5] = 0.33f;
            u[6] = -.3f;
            u[7] = 99.0f;
            u[8] = -0.555f;
            u[9] = -.123f;

            if (ss->format == PA_SAMPLE_FLOAT32RE)
                for (i = 0; i < 10; i++)
                    u[i] = PA_FLOAT32_SWAP(u[i]);

            break;
        }

        case PA_SAMPLE_S24NE:
        case PA_SAMPLE_S24RE: {
            uint8_t *u = d;

            PA_WRITE24NE(u,    0x000001);
            PA_WRITE24NE(u+3,  0xFF0002);
            PA_WRITE24NE(u+6,  0x7F0003);
            PA_WRITE24NE(u+9,  0x800004);
            PA_WRITE24NE(u+12, 0x9f0005);
            PA_WRITE24NE(u+15, 0x3f0006);
            PA_WRITE24NE(u+18,    0x107);
            PA_WRITE24NE(u+21, 0xF00008);
            PA_WRITE24NE(u+24,   0x2009);
            PA_WRITE24NE(u+27,   0x210A);
            break;
        }

        default:
            pa_assert_not_reached();
    }

    pa_memblock_release(r);

    return r;
}
コード例 #28
0
static int handle_response(struct userdata *u) {
    pa_assert(u);

    switch (u->state) {

        case STATE_AUTH:
            pa_assert(u->read_length == sizeof(int32_t));

            /* Process auth data */
            if (!*(int32_t*) u->read_data) {
                pa_log("Authentication failed: %s", pa_cstrerror(errno));
                return -1;
            }

            /* Request latency data */
            pa_assert(!u->write_data);
            *(int32_t*) (u->write_data = pa_xmalloc(u->write_length = sizeof(int32_t))) = ESD_PROTO_LATENCY;

            u->write_index = 0;
            u->state = STATE_LATENCY;

            /* Space for next response */
            pa_assert(u->read_length >= sizeof(int32_t));
            u->read_index = 0;
            u->read_length = sizeof(int32_t);

            break;

        case STATE_LATENCY: {
            int32_t *p;
            pa_assert(u->read_length == sizeof(int32_t));

            /* Process latency info */
            u->latency = (pa_usec_t) ((double) (*(int32_t*) u->read_data) * 1000000 / 44100);
            if (u->latency > 10000000) {
                pa_log_warn("Invalid latency information received from server");
                u->latency = 0;
            }

            /* Create stream */
            pa_assert(!u->write_data);
            p = u->write_data = pa_xmalloc0(u->write_length = sizeof(int32_t)*3+ESD_NAME_MAX);
            *(p++) = ESD_PROTO_STREAM_PLAY;
            *(p++) = u->format;
            *(p++) = u->rate;
            pa_strlcpy((char*) p, "PulseAudio Tunnel", ESD_NAME_MAX);

            u->write_index = 0;
            u->state = STATE_PREPARE;

            /* Don't read any further */
            pa_xfree(u->read_data);
            u->read_data = NULL;
            u->read_index = u->read_length = 0;

            break;
        }

        default:
            pa_assert_not_reached();
    }

    return 0;
}
コード例 #29
0
ファイル: context.c プロジェクト: felfert/pulseaudio
static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
    pa_context *c = userdata;

    pa_assert(pd);
    pa_assert(c);
    pa_assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME);

    pa_context_ref(c);

    if (command != PA_COMMAND_REPLY) {
        pa_context_handle_error(c, command, t, TRUE);
        goto finish;
    }

    switch(c->state) {
        case PA_CONTEXT_AUTHORIZING: {
            pa_tagstruct *reply;
            pa_bool_t shm_on_remote = FALSE;

            if (pa_tagstruct_getu32(t, &c->version) < 0 ||
                !pa_tagstruct_eof(t)) {
                pa_context_fail(c, PA_ERR_PROTOCOL);
                goto finish;
            }

            /* Minimum supported version */
            if (c->version < 8) {
                pa_context_fail(c, PA_ERR_VERSION);
                goto finish;
            }

            /* Starting with protocol version 13 the MSB of the version
               tag reflects if shm is available for this connection or
               not. */
            if (c->version >= 13) {
                shm_on_remote = !!(c->version & 0x80000000U);
                c->version &= 0x7FFFFFFFU;
            }

            pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);

            /* Enable shared memory support if possible */
            if (c->do_shm)
                if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
                    c->do_shm = FALSE;

            if (c->do_shm) {

                /* Only enable SHM if both sides are owned by the same
                 * user. This is a security measure because otherwise
                 * data private to the user might leak. */

#ifdef HAVE_CREDS
                const pa_creds *creds;
                if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
                    c->do_shm = FALSE;
#endif
            }

            pa_log_debug("Negotiated SHM: %s", pa_yes_no(c->do_shm));
            pa_pstream_enable_shm(c->pstream, c->do_shm);

            reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);

            if (c->version >= 13) {
                pa_init_proplist(c->proplist);
                pa_tagstruct_put_proplist(reply, c->proplist);
            } else
                pa_tagstruct_puts(reply, pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME));

            pa_pstream_send_tagstruct(c->pstream, reply);
            pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL);

            pa_context_set_state(c, PA_CONTEXT_SETTING_NAME);
            break;
        }

        case PA_CONTEXT_SETTING_NAME :

            if ((c->version >= 13 && (pa_tagstruct_getu32(t, &c->client_index) < 0 ||
                                      c->client_index == PA_INVALID_INDEX)) ||
                !pa_tagstruct_eof(t)) {
                pa_context_fail(c, PA_ERR_PROTOCOL);
                goto finish;
            }

            pa_context_set_state(c, PA_CONTEXT_READY);
            break;

        default:
            pa_assert_not_reached();
    }

finish:
    pa_context_unref(c);
}
コード例 #30
0
static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) {
    struct userdata *u = userdata;

    pa_assert(io);
    pa_assert(u);

    if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) {
        pa_log("Lost connection to evdev device.");
        goto fail;
    }

    if (events & PA_IO_EVENT_INPUT) {
        struct input_event ev;

        if (pa_loop_read(u->fd, &ev, sizeof(ev), &u->fd_type) <= 0) {
            pa_log("Failed to read from event device: %s", pa_cstrerror(errno));
            goto fail;
        }

        if (ev.type == EV_KEY && (ev.value == 1 || ev.value == 2)) {
            enum {
                INVALID,
                UP,
                DOWN,
                MUTE_TOGGLE
            } volchange = INVALID;

            pa_log_debug("Key code=%u, value=%u", ev.code, ev.value);

            switch (ev.code) {
                case KEY_VOLUMEDOWN:
                    volchange = DOWN;
                    break;

                case KEY_VOLUMEUP:
                    volchange = UP;
                    break;

                case KEY_MUTE:
                    volchange = MUTE_TOGGLE;
                    break;
            }

            if (volchange != INVALID) {
                pa_sink *s;

                if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK)))
                    pa_log("Failed to get sink '%s'", u->sink_name);
                else {
                    pa_cvolume cv = *pa_sink_get_volume(s, false);

                    switch (volchange) {
                        case UP:
                            pa_cvolume_inc_clamp(&cv, u->volume_step, u->volume_limit);
                            pa_sink_set_volume(s, &cv, true, true);
                            break;

                        case DOWN:
                            pa_cvolume_dec(&cv, u->volume_step);
                            pa_sink_set_volume(s, &cv, true, true);
                            break;

                        case MUTE_TOGGLE:
                            pa_sink_set_mute(s, !pa_sink_get_mute(s, false), true);
                            break;

                        case INVALID:
                            pa_assert_not_reached();
                    }
                }
            }
        }
    }

    return;

fail:
    u->module->core->mainloop->io_free(u->io);
    u->io = NULL;

    pa_module_unload_request(u->module, true);
}