libkarma-0.1.2/0000755000175000000120000000000011543330247012444 5ustar frankywheellibkarma-0.1.2/src/0000755000175000000120000000000011543330237013232 5ustar frankywheellibkarma-0.1.2/src/karma.c0000644000175000000120000002034511543330237014475 0ustar frankywheel/* * libkarma/karma.c * * Copyright (c) Frank Zschockelt 2004-2005 * Copyright (c) Enrique Vidal 2006 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include #include #include #include #include #include "lkarma.h" #include "karma.h" #include "karmaLan.h" #include "karmaUsb.h" #include "properties.h" #include "fdb.h" int using_usb = 0; char *karma_tmpdir = NULL; #ifdef __USE_ISOC99 #define set_usb_ptr(x) .lk_karma_ ##x = lk_karmaUsb_ ##x #define set_lan_ptr(x) .lk_karma_ ##x = lk_karmaLan_ ##x #define set_unimpl(x) .lk_karma_ ##x = unimpl #define set_unimpl_cast(x,y) (y) unimpl #else #define set_usb_ptr(x) lk_karmaUsb_ ##x #define set_lan_ptr(x) lk_karmaLan_ ##x #define set_unimpl(x) unimpl #define set_unimpl_cast(x,y) (y) unimpl #endif static int unimpl() { lk_errors_set(E_UNIMPLEM); return 0; } static struct lk_ops usb_ops = { set_usb_ptr(connect), set_usb_ptr(hangup), set_unimpl(send_request), set_unimpl(get_protocol_version), set_unimpl(get_authentication_salt), set_usb_ptr(authenticate), set_unimpl(get_device_details), set_usb_ptr(get_storage_details), set_usb_ptr(get_device_settings), set_unimpl(update_device_settings), set_usb_ptr(request_io_lock), set_usb_ptr(release_io_lock), set_unimpl(prepare), set_unimpl(get_all_file_details), set_unimpl(get_file_details), set_usb_ptr(update_file_details), set_usb_ptr(read_file_chunk), set_usb_ptr(write_file_chunk), set_usb_ptr(delete_file), set_unimpl(format_storage), set_unimpl(device_operation), set_usb_ptr(load_database), set_unimpl_cast(update_database, void (*)()), set_usb_ptr(write_smalldb), set_usb_ptr(fidToPath), }; static struct lk_ops lan_ops = { set_lan_ptr(connect), set_lan_ptr(hangup), set_lan_ptr(send_request), set_lan_ptr(get_protocol_version), set_lan_ptr(get_authentication_salt), set_lan_ptr(authenticate), set_lan_ptr(get_device_details), set_lan_ptr(get_storage_details), set_lan_ptr(get_device_settings), set_lan_ptr(update_device_settings), set_lan_ptr(request_io_lock), set_lan_ptr(release_io_lock), set_lan_ptr(prepare), set_lan_ptr(get_all_file_details), set_lan_ptr(get_file_details), set_lan_ptr(update_file_details), set_lan_ptr(read_file_chunk), set_lan_ptr(write_file_chunk), set_lan_ptr(delete_file), set_lan_ptr(format_storage), set_lan_ptr(device_operation), set_lan_ptr(load_database), set_lan_ptr(update_database), set_lan_ptr(write_smalldb), set_lan_ptr(fidToPath), }; struct lk_ops *lk_ops; void lk_karma_use_smalldb(void) { usb_ops.lk_karma_load_database = lk_karmaUsb_load_database_smalldb; } int lk_karma_write_smalldb(void) { return lk_ops->lk_karma_write_smalldb(); } char *lk_karma_fidToPath(int rio, uint32_t file_id) { return lk_ops->lk_karma_fidToPath(rio, file_id); } /* -------------------------------------------------------------------------- */ /* Basic Protocol Functions */ static int lk_karma_find_tmpdir(void) { int fd; char path[32]; memcpy(path, "/dev/shm/lkarmaXXXXXX", 22); fd = mkstemp(path); if (fd != -1) { close(fd); unlink(path); karma_tmpdir = strdup("/dev/shm/"); return 0; } memcpy(path, "/tmp/lkarmaXXXXXX", 19); fd = mkstemp(path); if (fd != -1) { close(fd); unlink(path); karma_tmpdir = strdup("/tmp/"); return 0; } lk_errors_set(E_NOTMPDIR); return 1; } int lk_karma_connect(char *ipHostOrPath) { int rio; using_usb = (ipHostOrPath[0] == '/'); lk_ops = using_usb ? &usb_ops : &lan_ops; rio = lk_ops->lk_karma_connect(ipHostOrPath); lk_fdb_set_device(rio); if (rio >= 0 && using_usb == 0 && karma_tmpdir == NULL) lk_karma_find_tmpdir(); return rio; } int32_t lk_karma_hangup(int rio) { return lk_ops->lk_karma_hangup(rio); } int lk_karma_send_request(int rio, uint32_t identifier, char *payload, int plen) { return lk_ops->lk_karma_send_request(rio, identifier, payload, plen); } int lk_karma_get_protocol_version(int rio, uint32_t * major_version, uint32_t * minor_version) { return lk_ops->lk_karma_get_protocol_version(rio, major_version, minor_version); } int32_t lk_karma_get_authentication_salt(int rio, char **salt) { return lk_ops->lk_karma_get_authentication_salt(rio, salt); } uint32_t lk_karma_authenticate(int rio, char *pass) { return lk_ops->lk_karma_authenticate(rio, pass); } int lk_karma_get_device_details(int rio, char **name, char **version, uint32_t * storagedevices) { return lk_ops->lk_karma_get_device_details(rio, name, version, storagedevices); } int lk_karma_get_storage_details(int rio, uint32_t storage_id, uint32_t * n_files, uint64_t * s_size, uint64_t * f_space, uint32_t * highest_file_id) { return lk_ops->lk_karma_get_storage_details(rio, storage_id, n_files, s_size, f_space, highest_file_id); } int lk_karma_get_device_settings(int rio, char **properties) { if (properties) *properties = NULL; return lk_ops->lk_karma_get_device_settings(rio); } int32_t lk_karma_update_device_settings(int rio, char *properties) { return lk_ops->lk_karma_update_device_settings(rio, properties); } int32_t lk_karma_request_io_lock(int rio, uint32_t type) { return lk_ops->lk_karma_request_io_lock(rio, type); } int32_t lk_karma_release_io_lock(int rio) { return lk_ops->lk_karma_release_io_lock(rio); } /* Not yet supported by the Rio Karma.*/ int32_t lk_karma_prepare(int rio, uint64_t size, uint32_t * file_id, uint32_t storage_id) { return lk_ops->lk_karma_prepare(rio, size, file_id, storage_id); } int32_t lk_karma_get_all_file_details(int rio, char **properties) { return lk_ops->lk_karma_get_all_file_details(rio, properties); } int32_t lk_karma_get_file_details(int rio, uint32_t file_id, char **properties) { return lk_ops->lk_karma_get_file_details(rio, file_id, properties); } int32_t lk_karma_update_file_details(int rio, uint32_t file_id, char *properties) { return lk_ops->lk_karma_update_file_details(rio, file_id, properties); } int32_t lk_karma_read_file_chunk(int rio, uint64_t offset, uint64_t size, uint32_t file_id, char **data, uint64_t * retsize) { return lk_ops->lk_karma_read_file_chunk(rio, offset, size, file_id, data, retsize); } int32_t lk_karma_write_file_chunk(int rio, uint64_t offset, uint64_t size, uint32_t file_id, uint32_t storage_id, const char *data) { return lk_ops->lk_karma_write_file_chunk(rio, offset, size, file_id, storage_id, data); } int32_t lk_karma_delete_file(int rio, uint32_t file_id) { return lk_ops->lk_karma_delete_file(rio, file_id); } /* Now, that command would be scary ;) (It's not supported by the rio karma ;)) */ int32_t lk_karma_format_storage(int rio, uint32_t storage_id) { return lk_ops->lk_karma_format_storage(rio, storage_id); } /* Not yet supported by the Rio Karma */ int32_t lk_karma_device_operation(int rio, uint64_t size, char *data, char **newdata) { return lk_ops->lk_karma_device_operation(rio, size, data, newdata); } /* Advanced Protocol Functions */ void lk_karma_load_database(int rio) { lk_ops->lk_karma_load_database(rio); } void lk_karma_update_database(int rio) { lk_ops->lk_karma_update_database(rio); } int lk_karma_parse_settings(char *buf) { int ret = 0; char *str; str = strstr(buf, "device_generation"); if (str) { str += strlen("device_generation") + 1; device_generation = strtol(str, NULL, 10); } else ret++; str = strstr(buf, "serial"); if (str) { str += strlen("serial") + 1; serial = strtol(str, NULL, 10); } else ret++; return ret; } libkarma-0.1.2/src/karma.h0000644000175000000120000001136611543330237014505 0ustar frankywheel/* * libkarma/karma.h * * Copyright (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _KARMA_H #define _KARMA_H #include extern int using_usb; extern char *karma_tmpdir; char * lk_karma_fidToPath (int rio, uint32_t file_id); /*Help-Functions:*/ int lk_karma_send_request (int rio, uint32_t identifier, char *payload, int plen); /*Basic Protocol Functions*/ int lk_karma_get_protocol_version (int rio, uint32_t *major_version, uint32_t *minor_version); int32_t lk_karma_get_authentication_salt(int rio, char **salt); int lk_karma_get_device_details (int rio, char **name, char **version, uint32_t *storagedevices); int32_t lk_karma_update_device_settings (int rio, char *properties); int32_t lk_karma_prepare (int rio, uint64_t size, uint32_t *file_id, uint32_t storage_id); int32_t lk_karma_format_storage (int rio, uint32_t storage_id); int32_t lk_karma_device_operation (int rio, uint64_t size, char *data, char **newdata); /*Advanced Protocol Functions:*/ void lk_karma_update_database (int rio); int lk_karma_parse_settings (char *buf); /* private stuff */ struct lk_ops { int (*lk_karma_connect) (char *ipHostOrPath); int32_t (*lk_karma_hangup) (int rio); int (*lk_karma_send_request) (int rio, uint32_t identifier, char *payload, int plen); int (*lk_karma_get_protocol_version) (int rio, uint32_t *major_version, uint32_t *minor_version); int32_t (*lk_karma_get_authentication_salt)(int rio, char **salt); uint32_t (*lk_karma_authenticate) (int rio, char *pass); int (*lk_karma_get_device_details) (int rio, char **name, char **version, uint32_t * storagedevices); int (*lk_karma_get_storage_details) (int rio, uint32_t storage_id, uint32_t * n_files, uint64_t * s_size, uint64_t * f_space, uint32_t * highest_file_id); int (*lk_karma_get_device_settings) (int rio); int32_t (*lk_karma_update_device_settings) (int rio, char *properties); int32_t (*lk_karma_request_io_lock) (int rio, uint32_t type); int32_t (*lk_karma_release_io_lock) (int rio); int32_t (*lk_karma_prepare) (int rio, uint64_t size, uint32_t * file_id, uint32_t storage_id); int32_t (*lk_karma_get_all_file_details) (int rio, char **properties); int32_t (*lk_karma_get_file_details) (int rio, uint32_t file_id, char **properties); int32_t (*lk_karma_update_file_details) (int rio, uint32_t file_id, char *properties); int32_t (*lk_karma_read_file_chunk) (int rio, uint64_t offset, uint64_t size, uint32_t file_id, char **data, uint64_t * retsize); int32_t (*lk_karma_write_file_chunk) (int rio, uint64_t offset, uint64_t size, uint32_t file_id, uint32_t storage_id, const char *data); int32_t (*lk_karma_delete_file) (int rio, uint32_t file_id); int32_t (*lk_karma_format_storage) (int rio, uint32_t storage_id); int32_t (*lk_karma_device_operation) (int rio, uint64_t size, char *data, char **newdata); void (*lk_karma_load_database) (int rio); void (*lk_karma_update_database) (int rio); int (*lk_karma_write_smalldb) (void); char * (*lk_karma_fidToPath) (int rio, uint32_t file_id); }; #endif /* _KARMA_H */ libkarma-0.1.2/src/Makefile0000644000175000000120000000473511543330237014703 0ustar frankywheelNAME=libkarma VERSION=0.1.1 TARGET=$(NAME) SRCS= errors.c fdb.c hash.c karma.c karmaLan.c karmaUsb.c md5.c mountSearch.c \ mp3.c playlist.c properties.c rio_rw.c ssdp.c status.c utf8.c \ util.c wav.c INST_HEADERS=lkarma.h utf8.h LIBDIR=../lib CC?=gcc AR?=ar RANLIB?=ranlib LN_S?=ln -s CFLAGS+=-fPIC -D_REENTRANT -Wall -pedantic CFLAGS+=-W -Wchar-subscripts -Wmissing-prototypes CFLAGS+=-Wmissing-declarations -Wno-switch -Wredundant-decls -Wno-unused MAJOR?=$(shell VERSION=${VERSION} echo $${VERSION%%\.*}) PLATFORM=$(shell uname) ifeq ($(PLATFORM),Darwin) LIBS=-ltag_c -lz -liconv LDFLAGS+=-dynamiclib -single_module OUT_BASE=$(TARGET).dynlib OUT_MAJOR=$(TARGET).$(MAJOR).dynlib OUT_VERSION=$(TARGET).$(VERSION).dynlib else OUT_BASE=$(TARGET).so OUT_MAJOR=$(TARGET).so.$(MAJOR) OUT_VERSION=$(TARGET).so.$(VERSION) LDFLAGS+=-shared -Wl,-soname,$(OUT_MAJOR) LIBS=-ltag_c -lz endif default: all install: shared-lib-stamp static-lib-stamp ../install-sh -m 0755 -d $(DESTDIR)$(PREFIX)/lib ../install-sh -m 0755 -d $(DESTDIR)$(PREFIX)/include ../install-sh -m 0755 -d $(DESTDIR)$(PREFIX)/include/libkarma ../install-sh -m 0644 -t $(DESTDIR)$(PREFIX)/lib/ $(LIBDIR)/$(TARGET).a ../install-sh -m 0755 -t $(DESTDIR)$(PREFIX)/lib/ $(LIBDIR)/$(OUT_VERSION) $(RM) $(DESTDIR)$(PREFIX)/lib/$(OUT_MAJOR) $(RM) $(DESTDIR)$(PREFIX)/lib/$(OUT_BASE) $(LN_S) $(OUT_VERSION) $(DESTDIR)$(PREFIX)/lib/$(OUT_MAJOR) $(LN_S) $(OUT_VERSION) $(DESTDIR)$(PREFIX)/lib/$(OUT_BASE) ../install-sh -m 0644 -t $(DESTDIR)$(PREFIX)/include/libkarma/ $(INST_HEADERS) uninstall: $(RM) $(PREFIX)/lib/$(TARGET).a $(PREFIX)/lib/$(OUT_MAJOR) $(PREFIX)/lib/$(OUT_BASE) $(PREFIX)/lib/$(OUT_VERSION) $(RM) -r $(PREFIX)/include/libkarma OBJS = $(SRCS:.c=.o) $(LIBDIR): @[ -d $(LIBDIR) ] || mkdir -p $(LIBDIR) > /dev/null 2>&1 $(LIBDIR)/$(TARGET).a: $(OBJS) $(LIBDIR) $(AR) r $(LIBDIR)/$(TARGET).a $(OBJS) $(RANLIB) $(LIBDIR)/$(TARGET).a $(LIBDIR)/$(OUT_VERSION): $(OBJS) $(LIBDIR) $(CC) $(LDFLAGS) $(OBJS) $(CFLAGS) -o $(LIBDIR)/$(OUT_VERSION) $(LIBS) $(LIBDIR)/$(OUT_MAJOR): $(LIBDIR)/$(OUT_VERSION) $(LIBDIR) $(LN_S) $(OUT_VERSION) $(LIBDIR)/$(OUT_MAJOR) $(LIBDIR)/$(OUT_BASE): $(LIBDIR)/$(OUT_VERSION) $(LIBDIR) $(LN_S) $(OUT_VERSION) $(LIBDIR)/$(OUT_BASE) shared-lib-stamp: $(LIBDIR)/$(OUT_VERSION) $(LIBDIR)/$(OUT_MAJOR) $(LIBDIR)/$(OUT_BASE) touch $@ static-lib-stamp: $(LIBDIR)/$(TARGET).a touch $@ all: static-lib-stamp shared-lib-stamp .PHONY: clean clean: rm -rf $(OBJS) $(LIBDIR)/ static-lib-stamp shared-lib-stamp libkarma-0.1.2/src/playlist.c0000644000175000000120000002063611543330237015246 0ustar frankywheel/* * libkarma/playlist.c * * Copyright (c) Frank Zschockelt 2005 * Copyright (c) Keith Bennett 2006 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include #include #include #include "lkarma.h" #include "properties.h" #include "playlist.h" #include "util.h" uint32_t get_playlist_fid(char * name); char * lk_playlist_escape(char * data, unsigned int length) { char * str; unsigned int i, count; str=malloc(length*5+1); for(i=0,count=0; i < length; i++, count++){ if(data[i]=='\\'){ str[count]='\\'; str[++count]='\\'; } else if(data[i]=='\n'){ str[count]='\\'; str[++count]='n'; } else if(data[i]>=32 || data[i]<0) str[count]=data[i]; else { str[count]='\\'; str[++count]='x'; if((data[i]/16)<10) str[++count]=(data[i]/16)+'0'; else str[++count]=(data[i]/16)+55; if((data[i]%16)<10) str[++count]=(data[i]%16)+'0'; else str[++count]=(data[i]%16)+55; } } str[count++]=0; str=(char *)realloc(str, count); return str; } unsigned int lk_playlist_unescape_inplace(char *str) { unsigned int length; char *r,*w, *end; r=w=str; end=&((str)[strlen(str)]); while(rname=strdup(name); pl->playlist=malloc(4); head=lk_htorl(767); memcpy(pl->playlist, &head, 4); pl->length=4; pl->fid=0; } return pl; } playlist * lk_playlist_read(char * name) { playlist *pl; pl=malloc(sizeof(playlist)); if(pl){ pl->fid=get_playlist_fid(name); if(pl->fid!=0){ if(lk_properties_get_property(pl->fid, "playlist")){ pl->length=lk_playlist_unescape( lk_properties_get_property(pl->fid, "playlist"), &pl->playlist); pl->name=strdup(name); }else{ free(pl); pl=lk_playlist_create(name); pl->fid=get_playlist_fid(name); } return pl; }else{ free(pl); return NULL; } }else return NULL; } playlist * lk_playlist_fid_read(uint32_t fid) { playlist *pl; if (fid==0) return NULL; pl=malloc(sizeof(playlist)); if(pl){ pl->fid=fid; if(lk_properties_get_property(pl->fid, "playlist")){ pl->length=lk_playlist_unescape( lk_properties_get_property(pl->fid, "playlist"), &pl->playlist); }else{ free(pl); pl=lk_playlist_create(lk_properties_get_property(fid, "title")); pl->fid=fid; } pl->name=strdup(lk_properties_get_property(fid, "title")); return pl; }else return NULL; } int lk_playlist_free(playlist ** pl) { if((*pl)->name) free((*pl)->name); if((*pl)->playlist) free((*pl)->playlist); if(*pl) free(*pl); *pl=NULL; return 0; } int lk_playlist_set_name(playlist * pl, char * name) { if(pl){ if(pl->name) free(pl->name); pl->name=strdup(name); return 0; }else return -1; } char * lk_playlist_get_name(playlist * pl) { return pl->name; } int lk_playlist_clear(playlist * pl) { if(pl){ pl->length=4; pl->playlist=(char *)realloc(pl->playlist, pl->length); return 0; }else return -1; } int lk_playlist_delete(playlist * pl, int karma) { uint32_t fid; fid=pl->fid; pl->fid=0; return lk_karma_delete_file(karma, fid); } int lk_playlist_count(playlist * pl) { if((pl->length-4)/8) return (pl->length-4)/8; else return 0; } int lk_playlist_get_item(playlist * pl, unsigned int n, uint32_t *fid, uint32_t * fid_generation) { *fid=*fid_generation=0; if(4+n*8 < pl->length){ memcpy(fid, &pl->playlist[4+n*8], 4); memcpy(fid_generation, &pl->playlist[8+n*8], 4); *fid=lk_rtohl(*fid); *fid_generation=lk_rtohl(*fid_generation); return 0; }else return -1; } int lk_playlist_set_item(playlist * pl, unsigned int n, uint32_t fid, uint32_t fid_generation) { if(4+n*8 < pl->length){ fid=lk_htorl(fid); memcpy(&pl->playlist[4+n*8], &fid, 4); fid_generation=lk_htorl(fid_generation); memcpy(&pl->playlist[8+n*8], &fid, 4); return 0; }else return -1; } int lk_playlist_append(playlist * pl, uint32_t fid, uint32_t fid_generation) { if(pl){ pl->length+=8; pl->playlist=(char *)realloc(pl->playlist, pl->length); fid=lk_htorl(fid); memcpy(&pl->playlist[pl->length-8], &fid, 4); fid_generation=lk_htorl(fid_generation); memcpy(&pl->playlist[pl->length-4], &fid_generation, 4); return 0; }else return -1; } int lk_playlist_remove(playlist * pl, unsigned int n) { n=n*8; if(n+4length){ memmove(&pl->playlist[4+n], &pl->playlist[12+n], pl->length-n-4); pl->length-=8; pl->playlist=(char *)realloc(pl->playlist, pl->length); return 0; }else return -1; } int lk_playlist_insert(playlist * pl, unsigned int at, uint32_t fid, uint32_t fid_generation) { at=at*8; if(at+4length){ pl->length+=8; pl->playlist=(char *)realloc(pl->playlist, pl->length); memmove(&pl->playlist[12+at], &pl->playlist[4+at], pl->length-at-12); return lk_playlist_set_item(pl, at/8, fid, fid_generation); }else return lk_playlist_append(pl, fid, fid_generation); } int lk_playlist_write(playlist * pl, int karma) { playlist * rootpl=NULL; HASH * property; char * prop, * escaped; uint32_t * tmp; int i; if(!pl->fid) pl->fid=lk_properties_new_property(); property=lk_properties_idsearch(pl->fid); lk_properties_set_property_hash(property, "type", "playlist"); lk_properties_set_property_hash(property, "title", pl->name); lk_properties_set_property_hash(property, "length", simple_itoa(pl->length)); escaped=lk_playlist_escape(pl->playlist, pl->length); lk_properties_set_property_hash(property, "playlist", escaped); free(escaped); lk_karma_write_file_chunk(karma, 0, 0, pl->fid, 0, NULL); prop=lk_properties_export(pl->fid); lk_karma_update_file_details(karma, pl->fid, prop); free(prop); rootpl=lk_playlist_read(lk_properties_get_property(256, "title")); lk_playlist_clear(rootpl); tmp=lk_properties_andOrSearch(EXACT|ORS, NULL, "type", "playlist"); for(i=0;tmp[i]!=0;i++){ if(tmp[i]!=256) lk_playlist_append(rootpl, tmp[i], 0); } free(tmp); escaped=lk_playlist_escape(rootpl->playlist, rootpl->length); property=lk_properties_idsearch(rootpl->fid); lk_properties_set_property_hash(property, "playlist", escaped); free(escaped); lk_properties_set_property_hash(property, "length", simple_itoa(rootpl->length)); prop=lk_properties_export(rootpl->fid); lk_karma_update_file_details(karma, rootpl->fid, prop); free(prop); lk_playlist_free(&rootpl); return 0; } libkarma-0.1.2/src/playlist.h0000644000175000000120000000153211543330237015245 0ustar frankywheel/* * libkarma/playlist.h * * Copyright (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _PLAYLIST_H #define _PLAYLIST_H #include #include "lkarma.h" char * lk_playlist_escape (char * data, unsigned int length); unsigned int lk_playlist_unescape_inplace(char * str); unsigned int lk_playlist_unescape (char * str, char ** data); int lk_playlist_delete (playlist * pl, int karma); int lk_playlist_remove (playlist * pl, unsigned int n); int lk_playlist_insert (playlist * pl, unsigned int n, uint32_t fid, uint32_t fid_generation); #endif /* _PLAYLIST_H */ libkarma-0.1.2/src/lkarma.h0000644000175000000120000002240611543330237014656 0ustar frankywheel/* * libkarma/lkarma.h * * Copyright (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _LKARMA_H #define _LKARMA_H #include #ifdef __cplusplus extern "C" { #endif #define FDB_FILENAME "__libkarma_fdb__.gz" /* * karma */ #define IO_LOCK_R 0 #define IO_LOCK_W 1 /*Help-Functions:*/ int lk_karma_connect (char *ipHostOrPath); /*Basic Protocol Functions*/ uint32_t lk_karma_authenticate (int rio, char *pass); int lk_karma_get_storage_details (int rio, uint32_t storage_id, uint32_t *n_files, uint64_t *s_size, uint64_t *f_space, uint32_t *highest_file_id); int lk_karma_get_device_settings (int rio, char **properties); int32_t lk_karma_request_io_lock (int rio, uint32_t type); int32_t lk_karma_release_io_lock (int rio); int32_t lk_karma_write_file_chunk (int rio, uint64_t offset, uint64_t size, uint32_t file_id, uint32_t storage_id, const char *data); int32_t lk_karma_get_all_file_details (int rio, char **properties); int32_t lk_karma_get_file_details (int rio, uint32_t file_id, char **properties); int32_t lk_karma_update_file_details (int rio, uint32_t file_id, char *properties); int32_t lk_karma_read_file_chunk (int rio, uint64_t offset, uint64_t size, uint32_t file_id, char **data, uint64_t *retsize); int32_t lk_karma_delete_file (int rio, uint32_t file_id); int32_t lk_karma_hangup (int rio); void lk_karma_use_smalldb (void); int lk_karma_write_smalldb (void); /*Advanced Protocol Functions:*/ void lk_karma_load_database (int rio); char **lk_fdb_getlist (char *fdb); /* * properties */ void lk_properties_init (void); void lk_properties_destroy (void); uint32_t lk_properties_import (char * properties); char * lk_properties_export (uint32_t id); uint32_t lk_properties_new_property (void); int lk_properties_del_property (uint32_t id); char * lk_properties_get_property (uint32_t id, char * key); int lk_properties_set_property (uint32_t id, char * property, char * data); int lk_properties_load (void); int lk_properties_save (void); int lk_properties_cache_obsolete (void); /* Exact/approximate And/Or search support: */ uint32_t *lk_properties_andOrSearch (int mode, uint32_t *search_in, char *key, char *data); #define ORS 0 /* mode == 00 = APPROX|ORS: Approx,Or */ #define ANDS 1 /* mode == 01 = APPROX|ANDS: Approx,And */ #define APPROX 0 /* mode == 10 = EXACT|ORS: Exact,Or */ #define EXACT 2 /* mode == 11 = EXACT|ANDS: Exact,And */ /* * errors */ typedef void *error_handler(void); int lk_errors_set(const int err); /* Sets error number */ void lk_errors_autoprint(const int autoPrint); /*Sets errors aoutoprint on/off*/ void lk_errors_setHandler(error_handler handler); /*Sets an error handl. func.*/ int lk_errors_number(void); /* checks error number and resets it */ int lk_errors_number_noreset(void); /* checks error number without resetting */ int lk_errors_p(const char *s1, const char *s2); /*prints s1+errStr+s2&resets*/ char * lk_errors_numberstr(int lkerrnum); /* returns err string for lkerrnum */ /* - no reset */ #define E_NOERR 0 /* Success */ #define E_HOST 1 /* error: gethostbyname() failed */ /* Sys */ #define E_SOCKET 2 /* error: socket() failed */ /* Sys */ #define E_SENDTO 3 /* error: sendto() failed */ /* Sys */ #define E_CONNECT 4 /* error: connect() failed */ /* Sys */ #define E_RECVFROM 5 /* error: recvfrom() failed */ /* Sys */ #define E_SELECT 6 /* error: select() failed */ /* Sys */ #define E_OPEN 7 /* error: open() failed */ /* Sys */ #define E_ICONVO 8 /* warning: iconv_open() failed */ /* Sys */ #define E_ICONV 9 /* warning: iconv() failed */ /* Sys */ #define E_ICONVC 10 /* error: iconv_close() failed */ /* Sys */ #define E_BADHEADER 11 /* error: broken Rio header */ #define E_BADIDENT 12 /* error: wrong protocol identifier */ #define E_FAILEDREQ 13 /* warning: failed request */ #define E_BADPROP 14 /* error: property parsing failed */ #define E_BADID 15 /* error: given id not found */ #define E_NOSSDP 16 /* warning: no ssdp answer */ #define E_SSDPPARSE 17 /* warning: ssdp parsing failed */ #define E_MKDIR 18 /* error: mkdir() failed */ /* Sys */ #define E_UTIME 19 /* error: utime() failed */ /* Sys */ #define E_NODIR 20 /* error: unexisting directory */ /* USB */ #define E_NOPROP 21 /* warning: missing properties file */ /* USB */ #define E_READ 22 /* error: read error */ /* USB */ #define E_WRITE 23 /* error: write error */ /* USB */ #define E_DELETE 24 /* warning: delete error */ /* USB */ #define E_NODEVSET 25 /* warning: no device-settings file */ /* USB */ #define E_UNIMPLEM 26 /* warning: unimplemented call */ /* USB */ #define E_MFINDERR 27 /* warning: mount search error */ /* MFIND */ #define E_NOMOUNT 28 /* warning: no mountpoints found */ /* MFIND */ #define E_MANYMOUNT 29 /* warning: more than 1 mountpoints */ /* MFIND */ #define E_NOSMALLDB 30 /* warning: Missing RK index file */ /* UTIL */ #define E_DUPE 31 /* warning: file already present */ /* RIO_RW */ #define E_PATHCREAT 32 /* warning: dir access/create failed */ /* RIO_RW */ #define E_NOHASH 33 /* error: no hash found */ /* RIO_RW */ #define E_WRCHUNK 34 /* error: write_file_chunk() failed */ /* RIO_RW */ #define E_SMALLMP3 35 /* error: tune file is too small */ /* RIO_RW */ #define E_UNSUPTAG 36 /* warning: unsupported tag type */ /* RIO_RW */ #define E_NOTAGFILE 37 /* warning: can't access tags file */ /* RIO_RW */ #define E_BADFDB 38 /* warning: unrecognised fdb file */ /* FDB */ #define E_UNSUPFDB 39 /* warning: unsupported fdb file */ /* FDB */ #define E_NOPATHPR 40 /* warning: missing path properties */ /* FDB */ #define E_NOTMPDIR 41 /* warning: no temporary directory found */ #define E_TMPCREAT 42 /* error: can't create temporary tag file */ #define MAXLKERRORS 42 /* * playlist */ typedef struct{ char * name; char * playlist; unsigned int length; uint32_t fid; } playlist; playlist * lk_playlist_fid_read (uint32_t fid); playlist * lk_playlist_read (char * name); int lk_playlist_free (playlist ** pl); int lk_playlist_set_name (playlist * pl, char * name); char * lk_playlist_get_name (playlist * pl); int lk_playlist_count (playlist * pl); int lk_playlist_get_item (playlist * pl, unsigned int n, uint32_t *fid, uint32_t * fid_generation); int lk_playlist_set_item (playlist * pl, unsigned int n, uint32_t fid, uint32_t fid_generation); playlist * lk_playlist_create (char * name); int lk_playlist_clear (playlist * pl); int lk_playlist_append (playlist * pl, uint32_t fid, uint32_t fid_generation); int lk_playlist_write (playlist * pl, int karma); /* * rio_rw */ /* #define MODE_PROPERTY "play_count_limit" */ #define MODE_PROPERTY "bpm" /* for taxi files chmod in lkarmafs */ int lk_rio_read_playlist(int rio, uint32_t fid, const char * filename); int lk_rio_read(int rio, uint32_t fid, const char * filename); int lk_synchronize_necessary(int rio); uint32_t lk_rio_write(int rio, const char * filename); void lk_karma_write_dupes(int set); int lk_rio_update_props_from_tags(int rio, uint32_t fid); /* * auto discover */ int lk_ssdp_discover(char **host, uint16_t *port); int lk_mountSearch_discover(char **device, char **mountPoint); /* * util */ char *simple_itoa(unsigned int i); /* * utf8 */ void utf8_destroy (void); int utf8_set_codeset (char * codeset); char * utf8_get_codeset (void); char * utf8_from_codeset (char * data); char * utf8_to_codeset (char * data); #ifdef __cplusplus } #endif /* C++ */ #endif /* _LKARMA_H */ libkarma-0.1.2/src/fdb.c0000644000175000000120000001371611543330237014141 0ustar frankywheel/* * libkarma/fdb.h * * Copyright (c) Frank Zschockelt 2005 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include #include #include #include "lkarma.h" #include "properties.h" #include "util.h" #include "rio_rw.h" #include "fdb.h" static int rio = 0; static int fdb_read_header(gzFile fdb_file) { char *p, buf[64]; int ver; gzread(fdb_file, buf, 64); buf[63] = '\0'; if (memcmp(buf, "LkFdB ", 6) != 0) { lk_errors_set(E_BADFDB); return -1; } for (p=buf; *p != '\0'; p++) if (*p == ' ') break; *p = '\0'; ver = atoi(buf); if (ver > 1) { lk_errors_set(E_BADFDB); return -1; } p++; for (; *p != '\0'; p++) if (*p == '\n') break; p++; gzseek(fdb_file, p-buf, SEEK_SET); return 0; } /* * fid:fid_generation path */ int lk_fdb_load(int download) { gzFile fdb_file; char * fname; char * buf=NULL,*p,*n_tok; int read,upd,size=0; uint32_t fid; uint32_t *db; char * fid_gen; HASH * tmp; /* * Datenbank vom Karma laden */ fname=lk_path_string(FDB_FILENAME); if (fname == NULL) return -1; if (download) { db=lk_properties_andOrSearch(EXACT|ORS, NULL, "title", FDB_FILENAME); if (db) { db=lk_properties_andOrSearch(EXACT|ANDS, db, "type", "taxi"); if (db) { unlink(fname); lk_rio_read(rio, *db, fname); free(db); } } } fdb_file=gzopen(fname, "r"); free(fname); if (fdb_file == NULL) return -1; if (fdb_read_header(fdb_file) != 0) return -1; do{ buf=realloc(buf, size+8192); read=gzread(fdb_file, &buf[size], 8192); size+=read; }while(read > 0); gzclose(fdb_file); if((read == -1) || (size == 0)){ free(buf); return read; } buf[size]='\0'; p=strtok_r(buf, ":", &n_tok); upd = properties_updated; while(p!=NULL){ fid=strtoul(p, (char **)NULL, 10); fid_gen=strtok_r(NULL, " ", &n_tok); p=strtok_r(NULL, "\n", &n_tok); if((tmp=lk_properties_idsearch(fid))) if(strcmp(fid_gen, lk_properties_get_property_hash(tmp, "fid_generation")) == 0) lk_properties_set_property_hash(tmp, "path", p); p=strtok_r(NULL, ":", &n_tok); } free(buf); properties_updated = upd; fdb_updated = 0; return 0; } char **lk_fdb_getlist(char *fdb) { gzFile fdb_file; char **list, **entry; char * buf=NULL,*p,*n_tok; int read,size=0; uint32_t fid; char * fid_gen; HASH * tmp; int nlist, len; fdb_file=gzopen(fdb, "r"); if (fdb_file == NULL) return NULL; if (fdb_read_header(fdb_file) != 0) return NULL; do{ buf=realloc(buf, size+8192); read=gzread(fdb_file, &buf[size], 8192); size+=read; }while(read > 0); gzclose(fdb_file); if((read == -1) || (size == 0)){ free(buf); return NULL; } buf[size]='\0'; nlist = 0; for(p=buf; *p != '\0'; p++) if (*p == '\n') nlist++; if (nlist == 0) return NULL; nlist++; entry = list = calloc(nlist*sizeof(char *), 1); p=strtok_r(buf, ":", &n_tok); while(p!=NULL){ fid=strtoul(p, (char **)NULL, 10); fid_gen=strtok_r(NULL, " ", &n_tok); p=strtok_r(NULL, "\n", &n_tok); len=strlen(p)+1; *entry = malloc(len); memcpy(*entry, p, len); entry++; p=strtok_r(NULL, ":", &n_tok); } free(buf); return list; } int lk_fdb_save(void) { gzFile fdb_file; char * fname; char * id, * path, * tm; uint32_t * fdb; HASH * tmp; int i=0, first=1, ret=0; fname=lk_path_string(FDB_FILENAME); fdb_file=gzopen(fname, "w"); if (fdb_file == NULL) return -1; gzwrite(fdb_file, "LkFdB 1 ", 8); if (serial) { id = simple_itoa(serial); gzwrite(fdb_file, id, strlen(id)); } else gzwrite(fdb_file, "0", 1); gzwrite(fdb_file, "\n", 1); fdb=lk_properties_andOrSearch(EXACT|ORS, NULL, "path", ""); if(fdb){ for(i=0; fdb[i]; i++){ tmp=lk_properties_idsearch(fdb[i]); if (!tmp) continue; path=lk_properties_get_property_hash(tmp, "path"); tm=lk_properties_get_property_hash(tmp, "fid_generation"); if (!path || !tm) { if (first) { tm=lk_properties_get_property_hash(tmp, "type"); /* playlist files always have a missing path */ if (tm && memcmp(tm, "playlist", 8) == 0) continue; else if (tm && strncmp(tm, "taxi", 5) == 0) { /* fdb file always has a missing path */ tm=lk_properties_get_property_hash(tmp, "title"); if (tm && strncmp(tm, FDB_FILENAME, strlen(FDB_FILENAME)+1) == 0) continue; } lk_errors_set(E_NOPATHPR); first = 0; } continue; } id=simple_itoa(fdb[i]); gzwrite(fdb_file, id, strlen(id)); gzwrite(fdb_file, ":", 1); gzwrite(fdb_file, tm, strlen(tm)); gzwrite(fdb_file, " ", 1); gzwrite(fdb_file, path, strlen(path)); gzwrite(fdb_file, "\n", 1); } free(fdb); gzclose(fdb_file); } ret = lk_rio_write_fdb(rio, fname); /* * Datenbank auf Karma als Taxifile kopieren... */ free(fname); fdb_updated = 0; return ret; } void lk_fdb_set_device(int karma) { rio = karma; } libkarma-0.1.2/src/fdb.h0000644000175000000120000000057711543330237014147 0ustar frankywheel/* * libkarma/fdb.h * * Copyright (c) Frank Zschockelt 2005 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _FDB_H #define _FDB_H extern int fdb_updated; int lk_fdb_load (int download); int lk_fdb_save (void); void lk_fdb_set_device(int karma); #endif /* _FDB_H */ libkarma-0.1.2/src/md5.c0000644000175000000120000001476511543330237014100 0ustar frankywheel/* * libkarma/md5.c - RFC 1321 compliant MD5 implementation * * Copyright (c) Christophe Devine 2001-2003 * (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include "md5.h" #define GET_UINT32(n,b,i) \ { \ (n) = ( (uint32_t) (b)[(i) ] ) \ | ( (uint32_t) (b)[(i) + 1] << 8 ) \ | ( (uint32_t) (b)[(i) + 2] << 16 ) \ | ( (uint32_t) (b)[(i) + 3] << 24 ); \ } #define PUT_UINT32(n,b,i) \ { \ (b)[(i) ] = (uint8_t) ( (n) ); \ (b)[(i) + 1] = (uint8_t) ( (n) >> 8 ); \ (b)[(i) + 2] = (uint8_t) ( (n) >> 16 ); \ (b)[(i) + 3] = (uint8_t) ( (n) >> 24 ); \ } void md5_starts( md5_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; } static void md5_process( md5_context *ctx, uint8_t data[64] ) { uint32_t X[16], A, B, C, D; GET_UINT32( X[0], data, 0 ); GET_UINT32( X[1], data, 4 ); GET_UINT32( X[2], data, 8 ); GET_UINT32( X[3], data, 12 ); GET_UINT32( X[4], data, 16 ); GET_UINT32( X[5], data, 20 ); GET_UINT32( X[6], data, 24 ); GET_UINT32( X[7], data, 28 ); GET_UINT32( X[8], data, 32 ); GET_UINT32( X[9], data, 36 ); GET_UINT32( X[10], data, 40 ); GET_UINT32( X[11], data, 44 ); GET_UINT32( X[12], data, 48 ); GET_UINT32( X[13], data, 52 ); GET_UINT32( X[14], data, 56 ); GET_UINT32( X[15], data, 60 ); #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) #define P(a,b,c,d,k,s,t) \ { \ a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ } A = ctx->state[0]; B = ctx->state[1]; C = ctx->state[2]; D = ctx->state[3]; #define F(x,y,z) (z ^ (x & (y ^ z))) P( A, B, C, D, 0, 7, 0xD76AA478 ); P( D, A, B, C, 1, 12, 0xE8C7B756 ); P( C, D, A, B, 2, 17, 0x242070DB ); P( B, C, D, A, 3, 22, 0xC1BDCEEE ); P( A, B, C, D, 4, 7, 0xF57C0FAF ); P( D, A, B, C, 5, 12, 0x4787C62A ); P( C, D, A, B, 6, 17, 0xA8304613 ); P( B, C, D, A, 7, 22, 0xFD469501 ); P( A, B, C, D, 8, 7, 0x698098D8 ); P( D, A, B, C, 9, 12, 0x8B44F7AF ); P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); P( B, C, D, A, 11, 22, 0x895CD7BE ); P( A, B, C, D, 12, 7, 0x6B901122 ); P( D, A, B, C, 13, 12, 0xFD987193 ); P( C, D, A, B, 14, 17, 0xA679438E ); P( B, C, D, A, 15, 22, 0x49B40821 ); #undef F #define F(x,y,z) (y ^ (z & (x ^ y))) P( A, B, C, D, 1, 5, 0xF61E2562 ); P( D, A, B, C, 6, 9, 0xC040B340 ); P( C, D, A, B, 11, 14, 0x265E5A51 ); P( B, C, D, A, 0, 20, 0xE9B6C7AA ); P( A, B, C, D, 5, 5, 0xD62F105D ); P( D, A, B, C, 10, 9, 0x02441453 ); P( C, D, A, B, 15, 14, 0xD8A1E681 ); P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); P( A, B, C, D, 9, 5, 0x21E1CDE6 ); P( D, A, B, C, 14, 9, 0xC33707D6 ); P( C, D, A, B, 3, 14, 0xF4D50D87 ); P( B, C, D, A, 8, 20, 0x455A14ED ); P( A, B, C, D, 13, 5, 0xA9E3E905 ); P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); P( C, D, A, B, 7, 14, 0x676F02D9 ); P( B, C, D, A, 12, 20, 0x8D2A4C8A ); #undef F #define F(x,y,z) (x ^ y ^ z) P( A, B, C, D, 5, 4, 0xFFFA3942 ); P( D, A, B, C, 8, 11, 0x8771F681 ); P( C, D, A, B, 11, 16, 0x6D9D6122 ); P( B, C, D, A, 14, 23, 0xFDE5380C ); P( A, B, C, D, 1, 4, 0xA4BEEA44 ); P( D, A, B, C, 4, 11, 0x4BDECFA9 ); P( C, D, A, B, 7, 16, 0xF6BB4B60 ); P( B, C, D, A, 10, 23, 0xBEBFBC70 ); P( A, B, C, D, 13, 4, 0x289B7EC6 ); P( D, A, B, C, 0, 11, 0xEAA127FA ); P( C, D, A, B, 3, 16, 0xD4EF3085 ); P( B, C, D, A, 6, 23, 0x04881D05 ); P( A, B, C, D, 9, 4, 0xD9D4D039 ); P( D, A, B, C, 12, 11, 0xE6DB99E5 ); P( C, D, A, B, 15, 16, 0x1FA27CF8 ); P( B, C, D, A, 2, 23, 0xC4AC5665 ); #undef F #define F(x,y,z) (y ^ (x | ~z)) P( A, B, C, D, 0, 6, 0xF4292244 ); P( D, A, B, C, 7, 10, 0x432AFF97 ); P( C, D, A, B, 14, 15, 0xAB9423A7 ); P( B, C, D, A, 5, 21, 0xFC93A039 ); P( A, B, C, D, 12, 6, 0x655B59C3 ); P( D, A, B, C, 3, 10, 0x8F0CCC92 ); P( C, D, A, B, 10, 15, 0xFFEFF47D ); P( B, C, D, A, 1, 21, 0x85845DD1 ); P( A, B, C, D, 8, 6, 0x6FA87E4F ); P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); P( C, D, A, B, 6, 15, 0xA3014314 ); P( B, C, D, A, 13, 21, 0x4E0811A1 ); P( A, B, C, D, 4, 6, 0xF7537E82 ); P( D, A, B, C, 11, 10, 0xBD3AF235 ); P( C, D, A, B, 2, 15, 0x2AD7D2BB ); P( B, C, D, A, 9, 21, 0xEB86D391 ); #undef F ctx->state[0] += A; ctx->state[1] += B; ctx->state[2] += C; ctx->state[3] += D; } void md5_update( md5_context *ctx, uint8_t *input, uint32_t length ) { uint32_t left, fill; if( ! length ) return; left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += length; ctx->total[0] &= 0xFFFFFFFF; if( ctx->total[0] < length ) ctx->total[1]++; if( left && length >= fill ) { memcpy( (void *) (ctx->buffer + left), (void *) input, fill ); md5_process( ctx, ctx->buffer ); length -= fill; input += fill; left = 0; } while( length >= 64 ) { md5_process( ctx, input ); length -= 64; input += 64; } if( length ) { memcpy( (void *) (ctx->buffer + left), (void *) input, length ); } } static uint8_t md5_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; void md5_finish( md5_context *ctx, uint8_t digest[16] ) { uint32_t last, padn; uint32_t high, low; uint8_t msglen[8]; high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); PUT_UINT32( low, msglen, 0 ); PUT_UINT32( high, msglen, 4 ); last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); md5_update( ctx, md5_padding, padn ); md5_update( ctx, msglen, 8 ); PUT_UINT32( ctx->state[0], digest, 0 ); PUT_UINT32( ctx->state[1], digest, 4 ); PUT_UINT32( ctx->state[2], digest, 8 ); PUT_UINT32( ctx->state[3], digest, 12 ); } libkarma-0.1.2/src/md5.h0000644000175000000120000000113711543330237014072 0ustar frankywheel/* * libkarma/md5.h - RFC 1321 compliant MD5 implementation * * Copyright (c) Christophe Devine 2001-2003 * (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _MD5_H #define _MD5_H #include typedef struct { uint32_t total[2]; uint32_t state[4]; uint8_t buffer[64]; } md5_context; void md5_starts( md5_context *ctx ); void md5_update( md5_context *ctx, uint8_t *input, uint32_t length ); void md5_finish( md5_context *ctx, uint8_t digest[16] ); #endif /* _MD5_H */ libkarma-0.1.2/src/mp3.c0000644000175000000120000002065511543330237014105 0ustar frankywheel/* * libkarma/mp3.c * * Copyright (c) Cedric Tefft 2000-2001 * (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * *************************************************************************** * This file is based in part on: * MP3Info 0.5 by Ricardo Cerqueira * MP3Stat 0.9 by Ed Sweetman and * Johannes Overmann * */ #include #include #include #include #include #include #include "mp3.h" int layer_tab[4]= {0, 3, 2, 1}; int frequencies[3][4] = { {22050,24000,16000,50000}, /* MPEG 2.0 */ {44100,48000,32000,50000}, /* MPEG 1.0 */ {11025,12000,8000,50000} /* MPEG 2.5 */ }; int bitrate[2][3][14] = { { /* MPEG 2.0 */ {32,48,56,64,80,96,112,128,144,160,176,192,224,256}, /* layer 1 */ {8,16,24,32,40,48,56,64,80,96,112,128,144,160}, /* layer 2 */ {8,16,24,32,40,48,56,64,80,96,112,128,144,160} /* layer 3 */ }, { /* MPEG 1.0 */ {32,64,96,128,160,192,224,256,288,320,352,384,416,448}, /* layer 1 */ {32,48,56,64,80,96,112,128,160,192,224,256,320,384}, /* layer 2 */ {32,40,48,56,64,80,96,112,128,160,192,224,256,320} /* layer 3 */ } }; int frame_size_index[] = {24000, 72000, 72000}; static int frame_length(mp3header *header); static int get_header(FILE *file,mp3header *header); static int sameConstant(mp3header *h1, mp3header *h2); static int get_id3(mp3info *mp3); static char *pad(char *string, int length); static char *unpad(char *string); static int get_first_header(mp3info *mp3,long startpos); int get_mp3_info(mp3info *mp3) { int l; int bitrate,lastrate; int counter=0; struct stat filestat; off_t sample_pos; stat(mp3->filename,&filestat); mp3->datasize=filestat.st_size; get_id3(mp3); if(get_first_header(mp3,0L)) { mp3->offset=ftell(mp3->file); lastrate=15-mp3->header.bitrate; while((counter < NUM_SAMPLES) && lastrate) { sample_pos=(counter*(mp3->datasize/NUM_SAMPLES+1))+mp3->offset; if(get_first_header(mp3,sample_pos)) { bitrate=15-mp3->header.bitrate; } else { bitrate=-1; } if(bitrate != lastrate) { mp3->vbr=1; counter=NUM_SAMPLES; } lastrate=bitrate; counter++; } mp3->frames=(mp3->datasize-mp3->offset)/(l=frame_length(&mp3->header)); mp3->ms = (int)(1000*(float)(frame_length(&mp3->header)*mp3->frames)/ (float)(header_bitrate(&mp3->header)*125)+0.5); mp3->vbr_average = header_bitrate(&mp3->header); } return 0; } static int get_first_header(mp3info *mp3, long startpos) { int k, l=0,c; mp3header h, h2; long valid_start=0; fseek(mp3->file,startpos,SEEK_SET); while (1) { while((c=fgetc(mp3->file)) != 255 && (c != EOF)); if(c == 255) { ungetc(c,mp3->file); valid_start=ftell(mp3->file); if((l=get_header(mp3->file,&h))) { fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR); for(k=1; (k < MIN_CONSEC_GOOD_FRAMES) && (mp3->datasize-ftell(mp3->file) >= FRAME_HEADER_SIZE); k++) { if(!(l=get_header(mp3->file,&h2))) break; if(!sameConstant(&h,&h2)) break; fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR); } if(k == MIN_CONSEC_GOOD_FRAMES) { fseek(mp3->file,valid_start,SEEK_SET); memcpy(&(mp3->header),&h2,sizeof(mp3header)); mp3->header_isvalid=1; return 1; } } } else { return 0; } } return 0; } /* Get next MP3 frame header. Return codes: positive value = Frame Length of this header 0 = No, we did not retrieve a valid frame header */ static int get_header(FILE *file,mp3header *header) { unsigned char buffer[FRAME_HEADER_SIZE]; int fl; if(fread(&buffer,FRAME_HEADER_SIZE,1,file)<1) { header->sync=0; return 0; } header->sync=(((int)buffer[0]<<4) | ((int)(buffer[1]&0xE0)>>4)); if(buffer[1] & 0x10) header->version=(buffer[1] >> 3) & 1; else header->version=2; header->layer=(buffer[1] >> 1) & 3; if((header->sync != 0xFFE) || (header->layer != 1)) { header->sync=0; return 0; } header->crc=buffer[1] & 1; header->bitrate=(buffer[2] >> 4) & 0x0F; header->freq=(buffer[2] >> 2) & 0x3; header->padding=(buffer[2] >>1) & 0x1; return ((fl=frame_length(header)) >= MIN_FRAME_SIZE ? fl : 0); } static int frame_length(mp3header *header) { return header->sync == 0xFFE ? (frame_size_index[3-header->layer]*((header->version&1)+1)* header_bitrate(header)/header_frequency(header))+ header->padding : 1; } int header_layer(mp3header *h) {return layer_tab[h->layer];} int header_bitrate(mp3header *h) { return bitrate[h->version & 1][3-h->layer][h->bitrate>0 ? h->bitrate-1: 0]; } int header_frequency(mp3header *h) { return frequencies[h->version][h->freq]; } static int sameConstant(mp3header *h1, mp3header *h2) { if((*(uint*)h1) == (*(uint*)h2)) return 1; if((h1->version == h2->version) && (h1->layer == h2->layer ) && (h1->crc == h2->crc ) && (h1->freq == h2->freq )) return 1; else return 0; } static int get_id3(mp3info *mp3) { int retcode=0; char fbuf[4]; if(mp3->datasize >= 128) { if(fseek(mp3->file, -128, SEEK_END )) { fprintf(stderr, "ERROR: Couldn't read last 128 bytes of %s!!\n", mp3->filename); retcode |= 4; } else { fread(fbuf,1,3,mp3->file); fbuf[3] = '\0'; mp3->id3.genre[0]=255; if (!strcmp((const char *)"TAG",(const char *)fbuf)) { mp3->id3_isvalid=1; mp3->datasize -= 128; fseek(mp3->file, -125, SEEK_END); fread(mp3->id3.title,1,30,mp3->file); mp3->id3.title[30] = '\0'; fread(mp3->id3.artist,1,30,mp3->file); mp3->id3.artist[30] = '\0'; fread(mp3->id3.album,1,30,mp3->file); mp3->id3.album[30] = '\0'; fread(mp3->id3.year,1,4,mp3->file); mp3->id3.year[4] = '\0'; fread(mp3->id3.comment,1,30,mp3->file); mp3->id3.comment[30] = '\0'; if(mp3->id3.comment[28] == '\0') { mp3->id3.track[0] = mp3->id3.comment[29]; } fread(mp3->id3.genre,1,1,mp3->file); unpad(mp3->id3.title); unpad(mp3->id3.artist); unpad(mp3->id3.album); unpad(mp3->id3.year); unpad(mp3->id3.comment); } } } return retcode; } static char *pad(char *string, int length) { int l; l=strlen(string); while(lid3.title,TEXT_FIELD_LEN); strncat(buf,mp3->id3.title,TEXT_FIELD_LEN); pad(mp3->id3.artist,TEXT_FIELD_LEN); strncat(buf,mp3->id3.artist,TEXT_FIELD_LEN); pad(mp3->id3.album,TEXT_FIELD_LEN); strncat(buf,mp3->id3.album,TEXT_FIELD_LEN); pad(mp3->id3.year,INT_FIELD_LEN); strncat(buf,mp3->id3.year,INT_FIELD_LEN); pad(mp3->id3.comment,TEXT_FIELD_LEN); strncat(buf,mp3->id3.comment,TEXT_FIELD_LEN); strncat(buf,(char*)mp3->id3.genre,1); if (mp3->id3.track[0] != '\0') { buf[125]='\0'; buf[126]=mp3->id3.track[0]; } fseek(mp3->file,-128*mp3->id3_isvalid,SEEK_END); return (int)fwrite(buf,1,128,mp3->file); } libkarma-0.1.2/src/mp3.h0000644000175000000120000000327111543330237014105 0ustar frankywheel/* * libkarma/mp3.h * * Copyright (c) Cedric Tefft 2000-2001 * (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * *************************************************************************** * This file is based in part on: * MP3Info 0.5 by Ricardo Cerqueira * MP3Stat 0.9 by Ed Sweetman and * Johannes Overmann * */ #ifndef _MP3_H #define _MP3_H /* MIN_CONSEC_GOOD_FRAMES defines how many consecutive valid MP3 frames we need to see before we decide we are looking at a real MP3 file */ #define MIN_CONSEC_GOOD_FRAMES 4 #define FRAME_HEADER_SIZE 4 #define MIN_FRAME_SIZE 21 #define NUM_SAMPLES 4 typedef struct { unsigned long sync; unsigned int version; unsigned int layer; unsigned int crc; unsigned int bitrate; unsigned int freq; unsigned int padding; unsigned int extension; } mp3header; typedef struct { char title[31]; char artist[31]; char album[31]; char year[5]; char comment[31]; unsigned char track[1]; unsigned char genre[1]; } id3tag; typedef struct { char *filename; FILE *file; off_t datasize; int header_isvalid; mp3header header; int id3_isvalid; id3tag id3; int vbr; int vbr_average; int ms; int offset; int frames; int badframes; } mp3info; int get_mp3_info(mp3info *mp3); int header_layer(mp3header *h); int header_bitrate(mp3header *h); int header_frequency(mp3header *h); int write_tag(mp3info *mp3); #endif /* _MP3_H */ libkarma-0.1.2/src/wav.c0000644000175000000120000000347111543330237014200 0ustar frankywheel/* * libkarma/wav.c * * Copyright (c) Paul van der Mark ???? * * (playwav.c - ask the search engine of your choice) * (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include #include #include #include #include #include "wav.h" /* open file for reading and parse RIFF header: A riff header is constructed of a header word+opt. size of chunk+chunk(data) where a chunk can contain multiple headers So a wave file looks like "RIFF" size "WAVE" "fmt " size chunk with format parameters optional chunks like fact "data", size chunk with samples RIFFssssWAVEfmt ssssbbbbbbbbbdatabbbbbbb If you think this is complicated:look at compressed audio/video(AVI) riffs :) */ typedef u_char uc; #define TOFOUR(a) (((uc) a[0]<<24)|((uc) a[1]<<16)|((uc) a[2]<<8)|((uc) a[3])) #define RIFF TOFOUR("RIFF") #define WAVE TOFOUR("WAVE") #define FMT TOFOUR("fmt ") int openwav(wave_header **wh, char *filename) { int filefd; if(0==(*wh=malloc(sizeof(wave_header)))) return -1; (void) memset(*wh, 0, sizeof(wave_header)); if(-1==(filefd=open(filename, O_RDONLY))) return -1; if(read(filefd, *wh, sizeof(wave_header)) != (ssize_t) sizeof(wave_header)){ (void) close(filefd); /* close input file */ return -1; } (void) close(filefd); if((TOFOUR((*wh)->RiffID) != RIFF) || (TOFOUR((*wh)->WaveID) != WAVE) || (TOFOUR((*wh)->FmtID) != FMT)) return -1; return 0; } void cleanup(wave_header **wh) { if(*wh!=0) free(*wh); *wh=0; } libkarma-0.1.2/src/wav.h0000644000175000000120000000154111543330237014201 0ustar frankywheel/* * libkarma/wav.h * * Copyright (c) Paul van der Mark ???? * * (playwav.c - ask the search engine of your choice) * (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _WAV_H #define _WAV_H typedef struct { char RiffID [4] ; u_long RiffSize ; char WaveID [4] ; char FmtID [4] ; u_long FmtSize ; u_short wFormatTag ; u_short nChannels ; u_long nSamplesPerSec ; u_long nAvgBytesPerSec ; u_short nBlockAlign ; u_short wBitsPerSample ; } wave_header; int openwav(wave_header **, char *); void cleanup(wave_header **); #endif /* _WAV_H */ libkarma-0.1.2/src/errors.c0000644000175000000120000001121011543330237014705 0ustar frankywheel/* * libkarma/errors.c * * Copyright (c) Enrique Vidal 2004 * (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include #include #include #include "lkarma.h" const char *lkerrorList[MAXLKERRORS + 1] = { /* E_NOERR 0 */ "", /* E_HOST 1 */ "** Libkarma error: gethostbyname() failed", /* E_SOCKET 2 */ "** Libkarma error: socket() failed", /* E_SENDTO 3 */ "** Libkarma error: sendto() failed", /* E_CONNECT 4 */ "** Libkarma error: connect() failed", /* E_RECVFROM 5 */ "** Libkarma error: recvfrom() failed", /* E_SELECT 6 */ "** Libkarma error: select() failed", /* E_OPEN 7 */ "** Libkarma error: open() failed", /* E_ICONVO 8 */ "* Libkarma warning: iconv_open() failed", /* E_ICONV 9 */ "* Libkarma warning: iconv() failed", /* E_ICONVC 10 */ "** Libkarma error: iconv_close() failed", /* E_BADHEADER 11 */ "** Libkarma error: broken Rio header", /* E_BADIDENT 12 */ "** Libkarma error: wrong protocol identifier", /* E_FAILEDREQ 13 */ "* Libkarma warning: failed request", /* E_BADPROP 14 */ "** Libkarma error: property parsing failed", /* E_BADID 15 */ "** Libkarma error: given id not found", /* E_NOSSDP 16 */ "* Libkarma warning: no ssdp answer", /* E_SSDPPARSE 17 */ "* Libkarma warning: ssdp parsing failed", /* E_MKDIR 18 */ "** Libkarma error: mkdir() failed", /* E_UTIME 19 */ "** Libkarma error: utime() failed", /* E_NODIR 20 */ "** Libkarma error: unexisting directory", /* E_NOPROP 21 */ "* Libkarma warning: missing properties file", /* E_READ 22 */ "* Libkarma warning: read error", /* E_WRITE 23 */ "** Libkarma error: write error", /* E_DELETE 24 */ "** Libkarma error: delete error", /* E_NODEVSET 25 */ "* Libkarma warning: no device-settings file", /* E_UNIMPLEM 26 */ "* Libkarma warning: unimplemented call", /* E_MFINDERR 27 */ "* Libkarma warning: mount search error", /* E_NOMOUNT 28 */ "* Libkarma warning: no mountpoint found", /* E_MANYMOUNT 29 */ "* Libkarma warning: more than one mountpoints", /* E_NOSMALLDB 30 */ "* Libkarma warning: Missing RK index file (smalldb)", /* E_DUPE 31 */ "* Libkarma warning: tune already present", /* E_PATHCREAT 32 */ "* Libkarma warning: dir access/create failed", /* E_NOHASH 33 */ "** Libkarma error: no hash found", /* E_WRCHUNK 34 */ "** Libkarma error: write_file_chunk() failed", /* E_SMALLMP3 35 */ "** Libkarma error: tune file is too small", /* E_UNSUPTAG 36 */ "* Libkarma warning: unsupported tag type", /* E_NOTAGFILE 37 */ "* Libkarma warning: can't access tags file", /* E_BADFDB 38 */ "* Libkarma warning: unrecognised fdb file", /* E_UNSUPFDB 39 */ "* Libkarma warning: unsupported fdb file", /* E_NOPATHPR 40 */ "* Libkarma warning: missing path properties", /* E_NOTMPDIR 41 */ "* Libkarma warning: no temporary directory found", /* E_TMPCREAT 42 */ "** Libkarma error: can't create temporary tag file" }; #define libkarmaErrorString lkerrorList[libkarmaError] #define previousErrorString lkerrorList[previousError] /* libkarmaErrorString is assumedly valid only if libkarmaErrorFlag == 1 */ static int libkarmaError = 0; static int previousError = 0; static int autoPrintErrors = 1; static error_handler *callback = NULL; /* ---------------------------- Error Setting --------------------------- */ int lk_errors_set(const int err) { lk_errors_number(); if((err < 0) || (err > MAXLKERRORS)) return -1; libkarmaError = err; if(callback) { callback(); } if(autoPrintErrors) fprintf(stderr, "%s\n", libkarmaErrorString); return 0; } /* -------------------------- Error checking -------------------------- */ void lk_errors_autoprint(const int autoPrint) { autoPrintErrors = autoPrint; } void lk_errors_setHandler(error_handler * handler) { callback = handler; } int lk_errors_number() { /* checks current error number and backs-up and resets it */ previousError = libkarmaError; libkarmaError = 0; return previousError; } int lk_errors_number_noreset() { return libkarmaError; } int lk_errors_p(const char *s1, const char *s2) { if(lk_errors_number()) fprintf(stderr, "%s%s%s\n", s1, previousErrorString, s2); return previousError; } char *lk_errors_numberstr(int lkerrnum) { if((lkerrnum < 0) || (lkerrnum > MAXLKERRORS)) return NULL; return (char *)lkerrorList[lkerrnum]; } libkarma-0.1.2/src/Jamfile0000644000175000000120000000056611543330237014533 0ustar frankywheelSubDir TOP src ; BuildLib karma : ; LibMember karma : errors.c hash.c karma.c karmaUsb.c karmaLan.c md5.c properties.c ssdp.c util.c playlist.c status.c fdb.c rio_rw.c wav.c mp3.c utf8.c mountSearch.c ; LINKFLAGS += -lz -lusb ; InstallLib $(PREFIX)/lib : libkarma$(SUFLIB) ; InstallShell $(PREFIX)/lib : libkarma$(SUFLIBSHR) ; InstallFile $(PREFIX)/include : lkarma.h ; libkarma-0.1.2/src/hash.c0000644000175000000120000000756711543330237014340 0ustar frankywheel/* * libkarma/hash.c * * Copyright (c) Michael R. Elkins 1996-2000 * (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include #include #include #include "hash.h" #define SOMEPRIME 149711 #define STRCMP(a,b) strcmp(a?a:"", b?b:"") int hash_string(const unsigned char *s, int n) { int h = 0; while(*s) h += (h << 7) + *s++; h = (h * SOMEPRIME) % n; h = (h >= 0) ? h : h + n; return (h % n); } HASH *hash_create(int nelem) { HASH *table = malloc(sizeof(HASH)); if(nelem == 0) nelem = 2; table->nelem = nelem; table->table = calloc(nelem, sizeof(struct hash_elem *)); return table; } int hash_count(HASH * table) { int count, i; struct hash_elem *tmp; for (i = 0, count = 0; i < table->nelem; i++) { tmp = table->table[i]; while(tmp) { tmp = tmp->next; count++; } } return count; } void hash_iterate(HASH * table, int index, const char **key, void **data) { int i; struct hash_elem *tmp = NULL; i = 0; while(index) { tmp = table->table[i]; while(tmp && --index) tmp = tmp->next; i++; } *key = tmp->key; *data = tmp->data; } void hash_walker(HASH * table, void (*fn) (const char *key, void *data)) { int i; struct hash_elem *tmp; for (i = 0; i < table->nelem; i++) { tmp = table->table[i]; while(tmp) { fn(tmp->key, tmp->data); tmp = tmp->next; } } } /* table hash table to update * key key to hash on * data data to associate with `key' */ int hash_insert(HASH * table, const char *key, void *data) { struct hash_elem *ptr; int h; struct hash_elem *tmp, *last; int r; ptr = (struct hash_elem *)malloc(sizeof(struct hash_elem)); h = hash_string((unsigned char *)key, table->nelem); ptr->key = key; ptr->data = data; for (tmp = table->table[h], last = NULL; tmp; last = tmp, tmp = tmp->next) { r = STRCMP(tmp->key, key); if(r == 0) { free(tmp->data); tmp->data = ptr->data; free((char *)tmp->key); tmp->key = ptr->key; free(ptr); return h; } if(r > 0) break; } if(last) last->next = ptr; else table->table[h] = ptr; ptr->next = tmp; return h; } void *hash_find_hash(const HASH * table, int hash, const char *key) { struct hash_elem *ptr = table->table[hash]; for (; ptr; ptr = ptr->next) { if(STRCMP(key, ptr->key) == 0) return ptr->data; } return NULL; } void hash_delete_hash(HASH * table, int hash, const char *key, const void *data) { struct hash_elem *ptr = table->table[hash]; struct hash_elem **last = &table->table[hash]; for (; ptr; last = &ptr->next, ptr = ptr->next) { /* if `data' is given, look for a matching ->data member. * This is required for the case where we have multiple * entries with the same key */ if((data == ptr->data) || (!data && STRCMP(ptr->key, key) == 0)) { *last = ptr->next; free((char *)ptr->key); free(ptr->data); free(ptr); return; } } } /* ptr pointer to the hash table to be freed */ void hash_destroy(HASH ** ptr) { int i; HASH *pptr = *ptr; struct hash_elem *elem, *tmp; for (i = 0; i < pptr->nelem; i++) { for (elem = pptr->table[i]; elem;) { tmp = elem; elem = elem->next; free((char *)tmp->key); free(tmp->data); free(tmp); } } free(pptr->table); free(*ptr); } libkarma-0.1.2/src/hash.h0000644000175000000120000000235011543330237014326 0ustar frankywheel/* * libkarma/hash.h * * Copyright (c) Michael R. Elkins 1996-2000 * (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _HASH_H #define _HASH_H struct hash_elem { const char *key; void *data; struct hash_elem *next; }; typedef struct { int nelem; struct hash_elem **table; } HASH; #define hash_find(table, key) \ hash_find_hash(table, hash_string((unsigned char *)key, table->nelem), key) #define hash_delete(table,key,data,destroy) \ hash_delete_hash(table, hash_string((unsigned char *)key, table->nelem), \ key, data, destroy) HASH * hash_create(int nelem); int hash_string(const unsigned char *s, int n); int hash_insert(HASH * table, const char *key, void *data); int hash_count(HASH * table); void hash_iterate(HASH * table, int index, const char **key, void **data); void hash_walker(HASH * table, void (*fn)(const char *key, void *data)); void *hash_find_hash(const HASH * table, int hash, const char *key); void hash_delete_hash(HASH * table, int hash, const char *key, const void *data); void hash_destroy(HASH ** hash); #endif /* _HASH_H */ libkarma-0.1.2/src/properties.c0000644000175000000120000005343611543330237015605 0ustar frankywheel/* * libkarma/properties.c * * Copyright (c) Frank Zschockelt 2004-2006 * Copyright (c) Keith Bennett 2006 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include #include #include #include #include #include #include #include #include #include "lkarma.h" #include "properties.h" #include "playlist.h" #include "util.h" #include "fdb.h" #define HASHSIZE 16 #define TABLECHUNK 4096 #define FIRSTFID 17 /* 272/16 */ struct klist{ HASH ** fidTable; uint32_t ftsize; uint32_t count; uint32_t next_fid; }; struct klist props = {NULL, 0, 0, 17}; int properties_updated = 0; int fdb_updated = 0; uint32_t device_generation; uint32_t serial; void lk_properties_init(void) { uint32_t i; props.count=0; props.next_fid=17; props.ftsize=TABLECHUNK; props.fidTable=malloc(props.ftsize*sizeof(HASH *)); for(i=0;i 0) { if(props.fidTable[i]){ hash_destroy(&props.fidTable[i]); props.count--; } i++; } free(props.fidTable); props.fidTable=NULL; props.count=0; props.next_fid=17; properties_updated = 0; fdb_updated = 0; } uint32_t lk_properties_import(char * properties) { uint32_t count=0; char *key, *value; char *ikey, *ivalue; HASH * item; uint32_t fid,i; char *n_tok, *last; last=&(properties[strlen(properties)])+1; /* otherwise we can't see whether n_tok is outside of properties */ item=hash_create(HASHSIZE); hash_insert(item, strdup("fid"), strdup("0")); key=strtok_r(properties, "=", &n_tok); if(key==NULL){ lk_errors_set(E_BADPROP); return -1; } /* fprintf(stderr, "n_tok = --%c--\n", *n_tok); */ if(*n_tok == '\n') {value=""; n_tok++;} else value=strtok_r(NULL, "\n", &n_tok); while(value != NULL){ ikey=strdup(key); ivalue=strdup(value); /* hash_insert(item, ikey, ivalue); /////////////// */ if(strlen(ivalue)) hash_insert(item, ikey, ivalue); else { if (ikey) free(ikey); if (ivalue) free(ivalue); } /* fprintf(stderr, "hash_insert -%s--%s-\n", ikey, ivalue); */ if((n_tok[0] == '\n')||(n_tok[0]=='\0')){ ++n_tok; fid=(uint32_t)(atol(lk_properties_get_property_hash(item, "fid"))/16); while(fid >= props.ftsize){ i=props.ftsize+TABLECHUNK; props.fidTable=realloc(props.fidTable, i*sizeof(HASH *)); for( ;props.ftsizenelem; i++) { tmp=table->table[i]; while(tmp){ export_hash(tmp->key, tmp->data); tmp=tmp->next; } } } return p; } /* The karma only plays files when the ID is > 256 and ID%16==0 */ uint32_t lk_properties_getnextfid(void) { while(props.fidTable[props.next_fid]) props.next_fid++; return props.next_fid*16; } uint32_t lk_properties_new_property(void) { HASH *item; static uint32_t new_fid; uint32_t i; item=hash_create(HASHSIZE); new_fid=lk_properties_getnextfid(); lk_properties_set_property_hash(item, "fid", simple_itoa(new_fid)); while(new_fid/16 >= props.ftsize){ i=props.ftsize+TABLECHUNK; props.fidTable=realloc(props.fidTable, i*sizeof(HASH *)); for( ;props.ftsize1) {exact = 1; and = mode-2;} else {exact = 0; and = mode;} #define STRMATCH(a,b) exact \ ? (((a==NULL)&&(b==NULL))||(b&&(b[0]==0))||(a&&b&&(strcmp(a,b)==0))) \ : (((a==NULL)&&(b==NULL))|| (b && a && (strstr(a,b)!=NULL))) /* exact ? ((b==NULL)||((a==NULL)&&(b==NULL))||(a && (strcmp(a,b)==0))):\*/ /* (((a==NULL)&&(b==NULL)) || (b && a && (strstr(a,b)!=NULL)))*/ /* exact?((data[0]==0)||(val[0]==0)||(strcmp(val, data)==0)):\ */ /* (strstr(val, data)!=NULL) */ /* fprintf(stderr, "+++> %d ---%s+++%s---\n", mode, key, data); */ if(search_in==NULL){ if(and) /* AND merge with zero elements */ return NULL; hash=hash_string((const unsigned char *)key, HASHSIZE); while(count <= props.count){ if(props.fidTable[fid]){ ++count; val = (char *)hash_find_hash(props.fidTable[fid], hash, key); if(STRMATCH(val, data)) { ++i; result=realloc(result, i*sizeof(uint32_t)); result[i-1]=fid*16; } } ++fid; } } else if (and) { /* AND merge */ while(search_in[j] != 0){ val=lk_properties_get_property(search_in[j], key); if(STRMATCH(val, data)){ ++i; result=realloc(result, i*sizeof(uint32_t)); result[i-1]=search_in[j]; } ++j; } free(search_in); }else{ /* OR merge */ while(search_in[i] != 0) ++i; result=malloc((i) * sizeof(uint32_t)); memcpy(result, search_in, (i) * sizeof(uint32_t)); hash=hash_string((const unsigned char *)key, HASHSIZE); while(count <= props.count){ if(props.fidTable[fid]){ ++count; val=(char *)hash_find_hash(props.fidTable[fid], hash, key); if(STRMATCH(val, data)){ fid*=16; j=0; while((jstr, "The ", 4) == 0 || memcmp(t1->str, "the ", 4) == 0 ) s1 = 4; if (memcmp(t2->str, "The ", 4) == 0 || memcmp(t2->str, "the ", 4) == 0 ) s2 = 4; return strcmp(t1->str+s1, t2->str+s2); } static int cmp(const void *p1, const void *p2) { table_t *t1 = (table_t *)p1; table_t *t2 = (table_t *)p2; return strcmp(t1->str, t2->str); } int lk_properties_write_property(FILE *fp, char *attr, smalldb_type_t type, table_t *table, uint32_t *offset, uint32_t *arrsz, char **arr) { char *str, *ptr, *offset_c; uint32_t i, j, n, osz, sz, len, off, idx, profile = 0; uint16_t *offset_16; sz = len = 0; ptr = *arr; offset_c = (char *) offset; offset_16 = (uint16_t *) offset; if (type == SDB_BLOB || type == SDB_STRING) { for(i=0,j=16,off=0; i *arrsz) { while (len > *arrsz) *arrsz *= 2; *arr = realloc(*arr, *arrsz); } memcpy(*arr+off, str, sz); } else if (type == SDB_STRING) { sz = 1; len += sz; *(*arr+off) = '\0'; } else sz = 0; table[i].len = sz; table[i].idx = i; off = len; i++; } n = i; ptr = *arr; for (i=0; iversion = 2; db->eight = 8; db->three = 3; db->num_playlists = 0; db->dmap_size = 0; db->num_attribs = 36; db->attribs = malloc(db->num_attribs * sizeof(smalldb_attrib_t)); if (!db->attribs) return 1; optr = ptr = propnames; for (i = 0; i < db->num_attribs; i++) { for (; *ptr && *ptr != ' '; ptr++); len = ptr - optr; db->attribs[i].name = malloc(len+1); memcpy(db->attribs[i].name, optr, len); db->attribs[i].name[len] = '\0'; optr = ++ptr; db->attribs[i].type = (smalldb_type_t) types[i]; db->attribs[i].dunno = dunno[i]; } return 0; } int lk_properties_write_smalldb(char *usbMountPoint, karma_db_t *db) { uint32_t i, len, arrsz, nfiles = props.count; uint32_t ret = 0; uint32_t *offset = NULL; table_t *table = NULL; char *tmp = NULL; char *arr = NULL; FILE *fp; if (properties_updated == 0) return 0; arrsz = 40*nfiles; arr = malloc(arrsz); if (!arr) goto err; offset = malloc(nfiles*sizeof(uint32_t)); if (!offset) goto err; table = malloc(nfiles*sizeof(table_t)); if (!table) goto err; tmp = calloc(strlen(usbMountPoint) + strlen(RK_SMALLDB) + 1, 1); if (!tmp) goto err; sprintf(tmp, "%s%s", usbMountPoint, RK_SMALLDB); fp = fopen(tmp, "w+"); if (!fp) { mk_path(tmp); fp = fopen(tmp, "w+"); } if (!fp) { perror(tmp); goto err; } free(tmp); tmp = NULL; if (!db) db = calloc(sizeof(karma_db_t), 1); if (!db) goto err; if (db->num_attribs == 0) { ret = smalldb_init(db); if (ret) goto err; } db->ctime = (int) time(NULL); fwrite(&db->version, sizeof(uint32_t), 1, fp); fwrite(&db->ctime, sizeof(uint32_t), 1, fp); fwrite(&db->eight, sizeof(uint32_t), 1, fp); fwrite(&db->three, sizeof(uint32_t), 1, fp); fwrite(&db->num_attribs, sizeof(uint32_t), 1, fp); for (i=0, len=0; inum_attribs; i++) { smalldb_attrib_t *atb = &db->attribs[i]; fwrite(&atb->type, sizeof(uint32_t), 1, fp); fwrite(&atb->dunno, sizeof(uint32_t), 1, fp); len += strlen(atb->name) + 1; } fwrite(&len, sizeof(uint32_t), 1, fp); for (i=0; inum_attribs; i++) { char *name = db->attribs[i].name; fwrite(name, strlen(name), 1, fp); fputc(' ', fp); } fwrite(&db->num_playlists, sizeof(uint32_t), 1, fp); for (i=0; inum_playlists; i++) { /* playlist section, copy as opaque data for now */ fwrite(&db->playlists[i].index, sizeof(uint32_t), 1, fp); fwrite(&db->playlists[i].len, sizeof(uint32_t), 1, fp); fwrite(db->playlists[i].playlist, db->playlists[i].len, 1, fp); } fwrite(&nfiles, sizeof(uint32_t), 1, fp); fwrite(&nfiles, sizeof(uint32_t), 1, fp); if (nfiles > 0) { for (i=0; inum_attribs; i++) { ret = lk_properties_write_property(fp, db->attribs[i].name, db->attribs[i].type, table, offset, &arrsz, &arr); if (ret) { fprintf(stderr, "error writing property: %s\n", db->attribs[i].name); goto err; } } } fwrite(&db->dmap_size, sizeof(uint32_t), 1, fp); if (db->dmap_size) fwrite(db->dmap, db->dmap_size, 1, fp); fwrite(&db->ctime, sizeof(uint32_t), 1, fp); fclose(fp); goto out; err: ret = 1; out: if (arr) free(arr); if (offset) free(offset); if (table) free(table); if (tmp) free(tmp); return ret; } libkarma-0.1.2/src/properties.h0000644000175000000120000000407011543330237015600 0ustar frankywheel/* * libkarma/properties.h * * Copyright (c) Frank Zschockelt 2004 * Copyright (c) Keith Bennett * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _PROPERTIES_H #define _PROPERTIES_H #include #include #include #include "hash.h" #include "lkarma.h" #define RK_SMALLDB "/var/smalldb" typedef enum smalldb_type { SDB_LE32, SDB_STRING, SDB_BLOB, SDB_CHAR, SDB_LE16 } smalldb_type_t; typedef struct smalldb_attrib { char *name; smalldb_type_t type; uint32_t dunno; } smalldb_attrib_t; typedef struct playlist_attrib { uint32_t index; uint32_t len; char *playlist; } playlist_t; typedef struct karma_db { uint32_t version; uint32_t ctime; uint32_t eight; uint32_t three; uint32_t num_attribs; uint32_t prop_size; uint32_t num_playlists; uint32_t dmap_size; smalldb_attrib_t *attribs; playlist_t *playlists; unsigned char *dmap; } karma_db_t; typedef struct table { char *str; uint32_t len; uint32_t idx; } table_t; extern uint32_t device_generation; extern uint32_t serial; extern int properties_updated; /* char * lk_properties_get_codeset (void); void lk_properties_set_codeset (char * codeset); */ uint32_t lk_properties_getnextfid (void); char * lk_properties_get_property_hash(HASH * p, char * key); void lk_properties_set_property_hash(HASH * p, char * property, char * data); HASH * lk_properties_idsearch (uint32_t fid); void lk_properties_inc_devgeneration(void); int lk_properties_write_smalldb (char *usbMountPoint, karma_db_t *db); int lk_properties_write_property (FILE *fp, char *attr, smalldb_type_t type, table_t *table, uint32_t *offset, uint32_t *arrsz, char **arr); #endif /* _PROPERTIES_H */ libkarma-0.1.2/src/rio_rw.c0000644000175000000120000005034211543330237014703 0ustar frankywheel/* * libkarma/rio_rw.c * * Copyright (c) Frank Zschockelt 2004 * Copyright (c) Keith Bennett 2006 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "mp3.h" #include "wav.h" #include "lkarma.h" #include "karma.h" #include "properties.h" #include "util.h" #include "rio_rw.h" #include "fdb.h" /* #define BLOCKSIZE 32768 */ #define BLOCKSIZE 131072 /* #define NOT_TAGGED "[karmalib 0.4]" */ #define NOT_TAGGED "unTagged" /* something more explicit and readable ... */ enum { TYPE_DATA, TYPE_MP3, TYPE_OGG, TYPE_FLAC, TYPE_WAV, TYPE_WMA }; static int write_dupes = 0; static void add_general(HASH * p, const char *filename, int updateLength); static int get_ogg_props(HASH *p, const char *filename); static int get_flac_props(HASH *p, const char *filename); static int get_mp3_props(HASH *p, mp3info *mp3); static int get_taxi_props(HASH *p); static int get_wave_props(HASH *p, const char *filename); static void add_tag(HASH *p, char *key, char *value); static int set_tag_props(HASH *p, const char *filename, int type); static int get_file_type(mp3info *mp3); int lk_synchronize_necessary(int rio) { uint32_t old; old = device_generation; lk_karma_get_device_settings(rio, NULL); return (old != device_generation); } int lk_rio_read_playlist(int rio, uint32_t fid, const char * filename) { playlist *pl; int dst; pl=lk_playlist_fid_read(fid); if (pl==NULL) return -1; /* Can't get playlist for this fid */ if (mk_path(filename)) { lk_errors_set(E_PATHCREAT); /* fprintf(stderr,"** Error creating directory of path: %s\n",filename); */ } dst=open(filename, O_CREAT|O_EXCL|O_WRONLY,S_IREAD|S_IWRITE|S_IRGRP|S_IROTH); if(dst==-1) return -1; /* Can't open: e.g., file already exist */ write(dst, pl->playlist, pl->length); close(dst); free(pl->playlist); free(pl); return 0; } int lk_rio_read(int rio, uint32_t fid, const char * filename) { int dst; uint64_t blk=BLOCKSIZE, offs=0, filesize=0; uint64_t got=0; char *tmp, *tmp1; /* dst=creat(filename, O_EXCL); */ if (mk_path(filename)) { lk_errors_set(E_PATHCREAT); /* fprintf(stderr,"** Error creating directory of path: %s\n",filename); */ } dst=open(filename, O_CREAT|O_EXCL|O_WRONLY,S_IREAD|S_IWRITE|S_IRGRP|S_IROTH); if(dst==-1) return -1; /* Can not open (e.g., file already exist) */ tmp1=lk_properties_get_property(fid, "length"); if(tmp1 != NULL) filesize=atoll(tmp1); else return -1; /* tmp1==NULL => filesize undefined */ if(filesize<=0) return -1; /* Mystery: filesize sometimes can be 0 ???!!! */ while(offs 0) { off = blk; blk = len; ret = lk_karma_read_file_chunk(rio, off, blk, fid, &tmp, &got); if (ret != 0 || got != blk) goto err; ret = lseek(fd, off, SEEK_SET); ret = write(fd, tmp, got); free(tmp); } /* tail */ blk = RID_BLOCKS + 128; off = length - blk; ret = lk_karma_read_file_chunk(rio, off, blk, fid, &tmp, &got); if (ret != 0 || got != blk) goto err; ret = lseek(fd, (mp3.offset + 2*RID_BLOCKS), SEEK_SET); if (memcmp(tmp+got-128, "TAG", 3) == 0) { ret = write(fd, tmp, got); length -= 128; } else ret = write(fd, tmp+128, got-128); free(tmp); /* middle 64k */ blk = RID_BLOCKS; off = (mp3.offset + length - RID_BLOCKS)/2; ret = lk_karma_read_file_chunk(rio, off, blk, fid, &tmp, &got); if (ret != 0 || got != blk) goto err; ret = lseek(fd, (mp3.offset + RID_BLOCKS), SEEK_SET); ret = write(fd, tmp, got); free(tmp); close(fd); mp3.datasize = mp3.offset + 3*RID_BLOCKS; return filename; err: if (filename) { close(fd); unlink(filename); } if (tmp) free(tmp); lk_errors_set(E_TMPCREAT); return NULL; } int lk_rio_update_props_from_tags(int rio, uint32_t fid) { int ret; char *filename; if (using_usb) filename = lk_karma_fidToPath(rio, fid); else filename = lk_rio_create_temp_file(rio, fid); if (!filename) return -1; /* Don't update the length propery (last arg = 0). Length of fid * was already correctly set when the fid was first created and * length of files provided by lk_rio_create_temp_file() are wrong */ ret = lk_rio_do_update_props_from_tags(rio, fid, filename, 0); if (using_usb == 0 || ret) unlink(filename); free(filename); return ret; } /* To use that function properly: 1. Get an IO Lock for Writing 2. call synchronize_necessary and synchronize the properties if necessary ;) 3. use rio_write as often as you need to :) 4. release the IO Lock. */ static uint32_t lk_rio_do_write(int fdb, int rio, const char * filename) { int got, fd, len; uint32_t fid = 0, *ids; uint64_t offs=0; char *p, tmp[BLOCKSIZE]; const uint64_t siz=BLOCKSIZE; char *rid, *path, fullpath[257+PATH_MAX]; fd=open(filename, O_RDONLY); if (fd == -1) return -1; if (fdb) { ids = lk_properties_andOrSearch(EXACT|ORS, NULL, "title", FDB_FILENAME); if (ids) { ids = lk_properties_andOrSearch(EXACT|ANDS, ids, "type", "taxi"); if (ids) { fid = *ids; free(ids); } } } if (!fid) fid = lk_properties_new_property(); got = lk_rio_do_update_props_from_tags(rio, fid, filename, 1); if (got != 0) { lk_properties_del_property(fid); close(fd); return -1; } /** Brought here from lk_rio_update_props_from_tags() **/ rid = lk_properties_get_property(fid, "rid"); if (write_dupes == 0 && fdb == 0) { ids = lk_properties_andOrSearch(EXACT|ORS, NULL, "rid", rid); if ((ids != NULL) && (ids[1] != 0)) { /* more than 1 fid with this rid*/ free(ids); lk_errors_set(E_DUPE); lk_properties_del_property(fid); close(fd); return -1; } } while((got=read(fd, &tmp, siz)) > 0) { /* Now writing the data */ if(lk_karma_write_file_chunk(rio, offs, got, fid, 0, tmp)!=0) { lk_errors_set(E_WRCHUNK); lk_properties_del_property(fid); close(fd); return -1; } offs+=got; } close(fd); if (!fdb) { if (gethostname(fullpath, 255) != 0) fullpath[0] = '\0'; len = strlen(fullpath); fullpath[len] = ':'; path = realpath(filename, fullpath+len+1); if (path) { lk_properties_set_property(fid, "path", fullpath); fdb_updated = 1; } } p=lk_properties_export(fid); got=lk_karma_update_file_details(rio, fid, p); free(p); return fid; } uint32_t lk_rio_write(int rio, const char * filename) { return lk_rio_do_write(0, rio, filename); } uint32_t lk_rio_write_fdb(int rio, const char * filename) { return lk_rio_do_write(1, rio, filename); } static void add_general(HASH * p, const char *filename, int updateLength) { time_t generation_time; char *t; struct stat len; if(updateLength) lstat(filename, &len); generation_time=time(NULL); lk_properties_set_property_hash(p, "profile", ""); lk_properties_set_property_hash(p, "fid_generation", simple_itoa(generation_time)); lk_properties_set_property_hash(p, "ctime", simple_itoa(generation_time)); if(updateLength) lk_properties_set_property_hash(p, "length", simple_itoa(len.st_size)); t=strrchr(filename, '/'); t=utf8_to_codeset((char *)(t?t+1:filename)); lk_properties_set_property_hash(p, "title", t); free(t); } static int get_ogg_props(HASH *p, const char *filename) { lk_properties_set_property_hash(p, "type", "tune"); lk_properties_set_property_hash(p, "codec", "vorbis"); /*default values*/ lk_properties_set_property_hash(p, "genre", NOT_TAGGED); lk_properties_set_property_hash(p, "artist", NOT_TAGGED); lk_properties_set_property_hash(p, "source", NOT_TAGGED); return set_tag_props(p, filename, TagLib_File_OggVorbis); } static int get_flac_props(HASH *p, const char *filename) { lk_properties_set_property_hash(p, "type", "tune"); lk_properties_set_property_hash(p, "codec", "flac"); /*default values*/ lk_properties_set_property_hash(p, "genre", NOT_TAGGED); lk_properties_set_property_hash(p, "artist", NOT_TAGGED); lk_properties_set_property_hash(p, "source", NOT_TAGGED); #ifndef TagLib_File_FLAC /* older tag_c libs don't have TagLib_File_FLAC */ #define TagLib_File_FLAC -1 #endif return set_tag_props(p, filename, TagLib_File_FLAC); } static int get_mp3_props(HASH *p, mp3info *mp3) { int ret = 0, brate = 0; char bitrate[5]; char* aux; uint64_t length; lk_properties_set_property_hash(p, "type", "tune"); lk_properties_set_property_hash(p, "codec", "mp3"); lk_properties_set_property_hash(p, "offset", simple_itoa(mp3->offset)); /*default values*/ lk_properties_set_property_hash(p, "genre", NOT_TAGGED); lk_properties_set_property_hash(p, "artist", NOT_TAGGED); lk_properties_set_property_hash(p, "source", NOT_TAGGED); ret = set_tag_props(p, mp3->filename, TagLib_File_MPEG); if(!mp3->vbr){ brate = header_bitrate(&mp3->header); strcpy(bitrate, "fs"); strcat(bitrate, simple_itoa(brate)); lk_properties_set_property_hash(p, "bitrate", bitrate); /* fix bad duration yield by lk_rio_do_update_props_from_tags */ aux = lk_properties_get_property_hash(p, "length"); if(aux != NULL) { length = strtoull(aux, NULL, 10); lk_properties_set_property_hash(p, "duration", simple_itoa(8*(length/brate))); } } return ret; } static int get_taxi_props(HASH *p) { lk_properties_set_property_hash(p, "duration", "0"); lk_properties_set_property_hash(p, "offset", "0"); /* lk_properties_set_property_hash(p, "bitrate", "fs128"); */ /* unneeded */ lk_properties_set_property_hash(p, "codec", "taxi"); lk_properties_set_property_hash(p, "type", "taxi"); /* Set read-only access permissions for lkarmafs */ lk_properties_set_property_hash(p, MODE_PROPERTY, "33060"); return 0; } /* int get_wma_props(HASH *p, const char *filename) { return 0; } */ static int get_wave_props(HASH *p, const char *filename) { wave_header *wh; if(openwav(&wh, (char*)filename) == -1){ cleanup(&wh); return 1; } lk_properties_set_property_hash(p, "codec", "wave"); lk_properties_set_property_hash(p, "type", "tune"); lk_properties_set_property_hash(p, "bitrate", "fs999"); lk_properties_set_property_hash(p, "genre", NOT_TAGGED); lk_properties_set_property_hash(p, "artist", "wave_file"); lk_properties_set_property_hash(p, "source", "wave_file"); lk_properties_set_property_hash(p, "samplerate", simple_itoa(wh->nSamplesPerSec)); lk_properties_set_property_hash(p, "duration", simple_itoa(1000 * wh->RiffSize/wh->nChannels/ (wh->nChannels * wh->nSamplesPerSec))); lk_properties_set_property_hash(p, "file_id", "0"); lk_properties_set_property_hash(p, "tracknr", "0"); cleanup(&wh); return 0; } static void add_tag(HASH *p, char *key, char *value) { if (value[0]) lk_properties_set_property_hash(p, key, value); /* printf("Key = %s ; Value = %s\n", key, value); */ } char *strrtrim (char *s) { size_t n; if(!s) return NULL; n = strlen(s) - 1; while (n && (isspace(s[n]))) n--; s[n+1] = '\0'; return s; } /*** You can use this with all tag-formats, which taglib supports. */ static int set_tag_props(HASH *p, const char *filename, int type) { TagLib_File *tl_file; TagLib_Tag *tl_tag; const TagLib_AudioProperties * tl_audio; int i; int fdTestOpen; char bitrate[6]; uint32_t *ids; char *title, *source, *artist; /** Test needed since taglib_file_new[_type] returns !NULL if its open fails */ fdTestOpen = open(filename, O_RDONLY); if (fdTestOpen != -1) close(fdTestOpen); else { lk_errors_set(E_NOTAGFILE); return 0; } /** end Test */ if (type != -1) tl_file = taglib_file_new_type(filename, type); else tl_file = taglib_file_new(filename); if (! tl_file) { lk_errors_set(E_UNSUPTAG); return 0; } tl_tag = taglib_file_tag(tl_file); if (! tl_tag) return 0; tl_audio = taglib_file_audioproperties(tl_file); title = taglib_tag_title (tl_tag); source = taglib_tag_album (tl_tag); artist = taglib_tag_artist(tl_tag); title = strrtrim(title); source = strrtrim(source); artist = strrtrim(artist); /* fprintf(stderr, "set_tag_props -%s-%s-%s-\n", artist, source, title); */ if (write_dupes == 0) { ids = lk_properties_andOrSearch(EXACT|ORS, NULL, "title", title); if (ids) { ids = lk_properties_andOrSearch(EXACT|ANDS, ids, "source", source); if (ids) { ids = lk_properties_andOrSearch(EXACT|ANDS, ids, "artist", artist); if (ids) { free(ids); lk_errors_set(E_DUPE); return -1; } } } } add_tag(p, "title", title); add_tag(p, "source", source); add_tag(p, "artist", artist); add_tag(p, "comment", taglib_tag_comment(tl_tag)); add_tag(p, "genre", taglib_tag_genre(tl_tag)); i = taglib_tag_year(tl_tag); if (i) add_tag(p, "year", simple_itoa(i)); i = taglib_tag_track(tl_tag); if (i) { add_tag(p, "tracknr", simple_itoa(i)); add_tag(p, "file_id", simple_itoa(i)); } i=taglib_audioproperties_samplerate(tl_audio); if(i) add_tag(p, "samplerate", simple_itoa(i)); i=taglib_audioproperties_length(tl_audio)*1000; if(i) add_tag(p, "duration", simple_itoa(i)); strcpy(bitrate, "vs"); i=taglib_audioproperties_bitrate(tl_audio); if(i){ if(i>999) strcat(bitrate, "999"); else strcat(bitrate, simple_itoa(i)); add_tag(p, "bitrate", bitrate); } taglib_file_free(tl_file); /*taglib_tag_free_strings();*/ return 0; } static int get_file_type(mp3info *mp3) { int ret, type = TYPE_DATA; unsigned int i, off; unsigned char buf[48]; struct stat st; ret = stat(mp3->filename, &st); if (ret != 0) return -1; mp3->datasize = st.st_size; mp3->file = fopen(mp3->filename, "r"); if (mp3->file == NULL) return -1; if (mp3->datasize >= 128) { if (fseek(mp3->file, -128, SEEK_END )) { lk_errors_set(E_SMALLMP3); /* fprintf(stderr,"read err: last 128 bytes of %s.\n",mp3->filename);*/ return -1; } else { fread(buf, 1, 3, mp3->file); if (memcmp(buf, "TAG", 3) == 0) mp3->datasize -= 128; } fseek(mp3->file, 0, SEEK_SET); } fread(buf, 1, 48, mp3->file); if (memcmp(buf, "ID3", 3) == 0) { mp3->offset = (((buf[6]&0x7f)<<21)|((buf[7]&0x7f)<<14)| ((buf[8]&0x7f)<<7) |(buf[9]&0x7f)) + 10; fseek(mp3->file, mp3->offset, SEEK_SET); fread(buf, 1, 48, mp3->file); } if (memcmp(buf, "OggS", 4) == 0) { mp3->offset += buf[27] + 28; if (memcmp(buf+29, "vorbis", 6) == 0) { type = TYPE_OGG; fseek(mp3->file, mp3->offset, SEEK_SET); fread(buf, 1, 48, mp3->file); mp3->offset += buf[26] + 27; for (i=0; ioffset += buf[27+i]; } } else if (memcmp(buf, "fLaC", 4) == 0) { type = TYPE_FLAC; mp3->offset += 4; memcpy(buf, buf+4, 4); while ((buf[0]&0x80) == 0) { mp3->offset += (((buf[1]&0xff)<<16)| ((buf[2]&0xff)<<8) |(buf[3]&0xff)) + 4; fseek(mp3->file, mp3->offset, SEEK_SET); fread(buf, 1, 4, mp3->file); } mp3->offset += (((buf[1]&0xff)<<16)| ((buf[2]&0xff)<<8) |(buf[3]&0xff)) + 4; } else if (memcmp(buf, "RIFF", 4) == 0) { wave_header *wh; if (openwav(&wh, mp3->filename) == -1){ cleanup(&wh); return -1; } type = TYPE_WAV; mp3->offset = 0; cleanup(&wh); } else { fseek(mp3->file, 0, SEEK_SET); get_mp3_info(mp3); if (mp3->header_isvalid) type = TYPE_MP3; } fclose(mp3->file); return type; } void lk_karma_write_dupes(int set) { write_dupes = set; } libkarma-0.1.2/src/rio_rw.h0000644000175000000120000000051211543330237014702 0ustar frankywheel/* * libkarma/rio_rw.h * * Copyright (c) Frank Zschockelt 2004-2005 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _RIO_RW_H #define _RIO_RW_H uint32_t lk_rio_write_fdb(int rio, const char * filename); #endif /* _RIO_RW_H */ libkarma-0.1.2/src/ssdp.c0000644000175000000120000001106511543330237014352 0ustar frankywheel/* * libkarma/ssdp.c * * Copyright (c) Nicolas Justin+Gregrory Kokanosky 2004 * (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ /* * This file is rudimentary implementation of the * Simple Service Discovery Protocol/1.0, also known * as Universal Plug'n'Play. Ths implementation is based * on the draft v1.03 which can be found at: * http://www.upnp.org/download/draft_cai_ssdp_v1_03.txt * * This feature is enabled by default on the Karma. */ #include #include #include #include #include #include #ifdef __NetBSD__ #include #endif #include #include "lkarma.h" #include "ssdp.h" static int get_host_from_ssdp(char *buffer, char **hostname, uint16_t * port); /* Parse the URL found at the "LOCATION:" entry of * the SSDP reply in 'buffer'. 'hostname' and 'port' * allocated, the caller is responsible to free them. * 'hostname' is guaranteed to be null terminated. * Return 0 on success, -1 otherwise. */ static int get_host_from_ssdp(char *buffer, char **hostname, uint16_t * port) { char *pos1, *pos2; char tmp; if((pos1 = strstr(buffer, "LOCATION:")) == NULL) { return -1; } /* Find http:// */ if((pos1 = index(pos1, '/')) == NULL) return -1; pos1 += 2; /* jump to one char after http:// */ /* search the ':' in "hostname:4444" */ if((pos2 = index(pos1, ':')) == NULL) return -1; tmp = *pos2; *pos2 = '\0'; /*copy the hostname */ if((*hostname = strdup(pos1)) == NULL) return -1; *pos2 = tmp; /* Copy the port number */ /* Set pos2 to the end of the line */ pos1 = pos2 + 1; if((pos2 = index(pos1, '\r')) == NULL) return -1; tmp = *pos2; *pos2 = '\0'; *port = atoi(pos1); *pos2 = tmp; return 0; } /* Call this function if you want automatic discovery * of a Karma on your network. A SSDP:discover is sent * to the multicast address 239.255.255.250:1900, if * a response is received, hostname and port are set * respectivly to the Karma address (may be a hostname * or an IP address), and the port wich listen to the * Pearl protocol. * Return 0 if succeed, or -1 on error. */ int lk_ssdp_discover(char **host, uint16_t * port) { int sock; size_t ret; unsigned int socklen; struct sockaddr_in sockname; struct sockaddr clientsock; struct hostent *hostname; char data[] = "M-SEARCH * HTTP/1.1\r\n" "Host: 239.255.255.250:1900\r\n" "Man: \"ssdp:discover\"\r\n" "ST: urn:empeg-com:protocol2\r\n" "MX: 3\r\n" "\r\n"; char buffer[RESPONSE_BUFFER_LEN]; unsigned int len = RESPONSE_BUFFER_LEN; fd_set fds; struct timeval timeout; hostname = gethostbyname(SSDP_MULTICAST); hostname->h_addrtype = AF_INET; if((sock = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { lk_errors_set(E_SOCKET); /*err: socket() failed */ return -1; } memset((char *)&sockname, 0, sizeof(struct sockaddr_in)); sockname.sin_family = AF_INET; sockname.sin_port = htons(SSDP_PORT); sockname.sin_addr.s_addr = *((unsigned long *)(hostname->h_addr_list[0])); ret = sendto(sock, data, strlen(data), 0, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)); if(ret != strlen(data)) { lk_errors_set(E_SENDTO); /*err: sendto() failed */ return -1; } /* Get response */ FD_ZERO(&fds); FD_SET(sock, &fds); timeout.tv_sec = 3; timeout.tv_usec = 0; if(select(sock + 1, &fds, NULL, NULL, &timeout) < 0) { lk_errors_set(E_SELECT); return -1; } if(FD_ISSET(sock, &fds)) { socklen = sizeof(clientsock); if((len = recvfrom(sock, buffer, len, MSG_PEEK, &clientsock, &socklen)) == (size_t) - 1) { lk_errors_set(E_RECVFROM); /*err: recvfrom() failed */ return -1; } buffer[len-1] = '\0'; close(sock); /* Check the HTTP response code */ if(strncmp(buffer, "HTTP/1.1 200 OK", 12) != 0) { lk_errors_set(E_SSDPPARSE);/*err: ssdp parsing failed */ return -1; } if(get_host_from_ssdp(buffer, host, port) == -1) { lk_errors_set(E_SSDPPARSE);/*err: ssdp parsing failed */ return -1; } return 0; } else { lk_errors_set(E_NOSSDP); /*err: no ssdp answer */ return -1; } } libkarma-0.1.2/src/ssdp.h0000644000175000000120000000065511543330237014362 0ustar frankywheel/* * libkarma/ssdp.h * * Copyright (c) Nicolas Justin+Gregrory Kokanosky 2004 * (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _SSDP_H #define _SSDP_H #define RESPONSE_BUFFER_LEN 1024 #define SSDP_MULTICAST "239.255.255.250" #define SSDP_PORT 1900 #endif /* _SSDP_H */ libkarma-0.1.2/src/utf8.c0000644000175000000120000000431611543330237014270 0ustar frankywheel#include #include #include #include #include "lkarma.h" struct utf8{ iconv_t in; iconv_t out; char * charset; }; static struct utf8 utf={(iconv_t)-1, (iconv_t)-1, NULL}; void utf8_destroy(void) { free(utf.charset); iconv_close(utf.in); iconv_close(utf.out); utf.in=utf.out=(iconv_t)-1; } int utf8_set_codeset(char * codeset) { if(utf.in != (iconv_t)(-1)) { iconv_close(utf.in); utf.in = (iconv_t)(-1); } if(utf.out != (iconv_t)(-1)) { iconv_close(utf.out); utf.out = (iconv_t)(-1); } if(utf.charset) free(utf.charset); utf.charset=strdup(codeset); utf.in=iconv_open("UTF-8", codeset); utf.out=iconv_open(codeset, "UTF-8"); if ((utf.in == (iconv_t)-1) || (utf.out == (iconv_t)-1)) { lk_errors_set(E_ICONVO); free(utf.charset); return -1; } return 0; } char * utf8_get_codeset(void) { return utf.charset; } char * utf8_from_codeset(char * data) { char *ivalue, *auxdata, *auxvalue; size_t insz, outsz, nconv; if (data == NULL) return NULL; auxdata = data; insz = strlen(auxdata); outsz = 2 * insz; ivalue = (char *)malloc(outsz+1); ivalue[0] = '\0'; auxvalue = ivalue; nconv = iconv(utf.in, &auxdata, &insz, &auxvalue, &outsz); auxdata = data; /* *auxdata has been modified by iconv ... */ if (nconv == (size_t)-1) { lk_errors_set(E_ICONV); ivalue=strdup(data); } else auxvalue[0] = '\0'; ivalue = realloc(ivalue, strlen(ivalue)+1); return ivalue; } char * utf8_to_codeset(char * data) { char *ivalue, *auxdata, *auxvalue; size_t insz, outsz, nconv; if (data == NULL) return NULL; auxdata=data; insz = strlen(auxdata); outsz = 2 * insz; ivalue = (char *)malloc(outsz+1); ivalue[0] = '\0'; auxvalue = ivalue; nconv = iconv(utf.out, &auxdata, &insz, &auxvalue, &outsz); auxdata = data; /* *auxdata has been modified by iconv ... */ if (nconv == (size_t)-1) { lk_errors_set(E_ICONV); ivalue=strdup(data); } else auxvalue[0] = '\0'; ivalue = realloc(ivalue, strlen(ivalue)+1); return ivalue; } libkarma-0.1.2/src/utf8.h0000644000175000000120000000040011543330237014263 0ustar frankywheel/* * libkarma/utf8.h * * Copyright (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _UTF8_H #define _UTF8_H #endif /* _UTF8_H */ libkarma-0.1.2/src/util.c0000644000175000000120000001462511543330237014363 0ustar frankywheel/* * libkarma/util.c * * Copyright (c) Frank Zschockelt 2004 * * char *simple_itoa was borrowed from boa [http://www.boa.org] * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include #include #include #include #include #include #ifdef __linux__ #include #endif #ifdef __APPLE__ # define __BIG_ENDIAN __BIG_ENDIAN__ # if __LITTLE_ENDIAN__ # define __BYTE_ORDER __LITTLE_ENDIAN__ # else # define __BYTE_ORDER __BIG_ENDIAN # endif #endif #ifdef __NetBSD__ #include #define __BYTE_ORDER _BYTE_ORDER #define __BIG_ENDIAN _BIG_ENDIAN #endif #include "lkarma.h" #include "md5.h" #include "util.h" #include "properties.h" /*copied from the boa webserver*/ char *simple_itoa(unsigned int i) { /* 21 digits plus null terminator, good for 64-bit or smaller ints * for bigger ints, use a bigger buffer! * * 4294967295 is, incidentally, MAX_UINT (on 32bit systems at this time) * and is 10 bytes long */ static char local[22]; char *p = &local[21]; *p-- = '\0'; do{ *p-- = '0' + i%10; i/=10; }while(i>0); return p+1; } /* returns a string for $HOME/.openrio/pearl-$serial/$*fname */ char * lk_path_string(char * file) { int len; char * str, * home; home=strdup(getenv("HOME")); /*24=strlen("/.openrio/pearl-0123456/")*/ len=strlen(home)+24+strlen(file)+1; str=malloc(len); snprintf(str, len, "%s/.openrio/pearl-%d/%s", home, serial, file); /*cut the leading zeros*/ return str; } /* Recursively create directories in a path. The last element is assumed to be a filename, and simply ignored. Code based on create_bittorrent_path() */ int mk_path(const char *pathname) { int pos, ret; char *path; unsigned char separator; path=strdup(pathname); if (!*path) return -1; for (pos = 1; path[pos]; pos++) { separator = path[pos]; if (separator != '/') continue; path[pos] = 0; ret = mkdir(path, 0700); /*S_IREAD | S_IWRITE | S_IEXEC);*/ path[pos] = separator; if (ret < 0 && errno != EEXIST){ free(path); lk_errors_set(E_MKDIR); return -1; } } free(path); return 0; } /* ( ((x) & 0xff000000) >> 24) | ((x) & 0x00ff0000) >> 8) | ((x) & 0x0000ff00) << 8) | ((x) & 0x000000ff) << 24) */ uint32_t lk_htorl(uint32_t hostlong) { #if __BYTE_ORDER==__BIG_ENDIAN return (hostlong>>24) | ((hostlong&0xff0000)>>8) | ((hostlong&0xff00)<<8) | (hostlong<<24); #else return hostlong; #endif } uint32_t lk_rtohl(uint32_t hostlong) { return lk_htorl(hostlong); } /* ( (((x) & 0xff00000000000000ull) >> 56) | (((x) & 0x00ff000000000000ull) >> 40) | (((x) & 0x0000ff0000000000ull) >> 24) | (((x) & 0x000000ff00000000ull) >> 8) | (((x) & 0x00000000ff000000ull) << 8) | (((x) & 0x0000000000ff0000ull) << 24) | (((x) & 0x000000000000ff00ull) << 40) | (((x) & 0x00000000000000ffull) << 56)) */ uint64_t lk_htorll(uint64_t hostlong) { #if __BYTE_ORDER==__BIG_ENDIAN return (hostlong>>56) | ((hostlong&0xff000000000000ULL)>>40) | ((hostlong&0xff0000000000ULL)>>24) | ((hostlong&0xff00000000ULL)>>8) | ((hostlong&0xff000000ULL)<<8) | ((hostlong&0xff0000ULL)<<24) | ((hostlong&0xff00ULL)<<40) | (hostlong<<56); #else return hostlong; #endif } uint64_t lk_rtohll(uint64_t hostlong) { return lk_htorll(hostlong); } /* {thanks Cliff L. Biffle...} computes the RID of a file rid algorithm pseudocode: if(length of file <= 64k) return MD5(file); else A = MD5(first 64k); B = MD5(last 64k); C = MD5(64k starting at (length - 64k)/2); return A ^ B ^ C; oggs,flacs: offset=0 length=length of file mp3s: offset=after the tags length=length of file -128 */ #define RID_BLOCKS 65536 unsigned char * lk_generate_rid(int file, int offset, int length) { static unsigned char rid_output[33]; int i; uint32_t size; unsigned char cache[RID_BLOCKS]; unsigned char md5output[16], b_md5[16], c_md5[16]; unsigned char *ret; md5_context ctx; if(lseek(file, offset, SEEK_SET)==-1) return NULL; size=read(file, &cache, RID_BLOCKS); md5_starts(&ctx); if(length-offset < RID_BLOCKS){ md5_update(&ctx, (uint8_t *)&cache, size); md5_finish(&ctx, md5output); }else{ md5_update(&ctx, cache, RID_BLOCKS); md5_finish(&ctx, md5output); lseek(file, length-RID_BLOCKS, SEEK_SET); read(file, &cache, RID_BLOCKS); md5_starts(&ctx); md5_update(&ctx, cache, RID_BLOCKS); md5_finish(&ctx, b_md5); lseek(file, (offset + length - RID_BLOCKS)/2, SEEK_SET); size=read(file, &cache, RID_BLOCKS); md5_starts(&ctx); md5_update(&ctx, cache, size); md5_finish(&ctx, c_md5); for(i=0; i < 16; i++) md5output[i]=md5output[i]^b_md5[i]^c_md5[i]; } for(i=0; i<16;i++){ if((md5output[i]>>4)<10) rid_output[i*2]=(md5output[i]>>4)+'0'; else rid_output[i*2]=(md5output[i]>>4)+87; if((md5output[i]%16)<10) rid_output[i*2+1]=(md5output[i]%16)+'0'; else rid_output[i*2+1]=(md5output[i]%16)+87; } rid_output[32]='\0'; ret=&rid_output[0]; return ret; } int lk_is_karma_mountpoint(const char *mountpoint) { char *str = NULL; int len, ret; struct stat st; len = strlen(mountpoint); str = malloc(len+strlen(RK_SMALLDB)+1); if (!str) return -1; memcpy(str, mountpoint, len); memcpy(str+len, RK_SMALLDB, strlen(RK_SMALLDB)+1); ret = stat(str, &st); if (ret != 0 || S_ISREG(st.st_mode) == 0) { lk_errors_set(E_NOSMALLDB); goto err; } memcpy(str+len, "/fids0", strlen("/fids0")+1); ret = stat(str, &st); if (ret != 0 || S_ISDIR(st.st_mode) == 0) { lk_errors_set(E_NOMOUNT); goto err; } free(str); return 0; err: if (str) free(str); return -1; } libkarma-0.1.2/src/util.h0000644000175000000120000000125011543330237014356 0ustar frankywheel/* * libkarma/util.h * * Copyright (c) Frank Zschockelt 2004 * * char *simple_itoa was borrowed from boa [http://www.boa.org] * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _UTIL_H #define _UTIL_H char *lk_path_string(char * file); int mk_path(const char *pathname); uint32_t lk_htorl(uint32_t hostlong); uint32_t lk_rtohl(uint32_t hostlong); uint64_t lk_htorll(uint64_t hostlong); uint64_t lk_rtohll(uint64_t hostlong); unsigned char *lk_generate_rid(int file, int offset, int length); int lk_is_karma_mountpoint(const char *mountpoint); #endif /* _UTIL_H */ libkarma-0.1.2/src/status.c0000644000175000000120000000104311543330237014717 0ustar frankywheel/* * libkarma/status.c * * Copyright (c) Frank Zschockelt 2005 * * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include "status.h" static status_func * callback = NULL; int lk_status_init(status_func update) { return 0; } int lk_status_setup(const char * in_progress, uint32_t start, uint32_t units) { return 0; } int lk_status_increment(uint32_t step) { return 0; } int lk_status_destroy(void) { return 0; } libkarma-0.1.2/src/status.h0000644000175000000120000000104111543330237014722 0ustar frankywheel/* * libkarma/status.h * * Copyright (c) Frank Zschockelt 2005 * * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _STATUS_H #define _STATUS_H #include typedef void status_func(const char * in_progress,int percent); int lk_status_init(status_func update); int lk_status_setup(const char * in_progress, uint32_t start, uint32_t units); int lk_status_increment(uint32_t step); int lk_status_destroy(void); #endif /* _STATUS_H */ libkarma-0.1.2/src/mountSearch.c0000644000175000000120000000511111543330237015664 0ustar frankywheel/* * libkarma/mountSearch.c * * Copyright (c) Enrique Vidal 2006 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include #include #include #include #include #include #include "lkarma.h" #include "util.h" #define PROC_MOUNTS "/proc/mounts" int fd, ret; char *ini, *fin; static char *read_whole_file(char *filename) { int len = BUFSIZ; char *ptr = NULL; FILE *fp = fopen(filename, "rb"); int size; if (!fp) goto err; ptr = malloc(len); if (!ptr) goto err; while ((size = fread(ptr + len - BUFSIZ, 1, BUFSIZ, fp)) == BUFSIZ) { ptr = realloc(ptr, len + BUFSIZ); if (!ptr) goto err; len += BUFSIZ; } *(ptr + len - BUFSIZ + size) = 0; fclose(fp); err: return ptr; } int lk_mountSearch_discover(char **device, char **mountPoint) { char *buf, *dev, *mountp, *aux; int len, pos, kfd, found=0; buf = read_whole_file(PROC_MOUNTS); if (!buf) { lk_errors_set(E_MFINDERR); return -1; } /* fprintf(stderr, "%s\n\n", buf); */ ini = buf; pos = 0; while ((fin = strstr(ini, "\n"))) { if(fin) { *fin = '\0'; /* fprintf(stderr, "%s\n", ini); */ if(strstr(ini, "omfs")) { dev = ini; aux = strstr(dev, " "); *aux = '\0'; ini = aux + 1; if((mountp = strstr(ini, "/"))) { aux = strstr(mountp, " "); *aux = '\0'; if(((*device = strdup(dev)) == NULL) || ((*mountPoint = strdup(mountp)) == NULL)) { lk_errors_set(E_NOMOUNT); free(buf); return -1; } /* fprintf(stderr, "%s %s\n", *device, *mountPoint); */ if(lk_is_karma_mountpoint(*mountPoint) != 0) { free(*mountPoint); free(*device); *mountPoint=NULL; lk_errors_set(E_NOMOUNT); free(buf); return -1; } found++; } } } ini = fin + 1; } free(buf); if(found != 1) { lk_errors_set((found==0)?E_NOMOUNT:E_MANYMOUNT); return -found-1; } return 0; } libkarma-0.1.2/src/karmaLan.c0000644000175000000120000004257211543330237015136 0ustar frankywheel/* * libkarma/karma.c * * Copyright (c) Frank Zschockelt 2004-2005 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #ifdef __NetBSD__ #include #endif #include #include #include #include #include "lkarma.h" #include "karma.h" #include "karmaLan.h" #include "properties.h" #include "md5.h" #include "util.h" #include "fdb.h" #ifndef MSG_FIN #define MSG_FIN 0 #endif static int busy_handler(int rio, uint32_t waitfor); static uint32_t recv_header(int rio); static int32_t recv_status(int rio); static int32_t recv_properties(int rio, uint32_t identifier, uint32_t r_id, char ** properties); char *lk_karmaLan_fidToPath(int rio, uint32_t file_id) { return NULL; } /* Help-Functions */ int lk_karmaLan_connect(char * ip) { struct hostent *host; struct sockaddr_in dest; int rio; host = gethostbyname(ip); if(host == NULL){ lk_errors_set(E_HOST); return -1; /* err: gethostbyname() failed (see gethostbyname) */ } rio = socket(AF_INET, SOCK_STREAM, 0); if(rio == -1){ lk_errors_set(E_SOCKET); return -1; /* err: socket() failed (see socket) */ } memset(&dest, 0, sizeof(dest)); dest.sin_addr = *(struct in_addr *)host->h_addr_list[0]; dest.sin_family = AF_INET; dest.sin_port = htons(RIOPORT); if(connect(rio, (struct sockaddr *)&dest, sizeof(dest)) == -1){ lk_errors_set(E_CONNECT); return -1; /* err: connect() failed (see connect) */ } else return rio; } int lk_karmaLan_send_request(int rio, uint32_t identifier, char *payload, int plen) { char msg[HEADERLENGTH]; /* protocol signature */ memcpy(msg, RIO_HEADER, 4); /* command number from identifier */ identifier=lk_htorl(identifier); memcpy(&msg[4], &identifier, sizeof(identifier)); if(payload==NULL) send(rio, msg, HEADERLENGTH, MSG_FIN); else{ send(rio, msg, HEADERLENGTH, 0); send(rio, payload, plen, MSG_FIN); } return 0; } /* recv the header of the karma, it'll return -1 if the first part of the header doesn't match with the standard rio header, but if it does, it'll return the command identifier */ static uint32_t recv_header(int rio) { uint32_t h; char sig[4]; size_t n; n = recv(rio, &sig, 4, MSG_WAITALL); if(memcmp(sig, RIO_HEADER, 4)){ lk_errors_set(E_BADHEADER); return -1; /* err: broken Rio Header */ } n = recv(rio, &h, sizeof(h), MSG_WAITALL); return lk_rtohl(h); } /* returns the status as int32_t */ static int32_t recv_status(int rio) { int32_t s; recv(rio, &s, sizeof(s), MSG_WAITALL); return lk_rtohl(s); } /* recv the properties, copies the data to **properties, memory will be allocated by recv_properties, returns -1 if the header doesn't match with identifier or the status indicates an failure. */ static int32_t recv_properties(int rio, uint32_t identifier, uint32_t r_id, char ** properties) { uint64_t i=0; char id[4]; if(r_id > 0){ r_id=lk_htorl(r_id); memcpy(id, &r_id, sizeof(r_id)); lk_karmaLan_send_request(rio, identifier, id, 4); }else lk_karmaLan_send_request(rio, identifier, NULL, 0); *properties=NULL; if(busy_handler(rio, identifier)){ if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1; /* err: failed request */ } }else return -1; /* already set by busy_handler */ do{ if(i%8192==0) *properties=(char *)realloc(*properties, (i+8193)); (*properties)[i+4]='!'; recv(rio, &(*properties)[i], 4, MSG_WAITALL); i+=4; }while((*properties)[i-1]!=0); return 0; } static int busy_handler(int rio, uint32_t waitfor) { uint32_t header; header=recv_header(rio); if(header==BUSY){ do{ recv_status(rio); recv_status(rio); }while((header=recv_header(rio))==BUSY); } if(header==waitfor) return 1; else { lk_errors_set(E_BADHEADER); return 0; } } /* Basic Protocol Functions */ int lk_karmaLan_get_protocol_version(int rio, uint32_t * major_version, uint32_t * minor_version) { char versions[8]; *major_version=lk_htorl(*major_version); *minor_version=lk_htorl(*minor_version); memcpy(versions, major_version, sizeof(major_version)); memcpy(&versions[4], minor_version, sizeof(minor_version)); lk_karmaLan_send_request(rio, 0, versions, 8); if(!busy_handler(rio, GET_PROTOCOL_VERSION)) return -1; /* already set by busy_handler */ recv(rio, major_version, sizeof(uint32_t), 0); recv(rio, minor_version, sizeof(uint32_t), 0); *major_version=lk_rtohl(*major_version); *minor_version=lk_rtohl(*minor_version); return 0; } int32_t lk_karmaLan_get_authentication_salt(int rio, char ** salt) { *salt=(char *)malloc(SALTLENGTH); lk_karmaLan_send_request(rio, GET_AUTHENTICATION_SALT, NULL, 0); if(!busy_handler(rio, GET_AUTHENTICATION_SALT)) return -1; /* already set by busy_handler */ recv(rio, *salt, SALTLENGTH, 0); return 0; } uint32_t lk_karmaLan_authenticate(int rio, char * pass) { md5_context ctx; unsigned char * md5input; unsigned char md5sum[16]; char * salt; uint32_t rights; if(lk_karmaLan_get_authentication_salt(rio, &salt) == -1) return -1; /* get_authenticatoin_salt had set the errormsg */ md5input=(unsigned char *)malloc((strlen(pass)+SALTLENGTH+1)); memcpy(md5input, salt, SALTLENGTH); memcpy(&md5input[SALTLENGTH], pass, strlen(pass)); md5_starts(&ctx); md5_update(&ctx, (uint8_t *)md5input, SALTLENGTH+strlen(pass)); md5_finish(&ctx, md5sum); free(salt); free(md5input); lk_karmaLan_send_request(rio, AUTHENTICATE, (char *)md5sum, 16); if(!busy_handler(rio, AUTHENTICATE)) return -1; /* already set by busy_handler */ recv_status(rio); /* we don't care about the status, because we want to get the rights... */ recv(rio, &rights, sizeof(rights), 0); rights=lk_rtohl(rights); return rights; } int lk_karmaLan_get_device_details(int rio, char **name, char **version, uint32_t * storagedevices) { *name=(char *)malloc(DETAILSLENGTH); *version=(char *)malloc(DETAILSLENGTH); lk_karmaLan_send_request(rio, GET_DEVICE_DETAILS, NULL, 0); if(!busy_handler(rio, GET_DEVICE_DETAILS)) return -1; /* err already set by busy_handler */ recv(rio, *name, DETAILSLENGTH, 0); recv(rio, *version, DETAILSLENGTH, 0); recv(rio, storagedevices, sizeof(uint32_t), 0); *storagedevices=lk_rtohl(*storagedevices); return 0; } int lk_karmaLan_get_storage_details(int rio, uint32_t storage_id, uint32_t *n_files, uint64_t *s_size, uint64_t *f_space, uint32_t *highest_file_id) { char id[4]; storage_id=lk_htorl(storage_id); memcpy(id, &storage_id, sizeof(storage_id)); lk_karmaLan_send_request(rio, GET_STORAGE_DETAILS, id, sizeof(uint32_t)); if(!busy_handler(rio, GET_STORAGE_DETAILS)) return -1; /* err already set by busy_handler */ if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1; /* err: failed request */ } recv(rio, n_files, sizeof(uint32_t), 0); recv(rio, s_size, sizeof(uint64_t), 0); recv(rio, f_space, sizeof(uint64_t), 0); recv(rio, highest_file_id, sizeof(uint32_t), 0); *n_files=lk_rtohl(*n_files); *s_size=lk_rtohll(*s_size); *f_space=lk_rtohll(*f_space); *highest_file_id=lk_rtohl(*highest_file_id); return 0; } int lk_karmaLan_get_device_settings(int rio) { int ret; char *settings; recv_properties(rio, GET_DEVICE_SETTINGS, 0, &settings); if (settings == NULL) return -1; ret = lk_karma_parse_settings(settings); free(settings); return ret; } int32_t lk_karmaLan_update_device_settings(int rio, char * properties) { int len; len=strlen(properties); while(len%4) ++len; lk_karmaLan_send_request(rio, UPDATE_DEVICE_SETTINGS, properties, len); if(busy_handler(rio, UPDATE_DEVICE_SETTINGS)){ if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1; /* err: failed request */ }else return 0; } else return -1; /* already set by busy_handler */ } int32_t lk_karmaLan_request_io_lock(int rio, uint32_t type) { /* unused: int status; */ char p[4]; type=lk_htorl(type); memcpy(p, &type, sizeof(type)); lk_karmaLan_send_request(rio, REQUEST_IO_LOCK, p, 4); if(busy_handler(rio, REQUEST_IO_LOCK)) if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1; /* err: failed request */ }else return 0; else return -1; /* already set by busy_handler */ } int32_t lk_karmaLan_release_io_lock(int rio) { lk_karmaLan_send_request(rio, RELEASE_IO_LOCK, NULL, 0); if(busy_handler(rio, RELEASE_IO_LOCK)){ if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1; /* err: failed request */ }else return 0; } else return -1; /* already set by busy_handler */ } /*Not yet supported by the Rio Karma.*/ int32_t lk_karmaLan_prepare(int rio, uint64_t size, uint32_t *file_id, uint32_t storage_id) { char p[16]; size=lk_htorl(size); *file_id=lk_htorl(*file_id); storage_id=lk_htorl(storage_id); memcpy(p, &size, sizeof(size)); memcpy(&(p[4]), file_id, sizeof(file_id)); memcpy(&(p[12]), &storage_id, sizeof(storage_id)); lk_karmaLan_send_request(rio, PREPARE, p, 16); if(!busy_handler(rio, PREPARE)) return -1; /* already set by busy_handler */ recv(rio, file_id, sizeof(file_id), 0); *file_id=lk_rtohl(*file_id); if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1; /* err: failed request */ }else return 0; } int32_t lk_karmaLan_write_file_chunk(int rio, uint64_t offset, uint64_t size, uint32_t file_id, uint32_t storage_id, const char *data) { char * packet; uint64_t align_diff = ( (size % 4) ? 4 - (size % 4) : 0 ); uint64_t aligned_size = size + align_diff; packet=malloc(sizeof(uint64_t)*3 + aligned_size); offset=lk_htorll(offset); size=lk_htorll(size); file_id=lk_htorl(file_id); storage_id=lk_htorl(storage_id); memcpy(packet, &offset, sizeof(offset)); memcpy(&packet[8], &size, sizeof(size)); size=lk_rtohll(size); memcpy(&packet[16], &file_id, sizeof(file_id)); memcpy(&packet[20], &storage_id, sizeof(storage_id)); memcpy(&packet[24], data, size); if (align_diff) memset(&packet[24+size], 0, align_diff); lk_karmaLan_send_request(rio, WRITE_FILE_CHUNK, packet, aligned_size + sizeof(uint64_t)*3); free(packet); if(busy_handler(rio, WRITE_FILE_CHUNK)){ if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1; /* err: failed request */ }else return 0; } else return -1; /* already set by busy_handler */ } int32_t lk_karmaLan_get_all_file_details(int rio, char ** properties) { return recv_properties(rio, GET_ALL_FILE_DETAILS, 0, properties); } int32_t lk_karmaLan_get_file_details(int rio, uint32_t file_id, char **properties) { return recv_properties(rio, GET_FILE_DETAILS, file_id, properties); } int32_t lk_karmaLan_update_file_details(int rio, uint32_t file_id, char *properties) { char * packet; /* unused *tmp; */ int len,rlen; rlen=strlen(properties); len=rlen; ++len; while(len%4) ++len; packet=malloc(sizeof(uint32_t)+len); file_id=lk_htorl(file_id); memcpy(packet, &file_id, sizeof(file_id)); memcpy(&packet[4], properties, len); memset(&packet[rlen+sizeof(uint32_t)], 0, len-rlen); lk_karmaLan_send_request(rio, UPDATE_FILE_DETAILS, packet, len+sizeof(uint32_t)); free(packet); if(busy_handler(rio, UPDATE_FILE_DETAILS)){ lk_properties_inc_devgeneration(); if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1; /* err: failed request */ }else return 0; }else return -1; /* already set by busy_handler */ } int32_t lk_karmaLan_read_file_chunk(int rio, uint64_t offset, uint64_t size, uint32_t file_id, char ** data, uint64_t * retsize) { /* Warning: except for the last call, "size" must be a multiple of 4 */ char p[20]; uint64_t realsize; int r; *retsize=0; offset=lk_htorll(offset); size=lk_htorll(size); file_id=lk_htorl(file_id); memcpy(&p, &offset, sizeof(offset)); memcpy(&p[8], &size, sizeof(size)); memcpy(&p[16], &file_id, sizeof(file_id)); lk_karmaLan_send_request(rio, READ_FILE_CHUNK, p, 20); if(!busy_handler(rio, READ_FILE_CHUNK)) return -1; /* already set by busy_handler */ recv(rio, &realsize, sizeof(uint64_t), 0); realsize=lk_rtohll(realsize); r = realsize%4; /* division reminder */ realsize = realsize + (r?(4-r):0); /* padding to multiple of 4 bytes */ *data=(char *)malloc(realsize+1); if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1; } *retsize=recv(rio, *data, realsize, MSG_WAITALL); if (r) *retsize -= (4-r); /* return the unpadded chunk size */ if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1; /* err: failed request */ }else return 0; } int32_t lk_karmaLan_delete_file(int rio, uint32_t file_id) { int ret = 0; char id[4]; file_id=lk_htorl(file_id); memcpy(id, &file_id, sizeof(file_id)); lk_karmaLan_send_request(rio, DELETE_FILE, id, 4); if(busy_handler(rio, DELETE_FILE)){ lk_properties_inc_devgeneration(); if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); ret = -1; /* err: failed request */ } /* else ret = 0; */ } else ret = -1; /* already set by busy_handler */ if(!ret) lk_properties_del_property(file_id); return ret; } /* Now, that command would be scary ;) (It's not supported by the rio karma ;)) */ int32_t lk_karmaLan_format_storage(int rio, uint32_t storage_id) { char id[4]; storage_id=lk_htorl(storage_id); memcpy(id, &storage_id, sizeof(storage_id)); lk_karmaLan_send_request(rio, FORMAT_STORAGE, id, 4); if(busy_handler(rio, FORMAT_STORAGE)){ if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1;/* err: failed request */ }else return 0; } else return -1; /* already set by busy_handler */ } int32_t lk_karmaLan_hangup(int rio) { lk_karmaLan_send_request(rio, HANGUP, NULL, 0); if(busy_handler(rio, HANGUP)){ if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1;/* err: failed request */ }else return 0; }else return -1; /* already set by busy_handler */ } /*Not yet supported by the Rio Karma.*/ char blubb[]="I shot the ipod, but I didn't shoot no deputy, oh no! oh!"; int32_t lk_karmaLan_device_operation(int rio, uint64_t size, char *data, char **newdata) { char * d; d=malloc(sizeof(char)*sizeof(uint64_t)+sizeof(char)*size); size=lk_htorll(size); memcpy(d, &size, sizeof(size)); size=lk_rtohll(size); memcpy(&d[8], data, size); lk_karmaLan_send_request(rio, DEVICE_OPERATION, d, size+sizeof(uint64_t)); if(!busy_handler(rio, DEVICE_OPERATION)) return -1; /* already set by busy_handler */ recv(rio, &size, sizeof(uint64_t), 0); size=lk_rtohll(size); if(recv_status(rio) != 0){ lk_errors_set(E_FAILEDREQ); return -1; /* err: failed request */ } *newdata=realloc(*newdata, size); recv(rio, *newdata, size, MSG_WAITALL); return 0; } /* -------------------------------------------------------------------------- */ int lk_karmaLan_write_smalldb(void) { return 0; } /* Advanced Protocol Functions */ void lk_karmaLan_load_database(int rio) { char *settings; lk_karmaLan_get_device_settings(rio); if(lk_properties_cache_obsolete()){ /* DB was changed */ lk_karmaLan_get_all_file_details(rio, &settings); lk_properties_import(settings); free(settings); lk_fdb_load(1); }else{ lk_properties_load(); lk_fdb_load(0); } } void lk_karmaLan_update_database(int rio) { char *settings; uint32_t old = device_generation; lk_karmaLan_get_device_settings(rio); if(device_generation != old){ /* DB was changed */ lk_properties_destroy(); lk_properties_init(); lk_karmaLan_get_all_file_details(rio, &settings); lk_properties_import(settings); free(settings); } } libkarma-0.1.2/src/karmaLan.h0000644000175000000120000001005011543330237015125 0ustar frankywheel/* * libkarma/karma.h * * Copyright (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _KARMA_LAN_H #define _KARMA_LAN_H #include #define RIOPORT 8302 #define HEADERLENGTH 8 #define SALTLENGTH 16 #define DETAILSLENGTH 32 #define RIO_HEADER "\x52\x69\xC5\x8D" /* Ri~o */ #define GET_PROTOCOL_VERSION 0 #define NAK 1 #define BUSY 2 #define GET_AUTHENTICATION_SALT 3 #define AUTHENTICATE 4 #define GET_DEVICE_DETAILS 5 #define GET_STORAGE_DETAILS 6 #define GET_DEVICE_SETTINGS 7 #define UPDATE_DEVICE_SETTINGS 8 #define REQUEST_IO_LOCK 9 #define RELEASE_IO_LOCK 10 #define PREPARE 11 #define WRITE_FILE_CHUNK 12 #define GET_ALL_FILE_DETAILS 13 #define GET_FILE_DETAILS 14 #define UPDATE_FILE_DETAILS 15 #define READ_FILE_CHUNK 16 #define DELETE_FILE 17 #define FORMAT_STORAGE 18 #define HANGUP 19 #define DEVICE_OPERATION 20 char *lk_karmaLan_fidToPath(int rio, uint32_t file_id); /*Help-Functions:*/ int lk_karmaLan_connect (char *ip); int lk_karmaLan_send_request (int rio, uint32_t identifier, char *payload, int plen); /*Basic Protocol Functions*/ int lk_karmaLan_get_protocol_version (int rio, uint32_t *major_version, uint32_t *minor_version); int32_t lk_karmaLan_get_authentication_salt(int rio, char **salt); uint32_t lk_karmaLan_authenticate (int rio, char *pass); int lk_karmaLan_get_device_details (int rio, char **name, char **version, uint32_t *storagedevices); int lk_karmaLan_get_storage_details (int rio, uint32_t storage_id, uint32_t *n_files, uint64_t *s_size, uint64_t *f_space, uint32_t *highest_file_id); int lk_karmaLan_get_device_settings (int rio); int32_t lk_karmaLan_update_device_settings (int rio, char *properties); int32_t lk_karmaLan_request_io_lock (int rio, uint32_t type); int32_t lk_karmaLan_release_io_lock (int rio); int32_t lk_karmaLan_prepare (int rio, uint64_t size, uint32_t *file_id, uint32_t storage_id); int32_t lk_karmaLan_write_file_chunk (int rio, uint64_t offset, uint64_t size, uint32_t file_id, uint32_t storage_id, const char *data); int32_t lk_karmaLan_get_all_file_details (int rio, char **properties); int32_t lk_karmaLan_get_file_details (int rio, uint32_t file_id, char **properties); int32_t lk_karmaLan_update_file_details (int rio, uint32_t file_id, char *properties); int32_t lk_karmaLan_read_file_chunk (int rio, uint64_t offset, uint64_t size, uint32_t file_id, char **data, uint64_t *retsize); int32_t lk_karmaLan_delete_file (int rio, uint32_t file_id); int32_t lk_karmaLan_format_storage (int rio, uint32_t storage_id); int32_t lk_karmaLan_hangup (int rio); int32_t lk_karmaLan_device_operation (int rio, uint64_t size, char *data, char **newdata); int lk_karmaLan_write_smalldb (void); /*Advanced Protocol Functions:*/ void lk_karmaLan_load_database (int rio); void lk_karmaLan_update_database (int rio); #endif /* _KARMA_LAN_H */ libkarma-0.1.2/src/karmaUsb.c0000644000175000000120000007155311543330237015156 0ustar frankywheel/* * libkarma/karma.c * * Copyright (c) Frank Zschockelt 2004-2005 * Copyright (c) Enrique Vidal 2006 * Copyright (c) Keith Bennett 2006 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. */ #ifndef __APPLE__ #define _XOPEN_SOURCE 500 /* Needed by pread/pwrite */ #endif #include #include #include #include #include #include #include #include #include #include #include #ifdef __APPLE__ #include #else #include #include /* or */ #endif #include "lkarma.h" #include "karma.h" #include "karmaUsb.h" #include "properties.h" #include "playlist.h" #include "md5.h" #include "util.h" #include "fdb.h" #ifndef MSG_FIN #define MSG_FIN 0 #endif char *usbMountPoint = NULL; static karma_db_t *db = NULL; /* -------------------------------------------------------------------------- */ /* Auxiliary Function */ /* -------------------------------------------------------------------------- */ char *lk_karmaUsb_fidToPath(int rio, uint32_t file_id) { int i, len; char *path = NULL; len = strlen(usbMountPoint) + 17; path = malloc(len); sprintf(path, "%sfids0/_%.8x", usbMountPoint, file_id); len = strlen(path); for (i = len; i >= len - 3; i--) path[i + 1] = path[i]; path[len - 3] = '/'; return path; } /* -------------------------------------------------------------------------- */ /* Basic Protocol Functions */ /* -------------------------------------------------------------------------- */ int lk_karmaUsb_connect(char *path) { /* ******************** Implemented OMFS mount here ?? ********************** */ /* The path must be absolute to be accesible in lkarmafs; e.g.: /mnt/karma2/ */ int len = strlen(path); char *fname; struct utimbuf time; int ret = 0; usbMountPoint = malloc(len + 2); strcpy(usbMountPoint, path); if(path[len - 1] != '/') strcat(usbMountPoint, "/"); lk_karmaUsb_get_device_settings(0); time.modtime=0; fname=lk_path_string("fileinfo"); if(utime(fname, &time)==-1){ free(fname); lk_errors_set(E_UTIME); } return ret; } /* -------------------------------------------------------------------------- */ int32_t lk_karmaUsb_hangup(int rio) { /* ********************* Implemented OMFS umount here ?? ******************** */ if (db) { if (db->attribs) { uint32_t i; for (i = 0; i < db->num_attribs; i++) if (db->attribs[i].name) free(db->attribs[i].name); free(db->attribs); } free(db); } if (usbMountPoint) free(usbMountPoint); return 0; } /* -------------------------------------------------------------------------- */ uint32_t lk_karmaUsb_authenticate(int rio, char *pass) { return 0; } /* -------------------------------------------------------------------------- */ int lk_karmaUsb_get_storage_details(int rio, uint32_t storage_id, uint32_t * n_files, uint64_t * s_size, uint64_t * f_space, uint32_t * highest_file_id) { int aux; struct statfs buf; aux = statfs(usbMountPoint, &buf); /*perror("+++statfs"); */ if(aux == -1) { lk_errors_set(E_NOMOUNT); return -1; } *n_files = buf.f_files; *s_size = buf.f_bsize * (uint64_t) buf.f_blocks; *f_space = buf.f_bsize * (uint64_t) buf.f_bfree; *highest_file_id = buf.f_files; return 0; /* copied from my test karma */ /* static uint32_t files = 0, hfid = 372613120; */ /* static uint64_t size = 19453096, space = 17141096; // 1024-byte blocks */ /* *n_files = lk_htorl(files); *highest_file_id = lk_htorl(hfid); */ /* *s_size = lk_htorll(1024*size); *f_space = lk_htorll(1024*space); */ } /* -------------------------------------------------------------------------- */ int lk_karmaUsb_get_device_settings(int rio) { #define DEVICE_SETTINGS_FILE "device_settings" #define MIN_DEV_SET_LENGTH 256 /* typical lengths are > 350 */ static char buf[512]; static uint32_t cached_device_generation = 0; static int32_t cached_serial = -1; int fd, ret = 0; char path[1024]=""; if (cached_serial == -1) { ret = strlen(usbMountPoint); strncat(path, usbMountPoint, 1024); strncat(path+ret, DEVICE_SETTINGS_FILE, 1024-ret); fd = open(path, O_RDONLY); if(fd != -1) ret = read(fd, buf, 512); close(fd); if(ret < MIN_DEV_SET_LENGTH) { lk_errors_set(E_NODEVSET); cached_device_generation = 0; cached_serial = 0; } else { lk_karma_parse_settings(buf); cached_device_generation = device_generation; cached_serial = serial; } } device_generation = cached_device_generation; serial = cached_serial; return 0; } /* -------------------------------------------------------------------------- */ int32_t lk_karmaUsb_request_io_lock(int rio, uint32_t type) { /* ****************************** UNNEEDED ********************************** */ return 0; } int32_t lk_karmaUsb_release_io_lock(int rio) { /* ****************************** UNNEEDED ********************************** */ return 0; } /* smalldb helpers */ static int read32(FILE * fp, uint32_t * dest) { int count = fread(dest, sizeof(uint32_t), 1, fp); *dest = lk_rtohl(*dest); return count == 1; } static int read16(FILE * fp, uint32_t * dest) { uint16_t tmp; int count = fread(&tmp, sizeof(uint16_t), 1, fp); *dest = tmp; return count == 1; } static int read8(FILE * fp, uint32_t * dest) { uint8_t tmp; int count = fread(&tmp, sizeof(uint8_t), 1, fp); *dest = tmp; return count == 1; } static int is_deleted(karma_db_t * db, uint32_t index) { if((index >> 3) >= db->dmap_size) return 0; return db->dmap[index >> 3] & (1 << (index % 8)); } static int read_attribute(FILE * fp, smalldb_attrib_t * attrib, char **prop_strs, int nfiles, size_t * allocated_size) { int i; uint32_t otmpnum, tmpnum; char buf[BUFSIZ] = ""; smalldb_type_t type = attrib->type; size_t needed_size; char *table = NULL; uint32_t table_len = 0; int ret = 0; long ptr, end_ptr = 0; buf[sizeof(buf) - 1] = 0; ptr = ftell(fp); if(type == SDB_STRING) { if(!read32(fp, &table_len)) goto err; ptr = ftell(fp); fseek(fp, 4 * nfiles, SEEK_CUR); } else if(type == SDB_BLOB) { ptr = ftell(fp); fseek(fp, 4 * nfiles, SEEK_CUR); if(!read32(fp, &table_len)) goto err; } if(type == SDB_BLOB || type == SDB_STRING) { if(table_len > 0) { table = malloc(table_len); if(!table) goto err; if(fread(table, 1, table_len, fp) != table_len) goto err; } end_ptr = ftell(fp); fseek(fp, ptr, SEEK_SET); if(type == SDB_BLOB) { if(!read32(fp, &otmpnum)) goto err; } } for (i = 0; i < nfiles; i++) { switch (type) { case SDB_LE32: case SDB_BLOB: case SDB_STRING: if(!read32(fp, &tmpnum)) goto err; break; case SDB_LE16: if(!read16(fp, &tmpnum)) goto err; break; case SDB_CHAR: if(!read8(fp, &tmpnum)) goto err; break; } if(type != SDB_BLOB && type != SDB_STRING) { snprintf(buf, sizeof(buf) - 2, "%s=%d\n", attrib->name, tmpnum); } else if(type == SDB_STRING && table) { char *v = &table[tmpnum]; if(v) snprintf(buf, sizeof(buf) - 2, "%s=%s\n", attrib->name, v); } else if(type == SDB_BLOB && table) { int len; char *v; if(i == nfiles - 1) len = table_len - otmpnum; else len = tmpnum - otmpnum; v = lk_playlist_escape(&table[otmpnum], len); if(v) { snprintf(buf, sizeof(buf) - 2, "%s=%s\n", attrib->name, v); free(v); } otmpnum = tmpnum; } if(strlen(buf) == 0) snprintf(buf, sizeof(buf) - 2, "%s=\n", attrib->name); if(!prop_strs[i]) { needed_size = strlen(buf) + 1; while(needed_size > *allocated_size) *allocated_size *= 2; prop_strs[i] = calloc(*allocated_size, 1); if(!prop_strs[i]) goto err; } needed_size = strlen(prop_strs[i]) + strlen(buf) + 1; if(needed_size > *allocated_size) { while(needed_size > *allocated_size) *allocated_size *= 2; prop_strs[i] = realloc(prop_strs[i], *allocated_size); if(!prop_strs[i]) goto err; } strcat(prop_strs[i], buf); } if(end_ptr > ptr) fseek(fp, end_ptr, SEEK_SET); ret = 1; err: if(table) free(table); return ret; } /* -------------------------------------------------------------------------- */ /* Essential Functions */ /* -------------------------------------------------------------------------- */ static int read_file_info(char *fname, char *path, int *offset, int *tlen, char **properties) { int oneFile, zeroFile; int got, ret, len, k; char realFile[1024], fidLine[32], *aux; struct stat statbuf; char *str; uint32_t fid; len = strlen(path); if (len < 1024) { memcpy(realFile, path, len); k = strlen(fname); if (len+k+1 < 1024) memcpy(realFile+len, fname, k+1); } /* fprintf(stderr, "--> %s\n", realFile); */ realFile[strlen(realFile) - 1] = '1'; oneFile = open(realFile, O_RDONLY); if(oneFile == -1) { /* fprintf(stderr,"\nWarning: wrong file (%s)\n", realFile); */ lk_errors_set(E_NOPROP); return 1; } ret = fstat(oneFile, &statbuf); if(ret != 0) { lk_errors_set(E_NOPROP); return 1; } len = statbuf.st_size + 34; if(*tlen < len + *offset) { while(*tlen < len + *offset) *tlen += 1024; *properties = realloc(*properties, *tlen); } strncpy(fidLine, rindex(path, '_') + 1, 16); fidLine[strlen(fidLine) - 1] = '\0'; strncat(fidLine, fname, 16 - strlen(fidLine)); fid = strtol(fidLine, NULL, 16); /* fprintf(stderr,"%s %5d, %4d %7d, ", fidLine, fid, *numFiles, *offset); */ sprintf(fidLine, "fid=%d\n", fid); aux = strcpy(*properties + *offset, fidLine); *offset += strlen(fidLine); got = read(oneFile, *properties + *offset, len); /* fprintf(stderr,"%3d %d\n", got, strlen(*properties)); */ for (k = 0; k < got; k++) /* illegal null bytes are converted to ' ' */ if(*(*properties + *offset + k) == 0) *(*properties + *offset + k) = ' '; if(got == -1 || got > len - 2) { lk_errors_set(E_FAILEDREQ); } /* fprintf(stderr, "\n%s\n-------\n", *properties+*offset); */ *offset += got; if(strstr(*properties + *offset - got, "type=playlist") != NULL) { realFile[strlen(realFile) - 1] = '0'; zeroFile = open(realFile, O_RDONLY); if(zeroFile == -1) { lk_errors_set(E_NOPROP); return 1; } ret = fstat(zeroFile, &statbuf); if(ret != 0) { lk_errors_set(E_NOPROP); return 1; } len = 4 * statbuf.st_size + strlen("playlist=\n"); if(*tlen < len + *offset) { while(*tlen < len + *offset) *tlen += 1024; *properties = realloc(*properties, *tlen); } strncpy(*properties + *offset, "playlist=", len); *offset += strlen("playlist="); got = read(zeroFile, (*properties + *offset), len); close(zeroFile); str = lk_playlist_escape(*properties + *offset, got); got = strlen(str); memcpy(*properties + *offset, str, got); free(str); if(got == -1 || got > len - 2) { lk_errors_set(E_FAILEDREQ); } *offset += got; *(*properties + *offset) = '\n'; (*offset)++; } *(*properties + *offset) = '\n'; (*offset)++; close(oneFile); return 0; } static int32_t read_properties(char **properties) { DIR *dp0, *dp; struct dirent *de0, *de; char path1[1024] = "", path[1024] = ""; int numFiles = 0, offset = 0, tlen = 0, ret; strncpy(path1, usbMountPoint, 1023 - strlen("/fids0/_00000/100")); strcat(path1, "/fids0/"); dp0 = opendir(path1); if(!dp0) { mk_path(path1); dp0 = opendir(path1); if (!dp0) { lk_errors_set(E_NODIR); return -1; } } while((de0 = readdir(dp0)) != NULL) { if(strncmp(de0->d_name, "_0", 2) != 0) continue; strcpy(path, path1); strcat(path, de0->d_name); strcat(path, "/"); dp = opendir(path); if(dp == NULL) { lk_errors_set(E_NODIR); return -1; } while((de = readdir(dp)) != NULL) { if((strcmp(de->d_name, ".")) && (strcmp(de->d_name, "..")) && de->d_name[strlen(de->d_name) - 1] == '0') { ret = read_file_info(de->d_name, path, &offset, &tlen, properties); if (!ret) numFiles++; /* fprintf(stderr, "\rReading: %3d files. Please wait... ", numFiles); */ } } closedir(dp); } closedir(dp0); if(*properties) *(*properties + offset) = '\0'; else { lk_errors_set(E_FAILEDREQ); return -1; } /* fprintf(stderr, "------------------------------\n%s\n", *properties); */ return 0; } static void scan_playlist(uint32_t id, uint32_t * nfiles, size_t * allocated_size, char **prop_strs) { playlist_t *pl = &db->playlists[id]; char *ptr = pl->playlist; char *str, *prop; char buf[BUFSIZ] = ""; uint32_t i, tmp32, fid, idx; uint16_t tmp16; char tmp8; size_t len = 0, plen = 1; int tmpnum; if(!ptr) return; idx = pl->index; if(!prop_strs[idx]) { prop_strs[idx] = calloc(*allocated_size, 1); if(!prop_strs[idx]) goto err; } prop = prop_strs[idx]; if(idx < *nfiles) { for (str = prop + 4; *str && *str != '\n'; str++) ; *str = '\0'; fid = (uint32_t) atol(prop + 4); memcpy(&tmp32, ptr, sizeof(tmp32)); if(fid != tmp32) fprintf(stderr, "error: fids do not match\n"); } else *nfiles = idx + 1; for (i = 0; i < db->num_attribs; i++) { str = NULL; switch (db->attribs[i].type) { case SDB_STRING: str = ptr; if(str) snprintf(buf, sizeof(buf) - 2, "%s=%s\n", db->attribs[i].name, str); else *buf = '\0'; ptr += strlen(str) + 1; if(memcmp(db->attribs[i].name, "rid", 3) == 0) ptr = pl->playlist + pl->len - (db->num_attribs - i - 1) * sizeof(tmp32); break; case SDB_BLOB: memcpy(&tmp32, ptr, sizeof(tmp32)); ptr += sizeof(tmp32); str = lk_playlist_escape(ptr, tmp32); if(str) { snprintf(buf, sizeof(buf) - 2, "%s=%s\n", db->attribs[i].name, str); free(str); } else *buf = '\0'; ptr += tmp32; tmpnum = tmp32; break; case SDB_LE32: memcpy(&tmp32, ptr, sizeof(tmp32)); ptr += sizeof(tmp32); len += sizeof(tmp32); tmpnum = tmp32; break; case SDB_LE16: memcpy(&tmp16, ptr, sizeof(tmp16)); ptr += sizeof(tmp16); len += sizeof(tmp16); tmpnum = tmp16; break; case SDB_CHAR: memcpy(&tmp8, ptr, sizeof(tmp8)); ptr += sizeof(tmp8); len += sizeof(tmp8); if(memcmp(db->attribs[i].name, "marked", 6) == 0) ptr += sizeof(tmp8); tmpnum = tmp8; break; } if(!str) snprintf(buf, sizeof(buf) - 2, "%s=%d\n", db->attribs[i].name, tmpnum); len = strlen(buf); plen += len; if(plen > *allocated_size) { while(plen > *allocated_size) *allocated_size *= 2; prop_strs[idx] = realloc(prop_strs[idx], *allocated_size); if(!prop_strs[idx]) goto err; if(prop != prop_strs[idx]) prop = prop_strs[idx] + plen - len; } memcpy(prop, buf, len); prop += len; } *prop = '\0'; return; err: fprintf(stderr, "scan_playlist: error allocating memory\n"); } static void delete_file(char *props) { unsigned int fid; /* The first entry is always the fid */ fid = atoi(&props[4]); unlink(lk_karmaUsb_fidToPath(0, fid)); } static int32_t read_properties_smalldb(char **properties) { /* parse smalldb for all properties */ FILE *fp = NULL; char *tmp, *ptr; char **prop_strs = NULL; char *propnames = NULL; uint32_t tmpnum, nfiles; size_t allocated_size = BUFSIZ; /* of each prop string */ uint32_t i, j; int ret = -1; if(!db) db = calloc(sizeof(karma_db_t), 1); if(!db) goto err; tmp = calloc(strlen(usbMountPoint) + strlen(RK_SMALLDB) + 1, 1); if(!tmp) goto err; sprintf(tmp, "%s%s", usbMountPoint, RK_SMALLDB); fp = fopen(tmp, "rb"); free(tmp); if(!fp) goto err; if(!read32(fp, &db->version)) goto err; if(!read32(fp, &db->ctime)) goto err; if(!read32(fp, &db->eight)) goto err; if(!read32(fp, &db->three)) goto err; if(!read32(fp, &db->num_attribs)) goto err; db->attribs = malloc(db->num_attribs * sizeof(smalldb_attrib_t)); if(!db->attribs) goto err; for (i = 0; i < db->num_attribs; i++) { uint32_t type; if(!read32(fp, &type)) goto err; db->attribs[i].type = (smalldb_type_t) type; if(!read32(fp, &type)) goto err; db->attribs[i].dunno = type; } if(!read32(fp, &db->prop_size)) goto err; propnames = malloc(db->prop_size); if(fread(propnames, 1, db->prop_size, fp) != db->prop_size) goto err; tmp = strtok(propnames, " "); for (i = 0; i < db->num_attribs && *tmp; i++) { db->attribs[i].name = strdup(tmp); if(i < db->num_attribs - 1) tmp = strtok(NULL, " "); } if(i != db->num_attribs || !read32(fp, &db->num_playlists)) goto err; db->playlists = malloc(db->num_playlists * sizeof(playlist_t)); if(!db->playlists) goto err; for (i = 0; i < db->num_playlists; i++) { /* playlist section, copy as opaque data for now */ read32(fp, &db->playlists[i].index); read32(fp, &db->playlists[i].len); db->playlists[i].playlist = malloc(db->playlists[i].len); fread(db->playlists[i].playlist, db->playlists[i].len, 1, fp); } fseek(fp, 4, SEEK_CUR); if(!read32(fp, &nfiles)) goto err; if(nfiles == 0) goto out; /* we have to check the delete map after all the properties are read in, * so build each property string and store it in an array for later. */ prop_strs = calloc((nfiles + db->num_playlists) * sizeof(char *), 1); if(!prop_strs) goto err; for (i = 0; i < db->num_attribs; i++) if(!read_attribute(fp, &db->attribs[i], prop_strs, nfiles, &allocated_size)) goto err; /* now read delete string */ if(!read32(fp, &db->dmap_size)) goto err; db->dmap = malloc(db->dmap_size); if(!db->dmap) goto err; fread(db->dmap, db->dmap_size, 1, fp); for (i = 0; i < db->num_playlists; i++) scan_playlist(i, &nfiles, &allocated_size, prop_strs); /* return concatenated string */ ptr = tmp = malloc((allocated_size + 1) * nfiles); *tmp = 0; for (i = 0; i < nfiles; i++) { if(prop_strs[i]) { if(is_deleted(db, i)) { for (j = 0; j < db->num_playlists; j++) if(db->playlists[j].index == i) goto outer; delete_file(prop_strs[i]); continue; } outer: tmpnum = strlen(prop_strs[i]); memcpy(ptr, prop_strs[i], tmpnum); ptr += tmpnum; *ptr = '\n'; ptr++; free(prop_strs[i]); } } *ptr = '\0'; *properties = tmp; out: ret = 0; err: if(ret != 0) printf("Could not read smalldb\n"); if(propnames) free(propnames); if(prop_strs) free(prop_strs); if (db) { db->dmap_size = 0; db->num_playlists = 0; if (db->dmap) free(db->dmap); if (db->playlists) free(db->playlists); } if(fp) fclose(fp); return ret; } /* .......................................................................... */ int32_t lk_karmaUsb_get_all_file_details(int rio, char **properties) { return read_properties(properties); } /* -------------------------------------------------------------------------- */ int32_t lk_karmaUsb_read_file_chunk(int rio, uint64_t offset, uint64_t size, uint32_t file_id, char **data, uint64_t * retsize) { int fd; int res; char *path = NULL; path = lk_karmaUsb_fidToPath(rio, file_id); fd = open(path, O_RDONLY); free(path); /* if(offset==0) fprintf(stderr, "--> %s %x %d\n", path, file_id, file_id); fprintf(stderr, "---> %s\n", strerror(errno)); */ if(fd == -1) { close(fd); lk_errors_set(E_READ); return -1; } *data = (char *)malloc((size_t) size); res = pread(fd, *data, (size_t) size, (size_t) offset); /* fprintf(stderr, "--> %d\n", res); */ if(res >= 0) *retsize = res; else { close(fd); lk_errors_set(E_READ); return -1; } close(fd); return 0; } /* -------------------------------------------------------------------------- */ int32_t lk_karmaUsb_write_file_chunk(int rio, uint64_t offset, uint64_t size, uint32_t file_id, uint32_t storage_id, const char *data) { #define PERMS S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH int fd; int res, ret; char *path = NULL; path = lk_karmaUsb_fidToPath(rio, file_id); /* if(offset==0) fprintf(stderr, "--> %s %x %d\n", path, file_id, file_id); */ if((fd = open(path, O_WRONLY | O_CREAT, PERMS)) == EEXIST) fd = open(path, O_WRONLY | O_TRUNC, PERMS); /* make sure the directory is there and try again */ if (fd == -1) { mk_path(path); if((fd = open(path, O_WRONLY | O_CREAT, PERMS)) == EEXIST) fd = open(path, O_WRONLY | O_TRUNC, PERMS); } free(path); /* fprintf(stderr, "---> %s\n", strerror(errno)); */ if(fd == -1) { close(fd); lk_errors_set(E_WRITE); return -1; } res = pwrite(fd, data, (size_t) size, (size_t) offset); /* fprintf(stderr, "--> %d\n", res); */ if(res < 0) { close(fd); lk_errors_set(E_WRITE); return -1; } close(fd); return 0; } /* -------------------------------------------------------------------------- */ int32_t lk_karmaUsb_update_file_details(int rio, uint32_t file_id, char *properties) { /* Modify (or create) the *1 file of file_id with properties */ /* ************************* UPDATE smalldb TOO ?? ************************** */ #define PERMS S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH int fd; int len, res, ret; char *path = NULL; if(!properties) { lk_errors_set(E_FAILEDREQ); return -1; } path = lk_karmaUsb_fidToPath(rio, file_id); path[strlen(path) - 1] = '1'; /* fprintf(stderr, "--> %s %x %d\n", path, file_id, file_id); */ unlink(path); fd = open(path, O_WRONLY | O_CREAT, PERMS); if(fd == -1 && errno == ENOENT) { res = strlen(path); path[res - 4] = '\0'; ret = mkdir(path, 0755); path[res - 4] = '/'; if(!ret) fd = open(path, O_WRONLY | O_CREAT, PERMS); } free(path); /* fprintf(stderr, "---> %s\n", strerror(errno)); */ if(fd == -1) { close(fd); lk_errors_set(E_WRITE); return -1; } len = strlen(properties); res = write(fd, properties, len); /* fprintf(stderr,"--> len=%d %d\n", len, res); */ if(res == -1) { close(fd); lk_errors_set(E_WRITE); return -1; } close(fd); return 0; } /* -------------------------------------------------------------------------- */ int32_t lk_karmaUsb_delete_file(int rio, uint32_t file_id) { int ret = 0; char *path = NULL; path = lk_karmaUsb_fidToPath(rio, file_id); /* fprintf(stderr, "--> %s %x %d\n", path, file_id, file_id); */ if(unlink(path)) ret = -1; path[strlen(path) - 1] = '1'; /* fprintf(stderr, "--> %s\n", path); */ if(unlink(path)) ret = -1; if(ret == -1) lk_errors_set(E_DELETE); if (!ret) lk_properties_del_property(file_id); free(path); return ret; } /* -------------------------------------------------------------------------- */ int lk_karmaUsb_write_smalldb(void) { int val = 0; errno = 0; val = lk_properties_write_smalldb(usbMountPoint, db); perror("lk_karmaUsb_write_smalldb()"); return val; } /* -------------------------------------------------------------------------- */ /* Advanced Protocol Functions */ /* -------------------------------------------------------------------------- */ void lk_karmaUsb_load_database(int rio) { int count = 0, aux = 0; char *properties = NULL; aux = lk_karmaUsb_get_device_settings(rio); aux = read_properties(&properties); if(properties) count = lk_properties_import(properties); else { lk_errors_set(E_FAILEDREQ); return; } lk_fdb_load(1); if(properties) free(properties); } void lk_karmaUsb_load_database_smalldb(int rio) { int count = 0, aux = 0; char *properties = NULL; aux = lk_karmaUsb_get_device_settings(rio); aux = read_properties_smalldb(&properties); if(properties) count = lk_properties_import(properties); /* else just assume a new blank DB */ else lk_properties_init(); lk_fdb_load(1); /* fprintf(stderr, "smalldb: %d Files\n", count); */ if(properties) free(properties); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* THE LAN VERSIONS USED ONLY INTERNALLY IN karmaLan.c int lk_karmaUsb_get_protocol_version(int rio, uint32_t *major_version, uint32_t *minor_version){return 0;} int lk_karmaUsb_send_request(int rio, uint32_t identifier, char * payload, int plen){return 0;} int32_t lk_karmaUsb_get_authentication_salt(int rio, char **salt) {return 0;} */ /* -------------------------------------------------------------------------- */ /* UNUSED int lk_karmaUsb_get_device_details(int rio, char **name, char **version, uint32_t *storagedevices){return 0;} int32_t lk_karmaUsb_get_file_details(int rio, uint32_t file_id, char **properties){return 0;} int32_t lk_karmaUsb_update_device_settings(int rio, char *properties){return 0;} int32_t lk_karmaUsb_prepare(int rio, uint64_t size, uint32_t *file_id, uint32_t storage_id){return 0;} int32_t lk_karmaUsb_format_storage(int rio, uint32_t storage_id) {return 0;} int32_t lk_karmaUsb_device_operation(int rio, uint64_t size, char *data, char **newdata) {return 0;} void lk_karmaUsb_update_database(int rio){} */ /* -------------------------------------------------------------------------- */ libkarma-0.1.2/src/karmaUsb.h0000644000175000000120000000406711543330237015157 0ustar frankywheel/* * libkarma/karma.h * * Copyright (c) Frank Zschockelt 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #ifndef _KARMA_USB_H #define _KARMA_USB_H #include char * lk_karmaUsb_fidToPath (int rio, uint32_t file_id); /*Help-Functions:*/ int lk_karmaUsb_connect (char *ip); /*Basic Protocol Functions*/ uint32_t lk_karmaUsb_authenticate (int rio, char *pass); int lk_karmaUsb_get_storage_details (int rio, uint32_t storage_id, uint32_t *n_files, uint64_t *s_size, uint64_t *f_space, uint32_t *highest_file_id); int lk_karmaUsb_get_device_settings (int rio); int32_t lk_karmaUsb_request_io_lock (int rio, uint32_t type); int32_t lk_karmaUsb_release_io_lock (int rio); int32_t lk_karmaUsb_write_file_chunk (int rio, uint64_t offset, uint64_t size, uint32_t file_id, uint32_t storage_id, const char *data); int32_t lk_karmaUsb_get_all_file_details (int rio, char **properties); int32_t lk_karmaUsb_update_file_details (int rio, uint32_t file_id, char * properties); int32_t lk_karmaUsb_read_file_chunk (int rio, uint64_t offset, uint64_t size, uint32_t file_id, char **data, uint64_t *retsize); int32_t lk_karmaUsb_delete_file (int rio, uint32_t file_id); int32_t lk_karmaUsb_hangup (int rio); int lk_karmaUsb_write_smalldb (void); /*Advanced Protocol Functions:*/ void lk_karmaUsb_load_database (int rio); void lk_karmaUsb_load_database_smalldb (int rio); #endif /* _KARMA_USB_H */ libkarma-0.1.2/TODO0000644000175000000120000000054011543330237013132 0ustar frankywheel- lkarmaUsb: Manage the "smalldb" in addition to the fids?/_000??/??1 files - lkarmaUsb: Check correctness of get_storage_details() - lkarmaUsb: Implement a true get_device_settings() using USB commands - lkarmaUsb assumes that all the required dirs under the mount point exist - lkarmaUsb: Create/delete directories mountPoint/fids?/_000?? as needed libkarma-0.1.2/Makefile0000664000175000000120000000356111543330237014112 0ustar frankywheelLK_SRC=src TOOLSDIR=tools PREFIX=/usr INSTALL?=./install-sh VERSION=0.1.2 SHELL=/bin/bash export PREFIX export VERSION DISTNAME=libkarma-$(VERSION) DISTFILES= $(LK_SRC)/{Jamfile,Makefile,*[ch]} \ $(TOOLSDIR)/{Jamfile,Makefile,*[ch]} \ karma-sharp/{Makefile,karma-sharp.pc.in,Song.cs,Device.cs} \ Jamfile Makefile COPYING ChangeLog THANKS INSTALL* TODO \ install-sh karma-tools.spec DOCS=THANKS TODO ChangeLog INSTALL_DIR := $(INSTALL) -d -o root -g root -m 0755 INSTALL_FILE := $(INSTALL) -o root -g root -m 0644 INSTALL_PROGRAM := $(INSTALL) -o root -g root -m 0755 INSTALL_SCRIPT := $(INSTALL) -o root -g root -m 0755 all: libkarma tools karma-sharp static: libkarma toolsStatic karma-sharp install: libkarma tools karma-sharp cd $(LK_SRC) && $(MAKE) install cd karma-sharp && $(MAKE) install cd tools && $(MAKE) install $(INSTALL_DIR) $(DESTDIR)/$(PREFIX)/share/doc/libkarma $(INSTALL_FILE) $(DOCS) $(DESTDIR)/$(PREFIX)/share/doc/libkarma uninstall: cd $(LK_SRC) && $(MAKE) uninstall cd karma-sharp && $(MAKE) uninstall cd tools && $(MAKE) uninstall rm -rf $(DESTDIR)/$(PREFIX)/share/doc/libkarma libkarma: FORCE cd $(LK_SRC) && $(MAKE) tools: FORCE cd $(TOOLSDIR) && $(MAKE) toolsStatic: FORCE cd $(TOOLSDIR) && $(MAKE) static karma-sharp: FORCE cd karma-sharp && $(MAKE) dist: mkdir -p $(DISTNAME) mkdir -p $(DISTNAME)/$(LK_SRC) mkdir -p $(DISTNAME)/$(TOOLSDIR) mkdir -p $(DISTNAME)/karma-sharp cp --parents $(DISTFILES) $(DISTNAME) tar czvf $(DISTNAME).tar.gz $(DISTNAME) $(RM) -r $(DISTNAME) distcheck: dist mkdir build cd build && tar xzvf ../$(DISTNAME).tar.gz && \ cd $(DISTNAME) && $(MAKE) $(RM) -r build .PHONY: clean clean-libkarma: ( cd $(LK_SRC) ; make clean ) clean-tools: ( cd $(TOOLSDIR) ; make clean ) clean-karma-sharp: ( cd karma-sharp ; make clean ) clean: clean-tools clean-libkarma clean-karma-sharp FORCE: libkarma-0.1.2/Makefile.orig0000664000175000000120000000325511543330237015051 0ustar frankywheelLK_SRC=src TOOLSDIR=tools PREFIX=/usr INSTALL?=./install-sh VERSION=0.1.1 SHELL=/bin/bash export PREFIX export VERSION DISTNAME=libkarma-$(VERSION) DISTFILES= $(LK_SRC)/{Jamfile,Makefile,*[ch]} \ $(TOOLSDIR)/{Jamfile,Makefile,*[ch]} \ karma-sharp/{Makefile,karma-sharp.pc.in,Song.cs,Device.cs} \ Jamfile Makefile COPYING ChangeLog THANKS INSTALL* TODO \ install-sh karma-tools.spec INSTALL_DIR := $(INSTALL) -d -o root -g root -m 0755 INSTALL_FILE := $(INSTALL) -o root -g root -m 0644 INSTALL_PROGRAM := $(INSTALL) -o root -g root -m 0755 INSTALL_SCRIPT := $(INSTALL) -o root -g root -m 0755 all: libkarma tools karma-sharp static: libkarma toolsStatic karma-sharp install: libkarma tools karma-sharp cd $(LK_SRC) && $(MAKE) install cd karma-sharp && $(MAKE) install cd tools && $(MAKE) install uninstall: cd $(LK_SRC) && $(MAKE) uninstall cd karma-sharp && $(MAKE) uninstall cd tools && $(MAKE) uninstall libkarma: FORCE cd $(LK_SRC) && $(MAKE) tools: FORCE cd $(TOOLSDIR) && $(MAKE) toolsStatic: FORCE cd $(TOOLSDIR) && $(MAKE) static karma-sharp: FORCE cd karma-sharp && $(MAKE) dist: mkdir -p $(DISTNAME) mkdir -p $(DISTNAME)/$(LK_SRC) mkdir -p $(DISTNAME)/$(TOOLSDIR) mkdir -p $(DISTNAME)/karma-sharp cp --parents $(DISTFILES) $(DISTNAME) tar czvf $(DISTNAME).tar.gz $(DISTNAME) $(RM) -r $(DISTNAME) distcheck: dist mkdir build cd build && tar xzvf ../$(DISTNAME).tar.gz && \ cd $(DISTNAME) && $(MAKE) $(RM) -r build .PHONY: clean clean-libkarma: ( cd $(LK_SRC) ; make clean ) clean-tools: ( cd $(TOOLSDIR) ; make clean ) clean-karma-sharp: ( cd karma-sharp ; make clean ) clean: clean-tools clean-libkarma clean-karma-sharp FORCE: libkarma-0.1.2/tests/0000755000175000000120000000000011543330237013605 5ustar frankywheellibkarma-0.1.2/tests/test2/0000755000175000000120000000000011543330237014646 5ustar frankywheellibkarma-0.1.2/tests/test2/fids0/0000755000175000000120000000000011543330237015653 5ustar frankywheellibkarma-0.1.2/tests/test2/fids0/_00000/0000755000175000000120000000000011543330237016451 5ustar frankywheellibkarma-0.1.2/tests/test2/fids0/_00000/1410000644000175000000120000000064711543330237016710 0ustar frankywheelduration=281000 length=6383450 samplerate=44100 ctime=1153781795 rms=8226 stddev=1905 play_last=1153785803 play_count=1 tracknr=3 file_id=3 profile=U\x00\x00\x00¥ªjjPV\x15Uª\x06\x00\x00ªÿ¯šÿª\x01@ÿÿÿÿ\x00@þÿ–ZUi\x00@©j type=tune codec=vorbis artist=Björk source=Medulla title=Where is the Line? bitrate=vs192 genre=Alternative year=2004 rid=d158e808e7bde099dee1e600899fea6e fid_generation=1153781795 profiler_version=1001 libkarma-0.1.2/tests/test2/fids0/_00000/1a10000644000175000000120000000073011543330237016756 0ustar frankywheelduration=237000 length=5622917 samplerate=44100 ctime=1153781798 rms=8745 stddev=2408 play_last=1153786580 play_count=1 tracknr=6 file_id=6 profile=\x15\x00\x00\x00ªªjUªúûªú¿ú¯ZA\x01@ª®ªªÿÿÿÿYU©ÿ\x04\x14PU\x00\x00\x00\x00 type=tune codec=vorbis artist=Björk source=Medulla title=Who Is It (Carry My Joy On The Left, Carry My Pain On The Right) bitrate=vs192 genre=Alternative year=2004 rid=7c1f1dc8abc5ff891457b9e22125d33e fid_generation=1153781798 profiler_version=1001 libkarma-0.1.2/tests/test2/fileinfo0000644000175000000120000000207211543330237016365 0ustar frankywheelbytes_silence_sof=0 normalisation=0 bpm=0 rid=d158e808e7bde099dee1e600899fea6e codec=vorbis fid_generation=1153781795 play_count=0 replay_gain_audiophile=0 samplerate=44100 file_id=3 options=0 play_count_limit=0 bitrate=vs192 replay_gain_peak=0 stddev=0 play_last=0 replay_gain_radio=0 profiler_version=0 artist=Björk offset=0 duration=281000 tracknr=3 marked=0 fid=320 trailer=0 bytes_silence_eof=0 ctime=1153781795 length=6383450 rms=0 title=Where is the Line? type=tune genre=Alternative source=Medulla year=2004 bytes_silence_sof=0 normalisation=0 bpm=0 rid=7c1f1dc8abc5ff891457b9e22125d33e codec=vorbis fid_generation=1153781798 play_count=0 replay_gain_audiophile=0 samplerate=44100 file_id=6 options=0 play_count_limit=0 bitrate=vs192 replay_gain_peak=0 stddev=0 play_last=0 replay_gain_radio=0 profiler_version=0 artist=Björk offset=0 duration=237000 tracknr=6 marked=0 fid=416 trailer=0 bytes_silence_eof=0 ctime=1153781798 length=5622917 rms=0 title=Who Is It (Carry My Joy On The Left, Carry My Pain On The Right) type=tune genre=Alternative source=Medulla year=2004 libkarma-0.1.2/tests/test4/0000755000175000000120000000000011543330237014650 5ustar frankywheellibkarma-0.1.2/tests/test4/fids0/0000755000175000000120000000000011543330237015655 5ustar frankywheellibkarma-0.1.2/tests/test4/fids0/_00000/0000755000175000000120000000000011543330237016453 5ustar frankywheellibkarma-0.1.2/tests/test4/fids0/_00000/1410000644000175000000120000000064711543330237016712 0ustar frankywheelduration=281000 length=6383450 samplerate=44100 ctime=1153781795 rms=8226 stddev=1905 play_last=1153785803 play_count=1 tracknr=3 file_id=3 profile=U\x00\x00\x00¥ªjjPV\x15Uª\x06\x00\x00ªÿ¯šÿª\x01@ÿÿÿÿ\x00@þÿ–ZUi\x00@©j type=tune codec=vorbis artist=Björk source=Medulla title=Where is the Line? bitrate=vs192 genre=Alternative year=2004 rid=d158e808e7bde099dee1e600899fea6e fid_generation=1153781795 profiler_version=1001 libkarma-0.1.2/tests/test4/fids0/_00000/1a10000644000175000000120000000073011543330237016760 0ustar frankywheelduration=237000 length=5622917 samplerate=44100 ctime=1153781798 rms=8745 stddev=2408 play_last=1153786580 play_count=1 tracknr=6 file_id=6 profile=\x15\x00\x00\x00ªªjUªúûªú¿ú¯ZA\x01@ª®ªªÿÿÿÿYU©ÿ\x04\x14PU\x00\x00\x00\x00 type=tune codec=vorbis artist=Björk source=Medulla title=Who Is It (Carry My Joy On The Left, Carry My Pain On The Right) bitrate=vs192 genre=Alternative year=2004 rid=7c1f1dc8abc5ff891457b9e22125d33e fid_generation=1153781798 profiler_version=1001 libkarma-0.1.2/tests/test4/fileinfo0000644000175000000120000000327711543330237016377 0ustar frankywheelbytes_silence_sof=0 normalisation=0 bpm=0 fid_generation=2164627 play_count=0 replay_gain_audiophile=0 samplerate=0 file_id=0 options=0 play_count_limit=0 replay_gain_peak=0 stddev=0 play_last=0 replay_gain_radio=0 profiler_version=0 offset=0 duration=0 tracknr=0 marked=0 fid=256 trailer=0 bytes_silence_eof=0 ctime=0 length=0 rms=0 title=All Music type=playlist profile=U\x00\x00\x00¥ªjjPV\x15Uª\x06\x00\x00ªÿ¯šÿª\x01@ÿÿÿÿ\x00@þÿ–ZUi\x00@©j bytes_silence_sof=0 normalisation=0 bpm=0 rid=d158e808e7bde099dee1e600899fea6e codec=vorbis fid_generation=1153781795 play_count=256 replay_gain_audiophile=0 samplerate=44100 file_id=3 options=0 play_count_limit=0 bitrate=vs192 replay_gain_peak=0 stddev=1905 play_last=1153785803 replay_gain_radio=0 profiler_version=1001 artist=Björk offset=0 duration=281000 tracknr=3 marked=0 fid=320 trailer=0 bytes_silence_eof=0 ctime=1153781795 length=6383450 rms=8226 title=Where is the Line? type=tune genre=Alternative profile=U\x00\x00\x00¥ªjjPV\x15Uª\x06\x00\x00ªÿ¯šÿª\x01@ÿÿÿÿ\x00@þÿ–ZUi\x00@©j source=Medulla year=2004 bytes_silence_sof=0 normalisation=0 bpm=0 rid=7c1f1dc8abc5ff891457b9e22125d33e codec=vorbis fid_generation=1153781798 play_count=256 replay_gain_audiophile=0 samplerate=44100 file_id=6 options=0 play_count_limit=0 bitrate=vs192 replay_gain_peak=0 stddev=2408 play_last=1153786580 replay_gain_radio=0 profiler_version=1001 artist=Björk offset=0 duration=237000 tracknr=6 marked=0 fid=416 trailer=0 bytes_silence_eof=0 ctime=1153781798 length=5622917 rms=8745 title=Who Is It (Carry My Joy On The Left, Carry My Pain On The Right) type=tune genre=Alternative profile=\x15\x00\x00\x00ªªjUªúûªú¿ú¯ZA\x01@ª®ªªÿÿÿÿYU©ÿ\x04\x14PU\x00\x00\x00\x00 source=Medulla year=2004 libkarma-0.1.2/tests/test5/0000755000175000000120000000000011543330237014651 5ustar frankywheellibkarma-0.1.2/tests/test5/fids0/0000755000175000000120000000000011543330237015656 5ustar frankywheellibkarma-0.1.2/tests/test5/fids0/_00000/0000755000175000000120000000000011543330237016454 5ustar frankywheellibkarma-0.1.2/tests/test5/fids0/_00000/1110000644000175000000120000001054511543330237016706 0ustar frankywheelrid=93bd65ea464ffb8036cb8b3b9b74c578 codec=vorbis fid_generation=1153790572 samplerate=44100 bitrate=vs112 artist=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa duration=1000 fid=272 ctime=1153790572 length=8448 title=b type=tune genre=Jazz profile= source=c year=1990 libkarma-0.1.2/tests/test5/fids0/_00000/1210000644000175000000120000001054511543330237016707 0ustar frankywheelrid=13164cf9f1fd7913c4da0178c055b676 codec=vorbis fid_generation=1153790600 samplerate=44100 bitrate=vs112 artist=a duration=1000 fid=288 ctime=1153790600 length=8448 title=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb type=tune genre=Jazz profile= source=c year=1990 libkarma-0.1.2/tests/test5/fids0/_00000/1310000644000175000000120000001054511543330237016710 0ustar frankywheelrid=b13a072a4e3efa34fbe647f44ebad1f8 codec=vorbis fid_generation=1153790624 samplerate=44100 bitrate=vs112 artist=a duration=1000 fid=304 ctime=1153790624 length=8448 title=b type=tune genre=Jazz profile= source=cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc year=1990 libkarma-0.1.2/tests/test5/fids0/_00000/1410000644000175000000120000001054311543330237016707 0ustar frankywheelrid=b9c9dc0d7a7222da7200f085d315513e codec=vorbis fid_generation=1153790742 samplerate=44100 bitrate=vs112 artist=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa duration=1000 fid=320 ctime=1153790742 length=8446 title=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb type=tune genre=Jazz profile= source=cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc year=1990 libkarma-0.1.2/tests/test5/fileinfo0000644000175000000120000004461211543330237016376 0ustar frankywheelbytes_silence_sof=0 normalisation=0 bpm=0 rid=93bd65ea464ffb8036cb8b3b9b74c578 codec=vorbis fid_generation=1153790572 play_count=0 replay_gain_audiophile=0 samplerate=44100 file_id=0 options=0 play_count_limit=0 bitrate=vs112 replay_gain_peak=0 stddev=0 play_last=0 replay_gain_radio=0 profiler_version=0 artist=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa offset=0 duration=1000 tracknr=0 marked=0 fid=272 trailer=0 bytes_silence_eof=0 ctime=1153790572 length=8448 rms=0 title=b type=tune genre=Jazz source=c year=1990 bytes_silence_sof=0 normalisation=0 bpm=0 rid=13164cf9f1fd7913c4da0178c055b676 codec=vorbis fid_generation=1153790600 play_count=0 replay_gain_audiophile=0 samplerate=44100 file_id=0 options=0 play_count_limit=0 bitrate=vs112 replay_gain_peak=0 stddev=0 play_last=0 replay_gain_radio=0 profiler_version=0 artist=a offset=0 duration=1000 tracknr=0 marked=0 fid=288 trailer=0 bytes_silence_eof=0 ctime=1153790600 length=8448 rms=0 title=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb type=tune genre=Jazz source=c year=1990 bytes_silence_sof=0 normalisation=0 bpm=0 rid=b13a072a4e3efa34fbe647f44ebad1f8 codec=vorbis fid_generation=1153790624 play_count=0 replay_gain_audiophile=0 samplerate=44100 file_id=0 options=0 play_count_limit=0 bitrate=vs112 replay_gain_peak=0 stddev=0 play_last=0 replay_gain_radio=0 profiler_version=0 artist=a offset=0 duration=1000 tracknr=0 marked=0 fid=304 trailer=0 bytes_silence_eof=0 ctime=1153790624 length=8448 rms=0 title=b type=tune genre=Jazz source=cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc year=1990 bytes_silence_sof=0 normalisation=0 bpm=0 rid=b9c9dc0d7a7222da7200f085d315513e codec=vorbis fid_generation=1153790742 play_count=0 replay_gain_audiophile=0 samplerate=44100 file_id=0 options=0 play_count_limit=0 bitrate=vs112 replay_gain_peak=0 stddev=0 play_last=0 replay_gain_radio=0 profiler_version=0 artist=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa offset=0 duration=1000 tracknr=0 marked=0 fid=320 trailer=0 bytes_silence_eof=0 ctime=1153790742 length=8446 rms=0 title=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb type=tune genre=Jazz source=cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc year=1990 libkarma-0.1.2/tests/test.sh0000644000175000000120000000227611543330237015127 0ustar frankywheel#! /bin/sh RIOCP=../tools/riocp TESTDIR=`pwd` HOME=`pwd` rm -rf $HOME/.openrio $RIOCP -a $TESTDIR/test1 > /dev/null 2>&1 test=test1 echo -n "$test: " rm -f $HOME/.openrio/*/fileinfo $RIOCP -ba $TESTDIR/$test > /dev/null 2>&1 [ -f $HOME/.openrio/*/fileinfo -a ! -s $HOME/.openrio/*/fileinfo ] \ && echo passed || echo failed test=test2 echo -n "$test: " rm -f $HOME/.openrio/*/fileinfo $RIOCP -ba $TESTDIR/$test > /dev/null 2>&1 diff $HOME/.openrio/*/fileinfo $TESTDIR/$test/fileinfo \ && echo passed || echo failed test=test3 echo -n "$test: " mkdir -p $TESTDIR/$test/fids0 > /dev/null 2>&1 $RIOCP -a $TESTDIR/$test /dev/null > /dev/null 2>&1 [ -f $TESTDIR/$test/fids0/_00000/111 ] && echo passed || echo failed rm -rf $TESTDIR/$test/* test=test4 echo -n "$test: " cp $TESTDIR/$test/var/smalldb.orig $TESTDIR/$test/var/smalldb $RIOCP -bwa $TESTDIR/$test > /dev/null 2>&1 $RIOCP -bwa $TESTDIR/$test > /dev/null 2>&1 [ -s $HOME/.openrio/*/fileinfo ] \ && echo passed || echo failed test=test5 echo -n "$test: " cp $TESTDIR/$test/var/smalldb.orig $TESTDIR/$test/var/smalldb $RIOCP -bwa $TESTDIR/$test > /dev/null 2>&1 diff $HOME/.openrio/*/fileinfo $TESTDIR/$test/fileinfo \ && echo passed || echo failed libkarma-0.1.2/tools/0000755000175000000120000000000011543330237013603 5ustar frankywheellibkarma-0.1.2/tools/TODO0000644000175000000120000000421511543330237014275 0ustar frankywheelriocp (towards `lktool'): ^^^^^^^^^^^^^^^^^^^^^^^^^ + Search - allow searches (in the DB) without rioKarma connected - allow escaping "+" and "," - allow ignoring case - dates <--> user locale - dates: allow "before"/"after", etc. - sizes/numbers: allow "larger"/"smaller", etc. - regular expressions ? - parenthesis ? + Download - Allow to specify permissions for created files and dirs - Add other properties such as date, length, fid_generation, etc. ? + Playlists - Upload playlists - Handle playlists in human readable formats (e.g. "m3u") - Check playlists for consistency --------------------------------------------------------------------------- DONE: - utf8 --> user charset (in properties.c) - Folders-based (up/down)load --> A test version working - Build filenames from properties (download options "(-u|-x|-l) ...") - Allow escaping '%' in the properties format string - Options to change blank and other unwished characters in pathnames - Create directories as needed for the path specified by propertiesString - Fix UTF8 issues in pathnames - Delete files identified by search results - Delete: Ask for confirmation, with optional "force" + Rewrite folders-based (up/down)load code - Correctly handle the name and path of the fidsAndfilenames file - Fixed segfault if libkarma_fdb.gz is empty - moved pathname editting (tr) out of riocp.c and changed -q after delete - Fixed broken search (since 0.3.1) - Fixed userCodeset display of search trace ("OR/ANDing with ...") - allow exact searches DISCARDED: + Improve Folders-based (up/down)load code ### Now better handled with lkarmafs - *** Re-Implement folders-based (up/down)load using the "playlist" property - Copy the fidsAndfilenames file to/from RioKarma as a taxi file - Allow search functionality for folders-based download - Update fidsAndfilenames file in sync with DB changes - Remember the full pathname ? - Remember the Root (working) Directory (RD) in the fidsAndfilenames file ? - Optionally use the RD from the fidsAndfilenames file when downloading ? - Optionally allow change the RD and/or filename prefixes in command line libkarma-0.1.2/tools/Makefile0000644000175000000120000000247211543330237015250 0ustar frankywheelINCLUDES=-I../src LIBDIR=../lib LIBKARMA=$(LIBDIR)/libkarma.a ifeq ($(MAKECMDGOALS),static) LIBKARMA=$(LIBDIR)/libkarma.a LKARMA=$(LIBKARMA) else PLATFORM=$(shell uname) ifeq ($(PLATFORM),Darwin) LDFLAGS+=-liconv LIBKARMA=$(LIBDIR)/libkarma.dynlib else LIBKARMA=$(LIBDIR)/libkarma.so endif LKARMA=-lkarma endif SRCS=pathedit.c CC?=gcc CFLAGS+=-Wall -pedantic LDFLAGS+=-ltag_c -lz -L $(LIBDIR) OBJS=$(SRCS:.c=.o) TOOLS=riocp chprop karma_helper MANPAGES=riocp.1 chprop.1 karma_helper.1 default: $(TOOLS) all: $(TOOLS) static: $(TOOLS) @echo Linking tools with the static lib: $(LIBKARMA) riocp: riocp.c $(OBJS) $(LIBKARMA) $(CC) $(INCLUDES) $(LDFLAGS) $(CFLAGS) $@.c -o $@ $(OBJS) $(LKARMA) chprop: chprop.c $(LIBKARMA) $(CC) $(INCLUDES) $(LDFLAGS) $(CFLAGS) $@.c -o $@ $(LKARMA) playlist_show: playlist_show.c $(LIBKARMA) $(CC) $(INCLUDES) $(LDFLAGS) $(CFLAGS) $@.c -o $@ $(LKARMA) karma_helper: karma_helper.c $(CC) $(INCLUDES) $(CFLAGS) $@.c -o $@ -lusb install: ../install-sh -m 0755 -d $(DESTDIR)$(PREFIX)/bin ../install-sh -m 0755 -t $(DESTDIR)$(PREFIX)/bin/ $(TOOLS) ../install-sh -m 0755 -d $(DESTDIR)$(PREFIX)/share/man/man1 ../install-sh -m 0755 -t $(DESTDIR)$(PREFIX)/share/man/man1 $(MANPAGES) uninstall: cd $(PREFIX)/bin && $(RM) $(TOOLS) .PHONY: clean clean: rm -rf *.o $(TOOLS) libkarma-0.1.2/tools/create_device-settings0000755000175000000120000000141611543330237020153 0ustar frankywheel#!/bin/bash if [ $# -lt 1 ] || [ "${1%elp}" = "-h" ] || [ "${1%elp}" = "--h" ] ; then echo "\ Usage: ${0##*/} [-h] karma_mount_point For a RK mounted on karma_mount_point, uses karma_helper to create the file karma_mount_point/device_settings. This file contains the Rio Karma serial number needed for properly setting the local cache ~/.openrio/pearl-serialNo/fileinfo " exit 0 fi # TMP=${TMPDIR:-/tmp}/${0##*/}.$$ ; trap "rm $TMP* 2>/dev/null" EXIT PATH=$PATH:. # umount $1 karma_helper -u karma_helper -l karma_helper -r karma_helper -i | sed '/^ *$/d' > $TMP karma_helper -b # echo -n Mounting the RK on $1" " while ! mount $1 2>/dev/null ; do sleep 1 ; echo -n \. ; done echo " "mounted! echo Creating $1/device_settings # cp $TMP $1/device_settings libkarma-0.1.2/tools/ftw.c0000644000175000000120000000410211543330237014544 0ustar frankywheel/* * Written by Felix von Leitner [see dietlibc] * minor modifications by Michael Piotrowski * The license for the diet libc is the GNU General Public License, version 2 * (as included in the file LICENSE). */ #include #include #include #include #include #include #include int ftw(const char*dir,int(*f)(const char*file,const struct stat*sb,int flag), int dpth){ char* cd; size_t cdl; DIR* d; struct dirent* de; struct stat sb; int r; unsigned int oldlen=0; char* filename; /* the warning gcc issues here is bogus */ /* Argument is not a directory */ if (chdir(dir)){ int flg; if (!lstat(dir, &sb)){ if (S_ISLNK(sb.st_mode)) flg = FTW_SL; else flg = FTW_F; } else flg = FTW_NS; r = f(dir, &sb, flg); return r; } cd=alloca(PATH_MAX+1); if(!getcwd(cd,PATH_MAX))return-1; cd[PATH_MAX]='\0'; cdl=strlen(cd); if(!(d=opendir(".")))return-1; while((de=readdir(d))){ int flg; size_t nl; if(de->d_name[0]=='.'){ if(!de->d_name[1])continue; if(de->d_name[1]=='.'&&!de->d_name[2])continue; } nl=strlen(de->d_name); if (nl+cdl+2>oldlen) filename=alloca(oldlen=nl+cdl+2); memmove(filename,cd,cdl); filename[cdl]='/'; memmove(filename+cdl+1,de->d_name,nl+1); if(!lstat(de->d_name,&sb)){ if(S_ISLNK(sb.st_mode))flg=FTW_SL; else if(S_ISDIR(sb.st_mode))flg=FTW_D; else flg=FTW_F; }else flg=FTW_NS; r=f(filename,&sb,flg); if(r){ closedir(d); return r; } if(flg==FTW_D&&dpth){ r=ftw(filename,f,dpth-1); #if defined __NetBSD__ || defined __FreeBSD__ fchdir(d->dd_fd); #else fchdir(d->fd); #endif if (r){ closedir(d); return r; } } } return closedir(d); } libkarma-0.1.2/tools/ftw.h0000644000175000000120000000212611543330237014555 0ustar frankywheel/* * Written by Felix von Leitner [see dietlibc] * The license for the diet libc is the GNU General Public License, version 2 * (as included in the file LICENSE). */ #ifndef _FTW_H #define _FTW_H #include #include struct FTW { int base; int level; }; int ftw (const char *dir, int (*fn)(const char *file, const struct stat *sb, int flag), int depth); enum { FTW_F, /* Regular file. */ #define FTW_F FTW_F FTW_D, /* Directory. */ #define FTW_D FTW_D FTW_DNR, /* Unreadable directory. */ #define FTW_DNR FTW_DNR FTW_NS, /* Unstatable file. */ #define FTW_NS FTW_NS FTW_SL, /* Symbolic link. */ # define FTW_SL FTW_SL /* These flags are only passed from the `nftw' function. */ FTW_DP, /* Directory, all subdirs have been visited. */ # define FTW_DP FTW_DP FTW_SLN /* Symbolic link naming non-existing file. */ # define FTW_SLN FTW_SLN }; typedef int (*__ftw_func_t) (const char *__filename, const struct stat *__status, int __flag); #endif libkarma-0.1.2/tools/rkUsb0000755000175000000120000000324611543330237014624 0ustar frankywheel#!/bin/bash if [ $# -gt 1 ] || [ "${1%elp}" = "-h" ] || [ "${1%elp}" = "--h" ] ; then echo "\ Using karma_helper, logically connect and mount (or unmount and disconnect) the RK from the USB interface. Assumes the mountpoint is /mnt/karma2. Without options toggles \"${0##*/} -c\" / \"${0##*/} -u\" Option -u previously umounts lkarmafs, if mounted. Usage: ${0##*/} [-h[elp]] [[-]c[onnect]] [[-]u[nconnect]]" exit 0 fi # KH=`which karma_helper` MNTPOINT=/mnt/karma2 ; OPT=u # if [ $# -eq 0 ] ; then if mount | grep -q "$MNTPOINT.*omfs" ; then OPT=u ; else OPT=c ; fi else if [ -z "${1%-c*}" ] || [ -z "${1%c*}" ] ; then OPT=c elif [ -z "${1%-u*}" ] || [ -z "${1%u*}" ] ; then OPT=u else echo Unknown option $1 ; $0 -h ; exit 1 fi fi # if [ "$OPT" == "c" ] ; then echo -n Binding the RK ..." " sudo $KH -b echo "done!" echo -n Mounting the RK on $MNTPOINT" " if mount | grep -q "$MNTPOINT.*omfs" ; then echo ... was already mounted. else while ! mount $MNTPOINT 2>/dev/null ; do sleep 1 ; echo -n \. ; done echo " "mounted! fi elif [ "$OPT" == "u" ] ; then LKARMAMNT=`mount | awk '/lkarmafs/{print $3}'` if [ ! -z $LKARMAMNT ] ; then echo -n Unmounting lkarmafs from $LKARMAMNT ..." " if ! fusermount -u $LKARMAMNT then echo "*** failed" ; else echo "done!" ; fi sleep 1 fi echo -n Unmounting the RK from $MNTPOINT ..." " if RES=`LANG=C umount $MNTPOINT 2>&1` then echo "done!" ; else if echo $RES | grep -q 'is not mounted' then echo "Not mounted" ; else echo "*** failed!" ; fi fi echo -n Unbinding and disconnecting the RK ..." " for o in u l r ; do sudo $KH -$o ; done echo "done!" fi libkarma-0.1.2/tools/riocp.10000644000175000000120000000752111543330237015006 0ustar frankywheel.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH RIOCP 1 "June 27, 2008" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME riocp \- program to transfer files to and from the Rio Karma .SH SYNOPSIS .B riocp .RI [ options ] " files_to_upload" ... .SH DESCRIPTION This manual page documents briefly the \fBriocp\fP command. .PP \fBriocp\fP is a program that searches for and lists files on the Rio Karma. It also allows the user to transfer files to and from the device. .SH OPTIONS A summary of options is included below. .TP .BR "\-a " { \fIpath\fP | \fIhostname\fP | \fIIP-ADDR\fP } Set access location of Rio Karma. Can be either a hostname or IP address for network access; or a path in the filesystem where the Rio Karma is mounted for USB access. .TP .B \-b Get database by scanning *1 files, instead of smalldb. .TP .B \-c \fIcharset\fP Set codeset to use when communicating with the Rio Karma. .TP .B \-D \fIdummyName\fP Use \fIdummyName\fP for missing or empty props. Default if not set is '\fI-UnKnown-\fP'. .TP .B \-d Download the files searched for with "\fB-s\fP". .TP .B \-e \fIset1\fP \fIset2\fP \fIset3\fP Edit the download pathname using \fIset1\fP and \fIset2\fP as in unix \fBtr\fP. If \fIset3\fP is empty (""): just translate as in \fBtr\fP; otherwise, further delete all chars given in \fIset3\fP. .TP .B \-F Use filenames in \fB~/.openrio/.../__libkarma_fdb__.gz\fP for download. .TP .B \-f Force the files to be written even if they are dupes. .TP .B \-H Download files listed in \fB~/.openrio/.../__libkarma_fdb__.gz\fP that match the current hostname. .TP .B \-h Show summary of options. .TP .B \-l \fIprops\fP Like \fB-u\fP for \fItype\fP='\fBplaylist\fP'. The default is to use whatever is set for \fB-u\fP. .TP .B \-p \fIpassWord\fP Password for accessing the Rio Karma via the network. .TP .B \-q Squeeze repeated chars (given in "\fIset2\fP" of \fB-e\fP), after the optional delete. .TP .B \-R Same as \fB-r\fP, but do not ask for confirmation. .TP .B \-r Remove these files (after the optional download). .TP .B \-s \fIsearchString\fP Search karma DB according to \fIsearchString\fP. \fIsearchString\fP syntax: \fIproperty\fP=\fIsearchStr\fP[{,|+}...], where: .RS .PP - \fIsearchStr\fP is a substring of the \fIproperty\fP value (see \fB~/.openrio/*/fileinfo\fP for possible \fIproperty\fP names) .PP - '\fB,\fP' and '\fB+\fP' mean AND and OR, respectively .PP - each AND/OR operator is applied to the previous search results .RE .TP .B \-U \fIfdb.gz\fP Upload files listed in the given \fIfdb.gz\fP file. .TP .B \-u \fIprops\fP Use properties to build download path for \fItype\fP=\fBtune\fP. "\fIprops\fP" are formating strings (as in "\fBprintf\fP"), where: .RS .PP .B %a .RI "= " Artist .PP .B %c .RI "= " Codec .PP .B %f .RI "= " fid .PP .B %g .RI "= " Genre .PP .B %n .RI "= " "Track Number" .PP .B %s .RI "= " Source .PP .B %T .RI "= " Type .PP .B %t .RI "= " Title .PP The default is "\fI%f.%c\fP". .RE .TP .B \-w Don't rewrite the smalldb database file. .TP .B \-x \fIprops\fP Like \fB-u\fP for \fItype\fP='\fBtaxi\fP'. The default is to use whatever is set for \fB-u\fP. .SH SEE ALSO .BR printf (3), .BR tr (1). .SH AUTHOR riocp was written by Frank Zschockelt . .PP This manual page was written by Joe Nahmias , for the Debian project (but may be used by others). libkarma-0.1.2/tools/riocp.c0000644000175000000120000006230311543330237015067 0ustar frankywheel/* * libkarma/riocp.c * * Copyright (c) Frank Zschockelt 2004-2005 * Enrique Vidal 2004-2005 * Keith Bennett 2006 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include #include #include #include #include #include #include #ifdef LINUX #include #else #include "ftw.h" #endif #include #include #include #include "pathedit.h" #define CHECK(x) (x<0)?"failed":"ok" #define defaultCodeset "ISO8859-15" #define ssdpRetry 3 /* number of retries allowed for SSDP */ #define UNK_NAME "-UnKnown-" void usage(int complete); void currentKarma(int i, int *k); int treecopy(const char *file, const struct stat *sb, int flag); uint32_t * searchStr(int exact, char *searchString, char *unkName); double getUsedSize(int karma); void deleteFids(uint32_t *vp); int isodigit (char d); char esc(char c); char *expand(char *str); void downloadFids(uint32_t *vp, int doDownload, char *unkName, char* useTuneProps, char* useTaxiProps, char* usePlstProps, char* edPathStr1, char* edPathStr2, char* edPathStr3, int squeezeRep, int expandPlaylists, char *playListName); void usage(int complete) { printf("usage: riocp [-h] [-a {path|hostname|ip}] [-p passWord] " "[-s searchString ]\n" " [-u props] [-x props] [-l props] " "[-c charSet] [-e set1 set2 set3]\n" " [-D dummyName] [-U fdb.gz] [-b] [-d] [-f] [-F]\n" " [-H] [-L] [-q] [-r] [-R] [-w] [files_to_upload ...]\n" "\n"); if(!complete) return; printf(" \"-s\" AND/OR-search karma DB according to a \"searchString\";\n" " \"searchString\" syntax: =[{,|+}...], " "where: \n" " - is a substring of the value\n" " (see ~/.openrio/*/fileinfo for possible names)" "\n" " - \',\' and \'+\' mean AND and OR, respectively\n" " - each AND/OR operator is applied to the previous search " "results\n"); printf(" \"-S\" Same as \"-s\" but must be an exact match\n" "\n"); printf(" \"-u\" use properties to build download path for =\'tune\'." " Default=\'%%f.%%c\'\n" " \"-x\" like -u for =\'taxi\',. Default=\"-u props\"\n" " \"-l\" like -u for =\'playlist\'. Default=\"-x props\"\n"); printf(" \"props\" are formatting strings (as in \"printf\"), where\n" " \'%%T\', \'%%g\', \'%%a\', \'%%s\', \'%%f\', \'%%t\', " "\'%%n\', \'%%c\' are, resp., values of\n" " , , , , , , " "<tracknr>, <codec>\n" " If -L enabled, \'%%l\' is the <playListName> in -l props\n" "\n"); printf(" \"-e\" edit the download pathname using \"set1\" and " "\"set2\" as in unix \'tr\'\n" " - if \"set3\" is empty (\"\"): just translate as in \'tr\';" "\n" " - otherwise, further delete all chars given in \"set3\"\n" " \"-q\" squeeze repeated chars (given in \"set2\"), after the " "optional delete\n\n"); printf(" \"-D\" Use dummyName for missing or empty props. (def. -UnKnown-)" "\n"); printf(" \"-d\" download the files searched for with \"-s\"\n" " \"-r\" remove these files (after the optional download)\n" " \"-R\" same as -r, but do not ask for confirmation\n"); printf(" \"-b\" get database by scanning *1 files, instead of smalldb\n"); printf(" \"-w\" don't rewrite the smalldb database file\n"); printf(" \"-f\" force the files to be written even if they are dupes\n"); printf(" \"-F\" Use filenames in ~/.openrio/.../" FDB_FILENAME " for download\n"); printf(" \"-H\" Download files listed in ~/.openrio/.../" FDB_FILENAME "\n that match the current hostname\n"); printf(" \"-L\" For playlists, print/download the listed tunes, " "rather than the lists\n"); printf(" \"-U\" Upload files listed in the given fdb.gz file\n"); } void currentKarma(int i, int *k) { static int karma; if (i) karma=*k; else *k=karma; } static void fdb_download(int checkhost) { int karma, i, len; uint32_t * fdb; char * filename, * p; char ourhostname[255], hostname[255], path[PATH_MAX]; currentKarma(0, &karma); fdb=lk_properties_andOrSearch(EXACT|ORS, NULL, "path", ""); if (!fdb) return; if (checkhost) { if (gethostname(ourhostname, 255) != 0) ourhostname[0] = '\0'; len = strlen(ourhostname) + 1; } for (i=0; fdb[i]; i++) { filename=lk_properties_get_property(fdb[i], "path"); if (!filename) continue; memcpy(hostname, filename, 255); for (p=hostname; *p != '\0'; p++) if (*p == ':') break; *p = '\0'; if (checkhost && memcmp(hostname, ourhostname, len) != 0) continue; memcpy(path, p+1, PATH_MAX); printf("Downloading fid %i to %s\n", fdb[i], path); fprintf(stderr, "lk_rio_read %s\n", CHECK(lk_rio_read(karma, fdb[i], path))); } free(fdb); } void fdb_upload(char *fdb) { char **list, **file; list = lk_fdb_getlist(fdb); for (file=list; *file; file++) { CHECK(ftw(*file, treecopy, 1)); free(*file); } if (list) free(list); } int treecopy(const char *file, const struct stat *sb, int flag) { static int first = 1; static int karma; int fid; if(first){ currentKarma(0, &karma); first=0; } if(flag==FTW_F) { fid = lk_rio_write(karma, file); printf("Uploading fid %d, %s: %s\n", fid, file, (fid>0)?"ok":"failed"); } return 0; } uint32_t * searchStr(int exact, char *searchString, char *unkName) { int sizec=0, andOr=-1; /* andOr = 1 (and), 0 (or) */ uint32_t *vc=NULL, *vp=NULL; /* vc/vp : current/previous */ char *keyValue=NULL, *key=NULL; char *opp=NULL, op='\0'; /* op: logical operator; opp: op pointer */ if (searchString==NULL) return NULL; op = ((opp = strpbrk(searchString, ",+"))==NULL) ? '\0' : opp[0]; keyValue=strsep(&searchString, "+,"); /* searchString -> */ /* past "," or "+" */ while (keyValue!=NULL) { key=utf8_to_codeset(keyValue); fprintf(stderr, "%9s FIDs with \"%-30s\":", (andOr==-1)?"Searching":(andOr?"ANDing":"ORing"),key); free(key); if(andOr==-1) andOr = ORS; if(exact) andOr = EXACT|andOr; key=strsep(&keyValue, "="); /* keyValue -> past the "=" */ if(!keyValue || strcmp(keyValue, unkName) == 0){ keyValue = NULL; andOr = EXACT|andOr; } if (vp){ vc=lk_properties_andOrSearch(andOr, vp, key, keyValue); /* frees vp */ vp=NULL; }else vc=lk_properties_andOrSearch(andOr, NULL, key, keyValue); sizec=0; if(vc != NULL) { while(vc[sizec] != 0) sizec++; /* size of vc */ vp = malloc((sizec+1)*sizeof(uint32_t)); memcpy(vp, vc, (sizec+1)*sizeof(uint32_t)); /* copy vp=vc */ free(vc); } fprintf(stderr, " %4d selected\n", sizec); if (searchString==NULL) break; andOr = (op==','); op = ((opp = strpbrk(searchString, ",+"))==NULL) ? '\0' : opp[0]; keyValue=strsep(&searchString, "+,"); /* searchString -> */ /* past "," or "+" */ } return vp; } void deleteFids(uint32_t *vp) { int karma, c; currentKarma(0, &karma); for (c=0; vp[c]!=0; c++) if (vp[c]!=256) { /* ignoring root playlist */ fprintf(stderr, "lk_karma_delete_file(fid=%d): %s\n", vp[c], CHECK(lk_karma_delete_file(karma, vp[c]))); /* lk_properties_del_property(vp[c]); *//* now in lk_karma_delete_file() */ } } /* -------------------------------------------------------------------------- */ /* ------------------ Pathname editing: now in pathedit.c ------------------- */ /* -------------------------------------------------------------------------- */ static uint32_t *addPlayListContents( uint32_t PLfid, uint32_t *previousFids) { int i, j, count; uint32_t fid, fidGeneration, *vp = previousFids; playlist *pl; pl = lk_playlist_fid_read(PLfid); count = lk_playlist_count(pl); printf("#---- Contents of playlist \"%s\" (fid=%d, %d entries)\n", pl->name, pl->fid, count); j=0; if(!vp) { vp = malloc(count*sizeof(uint32_t)+1); } else { while(vp[j]!=0) j++; vp = realloc(vp, (j+count)*sizeof(uint32_t)+1); } for (i=0; i<count; i++, j++) { lk_playlist_get_item(pl, i, &fid, &fidGeneration); vp[j] = fid; } vp[j] = 0; return vp; } void downloadFids(uint32_t *vp, int doDownload, char *unkName, char* useTuneProps, char* useTaxiProps, char* usePlstProps, char* edPathStr1, char* edPathStr2, char* edPathStr3, int squeezeRep, int expandPlaylists, char *playListName) { #define FLEN 512 int karma, i, j, len, pos; char c, cc, *useProps=NULL, filename[FLEN]; char *type, *genre, *artist,*source, *title, *tracknr, *codec; char *s; uint32_t fid, *vl; # define STRCAT(a,b) do { \ s = ((b&&strlen(b))?b:unkName); \ len = strlen(s); \ if (pos+len+1 < FLEN) { \ memcpy((a)+pos, s, len); \ pos += len; \ } \ } while(0) currentKarma(0, &karma); if(doDownload != 0 && vp[0] != 0) printf("# Fid Name\n#------------------------------------------\n"); for (j=0; vp[j]!=0; j++) { fid=vp[j]; type=lk_properties_get_property(fid, "type"); if(type==NULL) { fprintf(stderr, "**Could not get type of fid=%d\n", fid); return; } if(strcmp((char *)type, "playlist") == 0) { if(expandPlaylists) { vl = addPlayListContents(fid, NULL); title = lk_properties_get_property(fid, "title"); downloadFids(vl, doDownload, unkName, usePlstProps, usePlstProps, usePlstProps, edPathStr1, edPathStr2, edPathStr3, squeezeRep, expandPlaylists, title); free(vl); continue; } else useProps=strdup(usePlstProps); } if(strcmp((char *)type, "taxi") == 0) useProps=strdup(useTaxiProps); if(strcmp((char *)type, "tune") == 0) useProps=strdup(useTuneProps); pos = 0; for (i=0; useProps[i]!='\0'; i++) { cc=(useProps[i]); if (cc != '%') { /* just copy all non-special chars */ if (pos+2 < FLEN) { memcpy(filename+pos, useProps+i, 1); pos++; } continue; } /* if(cc == '%') */ c=useProps[++i]; switch(c) { case '\0': fprintf(stderr, "** Format error: %s\n", useProps); i--; break; case '%': if (pos+2 < FLEN) { memcpy(filename+pos, useProps+i, 1); pos++; } break; case 'T': /* <type> */ STRCAT(filename, type); break; case 'g': /*< genre> */ genre=lk_properties_get_property(fid, "genre"); STRCAT(filename, genre); break; case 'a': /* <artist> */ artist=lk_properties_get_property(fid, "artist"); artist=utf8_to_codeset(artist); STRCAT(filename, artist); if(artist) free(artist); break; case 's': /* <source> (album) */ source=lk_properties_get_property(fid, "source"); source=utf8_to_codeset(source); STRCAT(filename, source); if(source) free(source); break; case 'f': /* <fid> */ STRCAT(filename, simple_itoa(fid)); break; case 't': /* <title> */ title=lk_properties_get_property(fid, "title"); title=utf8_to_codeset(title); STRCAT(filename, title); if(title) free(title); else{ fprintf(stderr, "*Could not get title of fid=%d\n", fid); } break; case 'n': /* <tracknr> */ tracknr=lk_properties_get_property(fid, "tracknr"); STRCAT(filename, tracknr); break; case 'c': /* <codec>|"playlist" */ if(strcmp((char *)type, "playlist") == 0) STRCAT(filename, type); else{ codec=lk_properties_get_property(fid, "codec"); STRCAT(filename, codec); if(!codec){ fprintf(stderr, "*Could not get codec of fid=%d\n", fid); return; } } break; case 'l': /* playlist name */ if(expandPlaylists && playListName) STRCAT(filename, playListName); break; default: fprintf(stderr, "* Unknown property \'%c\' - ignored\n", c); break; } /* switch(c) */ } /* for i=0 ... */ filename[pos] = '\0'; free(useProps); /* 'tr'-editing filename */ if(edPathStr1 && edPathStr2 && edPathStr3) tr(filename, edPathStr1, edPathStr2, edPathStr3, squeezeRep); if(doDownload) { fprintf(stderr, "Downloading fid %i to %s\n", fid, filename); if(strcmp((char *)type, "playlist") == 0) { fprintf(stderr, "lk_rio_read_playlist %s\n", CHECK(lk_rio_read_playlist(karma, fid, filename))); }else{ fprintf(stderr, "lk_rio_read %s\n", CHECK(lk_rio_read(karma, fid, filename))); } }else{ printf("%5i %s\n", fid, filename); } filename[0]='\0'; if((!doDownload) && (vp[j+1]==0)) printf("#---- -------------------------------------\n"); } } double getUsedSize(int karma) { /* int rio; uint32_t storage_id; */ uint32_t n_files, highest_file_id; uint64_t s_size, f_space; double size, freeSpace; n_files=s_size=f_space=highest_file_id=0; lk_karma_get_storage_details(karma, 0, &n_files, &s_size, &f_space, &highest_file_id); size = s_size; freeSpace = f_space; /* fprintf(stderr, "%E", size - freeSpace); */ return(size - freeSpace); } /* ************************************************************************** */ int main(int argc, char * argv[]) { int i, c, r; char *settings; char *host=NULL; char *usercodeset=NULL;/*="ISO8859-15";*/ char *psw=NULL; /* "psw" is a bit better to search than old "p" ;) */ char *searchString=NULL; char *tunePropsToUse="%f.%c"; /* props string for tune download paths */ char *taxiPropsToUse=NULL; /* props string for taxi download paths */ char *plstPropsToUse=NULL; /* props string for playlst downld paths*/ char *editPathStr1=NULL; char *editPathStr2=NULL; char *editPathStr3=NULL; char *unkName=UNK_NAME; /* Dummy name for missing properties */ int expandPlaylists=0; int squeezeRepeats=0; int download=0; int fdbDownload=0; int removeFiles=0; int exact=0; int useSmalldb=1; int writeSmalldb=1; int checkHost=0; int ret=0; char yesNot='N'; int karma; uint16_t port; uint32_t *vp=NULL; /* vector of fids */ int dbChanged; char *utf; char *device=NULL; char *fdb=NULL; while ((c = getopt(argc, argv, "dhqrRbwfFHLa:c:e:p:s:S:u:x:l:D:U:")) != -1) { switch(c) { case 'h': case '?': usage(1); return -1; break; case 'd': download=1; break; case 'r': removeFiles=1; break; case 'R': removeFiles=2; /* don't ask confirmation questions */ break; case 'b': useSmalldb=0; break; case 'w': writeSmalldb=0; break; case 'f': lk_karma_write_dupes(1); break; case 'F': fdbDownload=1; checkHost=0; break; case 'H': fdbDownload=1; checkHost=1; break; case 'a': host=strdup(optarg); break; case 'c': usercodeset=strdup(optarg); break; case 'e': editPathStr1=strdup(optarg); if (optind>argc-2) {usage(1); return -1;} editPathStr2=strdup(argv[optind]); optind++; editPathStr3=strdup(argv[optind]); optind++; break; case 'q': squeezeRepeats=1; break; case 'p': psw=strdup(optarg); break; case 's': searchString=strdup(optarg); break; case 'S': searchString=strdup(optarg); exact = 1; break; case 'u': tunePropsToUse=strdup(optarg); break; case 'x': taxiPropsToUse=strdup(optarg); break; case 'l': plstPropsToUse=strdup(optarg); break; case 'D': unkName=strdup(optarg); break; case 'L': expandPlaylists = 1; break; case 'U': fdb=strdup(optarg); break; default: fprintf(stderr, "unknown option %c\n", c); break; } } if(taxiPropsToUse==NULL) taxiPropsToUse=strdup(tunePropsToUse); if(plstPropsToUse==NULL) plstPropsToUse=strdup(taxiPropsToUse); lk_errors_autoprint(0); if(useSmalldb) lk_karma_use_smalldb(); if(!host) { /* 'host' means a net host name, an IP, or mount directory */ /* trying to find a USB/OMFS-mounted Karma */ lk_errors_number(); lk_mountSearch_discover(&device, &host); host?fprintf(stderr, "Karma found: %s mounted on %s\n", device, host) :fprintf(stderr, "No mounted Karma found; trying Ethernet.\n"); } if (!host) { /* trying to find an Ethernet-connected Karma */ fprintf(stderr, "SSDP:"); for(i=0; (i<=ssdpRetry)&&(host==NULL); i++) { lk_errors_number(); lk_ssdp_discover(&host, &port); host?fprintf(stderr, " %s:%i\n", host, port) :fprintf(stderr, "."); } if(!host) fprintf(stderr, " no Karma found.\n"); } if (!host) { lk_errors_p("*", " -- Can't connect to Rio Karma\n"); usage(0); if(psw) free(psw); if(searchString) free(searchString); if(usercodeset) free(usercodeset); return -1; } karma=lk_karma_connect(host); lk_errors_p("",""); free(host); if(karma < 0) { fprintf(stderr, "unable to connect to rio karma\n\n"); usage(0); if(psw) free(psw); if(searchString) free(searchString); if(usercodeset) free(usercodeset); return -1; } currentKarma(1,&karma); /*lk_properties_init("ISO8859-15");*/ if(usercodeset != NULL){ lk_properties_init(); utf8_set_codeset(usercodeset); if (lk_errors_p("", "; Trying locale...")) { free(usercodeset); usercodeset = NULL; } } if(usercodeset == NULL){ if (! setlocale(LC_CTYPE, "")) fprintf(stderr,"* Warning: setlocale failed."); if(strlen(usercodeset = nl_langinfo(CODESET)) == 0) { fprintf(stderr, "* Warning: nl_langinfo problem; " "using default codeset %s\n", defaultCodeset); usercodeset = defaultCodeset; } lk_properties_init(); utf8_set_codeset(usercodeset); if(! lk_errors_p("","")) fprintf(stderr, "* Using %s codeset.\n", usercodeset); /*free(usercodeset);*/ } fprintf(stderr, "Using %s codeset.\n", usercodeset); lk_errors_autoprint(1); /* Setting auto-print-errors ON */ if(psw){ fprintf(stderr, "lk_karma_authenticate: %i\n", lk_karma_authenticate(karma, psw)); free(psw); }else fprintf(stderr, "lk_karma_authenticate: %i\n", lk_karma_authenticate(karma, "")); r = lk_karma_request_io_lock(karma,IO_LOCK_R); fprintf(stderr, "lk_karma_request_io_lock: %s\n", CHECK(r)); if(r == -1){ printf("Access Denied!\n"); lk_karma_hangup(karma); close(karma); lk_properties_destroy(); utf8_destroy(); return -1; } lk_karma_get_device_settings(karma, &settings); dbChanged = lk_properties_cache_obsolete(); if(dbChanged) { fprintf(stderr, "Downloading Rio database... "); fflush(stdout); if(getUsedSize(karma)>3E9) fprintf(stderr, " please wait... "); fflush(stderr); } free(settings); if(!r) lk_karma_load_database(karma); if(dbChanged) fprintf(stderr, "Done!\n"); if(fdbDownload) fdb_download(checkHost); if (searchString != NULL){ utf=utf8_from_codeset(searchString); free(searchString); vp=searchStr(exact, utf, unkName); free(utf); } if(vp) downloadFids(vp, download, unkName, tunePropsToUse, taxiPropsToUse, plstPropsToUse, editPathStr1, editPathStr2, editPathStr3, squeezeRepeats, expandPlaylists, NULL); if(taxiPropsToUse) free(taxiPropsToUse); if(plstPropsToUse) free(plstPropsToUse); if(removeFiles>0 && vp) { yesNot='Y'; for (i=0; vp[i]!=0; i++) continue; if(i>0) { printf("Ready to remove %d files; ", i); if(removeFiles==1) { printf("proceed (Y/N)? "); scanf("%c", &yesNot); }else{ printf("\n"); } if(yesNot!='Y' && yesNot!='y') printf("Remove aborted!\n"); else { fprintf(stderr, "lk_karma_request_io_lock (W): %s\n", CHECK(lk_karma_request_io_lock(karma,IO_LOCK_W))); deleteFids(vp); } } else fprintf(stderr, "No files to remove!\n"); } if(optind < argc || fdb){ fprintf(stderr, "lk_karma_request_io_lock (W): %s\n", CHECK(lk_karma_request_io_lock(karma,IO_LOCK_W))); if(lk_synchronize_necessary(karma)){ lk_karma_get_all_file_details(karma, &psw); lk_properties_import(psw); free(psw); } } if(optind < argc){ for(; optind<argc; optind++) ftw(argv[optind], treecopy, 1); } if (fdb) { fdb_upload(fdb); } lk_properties_save(); if (writeSmalldb) { ret = lk_karma_write_smalldb(); if (ret) fprintf(stderr, "error writing smalldb file\n"); } fprintf(stderr, "lk_karma_release_io_lock: %s\n", CHECK(lk_karma_release_io_lock(karma))); fprintf(stderr, "lk_karma_hangup: %s\n", CHECK(lk_karma_hangup(karma))); close(karma); free(vp); lk_properties_destroy(); utf8_destroy(); return ret; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/tools/Jamfile������������������������������������������������������������������������0000664�0001750�0000012�00000000725�11543330237�015103� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������SubDir TOP tools ; SubDirHdrs $(TOP)/src ; if $(STATIC) { LinkLibraries chprop riocp playlist_show : libkarma ; } else { LINKFLAGS += -lkarma -L$(TOP)/obj ; DEPENDS riocp chprop : libkarma.so ; } LINKFLAGS += -ltag_c ; Main chprop : chprop.c ; Main playlist_show : playlist_show.c ; if $(OS) = LINUX { Main riocp : riocp.c pathedit.c ; } else { Main riocp : riocp.c pathedit.c ftw.c ; } InstallBin $(PREFIX)/bin : chprop ; InstallBin $(PREFIX)/bin : riocp ; �������������������������������������������libkarma-0.1.2/tools/rioRegexp.sh�������������������������������������������������������������������0000644�0001750�0000012�00000000264�11543330237�016105� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/bash rioDB=`ls ~/.openrio/pearl-*/fileinfo | head -1` cat $rioDB | grep -v profile= | awk '!/^ *$/{printf "%s #_# ", $0}/^ *$/{printf "\n"}' | egrep $* | sed s'/ #_# /\ /g' ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/tools/karma_helper.1�����������������������������������������������������������������0000644�0001750�0000012�00000003464�11543330237�016326� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH KARMA_HELPER 1 "June 27, 2008" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp <n> insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME karma_helper \- adjusts the state of the Rio Karma .SH SYNOPSIS .B karma_helper .RI [ options ] " files" ... .SH DESCRIPTION This manual page documents briefly the .B karma_helper command. .PP .\" TeX users may be more comfortable with the \fB<whatever>\fP and .\" \fI<whatever>\fP escape sequences to invode bold face and italics, .\" respectively. \fBkarma_helper\fP is a program that sends USB commands to the Rio Karma to modify its state. .SH OPTIONS A summary of options is included below. .TP .B \-b Bind driver to device. .TP .B \-e Enter storage mode. .TP .B \-h Show summary of options. .TP .B \-i Retrieve device information string. .TP .B \-l Leave storage mode. .TP .B \-r Reset device (leave "Finished" screen). .TP .B \-t Update time. .TP .B \-u Unbind driver from device. .SH NOTES karma_helper requires root priveliges to directly access the USB layer and send most of the available commands. .SH SEE ALSO .BR riocp (1). .SH AUTHOR karma_helper was written by Frank Zschockelt <libkarma@freakysoft.de>. .PP This manual page was written by Joe Nahmias <jello@debian.org>, for the Debian project (but may be used by others). ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/tools/karma_helper.c�����������������������������������������������������������������0000644�0001750�0000012�00000016545�11543330237�016414� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * RIO Karma helper utility. */ #include <stdio.h> #include <usb.h> #include <string.h> #include <dirent.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <pwd.h> #define RIO_PROD 0x5210 #define RIO_SPROD "5210" #define RIO_VENDOR 0x045a #define RIO_SVEND "045a" #define RIO_DEV_DIR "/sys/bus/usb/devices/" #define RIO_BIND "/sys/bus/usb/drivers/usb-storage/bind" typedef struct usb_device usb_dev_t; #ifndef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP #define usb_detach_kernel_driver_np(a, b) (0) #endif static char *sysfs_read_dev(char *dev) { DIR *dir, *dir2; struct dirent *ent, *ent2; char c; char dirname[64]; char id[4]; int dirlen, devlen, prod, vend, fd; dir = opendir(RIO_DEV_DIR); if (!dir) return NULL; while ( (ent = readdir(dir)) != NULL) { c = ent->d_name[0]; if (c < '0' || c > '9') continue; dirlen = strlen(RIO_DEV_DIR); devlen = strlen(ent->d_name); memcpy(dirname, RIO_DEV_DIR, dirlen); memcpy(dirname+dirlen, ent->d_name, devlen); dirlen += devlen; dirname[dirlen++] = '/'; dirname[dirlen] = '\0'; dir2 = opendir(dirname); if (!dir2) continue; prod = vend = 0; while ( (ent2 = readdir(dir2)) != NULL) { if (memcmp(ent2->d_name, "idVendor", 8) == 0) { memcpy(dirname+dirlen, ent2->d_name, strlen(ent2->d_name)+1); fd = open(dirname, O_RDONLY); if (fd == -1) goto next; read(fd, id, 4); close(fd); if (memcmp(id, RIO_SVEND, 4) != 0) goto next; if (prod) goto found; vend = 1; } else if (memcmp(ent2->d_name, "idProduct", 9) == 0) { memcpy(dirname+dirlen, ent2->d_name, strlen(ent2->d_name)+1); fd = open(dirname, O_RDONLY); if (fd == -1) goto next; read(fd, id, 4); close(fd); if (memcmp(id, RIO_SPROD, 4) != 0) goto next; if (vend) goto found; prod = 1; } } next: closedir(dir2); dir2 = NULL; } if (dir2) closedir(dir2); if (dir) closedir(dir); return NULL; found: if (dir2) closedir(dir2); if (dir) closedir(dir); memcpy(dev, ent->d_name, devlen); memcpy(dev+devlen, ":1.0", devlen+5); return dev; } static void usage(int ret) { printf("usage: karma_helper [-b] [-u] [-e] [-l] [-r] [-t] [-i] [-h]\n\n" "options:\n" " -b bind driver to device\n" " -u unbind driver from device\n" " -e enter storage mode\n" " -l leave storage mode\n" " -r reset device (leave \"Finished\" screen)\n" " -t update time\n" " -i retrieve device information string\n" " -h display usage info\n"); exit(ret); } static usb_dev_t *get_device(int vendor, int product) { struct usb_device *device; struct usb_bus *bus; for (bus = usb_busses; bus; bus=bus->next) { for (device = bus->devices; device; device=device->next) { if (device->descriptor.idVendor == vendor && device->descriptor.idProduct == product) { return device; } } } return NULL; } int main(int argc, char **argv) { int i, ret, seq, cmd, fd = 0, sent = 0; time_t sec = 0; char riop[] = "RIOP"; char request[40]; char response[512]; usb_dev_t *device; usb_dev_handle *handle; int bind = 0; int unbind = 0; int info = 0; if (argc != 2 || *argv[1] != '-') usage(1); switch (*(argv[1]+1)) { case 'h': usage(0); break; case 'b': bind = 1; break; case 'u': unbind = 1; break; case 'e': cmd = 0x1; break; case 'l': cmd = 0x2; break; case 'r': cmd = 0xc; break; case 't': #ifndef __APPLE__ tzset(); sec = time(NULL) - timezone + daylight * 3600; cmd = 0x7; #endif break; case 'i': info = 1; cmd = 0x5; break; default: usage(1); } /* check for console permissions given by pam_console */ if (getuid() != 0) fd = open("/var/run/console/console.lock", O_RDONLY); if (fd > 0) { char *name = response; struct passwd *pass; ret = read(fd, name, 64); close(fd); if (!ret) goto err; name[ret] = '\0'; pass = getpwnam(name); if (!pass) goto err; if (pass->pw_uid == getuid()) goto ok; err: fprintf(stderr, "error: user does not have console ownership\n"); return 1; } ok: if (bind) { struct stat st; char *dev = request; char *bound = response; int len; fd = open(RIO_BIND, O_WRONLY); if (fd == -1) { fprintf(stderr, "error: unable to open " RIO_BIND "\n"); return 1; } dev = sysfs_read_dev(dev); if (!dev) { fprintf(stderr, "error: unable to find karma\n"); return 1; } len = strlen(RIO_BIND)-4; memcpy(bound, RIO_BIND, len); memcpy(bound+len, dev, strlen(dev)+1); ret = -1; for (i = 0; i < 100 && ret == -1; i++) { len = write(fd, dev, strlen(dev)); ret = stat(bound, &st); usleep(10); } close(fd); return ret; } seq = 0x10; usb_init(); usb_find_busses(); usb_find_devices(); if (!(device = get_device(RIO_VENDOR, RIO_PROD))) { fprintf(stderr, "Could not open device\n"); exit(1); } handle = usb_open(device); #ifdef __linux__ if (unbind) return usb_detach_kernel_driver_np(handle, 0); #endif if (usb_claim_interface(handle, 0) < 0) { perror("user.c"); exit(1); } usb_resetep(handle, 0x02); usb_resetep(handle, 0x88); memset(request, 0, sizeof(request)); memset(response, 0, sizeof(response)); strcpy (request, riop); request[5] = cmd; request[6] = seq; if (sec) memcpy(request+8, &sec, sizeof(sec)); usb_bulk_write(handle, 0x02, request, sizeof(request), 1000); usb_bulk_read(handle, 0x88, response, sizeof(response), 1000); for (i = 0; i < 100 && !sent; i++) { memset(request, 0, sizeof(request)); memset(response, 0, sizeof(response)); strcpy (request, riop); request[4] = (char)0x80; request[5] = 0; request[6] = seq; usb_bulk_write(handle, 0x02, request, sizeof(request), 1000); usb_bulk_read(handle, 0x88, response, sizeof(response), 1000); sent = (response[5] == request[6]); if (!sent) usleep(10); else if (info) printf("\n%s\n", &response[7]); } usb_release_interface(handle, 0); usb_close(handle); return 0; } �����������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/tools/playlist_show.c����������������������������������������������������������������0000644�0001750�0000012�00000001666�11543330237�016661� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <stdlib.h> #include <lkarma.h> int main(void){ playlist * pl; uint32_t fid, fidg; uint32_t * tmp; int k,i; lk_properties_init(); k=lk_karma_connect("10.0.0.42"); lk_karma_authenticate(k, "rio"); lk_karma_request_io_lock(k,IO_LOCK_R); lk_karma_load_database(k); lk_karma_hangup(k); lk_properties_save(); tmp=lk_properties_andOrSearch(0, NULL, "type", "playlist"); for(i=0;tmp[i]!=0;i++){ pl=lk_playlist_fid_read(tmp[i]); printf("%i,%i,%i\n", tmp[i], lk_playlist_count(pl), pl->length); for(k=0;k<lk_playlist_count(pl);k++){ lk_playlist_get_item(pl, k, &fid, &fidg); printf("playlist %s, %i, fid %u, fid_generation %u\n", lk_playlist_get_name(pl), k, fid, fidg); } lk_playlist_free(&pl); } lk_properties_destroy(); free(tmp); return 0; } ��������������������������������������������������������������������������libkarma-0.1.2/tools/chprop.1�����������������������������������������������������������������������0000644�0001750�0000012�00000003072�11543330237�015162� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH CHPROP 1 "January 1, 2007" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp <n> insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME chprop \- change file properties on the Rio Karma .SH SYNOPSIS .B chprop .BI "-a " hostname/ip .RI [ -p " " password ] .I fid key value .SH DESCRIPTION This manual page documents briefly the .B chprop command. .PP \fBchprop\fP is a program that changes properties of files on the Rio Karma. .SH OPTIONS A summary of options is included below. .TP .B \-a \fIhost/IP\fP Set access location of Rio Karma. Can be either a hostname or IP address for network access; or a path in the filesystem where the Rio Karma is mounted for USB access. .TP .B \-h Show summary of options. .TP .B \-p \fIpassword\fP Password for accessing the Rio Karma via the network. .SH SEE ALSO .\" .BR bar (1), .BR riocp (1). .SH AUTHOR chprop was written by Frank Zschockelt <libkarma@freakysoft.de>. .PP This manual page was written by Joe Nahmias <jello@debian.org>, for the Debian project (but may be used by others). ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/tools/chprop.c�����������������������������������������������������������������������0000644�0001750�0000012�00000004306�11543330237�015245� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * libkarma/chprop.c * * Copyright (c) Frank Zschockelt <libkarma@freakysoft.de> 2004 * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <lkarma.h> #define CHECK(x) x?"failed":"ok" void usage(void); void usage(void) { printf("usage: chprop -a hostname/ip [-p password] fid key value\n"); } int main(int argc, char * argv[]) { int c; int karma; char *host=NULL; char *p=NULL; uint32_t fid; while ((c = getopt(argc, argv, "ha:p:s:")) != -1) { switch(c) { case 'h': usage(); return -1; break; case 'a': host=strdup(optarg); break; case 'p': p=strdup(optarg); break; case '?': printf("unknown arg %c\n", optopt); break; } } if((!host) ||(optind+3 != argc)){ usage(); if(p) free(p); return -1; } karma=lk_karma_connect(host); free(host); if(karma < 0){ usage(); if(p) free(p); return -1; } lk_properties_init(); if(p){ printf("lk_karma_authenticate: %i\n", lk_karma_authenticate(karma, p)); free(p); }else printf("lk_karma_authenticate: %i\n", lk_karma_authenticate(karma, "")); printf("lk_karma_request_io_lock: %s\n", CHECK(lk_karma_request_io_lock(karma,IO_LOCK_W))); lk_karma_get_device_settings(karma, &p); lk_karma_load_database(karma); fid=strtoul(argv[optind], (char **) NULL, 10); lk_properties_set_property(fid, argv[optind+1], argv[optind+2]); p=lk_properties_export(fid); printf("lk_karma_update_file_details: %s\n", CHECK(lk_karma_update_file_details(karma, fid, p))); free(p); printf("lk_karma_release_io_lock: %s\n", CHECK(lk_karma_release_io_lock(karma))); printf("lk_karma_hangup: %s\n", CHECK(lk_karma_hangup(karma))); close(karma); lk_properties_destroy(); return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/tools/create_smalldb�����������������������������������������������������������������0000755�0001750�0000012�00000001371�11543330237�016474� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/bash if [ $# -lt 1 ] || [ "${1%elp}" = "-h" ] || [ "${1%elp}" = "--h" ] ; then echo "\ Usage: ${0##*/} [-h] karma_mount_point Mounts the RK on karma_mount_point and creates an empty index file (var/smalldb), along with a fids directory (fids0/_00000), if needed. " exit 0 fi # WASMOUNTED=1 if mount $1 2>/dev/null ; then WASMOUNTED=0 echo -n Mounting the RK on $1" " while mount $1 2>/dev/null ; do sleep 1 ; echo -n \. ; done echo " "mounted! fi mkdir -p $1/{var,fids0/_00000} if [ -f $1/var/smalldb ] ; then echo The file $1/var/smalldb already existed. else echo Creating empty $1/var/smalldb touch $1/var/smalldb fi if [ $WASMOUNTED == 0 ] ; then echo -n Unmounting $1 ..." " umount $1 echo done! fi�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/tools/pathedit.c���������������������������������������������������������������������0000644�0001750�0000012�00000011705�11543330237�015555� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * libkarma/pathedit.c * * Pathname editing * * Copyright (c) Enrique Vidal 2005, adapted from "tr.c", * Copyright (c) ams@wiw.org (Abhijit Menon-Sen) 1998. * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. */ #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define ins(p, c) *p++ = c #define next(p) *p++ int isodigit (char d); char esc(char c); char *expand(char *str); void tr(char *str, char *orig, char *sub, char *del, int squeezeRep); int isodigit (char d) { if ('0' <= d && d <= '7') { return 1; } return 0; } char esc(char c) { switch (c) { case 'a': c = '\a'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'v': c = '\v'; break; default: break; } return (c); } char *expand(char *str) { static char buf[512], num[8]; char i, j=0, k, *o = buf, *p = num; int a, class = 0; while ((i = next(str))) { switch (i) { case '\\': if (!(k = next(str))) { fprintf(stderr, "hanging '\\'.\n"); exit(1); } else if (tolower(k) == 'x') { p = num; if ((k = next(str)) == 0 || !isxdigit(k)) { fprintf(stderr, "parse error in \\x.\n"); exit(1); } *p++ = k; *p = 0; a = strtol(num, NULL, 16); if ((k = next(str)) == 0 || !isxdigit(k)) { ins(o, (char)a); str--; } else { *p++ = k; *p = 0; a = strtol(num, NULL, 16); ins(o, (char)a); } } else if (isodigit(k)) { p = num; *p++ = k; *p = 0; a = strtol(num, NULL, 8); if ((k = next(str)) == 0 || !isodigit(k)) { ins(o, (char)a); str--; } else { *p++ = k; *p = 0; a = strtol(num, NULL, 8); if ((k = next(str)) == 0 || !isodigit(k)) { ins(o, (char)a); str--; } else { *p++ = k; *p = 0; a = strtol(num, NULL, 8); ins(o, (char)a); } } } else { ins(o, esc(k)); } break; case '[': if (++class > 1) { fprintf(stderr, "* Literal [ inside character class.\n"); exit(1); } break; case '.': if (!class) { ins(o, '.'); } else { for (a = 0x20; a < 0x7f; ++a) { ins(o, (char)a); } } break; case '-': if (!class || (k = next(str)) == ']') { ins(o, '-'); if (class) { class--; } } else { if (j < k) { for (i = j+1; i <= k; ++i) { ins(o, i); } } else if (k < j) { for (i = j-1; i >= k; --i) { ins(o, i); } } } break; case ']': if (--class) { fprintf(stderr,"* literal ] outside character class.\n"); exit(1); } break; default: ins(o, i); } j = i; } ins(o, 0); return (buf); } void tr(char *str, char *orig, char *sub, char *del, int squeezeRep) { char c, a[1024], b[1024], d[1024]; int tab[256], i, cc, s1, s2; char *q, *p=str; for (i = 0; i < 256; ++i) { tab[i] = i; } strcpy(a, expand(orig)); strcpy(b, expand(sub)); strcpy(d, expand(del)); s1 = strlen(a); s2 = strlen(b); for (i = 0; i < s1; ++i) { cc=(int)a[i]; cc = (cc<0)?cc+256:cc; tab[cc] = i < s2 ? b[i] : b[s2 - 1]; /* tab[(int)a[i]] = i < s2 ? b[i] : b[s2 - 1]; */ } while ((c = *str)) { cc = (c<0)?c+256:c; *str++ = tab[cc]; } /* /////////////// Moved AFTER delete if (squeezeRep) { q=str=p; while ((c = *str)) { *str++; if ((c != *str) || (strchr(b, c)==NULL)) {*q++; *q=*str;} } } */ if(del && (strlen(del)>0)) { q=str=p; while ((c = *str)) { if ((strchr(d, c)==NULL)) *q++=*str; str++; } *q='\0'; } if (squeezeRep) { q=str=p; while ((c = *str)) { str++; if ((c != *str) || (strchr(b, c)==NULL)) {q++; *q=*str;} } } } /* -------------------------- End pathname editing -------------------------- */ �����������������������������������������������������������libkarma-0.1.2/tools/pathedit.h���������������������������������������������������������������������0000644�0001750�0000012�00000000612�11543330237�015555� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * libkarma/pathedit.h * * Pathname editing * * Copyright (c) Enrique Vidal 2005, adapted from "tr.c", * Copyright (c) ams@wiw.org (Abhijit Menon-Sen) 1998. * * You may distribute and modify this program under the terms of * the GNU GPL, version 2 or later. */ #ifndef _PATHEDIT_H #define _PATHEDIT_H void tr(char *str, char *orig, char *sub, char *del, int squeezeRep); #endif ����������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/THANKS�������������������������������������������������������������������������������0000644�0001750�0000012�00000000546�11543330237�013363� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ * Julian Seward for writing valgrind * Michael R. Elkins for writing mutt (hash.c/hash.h) * Christophe Devine for md5.c/md5.h * goodvib.ratm.homeip.net for providing a basis for ssdp * Enrique Vidal (too much :)) * Paul van der Mark for writing playwav.c (wav.c/wav.h) * the authors of mp3info for mp3.c/mp3.h * the authors of boa for simple_itoa ����������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/Jamfile������������������������������������������������������������������������������0000664�0001750�0000012�00000000422�11543330237�013735� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������SubDir TOP ; PREFIX += /usr/local ; CCFLAGS += -fPIC -D_REENTRANT -Wall -pedantic ; if $(DEBUG) { CCFLAGS += -ggdb -W -Wchar-subscripts -Wmissing-prototypes -Wmissing-declarations -Wno-switch -Wredundant-decls -Wno-unused ; } SubInclude TOP src ; SubInclude TOP tools ; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/Jamrules�����������������������������������������������������������������������������0000664�0001750�0000012�00000006757�11543330237�014171� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������NOTFILE libs dlls objs lists ; ALL_LIBS_TO_BUILD ?= libs dlls ; BUILDMODE ?= obj ; LIBPREFIX ?= lib ; LIBLISTSUFFIX ?= .list ; TOUCH = touch ; if $(UNIX) { PUSHD = "( cd" ; POPD = ")" ; LDSHARE ?= ld ; LDSHARE_FLAGS ?= -G ; SUFLIBSHR ?= .so ; ECHO = echo ; } else if $(BEOS) { } makeDirName LIBDIR : $(TOP) $(BUILDMODE) ; rule LibMember { # $(1) is short name of lib these sources are destined for. # $(2) is list of source files. local l o ; SOURCE_GRIST = ; # (Implicit grist is a pain.) makeDirName LOCATE_TARGET : $(LIBDIR) lib$(1) ; # # e.g., binaries for 'foo' library go in $TOP/debug/libfoo # directory. Objects $(2) ; # Set up a list file for this library: getLibListName l : $(1) ; LOCATE on $(l) = $(LIBDIR) ; # # e.g., for the 'foo' library, the list file is # $TOP/debug/libfoo.list. if ! $(LIST-STARTED-$(<)) { LIST-STARTED-$(<) = true ; RemoveExistingFile $(l) : $(l) ; # # The RemoveTarget rule has to be invoked once only, # and before any of the EchoToFile rules are invoked. } o = $(2:S=$(SUFOBJ):G=:D=lib$(1)) ; NOTFILE $(o) ; # # $(o) is a list of object file names, sans grist, and # qualified by the subdir in which it is stored. Thus, # each element of $(o) uniquely identifies a compiled object # associated with a built library. Elements of $(o) will be # used as dependencies but are not bindable. EchoToFile $(l) : $(o) ; Depends $(l) : $(2:S=$(SUFOBJ)) ; # # The list file depends on the compiled objects. If any # of them are newer, the list file gets recreated. Seems odd, # but it works, because a list is only updated when you're # updating a library. Depends objs : $(2:S=$(SUFOBJ)) ; } rule BuildLib { # $(1) is short name of lib to build. # $(2) is list of dependent lib short names # $(3) is .def file, for NT. # $(4) is list of join lib short names. local list libs ; SOURCE_GRIST = ; if $(LIB$(1)) { Exit BuildLib used more than once on $(1) ; } LIB$(1) = $(LIBPREFIX)$(1)$(SUFLIB) ; DLL$(1) = $(LIBPREFIX)$(1)$(SUFLIBSHR) ; libs = $(LIB$(1)) $(DLL$(1)) ; MakeLocate $(libs) : $(LIBDIR) ; if $(4) { getLibListName list : $(4) ; } else { getLibListName list : $(1) ; MakeLocate $(list) : $(LIBDIR) ; Clean clean : $(list) ; Depends lists : $(list) ; } Depends $(libs) : $(list) ; LIBLIST on $(libs) = $(list) ; LDSHARE_FLAGS on $(DLL$(1)) += $(LDSHARE_FLAGS) ; if $(BEOS) { } else { LinkDynamicLib $(DLL$(1)) ; RemoveExistingFile $(LIB$(1)) : $(LIB$(1)) ; ArchiveStaticLib $(LIB$(1)) ; if $(RANLIB) { Ranlib $(LIB$(<)) ; } } Depends libs : $(LIB$(1)) ; Depends dlls : $(DLL$(1)) ; Depends all : $(ALL_LIBS_TO_BUILD) ; Clean clean : $(libs) ; } actions quietly existing RemoveExistingFile { $(RM) $(>) } actions quietly together piecemeal EchoToFile { $(ECHO) $(>) >> $(<) } rule getLibListName { # $(1) is var to set. # $(2) is lib short name. # # E.g., "getLibListName l : foo ;" sets # l to libfoo.list. $(1) = lib$(2:S=$(LIBLISTSUFFIX)) ; } if $(UNIX) { actions LinkDynamicLib { $(PUSHD) $(<:D) $(LDSHARE) $(LDSHARE_FLAGS) $(LDSHARE_NAME_FLAG)$(<:BS) -o $(<:BS) `cat $(LIBLIST:BS) ` $(POPD) } actions ArchiveStaticLib { $(PUSHD) $(<:D) $(AR) $(<:BS) `cat $(LIBLIST:BS) ` $(POPD) } } else if $(BEOS) { actions LinkDynamicLib { } actions ArchiveStaticLib { } } actions quietly TouchFile { $(TOUCH) $(<) } �����������������libkarma-0.1.2/install-sh���������������������������������������������������������������������������0000755�0001750�0000012�00000022021�11543330237�014444� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/sh # install - install a program, script, or datafile scriptversion=2005-05-14.22 # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" chmodcmd="$chmodprog 0755" chowncmd= chgrpcmd= stripcmd= rmcmd="$rmprog -f" mvcmd="$mvprog" src= dst= dir_arg= dstarg= no_target_directory= usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: -c (ignored) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. --help display this help and exit. --version display version info and exit. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test -n "$1"; do case $1 in -c) shift continue;; -d) dir_arg=true shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; --help) echo "$usage"; exit $?;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -s) stripcmd=$stripprog shift continue;; -t) dstarg=$2 shift shift continue;; -T) no_target_directory=true shift continue;; --version) echo "$0 $scriptversion"; exit $?;; *) # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. test -n "$dir_arg$dstarg" && break # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dstarg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dstarg" shift # fnord fi shift # arg dstarg=$arg done break;; esac done if test -z "$1"; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi for src do # Protect names starting with `-'. case $src in -*) src=./$src ;; esac if test -n "$dir_arg"; then dst=$src src= if test -d "$dst"; then mkdircmd=: chmodcmd= else mkdircmd=$mkdirprog fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dstarg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dstarg # Protect names starting with `-'. case $dst in -*) dst=./$dst ;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dstarg: Is a directory" >&2 exit 1 fi dst=$dst/`basename "$src"` fi fi # This sed command emulates the dirname command. dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` # Make sure that the destination directory exists. # Skip lots of stat calls in the usual case. if test ! -d "$dstdir"; then defaultIFS=' ' IFS="${IFS-$defaultIFS}" oIFS=$IFS # Some sh's can't handle IFS=/ for some reason. IFS='%' set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` shift IFS=$oIFS pathcomp= while test $# -ne 0 ; do pathcomp=$pathcomp$1 shift if test ! -d "$pathcomp"; then $mkdirprog "$pathcomp" # mkdir can fail with a `File exist' error in case several # install-sh are creating the directory concurrently. This # is OK. test -d "$pathcomp" || exit fi pathcomp=$pathcomp/ done fi if test -n "$dir_arg"; then $doit $mkdircmd "$dst" \ && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } else dstfile=`basename "$dst"` # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 trap '(exit $?); exit' 1 2 13 15 # Copy the file name to the temp name. $doit $cpprog "$src" "$dsttmp" && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && # Now rename the file to the real destination. { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ || { # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { if test -f "$dstdir/$dstfile"; then $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ || { echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 (exit 1); exit 1 } else : fi } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" } } fi || { (exit 1); exit 1; } done # The final little trick to "correctly" pass the exit status to the exit trap. { (exit 0); exit 0 } # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/libkarma.fdi�������������������������������������������������������������������������0000600�0001750�0000012�00000003302�11543330237�014677� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="ISO-8859-1"?> <!-- -*- SGML -*- --> <deviceinfo version="0.2"> <device> <match key="@storage.originating_device:info.subsystem" string="usb"> <!-- SONICblue --> <match key="@storage.originating_device:usb.vendor_id" int="0x045a"> <!-- Rio Karma --> <match key="@storage.originating_device:usb.product_id" int="0x5210"> <match key="info.capabilities" contains_not="portable_audio_player"> <append key="info.capabilities" type="strlist">portable_audio_player</append> </match> <merge key="info.category" type="string">portable_audio_player</merge> <merge key="portable_audio_player.access_method" type="string">user</merge> <match key="portable_audio_player.access_method.protocols" contains_not="karma"> <append key="portable_audio_player.access_method.protocols" type="strlist">karma</append> </match> <append key="portable_audio_player.access_method.drivers" type="strlist">libkarma</append> <match key="portable_audio_player.output_formats" contains_not="audio/mpeg"> <append key="portable_audio_player.output_formats" type="strlist">audio/mpeg</append> </match> <match key="portable_audio_player.output_formats" contains_not="audio/x-ms-wma"> <append key="portable_audio_player.output_formats" type="strlist">audio/x-ms-wma</append> </match> <merge key="portable_audio_player.libkarma.protocol" type="string">karma</merge> <merge key="portable_audio_player.libkarma.name" type="string">SONICblue Rio Karma</merge> </match> </match> </match> </device> </deviceinfo> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/karma-tools.spec���������������������������������������������������������������������0000644�0001750�0000012�00000001653�11543330237�015555� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Summary: Rio Karma tools Name: karma-tools Version: 0.1.2 Release: 1.kb License: GPL Group: Development/Libraries Url: http://www.freakysoft.de/repos/libkarma Source: http://www.freakysoft.de/libkarma/libkarma-%{version}.tar.gz Packager: Keith Bennett <keith@mcs.st-and.ac.uk> BuildRoot: %{_tmppath}/%name-root %description Rio Karma tools %package -n libkarma-devel Summary: Rio Karma tools Group: Development/Libraries %description -n libkarma-devel Rio Karma tools %prep %setup -n libkarma-%{version} %build make PREFIX=%_prefix %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT make install PREFIX=%_prefix %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc ChangeLog COPYING INSTALL THANKS TODO %_bindir/riocp %_bindir/chprop %_bindir/playlist_show %attr(4755,root,root) %_bindir/karma_helper %files -n libkarma-devel %defattr(-,root,root) %_includedir/* %_libdir/* �������������������������������������������������������������������������������������libkarma-0.1.2/karma-sharp/�������������������������������������������������������������������������0000755�0001750�0000012�00000000000�11543330237�014651� 5����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/karma-sharp/Makefile�����������������������������������������������������������������0000644�0001750�0000012�00000002137�11543330237�016314� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ASSEMBLY_SOURCES=Song.cs Device.cs ASSEMBLY_RESOURCES= MCS=$(shell which gmcs) MCS_FLAGS = -debug ifeq ($(MCS),) HAS_MONO= else HAS_MONO=true endif ifdef HAS_MONO ASSEMBLY=karma-sharp.dll else ASSEMBLY= PRINT = Note: mcs not found, not building karma-sharp! endif all: $(ASSEMBLY) @echo $(PRINT) karma-sharp.pc: FORCE sed -e 's,@prefix@,$(PREFIX),g; s,@VERSION@,$(VERSION),g' \ karma-sharp.pc.in > karma-sharp.pc ifdef HAS_MONO install: $(ASSEMBLY) karma-sharp.pc $(ASSEMBLY).config ../install-sh -d $(DESTDIR)$(PREFIX)/lib/karma-sharp ../install-sh -d $(DESTDIR)$(PREFIX)/lib/pkgconfig ../install-sh -t $(DESTDIR)$(PREFIX)/lib/karma-sharp $(ASSEMBLY) $(ASSEMBLY).config ../install-sh -t $(DESTDIR)$(PREFIX)/lib/pkgconfig -m 0644 karma-sharp.pc else install: endif uninstall: FORCE $(RM) -r $(PREFIX)/lib/karma-sharp $(RM) $(PREFIX)/lib/pkgconfig/karma-sharp.pc $(ASSEMBLY): $(ASSEMBLY_SOURCES) $(ASSEMBLY_RESOURCES) $(MCS) $(MCS_FLAGS) -unsafe -target:library -out:$@ $(ASSEMBLY_SOURCES) $(ASSEMBLY_RESOURCES:%=-resource:%) -r:Mono.Posix clean: FORCE $(RM) *.dll *.mdb karma-sharp.pc FORCE: ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/karma-sharp/Makefile.orig������������������������������������������������������������0000644�0001750�0000012�00000002070�11543330237�017247� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ASSEMBLY_SOURCES=Song.cs Device.cs ASSEMBLY_RESOURCES= MCS=$(shell which mcs) MCS_FLAGS = -debug ifeq ($(MCS),) HAS_MONO= else HAS_MONO=true endif ifdef HAS_MONO ASSEMBLY=karma-sharp.dll else ASSEMBLY= PRINT = Note: mcs not found, not building karma-sharp! endif all: $(ASSEMBLY) @echo $(PRINT) karma-sharp.pc: FORCE sed -e 's,@prefix@,$(PREFIX),g; s,@VERSION@,$(VERSION),g' \ karma-sharp.pc.in > karma-sharp.pc ifdef HAS_MONO install: $(ASSEMBLY) karma-sharp.pc ../install-sh -d $(DESTDIR)$(PREFIX)/lib/karma-sharp ../install-sh -d $(DESTDIR)$(PREFIX)/lib/pkgconfig ../install-sh -t $(DESTDIR)$(PREFIX)/lib/karma-sharp $(ASSEMBLY) ../install-sh -t $(DESTDIR)$(PREFIX)/lib/pkgconfig -m 0644 karma-sharp.pc else install: endif uninstall: FORCE $(RM) -r $(PREFIX)/lib/karma-sharp $(RM) $(PREFIX)/lib/pkgconfig/karma-sharp.pc $(ASSEMBLY): $(ASSEMBLY_SOURCES) $(ASSEMBLY_RESOURCES) $(MCS) $(MCS_FLAGS) -unsafe -target:library -out:$@ $(ASSEMBLY_SOURCES) $(ASSEMBLY_RESOURCES:%=-resource:%) -r:Mono.Posix clean: FORCE $(RM) *.dll *.mdb karma-sharp.pc FORCE: ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/karma-sharp/karma-sharp.dll.config���������������������������������������������������0000664�0001750�0000012�00000000117�11543330237�021021� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<configuration> <dllmap dll="karma" target="libkarma.so.0" /> </configuration> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/karma-sharp/Device.cs����������������������������������������������������������������0000644�0001750�0000012�00000007410�11543330237�016401� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������using System; using System.IO; using System.Collections; using System.Runtime.InteropServices; namespace Karma { public delegate void OnUploadHandler(Song song); public class StorageDetails { public uint NumFiles; public ulong StorageSize; public ulong FreeSpace; public uint MaxFid; } public class Device { int rio_id; private ArrayList filesToAdd = new ArrayList(); [DllImport ("karma")] private static extern int lk_karma_connect(string ipHostOrPath); [DllImport ("karma")] private static extern void lk_karma_load_database(int rio); [DllImport ("karma")] private static extern void lk_karma_use_smalldb(); [DllImport ("karma")] private static extern void lk_karma_get_storage_details(int rio, int storage_id, out uint n_files, out ulong s_size, out ulong f_space, out uint highest_file_id); [DllImport ("karma")] private static extern IntPtr lk_properties_andOrSearch(int mode, IntPtr search_in, string key, string data); [DllImport ("karma")] private static extern int lk_rio_write(int rio, string filename); [DllImport ("karma")] private static extern int lk_karma_write_smalldb(); [DllImport ("karma")] private static extern int lk_karma_delete_file(int rio, int fid); [DllImport ("karma")] private static extern int lk_karma_request_io_lock(int rio, int type); [DllImport ("karma")] private static extern int lk_karma_release_io_lock(int rio); public event OnUploadHandler ProgressChanged; public Device(string ipHostOrPath) { rio_id = lk_karma_connect(ipHostOrPath); if (rio_id < 0) throw new ApplicationException("Failed to connect"); lk_karma_use_smalldb(); lk_karma_load_database(rio_id); } public StorageDetails GetStorageDetails() { uint nfiles; ulong size; ulong space; uint maxFid; lk_karma_get_storage_details(rio_id, 0, out nfiles, out size, out space, out maxFid); StorageDetails details = new StorageDetails(); details.NumFiles = nfiles; details.StorageSize = size; details.FreeSpace = space; details.MaxFid = maxFid; return details; } public ICollection GetSongs() { ArrayList songs = new ArrayList(); IntPtr fids = lk_properties_andOrSearch(0, IntPtr.Zero, "fid", ""); if (fids == IntPtr.Zero) return songs; int offset=0; int fid; while ((fid = Marshal.ReadInt32(fids, offset)) != 0) { Song tmp = new Song(fid); if (tmp.Type.Equals("tune")) songs.Add(tmp); offset += 4; } return songs; } public void QueueAddSong(string filename) { filesToAdd.Add(filename); } public void DeleteSong(int id) { lk_karma_request_io_lock(rio_id, 1); lk_karma_delete_file(rio_id, id); lk_karma_release_io_lock(rio_id); } public void Save() { lk_karma_request_io_lock(rio_id, 1); foreach (string filename in filesToAdd) { int fid = lk_rio_write(rio_id, filename); if (ProgressChanged != null && fid > 0) { ProgressChanged(new Song(fid)); } } filesToAdd.Clear(); lk_karma_release_io_lock(rio_id); lk_karma_write_smalldb(); } } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/karma-sharp/karma-sharp.pc.in��������������������������������������������������������0000644�0001750�0000012�00000000422�11543330237�020006� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������prefix=@prefix@ exec_prefix=${prefix} libdir=${prefix}/lib includedir=${prefix}/include Libraries=${prefix}/lib/karma-sharp/karma-sharp.dll Name: karma-sharp Description: karma-sharp - Library for interfacing with Rio Karma devices Version: @VERSION@ Libs: -r:${Libraries} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/karma-sharp/Song.cs������������������������������������������������������������������0000644�0001750�0000012�00000003724�11543330237�016114� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������using System; using System.IO; using System.Collections; using System.Runtime.InteropServices; using Mono.Unix.Native; namespace Karma { public class Song { int fid; [DllImport ("karma")] private static extern IntPtr lk_properties_get_property(int fid, string key); public Song(int fid) { this.fid = fid; } private string GetString(string key) { return Marshal.PtrToStringAnsi( lk_properties_get_property(fid, key)); } private int GetInt(string key) { try { string tmp = GetString(key); return (tmp == null) ? 0 : Int32.Parse(tmp); } catch (FormatException e) { return 0; } } public string Album { get { return GetString("source"); } } public string Artist { get { return GetString("artist"); } } public string Bitrate { get { return GetString("bitrate"); } } public string Codec { get { return GetString("codec"); } } public string Genre { get { return GetString("genre"); } } public int Id { get { return fid; } } public int Duration { get { return GetInt("duration") * 10; } } public string Title { get { return GetString("title"); } } public string Type { get { return GetString("type"); } } public uint TrackNumber { get { return (uint) GetInt("tracknr"); } } public uint PlayCount { get { return (uint) GetInt("play_count"); } } public DateTime LastPlayed { get { return NativeConvert.ToDateTime((long)GetInt("play_last")); } } public int Year { get { return GetInt("year"); } } } } ��������������������������������������������libkarma-0.1.2/INSTALL������������������������������������������������������������������������������0000644�0001750�0000012�00000002210�11543330237�013467� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Compiling: ^^^^^^^^^^ Using make: "make all" compiles both static and shared libkarma libraries and riocp/chprop in the "tools" directory, using the static libkarma library (libkarma.a) "make clean" removes everything created by "make" To compile only the static or the shared versions of libkarma and/or the tools, go to the directories "src" and/or "tools" and do "make" or "make shared", respectively. Compiling with jam: "jam" compiles libkarma as a shared library and riocp/chprop in the "tools" directory "jam clean" removes everything created by jam "STATIC=1 jam" compiles everything static "jam riocp" is possible as well... Installing: ^^^^^^^^^^^ "make install" will install into $PREFIX (defaults to /usr/local). Use "make PREFIX=whatever" to install elsewhere. "make uninstall" will remove the installed files. Building the RPM ^^^^^^^^^^^^^^^^ Type "make dist" to create the tarball. Then "rpm -ta --clean libkarma-<version>.tar.gz" to create the rpms. Two rpms are created: karma-tools and libkarma-devel. The latter package is only required for those who wish to write programs which use the libkarma library. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libkarma-0.1.2/ChangeLog����������������������������������������������������������������������������0000644�0001750�0000012�00000012701�11543330237�014216� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������0.1.2: * *bsd build fix * Use gmcs rather than mcs * add debugging info when writing the smalldb fails * Update manpages * Install documentation files. * Add dllmap for karma-sharp.dll to find libkarma. 0.1.1: * use DESTDIR/PREFIX instead of DEST in the Makefile * Fixed rio_rw.c create_temp_file/update_props_from_tags (LAN) bugs * Adapted karmaLan.c, karmaUsb.c and riocp.c to karma_delete_file change * Added lk_properties_del_property() into lk_karmaXXX_delete_file() * Added an HAL fdi file 0.1.0: * man files written by Joe Nahmias * removed the argument of lk_properties_cache_obsolete() * Added code to trim props trailing whitespace in set_tag_props/rio_rw.c * Added playlist-based print and download support in riocp * Updated Jamfiles and Makefiles and other build and install changes * Fixed props.count off-by-one bugs in andOrSearch and smalldb saving * Playlist functions added to lkarma.h 0.0.6: * Fixed null-bitrate-related segfaults * Fixed lk_mountSearch_discover when /proc/mounts > 1024 bytes * Don't check the device name of the mount in /proc/mounts * Changed MODE_PROPERTY from 'play_count_limit' to 'bpm' * Fixed bad length & duration yield by lk_rio_update_props_from_tags() * Added lk_rio_update_props_from_tags() to get correct rids in lkarmafs * Added support for calculating rids correctly in lkarmafs * Changed sorting tracks by artist to match "Rescan music" functionality * Changed device settings: don't use properties not held in smalldb * Re-implemented fdb support and made it functional * Fixed rio_rw error handling and several other bugs * Added lk_rio_update_props_from_tags() to help lkarmafs file upload * Get file type from its contents rather than the suffix. * Use the rid property to (optionally) avoid multiple uploaded copies 0.0.5: * Return an error during lk_karmaUsb_connect() if essential directories (fids0 and var) are not found * Added regression tests * Removed half-finished fdb code * Moved library interface into a seperate header file, "lkarma.h" * Use function pointers to group the usb-or-net switch in one place * Added mountSearch and fixed karma.c and errors.c bugs * Indent and Whitespace cleanup * Makefile/Jamfile Added missing targets * Add karma-sharp to support the Banshee music player * riocp.c Options for smalldb management and dummy names * riocp.c Added dummy names for missing or blank properties * karmaUsb.c/properties.c/etc. Added smalldb read/write support * karmaUsb.c Improve and fix memory allocation in read_properties() * karmaUsb.c Substitute zeroes (null bytes) from xx1 files with blanks * properties.c Changed hash_insert() call in lk_properties_import() (needed for missing properties AndOrSearch) * properties.c Fixed buggy STRMATCH() (needed for correct AndOrSearch) * fdb.c Fixed use of andOrSearch * Fixed OR Search (broken since libkarma-0.0.3 changeset 30) 0.0.4: * minor cleanup for the release of 0.0.4 0.0.4:-pre2: * Fixed lk_properties_import bug while parsing properties with value="" * Append "/" to the user-given usbMountPoint if necessary * Fixed a few potential memory faults in karmaUsb.c 0.0.4:-pre1: * First version with full support for mounted karma disk (USB/OMFS) * Changed karma.[ch], moved some functions to util.[ch] and created karmaUsb.[ch] and KarmaLan[.ch] to support USB/OMFS operation * changed hash_create(32) -> hash_create(16); saves up to 300KB * Added fidTable[] to klist (and eliminated `struct list * l'), for speeding up lk_properties_idsearch() * added support for EXACT AND/OR search and changed to EXACT all the calls to lk_properties_andOrSearch() which needed to be EXACT * Fixed Makefiles to include taglib (and remove libFLAC/libvorbisfile) * moved pathname editing (tr) out of riocp.c and changed -q after del * fixed a bug of write_file_chunk/rio_rw (byte padding of files) * added taglib to support all major music tags: id3v2, ogg, flac... * moved the charset conversions out of libkarma * all functions are namespace renamed as `lk_file_function' * get_next_fid has been made faster * folders-based up/down-load fully implemented into fdb.[ch] original pathnames are now saved as .openrio/*/libkarma_fdb.gz * CHANGELOG: 0.0.3 entries are now reverse time sorted 0.0.3: * src/playlist: preliminary support for playlist management * tools/riocp: tr-like editing of pathnames built from properties * tools/riocp-rio_rw: using properties to determine downlod paths * tools/riocp-rio_rw: deleting files * src/properties: add convertFromUtf8() and get_propertyUtf8() * src/properties: added a search functions * riocp/rio_rw: preliminary support of folders-based up/down-load with full paths writen/read to/from .openrio/*/fidNamesFile * replaced nested function (not ansi c) with an equivalent ansi one (Georg Sauthoff) * changed the caching mechanism to the openrio "standard" (http://www.cliff.biffle.org/software/pearl/openrio.php) * path to the cache compatible to rmmlite (Michael Piotrowski) * Patches for NetBSD by Michael Piotrowski (but you have to use jam;)) 0.0.2: * fixed karma.c for gcc 3.4 * stripped rio_rw/mp3/wav from the lib * fix for hash_insert (Enrique Vidal) * implemented caching via load_properties,save_properties, update_database * added ssdp support * jam support, see http://www.perforce.com/jam/jam.html * new Makefiles (Enrique Vidal) * fixed byte order in karma.c * error handling (errors.[ch]: Enrique Vidal) * utf8 supported in properties.c 0.0.1: * initial release ���������������������������������������������������������������libkarma-0.1.2/COPYING������������������������������������������������������������������������������0000644�0001750�0000012�00000035451�11543330237�013506� 0����������������������������������������������������������������������������������������������������ustar �franky��������������������������wheel������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������