xref: /haiku/src/add-ons/media/plugins/http_streamer/HTTPMediaIO.cpp (revision 78b14420513565ee1b68e0ac5db550fd855b287c)
1617b62c9SDario Casalinuovo /*
2617b62c9SDario Casalinuovo  * Copyright 2016, Dario Casalinuovo
3617b62c9SDario Casalinuovo  * Distributed under the terms of the MIT License.
4617b62c9SDario Casalinuovo  */
5617b62c9SDario Casalinuovo 
6617b62c9SDario Casalinuovo 
7617b62c9SDario Casalinuovo #include "HTTPMediaIO.h"
8617b62c9SDario Casalinuovo 
9fbabc74dSDario Casalinuovo #include <Handler.h>
10b4515980SDario Casalinuovo #include <HttpRequest.h>
11fbabc74dSDario Casalinuovo #include <UrlProtocolRoster.h>
12fbabc74dSDario Casalinuovo 
13f8fdf848SAugustin Cavalier #include "MediaDebug.h"
145232a911SBarrett17 
15d3630cbaSDario Casalinuovo 
16d3630cbaSDario Casalinuovo // 10 seconds timeout
17d3630cbaSDario Casalinuovo #define HTTP_TIMEOUT 10000000
18fbabc74dSDario Casalinuovo 
19ac4b8373SNiels Sascha Reedijk using namespace BPrivate::Network;
20ac4b8373SNiels Sascha Reedijk 
21fbabc74dSDario Casalinuovo 
22*78b14420SLeorize class FileListener : public BUrlProtocolListener, public BDataIO {
23fbabc74dSDario Casalinuovo public:
FileListener(HTTPMediaIO * owner)24be2c0725SDario Casalinuovo 		FileListener(HTTPMediaIO* owner)
25fbabc74dSDario Casalinuovo 			:
26ff5c2dc2SAdrien Destugues 			BUrlProtocolListener(),
27fbabc74dSDario Casalinuovo 			fRequest(NULL),
28f1c771f8SDario Casalinuovo 			fAdapterIO(owner),
29b4515980SDario Casalinuovo 			fInitSem(-1),
30b4515980SDario Casalinuovo 			fRunning(false)
31fbabc74dSDario Casalinuovo 		{
32fbabc74dSDario Casalinuovo 			fInputAdapter = fAdapterIO->BuildInputAdapter();
33d3630cbaSDario Casalinuovo 			fInitSem = create_sem(0, "http_streamer init sem");
34fbabc74dSDario Casalinuovo 		}
35fbabc74dSDario Casalinuovo 
~FileListener()363ff901acSDario Casalinuovo 		virtual ~FileListener()
373ff901acSDario Casalinuovo 		{
383ff901acSDario Casalinuovo 			_ReleaseInit();
393ff901acSDario Casalinuovo 		}
40fbabc74dSDario Casalinuovo 
ConnectionSuccessful() const41fbabc74dSDario Casalinuovo 		bool ConnectionSuccessful() const
42fbabc74dSDario Casalinuovo 		{
43fbabc74dSDario Casalinuovo 			return fRequest != NULL;
44fbabc74dSDario Casalinuovo 		}
45fbabc74dSDario Casalinuovo 
ConnectionOpened(BUrlRequest * request)46fbabc74dSDario Casalinuovo 		void ConnectionOpened(BUrlRequest* request)
47fbabc74dSDario Casalinuovo 		{
48fbabc74dSDario Casalinuovo 			fRequest = request;
49b4515980SDario Casalinuovo 			fRunning = true;
50fbabc74dSDario Casalinuovo 		}
51fbabc74dSDario Casalinuovo 
HeadersReceived(BUrlRequest * request)523e27f8d5SLeorize 		void HeadersReceived(BUrlRequest* request)
53a5b5f896SAdrien Destugues 		{
543ff901acSDario Casalinuovo 			if (request != fRequest) {
55fbabc74dSDario Casalinuovo 				delete request;
563ff901acSDario Casalinuovo 				return;
573ff901acSDario Casalinuovo 			}
58fbabc74dSDario Casalinuovo 
59*78b14420SLeorize 			fAdapterIO->UpdateSize();
60fbabc74dSDario Casalinuovo 		}
61fbabc74dSDario Casalinuovo 
RequestCompleted(BUrlRequest * request,bool success)62fbabc74dSDario Casalinuovo 		void RequestCompleted(BUrlRequest* request, bool success)
63fbabc74dSDario Casalinuovo 		{
64eed8ce57SDario Casalinuovo 			_ReleaseInit();
65eed8ce57SDario Casalinuovo 
66fbabc74dSDario Casalinuovo 			if (request != fRequest)
67fbabc74dSDario Casalinuovo 				return;
68fbabc74dSDario Casalinuovo 
69fbabc74dSDario Casalinuovo 			fRequest = NULL;
70fbabc74dSDario Casalinuovo 		}
71fbabc74dSDario Casalinuovo 
Write(const void * data,size_t size)72*78b14420SLeorize 		ssize_t Write(const void* data, size_t size)
73*78b14420SLeorize 		{
74*78b14420SLeorize 			_ReleaseInit();
75*78b14420SLeorize 
76*78b14420SLeorize 			return fInputAdapter->Write(data, size);
77*78b14420SLeorize 		}
78*78b14420SLeorize 
LockOnInit(bigtime_t timeout)79d3630cbaSDario Casalinuovo 		status_t LockOnInit(bigtime_t timeout)
80f1c771f8SDario Casalinuovo 		{
81d3630cbaSDario Casalinuovo 			return acquire_sem_etc(fInitSem, 1, B_RELATIVE_TIMEOUT, timeout);
82f1c771f8SDario Casalinuovo 		}
83f1c771f8SDario Casalinuovo 
IsRunning()84b4515980SDario Casalinuovo 		bool IsRunning()
85b4515980SDario Casalinuovo 		{
86b4515980SDario Casalinuovo 			return fRunning;
87b4515980SDario Casalinuovo 		}
88b4515980SDario Casalinuovo 
89fbabc74dSDario Casalinuovo private:
_ReleaseInit()90eed8ce57SDario Casalinuovo 		void _ReleaseInit()
91eed8ce57SDario Casalinuovo 		{
92eed8ce57SDario Casalinuovo 			if (fInitSem != -1) {
93eed8ce57SDario Casalinuovo 				release_sem(fInitSem);
94eed8ce57SDario Casalinuovo 				delete_sem(fInitSem);
95eed8ce57SDario Casalinuovo 				fInitSem = -1;
96eed8ce57SDario Casalinuovo 			}
97eed8ce57SDario Casalinuovo 		}
98eed8ce57SDario Casalinuovo 
99fbabc74dSDario Casalinuovo 		BUrlRequest*	fRequest;
100be2c0725SDario Casalinuovo 		HTTPMediaIO*	fAdapterIO;
101fbabc74dSDario Casalinuovo 		BInputAdapter*	fInputAdapter;
102d3630cbaSDario Casalinuovo 		sem_id			fInitSem;
103b4515980SDario Casalinuovo 		bool			fRunning;
104fbabc74dSDario Casalinuovo };
105fbabc74dSDario Casalinuovo 
106617b62c9SDario Casalinuovo 
HTTPMediaIO(BUrl url)1070ba82236SDario Casalinuovo HTTPMediaIO::HTTPMediaIO(BUrl url)
108617b62c9SDario Casalinuovo 	:
1095c05bb48SDario Casalinuovo 	BAdapterIO(B_MEDIA_STREAMING | B_MEDIA_SEEKABLE, HTTP_TIMEOUT),
11093a1f9d2SDario Casalinuovo 	fReq(NULL),
11193a1f9d2SDario Casalinuovo 	fListener(NULL),
1123ff901acSDario Casalinuovo 	fReqThread(-1),
113d3630cbaSDario Casalinuovo 	fUrl(url),
114b4e751b8SDario Casalinuovo 	fIsMutable(false)
115617b62c9SDario Casalinuovo {
1163ff901acSDario Casalinuovo 	CALLED();
117617b62c9SDario Casalinuovo }
118617b62c9SDario Casalinuovo 
119617b62c9SDario Casalinuovo 
~HTTPMediaIO()120617b62c9SDario Casalinuovo HTTPMediaIO::~HTTPMediaIO()
121617b62c9SDario Casalinuovo {
1223ff901acSDario Casalinuovo 	CALLED();
1233ff901acSDario Casalinuovo 
124af7d48feSAdrien Destugues 	if (fReq != NULL) {
1253ff901acSDario Casalinuovo 		fReq->Stop();
1263ff901acSDario Casalinuovo 		status_t status;
1273ff901acSDario Casalinuovo 		wait_for_thread(fReqThread, &status);
1283ff901acSDario Casalinuovo 
12998e33bf6SAdrien Destugues 		delete fReq;
130617b62c9SDario Casalinuovo 	}
131b2fa4e17SAdrien Destugues }
132617b62c9SDario Casalinuovo 
133617b62c9SDario Casalinuovo 
134b4e751b8SDario Casalinuovo void
GetFlags(int32 * flags) const135b4e751b8SDario Casalinuovo HTTPMediaIO::GetFlags(int32* flags) const
136b4e751b8SDario Casalinuovo {
137b4e751b8SDario Casalinuovo 	*flags = B_MEDIA_STREAMING | B_MEDIA_SEEK_BACKWARD;
138b4e751b8SDario Casalinuovo 	if (fIsMutable)
139b4e751b8SDario Casalinuovo 		*flags = *flags | B_MEDIA_MUTABLE_SIZE;
140b4e751b8SDario Casalinuovo }
141b4e751b8SDario Casalinuovo 
142b4e751b8SDario Casalinuovo 
143617b62c9SDario Casalinuovo ssize_t
WriteAt(off_t position,const void * buffer,size_t size)144617b62c9SDario Casalinuovo HTTPMediaIO::WriteAt(off_t position, const void* buffer, size_t size)
145617b62c9SDario Casalinuovo {
146617b62c9SDario Casalinuovo 	return B_NOT_SUPPORTED;
147617b62c9SDario Casalinuovo }
148f1c771f8SDario Casalinuovo 
149f1c771f8SDario Casalinuovo 
150f1c771f8SDario Casalinuovo status_t
SetSize(off_t size)151f1c771f8SDario Casalinuovo HTTPMediaIO::SetSize(off_t size)
152f1c771f8SDario Casalinuovo {
153f1c771f8SDario Casalinuovo 	return B_NOT_SUPPORTED;
154f1c771f8SDario Casalinuovo }
155f1c771f8SDario Casalinuovo 
156f1c771f8SDario Casalinuovo 
157f1c771f8SDario Casalinuovo status_t
Open()15893a1f9d2SDario Casalinuovo HTTPMediaIO::Open()
15993a1f9d2SDario Casalinuovo {
1603ff901acSDario Casalinuovo 	CALLED();
16193a1f9d2SDario Casalinuovo 
16293a1f9d2SDario Casalinuovo 	fListener = new FileListener(this);
16393a1f9d2SDario Casalinuovo 
164*78b14420SLeorize 	fReq = BUrlProtocolRoster::MakeRequest(fUrl, fListener, fListener);
16593a1f9d2SDario Casalinuovo 
16693a1f9d2SDario Casalinuovo 	if (fReq == NULL)
16793a1f9d2SDario Casalinuovo 		return B_ERROR;
16893a1f9d2SDario Casalinuovo 
169*78b14420SLeorize 	BHttpRequest* httpReq = dynamic_cast<BHttpRequest*>(fReq);
170*78b14420SLeorize 	if (httpReq != NULL)
171*78b14420SLeorize 		httpReq->SetStopOnError(true);
172*78b14420SLeorize 
173be2c0725SDario Casalinuovo 	fReqThread = fReq->Run();
174be2c0725SDario Casalinuovo 	if (fReqThread < 0)
17593a1f9d2SDario Casalinuovo 		return B_ERROR;
17693a1f9d2SDario Casalinuovo 
177d3630cbaSDario Casalinuovo 	status_t ret = fListener->LockOnInit(HTTP_TIMEOUT);
178d3630cbaSDario Casalinuovo 	if (ret != B_OK)
179d3630cbaSDario Casalinuovo 		return ret;
180d3630cbaSDario Casalinuovo 
18193a1f9d2SDario Casalinuovo 	return BAdapterIO::Open();
18293a1f9d2SDario Casalinuovo }
18393a1f9d2SDario Casalinuovo 
18493a1f9d2SDario Casalinuovo 
185eed8ce57SDario Casalinuovo bool
IsRunning() const186eed8ce57SDario Casalinuovo HTTPMediaIO::IsRunning() const
187eed8ce57SDario Casalinuovo {
188e42135e5SDario Casalinuovo 	if (fListener != NULL)
189b4515980SDario Casalinuovo 		return fListener->IsRunning();
190e42135e5SDario Casalinuovo 	else if (fReq != NULL)
1914e793dddSDario Casalinuovo 		return fReq->IsRunning();
192e42135e5SDario Casalinuovo 
193e42135e5SDario Casalinuovo 	return false;
194eed8ce57SDario Casalinuovo }
195eed8ce57SDario Casalinuovo 
196eed8ce57SDario Casalinuovo 
19793a1f9d2SDario Casalinuovo status_t
SeekRequested(off_t position)19893a1f9d2SDario Casalinuovo HTTPMediaIO::SeekRequested(off_t position)
19993a1f9d2SDario Casalinuovo {
20093a1f9d2SDario Casalinuovo 	return BAdapterIO::SeekRequested(position);
20193a1f9d2SDario Casalinuovo }
202be2c0725SDario Casalinuovo 
203be2c0725SDario Casalinuovo 
204be2c0725SDario Casalinuovo void
UpdateSize()205be2c0725SDario Casalinuovo HTTPMediaIO::UpdateSize()
206be2c0725SDario Casalinuovo {
207be2c0725SDario Casalinuovo 	// At this point we decide if our size is fixed or mutable,
208be2c0725SDario Casalinuovo 	// this will change the behavior of our parent.
209be2c0725SDario Casalinuovo 	off_t size = fReq->Result().Length();
210be2c0725SDario Casalinuovo 	if (size > 0)
211be2c0725SDario Casalinuovo 		BAdapterIO::SetSize(size);
212be2c0725SDario Casalinuovo 	else
213be2c0725SDario Casalinuovo 		fIsMutable = true;
214be2c0725SDario Casalinuovo }
215