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

« back to all changes in this revision

Viewing changes to src/decoder/MikmodDecoderPlugin.cxx

  • 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-2013 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 "MikmodDecoderPlugin.hxx"
 
22
#include "DecoderAPI.hxx"
 
23
#include "tag/TagHandler.hxx"
 
24
#include "system/FatalError.hxx"
 
25
#include "util/Domain.hxx"
 
26
#include "Log.hxx"
 
27
 
 
28
#include <glib.h>
 
29
#include <mikmod.h>
 
30
#include <assert.h>
 
31
 
 
32
static constexpr Domain mikmod_domain("mikmod");
 
33
 
 
34
/* this is largely copied from alsaplayer */
 
35
 
 
36
static constexpr size_t MIKMOD_FRAME_SIZE = 4096;
 
37
 
 
38
static BOOL
 
39
mikmod_mpd_init(void)
 
40
{
 
41
        return VC_Init();
 
42
}
 
43
 
 
44
static void
 
45
mikmod_mpd_exit(void)
 
46
{
 
47
        VC_Exit();
 
48
}
 
49
 
 
50
static void
 
51
mikmod_mpd_update(void)
 
52
{
 
53
}
 
54
 
 
55
static BOOL
 
56
mikmod_mpd_is_present(void)
 
57
{
 
58
        return true;
 
59
}
 
60
 
 
61
static char drv_name[] = PACKAGE_NAME;
 
62
static char drv_version[] = VERSION;
 
63
 
 
64
#if (LIBMIKMOD_VERSION > 0x030106)
 
65
static char drv_alias[] = PACKAGE;
 
66
#endif
 
67
 
 
68
static MDRIVER drv_mpd = {
 
69
        nullptr,
 
70
        drv_name,
 
71
        drv_version,
 
72
        0,
 
73
        255,
 
74
#if (LIBMIKMOD_VERSION > 0x030106)
 
75
        drv_alias,
 
76
#if (LIBMIKMOD_VERSION >= 0x030200)
 
77
        nullptr,  /* CmdLineHelp */
 
78
#endif
 
79
        nullptr,  /* CommandLine */
 
80
#endif
 
81
        mikmod_mpd_is_present,
 
82
        VC_SampleLoad,
 
83
        VC_SampleUnload,
 
84
        VC_SampleSpace,
 
85
        VC_SampleLength,
 
86
        mikmod_mpd_init,
 
87
        mikmod_mpd_exit,
 
88
        nullptr,
 
89
        VC_SetNumVoices,
 
90
        VC_PlayStart,
 
91
        VC_PlayStop,
 
92
        mikmod_mpd_update,
 
93
        nullptr,
 
94
        VC_VoiceSetVolume,
 
95
        VC_VoiceGetVolume,
 
96
        VC_VoiceSetFrequency,
 
97
        VC_VoiceGetFrequency,
 
98
        VC_VoiceSetPanning,
 
99
        VC_VoiceGetPanning,
 
100
        VC_VoicePlay,
 
101
        VC_VoiceStop,
 
102
        VC_VoiceStopped,
 
103
        VC_VoiceGetPosition,
 
104
        VC_VoiceRealVolume
 
105
};
 
106
 
 
107
static bool mikmod_loop;
 
108
static unsigned mikmod_sample_rate;
 
109
 
 
110
static bool
 
111
mikmod_decoder_init(const config_param &param)
 
112
{
 
113
        static char params[] = "";
 
114
 
 
115
        mikmod_loop = param.GetBlockValue("loop", false);
 
116
        mikmod_sample_rate = param.GetBlockValue("sample_rate", 44100u);
 
117
        if (!audio_valid_sample_rate(mikmod_sample_rate))
 
118
                FormatFatalError("Invalid sample rate in line %d: %u",
 
119
                                 param.line, mikmod_sample_rate);
 
120
 
 
121
        md_device = 0;
 
122
        md_reverb = 0;
 
123
 
 
124
        MikMod_RegisterDriver(&drv_mpd);
 
125
        MikMod_RegisterAllLoaders();
 
126
 
 
127
        md_pansep = 64;
 
128
        md_mixfreq = mikmod_sample_rate;
 
129
        md_mode = (DMODE_SOFT_MUSIC | DMODE_INTERP | DMODE_STEREO |
 
130
                   DMODE_16BITS);
 
131
 
 
132
        if (MikMod_Init(params)) {
 
133
                FormatError(mikmod_domain,
 
134
                            "Could not init MikMod: %s",
 
135
                            MikMod_strerror(MikMod_errno));
 
136
                return false;
 
137
        }
 
138
 
 
139
        return true;
 
140
}
 
