#include "udpplayer.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include "debug.h"

//
// cDataStreamSocketUDP
//

bool cDataStreamSocketUDP::Open() {
	sServ.sin_family = AF_INET;
	sServ.sin_addr.s_addr = htonl ( INADDR_ANY );
	sServ.sin_port = htons ( Port );

	sock=socket(AF_INET,SOCK_DGRAM,0);
	if (sock<0) {
		sock=0;
		return false;
	}

	int r=bind(sock,(sockaddr*)&sServ,sizeof sServ);
	if (r<0) {
		_dprintf("bind() failed\n");
		return false;
	}
	fcntl(sock,F_SETFL,O_NONBLOCK);

	return true;
}

void cDataStreamSocketUDP::Close() {
    if (sock) {
		close(sock);
	}
	sock=0;
}

uchar* cDataStreamSocketUDP::Get(int &Count) {
	if (nSrcBuffer>0) {
		// return remains
		Count=nSrcBuffer;
		return pSrcBuffer;
	}

	if (!sock) {
		if (!Open()) return NULL;
	}

	int r=recvfrom(sock,SrcBuffer,sizeof SrcBuffer,0,NULL,NULL);
	if (r<0) {
		if (errno==EAGAIN) return NULL;
		_dprintf("recvfrom: Error %i",errno);
		return NULL;
	}
	pSrcBuffer=SrcBuffer;
	nSrcBuffer=r;

	Count=nSrcBuffer;
	return pSrcBuffer;
}


void cDataStreamSocketUDP::Del(int Count) {
	nSrcBuffer-=Count;
	pSrcBuffer+=Count;
}

void cDataStreamSocketUDP::Reset() {
	nSrcBuffer=0;
}

int cDataStreamSocketUDP::GetPollHandle() {
	if (sock>0 && nSrcBuffer==0) return sock;
	return 0;
}

//
// cStreamPlayerUDP
//

cStreamPlayerUDP::cStreamPlayerUDP(char *url) {
	port=atoi(url);
	_dprintf("Listening on UDP port %i\n",port);
}

cStreamPlayerUDP::~cStreamPlayerUDP() {
	// Kill thread before deepest nested destructor finishes
	// Not good style, but not to avoid.
	Detach();
	Stop();
}

cDataStreamSource* cStreamPlayerUDP::NewSource() {
	return new cDataStreamSocketUDP(port);
}

void cStreamPlayerUDP::DeleteSource(cDataStreamSource *src) {
	delete src;
}


char* cStreamPlayerUDP::GetStatus() {
	int bps=0;
	int buffered=0;
	if (Throughput) bps=Throughput->GetBytesPerSec();
	if (StreamBuffer) buffered=StreamBuffer->Available();
	if (Remuxer) buffered+=Remuxer->Available();

	snprintf(StatusString,sizeof StatusString,"Listening on UDP port %i (%0.1f Kb/s, buf %ik)",port,bps/1024.0,buffered/1024);
	return StatusString;
}

