Add plugin for wma transcoding based on windows media format 9.5 SDK.

This commit is contained in:
Ron Pedde
2006-06-05 04:18:33 +00:00
parent 15ae458b87
commit 8f8a5a5cb7
15 changed files with 625 additions and 40 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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));

311
src/plugins/ssc-wma.cpp Normal file
View File

@@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <wmsdk.h>
#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;
}