~ubuntu-branches/ubuntu/utopic/mpd/utopic-proposed

« back to all changes in this revision

Viewing changes to src/decoder_buffer.c

  • Committer: Package Import Robot
  • Author(s): Steve Kowalik
  • Date: 2013-11-12 18:17:40 UTC
  • mfrom: (2.2.36 sid)
  • Revision ID: package-import@ubuntu.com-20131112181740-72aa4zihehoobedp
Tags: 0.18.3-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - Add libmp3lame-dev to Build-Depends, and enable LAME.
  - Read the user for the daemon from the config file in the init script.
  - Move avahi-daemon from Suggests to Recommends.
  - Added apport hook to include user configuration file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2003-2011 The Music Player Daemon Project
3
 
 * http://www.musicpd.org
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation; either version 2 of the License, or
8
 
 * (at your option) any later version.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License along
16
 
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
 
 */
19
 
 
20
 
#include "config.h"
21
 
#include "decoder_buffer.h"
22
 
#include "decoder_api.h"
23
 
 
24
 
#include <glib.h>
25
 
 
26
 
#include <assert.h>
27
 
 
28
 
struct decoder_buffer {
29
 
        struct decoder *decoder;
30
 
        struct input_stream *is;
31
 
 
32
 
        /** the allocated size of the buffer */
33
 
        size_t size;
34
 
 
35
 
        /** the current length of the buffer */
36
 
        size_t length;
37
 
 
38
 
        /** number of bytes already consumed at the beginning of the
39
 
            buffer */
40
 
        size_t consumed;
41
 
 
42
 
        /** the actual buffer (dynamic size) */
43
 
        unsigned char data[sizeof(size_t)];
44
 
};
45
 
 
46
 
struct decoder_buffer *
47
 
decoder_buffer_new(struct decoder *decoder, struct input_stream *is,
48
 
                   size_t size)
49
 
{
50
 
        struct decoder_buffer *buffer =
51
 
                g_malloc(sizeof(*buffer) - sizeof(buffer->data) + size);
52
 
 
53
 
        assert(is != NULL);
54
 
        assert(size > 0);
55
 
 
56
 
        buffer->decoder = decoder;
57
 
        buffer->is = is;
58
 
        buffer->size = size;
59
 
        buffer->length = 0;
60
 
        buffer->consumed = 0;
61
 
 
62
 
        return buffer;
63
 
}
64
 
 
65
 
void
66
 
decoder_buffer_free(struct decoder_buffer *buffer)
67
 
{
68
 
        assert(buffer != NULL);
69
 
 
70
 
        g_free(buffer);
71
 
}
72
 
 
73
 
bool
74
 
decoder_buffer_is_empty(const struct decoder_buffer *buffer)
75
 
{
76
 
        return buffer->consumed == buffer->length;
77
 
}
78
 
 
79
 
bool
80
 
decoder_buffer_is_full(const struct decoder_buffer *buffer)
81
 
{
82
 
        return buffer->consumed == 0 && buffer->length == buffer->size;
83
 
}
84
 
 
85
 
static void
86
 
decoder_buffer_shift(struct decoder_buffer *buffer)
87
 
{
88
 
        assert(buffer->consumed > 0);
89
 
 
90
 
        buffer->length -= buffer->consumed;
91
 
        memmove(buffer->data, buffer->data + buffer->consumed, buffer->length);
92
 
        buffer->consumed = 0;
93
 
}
94
 
 
95
 
bool
96
 
decoder_buffer_fill(struct decoder_buffer *buffer)
97
 
{
98
 
        size_t nbytes;
99
 
 
100
 
        if (buffer->consumed > 0)
101
 
                decoder_buffer_shift(buffer);
102
 
 
103
 
        if (buffer->length >= buffer->size)
104
 
                /* buffer is full */
105
 
                return false;
106
 
 
107
 
        nbytes = decoder_read(buffer->decoder, buffer->is,
108
 
                              buffer->data + buffer->length,
109
 
                              buffer->size - buffer->length);
110
 
        if (nbytes == 0)
111
 
                /* end of file, I/O error or decoder command
112
 
                   received */
113
 
                return false;
114
 
 
115
 
        buffer->length += nbytes;
116
 
        assert(buffer->length <= buffer->size);
117
 
 
118
 
        return true;
119
 
}
120
 
 
121
 
const void *
122
 
decoder_buffer_read(const struct decoder_buffer *buffer, size_t *length_r)
123
 
{
124
 
        if (buffer->consumed >= buffer->length)
125
 
                /* buffer is empty */
126
 
                return NULL;
127
 
 
128
 
        *length_r = buffer->length - buffer->consumed;
129
 
        return buffer->data + buffer->consumed;
130
 
}
131
 
 
132
 
void
133
 
decoder_buffer_consume(struct decoder_buffer *buffer, size_t nbytes)
134
 
{
135
 
        /* just move the "consumed" pointer - decoder_buffer_shift()
136
 
           will do the real work later (called by
137
 
           decoder_buffer_fill()) */
138
 
        buffer->consumed += nbytes;
139
 
 
140
 
        assert(buffer->consumed <= buffer->length);
141
 
}
142
 
 
143
 
bool
144
 
decoder_buffer_skip(struct decoder_buffer *buffer, size_t nbytes)
145
 
{
146
 
        size_t length;
147
 
        const void *data;
148
 
        bool success;
149
 
 
150
 
        /* this could probably be optimized by seeking */
151
 
 
152
 
        while (true) {
153
 
                data = decoder_buffer_read(buffer, &length);
154
 
                if (data != NULL) {
155
 
                        if (length > nbytes)
156
 
                                length = nbytes;
157
 
                        decoder_buffer_consume(buffer, length);
158
 
                        nbytes -= length;
159
 
                        if (nbytes == 0)
160
 
                                return true;
161
 
                }
162
 
 
163
 
                success = decoder_buffer_fill(buffer);
164
 
                if (!success)
165
 
                        return false;
166
 
        }
167
 
}