1/*
2 * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files or portions
6 * thereof (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so, subject
10 * to the following conditions:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *
15 *  * Redistributions in binary form must reproduce the above copyright notice
16 *    in the  binary, as well as this list of conditions and the following
17 *    disclaimer in the documentation and/or other materials provided with
18 *    the distribution.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
27 */
28
29
30/*!	This is a interface class for media kit notifications.
31	It is private to the media kit which uses it to pass notifications up to
32	the media_server which will broadcast them.
33*/
34
35// TODO: The BeBook, MediaDefs.h and the BeOS R5 do list
36// different strings for the message data fields of
37// the notification messages.
38
39
40#include "Notifications.h"
41
42#include <Messenger.h>
43#include <MediaNode.h>
44
45#include <AppMisc.h>
46
47#include "MediaDebug.h"
48#include "DataExchange.h"
49
50
51namespace BPrivate {
52namespace media {
53namespace notifications {
54
55
56status_t
57Register(const BMessenger& notifyHandler, const media_node& node,
58	int32 notification)
59{
60	CALLED();
61
62	if (notification == B_MEDIA_SERVER_STARTED
63		|| notification == B_MEDIA_SERVER_QUIT) {
64		BMessage msg(MEDIA_ROSTER_REQUEST_NOTIFICATIONS);
65		msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification);
66		msg.AddMessenger(NOTIFICATION_PARAM_MESSENGER, notifyHandler);
67		return BPrivate::media::dataexchange::SendToRoster(&msg);
68	}
69
70	BMessage msg(MEDIA_SERVER_REQUEST_NOTIFICATIONS);
71	msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification);
72	msg.AddInt32(NOTIFICATION_PARAM_TEAM, BPrivate::current_team());
73	msg.AddMessenger(NOTIFICATION_PARAM_MESSENGER, notifyHandler);
74	msg.AddData("node", B_RAW_TYPE, &node, sizeof(node));
75
76	return BPrivate::media::dataexchange::SendToServer(&msg);
77}
78
79
80status_t
81Unregister(const BMessenger& notifyHandler, const media_node& node,
82	int32 notification)
83{
84	CALLED();
85
86	if (notification == B_MEDIA_SERVER_STARTED
87		|| notification == B_MEDIA_SERVER_QUIT) {
88		BMessage msg(MEDIA_ROSTER_CANCEL_NOTIFICATIONS);
89		msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification);
90		msg.AddMessenger(NOTIFICATION_PARAM_MESSENGER, notifyHandler);
91		return BPrivate::media::dataexchange::SendToRoster(&msg);
92	}
93
94	BMessage msg(MEDIA_SERVER_CANCEL_NOTIFICATIONS);
95	msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification);
96	msg.AddInt32(NOTIFICATION_PARAM_TEAM, BPrivate::current_team());
97	msg.AddMessenger(NOTIFICATION_PARAM_MESSENGER, notifyHandler);
98	msg.AddData("node", B_RAW_TYPE, &node, sizeof(node));
99
100	return BPrivate::media::dataexchange::SendToServer(&msg);
101}
102
103
104/*!	Transmits the error code specified by \a what to anyone who's receiving
105	notifications from this node. If \a info isn't \c NULL, it's used as a
106	model message for the error notification message.
107	The message field "be:node_id" will contain the node ID.
108*/
109status_t
110ReportError(const media_node& node, BMediaNode::node_error what,
111	const BMessage* info)
112{
113	CALLED();
114	BMessage msg;
115	if (info != NULL)
116		msg = *info;
117
118	msg.what = MEDIA_SERVER_SEND_NOTIFICATIONS;
119	msg.AddInt32(NOTIFICATION_PARAM_WHAT, what);
120	msg.AddInt32("be:node_id", node.node);
121	msg.AddData("node", B_RAW_TYPE, &node, sizeof(node));
122
123	return BPrivate::media::dataexchange::SendToServer(&msg);
124}
125
126
127void
128NodesCreated(const media_node_id* ids, int32 count)
129{
130	CALLED();
131	BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS);
132	msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_NODE_CREATED);
133	for (int32 i = 0; i < count; i++) {
134		msg.AddInt32("media_node_id", ids[i]);
135	}
136
137	BPrivate::media::dataexchange::SendToServer(&msg);
138}
139
140
141void
142NodesDeleted(const media_node_id* ids, int32 count)
143{
144	CALLED();
145	BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS);
146	msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_NODE_DELETED);
147	for (int32 i = 0; i < count; i++) {
148		msg.AddInt32("media_node_id", ids[i]);
149	}
150
151	BPrivate::media::dataexchange::SendToServer(&msg);
152}
153
154
155void
156ConnectionMade(const media_input& input, const media_output& output,
157	const media_format& format)
158{
159	CALLED();
160	BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS);
161	msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_CONNECTION_MADE);
162	msg.AddData("input", B_RAW_TYPE, &input, sizeof(input));
163	msg.AddData("output", B_RAW_TYPE, &output, sizeof(output));
164	msg.AddData("format", B_RAW_TYPE, &format, sizeof(format));
165
166	BPrivate::media::dataexchange::SendToServer(&msg);
167}
168
169
170void
171ConnectionBroken(const media_source& source,
172	const media_destination& destination)
173{
174	CALLED();
175	BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS);
176	msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_CONNECTION_BROKEN);
177	msg.AddData("source", B_RAW_TYPE, &source, sizeof(source));
178	msg.AddData("destination", B_RAW_TYPE, &destination, sizeof(destination));
179
180	BPrivate::media::dataexchange::SendToServer(&msg);
181}
182
183
184void
185BuffersCreated(area_info* areas, int32 count)
186{
187	CALLED();
188	BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS);
189	msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_BUFFER_CREATED);
190	for (int32 i = 0; i < count; i++) {
191		msg.AddData("clone_info", B_RAW_TYPE, &areas[i], sizeof(area_info));
192	}
193
194	BPrivate::media::dataexchange::SendToServer(&msg);
195}
196
197
198void
199BuffersDeleted(const media_buffer_id* ids, int32 count)
200{
201	CALLED();
202	BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS);
203	msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_BUFFER_DELETED);
204	for (int32 i = 0; i < count; i++) {
205		msg.AddInt32("media_buffer_id", ids[i]);
206	}
207
208	BPrivate::media::dataexchange::SendToServer(&msg);
209}
210
211
212void
213FormatChanged(const media_source& source, const media_destination& destination,
214	const media_format& format)
215{
216	CALLED();
217	BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS);
218	msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_FORMAT_CHANGED);
219	msg.AddData("source", B_RAW_TYPE, &source, sizeof(source));
220	msg.AddData("destination", B_RAW_TYPE, &destination, sizeof(destination));
221	msg.AddData("format", B_RAW_TYPE, &format, sizeof(format));
222
223	BPrivate::media::dataexchange::SendToServer(&msg);
224}
225
226
227status_t
228ParameterChanged(const media_node& node, int32 parameterID)
229{
230	CALLED();
231	BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS);
232	msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_PARAMETER_CHANGED);
233	msg.AddData("node", B_RAW_TYPE, &node, sizeof(node));
234	msg.AddInt32("parameter", parameterID);
235
236	return BPrivate::media::dataexchange::SendToServer(&msg);
237}
238
239
240void
241WebChanged(const media_node& node)
242{
243	CALLED();
244	BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS);
245	msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_WEB_CHANGED);
246	msg.AddData("node", B_RAW_TYPE, &node, sizeof(node));
247
248	BPrivate::media::dataexchange::SendToServer(&msg);
249}
250
251
252status_t
253NewParameterValue(const media_node& node, int32 parameterID, bigtime_t when,
254	const void* param, size_t paramsize)
255{
256	CALLED();
257	BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS);
258	msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_NEW_PARAMETER_VALUE);
259	msg.AddData("node", B_RAW_TYPE, &node, sizeof(node));
260	msg.AddInt32("parameter", parameterID);
261	msg.AddInt64("when", when);
262	msg.AddData("value", B_RAW_TYPE, param, paramsize);
263
264	return BPrivate::media::dataexchange::SendToServer(&msg);
265}
266
267
268void
269FlavorsChanged(media_addon_id addOnID, int32 newCount, int32 goneCount)
270{
271	CALLED();
272	BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS);
273	msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_FLAVORS_CHANGED);
274	msg.AddInt32("be:addon_id", addOnID);
275	msg.AddInt32("be:new_count", newCount);
276	msg.AddInt32("be:gone_count", goneCount);
277
278	BPrivate::media::dataexchange::SendToServer(&msg);
279}
280
281
282void
283NodeStopped(const media_node& node, bigtime_t when)
284{
285	CALLED();
286	BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS);
287	msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_NODE_STOPPED);
288	msg.AddData("node", B_RAW_TYPE, &node, sizeof(node));
289	msg.AddInt64("when", when);
290
291	BPrivate::media::dataexchange::SendToServer(&msg);
292}
293
294
295// TODO: missing: B_MEDIA_TRANSPORT_STATE: "state", "location", "realtime"
296// TODO: missing: B_MEDIA_DEFAULT_CHANGED: "default", "node"
297
298
299bool
300IsValidNotificationRequest(bool node_specific, int32 notification)
301{
302	switch (notification) {
303		// valid for normal and node specific watching
304		case B_MEDIA_WILDCARD:
305		case B_MEDIA_NODE_CREATED:
306		case B_MEDIA_NODE_DELETED:
307		case B_MEDIA_CONNECTION_MADE:
308		case B_MEDIA_CONNECTION_BROKEN:
309		case B_MEDIA_BUFFER_CREATED:
310		case B_MEDIA_BUFFER_DELETED:
311		case B_MEDIA_TRANSPORT_STATE:
312		case B_MEDIA_DEFAULT_CHANGED:
313		case B_MEDIA_FLAVORS_CHANGED:
314			return true;
315
316		// invalid if we watch for a specific node
317		case B_MEDIA_SERVER_STARTED:
318		case B_MEDIA_SERVER_QUIT:
319			return !node_specific;
320
321		// only valid for node specific watching
322		case B_MEDIA_PARAMETER_CHANGED:
323		case B_MEDIA_FORMAT_CHANGED:
324		case B_MEDIA_WEB_CHANGED:
325		case B_MEDIA_NEW_PARAMETER_VALUE:
326		case B_MEDIA_NODE_STOPPED:
327			return node_specific;
328
329		// everything else is invalid
330		default:
331			return false;
332	}
333}
334
335}	// namespace notifications
336}	// namespace media
337}	// namespace BPrivate
338