[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