[Alsaplayer-devel] [announce] Monkey's Audio plugin
Peter Lemenkov
petro at mail.ru
Sun Jan 30 21:49:18 GMT 2005
I wrote preliminary version of plugin for playing Monkey's Audio.
I still have some things to do (tags, rpm specs, autotools), but
ritght now plugin works :). There are still some bugs and flaws, no
doubts.
Link for the latest version of plugin:
http://paula.comtv.ru/mac_engine.cpp
and makefile:
http://paula.comtv.ru/Makefile
Needs mac-3.99-u4
--
Regards, Peter Lemenkov.
-------------- next part --------------
VER_MAJOR = 0
VER_MINOR = 0
VER_SUBMINOR = 0
VER_BUILD = 2
PREFIX = /usr/local
# choose suitable compiler
COMPILATOR = g++
DEBUG = -Wall -O2
CFLAGS = -march=athlon
CPPFLAGS = -DBUILD_CROSS_PLATFORM -I$(PREFIX)/include/alsaplayer
LINKER_FLAGS = -lalsaplayer -lmac
LINKER_OBJECTS = mac_engine.o
# bumps the empty 'make' command
all: $(LINKER_OBJECTS)
$(CC) -shared $(LINKER_OBJECTS) $(LINKER_FLAGS) -o mac_engine.so
.cpp.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
install:
cp mac_engine.so $(PREFIX)/lib/alsaplayer/input/
clean:
rm -f ./*.o \
./*~ \
./*.so
-------------- next part --------------
/*
* mac_engine.cpp (C) 2005 by Peter Lemenkov <lemenkov at newmail.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <string.h> /* memset */
#include <alsaplayer/alsaplayer_error.h>
#include <alsaplayer/input_plugin.h>
#include <alsaplayer/reader.h>
#include <mac/All.h>
#include <mac/APETag.h>
#include <mac/MACLib.h>
#include <mac/CharacterHelper.h>
IAPEDecompress* ape_file = NULL;
#define BLOCK_SIZE 4096 /* We can use any block size we like */
struct ape_local_data
{
char path[FILENAME_MAX+1];
int total_ms;
int total_blocks;
};
static int ape_init(void)
{
return 1;
}
static void ape_shutdown(void)
{
return;
}
static float ape_can_handle(const char *path)
{
int ret = 0;
wchar_t* pUTF16 = GetUTF16FromANSI (path);
IAPEDecompress* temp = CreateIAPEDecompress(pUTF16, &ret);
delete temp;
free (pUTF16);
if(ret == ERROR_SUCCESS)
return 1.0;
return 0.0;
}
static int ape_open(input_object *obj, const char *path)
{
int ret = 0;
struct ape_local_data *data;
void* datasource = NULL;
if (!obj)
return 0;
obj->local_data = malloc(sizeof(struct ape_local_data));
if (!obj->local_data) {
return 0;
}
data = (struct ape_local_data *)obj->local_data;
memcpy(data->path, path, sizeof(data->path)-1);
if ((datasource = reader_open(path, NULL, NULL)) == NULL) {
return 0;
}
obj->flags = 0;
if (reader_seekable ((reader_type*)datasource)) {
obj->flags |= P_SEEK;
obj->flags |= P_PERFECTSEEK;
obj->flags |= P_FILEBASED;
} else {
obj->flags |= P_STREAMBASED;
}
wchar_t* pUTF16 = GetUTF16FromANSI (path);
ape_file = CreateIAPEDecompress(pUTF16, &ret);
free (pUTF16);
obj->nr_channels = ape_file->GetInfo(APE_INFO_CHANNELS);
obj->nr_tracks = 1;
data->total_ms = ape_file->GetInfo(APE_DECOMPRESS_LENGTH_MS);
data->total_blocks = ape_file->GetInfo(APE_DECOMPRESS_TOTAL_BLOCKS);
/* FIXME ??
* Although, it's clearly written in alsaplayer-docs
* that we should init obj->nr_frames here,
* no one of currently bundled input plugins do so.
* Any ideas?
*
*/
obj->frame_size = BLOCK_SIZE;
return 1;
}
static void ape_close(input_object *obj)
{
if (!obj)
return;
if (obj->local_data) {
free(obj->local_data);
obj->local_data = NULL;
}
delete ape_file;
ape_file = NULL;
}
static long ape_frame_to_sec (input_object *obj, int frame)
{
int ret = 0;
long result = 0;
struct ape_local_data *data;
if (!obj)
return result;
data = (struct ape_local_data *) obj->local_data;
wchar_t* pUTF16 = GetUTF16FromANSI (data->path);
IAPEDecompress* temp = CreateIAPEDecompress(pUTF16, &ret);
free (pUTF16);
if(ret == ERROR_SUCCESS){
result = (frame * BLOCK_SIZE) / \
(temp->GetInfo(APE_INFO_SAMPLE_RATE) * \
temp->GetInfo(APE_INFO_CHANNELS) * \
temp->GetInfo(APE_INFO_BYTES_PER_SAMPLE) / 100);
delete temp;
}
return result;
}
static int ape_sample_rate(input_object *obj)
{
int ret = 0;
struct ape_local_data *data;
data = (struct ape_local_data *) obj->local_data;
wchar_t* pUTF16 = GetUTF16FromANSI (data->path);
IAPEDecompress* temp = CreateIAPEDecompress(pUTF16, &ret);
free (pUTF16);
if(ret == ERROR_SUCCESS){
ret = temp->GetInfo(APE_INFO_SAMPLE_RATE);
delete temp;
}
return ret;
}
static int ape_channels(input_object *obj)
{
int ret = 0;
struct ape_local_data *data;
data = (struct ape_local_data *) obj->local_data;
wchar_t* pUTF16 = GetUTF16FromANSI (data->path);
IAPEDecompress* temp = CreateIAPEDecompress(pUTF16, &ret);
free (pUTF16);
if(ret == ERROR_SUCCESS){
ret = temp->GetInfo(APE_INFO_CHANNELS);
delete temp;
}
return ret;
}
static int ape_stream_info (input_object *obj, stream_info *info)
{
int ret = 0;
double sampleRate;
char *fileType;
struct ape_local_data *data;
if (!obj || !info)
return 0;
data = (struct ape_local_data *) obj->local_data;
wchar_t* pUTF16 = GetUTF16FromANSI (data->path);
IAPEDecompress* temp = CreateIAPEDecompress(pUTF16, &ret);
free (pUTF16);
/* TODO!
* parsing of the APE-tag
*
*/
/*
printf ("get tag!\n");
CAPETag* tag = (CAPETag*)temp->GetInfo (APE_INFO_TAG);
printf ("get id3 tag\n");
BOOL tag_id3 = tag->GetHasID3Tag ();
printf ("get ape tag\n");
BOOL tag_ape = tag->GetHasAPETag ();
printf("has id3 %d, has ape_tag %d\n", tag_id3, tag_ape);
if (tag_id3 || tag_ape){
// parse tag
BOOL first = TRUE;
CAPETagField* tag_field;
int index = 0;
while ((tag_field = tag->GetTagField (index)) != NULL){
first = FALSE;
index++;
const wchar_t* field_name;
char* name;
const char* field_value;
char* value;
field_name = tag_field->GetFieldName ();
name = GetANSIFromUTF16 (field_name);
field_value = tag_field->GetFieldValue ();
printf ("name: %s, value: %s", field_name, field_value);
}
}
*/
sprintf(info->stream_type, "%d channels, %dHz %s, version %.2f",
temp->GetInfo(APE_INFO_CHANNELS),
temp->GetInfo(APE_INFO_SAMPLE_RATE),
"stereo", /* TODO */
float (temp->GetInfo(APE_INFO_FILE_VERSION)) / 1000);
strcpy(info->status, "#status#");
strcpy(info->artist, "#artist#");
strcpy(info->title, data->path);
delete temp;
return 1;
}
static int ape_nr_frames(input_object *obj)
{
int ret = 0;
struct ape_local_data *data;
int frames = 0;
int64_t l = 0;
if (!obj || !obj->local_data)
return 0;
data = (struct ape_local_data *)obj->local_data;
wchar_t* pUTF16 = GetUTF16FromANSI (data->path);
IAPEDecompress* temp = CreateIAPEDecompress(pUTF16, &ret);
free (pUTF16);
l = temp->GetInfo(APE_INFO_WAV_DATA_BYTES);
frames = (l / BLOCK_SIZE);
delete temp;
return frames;
}
static int ape_frame_size(input_object *obj)
{
if (!obj) {
puts("No frame size!!!!");
return 0;
}
return obj->frame_size;
}
static int ape_frame_seek(input_object *obj, int frame)
{
struct ape_local_data *data;
int64_t pos;
if (!obj)
return 0;
data = (struct ape_local_data *)obj->local_data;
if (data) {
if (obj->flags & P_STREAMBASED)
return 0;
if (ape_file == NULL)
return 0;
ape_file->Seek(frame * BLOCK_SIZE / 4);
return frame;
}
return 0;
}
static int ape_play_frame (input_object *obj, char *buf)
{
int nRead = 0;
struct ape_local_data *data;
if (!obj)
return 0;
data = (struct ape_local_data *) obj->local_data;
if (!data)
return 0;
memset (buf, 0, sizeof (char) * BLOCK_SIZE);
ape_file->GetData (buf, 1024, &nRead);
if (nRead != 0)
return 1;
return 0;
}
static input_plugin ape_plugin;
#ifdef __cplusplus
extern "C" {
#endif
input_plugin *input_plugin_info (void)
{
memset(&ape_plugin, 0, sizeof(input_plugin));
ape_plugin.version = INPUT_PLUGIN_VERSION;
ape_plugin.name = "Monkey's Audio plugin ver. 0.0.0.2";
ape_plugin.author = "Peter Lemenkov";
ape_plugin.init = ape_init;
ape_plugin.shutdown = ape_shutdown;
ape_plugin.can_handle = ape_can_handle;
ape_plugin.open = ape_open;
ape_plugin.close = ape_close;
ape_plugin.play_frame = ape_play_frame;
ape_plugin.frame_seek = ape_frame_seek;
ape_plugin.frame_size = ape_frame_size;
ape_plugin.nr_frames = ape_nr_frames;
ape_plugin.frame_to_sec = ape_frame_to_sec;
ape_plugin.sample_rate = ape_sample_rate;
ape_plugin.channels = ape_channels;
ape_plugin.stream_info = ape_stream_info; /* TODO */
return &ape_plugin;
}
#ifdef __cplusplus
}
#endif
More information about the alsaplayer-devel
mailing list