mirror of
https://github.com/3proxy/3proxy.git
synced 2025-02-23 02:25:40 +08:00
Remove outdated LastFRipper plugin
This commit is contained in:
parent
5471e0faf4
commit
70ed1233fb
@ -1 +0,0 @@
|
||||
include Makefile.var
|
@ -1,7 +0,0 @@
|
||||
all: $(BUILDDIR)lastFripper$(DLSUFFICS)
|
||||
|
||||
lastFripper$(OBJSUFFICS): lastFripper.c
|
||||
$(CC) $(DCFLAGS) $(CFLAGS) lastFripper.c
|
||||
|
||||
$(BUILDDIR)lastFripper$(DLSUFFICS): lastFripper$(OBJSUFFICS)
|
||||
$(LN) $(LNOUT)../../$(BUILDDIR)lastFripper$(DLSUFFICS) $(LDFLAGS) $(DLFLAGS) lastFripper$(OBJSUFFICS)
|
@ -1,709 +0,0 @@
|
||||
/*
|
||||
released as a public domain
|
||||
std.denis, 2009
|
||||
*/
|
||||
#include "../../structures.h"
|
||||
#include "lastFripper.h"
|
||||
|
||||
#define strdup _strdup
|
||||
#define strnicmp _strnicmp
|
||||
#define ltoa _ltoa
|
||||
|
||||
#define mkdir _mkdir
|
||||
|
||||
#define PART_SUFFIX "_partial"
|
||||
|
||||
void my_mkdir( char* name )
|
||||
{
|
||||
char* pdir = name;
|
||||
|
||||
while( 1 ) {
|
||||
char ch;
|
||||
char* pnext = pdir;
|
||||
while( *pnext && *pnext != '\\' && *pnext != '/' )
|
||||
pnext++;
|
||||
if( *pnext == 0 )
|
||||
break;
|
||||
|
||||
ch = *pnext;
|
||||
*pnext = 0;
|
||||
mkdir( name );
|
||||
*pnext = ch;
|
||||
|
||||
pdir = pnext + 1;
|
||||
}
|
||||
mkdir( name );
|
||||
}
|
||||
|
||||
|
||||
__inline void myOutputDebugStringA1( char* str )
|
||||
{
|
||||
/* char fname[128];
|
||||
ltoa( GetCurrentThreadId(), fname, 10 );
|
||||
FILE* fp = fopen( fname, "ab" );
|
||||
fputs( str, fp );
|
||||
fputs( "\r\n", fp );
|
||||
fflush( fp );
|
||||
fclose( fp );
|
||||
*/
|
||||
}
|
||||
|
||||
__inline void myOutputDebugStringA( void* buf, int len )
|
||||
{
|
||||
/* char fname[128];
|
||||
ltoa( GetCurrentThreadId(), fname, 10 );
|
||||
FILE* fp = fopen( fname, "ab" );
|
||||
fwrite( buf, len, 1, fp );
|
||||
fputs( "\r\n", fp );
|
||||
fflush( fp );
|
||||
fclose( fp ); */
|
||||
}
|
||||
|
||||
#ifndef isnumber
|
||||
#define isnumber(i_n_arg) ((i_n_arg>='0')&&(i_n_arg<='9'))
|
||||
#endif
|
||||
|
||||
#define sizearr(x) (sizeof(x)/sizeof(x[0]))
|
||||
#define xmalloc( type, len ) ((type*)malloc( (len) * sizeof(type) ) )
|
||||
#define xcalloc( type, len ) ((type*)calloc( (len), sizeof(type) ) )
|
||||
|
||||
int clean_filename( char* filename )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; filename[i]; i++ )
|
||||
switch( filename[i] ) {
|
||||
case '*':
|
||||
case '?':
|
||||
case '<':
|
||||
case '>':
|
||||
case '\\':
|
||||
case '/':
|
||||
case ':':
|
||||
case '"':
|
||||
filename[i] = '_';
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
static struct pluginlink * pl;
|
||||
static int lfm_loaded = 0;
|
||||
static char* g_folder = 0;
|
||||
static char* g_format = 0;
|
||||
|
||||
static int lfm_format_filename( struct playlist_item* p_item, char* p_filename, int n_filename )
|
||||
{
|
||||
int i = 0, j;
|
||||
char ch;
|
||||
char* fmt;
|
||||
char *ff = NULL;
|
||||
|
||||
if( g_folder && *g_folder ) {
|
||||
strncpy( p_filename, g_folder, n_filename );
|
||||
i = strlen( p_filename );
|
||||
if( i < n_filename-1 && p_filename[i-1] != '\\' )
|
||||
p_filename[i++] = '\\';
|
||||
}
|
||||
|
||||
fmt = g_format;
|
||||
if( fmt == NULL ) fmt = "%a\\%t.mp3";
|
||||
while( ( ch = *fmt++ ) != 0 ) {
|
||||
if( ch == '%' ) {
|
||||
char* p_sz = NULL;
|
||||
char a_sz[32];
|
||||
ch = *fmt++;
|
||||
switch( ch ) {
|
||||
case 0:
|
||||
fmt--; break;
|
||||
case '%':
|
||||
p_sz = "%";
|
||||
break;
|
||||
case 'n': {
|
||||
static unsigned ndx = 0;
|
||||
ltoa( ndx++, a_sz, 10 );
|
||||
p_sz = a_sz;
|
||||
break;
|
||||
}
|
||||
case 'a':
|
||||
p_sz = p_item->artist;
|
||||
break;
|
||||
case 't':
|
||||
p_sz = p_item->title;
|
||||
break;
|
||||
case 'l':
|
||||
p_sz = p_item->album;
|
||||
break;
|
||||
}
|
||||
if( p_sz ) {
|
||||
strncpy( p_filename+i, p_sz, n_filename-i );
|
||||
p_filename[n_filename-1] = 0;
|
||||
i += clean_filename( p_filename+i );
|
||||
}
|
||||
} else
|
||||
if( i < n_filename ) p_filename[i++] = ch;
|
||||
}
|
||||
|
||||
for( j = i-1; j >= 0; j-- )
|
||||
if( p_filename[j] == '\\' || p_filename[j] == '/' ) {
|
||||
ff = p_filename + j;
|
||||
break;
|
||||
}
|
||||
if( ff ) {
|
||||
char ch = *ff;
|
||||
*ff = 0;
|
||||
my_mkdir( p_filename );
|
||||
*ff = ch;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void lfm_close_request( struct lfm_client_data* p_client )
|
||||
{
|
||||
struct lfm_filter_data* p_data;
|
||||
if( p_client == NULL ) return;
|
||||
p_data = p_client->p_data;
|
||||
if( p_data == NULL ) return;
|
||||
|
||||
if( p_client->req_type == LFM_PLAYLIST ) {
|
||||
free( p_client->pl_xml );
|
||||
} else if( p_client->req_type == LFM_GET && p_client->fp ) {
|
||||
struct playlist_item* p_item = p_client->pl_item;
|
||||
if( p_item ) {
|
||||
char id3v1[128];
|
||||
memset( id3v1, 0, 128 );
|
||||
strcpy( id3v1, "TAG" );
|
||||
strncpy( id3v1+3, p_item->title, 30 );
|
||||
strncpy( id3v1+33, p_item->artist, 30 );
|
||||
strncpy( id3v1+63, p_item->album, 30 );
|
||||
id3v1[127] = -1;
|
||||
fwrite( id3v1, 128, 1, p_client->fp );
|
||||
}
|
||||
fclose( p_client->fp );
|
||||
/*
|
||||
if( p_item ) {
|
||||
char filename_part[512], filename[512];
|
||||
int i = lfm_format_filename( p_item, filename_part, sizearr(filename_part) );
|
||||
memcpy( filename, filename_part, sizeof(filename) );
|
||||
strncpy( filename_part+i, PART_SUFFIX, sizearr(filename_part)-i );
|
||||
rename( filename_part, filename );
|
||||
}
|
||||
*/
|
||||
pthread_mutex_lock( &p_data->mutex );
|
||||
if( p_data->playlist != NULL && p_item != NULL ) {
|
||||
if( p_data->playlist == p_item )
|
||||
p_data->playlist = p_item->next;
|
||||
else {
|
||||
struct playlist_item *p_last = p_data->playlist;
|
||||
|
||||
while( p_last->next != NULL && p_last->next != p_item )
|
||||
p_last = p_last->next;
|
||||
|
||||
if( p_last->next )
|
||||
p_last->next = p_item->next;
|
||||
}
|
||||
if( p_item->artist ) free( p_item->artist );
|
||||
if( p_item->title ) free( p_item->title );
|
||||
if( p_item->album ) free( p_item->album );
|
||||
if( p_item->url ) free( p_item->url );
|
||||
free( p_item );
|
||||
}
|
||||
pthread_mutex_unlock( &p_data->mutex );
|
||||
}
|
||||
p_client->req_type = LFM_NONE;
|
||||
}
|
||||
|
||||
static void* lfm_filter_open( void * idata, struct srvparam * param ){
|
||||
struct lfm_filter_data* pdata = (struct lfm_filter_data*)idata;
|
||||
if( pdata ){
|
||||
pthread_mutex_lock( &pdata->mutex );
|
||||
pdata->refs++;
|
||||
pthread_mutex_unlock( &pdata->mutex );
|
||||
} else {
|
||||
if( ( pdata = xcalloc( struct lfm_filter_data, 1 ) ) != NULL ) {
|
||||
pthread_mutex_init( &pdata->mutex, NULL );
|
||||
pdata->playlist = NULL;
|
||||
pdata->refs++;
|
||||
}
|
||||
}
|
||||
return pdata;
|
||||
}
|
||||
|
||||
static FILTER_ACTION lfm_filter_client( void *fo, struct clientparam* param, void** fc )
|
||||
{
|
||||
struct lfm_filter_data* p_data;
|
||||
struct lfm_client_data* p_client;
|
||||
*fc = NULL;
|
||||
if( fo == NULL ) return PASS;
|
||||
|
||||
p_data = (struct lfm_filter_data*)fo;
|
||||
p_client = xcalloc( struct lfm_client_data, 1 );
|
||||
if( p_client == NULL ) return PASS;
|
||||
|
||||
p_client->p_data = p_data;
|
||||
p_client->req_type = LFM_NONE;
|
||||
|
||||
*fc = p_client;
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
static void lfm_filter_clear( void *fc )
|
||||
{
|
||||
struct lfm_client_data* p_client;
|
||||
|
||||
p_client = (struct lfm_client_data*)fc;
|
||||
if( p_client == NULL ) return;
|
||||
|
||||
lfm_close_request( p_client );
|
||||
|
||||
free( p_client );
|
||||
}
|
||||
|
||||
static void lfm_filter_close(void *fo){
|
||||
struct lfm_filter_data* p_data;
|
||||
struct playlist_item* p_item;
|
||||
|
||||
p_data = (struct lfm_filter_data*)fo;
|
||||
if( p_data == NULL ) return;
|
||||
|
||||
if( --p_data->refs > 0 ) return;
|
||||
|
||||
pthread_mutex_destroy( &p_data->mutex );
|
||||
p_item = p_data->playlist;
|
||||
while( p_item ) {
|
||||
struct playlist_item* p_old = p_item;
|
||||
p_item = p_item->next;
|
||||
|
||||
if( p_old->artist ) free( p_old->artist );
|
||||
if( p_old->title ) free( p_old->title );
|
||||
if( p_old->album ) free( p_old->album );
|
||||
if( p_old->url ) free( p_old->url );
|
||||
free( p_old );
|
||||
}
|
||||
|
||||
free( p_data );
|
||||
}
|
||||
|
||||
static FILTER_ACTION lfm_filter_request( void *fc, struct clientparam *param, unsigned char** buf_p, int* bufsize_p, int offset, int* length_p )
|
||||
{
|
||||
char* p_buf = (char*)( *buf_p + offset );
|
||||
int n_buf = *length_p - offset;
|
||||
struct lfm_client_data* p_client;
|
||||
struct lfm_filter_data* p_data;
|
||||
|
||||
if( p_buf == NULL || n_buf < 5 ) return CONTINUE;
|
||||
|
||||
p_client = (struct lfm_client_data*)fc;
|
||||
if( p_client == NULL ) return CONTINUE;
|
||||
p_data = p_client->p_data;
|
||||
if( p_data == NULL ) return CONTINUE;
|
||||
|
||||
pl->conf->filtermaxsize = 0;
|
||||
|
||||
lfm_close_request( p_client );
|
||||
|
||||
p_client->req_type = LFM_NONE;
|
||||
p_client->fp = NULL;
|
||||
|
||||
if( strncasecmp( p_buf, "GET ", 4 ) != 0 ) return CONTINUE;
|
||||
|
||||
p_buf += 4;
|
||||
|
||||
if( strncasecmp( p_buf, "http://ws.audioscrobbler.com/radio/xspf.php?", 44 ) == 0 ) {
|
||||
myOutputDebugStringA1( "getting a playlist" );
|
||||
p_client->req_type = LFM_PLAYLIST;
|
||||
} else {
|
||||
char zzz[256];
|
||||
int i;
|
||||
struct playlist_item* p_item;
|
||||
for( i = 0; i < n_buf && i < 256; i++ ) {
|
||||
if( p_buf[i] == '\r' ) break;
|
||||
zzz[i] = p_buf[i];
|
||||
}
|
||||
zzz[i] = 0;
|
||||
myOutputDebugStringA1( zzz );
|
||||
pthread_mutex_lock( &p_data->mutex );
|
||||
p_item = p_data->playlist;
|
||||
while( p_item ) {
|
||||
if( strncasecmp( p_buf, p_item->url, p_item->url_len ) == 0 )
|
||||
break;
|
||||
p_item = p_item->next;
|
||||
}
|
||||
pthread_mutex_unlock( &p_data->mutex );
|
||||
if( p_item ) {
|
||||
myOutputDebugStringA1( "getting a known url: " );
|
||||
myOutputDebugStringA1( p_item->title );
|
||||
p_client->req_type = LFM_GET;
|
||||
p_client->pl_item = p_item;
|
||||
}
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
static FILTER_ACTION lfm_filter_header_srv( void *fc, struct clientparam *param, unsigned char** buf_p, int* bufsize_p, int offset, int* length_p )
|
||||
{
|
||||
char* p_buf = (char*)( *buf_p + offset );
|
||||
struct lfm_client_data* p_client;
|
||||
int n_buf = *length_p - offset;
|
||||
struct lfm_filter_data* p_data;
|
||||
char zzz[100];
|
||||
int code;
|
||||
|
||||
if( p_buf == NULL || n_buf < 9 ) return CONTINUE;
|
||||
|
||||
p_client = (struct lfm_client_data*)fc;
|
||||
if( p_client == NULL ) return CONTINUE;
|
||||
p_data = p_client->p_data;
|
||||
if( p_data == NULL ) return CONTINUE;
|
||||
|
||||
code = atoi( p_buf + 9 );
|
||||
sprintf( zzz, "http code: %d", code );
|
||||
myOutputDebugStringA1( zzz );
|
||||
myOutputDebugStringA( p_buf, n_buf );
|
||||
if( p_client->req_type == LFM_GET && ( code > 300 && code < 304 || code == 307 ) ) {
|
||||
p_client->req_type = LFM_REDIR;
|
||||
do {
|
||||
char* p_line = p_buf;
|
||||
int n_line;
|
||||
|
||||
for(; n_buf > 0 && *p_buf != '\r'; p_buf++, n_buf-- ) {};
|
||||
n_line = p_buf - p_line;
|
||||
if( n_line <= 0 ) break;
|
||||
if( n_line > 10 && strncasecmp( p_line, "location: ", 10 ) == 0 ) {
|
||||
myOutputDebugStringA1( "redir/location: " );
|
||||
myOutputDebugStringA( p_line + 10, n_line - 10 );
|
||||
if( p_client->pl_item ) {
|
||||
char* p_url = p_line + 10;
|
||||
int n_url = n_line - 10;
|
||||
pthread_mutex_lock( &p_data->mutex );
|
||||
if( p_client->pl_item->url ) free( p_client->pl_item->url );
|
||||
p_client->pl_item->url = xmalloc( char, n_url + 1 + 1 );
|
||||
memcpy( p_client->pl_item->url, p_url, n_url );
|
||||
p_client->pl_item->url[n_url] = ' ';
|
||||
p_client->pl_item->url[n_url+1] = 0;
|
||||
p_client->pl_item->url_len = n_url + 1;
|
||||
myOutputDebugStringA1( "got a url: " );
|
||||
myOutputDebugStringA1( p_client->pl_item->url );
|
||||
pthread_mutex_unlock( &p_data->mutex );
|
||||
}
|
||||
p_client->req_type = LFM_NONE;
|
||||
}
|
||||
for(; n_buf > 0 && ( *p_buf == '\n' || *p_buf == '\r' ); p_buf++, n_buf-- ) {};
|
||||
} while( n_buf > 0 );
|
||||
}
|
||||
|
||||
if( code == 200 && p_client->req_type == LFM_GET ) {
|
||||
struct playlist_item* p_item = p_client->pl_item;
|
||||
char filename[512];
|
||||
int i = lfm_format_filename( p_item, filename, sizearr(filename) );
|
||||
/*
|
||||
strncpy( filename + i, PART_SUFFIX, sizearr(filename)-i );
|
||||
*/
|
||||
p_client->fp = fopen( filename, "wb" );
|
||||
}
|
||||
else if( code == 200 && p_client->req_type == LFM_PLAYLIST ) {
|
||||
p_client->pl_xml = xcalloc( struct xml_state, 1 );
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
void playlist_analyze( struct lfm_client_data* p_client, const char* p_buf, int len );
|
||||
static FILTER_ACTION lfm_filter_data_srv( void *fc, struct clientparam *param, unsigned char** buf_p, int* bufsize_p, int offset, int* length_p )
|
||||
{
|
||||
char* p_buf = (char*)( *buf_p + offset );
|
||||
int n_buf = *length_p - offset;
|
||||
struct lfm_client_data* p_client;
|
||||
struct lfm_filter_data* p_data;
|
||||
|
||||
|
||||
myOutputDebugStringA1( "filter_data_srv" );
|
||||
myOutputDebugStringA( p_buf, n_buf );
|
||||
|
||||
if( p_buf == NULL || n_buf < 1 ) return CONTINUE;
|
||||
|
||||
p_client = (struct lfm_client_data*)fc;
|
||||
if( p_client == NULL ) return CONTINUE;
|
||||
p_data = p_client->p_data;
|
||||
if( p_data == NULL ) return CONTINUE;
|
||||
|
||||
if( p_client->req_type == LFM_PLAYLIST )
|
||||
myOutputDebugStringA1( "filter_data_srv: playlist" );
|
||||
else if( p_client->req_type == LFM_GET ) {
|
||||
myOutputDebugStringA1( "filter_data_srv: retrieving" );
|
||||
if( p_client->fp == NULL )
|
||||
myOutputDebugStringA1( "but no file allocated" );
|
||||
}
|
||||
|
||||
if( p_client->req_type == LFM_PLAYLIST )
|
||||
playlist_analyze( p_client, p_buf, n_buf );
|
||||
if( p_client->fp )
|
||||
fwrite( p_buf, n_buf, 1, p_client->fp );
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
enum XmlState
|
||||
{
|
||||
XML_TEXT,
|
||||
XML_TAGNAME,
|
||||
XML_ATTRNAME_W,
|
||||
XML_ATTRNAME,
|
||||
XML_ATTRVALUE_W,
|
||||
XML_ATTRVALUE,
|
||||
XML_TAGCLOSE,
|
||||
XML_TAGOPENCLOSE,
|
||||
};
|
||||
|
||||
int xml_get_token_id( char** table, char* token )
|
||||
{
|
||||
int i;
|
||||
char* psz;
|
||||
for( psz = token; *psz; psz++ )
|
||||
*psz = tolower( *psz );
|
||||
for( i = 0; *table; i++, table++ )
|
||||
if( strcmp( *table, token ) == 0 ) return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
enum {
|
||||
XT_PLAYLIST,
|
||||
XT_TRACK_LIST,
|
||||
XT_TRACK,
|
||||
XT_LOCATION,
|
||||
XT_CREATOR,
|
||||
XT_ALBUM,
|
||||
XT_TITLE
|
||||
};
|
||||
|
||||
char* xt_list[] = {
|
||||
"playlist",
|
||||
"tracklist",
|
||||
"track",
|
||||
"location",
|
||||
"creator",
|
||||
"album",
|
||||
"title",
|
||||
NULL
|
||||
};
|
||||
|
||||
void playlist_analyze( struct lfm_client_data* p_client, const char* p_buf, int len )
|
||||
{
|
||||
struct xml_state* xs = p_client->pl_xml;
|
||||
int n_buf = len;
|
||||
|
||||
if( xs == NULL ) return;
|
||||
|
||||
while( n_buf > 0 ) {
|
||||
enum {
|
||||
XMS_NONE,
|
||||
XMS_TAG,
|
||||
XMS_ATTR_NAME,
|
||||
XMS_ATTR_VALUE,
|
||||
XMS_TEXT
|
||||
} gotta = XMS_NONE;
|
||||
char ch = *p_buf++;
|
||||
n_buf--;
|
||||
lbl_retry:
|
||||
switch( xs->state ) {
|
||||
case XML_TAGNAME:
|
||||
if( ch == '>' ) {
|
||||
xs->state = XML_TEXT;
|
||||
gotta = XMS_TAG;
|
||||
break;
|
||||
} else if( ch == '/' ) {
|
||||
if( xs->n_token == 0 )
|
||||
xs->closing = 1;
|
||||
else {
|
||||
xs->state = XML_ATTRNAME_W;
|
||||
gotta = XMS_TAG;
|
||||
xs->n_token--;
|
||||
}
|
||||
break;
|
||||
} else if( isspace( ch ) ) {
|
||||
xs->state = XML_ATTRNAME_W;
|
||||
gotta = XMS_TAG;
|
||||
break;
|
||||
}
|
||||
if( xs->n_token < TOKEN_MAXLEN ) xs->p_token[xs->n_token++] = ch;
|
||||
break;
|
||||
case XML_ATTRNAME_W:
|
||||
if( ch == '>' ) {
|
||||
xs->state = XML_TEXT;
|
||||
break;
|
||||
} else if( ch == '/' ) {
|
||||
xs->closing = 1;
|
||||
xs->state = XML_TEXT;
|
||||
gotta = XMS_TAG;
|
||||
break;
|
||||
} else if( !isspace( ch ) ) {
|
||||
xs->state = XML_ATTRNAME;
|
||||
goto lbl_retry;
|
||||
}
|
||||
break;
|
||||
case XML_ATTRNAME:
|
||||
if( ch == '=' ) {
|
||||
xs->state = XML_ATTRVALUE_W;
|
||||
gotta = XMS_ATTR_NAME;
|
||||
break;
|
||||
}
|
||||
if( xs->n_token < TOKEN_MAXLEN ) xs->p_token[xs->n_token++] = ch;
|
||||
break;
|
||||
case XML_ATTRVALUE_W:
|
||||
if( ch == '"' || ch == '\'' ) {
|
||||
xs->sep = ch;
|
||||
xs->state = XML_ATTRVALUE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case XML_ATTRVALUE:
|
||||
if( ch == xs->sep ) {
|
||||
xs->state = XML_ATTRNAME_W;
|
||||
gotta = XMS_ATTR_VALUE;
|
||||
break;
|
||||
}
|
||||
if( xs->n_token < TOKEN_MAXLEN ) xs->p_token[xs->n_token++] = ch;
|
||||
break;
|
||||
case XML_TEXT:
|
||||
if( ch == '<' ) {
|
||||
xs->state = XML_TAGNAME;
|
||||
gotta = XMS_TEXT;
|
||||
break;
|
||||
}
|
||||
if( xs->n_token < TOKEN_MAXLEN ) xs->p_token[xs->n_token++] = ch;
|
||||
break;
|
||||
}
|
||||
|
||||
if( gotta != XMS_NONE ) {
|
||||
xs->p_token[xs->n_token] = 0;
|
||||
|
||||
switch( gotta ) {
|
||||
case XMS_TAG: {
|
||||
int id = xml_get_token_id( xt_list, xs->p_token );
|
||||
if( !xs->closing ) {
|
||||
if( xs->level < sizeof(xs->tree) ) xs->tree[xs->level] = id;
|
||||
xs->level++;
|
||||
|
||||
if( id == XT_TRACK && xs->level == 3 && xs->tree[1] == XT_TRACK_LIST )
|
||||
xs->p_item = xcalloc( struct playlist_item, 1 );
|
||||
} else {
|
||||
if( xs->level > 0 ) xs->level--;
|
||||
if( id == XT_TRACK && xs->level == 2 && xs->tree[1] == XT_TRACK_LIST ) {
|
||||
char zzz[1024];
|
||||
_snprintf( zzz, 1024, "artist: <%s>, title: <%s>, url: <%s>",
|
||||
xs->p_item->artist, xs->p_item->title, xs->p_item->url );
|
||||
myOutputDebugStringA1( zzz );
|
||||
pthread_mutex_lock( &p_client->p_data->mutex );
|
||||
xs->p_item->next = p_client->p_data->playlist;
|
||||
p_client->p_data->playlist = xs->p_item;
|
||||
pthread_mutex_unlock( &p_client->p_data->mutex );
|
||||
}
|
||||
xs->closing = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case XMS_ATTR_NAME:
|
||||
break;
|
||||
case XMS_ATTR_VALUE:
|
||||
break;
|
||||
case XMS_TEXT:
|
||||
if( xs->level == 4 && xs->tree[1] == XT_TRACK_LIST && xs->tree[2] == XT_TRACK ) {
|
||||
struct playlist_item* item = xs->p_item;
|
||||
if( item )
|
||||
switch( xs->tree[3] ) {
|
||||
case XT_LOCATION:
|
||||
item->url_len = xs->n_token;
|
||||
item->url = xmalloc( char, item->url_len + 1 + 1);
|
||||
memcpy( item->url, xs->p_token, item->url_len );
|
||||
item->url[item->url_len++] = ' ';
|
||||
item->url[item->url_len] = 0;
|
||||
break;
|
||||
case XT_CREATOR:
|
||||
item->artist = strdup( xs->p_token );
|
||||
break;
|
||||
case XT_ALBUM:
|
||||
item->album = strdup( xs->p_token );
|
||||
break;
|
||||
case XT_TITLE:
|
||||
item->title = strdup( xs->p_token );
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
xs->n_token = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct filter lfm_filter = {
|
||||
NULL,
|
||||
"last.fm spy",
|
||||
NULL,
|
||||
|
||||
lfm_filter_open,
|
||||
lfm_filter_client,
|
||||
lfm_filter_request,
|
||||
NULL,
|
||||
lfm_filter_header_srv,
|
||||
NULL,
|
||||
NULL,
|
||||
lfm_filter_data_srv,
|
||||
lfm_filter_clear,
|
||||
lfm_filter_close
|
||||
};
|
||||
|
||||
static int h_lfm_folder( int argc, unsigned char **argv )
|
||||
{
|
||||
if( g_folder ) free( g_folder );
|
||||
g_folder = strdup( (char*)argv[1] );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int h_lfm_format( int argc, unsigned char **argv )
|
||||
{
|
||||
if( g_format ) free( g_format );
|
||||
g_format = strdup( (char*)argv[1] );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct commands lfm_commandhandlers[] = {
|
||||
{lfm_commandhandlers+1, "lfm_folder", h_lfm_folder, 2, 2},
|
||||
{NULL, "lfm_format", h_lfm_format, 2, 2}
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef WATCOM
|
||||
#pragma aux lfm_plugin "*" parm caller [ ] value struct float struct routine [eax] modify [eax ecx edx]
|
||||
#undef PLUGINCALL
|
||||
#define PLUGINCALL
|
||||
#endif
|
||||
|
||||
PLUGINAPI int PLUGINCALL lfm_plugin( struct pluginlink * pluginlink, int argc, char** argv )
|
||||
{
|
||||
pl = pluginlink;
|
||||
myOutputDebugStringA1( "lfm_plugin" );
|
||||
if( !lfm_loaded ) {
|
||||
lfm_loaded = 1;
|
||||
|
||||
lfm_filter.next = pl->conf->filters;
|
||||
pl->conf->filters = &lfm_filter;
|
||||
|
||||
lfm_commandhandlers[1].next = pl->commandhandlers->next;
|
||||
pl->commandhandlers->next = lfm_commandhandlers;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,66 +0,0 @@
|
||||
//
|
||||
// released as a public domain
|
||||
// std.denis, 2009
|
||||
//
|
||||
/*
|
||||
#include "direct.h"
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define strcasecmp stricmp
|
||||
#define strncasecmp strnicmp
|
||||
#else
|
||||
#define closesocket close
|
||||
extern pthread_attr_t pa;
|
||||
#endif
|
||||
|
||||
#ifndef SOCKET_ERROR
|
||||
#define SOCKET_ERROR -1
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum {
|
||||
LFM_NONE,
|
||||
LFM_PLAYLIST, // GET http://ws.audioscrobbler.com/radio/adjust.php(...)
|
||||
LFM_REDIR, // GET http://play.last.fm/user/(...)
|
||||
LFM_GET
|
||||
} LFM_CLASS;
|
||||
|
||||
struct playlist_item {
|
||||
struct playlist_item* next;
|
||||
|
||||
char* artist;
|
||||
char* title;
|
||||
char* album;
|
||||
char* url;
|
||||
int url_len;
|
||||
};
|
||||
|
||||
#define TOKEN_MAXLEN 1024
|
||||
struct xml_state {
|
||||
int state;
|
||||
int closing;
|
||||
char sep;
|
||||
|
||||
int level;
|
||||
char tree[128]; // 128 levels nesting
|
||||
|
||||
int n_token;
|
||||
char p_token[TOKEN_MAXLEN];
|
||||
|
||||
struct playlist_item* p_item;
|
||||
};
|
||||
|
||||
struct lfm_filter_data {
|
||||
pthread_mutex_t mutex;
|
||||
struct playlist_item* playlist;
|
||||
int refs;
|
||||
};
|
||||
struct lfm_client_data {
|
||||
struct lfm_filter_data* p_data;
|
||||
|
||||
int req_type;
|
||||
struct xml_state* pl_xml;
|
||||
struct playlist_item* pl_item;
|
||||
FILE* fp;
|
||||
};
|
Loading…
Reference in New Issue
Block a user