xref: /haiku/src/apps/cortex/support/MediaIcon.cpp (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
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 
51 __USE_CORTEX_NAMESPACE
52 
53 #include <Debug.h>
54 #define D_ALLOC(x) //PRINT (x)
55 #define D_INTERNAL(x) //PRINT (x)
56 
57 // -------------------------------------------------------- //
58 // *** ctor/dtor
59 // -------------------------------------------------------- //
60 
61 MediaIcon::MediaIcon(
62 	const live_node_info &nodeInfo,
63 	icon_size size)
64 	: BBitmap(BRect(0.0, 0.0, size - 1.0, size - 1.0), B_CMAP8),
65 	  m_size(size),
66 	  m_nodeKind(nodeInfo.node.kind) {
67 	D_ALLOC(("MediaIcon::MediaIcon(live_node_info '%s')\n", nodeInfo.name));
68 
69 	_findIconFor(nodeInfo);
70 }
71 
72 MediaIcon::MediaIcon(
73 	const dormant_node_info &nodeInfo,
74 	icon_size size)
75 	: BBitmap(BRect(0.0, 0.0, size - 1.0, size - 1.0), B_CMAP8),
76 	  m_size(size),
77 	  m_nodeKind(0) {
78 	D_ALLOC(("MediaIcon::MediaIcon(dormant_node_info '%s')\n", nodeInfo.name));
79 
80 	_findIconFor(nodeInfo);
81 }
82 
83 MediaIcon::~MediaIcon() {
84 	D_ALLOC(("MediaIcon::~MediaIcon()\n"));
85 
86 }
87 
88 // -------------------------------------------------------- //
89 // *** internal accessors (private)
90 // -------------------------------------------------------- //
91 
92 bool MediaIcon::_isPhysicalInput() const {
93 	D_INTERNAL(("MediaIcon::_isPhysicalInput()\n"));
94 
95 	return ((m_nodeKind & B_PHYSICAL_INPUT)
96 	     && (m_nodeKind & B_BUFFER_PRODUCER));
97 }
98 
99 bool MediaIcon::_isPhysicalOutput() const {
100 	D_INTERNAL(("MediaIcon::_isPhysicalOutput()\n"));
101 
102 	return ((m_nodeKind & B_PHYSICAL_OUTPUT)
103 	     && (m_nodeKind & B_BUFFER_CONSUMER));;
104 }
105 
106 bool MediaIcon::_isProducer() const {
107 	D_INTERNAL(("MediaIcon::_isProducer()\n"));
108 
109 	return (!(m_nodeKind & B_BUFFER_CONSUMER) &&
110 			 (m_nodeKind & B_BUFFER_PRODUCER) &&
111 			!(m_nodeKind & B_PHYSICAL_INPUT)  &&
112 			!(m_nodeKind & B_PHYSICAL_OUTPUT));
113 }
114 
115 bool MediaIcon::_isFilter() const {
116 	D_INTERNAL(("MediaIcon::_isFilter()\n"));
117 
118 	return ( (m_nodeKind & B_BUFFER_CONSUMER) &&
119 			 (m_nodeKind & B_BUFFER_PRODUCER) &&
120 		    !(m_nodeKind & B_PHYSICAL_INPUT)  &&
121 		    !(m_nodeKind & B_PHYSICAL_OUTPUT));
122 }
123 
124 bool MediaIcon::_isConsumer() const {
125 	D_INTERNAL(("MediaIcon::_isConsumer()\n"));
126 
127 	return ( (m_nodeKind & B_BUFFER_CONSUMER) &&
128 		    !(m_nodeKind & B_BUFFER_PRODUCER) &&
129 		    !(m_nodeKind & B_PHYSICAL_INPUT)  &&
130 		    !(m_nodeKind & B_PHYSICAL_OUTPUT));
131 }
132 
133 bool MediaIcon::_isSystemMixer() const {
134 	D_INTERNAL(("MediaIcon::_isSystemMixer()\n"));
135 
136 	return (m_nodeKind & B_SYSTEM_MIXER);
137 }
138 
139 bool MediaIcon::_isTimeSource() const {
140 	D_INTERNAL(("MediaIcon::_isTimeSource()\n"));
141 
142 	return ((m_nodeKind & B_TIME_SOURCE) &&
143 		   !(m_nodeKind & B_PHYSICAL_INPUT) &&
144 		   !(m_nodeKind & B_PHYSICAL_OUTPUT));
145 }
146 
147 // -------------------------------------------------------- //
148 // *** internal operations (private)
149 // -------------------------------------------------------- //
150 
151 void MediaIcon::_findIconFor(
152 	const live_node_info &nodeInfo) {
153 	D_INTERNAL(("MediaIcon::_findIconFor(live_node_info)\n"));
154 
155 	BMediaRoster *roster = BMediaRoster::CurrentRoster();
156 	if (m_nodeKind & B_FILE_INTERFACE) {
157 		entry_ref ref;
158 		if ((roster && (roster->GetRefFor(nodeInfo.node, &ref) == B_OK))
159 		 && (BNodeInfo::GetTrackerIcon(&ref, this, m_size) == B_OK)) {
160 			return;
161 		}
162 	}
163 	dormant_node_info dormantNodeInfo;
164 	if  (roster
165 	 && (roster->GetDormantNodeFor(nodeInfo.node, &dormantNodeInfo) == B_OK)) {
166 		D_INTERNAL((" -> instantiated from dormant node\n"));
167 		_findIconFor(dormantNodeInfo);
168 	}
169 	else {
170 		D_INTERNAL((" -> application internal node\n"));
171 		port_info portInfo;
172 		app_info appInfo;
173 		if ((get_port_info(nodeInfo.node.port, &portInfo) == B_OK)
174 		 && (be_roster->GetRunningAppInfo(portInfo.team, &appInfo) == B_OK)) {
175 			D_INTERNAL((" -> application info found: %s\n", appInfo.signature));
176 			app_info thisAppInfo;
177 			if ((be_app->GetAppInfo(&thisAppInfo) != B_OK)
178 			 || ((strcmp(appInfo.signature, thisAppInfo.signature) != 0)
179 			 && (strcmp(appInfo.signature, addon_host::g_appSignature) != 0))) {
180 				// only use app icon if the node doesn't belong to our team
181 				// or the addon-host
182 				BNodeInfo::GetTrackerIcon(&appInfo.ref, this, m_size);
183 				return;
184 			}
185 		}
186 		bool audioIn = false, audioOut = false, videoIn = false, videoOut = false;
187 		_getMediaTypesFor(nodeInfo, &audioIn, &audioOut, &videoIn, &videoOut);
188 		_findDefaultIconFor(audioIn, audioOut, videoIn, videoOut);
189 	}
190 }
191 
192 
193 void
194 MediaIcon::_findIconFor(const dormant_node_info &nodeInfo)
195 {
196 	D_INTERNAL(("MediaIcon::_findIconFor(dormant_node_info)\n"));
197 
198 	dormant_flavor_info flavorInfo;
199 	BMediaRoster *roster = BMediaRoster::CurrentRoster();
200 	status_t error = roster->GetDormantFlavorInfoFor(nodeInfo, &flavorInfo);
201 	if (error == B_OK) {
202 		m_nodeKind = flavorInfo.kinds;
203 		bool audioIn = false, audioOut = false;
204 		bool videoIn = false, videoOut = false;
205 		_getMediaTypesFor(flavorInfo, &audioIn, &audioOut, &videoIn, &videoOut);
206 		_findDefaultIconFor(audioIn, audioOut, videoIn, videoOut);
207 	} else {
208 		// use generic icon in case we couldn't get any info
209 		if (m_size == B_LARGE_ICON)
210 			SetBits(M_GENERIC_ICON.large, 1024, 0, B_CMAP8);
211 		else if (m_size == B_MINI_ICON)
212 			SetBits(M_GENERIC_ICON.small, 256, 0, B_CMAP8);
213 	}
214 }
215 
216 
217 void
218 MediaIcon::_getMediaTypesFor(const live_node_info &nodeInfo, bool *audioIn,
219 	bool *audioOut, bool *videoIn, bool *videoOut)
220 {
221 	D_INTERNAL(("MediaIcon::_getMediaTypeFor(live_node_info)\n"));
222 
223 	// get the media_types supported by this node
224 	const int32 numberOfInputs = 4;
225 	int32 numberOfFreeInputs, numberOfConnectedInputs;
226 	media_input inputs[numberOfInputs];
227 	const int32 numberOfOutputs = 4;
228 	int32 numberOfFreeOutputs, numberOfConnectedOutputs;
229 	media_output outputs[numberOfOutputs];
230 	BMediaRoster *roster = BMediaRoster::CurrentRoster();
231 	if (roster->GetFreeInputsFor(nodeInfo.node, inputs, numberOfInputs, &numberOfFreeInputs) == B_OK) {
232 		for (int32 i = 0; i < numberOfFreeInputs; i++) {
233 			if ((inputs[i].format.type == B_MEDIA_RAW_AUDIO)
234 			 || (inputs[i].format.type == B_MEDIA_ENCODED_AUDIO)) {
235 				*audioIn = true;
236 				continue;
237 			}
238 			if ((inputs[i].format.type == B_MEDIA_RAW_VIDEO)
239 			 || (inputs[i].format.type == B_MEDIA_ENCODED_VIDEO)) {
240 				*videoIn = true;
241 			}
242 		}
243 	}
244 	if (roster->GetConnectedInputsFor(nodeInfo.node, inputs, numberOfInputs, &numberOfConnectedInputs) == B_OK) {
245 		for (int32 i = 0; i < numberOfConnectedInputs; i++) {
246 			if ((inputs[i].format.type == B_MEDIA_RAW_AUDIO)
247 			 || (inputs[i].format.type == B_MEDIA_ENCODED_AUDIO)) {
248 				*audioIn = true;
249 				continue;
250 			}
251 			if ((inputs[i].format.type == B_MEDIA_RAW_VIDEO)
252 			 || (inputs[i].format.type == B_MEDIA_ENCODED_VIDEO)) {
253 				*videoIn = true;
254 			}
255 		}
256 	}
257 	if (roster->GetFreeOutputsFor(nodeInfo.node, outputs, numberOfOutputs, &numberOfFreeOutputs) == B_OK) {
258 		for (int32 i = 0; i < numberOfFreeOutputs; i++) {
259 			if ((outputs[i].format.type == B_MEDIA_RAW_AUDIO)
260 			 || (outputs[i].format.type == B_MEDIA_ENCODED_AUDIO)) {
261 				*audioOut = true;
262 				continue;
263 			}
264 			if ((outputs[i].format.type == B_MEDIA_RAW_VIDEO)
265 			 || (outputs[i].format.type == B_MEDIA_ENCODED_VIDEO)) {
266 				*videoOut = true;
267 			}
268 		}
269 	}
270 	if (roster->GetConnectedOutputsFor(nodeInfo.node, outputs, numberOfOutputs, &numberOfConnectedOutputs) == B_OK) {
271 		for (int32 i = 0; i < numberOfConnectedOutputs; i++) {
272 			if ((outputs[i].format.type == B_MEDIA_RAW_AUDIO)
273 			 || (outputs[i].format.type == B_MEDIA_ENCODED_AUDIO)) {
274 				*audioOut = true;
275 				continue;
276 			}
277 			if ((outputs[i].format.type == B_MEDIA_RAW_VIDEO)
278 			 || (outputs[i].format.type == B_MEDIA_ENCODED_VIDEO)) {
279 				*videoOut = true;
280 			}
281 		}
282 	}
283 }
284 
285 void MediaIcon::_getMediaTypesFor(
286 	const dormant_flavor_info &flavorInfo,
287 	bool *audioIn,
288 	bool *audioOut,
289 	bool *videoIn,
290 	bool *videoOut) {
291 	D_INTERNAL(("MediaIcon::_getMediaTypeFor(dormant_flavor_info)\n"));
292 
293 	for (int32 i = 0; i < flavorInfo.in_format_count; i++) {
294 		if ((flavorInfo.in_formats[i].type == B_MEDIA_RAW_AUDIO)
295 		 || (flavorInfo.in_formats[i].type == B_MEDIA_ENCODED_AUDIO)) {
296 			*audioIn = true;
297 			continue;
298 		}
299 		if ((flavorInfo.in_formats[i].type == B_MEDIA_RAW_VIDEO)
300 		 || (flavorInfo.in_formats[i].type == B_MEDIA_ENCODED_VIDEO)) {
301 			*videoIn = true;
302 		}
303 	}
304 	for (int32 i = 0; i < flavorInfo.out_format_count; i++)	{
305 		if ((flavorInfo.out_formats[i].type == B_MEDIA_RAW_AUDIO)
306 		 || (flavorInfo.out_formats[i].type == B_MEDIA_ENCODED_AUDIO)) {
307 			*audioOut = true;
308 			continue;
309 		}
310 		if ((flavorInfo.out_formats[i].type == B_MEDIA_RAW_VIDEO)
311 		 || (flavorInfo.out_formats[i].type == B_MEDIA_ENCODED_VIDEO)) {
312 			*videoOut = true;
313 		}
314 	}
315 }
316 
317 void MediaIcon::_findDefaultIconFor(
318 	bool audioIn,
319 	bool audioOut,
320 	bool videoIn,
321 	bool videoOut) {
322 	D_INTERNAL(("MediaIcon::_findDefaultIcon()\n"));
323 
324 	if (_isTimeSource()) {
325 		if (m_size == B_LARGE_ICON)
326 			SetBits(M_TIME_SOURCE_ICON.large, 1024, 0, B_CMAP8);
327 		else if (m_size == B_MINI_ICON)
328 			SetBits(M_TIME_SOURCE_ICON.small, 256, 0, B_CMAP8);
329 		return;
330 	}
331 
332 	if (_isSystemMixer()) {
333 		if (m_size == B_LARGE_ICON)
334 			SetBits(M_AUDIO_MIXER_ICON.large, 1024, 0, B_CMAP8);
335 		else if (m_size == B_MINI_ICON)
336 			SetBits(M_AUDIO_MIXER_ICON.small, 256, 0, B_CMAP8);
337 		return;
338 	}
339 
340 	if (m_nodeKind & B_FILE_INTERFACE) {
341 		if (_isProducer()) {
342 			if (m_size == B_LARGE_ICON)
343 				SetBits(M_FILE_READER_ICON.large, 1024, 0, B_CMAP8);
344 			else if (m_size == B_MINI_ICON)
345 				SetBits(M_FILE_READER_ICON.small, 256, 0, B_CMAP8);
346 			return;
347 		}
348 		else {
349 			if (m_size == B_LARGE_ICON)
350 				SetBits(M_FILE_WRITER_ICON.large, 1024, 0, B_CMAP8);
351 			else if (m_size == B_MINI_ICON)
352 				SetBits(M_FILE_WRITER_ICON.small, 256, 0, B_CMAP8);
353 			return;
354 		}
355 	}
356 
357 	if (_isPhysicalInput()) {
358 		if (audioOut) {
359 			if (m_size == B_LARGE_ICON)
360 				SetBits(M_AUDIO_INPUT_ICON.large, 1024, 0, B_CMAP8);
361 			else if (m_size == B_MINI_ICON)
362 				SetBits(M_AUDIO_INPUT_ICON.small, 256, 0, B_CMAP8);
363 			return;
364 		}
365 		else if (videoOut) {
366 			if (m_size == B_LARGE_ICON)
367 				SetBits(M_VIDEO_INPUT_ICON.large, 1024, 0, B_CMAP8);
368 			else if (m_size == B_MINI_ICON)
369 				SetBits(M_VIDEO_INPUT_ICON.small, 256, 0, B_CMAP8);
370 			return;
371 		}
372 	}
373 
374 	if (_isPhysicalOutput()) {
375 		if (audioIn) {
376 			if (m_size == B_LARGE_ICON)
377 				SetBits(M_AUDIO_OUTPUT_ICON.large, 1024, 0, B_CMAP8);
378 			else if (m_size == B_MINI_ICON)
379 				SetBits(M_AUDIO_OUTPUT_ICON.small, 256, 0, B_CMAP8);
380 			return;
381 		}
382 		else if (videoIn) {
383 			if (m_size == B_LARGE_ICON)
384 				SetBits(M_VIDEO_OUTPUT_ICON.large, 1024, 0, B_CMAP8);
385 			else if (m_size == B_MINI_ICON)
386 				SetBits(M_VIDEO_OUTPUT_ICON.small, 256, 0, B_CMAP8);
387 			return;
388 		}
389 	}
390 
391 	if (_isProducer()) {
392 		if (audioOut) {
393 			if (m_size == B_LARGE_ICON)
394 				SetBits(M_AUDIO_PRODUCER_ICON.large, 1024, 0, B_CMAP8);
395 			else if (m_size == B_MINI_ICON)
396 				SetBits(M_AUDIO_PRODUCER_ICON.small, 256, 0, B_CMAP8);
397 			return;
398 		}
399 		else if (videoOut) {
400 			if (m_size == B_LARGE_ICON)
401 				SetBits(M_VIDEO_PRODUCER_ICON.large, 1024, 0, B_CMAP8);
402 			else if (m_size == B_MINI_ICON)
403 				SetBits(M_VIDEO_PRODUCER_ICON.small, 256, 0, B_CMAP8);
404 			return;
405 		}
406 	}
407 
408 	if (_isFilter()) {
409 		if (audioIn && audioOut && !videoIn && !videoOut) {
410 			if (m_size == B_LARGE_ICON)
411 				SetBits(M_AUDIO_FILTER_ICON.large, 1024, 0, B_CMAP8);
412 			else if (m_size == B_MINI_ICON)
413 				SetBits(M_AUDIO_FILTER_ICON.small, 256, 0, B_CMAP8);
414 			return;
415 		}
416 		else if (audioIn && !videoIn && videoOut) {
417 			if (m_size == B_LARGE_ICON)
418 				SetBits(M_AUDIO_CONSUMER_ICON.large, 1024, 0, B_CMAP8);
419 			else if (m_size == B_MINI_ICON)
420 				SetBits(M_AUDIO_CONSUMER_ICON.small, 256, 0, B_CMAP8);
421 			return;
422 		}
423 		else if (!audioIn && !audioOut && videoIn && videoOut) {
424 			if (m_size == B_LARGE_ICON)
425 				SetBits(M_VIDEO_FILTER_ICON.large, 1024, 0, B_CMAP8);
426 			else if (m_size == B_MINI_ICON)
427 				SetBits(M_VIDEO_FILTER_ICON.small, 256, 0, B_CMAP8);
428 			return;
429 		}
430 	}
431 
432 	if (_isConsumer()) {
433 		if (audioIn) {
434 			if (m_size == B_LARGE_ICON)
435 				SetBits(M_AUDIO_CONSUMER_ICON.large, 1024, 0, B_CMAP8);
436 			else if (m_size == B_MINI_ICON)
437 				SetBits(M_AUDIO_CONSUMER_ICON.small, 256, 0, B_CMAP8);
438 			return;
439 		}
440 		else if (videoIn) {
441 			if (m_size == B_LARGE_ICON)
442 				SetBits(M_VIDEO_CONSUMER_ICON.large, 1024, 0, B_CMAP8);
443 			else if (m_size == B_MINI_ICON)
444 				SetBits(M_VIDEO_CONSUMER_ICON.small, 256, 0, B_CMAP8);
445 			return;
446 		}
447 	}
448 
449 	// assign a default icon
450 	if (m_size == B_LARGE_ICON)
451 		SetBits(M_GENERIC_ICON.large, 1024, 0, B_CMAP8);
452 	else if (m_size == B_MINI_ICON)
453 		SetBits(M_GENERIC_ICON.small, 256, 0, B_CMAP8);
454 }
455