1
/*
2
 * Adapted from AlsaPlayer 0.99.76
3
 *
4
 * mikmod_engine.c
5
 * Copyright (C) 1999 Paul N. Fisher <rao@gnu.org>
6
 * Copyright (C) 2002 Andy Lo A Foe <andy@alsaplayer.org>
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
#include "ip.h"
23
#include "xmalloc.h"
24
#include <mikmod.h>
25
#include "debug.h"
26
#include "comment.h"
27
28
struct mik_private {
29
	MODULE *file;
30
};
31
32
static int mikmod_init(void)
33
{
34
	static int inited = 0;
35
36
	if (inited)
37
		return 1;
38
39
	MikMod_RegisterAllDrivers();
40
	MikMod_RegisterAllLoaders();
41
42
	md_reverb = 0;
43
	/* we should let the user decide which one is better... */
44
	md_mode = DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX | DMODE_STEREO |
45
		DMODE_16BITS | DMODE_INTERP;
46
47
	if (MikMod_Init(NULL)) {
48
		d_print("Could not initialize mikmod, reason: %s\n",
49
				MikMod_strerror(MikMod_errno));
50
		return 0;
51
	}
52
53
	inited = 1;
54
	return 1;
55
}
56
57
static int mik_open(struct input_plugin_data *ip_data)
58
{
59
	MODULE *mf = NULL;
60
	struct mik_private *priv;
61
	int mi = mikmod_init();
62
63
	if (!mi)
64
		return -IP_ERROR_INTERNAL;
65
66
	mf = Player_Load(ip_data->filename, 255, 0);
67
68
	if (!mf)
69
		return -IP_ERROR_ERRNO;
70
71
	priv = xnew(struct mik_private, 1);
72
	priv->file = mf;
73
74
	ip_data->private = priv;
75
	ip_data->sf = sf_bits(16) | sf_rate(44100) | sf_channels(2) | sf_signed(1);
76
#ifdef WORDS_BIGENDIAN
77
	ip_data->sf |= sf_bigendian(1);
78
#endif
79
	channel_map_init_stereo(ip_data->channel_map);
80
	return 0;
81
}
82
83
static int mik_close(struct input_plugin_data *ip_data)
84
{
85
	struct mik_private *priv = ip_data->private;
86
87
	Player_Stop();
88
	Player_Free(priv->file);
89
	free(ip_data->private);
90
	ip_data->private = NULL;
91
	return 0;
92
}
93
94
static int mik_read(struct input_plugin_data *ip_data, char *buffer, int count)
95
{
96
	int length;
97
	struct mik_private *priv = ip_data->private;
98
99
	if (!Player_Active())
100
		Player_Start(priv->file);
101
102
	if (!Player_Active())
103
		return 0;
104
105
	length = VC_WriteBytes(buffer, count);
106
107
	return length;
108
}
109
110
static int mik_seek(struct input_plugin_data *ip_data, double offset)
111
{
112
	/* cannot seek in modules properly */
113
	return -IP_ERROR_FUNCTION_NOT_SUPPORTED;
114
}
115
116
static int mik_read_comments(struct input_plugin_data *ip_data, struct keyval **comments)
117
{
118
	struct mik_private *priv = ip_data->private;
119
	GROWING_KEYVALS(c);
120
	const char *val;
121
122
	val = priv->file->songname;
123
	if (val && val[0])
124
		comments_add_const(&c, "title", val);
125
126
	val = priv->file->comment;
127
	if (val && val[0])
128
		comments_add_const(&c, "comment", val);
129
130
	keyvals_terminate(&c);
131
	*comments = c.keyvals;
132
	return 0;
133
}
134
135
static int mik_duration(struct input_plugin_data *ip_data)
136
{
137
	return -IP_ERROR_FUNCTION_NOT_SUPPORTED;
138
}
139
140
static long mik_bitrate(struct input_plugin_data *ip_data)
141
{
142
	return -IP_ERROR_FUNCTION_NOT_SUPPORTED;
143
}
144
145
static char *mik_codec(struct input_plugin_data *ip_data)
146
{
147
	struct mik_private *priv = ip_data->private;
148
	const char *codec = priv->file->modtype;
149
	return (codec && codec[0]) ? xstrdup(codec) : NULL;
150
}
151
152
static char *mik_codec_profile(struct input_plugin_data *ip_data)
153
{
154
	return NULL;
155
}
156
157
const struct input_plugin_ops ip_ops = {
158
	.open = mik_open,
159
	.close = mik_close,
160
	.read = mik_read,
161
	.seek = mik_seek,
162
	.read_comments = mik_read_comments,
163
	.duration = mik_duration,
164
	.bitrate = mik_bitrate,
165
	.bitrate_current = mik_bitrate,
166
	.codec = mik_codec,
167
	.codec_profile = mik_codec_profile
168
};
169
170
const int ip_priority = 40;
171
const char * const ip_extensions[] = {
172
	"mod", "s3m", "xm", "it", "669", "amf", "dsm",
173
	"far", "med", "mtm", "stm", "ult",
174
	NULL
175
};
176
const char * const ip_mime_types[] = { NULL };
177
const char * const ip_options[] = { NULL };