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 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 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 86 MediaIcon::~MediaIcon() { 87 D_ALLOC(("MediaIcon::~MediaIcon()\n")); 88 89 } 90 91 // -------------------------------------------------------- // 92 // *** internal accessors (private) 93 // -------------------------------------------------------- // 94 95 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 102 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 109 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 118 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 127 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 136 bool MediaIcon::_isSystemMixer() const { 137 D_INTERNAL(("MediaIcon::_isSystemMixer()\n")); 138 139 return (m_nodeKind & B_SYSTEM_MIXER); 140 } 141 142 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 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 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 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 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 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