xref: /haiku/src/kits/media/DataExchange.cpp (revision f75a7bf508f3156d63a14f8fd77c5e0ca4d08c42)
1 /*
2  * Copyright 2002-2007, Marcus Overhagen. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <OS.h>
7 #include <Messenger.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include "debug.h"
11 #include "PortPool.h"
12 #include "MediaMisc.h"
13 #include "DataExchange.h"
14 #include "ServerInterface.h"
15 
16 #define TIMEOUT 15000000 // 15 seconds timeout!
17 
18 namespace BPrivate {
19 namespace media {
20 
21 team_id team;
22 
23 namespace dataexchange {
24 
25 BMessenger *MediaServerMessenger;
26 static port_id MediaServerPort;
27 static port_id MediaAddonServerPort;
28 
29 void find_media_server_port();
30 void find_media_addon_server_port();
31 
32 static BMessenger * GetMediaServerMessenger() {
33 	static BMessenger * messenger = new BMessenger(B_MEDIA_SERVER_SIGNATURE);
34 	return MediaServerMessenger = messenger;
35 }
36 
37 class initit
38 {
39 public:
40 	initit()
41 	{
42 		MediaServerMessenger = 0;
43 		find_media_server_port();
44 		find_media_addon_server_port();
45 
46 		thread_info info;
47 		get_thread_info(find_thread(NULL), &info);
48 		team = info.team;
49 	}
50 	~initit()
51 	{
52 		delete MediaServerMessenger;
53 	}
54 };
55 initit _initit;
56 
57 
58 void find_media_server_port()
59 {
60 	MediaServerPort = find_port(MEDIA_SERVER_PORT_NAME);
61 	if (MediaServerPort < 0) {
62 		ERROR("couldn't find MediaServerPort\n");
63 		MediaServerPort = BAD_MEDIA_SERVER_PORT; // make this a unique number
64 	}
65 }
66 
67 void find_media_addon_server_port()
68 {
69 	MediaAddonServerPort = find_port(MEDIA_ADDON_SERVER_PORT_NAME);
70 	if (MediaAddonServerPort < 0) {
71 		ERROR("couldn't find MediaAddonServerPort\n");
72 		MediaAddonServerPort = BAD_MEDIA_ADDON_SERVER_PORT; // make this a unique number
73 	}
74 }
75 
76 
77 status_t
78 request_data::SendReply(status_t result, reply_data *reply, int replysize) const
79 {
80 	reply->result = result;
81 	// we cheat and use the (command_data *) version of SendToPort
82 	return SendToPort(reply_port, 0, reinterpret_cast<command_data *>(reply), replysize);
83 }
84 
85 
86 // BMessage based data exchange with the media_server
87 status_t SendToServer(BMessage *msg)
88 {
89 	status_t rv;
90 	rv = GetMediaServerMessenger()->SendMessage(msg, static_cast<BHandler *>(NULL), TIMEOUT);
91 	if (rv != B_OK) {
92 		ERROR("SendToServer: SendMessage failed, error 0x%08lx (%s)\n", rv, strerror(rv));
93 		DEBUG_ONLY(msg->PrintToStream());
94 	}
95 	return rv;
96 }
97 
98 
99 status_t
100 QueryServer(BMessage &request, BMessage &reply)
101 {
102 	status_t status = GetMediaServerMessenger()->SendMessage(&request, &reply, TIMEOUT, TIMEOUT);
103 	if (status != B_OK) {
104 		ERROR("QueryServer: SendMessage failed, error 0x%08lx (%s)\n", status, strerror(status));
105 		DEBUG_ONLY(request.PrintToStream());
106 		DEBUG_ONLY(reply.PrintToStream());
107 	}
108 	return status;
109 }
110 
111 
112 // Raw data based data exchange with the media_server
113 status_t SendToServer(int32 msgcode, command_data *msg, int size)
114 {
115 	return SendToPort(MediaServerPort, msgcode, msg, size);
116 }
117 
118 status_t QueryServer(int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize)
119 {
120 	return QueryPort(MediaServerPort, msgcode, request, requestsize, reply, replysize);
121 }
122 
123 
124 // Raw data based data exchange with the media_addon_server
125 status_t SendToAddonServer(int32 msgcode, command_data *msg, int size)
126 {
127 	return SendToPort(MediaAddonServerPort, msgcode, msg, size);
128 }
129 
130 
131 status_t QueryAddonServer(int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize)
132 {
133 	return QueryPort(MediaAddonServerPort, msgcode, request, requestsize, reply, replysize);
134 }
135 
136 
137 // Raw data based data exchange with the media_server
138 status_t SendToPort(port_id sendport, int32 msgcode, command_data *msg, int size)
139 {
140 	status_t rv;
141 
142 	rv = write_port_etc(sendport, msgcode, msg, size, B_RELATIVE_TIMEOUT, TIMEOUT);
143 	if (rv != B_OK) {
144 		ERROR("SendToPort: write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, sendport, rv, strerror(rv));
145 		if (rv == B_BAD_PORT_ID && sendport == MediaServerPort) {
146 			find_media_server_port();
147 			sendport = MediaServerPort;
148 		} else if (rv == B_BAD_PORT_ID && sendport == MediaAddonServerPort) {
149 			find_media_addon_server_port();
150 			sendport = MediaAddonServerPort;
151 		} else {
152 			return rv;
153 		}
154 
155 		rv = write_port_etc(sendport, msgcode, msg, size, B_RELATIVE_TIMEOUT, TIMEOUT);
156 		if (rv != B_OK) {
157 			ERROR("SendToPort: retrying write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, sendport, rv, strerror(rv));
158 			return rv;
159 		}
160 	}
161 	return B_OK;
162 }
163 
164 
165 status_t QueryPort(port_id requestport, int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize)
166 {
167 	status_t rv;
168 	int32 code;
169 
170 	request->reply_port = _PortPool->GetPort();
171 
172 	rv = write_port_etc(requestport, msgcode, request, requestsize, B_RELATIVE_TIMEOUT, TIMEOUT);
173 
174 	if (rv != B_OK) {
175 		ERROR("QueryPort: write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, requestport, rv, strerror(rv));
176 		if (rv == B_BAD_PORT_ID && requestport == MediaServerPort) {
177 			find_media_server_port();
178 			requestport = MediaServerPort;
179 		} else if (rv == B_BAD_PORT_ID && requestport == MediaAddonServerPort) {
180 			find_media_addon_server_port();
181 			requestport = MediaAddonServerPort;
182 		} else {
183 			_PortPool->PutPort(request->reply_port);
184 			return rv;
185 		}
186 
187 		rv = write_port_etc(requestport, msgcode, request, requestsize, B_RELATIVE_TIMEOUT, TIMEOUT);
188 		if (rv != B_OK) {
189 			ERROR("QueryPort: retrying write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, requestport, rv, strerror(rv));
190 			_PortPool->PutPort(request->reply_port);
191 			return rv;
192 		}
193 	}
194 
195 	rv = read_port_etc(request->reply_port, &code, reply, replysize, B_RELATIVE_TIMEOUT, TIMEOUT);
196 	_PortPool->PutPort(request->reply_port);
197 
198 	if (rv < B_OK) {
199 		ERROR("QueryPort: read_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, request->reply_port, rv, strerror(rv));
200 	}
201 
202 	return (rv < B_OK) ? rv : reply->result;
203 }
204 
205 }; // dataexchange
206 }; // media
207 }; // BPrivate
208 
209