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
22namespace BPrivate {
23namespace media {
24namespace dataexchange {
25
26
27static BMessenger sMediaServerMessenger;
28static BMessenger sMediaRosterMessenger;
29static port_id sMediaServerPort;
30static port_id sMediaAddonServerPort;
31
32static void find_media_server_port();
33static void find_media_addon_server_port();
34
35
36static void
37find_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
47static void
48find_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
61void
62InitServerDataExchange()
63{
64	sMediaServerMessenger = BMessenger(B_MEDIA_SERVER_SIGNATURE);
65	find_media_server_port();
66	find_media_addon_server_port();
67}
68
69
70void
71InitRosterDataExchange(const BMessenger& rosterMessenger)
72{
73	sMediaRosterMessenger = rosterMessenger;
74}
75
76
77//! BMessage based data exchange with the local BMediaRoster
78status_t
79SendToRoster(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
92status_t
93SendToServer(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
105status_t
106QueryServer(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
120status_t
121SendToServer(int32 msgCode, command_data* msg, size_t size)
122{
123	return SendToPort(sMediaServerPort, msgCode, msg, size);
124}
125
126status_t
127QueryServer(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
136status_t
137SendToAddOnServer(int32 msgCode, command_data* msg, size_t size)
138{
139	return SendToPort(sMediaAddonServerPort, msgCode, msg, size);
140}
141
142
143status_t
144QueryAddOnServer(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
153status_t
154SendToPort(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
184status_t
185QueryPort(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