001package Torello.Browser; 002 003import java.util.*; 004import javax.json.*; 005import javax.json.stream.*; 006import java.io.*; 007 008import java.lang.reflect.Method; 009import java.lang.reflect.Parameter; 010import java.util.function.Function; 011 012import Torello.Java.Additional.*; 013import Torello.Java.JSON.*; 014 015import static Torello.Java.JSON.JFlag.*; 016 017import Torello.Java.StrCmpr; 018import Torello.JavaDoc.StaticFunctional; 019import Torello.JavaDoc.JDHeaderBackgroundImg; 020import Torello.JavaDoc.Excuse; 021 022/** 023 * <SPAN CLASS=COPIEDJDK><B>A domain for interacting with Cast, Presentation API, and Remote Playback API 024 * functionalities.</B></SPAN> 025 * 026 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE> 027 */ 028@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION}) 029@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE") 030public class Cast 031{ 032 // ******************************************************************************************** 033 // ******************************************************************************************** 034 // Class Header Stuff 035 // ******************************************************************************************** 036 // ******************************************************************************************** 037 038 039 // No Pubic Constructors 040 private Cast () { } 041 042 // These two Vector's are used by all the "Methods" exported by this class. java.lang.reflect 043 // is used to generate the JSON String's. It saves thousands of lines of Auto-Generated Code. 044 private static final Map<String, Vector<String>> parameterNames = new HashMap<>(); 045 private static final Map<String, Vector<Class<?>>> parameterTypes = new HashMap<>(); 046 047 // Some Methods do not take any parameters - for instance all the "enable()" and "disable()" 048 // I simply could not get ride of RAW-TYPES and UNCHECKED warnings... so there are now, 049 // offically, two empty-vectors. One for String's, and the other for Classes. 050 051 private static final Vector<String> EMPTY_VEC_STR = new Vector<>(); 052 private static final Vector<Class<?>> EMPTY_VEC_CLASS = new Vector<>(); 053 054 static 055 { 056 for (Method m : Cast.class.getMethods()) 057 { 058 // This doesn't work! The parameter names are all "arg0" ... "argN" 059 // It works for java.lang.reflect.Field, BUT NOT java.lang.reflect.Parameter! 060 // 061 // Vector<String> parameterNamesList = new Vector<>(); -- NOPE! 062 063 Vector<Class<?>> parameterTypesList = new Vector<>(); 064 065 for (Parameter p : m.getParameters()) parameterTypesList.add(p.getType()); 066 067 parameterTypes.put( 068 m.getName(), 069 (parameterTypesList.size() > 0) ? parameterTypesList : EMPTY_VEC_CLASS 070 ); 071 } 072 } 073 074 static 075 { 076 Vector<String> v = null; 077 078 v = new Vector<String>(1); 079 parameterNames.put("enable", v); 080 Collections.addAll(v, new String[] 081 { "presentationUrl", }); 082 083 parameterNames.put("disable", EMPTY_VEC_STR); 084 085 v = new Vector<String>(1); 086 parameterNames.put("setSinkToUse", v); 087 Collections.addAll(v, new String[] 088 { "sinkName", }); 089 090 v = new Vector<String>(1); 091 parameterNames.put("startTabMirroring", v); 092 Collections.addAll(v, new String[] 093 { "sinkName", }); 094 095 v = new Vector<String>(1); 096 parameterNames.put("stopCasting", v); 097 Collections.addAll(v, new String[] 098 { "sinkName", }); 099 } 100 101 102 // ******************************************************************************************** 103 // ******************************************************************************************** 104 // Types - Static Inner Classes 105 // ******************************************************************************************** 106 // ******************************************************************************************** 107 108 /** <CODE>[No Description Provided by Google]</CODE> */ 109 public static class Sink 110 extends BaseType 111 implements java.io.Serializable 112 { 113 /** For Object Serialization. java.io.Serializable */ 114 protected static final long serialVersionUID = 1; 115 116 public boolean[] optionals() 117 { return new boolean[] { false, false, true, }; } 118 119 /** <CODE>[No Description Provided by Google]</CODE> */ 120 public final String name; 121 122 /** <CODE>[No Description Provided by Google]</CODE> */ 123 public final String id; 124 125 /** 126 * Text describing the current session. Present only if there is an active 127 * session on the sink. 128 * <BR /> 129 * <BR /><B>OPTIONAL</B> 130 */ 131 public final String session; 132 133 /** 134 * Constructor 135 * 136 * @param name - 137 * 138 * @param id - 139 * 140 * @param session 141 * Text describing the current session. Present only if there is an active 142 * session on the sink. 143 * <BR /><B>OPTIONAL</B> 144 */ 145 public Sink(String name, String id, String session) 146 { 147 // Exception-Check(s) to ensure that if any parameters which are not declared as 148 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 149 150 if (name == null) BRDPC.throwNPE("name"); 151 if (id == null) BRDPC.throwNPE("id"); 152 153 this.name = name; 154 this.id = id; 155 this.session = session; 156 } 157 158 /** 159 * JSON Object Constructor 160 * @param jo A Json-Object having data about an instance of {@code 'Sink'}. 161 */ 162 public Sink (JsonObject jo) 163 { 164 this.name = ReadJSON.getString(jo, "name", false, true); 165 this.id = ReadJSON.getString(jo, "id", false, true); 166 this.session = ReadJSON.getString(jo, "session", true, false); 167 } 168 169 170 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 171 public boolean equals(Object other) 172 { 173 if (other == null) return false; 174 if (other.getClass() != this.getClass()) return false; 175 176 Sink o = (Sink) other; 177 178 return 179 Objects.equals(this.name, o.name) 180 && Objects.equals(this.id, o.id) 181 && Objects.equals(this.session, o.session); 182 } 183 184 /** Generates a Hash-Code for {@code 'this'} instance */ 185 public int hashCode() 186 { 187 return 188 Objects.hashCode(this.name) 189 + Objects.hashCode(this.id) 190 + Objects.hashCode(this.session); 191 } 192 } 193 194 /** 195 * This is fired whenever the list of available sinks changes. A sink is a 196 * device or a software surface that you can cast to. 197 */ 198 public static class sinksUpdated 199 extends BrowserEvent 200 implements java.io.Serializable 201 { 202 /** For Object Serialization. java.io.Serializable */ 203 protected static final long serialVersionUID = 1; 204 205 public boolean[] optionals() 206 { return new boolean[] { false, }; } 207 208 /** <CODE>[No Description Provided by Google]</CODE> */ 209 public final Cast.Sink[] sinks; 210 211 /** 212 * Constructor 213 * 214 * @param sinks - 215 */ 216 public sinksUpdated(Cast.Sink[] sinks) 217 { 218 super("Cast", "sinksUpdated", 1); 219 220 // Exception-Check(s) to ensure that if any parameters which are not declared as 221 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 222 223 if (sinks == null) BRDPC.throwNPE("sinks"); 224 225 this.sinks = sinks; 226 } 227 228 /** 229 * JSON Object Constructor 230 * @param jo A Json-Object having data about an instance of {@code 'sinksUpdated'}. 231 */ 232 public sinksUpdated (JsonObject jo) 233 { 234 super("Cast", "sinksUpdated", 1); 235 236 this.sinks = (jo.getJsonArray("sinks") == null) 237 ? null 238 : ReadArrJSON.DimN.objArr(jo.getJsonArray("sinks"), null, 0, Cast.Sink[].class); 239 240 } 241 242 243 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 244 public boolean equals(Object other) 245 { 246 if (other == null) return false; 247 if (other.getClass() != this.getClass()) return false; 248 249 sinksUpdated o = (sinksUpdated) other; 250 251 return 252 Arrays.deepEquals(this.sinks, o.sinks); 253 } 254 255 /** Generates a Hash-Code for {@code 'this'} instance */ 256 public int hashCode() 257 { 258 return 259 Arrays.deepHashCode(this.sinks); 260 } 261 } 262 263 /** 264 * This is fired whenever the outstanding issue/error message changes. 265 * |issueMessage| is empty if there is no issue. 266 */ 267 public static class issueUpdated 268 extends BrowserEvent 269 implements java.io.Serializable 270 { 271 /** For Object Serialization. java.io.Serializable */ 272 protected static final long serialVersionUID = 1; 273 274 public boolean[] optionals() 275 { return new boolean[] { false, }; } 276 277 /** <CODE>[No Description Provided by Google]</CODE> */ 278 public final String issueMessage; 279 280 /** 281 * Constructor 282 * 283 * @param issueMessage - 284 */ 285 public issueUpdated(String issueMessage) 286 { 287 super("Cast", "issueUpdated", 1); 288 289 // Exception-Check(s) to ensure that if any parameters which are not declared as 290 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 291 292 if (issueMessage == null) BRDPC.throwNPE("issueMessage"); 293 294 this.issueMessage = issueMessage; 295 } 296 297 /** 298 * JSON Object Constructor 299 * @param jo A Json-Object having data about an instance of {@code 'issueUpdated'}. 300 */ 301 public issueUpdated (JsonObject jo) 302 { 303 super("Cast", "issueUpdated", 1); 304 305 this.issueMessage = ReadJSON.getString(jo, "issueMessage", false, true); 306 } 307 308 309 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 310 public boolean equals(Object other) 311 { 312 if (other == null) return false; 313 if (other.getClass() != this.getClass()) return false; 314 315 issueUpdated o = (issueUpdated) other; 316 317 return 318 Objects.equals(this.issueMessage, o.issueMessage); 319 } 320 321 /** Generates a Hash-Code for {@code 'this'} instance */ 322 public int hashCode() 323 { 324 return 325 Objects.hashCode(this.issueMessage); 326 } 327 } 328 329 330 // Counter for keeping the WebSocket Request ID's distinct. 331 private static int counter = 1; 332 333 /** 334 * Starts observing for sinks that can be used for tab mirroring, and if set, 335 * sinks compatible with |presentationUrl| as well. When sinks are found, a 336 * |sinksUpdated| event is fired. 337 * Also starts observing for issue messages. When an issue is added or removed, 338 * an |issueUpdated| event is fired. 339 * 340 * @param presentationUrl - 341 * <BR /><B>OPTIONAL</B> 342 * 343 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 344 * {@link Ret0}></CODE> 345 * 346 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 347 * browser receives the invocation-request. 348 * 349 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 350 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 351 * {@code >} to ensure the Browser Function has run to completion. 352 */ 353 public static Script<String, JsonObject, Ret0> enable(String presentationUrl) 354 { 355 final int webSocketID = 14000000 + counter++; 356 final boolean[] optionals = { true, }; 357 358 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 359 String requestJSON = WriteJSON.get( 360 parameterTypes.get("enable"), 361 parameterNames.get("enable"), 362 optionals, webSocketID, 363 "Cast.enable", 364 presentationUrl 365 ); 366 367 // This Remote Command does not have a Return-Value. 368 return new Script<> 369 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 370 } 371 372 /** 373 * Stops observing for sinks and issues. 374 * 375 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 376 * {@link Ret0}></CODE> 377 * 378 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 379 * browser receives the invocation-request. 380 * 381 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 382 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 383 * {@code >} to ensure the Browser Function has run to completion. 384 */ 385 public static Script<String, JsonObject, Ret0> disable() 386 { 387 final int webSocketID = 14001000 + counter++; 388 final boolean[] optionals = new boolean[0]; 389 390 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 391 String requestJSON = WriteJSON.get( 392 parameterTypes.get("disable"), 393 parameterNames.get("disable"), 394 optionals, webSocketID, 395 "Cast.disable" 396 ); 397 398 // This Remote Command does not have a Return-Value. 399 return new Script<> 400 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 401 } 402 403 /** 404 * Sets a sink to be used when the web page requests the browser to choose a 405 * sink via Presentation API, Remote Playback API, or Cast SDK. 406 * 407 * @param sinkName - 408 * 409 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 410 * {@link Ret0}></CODE> 411 * 412 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 413 * browser receives the invocation-request. 414 * 415 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 416 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 417 * {@code >} to ensure the Browser Function has run to completion. 418 */ 419 public static Script<String, JsonObject, Ret0> setSinkToUse(String sinkName) 420 { 421 // Exception-Check(s) to ensure that if any parameters which are not declared as 422 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 423 424 if (sinkName == null) BRDPC.throwNPE("sinkName"); 425 426 final int webSocketID = 14002000 + counter++; 427 final boolean[] optionals = { false, }; 428 429 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 430 String requestJSON = WriteJSON.get( 431 parameterTypes.get("setSinkToUse"), 432 parameterNames.get("setSinkToUse"), 433 optionals, webSocketID, 434 "Cast.setSinkToUse", 435 sinkName 436 ); 437 438 // This Remote Command does not have a Return-Value. 439 return new Script<> 440 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 441 } 442 443 /** 444 * Starts mirroring the tab to the sink. 445 * 446 * @param sinkName - 447 * 448 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 449 * {@link Ret0}></CODE> 450 * 451 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 452 * browser receives the invocation-request. 453 * 454 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 455 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 456 * {@code >} to ensure the Browser Function has run to completion. 457 */ 458 public static Script<String, JsonObject, Ret0> startTabMirroring(String sinkName) 459 { 460 // Exception-Check(s) to ensure that if any parameters which are not declared as 461 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 462 463 if (sinkName == null) BRDPC.throwNPE("sinkName"); 464 465 final int webSocketID = 14003000 + counter++; 466 final boolean[] optionals = { false, }; 467 468 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 469 String requestJSON = WriteJSON.get( 470 parameterTypes.get("startTabMirroring"), 471 parameterNames.get("startTabMirroring"), 472 optionals, webSocketID, 473 "Cast.startTabMirroring", 474 sinkName 475 ); 476 477 // This Remote Command does not have a Return-Value. 478 return new Script<> 479 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 480 } 481 482 /** 483 * Stops the active Cast session on the sink. 484 * 485 * @param sinkName - 486 * 487 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 488 * {@link Ret0}></CODE> 489 * 490 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 491 * browser receives the invocation-request. 492 * 493 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 494 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 495 * {@code >} to ensure the Browser Function has run to completion. 496 */ 497 public static Script<String, JsonObject, Ret0> stopCasting(String sinkName) 498 { 499 // Exception-Check(s) to ensure that if any parameters which are not declared as 500 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 501 502 if (sinkName == null) BRDPC.throwNPE("sinkName"); 503 504 final int webSocketID = 14004000 + counter++; 505 final boolean[] optionals = { false, }; 506 507 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 508 String requestJSON = WriteJSON.get( 509 parameterTypes.get("stopCasting"), 510 parameterNames.get("stopCasting"), 511 optionals, webSocketID, 512 "Cast.stopCasting", 513 sinkName 514 ); 515 516 // This Remote Command does not have a Return-Value. 517 return new Script<> 518 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 519 } 520 521}