- renamed some constants to match esd.h
- ask server latency and use it (not always better...) - set and get host/port parameter, setting doesn't reconnect correctly. not saved yet. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19199 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -49,15 +49,11 @@
|
|||||||
ESDEndpoint::ESDEndpoint()
|
ESDEndpoint::ESDEndpoint()
|
||||||
: BDataIO()
|
: BDataIO()
|
||||||
, fHost(NULL)
|
, fHost(NULL)
|
||||||
, fPort(ESD_PORT)
|
, fPort(ESD_DEFAULT_PORT)
|
||||||
, fSocket(-1)
|
, fSocket(-1)
|
||||||
, fDefaultCommand(ESD_CMD_STREAM_PLAY)
|
|
||||||
, fDefaultCommandSent(false)
|
|
||||||
, fDefaultFormat(ESD_BITS8 | ESD_MONO)
|
|
||||||
, fDefaultRate(ESD_DEFAULT_RATE)
|
|
||||||
, fLatency(0LL)
|
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
ESDEndpoint::~ESDEndpoint()
|
ESDEndpoint::~ESDEndpoint()
|
||||||
@@ -68,6 +64,15 @@ ESDEndpoint::~ESDEndpoint()
|
|||||||
fSocket = -1;
|
fSocket = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ESDEndpoint::Reset()
|
||||||
|
{
|
||||||
|
fDefaultCommand = ESD_PROTO_STREAM_PLAY;
|
||||||
|
fDefaultCommandSent = false;
|
||||||
|
fDefaultFormat = ESD_BITS8 | ESD_MONO;
|
||||||
|
fDefaultRate = ESD_DEFAULT_RATE;
|
||||||
|
fLatency = 0LL;
|
||||||
|
}
|
||||||
|
|
||||||
status_t ESDEndpoint::SendAuthKey()
|
status_t ESDEndpoint::SendAuthKey()
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
@@ -104,6 +109,7 @@ status_t ESDEndpoint::SendAuthKey()
|
|||||||
status_t ESDEndpoint::Connect(const char *host, uint16 port)
|
status_t ESDEndpoint::Connect(const char *host, uint16 port)
|
||||||
{
|
{
|
||||||
status_t err;
|
status_t err;
|
||||||
|
int flag;
|
||||||
CALLED();
|
CALLED();
|
||||||
fHost = host;
|
fHost = host;
|
||||||
fPort = port;
|
fPort = port;
|
||||||
@@ -116,45 +122,103 @@ status_t ESDEndpoint::Connect(const char *host, uint16 port)
|
|||||||
return ENOENT;
|
return ENOENT;
|
||||||
memcpy((struct in_addr *)&sin.sin_addr, he->h_addr, sizeof(struct in_addr));
|
memcpy((struct in_addr *)&sin.sin_addr, he->h_addr, sizeof(struct in_addr));
|
||||||
|
|
||||||
|
/* close old connection */
|
||||||
|
if (fSocket > -1)
|
||||||
|
closesocket(fSocket);
|
||||||
|
Reset();
|
||||||
|
|
||||||
fSocket = socket(AF_INET, SOCK_STREAM, 0);
|
fSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (fSocket < 0)
|
if (fSocket < 0)
|
||||||
return errno;
|
return errno;
|
||||||
sin.sin_family = AF_INET;
|
sin.sin_family = AF_INET;
|
||||||
sin.sin_port = htons( port );
|
sin.sin_port = htons( port );
|
||||||
|
|
||||||
|
/*
|
||||||
|
flag = 128*1024;
|
||||||
|
setsockopt(fSocket, SOL_SOCKET, SO_SNDBUF, &flag, sizeof(flag));
|
||||||
|
setsockopt(fSocket, SOL_SOCKET, SO_RCVBUF, &flag, sizeof(flag));
|
||||||
|
*/
|
||||||
|
|
||||||
err = connect(fSocket, (struct sockaddr *) &sin, sizeof(sin));
|
err = connect(fSocket, (struct sockaddr *) &sin, sizeof(sin));
|
||||||
PRINT(("connect: %s\n", strerror(err)));
|
PRINT(("connect: %s\n", strerror(err)));
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return errno;
|
return errno;
|
||||||
|
|
||||||
/* uint32 cmd = ESD_CMD_CONNECT;
|
uint32 cmd;
|
||||||
|
uint32 result;
|
||||||
|
/* uint32 cmd = ESD_PROTO_CONNECT;
|
||||||
err = write(fSocket, &cmd, sizeof(cmd));
|
err = write(fSocket, &cmd, sizeof(cmd));
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return errno;
|
return errno;
|
||||||
if (err < sizeof(cmd))
|
if (err < sizeof(cmd))
|
||||||
return EIO;
|
return EIO;
|
||||||
*/
|
*/
|
||||||
|
/* send authentification key */
|
||||||
err = SendAuthKey();
|
err = SendAuthKey();
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return errno;
|
return errno;
|
||||||
|
|
||||||
|
/* send endian tag, wait for 'ok' and measure the round-trip time
|
||||||
|
* to account for the network latency
|
||||||
|
*/
|
||||||
bigtime_t ping = system_time();
|
bigtime_t ping = system_time();
|
||||||
|
|
||||||
uint32 endian = ESD_ENDIAN_TAG;
|
cmd = ESD_ENDIAN_TAG;
|
||||||
err = write(fSocket, &endian, sizeof(endian));
|
err = write(fSocket, &cmd, sizeof(cmd));
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return errno;
|
return errno;
|
||||||
if (err < sizeof(endian))
|
if (err < sizeof(cmd))
|
||||||
return EIO;
|
return EIO;
|
||||||
uint32 ok;
|
|
||||||
|
|
||||||
read(fSocket, &ok, sizeof(uint32));
|
read(fSocket, &result, sizeof(result));
|
||||||
|
if (result != 1)
|
||||||
|
fprintf(stderr, "ESDEndpoint::Connect: didn't get ok from ESD_PROTO_INIT (%ld)!\n", result);
|
||||||
|
|
||||||
ping = system_time() - ping;
|
ping = (system_time() - ping) / 2; /* approximate one-way trip time */
|
||||||
fLatency = ping;
|
fLatency = ping;
|
||||||
|
|
||||||
int flag = 1;
|
/* ask the server for its own latency
|
||||||
|
* sadly it seems to only give a fixed value,
|
||||||
|
* not counting the audio card's buffering into account.
|
||||||
|
* we take another measurement of the round-trip,
|
||||||
|
* and use the mean of the 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ping = system_time();
|
||||||
|
|
||||||
|
cmd = ESD_PROTO_LATENCY;
|
||||||
|
err = write(fSocket, &cmd, sizeof(cmd));
|
||||||
|
if (err < 0)
|
||||||
|
return errno;
|
||||||
|
if (err < sizeof(cmd))
|
||||||
|
return EIO;
|
||||||
|
|
||||||
|
read(fSocket, &result, sizeof(result));
|
||||||
|
fprintf(stderr, "ESDEndpoint::Connect: ESD_PROTO_LATENCY: %ld\n", result);
|
||||||
|
|
||||||
|
ping = (system_time() - ping) / 2; /* approximate one-way trip time */
|
||||||
|
|
||||||
|
bigtime_t serverLatency = result * 1000000LL / (ESD_DEFAULT_RATE * 2/*16b*/ * 2/*stereo*/ );
|
||||||
|
bigtime_t netLatency = (fLatency + ping) / 2; /* mean of both */
|
||||||
|
fprintf(stderr, "ESDEndpoint::Connect: Latency: server: %Ld, net1: %Ld, net2: %Ld\n", serverLatency, fLatency, ping);
|
||||||
|
|
||||||
|
fLatency = netLatency + serverLatency;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
flag = 1;
|
||||||
|
int len;
|
||||||
|
/* disable Nagle */
|
||||||
setsockopt(fSocket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
|
setsockopt(fSocket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
|
||||||
|
//setsockopt(fSocket, SOL_SOCKET, SO_NONBLOCK, &flag, sizeof(flag));
|
||||||
|
/*
|
||||||
|
len = sizeof(flag);
|
||||||
|
getsockopt(fSocket, SOL_SOCKET, SO_SNDBUF, &flag, &len);
|
||||||
|
fprintf(stderr, "ESDEndpoint::Connect: SNDBUF: %ld\n", flag);
|
||||||
|
flag = MIN(TCP_MAXWIN, MAX(flag, (4 * netLatency * (ESD_DEFAULT_RATE*2*2) / 1000000LL)));
|
||||||
|
fprintf(stderr, "ESDEndpoint::Connect: SNDBUF: %ld\n", flag);
|
||||||
|
setsockopt(fSocket, SOL_SOCKET, SO_SNDBUF, &flag, sizeof(flag));
|
||||||
|
*/
|
||||||
|
|
||||||
// read(fSocket, &ok, sizeof(uint32));
|
// read(fSocket, &ok, sizeof(uint32));
|
||||||
// connect
|
// connect
|
||||||
@@ -227,7 +291,7 @@ status_t ESDEndpoint::GetServerInfo()
|
|||||||
uint32 fmt;
|
uint32 fmt;
|
||||||
} si;
|
} si;
|
||||||
status_t err;
|
status_t err;
|
||||||
err = SendCommand(ESD_CMD_SERVER_INFO, (const uint8 *)&si, 0, (uint8 *)&si, sizeof(si));
|
err = SendCommand(ESD_PROTO_SERVER_INFO, (const uint8 *)&si, 0, (uint8 *)&si, sizeof(si));
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
PRINT(("err %d, version: %lu, rate: %lu, fmt: %lu\n", err, si.ver, si.rate, si.fmt));
|
PRINT(("err %d, version: %lu, rate: %lu, fmt: %lu\n", err, si.ver, si.rate, si.fmt));
|
||||||
|
|||||||
@@ -44,12 +44,13 @@ public:
|
|||||||
~ESDEndpoint();
|
~ESDEndpoint();
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
|
void Reset();
|
||||||
status_t SendAuthKey();
|
status_t SendAuthKey();
|
||||||
status_t Connect(const char *host, uint16 port=ESD_PORT);
|
status_t Connect(const char *host, uint16 port=ESD_DEFAULT_PORT);
|
||||||
status_t Disconnect();
|
status_t Disconnect();
|
||||||
|
|
||||||
/* set the default command and format for BDataIO interface */
|
/* set the default command and format for BDataIO interface */
|
||||||
status_t SetCommand(esd_command_t cmd=ESD_CMD_STREAM_PLAY);
|
status_t SetCommand(esd_command_t cmd=ESD_PROTO_STREAM_PLAY);
|
||||||
status_t SetFormat(int bits, int channels, float rate=ESD_DEFAULT_RATE);
|
status_t SetFormat(int bits, int channels, float rate=ESD_DEFAULT_RATE);
|
||||||
|
|
||||||
status_t GetServerInfo();
|
status_t GetServerInfo();
|
||||||
@@ -57,6 +58,8 @@ status_t GetServerInfo();
|
|||||||
/* */
|
/* */
|
||||||
|
|
||||||
bigtime_t GetLatency() const { return fLatency; };
|
bigtime_t GetLatency() const { return fLatency; };
|
||||||
|
const char *Host() const { return fHost.String(); };
|
||||||
|
uint16 Port() const { return fPort; };
|
||||||
|
|
||||||
bool CanSend();
|
bool CanSend();
|
||||||
|
|
||||||
|
|||||||
@@ -1087,14 +1087,31 @@ status_t
|
|||||||
ESDSinkNode::GetParameterValue(int32 id, bigtime_t* last_change, void* value, size_t* ioSize)
|
ESDSinkNode::GetParameterValue(int32 id, bigtime_t* last_change, void* value, size_t* ioSize)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
if (!fDevice)
|
||||||
PRINT(("id : %i\n", id));
|
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;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
BParameter *parameter = NULL;
|
BParameter *parameter = NULL;
|
||||||
for(int32 i=0; i<fWeb->CountParameters(); i++) {
|
for(int32 i=0; i<fWeb->CountParameters(); i++) {
|
||||||
parameter = fWeb->ParameterAt(i);
|
parameter = fWeb->ParameterAt(i);
|
||||||
if(parameter->ID() == id)
|
if(parameter->ID() == id)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if(!parameter) {
|
if(!parameter) {
|
||||||
// Hmmm, we were asked for a parameter that we don't actually
|
// Hmmm, we were asked for a parameter that we don't actually
|
||||||
@@ -1181,6 +1198,20 @@ ESDSinkNode::SetParameterValue(int32 id, bigtime_t performance_time, const void*
|
|||||||
if(parameter->ID() == id)
|
if(parameter->ID() == id)
|
||||||
break;
|
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 0
|
||||||
if(parameter) {
|
if(parameter) {
|
||||||
multi_mix_value_info MMVI;
|
multi_mix_value_info MMVI;
|
||||||
@@ -1259,8 +1290,13 @@ ESDSinkNode::MakeParameterWeb()
|
|||||||
int id = 0;
|
int id = 0;
|
||||||
BParameterGroup *group = web->MakeGroup("Server");
|
BParameterGroup *group = web->MakeGroup("Server");
|
||||||
BParameter *p;
|
BParameter *p;
|
||||||
p = group->MakeTextParameter(id++, B_MEDIA_RAW_AUDIO, "Hostname", B_GENERIC, 128);
|
fWebHostId = fWebPortId = -1;
|
||||||
p = group->MakeTextParameter(id++, B_MEDIA_RAW_AUDIO, "Port", B_GENERIC, 16);
|
#ifdef B_BEOS_VERSION_DANO /* not yet in 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);
|
||||||
|
#endif
|
||||||
return web;
|
return web;
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
|
|||||||
@@ -357,6 +357,8 @@ private:
|
|||||||
bool fTimeSourceStarted;
|
bool fTimeSourceStarted;
|
||||||
|
|
||||||
BParameterWeb *fWeb;
|
BParameterWeb *fWeb;
|
||||||
|
int32 fWebHostId;
|
||||||
|
int32 fWebPortId;
|
||||||
|
|
||||||
BMessage fConfig;
|
BMessage fConfig;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ typedef char esd_key_t[ESD_MAX_KEY];
|
|||||||
typedef char esd_name_t[ESD_MAX_NAME];
|
typedef char esd_name_t[ESD_MAX_NAME];
|
||||||
|
|
||||||
/* defaults */
|
/* defaults */
|
||||||
//#define ESD_PORT 5001
|
//#define ESD_DEFAULT_PORT 5001
|
||||||
#define ESD_PORT 16001
|
#define ESD_DEFAULT_PORT 16001
|
||||||
|
|
||||||
#define ESD_DEFAULT_RATE 44100
|
#define ESD_DEFAULT_RATE 44100
|
||||||
//#define ESD_DEFAULT_RATE 22050
|
//#define ESD_DEFAULT_RATE 22050
|
||||||
@@ -59,39 +59,40 @@ typedef char esd_name_t[ESD_MAX_NAME];
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
/* init */
|
/* init */
|
||||||
ESD_CMD_CONNECT = 0,
|
ESD_PROTO_CONNECT = 0,
|
||||||
|
|
||||||
/* security */
|
/* security */
|
||||||
ESD_CMD_LOCK,
|
ESD_PROTO_LOCK,
|
||||||
ESD_CMD_UNLOCK,
|
ESD_PROTO_UNLOCK,
|
||||||
|
|
||||||
ESD_CMD_STREAM_PLAY,
|
ESD_PROTO_STREAM_PLAY,
|
||||||
ESD_CMD_STREAM_REC,
|
ESD_PROTO_STREAM_REC,
|
||||||
ESD_CMD_STREAM_MON,
|
ESD_PROTO_STREAM_MON,
|
||||||
|
|
||||||
ESD_CMD_SAMPLE_CACHE,
|
ESD_PROTO_SAMPLE_CACHE,
|
||||||
ESD_CMD_SAMPLE_FREE,
|
ESD_PROTO_SAMPLE_FREE,
|
||||||
ESD_CMD_SAMPLE_PLAY,
|
ESD_PROTO_SAMPLE_PLAY,
|
||||||
ESD_CMD_SAMPLE_LOOP,
|
ESD_PROTO_SAMPLE_LOOP,
|
||||||
ESD_CMD_SAMPLE_STOP,
|
ESD_PROTO_SAMPLE_STOP,
|
||||||
ESD_CMD_SAMPLE_KILL,
|
ESD_PROTO_SAMPLE_KILL,
|
||||||
|
|
||||||
ESD_CMD_STANDBY,
|
ESD_PROTO_STANDBY,
|
||||||
ESD_CMD_RESUME,
|
ESD_PROTO_RESUME,
|
||||||
|
|
||||||
ESD_CMD_SAMPLE_GETID,
|
ESD_PROTO_SAMPLE_GETID,
|
||||||
ESD_CMD_STREAM_FILTER,
|
ESD_PROTO_STREAM_FILTER,
|
||||||
|
|
||||||
ESD_CMD_SERVER_INFO,
|
ESD_PROTO_SERVER_INFO,
|
||||||
ESD_CMD_SERVER_ALL_INFO,
|
ESD_PROTO_SERVER_ALL_INFO,
|
||||||
_ESD_CMD_SUBSCRIBE,
|
ESD_PROTO_SUBSCRIBE,
|
||||||
_ESD_CMD_UNSUBSCRIBE,
|
ESD_PROTO_UNSUBSCRIBE,
|
||||||
|
|
||||||
ESD_CMD_STREAM_PAN,
|
ESD_PROTO_STREAM_PAN,
|
||||||
ESD_CMD_SAMPLE_PAN,
|
ESD_PROTO_SAMPLE_PAN,
|
||||||
|
|
||||||
ESD_CMD_STANDBY_MODE,
|
ESD_PROTO_STANDBY_MODE,
|
||||||
ESD_CMD_LATENCY
|
ESD_PROTO_LATENCY,
|
||||||
|
ESD_PROTO_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ESD_MASK_BITS 0x000F
|
#define ESD_MASK_BITS 0x000F
|
||||||
|
|||||||
Reference in New Issue
Block a user