~diwic/ubuntu/lucid/pulseaudio/bugfixes

« back to all changes in this revision

Viewing changes to src/pulsecore/play-memchunk.c

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich
  • Date: 2008-11-04 15:46:00 UTC
  • mfrom: (1.2.1 upstream) (1.1.6 lenny)
  • Revision ID: james.westby@ubuntu.com-20081104154600-hlzknpcazaam0nxm
Tags: 0.9.13-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Don't build against, and create jack package. Jack is not in main.
  - Remove --disable-per-user-esound-socket from configure flags, as we still
    want per user esound sockets.
  - Remove stop links from rc0 and rc6.
  - Change default resample algorithm and bubffer size.
  - Add alsa configuration files to route alsa applications via pulseaudio.
  - Move libasound2-plugins from Recommends to Depends.
* debian/pulseaudio.preinst: When upgrading from intrepid, remove
  /etc/X11/Xsession.d/70pulseaudio, as this was used to minimize a race
  condition when starting GNOME in intrepid. This race should not exist in
  jaunty once libcanberra is built to use pulseaudio as a backend.
* Do not spawn a pulseaudio server if clients fail to find a running server.
* Remove explicit version dependency for libspeex-dev to allow the package
  to be built for now.
* Regenerate autotools files to work with Ubuntu's newer libtool/libltdl.
* debian/control: libpulsecore5 -> libpulsecore8 to match the library
  soname.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: play-memchunk.c 1971 2007-10-28 19:13:50Z lennart $ */