141
 
 
142
static void
 
143
mikmod_decoder_finish(void)
 
144
{
 
145
        MikMod_Exit();
 
146
}
 
147
 
 
148
static void
 
149
mikmod_decoder_file_decode(Decoder &decoder, const char *path_fs)
 
150
{
 
151
        /* deconstify the path because libmikmod wants a non-const
 
152
           string pointer */
 
153
        char *const path2 = const_cast<char *>(path_fs);
 
154
 
 
155
        MODULE *handle;
 
156
        int ret;
 
157
        SBYTE buffer[MIKMOD_FRAME_SIZE];
 
158
 
 
159
        handle = Player_Load(path2, 128, 0);
 
160
 
 
161
        if (handle == nullptr) {
 
162
                FormatError(mikmod_domain,
 
163
                            "failed to open mod: %s", path_fs);
 
164
                return;
 
165
        }
 
166
 
 
167
        handle->loop = mikmod_loop;
 
168
 
 
169
        const AudioFormat audio_format(mikmod_sample_rate, SampleFormat::S16, 2);
 
170
        assert(audio_format.IsValid());
 
171
 
 
172
        decoder_initialized(decoder, audio_format, false, 0);
 
173
 
 
174
        Player_Start(handle);
 
175
 
 
176
        DecoderCommand cmd = DecoderCommand::NONE;
 
177
        while (cmd == DecoderCommand::NONE && Player_Active()) {
 
178
                ret = VC_WriteBytes(buffer, sizeof(buffer));
 
179
                cmd = decoder_data(decoder, nullptr, buffer, ret, 0);
 
180
        }
 
181
 
 
182
        Player_Stop();
 
183
        Player_Free(handle);
 
184
}
 
185
 
 
186
static bool
 
187
mikmod_decoder_scan_file(const char *path_fs,
 
188
                         const struct tag_handler *handler, void *handler_ctx)
 
189
{
 
190
        /* deconstify the path because libmikmod wants a non-const
 
191
           string pointer */
 
192
        char *const path2 = const_cast<char *>(path_fs);
 
193
 
 
194
        MODULE *handle = Player_Load(path2, 128, 0);
 
195
 
 
196
        if (handle == nullptr) {
 
197
                FormatDebug(mikmod_domain,
 
198
                            "Failed to open file: %s", path_fs);
 
199
                return false;
 
200
        }
 
201
 
 
202
        Player_Free(handle);
 
203
 
 
204
        char *title = Player_LoadTitle(path2);
 
205
        if (title != nullptr) {
 
206
                tag_handler_invoke_tag(handler, handler_ctx,
 
207
                                       TAG_TITLE, title);
 
208
#if (LIBMIKMOD_VERSION >= 0x030200)
 
209
                MikMod_free(title);
 
210
#else
 
211
                free(title);
 
212
#endif
 
213
        }
 
214
 
 
215
        return true;
 
216
}
 
217
 
 
218
static const char *const mikmod_decoder_suffixes[] = {
 
219
        "amf",
 
220
        "dsm",
 
221
        "far",
 
222
        "gdm",
 
223
        "imf",
 
224
        "it",
 
225
        "med",
 
226
        "mod",
 
227
        "mtm",
 
228
        "s3m",
 
229
        "stm",
 
230
        "stx",
 
231
        "ult",
 
232
        "uni",
 
233
        "xm",
 
234
        nullptr
 
235
};
 
236
 
 
237
const struct DecoderPlugin mikmod_decoder_plugin = {
 
238
        "mikmod",
 
239
        mikmod_decoder_init,
 
240
        mikmod_decoder_finish,
 
241
        nullptr,
 
242
        mikmod_decoder_file_decode,
 
243
        mikmod_decoder_scan_file,
 
244
        nullptr,
 
245
        nullptr,
 
246
        mikmod_decoder_suffixes,
 
247
        nullptr,
 
248
};