- style cleanup
- remove multi_audio commented code - don't connect in ctor, but in Node::Connected(), this way it doesn't hang up everything on startup even if it's not the selected system output. - prepare for asynchronous connection - add an enable checkbox and change parameter handling git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27010 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -46,6 +46,7 @@
|
||||
#include <Debug.h>
|
||||
#include "ESDEndpoint.h"
|
||||
|
||||
|
||||
ESDEndpoint::ESDEndpoint()
|
||||
: BDataIO()
|
||||
, fHost(NULL)
|
||||
@@ -56,6 +57,7 @@ ESDEndpoint::ESDEndpoint()
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
ESDEndpoint::~ESDEndpoint()
|
||||
{
|
||||
CALLED();
|
||||
@@ -64,8 +66,18 @@ ESDEndpoint::~ESDEndpoint()
|
||||
fSocket = -1;
|
||||
}
|
||||
|
||||
void ESDEndpoint::Reset()
|
||||
|
||||
status_t
|
||||
ESDEndpoint::InitCheck() const
|
||||
{
|
||||
return fInitStatus;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ESDEndpoint::Reset()
|
||||
{
|
||||
fInitStatus = B_NO_INIT;
|
||||
fDefaultCommand = ESD_PROTO_STREAM_PLAY;
|
||||
fDefaultCommandSent = false;
|
||||
fDefaultFormat = ESD_BITS8 | ESD_MONO;
|
||||
@@ -73,7 +85,9 @@ void ESDEndpoint::Reset()
|
||||
fLatency = 0LL;
|
||||
}
|
||||
|
||||
status_t ESDEndpoint::SendAuthKey()
|
||||
|
||||
status_t
|
||||
ESDEndpoint::SendAuthKey()
|
||||
{
|
||||
CALLED();
|
||||
BPath kfPath;
|
||||
@@ -106,13 +120,49 @@ status_t ESDEndpoint::SendAuthKey()
|
||||
return write(fSocket, fAuthKey, ESD_MAX_KEY);
|
||||
}
|
||||
|
||||
status_t ESDEndpoint::Connect(const char *host, uint16 port)
|
||||
|
||||
bool
|
||||
ESDEndpoint::Connected() const
|
||||
{
|
||||
return (fInitStatus == B_OK);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ESDEndpoint::Connect(const char *host, uint16 port)
|
||||
{
|
||||
status_t err;
|
||||
// set up connection asynchronously
|
||||
fHost = host;
|
||||
fPort = port;
|
||||
|
||||
err = fConnectThread = spawn_thread(_ConnectThread, "ESDEndpoint Connection", B_LOW_PRIORITY, this);
|
||||
if (err < B_OK)
|
||||
return err;
|
||||
err = resume_thread(fConnectThread);
|
||||
|
||||
// TODO: return now instead and move Connect() call
|
||||
wait_for_thread(fConnectThread, &err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
ESDEndpoint::_ConnectThread(void *_arg)
|
||||
{
|
||||
ESDEndpoint *_this = (ESDEndpoint *)_arg;
|
||||
return _this->ConnectThread();
|
||||
}
|
||||
|
||||
int32
|
||||
ESDEndpoint::ConnectThread(void)
|
||||
{
|
||||
const char *host = fHost.String();
|
||||
uint16 port = fPort;
|
||||
status_t err;
|
||||
int flag;
|
||||
CALLED();
|
||||
fHost = host;
|
||||
fPort = port;
|
||||
|
||||
struct hostent *he;
|
||||
struct sockaddr_in sin;
|
||||
@@ -140,7 +190,7 @@ status_t ESDEndpoint::Connect(const char *host, uint16 port)
|
||||
*/
|
||||
|
||||
err = connect(fSocket, (struct sockaddr *) &sin, sizeof(sin));
|
||||
PRINT(("connect: %s\n", strerror(err)));
|
||||
PRINT(("connect: %ld, %s\n", err, strerror(errno)));
|
||||
if (err < 0)
|
||||
return errno;
|
||||
|
||||
@@ -220,17 +270,17 @@ status_t ESDEndpoint::Connect(const char *host, uint16 port)
|
||||
setsockopt(fSocket, SOL_SOCKET, SO_SNDBUF, &flag, sizeof(flag));
|
||||
*/
|
||||
|
||||
// read(fSocket, &ok, sizeof(uint32));
|
||||
// connect
|
||||
// auth
|
||||
// ask server latency
|
||||
// calc network latency (time (send+recv) / 2) ?
|
||||
// get default format
|
||||
|
||||
|
||||
// TODO: get default format
|
||||
|
||||
fInitStatus = B_OK;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t ESDEndpoint::Disconnect()
|
||||
status_t
|
||||
ESDEndpoint::Disconnect()
|
||||
{
|
||||
CALLED();
|
||||
if (fSocket > -1)
|
||||
@@ -239,7 +289,8 @@ status_t ESDEndpoint::Disconnect()
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t ESDEndpoint::SetCommand(esd_command_t cmd)
|
||||
status_t
|
||||
ESDEndpoint::SetCommand(esd_command_t cmd)
|
||||
{
|
||||
CALLED();
|
||||
if (fDefaultCommandSent)
|
||||
@@ -248,7 +299,8 @@ status_t ESDEndpoint::SetCommand(esd_command_t cmd)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t ESDEndpoint::SetFormat(int bits, int channels, float rate)
|
||||
status_t
|
||||
ESDEndpoint::SetFormat(int bits, int channels, float rate)
|
||||
{
|
||||
esd_format_t fmt = 0;
|
||||
CALLED();
|
||||
@@ -282,7 +334,8 @@ status_t ESDEndpoint::SetFormat(int bits, int channels, float rate)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t ESDEndpoint::GetServerInfo()
|
||||
status_t
|
||||
ESDEndpoint::GetServerInfo()
|
||||
{
|
||||
CALLED();
|
||||
struct serverinfo {
|
||||
@@ -298,19 +351,22 @@ status_t ESDEndpoint::GetServerInfo()
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
bool ESDEndpoint::CanSend()
|
||||
bool
|
||||
ESDEndpoint::CanSend()
|
||||
{
|
||||
CALLED();
|
||||
return fDefaultCommandSent;
|
||||
}
|
||||
|
||||
ssize_t ESDEndpoint::Read(void *buffer, size_t size)
|
||||
ssize_t
|
||||
ESDEndpoint::Read(void *buffer, size_t size)
|
||||
{
|
||||
CALLED();
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
ssize_t ESDEndpoint::Write(const void *buffer, size_t size)
|
||||
ssize_t
|
||||
ESDEndpoint::Write(const void *buffer, size_t size)
|
||||
{
|
||||
status_t err = B_OK;
|
||||
CALLED();
|
||||
@@ -336,7 +392,8 @@ ssize_t ESDEndpoint::Write(const void *buffer, size_t size)
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t ESDEndpoint::SendCommand(esd_command_t cmd, const uint8 *obuf, size_t olen, uint8 *ibuf, size_t ilen)
|
||||
status_t
|
||||
ESDEndpoint::SendCommand(esd_command_t cmd, const uint8 *obuf, size_t olen, uint8 *ibuf, size_t ilen)
|
||||
{
|
||||
status_t err;
|
||||
CALLED();
|
||||
@@ -358,7 +415,8 @@ status_t ESDEndpoint::SendCommand(esd_command_t cmd, const uint8 *obuf, size_t o
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t ESDEndpoint::SendDefaultCommand()
|
||||
status_t
|
||||
ESDEndpoint::SendDefaultCommand()
|
||||
{
|
||||
status_t err;
|
||||
struct {
|
||||
|
||||
@@ -44,8 +44,11 @@ public:
|
||||
~ESDEndpoint();
|
||||
|
||||
/* */
|
||||
status_t InitCheck() const;
|
||||
void Reset();
|
||||
status_t SendAuthKey();
|
||||
|
||||
bool Connected() const;
|
||||
status_t Connect(const char *host, uint16 port=ESD_DEFAULT_PORT);
|
||||
status_t Disconnect();
|
||||
|
||||
@@ -71,7 +74,12 @@ virtual ssize_t Write(const void *buffer, size_t size);
|
||||
status_t SendCommand(esd_command_t cmd, const uint8 *obuf, size_t olen, uint8 *ibuf, size_t ilen);
|
||||
status_t SendDefaultCommand();
|
||||
private:
|
||||
|
||||
|
||||
static int32 _ConnectThread(void *_arg);
|
||||
int32 ConnectThread(void);
|
||||
|
||||
status_t fInitStatus;
|
||||
thread_id fConnectThread;
|
||||
BString fHost;
|
||||
uint16 fPort;
|
||||
int fSocket;
|
||||
|
||||
@@ -133,9 +133,11 @@ ESDSinkNode::ESDSinkNode(BMediaAddOn *addon, char* name, BMessage * config)
|
||||
config->FindString("hostname", &fHostname);
|
||||
}
|
||||
if (fHostname.Length() < 1)
|
||||
fHostname = "192.168.0.253";
|
||||
fHostname = "192.168.0.1";
|
||||
fPort = ESD_DEFAULT_PORT;
|
||||
|
||||
fDevice = new ESDEndpoint();
|
||||
/*
|
||||
if (fDevice) {
|
||||
if (fDevice->Connect(fHostname.String()) >= 0) {
|
||||
fDevice->SetCommand();
|
||||
@@ -144,6 +146,10 @@ ESDSinkNode::ESDSinkNode(BMediaAddOn *addon, char* name, BMessage * config)
|
||||
fInitCheckStatus = fDevice->SendDefaultCommand();
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (!fDevice)
|
||||
return;
|
||||
fInitCheckStatus = B_OK;
|
||||
}
|
||||
|
||||
status_t ESDSinkNode::InitCheck(void) const
|
||||
@@ -432,6 +438,15 @@ status_t ESDSinkNode::Connected(
|
||||
return B_MEDIA_BAD_DESTINATION;
|
||||
}
|
||||
|
||||
//
|
||||
if (fDevice) {
|
||||
if (fDevice->Connect(fHostname.String(), fPort) >= 0) {
|
||||
fDevice->SetCommand();
|
||||
//fDevice->GetServerInfo();
|
||||
fDevice->SetFormat(ESD_FMT, 2);
|
||||
fInitCheckStatus = fDevice->SendDefaultCommand();
|
||||
}
|
||||
}
|
||||
// use one buffer length latency
|
||||
fInternalLatency = with_format.u.raw_audio.buffer_size * 10000 / 2
|
||||
/ ( (with_format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK)
|
||||
@@ -1076,18 +1091,27 @@ ESDSinkNode::GetParameterValue(int32 id, bigtime_t* last_change, void* value, si
|
||||
if (!fDevice)
|
||||
return B_ERROR;
|
||||
//PRINT(("id : %i\n", id));
|
||||
if (id == fWebHostId) {
|
||||
BString s = fDevice->Host();
|
||||
*ioSize = MIN(*ioSize, s.Length());
|
||||
memcpy(value, s.String(), *ioSize);
|
||||
return B_OK;
|
||||
}
|
||||
if (id == fWebPortId) {
|
||||
BString s;
|
||||
s << fDevice->Port();
|
||||
*ioSize = MIN(*ioSize, s.Length());
|
||||
memcpy(value, s.String(), *ioSize);
|
||||
return B_OK;
|
||||
switch (id) {
|
||||
case PARAM_ENABLED:
|
||||
// XXX
|
||||
break;
|
||||
case PARAM_HOST:
|
||||
{
|
||||
BString s = fDevice->Host();
|
||||
*ioSize = MIN(*ioSize, s.Length());
|
||||
memcpy(value, s.String(), *ioSize);
|
||||
return B_OK;
|
||||
}
|
||||
case PARAM_PORT:
|
||||
{
|
||||
BString s;
|
||||
s << fDevice->Port();
|
||||
*ioSize = MIN(*ioSize, s.Length());
|
||||
memcpy(value, s.String(), *ioSize);
|
||||
return B_OK;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
BParameter *parameter = NULL;
|
||||
@@ -1098,78 +1122,6 @@ ESDSinkNode::GetParameterValue(int32 id, bigtime_t* last_change, void* value, si
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if(!parameter) {
|
||||
// Hmmm, we were asked for a parameter that we don't actually
|
||||
// support. Report an error back to the caller.
|
||||
PRINT(("\terror - asked for illegal parameter %ld\n", id));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
multi_mix_value_info MMVI;
|
||||
multi_mix_value MMV[2];
|
||||
int rval;
|
||||
MMVI.values = MMV;
|
||||
id = id - 100;
|
||||
MMVI.item_count = 0;
|
||||
|
||||
if (*ioSize < sizeof(float))
|
||||
return B_ERROR;
|
||||
|
||||
if(parameter->Type() == BParameter::B_CONTINUOUS_PARAMETER) {
|
||||
MMVI.item_count = 1;
|
||||
MMV[0].id = id;
|
||||
|
||||
if(parameter->CountChannels() == 2) {
|
||||
if (*ioSize < 2*sizeof(float))
|
||||
return B_ERROR;
|
||||
MMVI.item_count = 2;
|
||||
MMV[1].id = id + 1;
|
||||
}
|
||||
|
||||
} else if(parameter->Type() == BParameter::B_DISCRETE_PARAMETER) {
|
||||
MMVI.item_count = 1;
|
||||
MMV[0].id = id;
|
||||
}
|
||||
|
||||
if(MMVI.item_count > 0) {
|
||||
rval = fDevice->DoGetMix(&MMVI);
|
||||
|
||||
if (B_OK != rval) {
|
||||
fprintf(stderr, "Failed on DRIVER_GET_MIX\n");
|
||||
} else {
|
||||
|
||||
if(parameter->Type() == BParameter::B_CONTINUOUS_PARAMETER) {
|
||||
((float*)value)[0] = MMV[0].gain;
|
||||
*ioSize = sizeof(float);
|
||||
|
||||
if(parameter->CountChannels() == 2) {
|
||||
((float*)value)[1] = MMV[1].gain;
|
||||
*ioSize = 2*sizeof(float);
|
||||
}
|
||||
|
||||
for(uint32 i=0; i < (*ioSize/sizeof(float)); i++) {
|
||||
PRINT(("B_CONTINUOUS_PARAMETER value[%i] : %f\n", i, ((float*)value)[i]));
|
||||
}
|
||||
} else if(parameter->Type() == BParameter::B_DISCRETE_PARAMETER) {
|
||||
|
||||
BDiscreteParameter *dparameter = (BDiscreteParameter*) parameter;
|
||||
if(dparameter->CountItems()<=2) {
|
||||
((int32*)value)[0] = (MMV[0].enable) ? 1 : 0;
|
||||
} else {
|
||||
((int32*)value)[0] = MMV[0].mux;
|
||||
}
|
||||
*ioSize = sizeof(int32);
|
||||
|
||||
for(uint32 i=0; i < (*ioSize/sizeof(int32)); i++) {
|
||||
PRINT(("B_DISCRETE_PARAMETER value[%i] : %i\n", i, ((int32*)value)[i]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return B_OK;
|
||||
#endif
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
@@ -1184,70 +1136,40 @@ ESDSinkNode::SetParameterValue(int32 id, bigtime_t performance_time, const void*
|
||||
if(parameter->ID() == id)
|
||||
break;
|
||||
}
|
||||
if (id == fWebHostId) {
|
||||
fprintf(stderr, "set HOST: %s\n", (const char *)value);
|
||||
BString host = (const char *)value;
|
||||
uint16 port = fDevice->Port();
|
||||
fDevice->Connect(host.String(), port);
|
||||
return;
|
||||
}
|
||||
if (id == fWebPortId) {
|
||||
fprintf(stderr, "set PORT: %s\n", (const char *)value);
|
||||
BString host = fDevice->Host();
|
||||
uint16 port = atoi((const char *)value);
|
||||
fDevice->Connect(host.String(), port);
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
if(parameter) {
|
||||
multi_mix_value_info MMVI;
|
||||
multi_mix_value MMV[2];
|
||||
int rval;
|
||||
MMVI.values = MMV;
|
||||
id = id - 100;
|
||||
MMVI.item_count = 0;
|
||||
|
||||
if(parameter->Type() == BParameter::B_CONTINUOUS_PARAMETER) {
|
||||
for(uint32 i=0; i < (size/sizeof(float)); i++) {
|
||||
PRINT(("B_CONTINUOUS_PARAMETER value[%i] : %f\n", i, ((float*)value)[i]));
|
||||
}
|
||||
MMVI.item_count = 1;
|
||||
MMV[0].id = id;
|
||||
MMV[0].gain = ((float*)value)[0];
|
||||
|
||||
if(parameter->CountChannels() == 2) {
|
||||
MMVI.item_count = 2;
|
||||
MMV[1].id = id + 1;
|
||||
MMV[1].gain = ((float*)value)[1];
|
||||
}
|
||||
|
||||
} else if(parameter->Type() == BParameter::B_DISCRETE_PARAMETER) {
|
||||
for(uint32 i=0; i < (size/sizeof(int32)); i++) {
|
||||
PRINT(("B_DISCRETE_PARAMETER value[%i] : %i\n", i, ((int32*)value)[i]));
|
||||
}
|
||||
BDiscreteParameter *dparameter = (BDiscreteParameter*) parameter;
|
||||
|
||||
if(dparameter->CountItems()<=2) {
|
||||
MMVI.item_count = 1;
|
||||
MMV[0].id = id;
|
||||
MMV[0].enable = (((int32*)value)[0] == 1) ? true : false;
|
||||
} else {
|
||||
MMVI.item_count = 1;
|
||||
MMV[0].id = id;
|
||||
MMV[0].mux = ((uint32*)value)[0];
|
||||
switch (id) {
|
||||
case PARAM_ENABLED:
|
||||
break;
|
||||
case PARAM_HOST:
|
||||
{
|
||||
fprintf(stderr, "set HOST: %s\n", (const char *)value);
|
||||
fHostname = (const char *)value;
|
||||
if (fDevice && fDevice->Connected()) {
|
||||
if (fDevice->Connect(fHostname.String(), fPort) >= 0) {
|
||||
fDevice->SetCommand();
|
||||
fDevice->SetFormat(ESD_FMT, 2);
|
||||
//fDevice->GetServerInfo();
|
||||
fInitCheckStatus = fDevice->SendDefaultCommand();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(MMVI.item_count > 0) {
|
||||
rval = fDevice->DoSetMix(&MMVI);
|
||||
|
||||
if (B_OK != rval)
|
||||
{
|
||||
fprintf(stderr, "Failed on DRIVER_SET_MIX\n");
|
||||
case PARAM_PORT:
|
||||
{
|
||||
fprintf(stderr, "set PORT: %s\n", (const char *)value);
|
||||
fPort = atoi((const char *)value);
|
||||
if (fDevice && fDevice->Connected()) {
|
||||
if (fDevice->Connect(fHostname.String(), fPort) >= 0) {
|
||||
fDevice->SetCommand();
|
||||
fDevice->SetFormat(ESD_FMT, 2);
|
||||
//fDevice->GetServerInfo();
|
||||
fInitCheckStatus = fDevice->SendDefaultCommand();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
BParameterWeb*
|
||||
@@ -1276,12 +1198,12 @@ ESDSinkNode::MakeParameterWeb()
|
||||
int id = 0;
|
||||
BParameterGroup *group = web->MakeGroup("Server");
|
||||
BParameter *p;
|
||||
fWebHostId = fWebPortId = -1;
|
||||
// XXX: use B_MEDIA_UNKNOWN_TYPE or _NO_TYPE ?
|
||||
// keep in sync with enum { PARAM_* } !
|
||||
p = group->MakeDiscreteParameter(PARAM_ENABLED, B_MEDIA_RAW_AUDIO, "Enable", B_ENABLE);
|
||||
#if defined(B_BEOS_VERSION_DANO) || defined(__HAIKU__)
|
||||
fWebHostId = id++;
|
||||
p = group->MakeTextParameter(fWebHostId, B_MEDIA_RAW_AUDIO, "Hostname", B_GENERIC, 128);
|
||||
fWebPortId = id++;
|
||||
p = group->MakeTextParameter(fWebPortId, B_MEDIA_RAW_AUDIO, "Port", B_GENERIC, 16);
|
||||
p = group->MakeTextParameter(PARAM_HOST, B_MEDIA_RAW_AUDIO, "Hostname", B_GENERIC, 128);
|
||||
p = group->MakeTextParameter(PARAM_PORT, B_MEDIA_RAW_AUDIO, "Port", B_GENERIC, 16);
|
||||
#endif
|
||||
return web;
|
||||
}
|
||||
|
||||
@@ -52,6 +52,13 @@
|
||||
const media_format & producer_format,
|
||||
const media_format & consumer_format);*/
|
||||
|
||||
|
||||
enum {
|
||||
PARAM_ENABLED,
|
||||
PARAM_HOST,
|
||||
PARAM_PORT
|
||||
};
|
||||
|
||||
class ESDSinkNode :
|
||||
public BBufferConsumer,
|
||||
#if ENABLE_INPUT
|
||||
@@ -345,6 +352,7 @@ private:
|
||||
thread_id fThread;
|
||||
|
||||
BString fHostname;
|
||||
uint16 fPort;
|
||||
ESDEndpoint *fDevice;
|
||||
|
||||
//multi_description MD;
|
||||
@@ -357,8 +365,6 @@ private:
|
||||
bool fTimeSourceStarted;
|
||||
|
||||
BParameterWeb *fWeb;
|
||||
int32 fWebHostId;
|
||||
int32 fWebPortId;
|
||||
|
||||
BMessage fConfig;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user