2
 
 
3
1
/***
4
2
  This file is part of PulseAudio.
5
3
 
6
 
  Copyright 2004-2006 Lennart Poettering
 
4
  Copyright 2004-2008 Lennart Poettering
7
5
 
8
6
  PulseAudio is free software; you can redistribute it and/or modify
9
7
  it under the terms of the GNU Lesser General Public License as published
30
28
#include <string.h>
31
29
 
32
30
#include <pulse/xmalloc.h>
 
31
#include <pulse/gccmacro.h>
33
32
 
34
33
#include <pulsecore/sink-input.h>
35
 
#include <pulsecore/gccmacro.h>
36
34
#include <pulsecore/thread-mq.h>
 
35
#include <pulsecore/play-memblockq.h>
37
36
 
38
37
#include "play-memchunk.h"
39
38
 
40
 
typedef struct memchunk_stream {
41
 
    pa_msgobject parent;
42
 
    pa_core *core;
43
 
    pa_sink_input *sink_input;
44
 
    pa_memchunk memchunk;
45
 
} memchunk_stream;
46
 
 
47
 
enum {
48
 
    MEMCHUNK_STREAM_MESSAGE_UNLINK,
49
 
};
50
 
 
51
 
PA_DECLARE_CLASS(memchunk_stream);
52
 
#define MEMCHUNK_STREAM(o) (memchunk_stream_cast(o))
53
 
static PA_DEFINE_CHECK_TYPE(memchunk_stream, pa_msgobject);
54
 
 
55
 
static void memchunk_stream_unlink(memchunk_stream *u) {
56
 
    pa_assert(u);
57
 
 
58
 
    if (!u->sink_input)
59
 
        return;
60
 
 
61
 
    pa_sink_input_unlink(u->sink_input);
62
 
 
63
 
    pa_sink_input_unref(u->sink_input);
64
 
    u->sink_input = NULL;
65
 
 
66
 
    memchunk_stream_unref(u);
67
 
}
68
 
 
69
 
static void memchunk_stream_free(pa_object *o) {
70
 
    memchunk_stream *u = MEMCHUNK_STREAM(o);
71
 
    pa_assert(u);
72
 
 
73
 
    memchunk_stream_unlink(u);
74
 
 
75
 
    if (u->memchunk.memblock)
76
 
        pa_memblock_unref(u->memchunk.memblock);
77
 
 
78
 
    pa_xfree(u);
79
 
}
80
 
 
81
 
static int memchunk_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
82
 
    memchunk_stream *u = MEMCHUNK_STREAM(o);
83
 
    memchunk_stream_assert_ref(u);
84
 
 
85
 
    switch (code) {
86
 
        case MEMCHUNK_STREAM_MESSAGE_UNLINK:
87
 
            memchunk_stream_unlink(u);
88
 
            break;
89
 
    }
90
 
 
91
 
    return 0;
92
 
}
93
 
 
94
 
static void sink_input_kill_cb(pa_sink_input *i) {
95
 
    pa_sink_input_assert_ref(i);
96
 
 
97
 
    memchunk_stream_unlink(MEMCHUNK_STREAM(i->userdata));
98
 
}
99
 
 
100
 
static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
101
 
    memchunk_stream *u;
102
 
 
103
 
    pa_assert(i);
104
 
    pa_assert(chunk);
105
 
    u = MEMCHUNK_STREAM(i->userdata);
106
 
    memchunk_stream_assert_ref(u);
107
 
 
108
 
    if (!u->memchunk.memblock)
109
 
        return -1;
110
 
 
111
 
    if (u->memchunk.length <= 0) {
112
 
        pa_memblock_unref(u->memchunk.memblock);
113
 
        u->memchunk.memblock = NULL;
114
 
        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), MEMCHUNK_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
115
 
        return -1;
116
 
    }
117
 
 
118
 
    pa_assert(u->memchunk.memblock);
119
 
    *chunk = u->memchunk;
120
 
    pa_memblock_ref(chunk->memblock);
121
 
 
122
 
    return 0;
123
 
}
124
 
 
125
 
static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
126
 
    memchunk_stream *u;
127
 
 
128
 
    pa_assert(i);
129
 
    pa_assert(length > 0);
130
 
    u = MEMCHUNK_STREAM(i->userdata);
131
 
    memchunk_stream_assert_ref(u);
132
 
 
133
 
    if (length < u->memchunk.length) {
134
 
        u->memchunk.length -= length;
135
 
        u->memchunk.index += length;
136
 
    } else
137
 
        u->memchunk.length = 0;
138
 
}
139
 
 
140
39
int pa_play_memchunk(
141
40
        pa_sink *sink,
142
 
        const char *name,
143
41
        const pa_sample_spec *ss,
144
42
        const pa_channel_map *map,
145
43
        const pa_memchunk *chunk,
146
 
        pa_cvolume *volume) {
 
44
        pa_cvolume *volume,
 
45
        pa_proplist *p,
 
46
        uint32_t *sink_input_index) {
147
47
 
148
 
    memchunk_stream *u = NULL;
149
 
    pa_sink_input_new_data data;
 
48
    pa_memblockq *q;
 
49
    int r;
150
50
 
151
51
    pa_assert(sink);
152
52
    pa_assert(ss);
153
53
    pa_assert(chunk);
154
54
 
155
 
    if (volume && pa_cvolume_is_muted(volume))
156
 
        return 0;
157
 
 
158
 
    pa_memchunk_will_need(chunk);
159
 
 
160
 
    u = pa_msgobject_new(memchunk_stream);
161
 
    u->parent.parent.free = memchunk_stream_free;
162
 
    u->parent.process_msg = memchunk_stream_process_msg;
163
 
    u->core = sink->core;
164
 
    u->memchunk = *chunk;
165
 
    pa_memblock_ref(u->memchunk.memblock);
166
 
 
167
 
    pa_sink_input_new_data_init(&data);
168
 
    data.sink = sink;
169
 
    data.driver = __FILE__;
170
 
    data.name = name;
171
 
    pa_sink_input_new_data_set_sample_spec(&data, ss);
172
 
    pa_sink_input_new_data_set_channel_map(&data, map);
173
 
    pa_sink_input_new_data_set_volume(&data, volume);
174
 
 
175
 
    if (!(u->sink_input = pa_sink_input_new(sink->core, &data, 0)))
176
 
        goto fail;
177
 
 
178
 
    u->sink_input->peek = sink_input_peek_cb;
179
 
    u->sink_input->drop = sink_input_drop_cb;
180
 
    u->sink_input->kill = sink_input_kill_cb;
181
 
    u->sink_input->userdata = u;
182
 
 
183
 
    pa_sink_input_put(u->sink_input);
184
 
 
185
 
    /* The reference to u is dangling here, because we want to keep
186
 
     * this stream around until it is fully played. */
 
55
    q = pa_memblockq_new(0, chunk->length, 0, pa_frame_size(ss), 1, 1, 0, NULL);
 
56
    pa_assert_se(pa_memblockq_push(q, chunk) >= 0);
 
57
 
 
58
    if ((r = pa_play_memblockq(sink, ss, map, q, volume, p, sink_input_index)) < 0) {
 
59
        pa_memblockq_free(q);
 
60
        return r;
 
61
    }
187
62
 
188
63
    return 0;
189
 
 
190
 
fail:
191
 
    if (u)
192
 
        memchunk_stream_unref(u);
193
 
 
194
 
    return -1;
195
64
}
196