diff --git a/src/add-ons/media/media-add-ons/esound_sink/ESDEndpoint.cpp b/src/add-ons/media/media-add-ons/esound_sink/ESDEndpoint.cpp index a4ca123a92..7772526dae 100644 --- a/src/add-ons/media/media-add-ons/esound_sink/ESDEndpoint.cpp +++ b/src/add-ons/media/media-add-ons/esound_sink/ESDEndpoint.cpp @@ -49,15 +49,11 @@ ESDEndpoint::ESDEndpoint() : BDataIO() , fHost(NULL) - , fPort(ESD_PORT) + , fPort(ESD_DEFAULT_PORT) , fSocket(-1) - , fDefaultCommand(ESD_CMD_STREAM_PLAY) - , fDefaultCommandSent(false) - , fDefaultFormat(ESD_BITS8 | ESD_MONO) - , fDefaultRate(ESD_DEFAULT_RATE) - , fLatency(0LL) { CALLED(); + Reset(); } ESDEndpoint::~ESDEndpoint() @@ -68,6 +64,15 @@ ESDEndpoint::~ESDEndpoint() 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() { CALLED(); @@ -104,6 +109,7 @@ status_t ESDEndpoint::SendAuthKey() status_t ESDEndpoint::Connect(const char *host, uint16 port) { status_t err; + int flag; CALLED(); fHost = host; fPort = port; @@ -116,46 +122,104 @@ status_t ESDEndpoint::Connect(const char *host, uint16 port) return ENOENT; 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); if (fSocket < 0) return errno; sin.sin_family = AF_INET; 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)); PRINT(("connect: %s\n", strerror(err))); if (err < 0) return errno; -/* uint32 cmd = ESD_CMD_CONNECT; + uint32 cmd; + uint32 result; +/* uint32 cmd = ESD_PROTO_CONNECT; err = write(fSocket, &cmd, sizeof(cmd)); if (err < 0) return errno; if (err < sizeof(cmd)) return EIO; */ + /* send authentification key */ err = SendAuthKey(); if (err < 0) 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(); - uint32 endian = ESD_ENDIAN_TAG; - err = write(fSocket, &endian, sizeof(endian)); + cmd = ESD_ENDIAN_TAG; + err = write(fSocket, &cmd, sizeof(cmd)); if (err < 0) return errno; - if (err < sizeof(endian)) + if (err < sizeof(cmd)) 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; - - 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, 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)); // connect // auth @@ -227,7 +291,7 @@ status_t ESDEndpoint::GetServerInfo() uint32 fmt; } si; 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) return err; PRINT(("err %d, version: %lu, rate: %lu, fmt: %lu\n", err, si.ver, si.rate, si.fmt)); diff --git a/src/add-ons/media/media-add-ons/esound_sink/ESDEndpoint.h b/src/add-ons/media/media-add-ons/esound_sink/ESDEndpoint.h index c199f30827..e6968f4b82 100644 --- a/src/add-ons/media/media-add-ons/esound_sink/ESDEndpoint.h +++ b/src/add-ons/media/media-add-ons/esound_sink/ESDEndpoint.h @@ -44,12 +44,13 @@ public: ~ESDEndpoint(); /* */ +void Reset(); 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(); /* 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 GetServerInfo(); @@ -57,6 +58,8 @@ status_t GetServerInfo(); /* */ bigtime_t GetLatency() const { return fLatency; }; +const char *Host() const { return fHost.String(); }; +uint16 Port() const { return fPort; }; bool CanSend(); diff --git a/src/add-ons/media/media-add-ons/esound_sink/ESDSinkNode.cpp b/src/add-ons/media/media-add-ons/esound_sink/ESDSinkNode.cpp index 44a5b82a0e..56410b827a 100644 --- a/src/add-ons/media/media-add-ons/esound_sink/ESDSinkNode.cpp +++ b/src/add-ons/media/media-add-ons/esound_sink/ESDSinkNode.cpp @@ -1087,14 +1087,31 @@ status_t ESDSinkNode::GetParameterValue(int32 id, bigtime_t* last_change, void* value, size_t* ioSize) { CALLED(); - - PRINT(("id : %i\n", id)); + 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; + } +#if 0 BParameter *parameter = NULL; for(int32 i=0; iCountParameters(); i++) { parameter = fWeb->ParameterAt(i); if(parameter->ID() == id) break; } +#endif + #if 0 if(!parameter) { // 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) 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; @@ -1259,8 +1290,13 @@ ESDSinkNode::MakeParameterWeb() int id = 0; BParameterGroup *group = web->MakeGroup("Server"); BParameter *p; - p = group->MakeTextParameter(id++, B_MEDIA_RAW_AUDIO, "Hostname", B_GENERIC, 128); - p = group->MakeTextParameter(id++, B_MEDIA_RAW_AUDIO, "Port", B_GENERIC, 16); + fWebHostId = fWebPortId = -1; +#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; } #if 0 diff --git a/src/add-ons/media/media-add-ons/esound_sink/ESDSinkNode.h b/src/add-ons/media/media-add-ons/esound_sink/ESDSinkNode.h index 1721263399..bf6ee2bdf4 100644 --- a/src/add-ons/media/media-add-ons/esound_sink/ESDSinkNode.h +++ b/src/add-ons/media/media-add-ons/esound_sink/ESDSinkNode.h @@ -357,6 +357,8 @@ private: bool fTimeSourceStarted; BParameterWeb *fWeb; + int32 fWebHostId; + int32 fWebPortId; BMessage fConfig; }; diff --git a/src/add-ons/media/media-add-ons/esound_sink/esdproto.h b/src/add-ons/media/media-add-ons/esound_sink/esdproto.h index f6c90e8070..e015b28e35 100644 --- a/src/add-ons/media/media-add-ons/esound_sink/esdproto.h +++ b/src/add-ons/media/media-add-ons/esound_sink/esdproto.h @@ -49,8 +49,8 @@ typedef char esd_key_t[ESD_MAX_KEY]; typedef char esd_name_t[ESD_MAX_NAME]; /* defaults */ -//#define ESD_PORT 5001 -#define ESD_PORT 16001 +//#define ESD_DEFAULT_PORT 5001 +#define ESD_DEFAULT_PORT 16001 #define ESD_DEFAULT_RATE 44100 //#define ESD_DEFAULT_RATE 22050 @@ -59,39 +59,40 @@ typedef char esd_name_t[ESD_MAX_NAME]; enum { /* init */ - ESD_CMD_CONNECT = 0, + ESD_PROTO_CONNECT = 0, /* security */ - ESD_CMD_LOCK, - ESD_CMD_UNLOCK, + ESD_PROTO_LOCK, + ESD_PROTO_UNLOCK, - ESD_CMD_STREAM_PLAY, - ESD_CMD_STREAM_REC, - ESD_CMD_STREAM_MON, + ESD_PROTO_STREAM_PLAY, + ESD_PROTO_STREAM_REC, + ESD_PROTO_STREAM_MON, - ESD_CMD_SAMPLE_CACHE, - ESD_CMD_SAMPLE_FREE, - ESD_CMD_SAMPLE_PLAY, - ESD_CMD_SAMPLE_LOOP, - ESD_CMD_SAMPLE_STOP, - ESD_CMD_SAMPLE_KILL, + ESD_PROTO_SAMPLE_CACHE, + ESD_PROTO_SAMPLE_FREE, + ESD_PROTO_SAMPLE_PLAY, + ESD_PROTO_SAMPLE_LOOP, + ESD_PROTO_SAMPLE_STOP, + ESD_PROTO_SAMPLE_KILL, - ESD_CMD_STANDBY, - ESD_CMD_RESUME, + ESD_PROTO_STANDBY, + ESD_PROTO_RESUME, - ESD_CMD_SAMPLE_GETID, - ESD_CMD_STREAM_FILTER, + ESD_PROTO_SAMPLE_GETID, + ESD_PROTO_STREAM_FILTER, - ESD_CMD_SERVER_INFO, - ESD_CMD_SERVER_ALL_INFO, - _ESD_CMD_SUBSCRIBE, - _ESD_CMD_UNSUBSCRIBE, + ESD_PROTO_SERVER_INFO, + ESD_PROTO_SERVER_ALL_INFO, + ESD_PROTO_SUBSCRIBE, + ESD_PROTO_UNSUBSCRIBE, - ESD_CMD_STREAM_PAN, - ESD_CMD_SAMPLE_PAN, + ESD_PROTO_STREAM_PAN, + ESD_PROTO_SAMPLE_PAN, - ESD_CMD_STANDBY_MODE, - ESD_CMD_LATENCY + ESD_PROTO_STANDBY_MODE, + ESD_PROTO_LATENCY, + ESD_PROTO_MAX }; #define ESD_MASK_BITS 0x000F