xref: /haiku/src/add-ons/media/plugins/http_streamer/HTTPMediaIO.cpp (revision d3630cbaecc65a75b841479655699294b24c99a9)
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>
10fbabc74dSDario Casalinuovo #include <UrlProtocolRoster.h>
11fbabc74dSDario Casalinuovo 
12*d3630cbaSDario Casalinuovo 
13*d3630cbaSDario Casalinuovo // 10 seconds timeout
14*d3630cbaSDario Casalinuovo #define HTTP_TIMEOUT 10000000
15fbabc74dSDario Casalinuovo 
16fbabc74dSDario Casalinuovo 
171acb1f50SDario Casalinuovo class FileListener : public BUrlProtocolAsynchronousListener {
18fbabc74dSDario Casalinuovo public:
19fbabc74dSDario Casalinuovo 		FileListener(BAdapterIO* owner)
20fbabc74dSDario Casalinuovo 			:
21fbabc74dSDario Casalinuovo 			BUrlProtocolAsynchronousListener(true),
22fbabc74dSDario Casalinuovo 			fRequest(NULL),
23f1c771f8SDario Casalinuovo 			fAdapterIO(owner),
24*d3630cbaSDario Casalinuovo 			fInitSem(-1)
25fbabc74dSDario Casalinuovo 		{
26fbabc74dSDario Casalinuovo 			fInputAdapter = fAdapterIO->BuildInputAdapter();
27*d3630cbaSDario Casalinuovo 			fInitSem = create_sem(0, "http_streamer init sem");
28fbabc74dSDario Casalinuovo 		}
29fbabc74dSDario Casalinuovo 
30fbabc74dSDario Casalinuovo 		virtual ~FileListener() {};
31fbabc74dSDario Casalinuovo 
32fbabc74dSDario Casalinuovo 		bool ConnectionSuccessful() const
33fbabc74dSDario Casalinuovo 		{
34fbabc74dSDario Casalinuovo 			return fRequest != NULL;
35fbabc74dSDario Casalinuovo 		}
36fbabc74dSDario Casalinuovo 
37fbabc74dSDario Casalinuovo 		void ConnectionOpened(BUrlRequest* request)
38fbabc74dSDario Casalinuovo 		{
39fbabc74dSDario Casalinuovo 			if (fRequest != NULL)
40fbabc74dSDario Casalinuovo 				fRequest->Stop();
41fbabc74dSDario Casalinuovo 
42fbabc74dSDario Casalinuovo 			fRequest = request;
43fbabc74dSDario Casalinuovo 		}
44fbabc74dSDario Casalinuovo 
45fbabc74dSDario Casalinuovo 		void DataReceived(BUrlRequest* request, const char* data,
46fbabc74dSDario Casalinuovo 			off_t position, ssize_t size)
47fbabc74dSDario Casalinuovo 		{
48*d3630cbaSDario Casalinuovo 			if (fInitSem != -1) {
49*d3630cbaSDario Casalinuovo 				release_sem(fInitSem);
50*d3630cbaSDario Casalinuovo 				delete_sem(fInitSem);
51*d3630cbaSDario Casalinuovo 				fInitSem = -1;
52*d3630cbaSDario Casalinuovo 			}
53*d3630cbaSDario Casalinuovo 
54fbabc74dSDario Casalinuovo 			if (request != fRequest)
55fbabc74dSDario Casalinuovo 				delete request;
56fbabc74dSDario Casalinuovo 
57fbabc74dSDario Casalinuovo 			fInputAdapter->Write(data, size);
58fbabc74dSDario Casalinuovo 		}
59fbabc74dSDario Casalinuovo 
60fbabc74dSDario Casalinuovo 		void RequestCompleted(BUrlRequest* request, bool success)
61fbabc74dSDario Casalinuovo 		{
62fbabc74dSDario Casalinuovo 			if (request != fRequest)
63fbabc74dSDario Casalinuovo 				return;
64fbabc74dSDario Casalinuovo 
65fbabc74dSDario Casalinuovo 			fRequest = NULL;
66fbabc74dSDario Casalinuovo 			delete request;
67fbabc74dSDario Casalinuovo 		}
68fbabc74dSDario Casalinuovo 
69*d3630cbaSDario Casalinuovo 		status_t LockOnInit(bigtime_t timeout)
70f1c771f8SDario Casalinuovo 		{
71*d3630cbaSDario Casalinuovo 			return acquire_sem_etc(fInitSem, 1, B_RELATIVE_TIMEOUT, timeout);
72f1c771f8SDario Casalinuovo 		}
73f1c771f8SDario Casalinuovo 
74fbabc74dSDario Casalinuovo private:
75fbabc74dSDario Casalinuovo 		BUrlRequest*	fRequest;
76fbabc74dSDario Casalinuovo 		BAdapterIO*		fAdapterIO;
77fbabc74dSDario Casalinuovo 		BInputAdapter*	fInputAdapter;
78*d3630cbaSDario Casalinuovo 		sem_id			fInitSem;
79fbabc74dSDario Casalinuovo };
80fbabc74dSDario Casalinuovo 
81617b62c9SDario Casalinuovo 
820ba82236SDario Casalinuovo HTTPMediaIO::HTTPMediaIO(BUrl url)
83617b62c9SDario Casalinuovo 	:
84*d3630cbaSDario Casalinuovo 	BAdapterIO(B_MEDIA_STREAMING | B_MEDIA_SEEK_BACKWARD, HTTP_TIMEOUT),
8593a1f9d2SDario Casalinuovo 	fContext(NULL),
8693a1f9d2SDario Casalinuovo 	fReq(NULL),
8793a1f9d2SDario Casalinuovo 	fListener(NULL),
88*d3630cbaSDario Casalinuovo 	fUrl(url),
89*d3630cbaSDario Casalinuovo 	fTotalSize(0)
90617b62c9SDario Casalinuovo {
91617b62c9SDario Casalinuovo }
92617b62c9SDario Casalinuovo 
93617b62c9SDario Casalinuovo 
94617b62c9SDario Casalinuovo HTTPMediaIO::~HTTPMediaIO()
95617b62c9SDario Casalinuovo {
96617b62c9SDario Casalinuovo }
97617b62c9SDario Casalinuovo 
98617b62c9SDario Casalinuovo 
99617b62c9SDario Casalinuovo ssize_t
100617b62c9SDario Casalinuovo HTTPMediaIO::WriteAt(off_t position, const void* buffer, size_t size)
101617b62c9SDario Casalinuovo {
102617b62c9SDario Casalinuovo 	return B_NOT_SUPPORTED;
103617b62c9SDario Casalinuovo }
104f1c771f8SDario Casalinuovo 
105f1c771f8SDario Casalinuovo 
106f1c771f8SDario Casalinuovo status_t
107f1c771f8SDario Casalinuovo HTTPMediaIO::SetSize(off_t size)
108f1c771f8SDario Casalinuovo {
109f1c771f8SDario Casalinuovo 	return B_NOT_SUPPORTED;
110f1c771f8SDario Casalinuovo }
111f1c771f8SDario Casalinuovo 
112f1c771f8SDario Casalinuovo 
113f1c771f8SDario Casalinuovo status_t
114f1c771f8SDario Casalinuovo HTTPMediaIO::GetSize(off_t* size) const
115f1c771f8SDario Casalinuovo {
116*d3630cbaSDario Casalinuovo 	if (fReq == NULL)
117*d3630cbaSDario Casalinuovo 		return B_ERROR;
118*d3630cbaSDario Casalinuovo 
119*d3630cbaSDario Casalinuovo 	*size = fTotalSize;
120f1c771f8SDario Casalinuovo 	return B_OK;
121f1c771f8SDario Casalinuovo }
12293a1f9d2SDario Casalinuovo 
12393a1f9d2SDario Casalinuovo 
12493a1f9d2SDario Casalinuovo status_t
12593a1f9d2SDario Casalinuovo HTTPMediaIO::Open()
12693a1f9d2SDario Casalinuovo {
12793a1f9d2SDario Casalinuovo 	fContext = new BUrlContext();
12893a1f9d2SDario Casalinuovo 	fContext->AcquireReference();
12993a1f9d2SDario Casalinuovo 
13093a1f9d2SDario Casalinuovo 	fListener = new FileListener(this);
13193a1f9d2SDario Casalinuovo 
13293a1f9d2SDario Casalinuovo 	fReq = BUrlProtocolRoster::MakeRequest(fUrl,
13393a1f9d2SDario Casalinuovo 		fListener, fContext);
13493a1f9d2SDario Casalinuovo 
13593a1f9d2SDario Casalinuovo 	if (fReq == NULL)
13693a1f9d2SDario Casalinuovo 		return B_ERROR;
13793a1f9d2SDario Casalinuovo 
13893a1f9d2SDario Casalinuovo 	if (fReq->Run() < 0)
13993a1f9d2SDario Casalinuovo 		return B_ERROR;
14093a1f9d2SDario Casalinuovo 
141*d3630cbaSDario Casalinuovo 	status_t ret = fListener->LockOnInit(HTTP_TIMEOUT);
142*d3630cbaSDario Casalinuovo 	if (ret != B_OK)
143*d3630cbaSDario Casalinuovo 		return ret;
144*d3630cbaSDario Casalinuovo 
145*d3630cbaSDario Casalinuovo 	fTotalSize = fReq->Result().Length();
146*d3630cbaSDario Casalinuovo 
14793a1f9d2SDario Casalinuovo 	return BAdapterIO::Open();
14893a1f9d2SDario Casalinuovo }
14993a1f9d2SDario Casalinuovo 
15093a1f9d2SDario Casalinuovo 
15193a1f9d2SDario Casalinuovo void
15293a1f9d2SDario Casalinuovo HTTPMediaIO::Close()
15393a1f9d2SDario Casalinuovo {
15493a1f9d2SDario Casalinuovo 	delete fReq;
15593a1f9d2SDario Casalinuovo 	delete fListener;
15693a1f9d2SDario Casalinuovo 
15793a1f9d2SDario Casalinuovo 	fContext->ReleaseReference();
15893a1f9d2SDario Casalinuovo 	delete fContext;
15993a1f9d2SDario Casalinuovo 
16093a1f9d2SDario Casalinuovo 	BAdapterIO::Close();
16193a1f9d2SDario Casalinuovo }
16293a1f9d2SDario Casalinuovo 
16393a1f9d2SDario Casalinuovo 
16493a1f9d2SDario Casalinuovo status_t
16593a1f9d2SDario Casalinuovo HTTPMediaIO::SeekRequested(off_t position)
16693a1f9d2SDario Casalinuovo {
16793a1f9d2SDario Casalinuovo 	return BAdapterIO::SeekRequested(position);
16893a1f9d2SDario Casalinuovo }
169