diff --git a/src/ff-plugins.h b/src/ff-plugins.h index 0ed504d0..42ad0c15 100644 --- a/src/ff-plugins.h +++ b/src/ff-plugins.h @@ -108,7 +108,7 @@ typedef struct tag_db_query { int playlist_id; /* for items query */ int totalcount; /* returned total count */ - void *private; + void *priv; } DB_QUERY; diff --git a/src/plugin.c b/src/plugin.c index 06f2bb3b..21393910 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -530,14 +530,14 @@ int plugin_auth_handle(WS_CONNINFO *pwsc, char *username, char *pw) { /* so functions must be a tag_plugin_output_fn */ auth_fn=(ppi->pinfo->output_fns)->auth; - if(auth_fn) { - result=auth_fn(pwsc,username,pw); - _plugin_unlock(); - return result; - } else { - _plugin_unlock(); - return TRUE; - } + if(auth_fn) { + result=auth_fn(pwsc,username,pw); + _plugin_unlock(); + return result; + } else { + _plugin_unlock(); + return TRUE; + } } } ppi = ppi->next; @@ -642,7 +642,9 @@ int _plugin_ssc_copy(WS_CONNINFO *pwsc, PLUGIN_TRANSCODE_FN *pfn, while((bytes_read=pfn->ssc_read(vp,buffer,sizeof(buffer))) > 0) { total_bytes_read += bytes_read; - ws_writebinary(pwsc,buffer,bytes_read); + if(ws_writebinary(pwsc,buffer,bytes_read) != bytes_read) { + return total_bytes_read; + } } if(bytes_read < 0) @@ -794,7 +796,7 @@ int pi_db_enum_start(char **pe, DB_QUERY *pinfo) { return DB_E_MALLOC; } memset(pqi,0,sizeof(DBQUERYINFO)); - pinfo->private = (void*)pqi; + pinfo->priv = (void*)pqi; if(pinfo->filter) { pqi->pt = sp_init(); @@ -854,7 +856,7 @@ int pi_db_enum_start(char **pe, DB_QUERY *pinfo) { int pi_db_enum_fetch_row(char **pe, char ***row, DB_QUERY *pinfo) { return db_enum_fetch_row(pe, (PACKED_MP3FILE*)row, - (DBQUERYINFO*)pinfo->private); + (DBQUERYINFO*)pinfo->priv); } int pi_db_enum_end(char **pe) { @@ -872,8 +874,8 @@ void pi_db_enum_dispose(char **pe, DB_QUERY *pinfo) { if(!pinfo) return; - if(pinfo->private) { - pqi = (DBQUERYINFO *)pinfo->private; + if(pinfo->priv) { + pqi = (DBQUERYINFO *)pinfo->priv; if(pqi->pt) { sp_dispose(pqi->pt); pqi->pt = NULL; diff --git a/src/plugins/rsp.c b/src/plugins/rsp.c index fa1dcd99..e7792063 100644 --- a/src/plugins/rsp.c +++ b/src/plugins/rsp.c @@ -162,18 +162,18 @@ int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password) { readpassword = _ppi->conf_alloc_string("general","password",NULL); if(password == NULL) { /* testing to see if we need a pw */ if((readpassword == NULL) || (strlen(readpassword)==0)) { - if(readpassword) free(readpassword); + if(readpassword) _ppi->conf_dispose_string(readpassword); return TRUE; } else { - free(readpassword); + _ppi->conf_dispose_string(readpassword); return FALSE; } } else { if(strcasecmp(password,readpassword)) { - free(readpassword); + _ppi->conf_dispose_string(readpassword); return FALSE; } else { - free(readpassword); + _ppi->conf_dispose_string(readpassword); return TRUE; } } @@ -190,9 +190,12 @@ void plugin_handler(WS_CONNINFO *pwsc) { int index, part; int found; + _ppi->log(E_DBG,"Getting uri...\n"); + string = _ppi->ws_uri(pwsc); string++; + _ppi->log(E_DBG,"Mallocing privinfo...\n"); ppi = (PRIVINFO *)malloc(sizeof(PRIVINFO)); if(ppi) { memset(ppi,0,sizeof(PRIVINFO)); diff --git a/src/plugins/ssc-wma.cpp b/src/plugins/ssc-wma.cpp new file mode 100644 index 00000000..99b24926 --- /dev/null +++ b/src/plugins/ssc-wma.cpp @@ -0,0 +1,311 @@ +/* + * $Id: $ + * + * Win32-only transcoder for WMA using the Windows Media Format SDK. + */ + +#define _WIN32_DCOM + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include +#include + +#include "ff-plugins.h" + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +typedef struct tag_ssc_handle { + int state; + IWMSyncReader *pReader; + int errnum; + + int duration; + char wav_header[44]; + int wav_offset; + + INSSBuffer *pBuffer; + BYTE *pdata; + DWORD data_len; + int offset; +} SSCHANDLE; + +#define STATE_DONE 0 +#define STATE_OPEN 1 +#define STATE_STREAMOPEN 2 + +#define SSC_WMA_E_SUCCESS 0 +#define SSC_WMA_E_NOCOM 1 +#define SSC_WMA_E_NOREADER 2 +#define SSC_WMA_E_OPEN 3 +#define SSC_WMA_E_READ 4 + +char *_ssc_wma_errors[] = { + "Success", + "Could not initialize COM", + "Could not create WMA reader", + "Could not open file", + "Error while reading file" +}; + + + +/* Forwards */ +void *ssc_wma_init(void); +void ssc_wma_deinit(void *pv); +int ssc_wma_open(void *pv, char *file, char *codec, int duration); +int ssc_wma_close(void *pv); +int ssc_wma_read(void *pv, char *buffer, int len); +char *ssc_wma_error(void *pv); + +PLUGIN_INFO *plugin_info(PLUGIN_INPUT_FN*); + +/* Globals */ +PLUGIN_TRANSCODE_FN _ptfn = { + ssc_wma_init, + ssc_wma_deinit, + ssc_wma_open, + ssc_wma_close, + ssc_wma_read, + ssc_wma_error +}; + +PLUGIN_INPUT_FN *_ppi; + +PLUGIN_INFO _pi = { + PLUGIN_VERSION, /* version */ + PLUGIN_TRANSCODE, /* type */ + "ssc-wma/" VERSION, /* server */ + NULL, /* url */ + NULL, /* output fns */ + NULL, /* event fns */ + &_ptfn, /* fns */ + NULL, /* rend info */ + "wma,wmal,wmap,wmav" /* codeclist */ +}; + +/** + * return the string representation of the last error + */ +char *ssc_wma_error(void *pv) { + SSCHANDLE *handle = (SSCHANDLE*)pv; + + return _ssc_wma_errors[handle->errnum]; +} + +PLUGIN_INFO *plugin_info(PLUGIN_INPUT_FN *ppi) { + _ppi = ppi; + return &_pi; +} + +void *ssc_wma_init(void) { + SSCHANDLE *handle; + HRESULT hr; + + hr = CoInitializeEx(NULL,COINIT_MULTITHREADED); + if(FAILED(hr)) { + _ppi->log(E_INF,"Could not initialize COM, Error code: 0x%08X\n",hr); + return NULL; + } + + handle=(SSCHANDLE *)malloc(sizeof(SSCHANDLE)); + if(handle) { + memset(handle,0,sizeof(SSCHANDLE)); + } + + return (void*)handle; +} + +void ssc_wma_deinit(void *vp) { + SSCHANDLE *handle = (SSCHANDLE *)vp; + ssc_wma_close(handle); + + if(handle) { + free(handle); + CoUninitialize(); + } + + return; +} + +int ssc_wma_open(void *vp, char *file, char *codec, int duration) { + SSCHANDLE *handle = (SSCHANDLE*)vp; + HRESULT hr = S_OK; + WCHAR fname[PATH_MAX]; + + if(!handle) + return FALSE; + + handle->state = STATE_DONE; + handle->duration = duration; + + hr = WMCreateSyncReader(NULL,0,&handle->pReader); + if(FAILED(hr)) { + _ppi->log(E_INF,"Could not create WMA reader. Error code: 0x%08X\n",hr); + handle->errnum = SSC_WMA_E_NOREADER; + return FALSE; + } + + /* convert file name to wchar */ + MultiByteToWideChar(GetACP(),0,file,-1,fname,sizeof(fname)/sizeof(fname[0])); + + hr = handle->pReader->Open(fname); + if(FAILED(hr)) { + _ppi->log(E_INF,"Could not open file. Error code: 0x%08X\n",hr); + handle->errnum = SSC_WMA_E_OPEN; + return FALSE; + } + handle->state=STATE_OPEN; + + hr = handle->pReader->SetRange(0,0); + if(FAILED(hr)) { + _ppi->log(E_INF,"Could not set range. Error code: 0x%08X\n",hr); + handle->errnum = SSC_WMA_E_OPEN; + return FALSE; + } + + hr = handle->pReader->SetReadStreamSamples(1,0); + if(FAILED(hr)) { + _ppi->log(E_INF,"Could not stream samples. Error code: 0x%08X\n",hr); + handle->errnum = SSC_WMA_E_OPEN; + return FALSE; + } + + + return TRUE; +} + +int ssc_wma_close(void *vp) { + SSCHANDLE *handle = (SSCHANDLE *)vp; + + if(!handle) + return TRUE; + + if(handle->state >= STATE_OPEN) { + handle->pReader->Close(); + } + + if(handle->pReader) + handle->pReader->Release(); + handle->pReader = NULL; + + handle->state = STATE_DONE; + return TRUE; +} + + + +int ssc_wma_read(void *vp, char *buffer, int len) { + SSCHANDLE *handle = (SSCHANDLE *)vp; + int bytes_returned = 0; + int bytes_to_copy; + HRESULT hr; + + unsigned int channels, sample_rate, bits_per_sample; + unsigned int byte_rate, block_align, duration; + + QWORD sample_time=0, sample_duration=0; + DWORD sample_len=0, flags=0, output_number=0; + + /* if we have not yet sent the header, let's do that first */ + if(handle->wav_offset != sizeof(handle->wav_header)) { + /* still have some to send */ + if(!handle->wav_offset) { + /* Should pull this from format info in the wma file */ + channels = 2; + sample_rate = 44100; + bits_per_sample = 16; + + if(handle->duration) + duration = handle->duration; + + sample_len = ((bits_per_sample * sample_rate * channels / 8) * (duration/1000)); + byte_rate = sample_rate * channels * bits_per_sample / 8; + block_align = channels * bits_per_sample / 8; + + _ppi->log(E_DBG,"Channels.......: %d\n",channels); + _ppi->log(E_DBG,"Sample rate....: %d\n",sample_rate); + _ppi->log(E_DBG,"Bits/Sample....: %d\n",bits_per_sample); + + memcpy(&handle->wav_header[0],"RIFF",4); + *((unsigned int*)(&handle->wav_header[4])) = 36 + sample_len; + memcpy(&handle->wav_header[8],"WAVE",4); + memcpy(&handle->wav_header[12],"fmt ",4); + *((unsigned int*)(&handle->wav_header[16])) = 16; + *((unsigned short*)(&handle->wav_header[20])) = 1; + *((unsigned short*)(&handle->wav_header[22])) = channels; + *((unsigned int*)(&handle->wav_header[24])) = sample_rate; + *((unsigned int*)(&handle->wav_header[28])) = byte_rate; + *((unsigned short*)(&handle->wav_header[32])) = block_align; + *((unsigned short*)(&handle->wav_header[34])) = bits_per_sample; + memcpy(&handle->wav_header[36],"data",4); + *((unsigned int*)(&handle->wav_header[40])) = sample_len; + } + + bytes_to_copy = sizeof(handle->wav_header) - handle->wav_offset; + if(len < bytes_to_copy) + bytes_to_copy = len; + + memcpy(buffer,&handle->wav_header[handle->wav_offset],bytes_to_copy); + handle->wav_offset += bytes_to_copy; + return bytes_to_copy; + } + + /* see if we have any leftover data */ + if(handle->data_len) { + bytes_returned = handle->data_len; + if(bytes_returned > len) { + bytes_returned = len; + } + + memcpy(buffer,handle->pdata + handle->offset,bytes_returned); + handle->offset += bytes_returned; + handle->data_len -= bytes_returned; + + if(!handle->data_len) { + handle->pBuffer->Release(); + handle->pBuffer = NULL; + } + + return bytes_returned; + } + + handle->offset = 0; + hr = handle->pReader->GetNextSample(1,&handle->pBuffer,&sample_time, &sample_duration, &flags, &output_number, NULL); + if(SUCCEEDED(hr)) { + hr = handle->pBuffer->GetBufferAndLength(&handle->pdata, &handle->data_len); + if(FAILED(hr)) { + _ppi->log(E_LOG,"Read error while transcoding file\n"); + handle->errnum = SSC_WMA_E_READ; + return -1; + } + + _ppi->log(E_DBG,"Read %d bytes\n",handle->data_len); + + bytes_returned = handle->data_len; + if(bytes_returned > len) + bytes_returned = len; + + memcpy(buffer,handle->pdata + handle->offset,bytes_returned); + handle->offset += bytes_returned; + handle->data_len -= bytes_returned; + + if(!handle->data_len) { + handle->pBuffer->Release(); + handle->pBuffer = NULL; + } + } else { + return 0; + } + + return bytes_returned; +} diff --git a/win32/FireflyShell/FireflyShell.vcproj b/win32/FireflyShell/FireflyShell.vcproj index 6b22a52b..f7c7b20d 100644 --- a/win32/FireflyShell/FireflyShell.vcproj +++ b/win32/FireflyShell/FireflyShell.vcproj @@ -43,8 +43,7 @@ + Name="VCPreBuildEventTool"/> + Name="VCPreBuildEventTool"/> + Name="VCPreBuildEventTool"/> + Name="VCPreBuildEventTool"/> + Name="VCPreBuildEventTool"/> + Name="VCPreBuildEventTool"/> + Name="VCPreBuildEventTool"/> + Name="VCPreBuildEventTool"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/win32/versionize.bat b/win32/versionize.bat index 8e39a1eb..ee4804e7 100644 --- a/win32/versionize.bat +++ b/win32/versionize.bat @@ -11,3 +11,4 @@ echo Fixing version info... %SUBWC% %0\..\.. %0\..\rsp.rc.templ %0\..\rsp.rc %SUBWC% %0\..\.. %0\..\w32-event.rc.templ %0\..\w32-event.rc %SUBWC% %0\..\.. %0\..\FireflyShell\version.h.templ %0\..\FireflyShell\version.h +%SUBWC% %0\..\.. %0\..\ssc-wma\ssc-wma.rc.templ %0\..\ssc-wma\ssc-wma.rc diff --git a/win32/w32-event.vcproj b/win32/w32-event.vcproj index 1deeb043..f3f9bc8a 100644 --- a/win32/w32-event.vcproj +++ b/win32/w32-event.vcproj @@ -47,8 +47,7 @@ + Name="VCPreBuildEventTool"/> + Name="VCPreBuildEventTool"/>