xref: /haiku/src/apps/cortex/support/MediaIcon.cpp (revision c377d661268f0f924b50dcc1c105747d8cedaf1e)
1 /*
2  * Copyright (c) 1999-2000, Eric Moon.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions, and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions, and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 
32 // MediaIcon.cpp
33 
34 #include "MediaIcon.h"
35 #include "MediaIconBits.h"
36 #include "AddOnHostProtocol.h"
37 
38 // Application Kit
39 #include <Application.h>
40 #include <Roster.h>
41 // Media Kit
42 #include <MediaDefs.h>
43 #include <MediaNode.h>
44 #include <MediaRoster.h>
45 #include <MediaAddOn.h>
46 // Storage Kit
47 #include <NodeInfo.h>
48 // Support Kit
49 #include <String.h>
50 // Interface Kit
51 #include <IconUtils.h>
52 
53 
54 __USE_CORTEX_NAMESPACE
55 
56 #include <Debug.h>
57 #define D_ALLOC(x) //PRINT (x)
58 #define D_INTERNAL(x) //PRINT (x)
59 
60 // -------------------------------------------------------- //
61 // *** ctor/dtor
62 // -------------------------------------------------------- //
63 
MediaIcon(const live_node_info & nodeInfo,icon_size size)64 MediaIcon::MediaIcon(
65 	const live_node_info &nodeInfo,
66 	icon_size size)
67 	: BBitmap(BRect(0.0, 0.0, size - 1.0, size - 1.0), B_RGBA32),
68 	  m_size(size),
69 	  m_nodeKind(nodeInfo.node.kind) {
70 	D_ALLOC(("MediaIcon::MediaIcon(live_node_info '%s')\n", nodeInfo.name));
71 
72 	_findIconFor(nodeInfo);
73 }
74 
MediaIcon(const dormant_node_info & nodeInfo,icon_size size)75 MediaIcon::MediaIcon(
76 	const dormant_node_info &nodeInfo,
77 	icon_size size)
78 	: BBitmap(BRect(0.0, 0.0, size - 1.0, size - 1.0), B_RGBA32),
79 	  m_size(size),
80 	  m_nodeKind(0) {
81 	D_ALLOC(("MediaIcon::MediaIcon(dormant_node_info '%s')\n", nodeInfo.name));
82 
83 	_findIconFor(nodeInfo);
84 }
85 
~MediaIcon()86 MediaIcon::~MediaIcon() {
87 	D_ALLOC(("MediaIcon::~MediaIcon()\n"));
88 
89 }
90 
91 // -------------------------------------------------------- //
92 // *** internal accessors (private)
93 // -------------------------------------------------------- //
94 
_isPhysicalInput() const95 bool MediaIcon::_isPhysicalInput() const {
96 	D_INTERNAL(("MediaIcon::_isPhysicalInput()\n"));
97 
98 	return ((m_nodeKind & B_PHYSICAL_INPUT)
99 	     && (m_nodeKind & B_BUFFER_PRODUCER));
100 }
101 
_isPhysicalOutput() const102 bool MediaIcon::_isPhysicalOutput() const {
103 	D_INTERNAL(("MediaIcon::_isPhysicalOutput()\n"));
104 
105 	return ((m_nodeKind & B_PHYSICAL_OUTPUT)
106 	     && (m_nodeKind & B_BUFFER_CONSUMER));;
107 }
108 
_isProducer() const109 bool MediaIcon::_isProducer() const {
110 	D_INTERNAL(("MediaIcon::_isProducer()\n"));
111 
112 	return (!(m_nodeKind & B_BUFFER_CONSUMER) &&
113 			 (m_nodeKind & B_BUFFER_PRODUCER) &&
114 			!(m_nodeKind & B_PHYSICAL_INPUT)  &&
115 			!(m_nodeKind & B_PHYSICAL_OUTPUT));
116 }
117 
_isFilter() const118 bool MediaIcon::_isFilter() const {
119 	D_INTERNAL(("MediaIcon::_isFilter()\n"));
120 
121 	return ( (m_nodeKind & B_BUFFER_CONSUMER) &&
122 			 (m_nodeKind & B_BUFFER_PRODUCER) &&
123 		    !(m_nodeKind & B_PHYSICAL_INPUT)  &&
124 		    !(m_nodeKind & B_PHYSICAL_OUTPUT));
125 }
126 
_isConsumer() const127 bool MediaIcon::_isConsumer() const {
128 	D_INTERNAL(("MediaIcon::_isConsumer()\n"));
129 
130 	return ( (m_nodeKind & B_BUFFER_CONSUMER) &&
131 		    !(m_nodeKind & B_BUFFER_PRODUCER) &&
132 		    !(m_nodeKind & B_PHYSICAL_INPUT)  &&
133 		    !(m_nodeKind & B_PHYSICAL_OUTPUT));
134 }
135 
_isSystemMixer() const136 bool MediaIcon::_isSystemMixer() const {
137 	D_INTERNAL(("MediaIcon::_isSystemMixer()\n"));
138 
139 	return (m_nodeKind & B_SYSTEM_MIXER);
140 }
141 
_isTimeSource() const142 bool MediaIcon::_isTimeSource() const {
143 	D_INTERNAL(("MediaIcon::_isTimeSource()\n"));
144 
145 	return ((m_nodeKind & B_TIME_SOURCE) &&
146 		   !(m_nodeKind & B_PHYSICAL_INPUT) &&
147 		   !(m_nodeKind & B_PHYSICAL_OUTPUT));
148 }
149 
150 // -------------------------------------------------------- //
151 // *** internal operations (private)
152 // -------------------------------------------------------- //
153 
_findIconFor(const live_node_info & nodeInfo)154 void MediaIcon::_findIconFor(
155 	const live_node_info &nodeInfo) {
156 	D_INTERNAL(("MediaIcon::_findIconFor(live_node_info)\n"));
157 
158 	BMediaRoster *roster = BMediaRoster::CurrentRoster();
159 	if (m_nodeKind & B_FILE_INTERFACE) {
160 		entry_ref ref;
161 		if ((roster && (roster->GetRefFor(nodeInfo.node, &ref) == B_OK))
162 		 && (BNodeInfo::GetTrackerIcon(&ref, this, m_size) == B_OK)) {
163 			return;
164 		}
165 	}
166 	dormant_node_info dormantNodeInfo;
167 	if  (roster
168 	 && (roster->GetDormantNodeFor(nodeInfo.node, &dormantNodeInfo) == B_OK)) {
169 		D_INTERNAL((" -> instantiated from dormant node\n"));
170 		_findIconFor(dormantNodeInfo);
171 	}
172 	else {
173 		D_INTERNAL((" -> application internal node\n"));
174 		port_info portInfo;
175 		app_info appInfo;
176 		if ((get_port_info(nodeInfo.node.port, &portInfo) == B_OK)
177 		 && (be_roster->GetRunningAppInfo(portInfo.team, &appInfo) == B_OK)) {
178 			D_INTERNAL((" -> application info found: %s\n", appInfo.signature));
179 			app_info thisAppInfo;
180 			if ((be_app->GetAppInfo(&thisAppInfo) != B_OK)
181 			 || ((strcmp(appInfo.signature, thisAppInfo.signature) != 0)
182 			 && (strcmp(appInfo.signature, addon_host::g_appSignature) != 0))) {
183 				// only use app icon if the node doesn't belong to our team
184 				// or the addon-host
185 				BNodeInfo::GetTrackerIcon(&appInfo.ref, this, m_size);
186 				return;
187 			}
188 		}
189 		bool audioIn = false, audioOut = false, videoIn = false, videoOut = false;
190 		_getMediaTypesFor(nodeInfo, &audioIn, &audioOut, &videoIn, &videoOut);
191 		_findDefaultIconFor(audioIn, audioOut, videoIn, videoOut);
192 	}
193 }
194 
195 
196 void
_findIconFor(const dormant_node_info & nodeInfo)197 MediaIcon::_findIconFor(const dormant_node_info &nodeInfo)
198 {
199 	D_INTERNAL(("MediaIcon::_findIconFor(dormant_node_info)\n"));
200 
201 	dormant_flavor_info flavorInfo;
202 	BMediaRoster *roster = BMediaRoster::CurrentRoster();
203 	status_t error = roster->GetDormantFlavorInfoFor(nodeInfo, &flavorInfo);
204 	if (error == B_OK) {
205 		m_nodeKind = flavorInfo.kinds;
206 		bool audioIn = false, audioOut = false;
207 		bool videoIn = false, videoOut = false;
208 		_getMediaTypesFor(flavorInfo, &audioIn, &audioOut, &videoIn, &videoOut);
209 		_findDefaultIconFor(audioIn, audioOut, videoIn, videoOut);
210 	} else if (BString(nodeInfo.name).Compare("System clock") == 0) {
211 		BIconUtils::GetVectorIcon(M_TIME_SOURCE_ICON,
212 			sizeof(M_TIME_SOURCE_ICON), this);
213 	} else {
214 		// use generic icon in case we couldn't get any info
215 		BIconUtils::GetVectorIcon(M_GENERIC_ICON,
216 			sizeof(M_GENERIC_ICON), this);
217 	}
218 }
219 
220 
221 void
_getMediaTypesFor(const live_node_info & nodeInfo,bool * audioIn,bool * audioOut,bool * videoIn,bool * videoOut)222 MediaIcon::_getMediaTypesFor(const live_node_info &nodeInfo, bool *audioIn,
223 	bool *audioOut, bool *videoIn, bool *videoOut)
224 {
225 	D_INTERNAL(("MediaIcon::_getMediaTypeFor(live_node_info)\n"));
226 
227 	// get the media_types supported by this node
228 	const int32 numberOfInputs = 4;
229 	int32 numberOfFreeInputs, numberOfConnectedInputs;
230 	media_input inputs[numberOfInputs];
231 	const int32 numberOfOutputs = 4;
232 	int32 numberOfFreeOutputs, numberOfConnectedOutputs;
233 	media_output outputs[numberOfOutputs];
234 	BMediaRoster *roster = BMediaRoster::CurrentRoster();
235 	if (roster->GetFreeInputsFor(nodeInfo.node, inputs, numberOfInputs,
236 			&numberOfFreeInputs) == B_OK) {
237 		for (int32 i = 0; i < numberOfFreeInputs; i++) {
238 			if ((inputs[i].format.type == B_MEDIA_RAW_AUDIO)
239 			 || (inputs[i].format.type == B_MEDIA_ENCODED_AUDIO)) {
240 				*audioIn = true;
241 				continue;
242 			}
243 			if ((inputs[i].format.type == B_MEDIA_RAW_VIDEO)
244 			 || (inputs[i].format.type == B_MEDIA_ENCODED_VIDEO)) {
245 				*videoIn = true;
246 			}
247 		}
248 	}
249 	if (roster->GetConnectedInputsFor(nodeInfo.node, inputs, numberOfInputs,
250 			&numberOfConnectedInputs) == B_OK) {
251 		for (int32 i = 0; i < numberOfConnectedInputs; i++) {
252 			if ((inputs[i].format.type == B_MEDIA_RAW_AUDIO)
253 			 || (inputs[i].format.type == B_MEDIA_ENCODED_AUDIO)) {
254 				*audioIn = true;
255 				continue;
256 			}
257 			if ((inputs[i].format.type == B_MEDIA_RAW_VIDEO)
258 			 || (inputs[i].format.type == B_MEDIA_ENCODED_VIDEO)) {
259 				*videoIn = true;
260 			}
261 		}
262 	}
263 	if (roster->GetFreeOutputsFor(nodeInfo.node, outputs, numberOfOutputs,
264 			&numberOfFreeOutputs) == B_OK) {
265 		for (int32 i = 0; i < numberOfFreeOutputs; i++) {
266 			if ((outputs[i].format.type == B_MEDIA_RAW_AUDIO)
267 			 || (outputs[i].format.type == B_MEDIA_ENCODED_AUDIO)) {
268 				*audioOut = true;
269 				continue;
270 			}
271 			if ((outputs[i].format.type == B_MEDIA_RAW_VIDEO)
272 			 || (outputs[i].format.type == B_MEDIA_ENCODED_VIDEO)) {
273 				*videoOut = true;
274 			}
275 		}
276 	}
277 	if (roster->GetConnectedOutputsFor(nodeInfo.node, outputs, numberOfOutputs,
278 			&numberOfConnectedOutputs) == B_OK) {
279 		for (int32 i = 0; i < numberOfConnectedOutputs; i++) {
280 			if ((outputs[i].format.type == B_MEDIA_RAW_AUDIO)
281 			 || (outputs[i].format.type == B_MEDIA_ENCODED_AUDIO)) {
282 				*audioOut = true;
283 				continue;
284 			}
285 			if ((outputs[i].format.type == B_MEDIA_RAW_VIDEO)
286 			 || (outputs[i].format.type == B_MEDIA_ENCODED_VIDEO)) {
287 				*videoOut = true;
288 			}
289 		}
290 	}
291 }
292 
_getMediaTypesFor(const dormant_flavor_info & flavorInfo,bool * audioIn,bool * audioOut,bool * videoIn,bool * videoOut)293 void MediaIcon::_getMediaTypesFor(
294 	const dormant_flavor_info &flavorInfo,
295 	bool *audioIn,
296 	bool *audioOut,
297 	bool *videoIn,
298 	bool *videoOut) {
299 	D_INTERNAL(("MediaIcon::_getMediaTypeFor(dormant_flavor_info)\n"));
300 
301 	for (int32 i = 0; i < flavorInfo.in_format_count; i++) {
302 		if ((flavorInfo.in_formats[i].type == B_MEDIA_RAW_AUDIO)
303 		 || (flavorInfo.in_formats[i].type == B_MEDIA_ENCODED_AUDIO)) {
304 			*audioIn = true;
305 			continue;
306 		}
307 		if ((flavorInfo.in_formats[i].type == B_MEDIA_RAW_VIDEO)
308 		 || (flavorInfo.in_formats[i].type == B_MEDIA_ENCODED_VIDEO)) {
309 			*videoIn = true;
310 		}
311 	}
312 	for (int32 i = 0; i < flavorInfo.out_format_count; i++)	{
313 		if ((flavorInfo.out_formats[i].type == B_MEDIA_RAW_AUDIO)
314 		 || (flavorInfo.out_formats[i].type == B_MEDIA_ENCODED_AUDIO)) {
315 			*audioOut = true;
316 			continue;
317 		}
318 		if ((flavorInfo.out_formats[i].type == B_MEDIA_RAW_VIDEO)
319 		 || (flavorInfo.out_formats[i].type == B_MEDIA_ENCODED_VIDEO)) {
320 			*videoOut = true;
321 		}
322 	}
323 }
324 
_findDefaultIconFor(bool audioIn,bool audioOut,bool videoIn,bool videoOut)325 void MediaIcon::_findDefaultIconFor(
326 	bool audioIn,
327 	bool audioOut,
328 	bool videoIn,
329 	bool videoOut) {
330 	D_INTERNAL(("MediaIcon::_findDefaultIcon()\n"));
331 
332 	if (_isTimeSource()) {
333 		BIconUtils::GetVectorIcon(M_TIME_SOURCE_ICON,
334 			sizeof(M_TIME_SOURCE_ICON), this);
335 		return;
336 	}
337 
338 	if (_isSystemMixer()) {
339 		BIconUtils::GetVectorIcon(M_AUDIO_MIXER_ICON,
340 			sizeof(M_AUDIO_MIXER_ICON), this);
341 		return;
342 	}
343 
344 	if (m_nodeKind & B_FILE_INTERFACE) {
345 		if (_isProducer()) {
346 			BIconUtils::GetVectorIcon(M_FILE_READER_ICON,
347 				sizeof(M_FILE_READER_ICON), this);
348 			return;
349 		} else {
350 			BIconUtils::GetVectorIcon(M_FILE_WRITER_ICON,
351 				sizeof(M_FILE_WRITER_ICON), this);
352 			return;
353 		}
354 	}
355 
356 	if (_isPhysicalInput()) {
357 		if (audioIn) {
358 			BIconUtils::GetVectorIcon(M_AUDIO_DEVICE_ICON,
359 				sizeof(M_AUDIO_DEVICE_ICON), this);
360 			return;
361 		} else if (audioOut) {
362 			BIconUtils::GetVectorIcon(M_AUDIO_INPUT_ICON,
363 				sizeof(M_AUDIO_INPUT_ICON), this);
364 			return;
365 		} else if (videoOut) {
366 			BIconUtils::GetVectorIcon(M_VIDEO_INPUT_ICON,
367 				sizeof(M_VIDEO_INPUT_ICON), this);
368 			return;
369 		}
370 	}
371 
372 	if (_isPhysicalOutput()) {
373 		if (audioIn) {
374 			BIconUtils::GetVectorIcon(M_AUDIO_OUTPUT_ICON,
375 				sizeof(M_AUDIO_OUTPUT_ICON), this);
376 			return;
377 		} else if (videoIn) {
378 			BIconUtils::GetVectorIcon(M_VIDEO_OUTPUT_ICON,
379 				sizeof(M_VIDEO_OUTPUT_ICON), this);
380 			return;
381 		}
382 	}
383 
384 	if (_isProducer()) {
385 		if (audioOut) {
386 			BIconUtils::GetVectorIcon(M_AUDIO_PRODUCER_ICON,
387 				sizeof(M_AUDIO_PRODUCER_ICON), this);
388 			return;
389 		} else if (videoOut) {
390 			BIconUtils::GetVectorIcon(M_VIDEO_PRODUCER_ICON,
391 				sizeof(M_VIDEO_PRODUCER_ICON), this);
392 			return;
393 		}
394 	}
395 
396 	if (_isFilter()) {
397 		if (audioIn && audioOut && !videoIn && !videoOut) {
398 			BIconUtils::GetVectorIcon(M_AUDIO_FILTER_ICON,
399 				sizeof(M_AUDIO_FILTER_ICON), this);
400 			return;
401 		} else if (audioIn && !videoIn && videoOut) {
402 			BIconUtils::GetVectorIcon(M_AUDIO_CONSUMER_ICON,
403 				sizeof(M_AUDIO_CONSUMER_ICON), this);
404 			return;
405 		} else if (!audioIn && !audioOut && videoIn && videoOut) {
406 			BIconUtils::GetVectorIcon(M_VIDEO_FILTER_ICON,
407 				sizeof(M_VIDEO_FILTER_ICON), this);
408 			return;
409 		}
410 	}
411 
412 	if (_isConsumer()) {
413 		if (audioIn) {
414 			BIconUtils::GetVectorIcon(M_AUDIO_CONSUMER_ICON,
415 				sizeof(M_AUDIO_CONSUMER_ICON), this);
416 			return;
417 		} else if (videoIn) {
418 			BIconUtils::GetVectorIcon(M_VIDEO_CONSUMER_ICON,
419 				sizeof(M_VIDEO_CONSUMER_ICON), this);
420 			return;
421 		}
422 	}
423 
424 	// assign a default icon
425 	BIconUtils::GetVectorIcon(M_GENERIC_ICON, sizeof(M_GENERIC_ICON), this);
426 }
427