xref: /haiku/src/kits/media/DataExchange.cpp (revision efafab643ce980e3f3c916795ed302599f6b4f66)
1 /*
2  * Copyright 2002-2007, Marcus Overhagen. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <DataExchange.h>
8 
9 #include <string.h>
10 #include <unistd.h>
11 
12 #include <Messenger.h>
13 #include <OS.h>
14 
15 #include <MediaDebug.h>
16 #include <MediaMisc.h>
17 
18 
19 #define TIMEOUT 15000000 // 15 seconds timeout!
20 
21 
22 namespace BPrivate {
23 namespace media {
24 namespace dataexchange {
25 
26 
27 static BMessenger sMediaServerMessenger;
28 static BMessenger sMediaRosterMessenger;
29 static port_id sMediaServerPort;
30 static port_id sMediaAddonServerPort;
31 
32 static void find_media_server_port();
33 static void find_media_addon_server_port();
34 
35 
36 static void
37 find_media_server_port()
38 {
39 	sMediaServerPort = find_port(MEDIA_SERVER_PORT_NAME);
40 	if (sMediaServerPort < 0) {
41 		TRACE("couldn't find sMediaServerPort\n");
42 		sMediaServerPort = BAD_MEDIA_SERVER_PORT; // make this a unique number
43 	}
44 }
45 
46 
47 static void
48 find_media_addon_server_port()
49 {
50 	sMediaAddonServerPort = find_port(MEDIA_ADDON_SERVER_PORT_NAME);
51 	if (sMediaAddonServerPort < 0) {
52 		TRACE("couldn't find sMediaAddonServerPort\n");
53 		sMediaAddonServerPort = BAD_MEDIA_ADDON_SERVER_PORT; // make this a unique number
54 	}
55 }
56 
57 
58 // #pragma mark -
59 
60 
61 void
62 InitServerDataExchange()
63 {
64 	sMediaServerMessenger = BMessenger(B_MEDIA_SERVER_SIGNATURE);
65 	find_media_server_port();
66 	find_media_addon_server_port();
67 }
68 
69 
70 void
71 InitRosterDataExchange(const BMessenger& rosterMessenger)
72 {
73 	sMediaRosterMessenger = rosterMessenger;
74 }
75 
76 
77 //! BMessage based data exchange with the local BMediaRoster
78 status_t
79 SendToRoster(BMessage* msg)
80 {
81 	status_t status = sMediaRosterMessenger.SendMessage(msg,
82 		static_cast<BHandler*>(NULL), TIMEOUT);
83 	if (status != B_OK) {
84 		ERROR("SendToRoster: SendMessage failed: %s\n", strerror(status));
85 		DEBUG_ONLY(msg->PrintToStream());
86 	}
87 	return status;
88 }
89 
90 
91 //! BMessage based data exchange with the media_server
92 status_t
93 SendToServer(BMessage* msg)
94 {
95 	status_t status = sMediaServerMessenger.SendMessage(msg,
96 		static_cast<BHandler*>(NULL), TIMEOUT);
97 	if (status != B_OK) {
98 		ERROR("SendToServer: SendMessage failed: %s\n", strerror(status));
99 		DEBUG_ONLY(msg->PrintToStream());
100 	}
101 	return status;
102 }
103 
104 
105 status_t
106 QueryServer(BMessage& request, BMessage& reply)
107 {
108 	status_t status = sMediaServerMessenger.SendMessage(&request, &reply,
109 		TIMEOUT, TIMEOUT);
110 	if (status != B_OK) {
111 		ERROR("QueryServer: SendMessage failed: %s\n", strerror(status));
112 		DEBUG_ONLY(request.PrintToStream());
113 		DEBUG_ONLY(reply.PrintToStream());
114 	}
115 	return status;
116 }
117 
118 
119 //! Raw data based data exchange with the media_server
120 status_t
121 SendToServer(int32 msgCode, command_data* msg, size_t size)
122 {
123 	return SendToPort(sMediaServerPort, msgCode, msg, size);
124 }
125 
126 status_t
127 QueryServer(int32 msgCode, request_data* request, size_t requestSize,
128 	reply_data* reply, size_t replySize)
129 {
130 	return QueryPort(sMediaServerPort, msgCode, request, requestSize, reply,
131 		replySize);
132 }
133 
134 
135 //! Raw data based data exchange with the media_addon_server
136 status_t
137 SendToAddOnServer(int32 msgCode, command_data* msg, size_t size)
138 {
139 	return SendToPort(sMediaAddonServerPort, msgCode, msg, size);
140 }
141 
142 
143 status_t
144 QueryAddOnServer(int32 msgCode, request_data* request, size_t requestSize,
145 	reply_data* reply, size_t replySize)
146 {
147 	return QueryPort(sMediaAddonServerPort, msgCode, request, requestSize,
148 		reply, replySize);
149 }
150 
151 
152 //! Raw data based data exchange with the media_server
153 status_t
154 SendToPort(port_id sendPort, int32 msgCode, command_data* msg, size_t size)
155 {
156 	status_t status = write_port_etc(sendPort, msgCode, msg, size,
157 		B_RELATIVE_TIMEOUT, TIMEOUT);
158 	if (status != B_OK) {
159 		ERROR("SendToPort: write_port failed, msgcode 0x%" B_PRIx32 ", port %"
160 			B_PRId32 ": %s\n", msgCode, sendPort, strerror(status));
161 		if (status == B_BAD_PORT_ID && sendPort == sMediaServerPort) {
162 			find_media_server_port();
163 			sendPort = sMediaServerPort;
164 		} else if (status == B_BAD_PORT_ID
165 			&& sendPort == sMediaAddonServerPort) {
166 			find_media_addon_server_port();
167 			sendPort = sMediaAddonServerPort;
168 		} else
169 			return status;
170 
171 		status = write_port_etc(sendPort, msgCode, msg, size,
172 			B_RELATIVE_TIMEOUT, TIMEOUT);
173 		if (status != B_OK) {
174 			ERROR("SendToPort: retrying write_port failed, msgCode 0x%" B_PRIx32
175 				", port %" B_PRId32 ": %s\n", msgCode, sendPort,
176 				strerror(status));
177 			return status;
178 		}
179 	}
180 	return B_OK;
181 }
182 
183 
184 status_t
185 QueryPort(port_id requestPort, int32 msgCode, request_data* request,
186 	size_t requestSize, reply_data* reply, size_t replySize)
187 {
188 	status_t status = write_port_etc(requestPort, msgCode, request, requestSize,
189 		B_RELATIVE_TIMEOUT, TIMEOUT);
190 	if (status != B_OK) {
191 		ERROR("QueryPort: write_port failed, msgcode 0x%" B_PRIx32 ", port %"
192 			B_PRId32 ": %s\n", msgCode, requestPort, strerror(status));
193 
194 		if (status == B_BAD_PORT_ID && requestPort == sMediaServerPort) {
195 			find_media_server_port();
196 			requestPort = sMediaServerPort;
197 		} else if (status == B_BAD_PORT_ID
198 			&& requestPort == sMediaAddonServerPort) {
199 			find_media_addon_server_port();
200 			requestPort = sMediaAddonServerPort;
201 		} else
202 			return status;
203 
204 		status = write_port_etc(requestPort, msgCode, request, requestSize,
205 			B_RELATIVE_TIMEOUT, TIMEOUT);
206 		if (status != B_OK) {
207 			ERROR("QueryPort: retrying write_port failed, msgcode 0x%" B_PRIx32
208 				", port %" B_PRId32 ": %s\n", msgCode, requestPort,
209 				strerror(status));
210 			return status;
211 		}
212 	}
213 
214 	int32 code;
215 	status = read_port_etc(request->reply_port, &code, reply, replySize,
216 		B_RELATIVE_TIMEOUT, TIMEOUT);
217 	if (status < B_OK) {
218 		ERROR("QueryPort: read_port failed, msgcode 0x%" B_PRIx32 ", port %"
219 			B_PRId32 ": %s\n", msgCode, request->reply_port, strerror(status));
220 	}
221 
222 	return status < B_OK ? status : reply->result;
223 }
224 
225 
226 }	// dataexchange
227 }	// media
228 }	// BPrivate
229