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