xref: /haiku/src/kits/media/DataExchange.cpp (revision f8da8f3477d3c18142e59d17d05a545982faa5a8)
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 <debug.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 port_id sMediaServerPort;
29 static port_id sMediaAddonServerPort;
30 
31 static void find_media_server_port();
32 static void find_media_addon_server_port();
33 
34 
35 static void
36 find_media_server_port()
37 {
38 	sMediaServerPort = find_port(MEDIA_SERVER_PORT_NAME);
39 	if (sMediaServerPort < 0) {
40 		TRACE("couldn't find sMediaServerPort\n");
41 		sMediaServerPort = BAD_MEDIA_SERVER_PORT; // make this a unique number
42 	}
43 }
44 
45 
46 static void
47 find_media_addon_server_port()
48 {
49 	sMediaAddonServerPort = find_port(MEDIA_ADDON_SERVER_PORT_NAME);
50 	if (sMediaAddonServerPort < 0) {
51 		TRACE("couldn't find sMediaAddonServerPort\n");
52 		sMediaAddonServerPort = BAD_MEDIA_ADDON_SERVER_PORT; // make this a unique number
53 	}
54 }
55 
56 
57 // #pragma mark -
58 
59 
60 void
61 InitDataExchange()
62 {
63 	sMediaServerMessenger = BMessenger(B_MEDIA_SERVER_SIGNATURE);
64 	find_media_server_port();
65 	find_media_addon_server_port();
66 }
67 
68 
69 //! BMessage based data exchange with the media_server
70 status_t
71 SendToServer(BMessage* msg)
72 {
73 	status_t status = sMediaServerMessenger.SendMessage(msg,
74 		static_cast<BHandler*>(NULL), TIMEOUT);
75 	if (status != B_OK) {
76 		ERROR("SendToServer: SendMessage failed: %s\n", strerror(status));
77 		DEBUG_ONLY(msg->PrintToStream());
78 	}
79 	return status;
80 }
81 
82 
83 status_t
84 QueryServer(BMessage& request, BMessage& reply)
85 {
86 	status_t status = sMediaServerMessenger.SendMessage(&request, &reply,
87 		TIMEOUT, TIMEOUT);
88 	if (status != B_OK) {
89 		ERROR("QueryServer: SendMessage failed: %s\n", strerror(status));
90 		DEBUG_ONLY(request.PrintToStream());
91 		DEBUG_ONLY(reply.PrintToStream());
92 	}
93 	return status;
94 }
95 
96 
97 //! Raw data based data exchange with the media_server
98 status_t
99 SendToServer(int32 msgCode, command_data* msg, size_t size)
100 {
101 	return SendToPort(sMediaServerPort, msgCode, msg, size);
102 }
103 
104 status_t
105 QueryServer(int32 msgCode, request_data* request, size_t requestSize,
106 	reply_data* reply, size_t replySize)
107 {
108 	return QueryPort(sMediaServerPort, msgCode, request, requestSize, reply,
109 		replySize);
110 }
111 
112 
113 //! Raw data based data exchange with the media_addon_server
114 status_t
115 SendToAddOnServer(int32 msgCode, command_data* msg, size_t size)
116 {
117 	return SendToPort(sMediaAddonServerPort, msgCode, msg, size);
118 }
119 
120 
121 status_t
122 QueryAddOnServer(int32 msgCode, request_data* request, size_t requestSize,
123 	reply_data* reply, size_t replySize)
124 {
125 	return QueryPort(sMediaAddonServerPort, msgCode, request, requestSize,
126 		reply, replySize);
127 }
128 
129 
130 //! Raw data based data exchange with the media_server
131 status_t
132 SendToPort(port_id sendPort, int32 msgCode, command_data* msg, size_t size)
133 {
134 	status_t status = write_port_etc(sendPort, msgCode, msg, size,
135 		B_RELATIVE_TIMEOUT, TIMEOUT);
136 	if (status != B_OK) {
137 		ERROR("SendToPort: write_port failed, msgcode 0x%" B_PRIx32 ", port %"
138 			B_PRId32 ": %s\n", msgCode, sendPort, strerror(status));
139 		if (status == B_BAD_PORT_ID && sendPort == sMediaServerPort) {
140 			find_media_server_port();
141 			sendPort = sMediaServerPort;
142 		} else if (status == B_BAD_PORT_ID
143 			&& sendPort == sMediaAddonServerPort) {
144 			find_media_addon_server_port();
145 			sendPort = sMediaAddonServerPort;
146 		} else
147 			return status;
148 
149 		status = write_port_etc(sendPort, msgCode, msg, size,
150 			B_RELATIVE_TIMEOUT, TIMEOUT);
151 		if (status != B_OK) {
152 			ERROR("SendToPort: retrying write_port failed, msgCode 0x%" B_PRIx32
153 				", port %" B_PRId32 ": %s\n", msgCode, sendPort,
154 				strerror(status));
155 			return status;
156 		}
157 	}
158 	return B_OK;
159 }
160 
161 
162 status_t
163 QueryPort(port_id requestPort, int32 msgCode, request_data* request,
164 	size_t requestSize, reply_data* reply, size_t replySize)
165 {
166 	status_t status = write_port_etc(requestPort, msgCode, request, requestSize,
167 		B_RELATIVE_TIMEOUT, TIMEOUT);
168 	if (status != B_OK) {
169 		ERROR("QueryPort: write_port failed, msgcode 0x%" B_PRIx32 ", port %"
170 			B_PRId32 ": %s\n", msgCode, requestPort, strerror(status));
171 
172 		if (status == B_BAD_PORT_ID && requestPort == sMediaServerPort) {
173 			find_media_server_port();
174 			requestPort = sMediaServerPort;
175 		} else if (status == B_BAD_PORT_ID
176 			&& requestPort == sMediaAddonServerPort) {
177 			find_media_addon_server_port();
178 			requestPort = sMediaAddonServerPort;
179 		} else
180 			return status;
181 
182 		status = write_port_etc(requestPort, msgCode, request, requestSize,
183 			B_RELATIVE_TIMEOUT, TIMEOUT);
184 		if (status != B_OK) {
185 			ERROR("QueryPort: retrying write_port failed, msgcode 0x%" B_PRIx32
186 				", port %" B_PRId32 ": %s\n", msgCode, requestPort,
187 				strerror(status));
188 			return status;
189 		}
190 	}
191 
192 	int32 code;
193 	status = read_port_etc(request->reply_port, &code, reply, replySize,
194 		B_RELATIVE_TIMEOUT, TIMEOUT);
195 	if (status < B_OK) {
196 		ERROR("QueryPort: read_port failed, msgcode 0x%" B_PRIx32 ", port %"
197 			B_PRId32 ": %s\n", msgCode, request->reply_port, strerror(status));
198 	}
199 
200 	return status < B_OK ? status : reply->result;
201 }
202 
203 
204 }	// dataexchange
205 }	// media
206 }	// BPrivate
207