xref: /haiku/src/kits/media/DataExchange.cpp (revision 93aeb8c3bc3f13cb1f282e3e749258a23790d947)
1 /*
2  * Copyright 2002, 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 	rv = write_port_etc(sendport, msgcode, msg, size, B_RELATIVE_TIMEOUT, TIMEOUT);
142 	if (rv != B_OK) {
143 		ERROR("SendToPort: write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, sendport, rv, strerror(rv));
144 		if (rv == B_BAD_PORT_ID && sendport == MediaServerPort) {
145 			find_media_server_port();
146 			sendport = MediaServerPort;
147 		} else if (rv == B_BAD_PORT_ID && sendport == MediaAddonServerPort) {
148 			find_media_addon_server_port();
149 			sendport = MediaAddonServerPort;
150 		} else {
151 			return rv;
152 		}
153 		rv = write_port_etc(sendport, msgcode, msg, size, B_RELATIVE_TIMEOUT, TIMEOUT);
154 		if (rv != B_OK) {
155 			ERROR("SendToPort: retrying write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, sendport, rv, strerror(rv));
156 			return rv;
157 		}
158 	}
159 	return B_OK;
160 }
161 
162 
163 status_t QueryPort(port_id requestport, int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize)
164 {
165 	status_t rv;
166 	int32 code;
167 
168 	request->reply_port = _PortPool->GetPort();
169 
170 	rv = write_port_etc(requestport, msgcode, request, requestsize, B_RELATIVE_TIMEOUT, TIMEOUT);
171 
172 	if (rv != B_OK) {
173 		ERROR("QueryPort: write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, requestport, rv, strerror(rv));
174 		if (rv == B_BAD_PORT_ID && requestport == MediaServerPort) {
175 			find_media_server_port();
176 			requestport = MediaServerPort;
177 		} else if (rv == B_BAD_PORT_ID && requestport == MediaAddonServerPort) {
178 			find_media_addon_server_port();
179 			requestport = MediaAddonServerPort;
180 		} else {
181 			_PortPool->PutPort(request->reply_port);
182 			return rv;
183 		}
184 		rv = write_port_etc(requestport, msgcode, request, requestsize, B_RELATIVE_TIMEOUT, TIMEOUT);
185 		if (rv != B_OK) {
186 			ERROR("QueryPort: retrying write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, requestport, rv, strerror(rv));
187 			_PortPool->PutPort(request->reply_port);
188 			return rv;
189 		}
190 	}
191 
192 	rv = read_port_etc(request->reply_port, &code, reply, replysize, B_RELATIVE_TIMEOUT, TIMEOUT);
193 	_PortPool->PutPort(request->reply_port);
194 
195 	if (rv < B_OK) {
196 		ERROR("QueryPort: read_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, request->reply_port, rv, strerror(rv));
197 	}
198 
199 	return (rv < B_OK) ? rv : reply->result;
200 }
201 
202 }; // dataexchange
203 }; // media
204 }; // BPrivate
205 
206