xref: /haiku/src/add-ons/media/plugins/http_streamer/HTTPMediaIO.cpp (revision 5c05bb48f4191d8f4179e1a8d0deaf0d51bbaffc)
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 
12d3630cbaSDario Casalinuovo 
13d3630cbaSDario Casalinuovo // 10 seconds timeout
14d3630cbaSDario 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),
24d3630cbaSDario Casalinuovo 			fInitSem(-1)
25fbabc74dSDario Casalinuovo 		{
26fbabc74dSDario Casalinuovo 			fInputAdapter = fAdapterIO->BuildInputAdapter();
27d3630cbaSDario 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 		{
48d3630cbaSDario Casalinuovo 			if (fInitSem != -1) {
49d3630cbaSDario Casalinuovo 				release_sem(fInitSem);
50d3630cbaSDario Casalinuovo 				delete_sem(fInitSem);
51d3630cbaSDario Casalinuovo 				fInitSem = -1;
52d3630cbaSDario Casalinuovo 			}
53d3630cbaSDario 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 
69d3630cbaSDario Casalinuovo 		status_t LockOnInit(bigtime_t timeout)
70f1c771f8SDario Casalinuovo 		{
71d3630cbaSDario 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;
78d3630cbaSDario Casalinuovo 		sem_id			fInitSem;
79fbabc74dSDario Casalinuovo };
80fbabc74dSDario Casalinuovo 
81617b62c9SDario Casalinuovo 
820ba82236SDario Casalinuovo HTTPMediaIO::HTTPMediaIO(BUrl url)
83617b62c9SDario Casalinuovo 	:
84*5c05bb48SDario Casalinuovo 	BAdapterIO(B_MEDIA_STREAMING | B_MEDIA_SEEKABLE, HTTP_TIMEOUT),
8593a1f9d2SDario Casalinuovo 	fContext(NULL),
8693a1f9d2SDario Casalinuovo 	fReq(NULL),
8793a1f9d2SDario Casalinuovo 	fListener(NULL),
88d3630cbaSDario Casalinuovo 	fUrl(url),
89b4e751b8SDario Casalinuovo 	fIsMutable(false)
90617b62c9SDario Casalinuovo {
91617b62c9SDario Casalinuovo }
92617b62c9SDario Casalinuovo 
93617b62c9SDario Casalinuovo 
94617b62c9SDario Casalinuovo HTTPMediaIO::~HTTPMediaIO()
95617b62c9SDario Casalinuovo {
96617b62c9SDario Casalinuovo }
97617b62c9SDario Casalinuovo 
98617b62c9SDario Casalinuovo 
99b4e751b8SDario Casalinuovo void
100b4e751b8SDario Casalinuovo HTTPMediaIO::GetFlags(int32* flags) const
101b4e751b8SDario Casalinuovo {
102b4e751b8SDario Casalinuovo 	*flags = B_MEDIA_STREAMING | B_MEDIA_SEEK_BACKWARD;
103b4e751b8SDario Casalinuovo 	if (fIsMutable)
104b4e751b8SDario Casalinuovo 		*flags = *flags | B_MEDIA_MUTABLE_SIZE;
105b4e751b8SDario Casalinuovo }
106b4e751b8SDario Casalinuovo 
107b4e751b8SDario Casalinuovo 
108617b62c9SDario Casalinuovo ssize_t
109617b62c9SDario Casalinuovo HTTPMediaIO::WriteAt(off_t position, const void* buffer, size_t size)
110617b62c9SDario Casalinuovo {
111617b62c9SDario Casalinuovo 	return B_NOT_SUPPORTED;
112617b62c9SDario Casalinuovo }
113f1c771f8SDario Casalinuovo 
114f1c771f8SDario Casalinuovo 
115f1c771f8SDario Casalinuovo status_t
116f1c771f8SDario Casalinuovo HTTPMediaIO::SetSize(off_t size)
117f1c771f8SDario Casalinuovo {
118f1c771f8SDario Casalinuovo 	return B_NOT_SUPPORTED;
119f1c771f8SDario Casalinuovo }
120f1c771f8SDario Casalinuovo 
121f1c771f8SDario Casalinuovo 
122f1c771f8SDario Casalinuovo status_t
12393a1f9d2SDario Casalinuovo HTTPMediaIO::Open()
12493a1f9d2SDario Casalinuovo {
12593a1f9d2SDario Casalinuovo 	fContext = new BUrlContext();
12693a1f9d2SDario Casalinuovo 	fContext->AcquireReference();
12793a1f9d2SDario Casalinuovo 
12893a1f9d2SDario Casalinuovo 	fListener = new FileListener(this);
12993a1f9d2SDario Casalinuovo 
13093a1f9d2SDario Casalinuovo 	fReq = BUrlProtocolRoster::MakeRequest(fUrl,
13193a1f9d2SDario Casalinuovo 		fListener, fContext);
13293a1f9d2SDario Casalinuovo 
13393a1f9d2SDario Casalinuovo 	if (fReq == NULL)
13493a1f9d2SDario Casalinuovo 		return B_ERROR;
13593a1f9d2SDario Casalinuovo 
13693a1f9d2SDario Casalinuovo 	if (fReq->Run() < 0)
13793a1f9d2SDario Casalinuovo 		return B_ERROR;
13893a1f9d2SDario Casalinuovo 
139d3630cbaSDario Casalinuovo 	status_t ret = fListener->LockOnInit(HTTP_TIMEOUT);
140d3630cbaSDario Casalinuovo 	if (ret != B_OK)
141d3630cbaSDario Casalinuovo 		return ret;
142d3630cbaSDario Casalinuovo 
143b4e751b8SDario Casalinuovo 	off_t totalSize = fReq->Result().Length();
144b4e751b8SDario Casalinuovo 
145b4e751b8SDario Casalinuovo 	// At this point we decide if our size is fixed or mutable,
146b4e751b8SDario Casalinuovo 	// this will change the behavior of our parent.
147b4e751b8SDario Casalinuovo 	if (totalSize > 0)
148b4e751b8SDario Casalinuovo 		BAdapterIO::SetSize(totalSize);
149b4e751b8SDario Casalinuovo 	else
150b4e751b8SDario Casalinuovo 		fIsMutable = true;
151d3630cbaSDario Casalinuovo 
15293a1f9d2SDario Casalinuovo 	return BAdapterIO::Open();
15393a1f9d2SDario Casalinuovo }
15493a1f9d2SDario Casalinuovo 
15593a1f9d2SDario Casalinuovo 
15693a1f9d2SDario Casalinuovo void
15793a1f9d2SDario Casalinuovo HTTPMediaIO::Close()
15893a1f9d2SDario Casalinuovo {
15993a1f9d2SDario Casalinuovo 	delete fReq;
16093a1f9d2SDario Casalinuovo 	delete fListener;
16193a1f9d2SDario Casalinuovo 
16293a1f9d2SDario Casalinuovo 	fContext->ReleaseReference();
16393a1f9d2SDario Casalinuovo 	delete fContext;
16493a1f9d2SDario Casalinuovo 
16593a1f9d2SDario Casalinuovo 	BAdapterIO::Close();
16693a1f9d2SDario Casalinuovo }
16793a1f9d2SDario Casalinuovo 
16893a1f9d2SDario Casalinuovo 
16993a1f9d2SDario Casalinuovo status_t
17093a1f9d2SDario Casalinuovo HTTPMediaIO::SeekRequested(off_t position)
17193a1f9d2SDario Casalinuovo {
17293a1f9d2SDario Casalinuovo 	return BAdapterIO::SeekRequested(position);
17393a1f9d2SDario Casalinuovo }
174