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