1 /* 2 * This is system cordova_plugin (TV specific API). 3 * Apache License (2004). See http://www.apache.org/licenses/LICENSE-2.0 4 * 5 * Copyright (c) 2014, LG Electronics, Inc. 6 */ 7 8 9 /** 10 * This represents the InputSource API itself, and provides a global namespace for operating InputSource service. 11 * @class 12 */ 13 cordova.define('cordova/plugin/inputSource', function (require, exports, module) { // jshint ignore:line 14 15 function log(msg) { 16 //console.log//will be removed // jshint ignore:line 17 } 18 19 var service; 20 if (window.PalmSystem) { // jshint ignore:line 21 log("Window.PalmSystem Available"); 22 service = require('cordova/plugin/webos/service'); 23 } else { 24 service = { 25 Request : function(uri, params) { 26 log(uri + " invoked. But I am a dummy because PalmSystem is not available"); 27 28 if (typeof params.onFailure === 'function') { 29 params.onFailure({ returnValue:false, 30 errorText:"PalmSystem Not Available. Cordova is not installed?"}); 31 } 32 }}; 33 } 34 35 /** 36 * inputSource interface 37 */ 38 var InputSource = function () { 39 }; 40 41 var broadcast = null; 42 43 function checkErrorCodeNText(result, errorCode, errorText) { 44 45 if (result.errorCode === undefined || result.errorCode === null ) { 46 result.errorCode = errorCode; 47 } 48 if (result.errorText ===undefined || result.errorText === null) { 49 result.errorText = errorText; 50 } 51 } 52 53 /** 54 * Imports video tag to show the input source dynamically. This is used to embed input source in an html page. 55 * 56 * @class InputSource 57 * @param {Function} successCallback success callback function. 58 * @param {Function} errorCallback failure callback function. 59 * @param {Object} options 60 * <div align=left> 61 * <table class="hcap_spec" width=400> 62 * <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead> 63 * <tbody> 64 * <tr><th>divId</th><th>String</th><th>Div tag ID with the video tag in it. </th><th>required</th></tr> 65 * <tr class="odd"><th>videoId</th><th>String</th><th>The ID of the video tag to be dynamically created. </th><th>required</th></tr> 66 * <tr><th>callback</th><th>Function</th><th>An event handler (onloadedmetadata) that is called when the video tag is created. </th><th>required</th></tr> 67 * <tr class="odd"><th>src</th><th>String</th><th>The src attribute of the video tag. ext://[externalInput]:[portNum]. (eg: "ext://hdmi:1") </th><th>required</th></tr> 68 * </tbody> 69 * </table> 70 * @return <p>None.</p> 71 * @example 72 * // HTML code 73 * < body onload="onLoad()" > 74 * < div id = "videoDiv" style="width:640px; height:380px" > 75 * < /div > 76 * < /body > 77 * 78 * // Javascript code 79 * function init () { 80 * } 81 * 82 * function onLoad() { 83 * var options = { 84 * divId : "videoDiv", // It should be matched to div tag name in an html page. 85 * videoId : "broadcastvideo", 86 * callback : init, 87 * src : "ext://hdmi:1" 88 * }; 89 * 90 * function successCb() { 91 * // Do something 92 * } 93 * 94 * function failureCb(cbObject) { 95 * var errorCode = cbObject.errorCode; 96 * var errorText = cbObject.errorText; 97 * console.log ("Error Code [" + errorCode + "]: " + errorText); 98 * } 99 * 100 * var inputSource = new InputSource(); 101 * inputSource.initialize(successCb, failureCb, options); 102 * } 103 * @since 1.0 104 * @since 1.1 options.isLastChannel removed 105 */ 106 InputSource.prototype.initialize = function (successCallback, errorCallback, options) { 107 108 log("initialize: " + JSON.stringify(options)); 109 110 // bound check 111 if (options.divId === undefined || typeof options.divId !== 'string' || options.divId === null || options.divId.length <= 0 || 112 options.videoId === undefined || typeof options.videoId !== 'string' || options.videoId === null || options.videoId.length <= 0 || 113 options.callback === undefined || typeof options.callback !== 'function' || 114 options.src === undefined || typeof options.src !== 'string' || options.src === null || options.src.length <= 0 ) { 115 116 if (typeof errorCallback === 'function') { 117 var result = {}; 118 checkErrorCodeNText(result, "II", "InputSource.initialize returns failure. invalid parameters."); 119 errorCallback(result); 120 } 121 122 return; 123 } 124 125 convertInputSource(options.src, function success(inputSource) { 126 // success callback 127 options.src = inputSource; 128 broadcast = new Broadcast(); // jshint ignore:line 129 130 log("initialize: converted " + JSON.stringify(options)); 131 132 broadcast.initialize(successCallback, errorCallback, options); 133 134 }, function failure(cbObj) { 135 // failure callback 136 log("initialize: failure " + JSON.stringify(cbObj)); 137 138 if (typeof errorCallback === 'function') { 139 var result = {}; 140 checkErrorCodeNText(result, "II", "InputSource.initialize returns failure. invalid parameters."); 141 errorCallback(result); 142 } 143 }); 144 145 log("initialize: Done"); 146 147 }; 148 149 /** 150 * Changes the input source that viewer is currently watching. This method is used to change to other input source after initializing the inputSource object (creating video tag. etc.) using InputSource.initialize() method. 151 * Available input types and number of input sources for each input types may differ model by model. <br> 152 * For example, LS55A model has the following inputs : (HDMI1, HDMI2, DP, DVI) or SM5B model has the following inputs : (HDMI1, DP, DVI, RGB, OPS) 153 * @class InputSource 154 * @param {Function} successCallback success callback function. 155 * @param {Function} errorCallback failure callback function. 156 * @param {Object} options 157 * <div align=left> 158 * <table class="hcap_spec" width=400> 159 * <thead><tr><th>Property</th><th>Type</th><th>Description</th><th>Required</th></tr></thead> 160 * <tbody> 161 * <tr><th>src</th><th>String</th><th>Define the src attribute of video tag. "ext://[externalinput]:[portNum]" (eg, "ext://dp:1")</a> </th><th>required</th></tr> 162 * </tbody> 163 * </table> 164 * </div> 165 * @return <p>If the method is successfully executed, success callback function is called without a parameter.</br> 166 * If an error occurs, failure callback function is called with failure callback object as a parameter.</p> 167 * @example 168 * // Javascript code 169 * function changeInputSource () { 170 * var options = { 171 * src : "ext://hdmi:1" 172 * }; 173 * 174 * function successCb() { 175 * // Do something 176 * } 177 * 178 * function failureCb(cbObject) { 179 * var errorCode = cbObject.errorCode; 180 * var errorText = cbObject.errorText; 181 * console.log ("Error Code [" + errorCode + "]: " + errorText); 182 * } 183 * 184 * var inputSource = new InputSource(); 185 * inputSource.changeInputSource(successCb, failureCb, options); 186 * } 187 * @since 1.0 188 * @see <a href="InputSource%23getInputSourceStatus.html">InputSource.getInputSourceStatus()</a><br> 189 */ 190 InputSource.prototype.changeInputSource = function (successCallback, errorCallback, options) { 191 192 // bound check 193 if ( options.src === undefined || typeof options.src !== 'string' || options.src === null || options.src.length <= 0) { 194 195 if (typeof errorCallback === 'function') { 196 var result = {}; 197 checkErrorCodeNText(result, "ICIS", "InputSource.changeInputSource returns failure. invalid argument. "); 198 errorCallback(result); 199 } 200 201 return; 202 } 203 204 //TODO; deprecated changeInput in broadcast.js 205 206 log("changeInputSource: " + JSON.stringify(options)); 207 208 convertInputSource(options.src, function success (inputSource) { 209 // success callback 210 options.src = inputSource; 211 212 if (broadcast.setInput(options)) { 213 log("changeInputSource: On Success"); 214 successCallback(); 215 } else { 216 var result = {}; 217 log("changeInputSource: On Failure"); 218 checkErrorCodeNText(result, "ICIS", "InputSource.changeInputSource returns failure."); 219 errorCallback(result); 220 } 221 222 }, function failure(cbObj) { 223 // failure callback 224 log("changeInputSource: failure " + JSON.stringify(cbObj)); 225 226 if (typeof errorCallback === 'function') { 227 var result = {}; 228 checkErrorCodeNText(result, "ICIS", "InputSource.changeInputSource returns failure. invalid argument. "); 229 errorCallback(result); 230 } 231 }); 232 233 log("changeInputSource: Done"); 234 }; 235 236 /** 237 * Gets current input source status. 238 * @class InputSource 239 * @param {Function} successCallback success callback function. 240 * @param {Function} errorCallback failure callback function. 241 * @return {Object} array of inputSource object, signal state and current input source. 242 * <div align=left> 243 * <table class="hcap_spec" width=400> 244 * <thead><tr><th>Property</th><th>Type</th><th>Description</th></tr></thead> 245 * <tbody> 246 * <tr><th>inputSourceList[]</th><th>Array</th><th>An array with input source object.</th></tr> 247 * <tr class="odd"><th>inputSourceList[].inputPort</th><th>String</th><th>Input label (ext://hdmi:1, ext://hdmi:2, ext://dp:1, ext://dvi:1 etc) </th></tr> 248 * <tr><th>currentSignalState</th><th>String</th><th>Status and change information of the input that is currently selected.<br>"good" : good signal, "bad" : poor signal, "unknown" : can't indicate a signal status </th></tr> 249 * <tr class="odd"><th>currentInputSource</th><th>String</th><th>Input source that the viewer is currently watching.<br>input label </th></tr> 250 * </tbody> 251 * </table> 252 * </div> 253 * 254 * @example 255 * // Javascript code 256 * function getInputSourceStatus () { 257 * function successCb(cbObject) { 258 * var inputSourceList = cbObject.inputSourceList; 259 * for ( var i = 0; i < inputSourceList.length; i++) { 260 * console.log("inputSourceList[" + i + "] : " + JSON.stringify(inputSourceList[i])); 261 * console.log("inputSourceList[" + i + "].inputPort : " + inputSourceList[i].inputPort); 262 * } 263 * console.log("currentInputSource : " + cbObject.currentInputSource); 264 * console.log("currentSignalState : " + cbObject.currentSignalState); 265 * // Do something 266 * } 267 * 268 * function failureCb(cbObject) { 269 * var errorCode = cbObject.errorCode; 270 * var errorText = cbObject.errorText; 271 * console.log ("Error Code [" + errorCode + "]: " + errorText); 272 * } 273 * 274 * var inputSource = new InputSource(); 275 * inputSource.getInputSourceStatus(successCb, failureCb); 276 * } 277 * @since 1.0 278 * @see <a href="InputSource%23changeInputSource.html">InputSource.changeInputSource()</a><br> 279 */ 280 InputSource.prototype.getInputSourceStatus = function (successCallback, errorCallback) { 281 282 log("getInputSourceStatus: "); 283 284 285 286 service.Request("luna://com.webos.service.eim/", { 287 method : "getAllInputStatus", 288 onSuccess : function(result) { 289 log("getInputSourceStatus: On Success"); 290 291 if (result.returnValue === true) { 292 if (successCallback && typeof successCallback === 'function') { 293 294 checkPlatformVersion(function(ver){ 295 296 log("convertInputSource: " + JSON.stringify(result.totalCount)); 297 log("convertInputSource: " + JSON.stringify(result.devices)); 298 log("version: " + ver); 299 300 301 var cbObj = {}; 302 var inputList = new Array(result.totalCount); 303 var convertList = new Array(result.totalCount); 304 305 for (var i=0; i<inputList.length; i++) { 306 inputList[i] = {}; 307 inputList[i].inputPort = parseInputSource(result.devices[i].label); 308 309 310 switch (ver) { 311 case 1 : 312 // fixed input for hdmi:3, hdmi:4. requested by youngjun.lee 313 var tempInputSource = result.devices[i].id.split("_"); 314 inputList[i].inputPort = 'ext://' + tempInputSource[0].toLowerCase() + ':' + tempInputSource[1]; 315 if (inputList[i].inputPort === 'ext://hdmi:3') { 316 inputList[i].inputPort = 'ext://dp:1'; 317 } else if (inputList[i].inputPort === 'ext://hdmi:4') { 318 inputList[i].inputPort = 'ext://dvi:1'; 319 } 320 // end 321 322 break; 323 case 2 : 324 325 var tempInputSource = result.devices[i].id.split("_"); 326 inputList[i].inputPort = 'ext://' + tempInputSource[0].toLowerCase() + ':' + tempInputSource[1]; 327 if (inputList[i].inputPort === 'ext://hdmi:3') { 328 inputList[i].inputPort = 'ext://dp:1'; 329 } else if (inputList[i].inputPort === 'ext://hdmi:2') { 330 inputList[i].inputPort = 'ext://dvi:1'; 331 } else if (inputList[i].inputPort === 'ext://hdmi:4') { 332 inputList[i].inputPort = 'ext://ops:1'; 333 } 334 break; 335 default : 336 break; 337 } 338 339 convertList[i] = {}; 340 convertList[i].inputPort = inputList[i].inputPort; 341 convertList[i].id = result.devices[i].id; 342 } 343 344 cbObj.inputSourceList = inputList; 345 346 service.Request("luna://com.webos.service.eim/", { 347 method : "getCurrentInput", 348 parameters : {}, 349 onSuccess : function(result) { 350 log("InputSource.getInputSourceStatus: On Success 3"); 351 352 if (result.returnValue === true) { 353 354 if (successCallback && typeof successCallback === 'function') { 355 356 cbObj.currentInputSource = {}; 357 358 for (var i=0; i<convertList.length; i++) { 359 if (convertList[i].id === result.mainInputSourceId) { 360 cbObj.currentInputSource = convertList[i].inputPort; 361 break; 362 } 363 } 364 365 cbObj.currentSignalState = "unknown"; 366 367 if (broadcast !== null) { 368 log("InputSource.getInputSourceStatus : broadcast is not null"); 369 370 broadcast.getSignalStatus(function successCb(cbObject) { 371 372 cbObj.currentSignalState = cbObject.videoSignalState; 373 log("InputSource.getInputSourceStatus: On Success 2"); 374 375 if (successCallback && typeof successCallback === 'function') { 376 log("getInputSourceStatus: On Success" + JSON.stringify(cbObj)); 377 successCallback(cbObj); 378 return; 379 } 380 381 }, function failureCb() { 382 383 log("InputSource.getInputSourceStatus : signal state is fail."); 384 if (successCallback && typeof successCallback === 'function') { 385 log("getInputSourceStatus: On Success" + JSON.stringify(cbObj)); 386 successCallback(cbObj); 387 return; 388 } 389 }); 390 391 } else { 392 393 log("InputSource.getInputSourceStatus : it does not initialize."); 394 if (successCallback && typeof successCallback === 'function') { 395 log("getInputSourceStatus: On Success" + JSON.stringify(cbObj)); 396 successCallback(cbObj); 397 return; 398 } 399 } 400 } 401 } 402 }, 403 onFailure : function(result) { 404 log("InputSource.getInputSourceStatus: On Failure 2"); 405 delete result.returnValue; 406 if (errorCallback && typeof errorCallback === 'function') { 407 checkErrorCodeNText(result, "IGISS", "InputSource.getInputSourceStatus returns failure."); 408 errorCallback(result); 409 return; 410 } 411 } 412 }); 413 }); // check version 414 } // if (successCallback && typeof successCallback === 'function') { 415 } // if (result.returnValue === true) { 416 }, 417 onFailure : function(result) { 418 log("getInputSourceStatus: On Failure"); 419 delete result.returnValue; 420 if (errorCallback && typeof errorCallback === 'function') { 421 checkErrorCodeNText(result, "IGISS", "InputSource.changeInputSource returns failure on gathering input list."); 422 errorCallback(result); 423 } 424 } 425 }); 426 427 log("InputSource.getInputSourceStatus Done"); 428 429 }; 430 431 function parseInputSource(str) { 432 433 var index = 1; 434 var length = str.length; 435 436 if (!isNaN(parseInt(str.charAt(length-1), 10))) { 437 // has number 438 index = str.charAt(length-1); 439 length--; 440 } 441 442 str = str.substring(0, length) +":"+ index; 443 str = "ext://" + str.toLowerCase(); 444 445 return str; 446 } 447 448 var version = null; 449 function checkPlatformVersion(cb) { 450 451 if (version === null) { 452 453 service.Request('luna://com.webos.service.tv.systemproperty', { 454 method: 'getSystemInfo', 455 parameters: { 456 keys: ["sdkVersion"] 457 }, 458 onSuccess: function(result) { 459 log("getPlatformInfo: onSuccess"); 460 461 var temp = result.sdkVersion.split('.'); 462 if (temp.length >= 1 && temp[0] === '1') { 463 version = 1; 464 } else if (temp.length >= 1 && temp[0] === '2') { 465 version = 2; 466 } else { 467 version = 0; 468 } 469 470 delete result.returnValue; 471 472 cb(version); 473 474 }, 475 onFailure: function(error) { 476 log("getPlatformInfo: onFailure"); 477 delete error.returnValue; 478 version = 0; 479 480 cb(version); 481 } 482 }); 483 484 } else { 485 cb(version); 486 } 487 } 488 489 function convertInputSource(inputSource, successCallback, errorCallback) { 490 491 service.Request("luna://com.webos.service.eim/", { 492 method : "getAllInputStatus", 493 onSuccess : function(result) { 494 log("convertInputSource: On Success " + inputSource); 495 496 if (result.returnValue === true) { 497 if (successCallback && typeof successCallback === 'function') { 498 var inputList = new Array(result.totalCount); 499 500 checkPlatformVersion(function(ver){ 501 502 log("convertInputSource: " + JSON.stringify(result.totalCount)); 503 log("convertInputSource: " + JSON.stringify(result.devices)); 504 log("version: " + ver); 505 506 switch (ver) { 507 case 1 : 508 // fixed input for hdmi:3, hdmi:4. requested by youngjun.lee 509 if (inputSource === 'ext://dp:1') { 510 inputSource = 'ext://hdmi:3'; 511 } else if (inputSource === 'ext://dvi:1') { 512 inputSource = 'ext://hdmi:4'; 513 } 514 // end 515 break; 516 case 2 : 517 if (inputSource === 'ext://dp:1') { 518 inputSource = 'ext://hdmi:3'; 519 } else if (inputSource === 'ext://dvi:1') { 520 inputSource = 'ext://hdmi:2'; 521 } else if (inputSource === 'ext://ops:1') { 522 inputSource = 'ext://hdmi:4'; 523 } 524 break; 525 default : 526 break; 527 } 528 529 for (var i=0; i<inputList.length; i++) { 530 inputList[i] = {}; 531 inputList[i].inputPort = parseInputSource(result.devices[i].label); 532 var tempInputSource = result.devices[i].id.split("_"); 533 inputList[i].id = 'ext://' + tempInputSource[0].toLowerCase() + ':' + tempInputSource[1]; 534 535 if (inputSource === inputList[i].id) { 536 // ok 537 log("convertInputSource: On Success ok " + inputSource); 538 successCallback(inputSource); 539 return; 540 } 541 } 542 543 for (var j=0; j<inputList.length; j++) { 544 if (inputSource === inputList[j].inputPort) { 545 // convert source 546 inputSource = inputList[j].id; 547 log("convertInputSource: On Success converted " + inputSource); 548 successCallback(inputSource); 549 return; 550 } 551 } 552 553 log("convertInputSource: On Failure " + inputSource); 554 var errResult = {}; 555 checkErrorCodeNText(errResult, "IGISS", "convertInputSource. It does not support inputsource type."); 556 errorCallback(errResult); 557 558 559 }); 560 561 } 562 } 563 }, 564 onFailure : function(result) { 565 log("convertInputSource: On Failure"); 566 delete result.returnValue; 567 if (errorCallback && typeof errorCallback === 'function') { 568 checkErrorCodeNText(result, "IGISS", "convertInputSource returns failure on gathering input list."); 569 errorCallback(result); 570 } 571 } 572 }); 573 574 575 } 576 577 module.exports = InputSource; 578 }); 579 580 InputSource = cordova.require('cordova/plugin/inputSource'); // jshint ignore:line 581 582 583 584 585