Skip to content

Added GodDragon 1.0.16 release #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 383 commits into
base: master
Choose a base branch
from
Open

Conversation

lot5000
Copy link
Owner

@lot5000 lot5000 commented Nov 2, 2018

No description provided.

@GodDragoner GodDragoner force-pushed the master branch 2 times, most recently from b7ae241 to 4b72254 Compare March 1, 2019 19:36
GodDragoner and others added 28 commits March 19, 2019 01:02
# Conflicts:
#	src/me/goddragon/teaseai/gui/settings/URLMediaSettings.java
# Conflicts:
#	src/me/goddragon/teaseai/gui/settings/URLMediaSettings.java
Conflicts:
	src/me/goddragon/teaseai/gui/settings/URLMediaSettings.java
Conflicts:
	src/me/goddragon/teaseai/gui/settings/URLMediaSettings.java
FrozenWolf4887 and others added 30 commits January 21, 2021 21:55
This is actually a major refactor of the processing of tags within chat
messages to reduce the complexity and increase the ease of
extensibility.

Due to the extensive change, the following personality script has been
used to verify the changes:

"
function testCategory(categoryName, message) {
    sendMessage("[* TEST CATEGORY: " + categoryName + " *]", 0, false);
}
function test(testName, message) {
    sendMessage("TEST: " + testName, 0, false);
    sendMessage(message, 0, false);
}
lockImages();

testCategory("General");

test("Unformatted", "Mary had a little lamb");
test("Weight1 (w)", "<w=EXTRA_LIGHT>Extra light</w> Normal <w=EXTRA_BOLD>Extra bold</w>");
test("Weight2 (weight)", "<weight=EXTRA_LIGHT>Extra light</weight> Normal <weight=EXTRA_BOLD>Extra bold</weight>");
test("Weight3 (fontweight)", "<fontweight=EXTRA_LIGHT>Extra light</fontweight> Normal <fontweight=EXTRA_BOLD>Extra bold</fontweight>");
test("Font1 (f)", "<f=FreeMono>Free Mono</f> <f=FreeSerif>Free Serif</f> Normal");
test("Font2 (font)", "<font=FreeMono>Free Mono</font> <font=FreeSerif>Free Serif</font> Normal");
test("Size1 (fs)", "<fs=20>Massive</fs> Normal <fs=8>Tiny</fs>");
test("Size2 (fontsize)", "<fontsize=20>Massive</fontsize> Normal <fontsize=8>Tiny</fontsize>");
test("Underline1 (u)", "<u>Underlined</u>");
test("Underline2 (under)", "<under>Underlined</under> Normal");
test("Underline3 (underline)", "<underline>Underlined</underline> Normal");
test("Strikethrough (s)", "<s>Strikethrough</s> Normal");
test("Strikethrough (strike)", "<strike>Strikethrough</strike> Normal");
test("Strikethrough (strikethrough)", "<strikethrough>Strikethrough</strikethrough> Normal");
test("Color1 (c=name)", "<c=RED>Red</c> Normal <c=BLUE>Blue</c> <c=GREEN>Green</c>");
test("Color2 (col=name)", "<col=RED>Red</col> Normal <col=BLUE>Blue</col> <col=GREEN>Green</col>");
test("Color3 (color=name)", "<color=RED>Red</color> Normal <color=BLUE>Blue</color> <color=GREEN>Green</color>");
test("Color4 (c=0xnnnnnnnn)", "<c=0x800000ff>Red</color> Normal <c=0x000080ff>Blue</c> <c=0x008000ff>Green</c>");
test("Color5 (c=#nnnnnn)", "<c=#800000>Red</color> Normal <c=#000080>Blue</c> <c=#008000>Green</c>");
test("Color6 (c=rgb(n,n,n))", "<c=rgb(128,0,0)>Red</color> Normal <c=rgb(0,0,128)>Blue</c> <c=rgb(0,128,0)>Green</c>");
test("Color7 (c=rgb(n%,n%,n%))", "<c=rgb(50%,0,0)>Red</color> Normal <c=rgb(0,0,50%)>Blue</c> <c=rgb(0,50%,0)>Green</c>");
test("Italics1", "Hello <i>italics</i> Normal");
test("Italics2", "Hello <italics>italics</italics> Normal");
test("Bold1", "<b>Bold</b> Normal");
test("Bold2", "<bold>Bold</bold> Normal");
test("Image1 (img)", "Mary <img=Images/Spicy/Emotes/heart.gif> her little lamb");
test("Image2 (image)", "Mary <image=Images/Spicy/Emotes/heart.gif> her little lamb");
test("Image3 (picture)", "Mary <picture=Images/Spicy/Emotes/heart.gif> her little lamb");
test("Image4 (gif)", "Mary <gif=Images/Spicy/Emotes/heart.gif> her little lamb");
test("Image5 (img=animation)", "Mary <img=Images/Spicy/Emotes/banana.gif> her little lamb");
test("Image6 (img=jpg)", "Mary <img=Images/Spicy/Toys/spiderGag.jpg> her little lamb");

testCategory("Overlapping");

test("Bold/Italics", "<b>Bold <i>Italic and bold </b>Italic </i>Normal");
test("Bold/Underline", "<b>Bold <u>Underlined and bold </b>Underlined </u>Normal");

testCategory("Stacked");

test("Italics", "<i><i>Italic</i> Still italic </i>Normal");
test("Bold", "<b><b>Bold</b> Still bold </b>Normal");
test("Color", "Normal <c=BLUE>Blue <c=GREEN>Green <c=RED>Red </c>Green </c>Blue </c>Normal");

testCategory("Parsing");

test("Escaped tags", "Sad :‑\\< and angry \\>:[");
test("Closing only", "Did you know that 5 > 4?");
test("Uncapped", "<color=BLUE");
test("Unmatchable", "<@color=BLUE>");

testCategory("Unknown");

test("Unrecognised", "Some <mango> fruit </apple>");

testCategory("Missing args");

test("Weight", "<w>Extra light</w> Normal");
test("Font", "<f>Free Mono</f> Normal");
test("Size", "<fs>Massive</fs> Normal");
test("Color", "<c>Red</c> Normal");
test("Image", "Mary <img> her little lamb");

testCategory("Redundant args");

test("Underline", "<u=foo>Underlined</u>");
test("Italics", "Hello<i=bar>italics</i> Normal");
test("Bold", "<b=zip>Bold</b> Normal");

testCategory("Missing images");

test("Image1 (img=gif)", "<img=Images/does-not-exist.gif>");
test("Image2 (img=jpg)", "<img=Images/does-not-exist.jpg>");

sleep(300);
"
If there were no urls or folders, an index exception was being thrown on
urls.get().
Since null parameters are typeless, reflection is unable to match any
defined handler.  Previously it would crash on attempting to determine the
type of null.  Now it treats a null parameter as a void type.
This will round down the floating point value and delegate.

Tested with the following script:
"
// showImage(String)
const file1 = showImage('Images/Spicy/Assistant/1/124259409_004_122_372lo.jpg');
sleep(1);
const file2 = showImage('Images/Spicy/Assistant/1/124269531_087_122_237lo.jpg', 2);
const file3 = showImage('Images/Spicy/Assistant/1/140222767_019_122_398lo.jpg', 3.5);

// showImage(File)
showImage(file1);
sleep(1);
showImage(file2, 2);
showImage(file3, 3.5);

// showImage(MediaURL)
const MediaURL = Java.type('me.goddragon.teaseai.api.media.MediaURL');
const MediaType = Java.type('me.goddragon.teaseai.api.media.MediaType');
const mediaUrl = new MediaURL(MediaType.IMAGE, 'teaser-teased.tumblr.com');
showImage(mediaUrl);
sleep(1);
showImage(mediaUrl, 2);
showImage(mediaUrl, 3.5);

// Bad calls
showImage();
showImage(null);
showImage(2, file1);
showImage(file2, 1, 2.2);
showImage(1, mediaUrl);
showImage(mediaUrl, 1.1, 2);
"
The previous implementation of sendMessage(String, Number, Boolean) didn't
multiply the duration value by 1000 to convert from seconds to
milliseconds.  It's not clear whether this was intentional to provide the
possibility of passing -1 to customMessage() as the duration which has a
special interpretation.  However, neither the Spicy or Mischevious
personalites used this function, and it's not mentioned on the Wiki page.

Tested with the following script:
"
lockImages();

// sendMessage(String)
sendMessage('Mary had a little lamb');

// sendMessage(String, Number)
sendMessage('its fleece was white as snow', 2);
sendMessage('and everywhere that Mary went', 3.5);

// sendMessage(String, String)
sendMessage('Mary had a little lamb', 'Images/Spicy/Assistant/1/124259409_004_122_372lo.jpg');

// sendMessage(String, Number, Boolean)
sendMessage('who\s fleece was white as snow', 10, true);
sendMessage('and everywhere that Mary went', 3.5, false);

sleep(5);

// Bad calls
sendMessage();
sendMessage(null);
sendMessage(2, 'Mary had a little lamb');
sendMessage('its fleece was white as snow', 2, 3.5);
"
Standard Java reflection method matching is based on exact parameter type
matches.  On some API methods that may not always be appropriate.  For
example, getVar(String, Object) uses the second parameter as the default
value when the variable name isn't found.  However, a call to
getVar('myVar', true) would only match against onCall(String, Boolean) and
not match against onCall(String, Object).

This new mechanism first tries the exact match as before, but if that fails
it will cycle through each onCall method to see if one can support suitable
type conversion of the arguments to the defined parameter types, allowing
calls such as getVar('myVar', true) to match with onCall(String, Object).
Tested with the following script:
"
lockImages();

function assert(expression, message) {
    if (true == expression) {
        sendMessage('Pass', 0, false);
    } else {
        sendMessage('FAIL: ' + message, 0, false);
    }
}

// preparation
setVar('testBoolVar', true);
setVar('testIntVar', 8);
setVar('testFloatVar', 5.6);
setVar('testStringVar', 'Puppy');

// getVar(String)
const noSuchVar = getVar('noSuchVar');
assert(noSuchVar == null, 'Variable was found when it shouldn\'t have been');

const boolVar = getVar('testBoolVar');
assert(boolVar != null, 'Boolean variable should have been found');
assert(typeof boolVar == 'boolean', 'Boolean type mismatch');

const intVar = getVar('testIntVar');
assert(intVar != null, 'Number variable should have been found');
assert(typeof intVar == 'number', 'Number type mismatch');

const floatVar = getVar('testFloatVar');
assert(floatVar != null, 'Number variable should have been found');
assert(typeof floatVar == 'number', 'Number type mismatch');

const stringVar = getVar('testStringVar');
assert(stringVar != null, 'String variable should have been found');
assert(typeof stringVar == 'string', 'String type mismatch');

// getVar(String, Object)
const defaultBoolVar1 = getVar('noSuchVar', true);
assert(defaultBoolVar1 != null, 'Boolean should have defaulted');
assert(typeof defaultBoolVar1 == 'boolean');
assert(defaultBoolVar1 == true, 'Boolean is wrong default');

const defaultBoolVar2 = getVar('noSuchVar', false);
assert(defaultBoolVar2 != null, 'Boolean should have defaulted');
assert(typeof defaultBoolVar2 == 'boolean');
assert(defaultBoolVar2 == false, 'Boolean is wrong default');

const defaultIntVar = getVar('noSuchVar', 12);
assert(defaultIntVar != null, 'Number should have defaulted');
assert(typeof defaultIntVar == 'number');
assert(defaultIntVar == 12, 'Number is wrong default');

const defaultFloatVar = getVar('noSuchVar', 15.7);
assert(defaultFloatVar != null, 'Number should have defaulted');
assert(typeof defaultFloatVar == 'number');
assert(defaultFloatVar == 15.7, 'Number is wrong default');

const defaultStringVar = getVar('noSuchVar', 'test text');
assert(defaultStringVar != null, 'String should have defaulted');
assert(typeof defaultStringVar == 'string');
assert(defaultStringVar == 'test text', 'String is wrong default');

// Bad calls
const bad1 = getVar();
assert(bad1 == null, 'Bad call should return null');
const bad2 = getVar(null);
assert(bad2 == null, 'Bad call should return null');

createInput('Done.');
"
Now that CustomFunctionExtended supports implicit type conversions, types
such as Integer and Double can be automatically matched to the Number type.
Therefore calls such as:
  showImage('image.jpg', 3);    // i.e. showImage(String, Integer);
  showImage('image.jpg', 5.5);  // i.e. showImage(String, Double);
are both matched to:
  onCall(String, Number);
Now that CustomFunctionExtended supports implicit type conversions, types
such as Integer and Double can be automatically matched to the Number type.
Therefore calls such as:
  sendMessage('Hello', 3);    // i.e. sendMessage(String, Integer);
  sendMessage('Hello', 5.5);  // i.e. sendMessage(String, Double);
are both matched to:
  onCall(String, Number);
For developers, the optionally overridable preOnCall in
CustomFunctionExtended could easily go unnoticed, and it's not immediately
clear whether it's called before or after a successful method candidate has
been found.  For those reasons, it's best not to have it at all.
Tested with the following script:
"
lockImages();

function assert(expression, message) {
    if (true == expression) {
        sendMessage('Pass', 0, false);
    } else {
        sendMessage('FAIL: ' + message, 0, false);
    }
}

const uniqueId = setDate().getTimeInMillis();
const testBoolVarName = 'testBoolVar' + uniqueId
const testIntVarName = 'testIntVar' + uniqueId
const testFloatVarName = 'testFloatVar' + uniqueId
const testStringVarName = 'testStringVar' + uniqueId

// setVar new variable
const vBoolCreated = setVar(testBoolVarName, true);
assert(vBoolCreated != null, 'Setting a variable should return the set object');
assert(typeof vBoolCreated == 'boolean', 'Boolean type mismatch');
assert(vBoolCreated == true, 'Incorrect boolean value');

const vIntCreated = setVar(testIntVarName, 5);
assert(vIntCreated != null, 'Setting a variable should return the set object');
assert(typeof vIntCreated == 'number', 'Number type mismatch');
assert(vIntCreated == 5, 'Incorrect integer value');

const vFloatCreated = setVar(testFloatVarName, 6.5);
assert(vFloatCreated != null, 'Setting a variable should return the set object');
assert(typeof vFloatCreated == 'number', 'Number type mismatch');
assert(vFloatCreated == 6.5, 'Incorrect float value');

const vStringCreated = setVar(testStringVarName, 'Hello');
assert(vStringCreated != null, 'Setting a variable should return the set object');
assert(typeof vStringCreated == 'string', 'String type mismatch');
assert(vStringCreated == 'Hello', 'Incorrect string value');

// getVar of set variable
const vBoolRetrieved = getVar(testBoolVarName);
assert(vBoolRetrieved != null, 'Missing retrieved variable');
assert(typeof vBoolRetrieved == 'boolean', 'Boolean type mismatch');
assert(vBoolRetrieved == true, 'Incorrect boolean value');

const vIntRetrieved = getVar(testIntVarName);
assert(vIntRetrieved != null, 'Missing retrieved variable');
assert(typeof vIntRetrieved == 'number', 'Number type mismatch');
assert(vIntRetrieved == 5, 'Incorrect integer value');

const vFloatRetrieved = getVar(testFloatVarName);
assert(vFloatRetrieved != null, 'Missing retrieved variable');
assert(typeof vFloatRetrieved == 'number', 'Number type mismatch');
assert(vFloatRetrieved == 6.5, 'Incorrect float value');

const vStringRetrieved = getVar(testStringVarName);
assert(vStringRetrieved != null, 'Missing retrieved variable');
assert(typeof vStringRetrieved == 'string', 'String type mismatch');
assert(vStringRetrieved == 'Hello', 'Incorrect string value');

// setVar replace existing variable with same type
const vBoolReplaced = setVar(testBoolVarName, false);
assert(vBoolReplaced != null, 'Setting a variable should return the set object');
assert(typeof vBoolReplaced == 'boolean', 'Boolean type mismatch');
assert(vBoolReplaced == false, 'Incorrect boolean value');

const vIntReplaced = setVar(testIntVarName, 7);
assert(vIntReplaced != null, 'Setting a variable should return the set object');
assert(typeof vIntReplaced == 'number', 'Number type mismatch');
assert(vIntReplaced == 7, 'Incorrect integer value');

const vFloatReplaced = setVar(testFloatVarName, 8.5);
assert(vFloatReplaced != null, 'Setting a variable should return the set object');
assert(typeof vFloatReplaced == 'number', 'Number type mismatch');
assert(vFloatReplaced == 8.5, 'Incorrect float value');

const vStringReplaced = setVar(testStringVarName, 'World');
assert(vStringReplaced != null, 'Setting a variable should return the set object');
assert(typeof vStringReplaced == 'string', 'String type mismatch');
assert(vStringReplaced == 'World', 'Incorrect string value');

// getVar of updated variable
const vBoolUpdated = getVar(testBoolVarName);
assert(vBoolUpdated != null, 'Missing retrieved variable');
assert(typeof vBoolUpdated == 'boolean', 'Boolean type mismatch');
assert(vBoolUpdated == false, 'Incorrect boolean value');

const vIntUpdated = getVar(testIntVarName);
assert(vIntUpdated != null, 'Missing retrieved variable');
assert(typeof vIntUpdated == 'number', 'Number type mismatch');
assert(vIntUpdated == 7, 'Incorrect integer value');

const vFloatUpdated = getVar(testFloatVarName);
assert(vFloatUpdated != null, 'Missing retrieved variable');
assert(typeof vFloatUpdated == 'number', 'Number type mismatch');
assert(vFloatUpdated == 8.5, 'Incorrect float value');

const vStringUpdated = getVar(testStringVarName);
assert(vStringUpdated != null, 'Missing retrieved variable');
assert(typeof vStringUpdated == 'string', 'String type mismatch');
assert(vStringUpdated == 'World', 'Incorrect string value');

// setVar replace existing variable with different type
const vIntReplacedWithBool = setVar(testIntVarName, true);
assert(vIntReplacedWithBool != null, 'Setting a variable should return the set object');
assert(typeof vIntReplacedWithBool == 'boolean', 'Boolean type mismatch');
assert(vIntReplacedWithBool == true, 'Incorrect boolean value');

const vBoolReplacedWithInt = setVar(testBoolVarName, 11);
assert(vBoolReplacedWithInt != null, 'Setting a variable should return the set object');
assert(typeof vBoolReplacedWithInt == 'number', 'Number type mismatch');
assert(vBoolReplacedWithInt == 11, 'Incorrect integer value');

const vStringReplacedWithFloat = setVar(testStringVarName, 12.5);
assert(vStringReplacedWithFloat != null, 'Setting a variable should return the set object');
assert(typeof vStringReplacedWithFloat == 'number', 'Number type mismatch');
assert(vStringReplacedWithFloat == 12.5, 'Incorrect float value');

const vFloatReplacedWithString = setVar(testFloatVarName, 'Banana');
assert(vFloatReplacedWithString != null, 'Setting a variable should return the set object');
assert(typeof vFloatReplacedWithString == 'string', 'String type mismatch');
assert(vFloatReplacedWithString == 'Banana', 'Incorrect string value');

// getVar of new variable type
const vBoolNewType = getVar(testIntVarName);
assert(vBoolNewType != null, 'Missing retrieved variable');
assert(typeof vBoolNewType == 'boolean', 'Boolean type mismatch');
assert(vBoolNewType == true, 'Incorrect boolean value');

const vIntNewType = getVar(testBoolVarName);
assert(vIntNewType != null, 'Missing retrieved variable');
assert(typeof vIntNewType == 'number', 'Number type mismatch');
assert(vIntNewType == 11, 'Incorrect integer value');

const vFloatNewType = getVar(testStringVarName);
assert(vFloatNewType != null, 'Missing retrieved variable');
assert(typeof vFloatNewType == 'number', 'Number type mismatch');
assert(vFloatNewType == 12.5, 'Incorrect float value');

const vStringNewType = getVar(testFloatVarName);
assert(vStringNewType != null, 'Missing retrieved variable');
assert(typeof vStringNewType == 'string', 'String type mismatch');
assert(vStringNewType == 'Banana', 'Incorrect string value');

// Bad calls
const bad1 = setVar();
assert(bad1 == null, 'Bad call should return null');
const bad2 = setVar(null);
assert(bad2 == null, 'Bad call should return null');
const bad3 = setVar('someVar', 0, 1);
assert(bad3 == null, 'Bad call should return null');

createInput('Done.');
"
When using reflection to match argument types, null is typeless and
cannot be matched against an explicit type. Some personalities call
GetVar with the default argument as null in order to determine whether
the variable exists, even though calling GetVar without the default
argument is equivalent. To support a null parameter, an explicit signature
can be used, in this case:
    Object onCall(String variableName, Void nullValue)
where the 'Void nullValue' will match against a call to:
    GetVar("foo", null).

When there is no match at all for the call, the list of candidate functions
includes the explicit null variant:
    INFO: Candidate functions are:
    INFO:     getVar(String)
    INFO:     getVar(String, Object)
    INFO:     getVar(String, null)

Tested with the following script:
"
lockImages();

function assert(expression, message) {
    if (true == expression) {
        sendMessage('Pass', 0, false);
    } else {
        sendMessage('FAIL: ' + message, 0, false);
    }
}

// preparation
setVar('testBoolVar', true);
setVar('testIntVar', 8);
setVar('testFloatVar', 5.6);
setVar('testStringVar', 'Puppy');

// getVar(String)
const noSuchVar = getVar('noSuchVar');
assert(noSuchVar == null, 'Variable was found when it shouldn\'t have been');

const boolVar = getVar('testBoolVar');
assert(boolVar != null, 'Boolean variable should have been found');
assert(typeof boolVar == 'boolean', 'Boolean type mismatch');
assert(boolVar == true);

const intVar = getVar('testIntVar');
assert(intVar != null, 'Number variable should have been found');
assert(typeof intVar == 'number', 'Number type mismatch');
assert(intVar == 8);

const floatVar = getVar('testFloatVar');
assert(floatVar != null, 'Number variable should have been found');
assert(typeof floatVar == 'number', 'Number type mismatch');
assert(floatVar == 5.6);

const stringVar = getVar('testStringVar');
assert(stringVar != null, 'String variable should have been found');
assert(typeof stringVar == 'string', 'String type mismatch');
assert(stringVar == 'Puppy');

// getVar(String, Object)
const defaultBoolVar1 = getVar('noSuchVar', true);
assert(defaultBoolVar1 != null, 'Boolean should have defaulted');
assert(typeof defaultBoolVar1 == 'boolean');
assert(defaultBoolVar1 == true, 'Boolean is wrong default');

const defaultBoolVar2 = getVar('noSuchVar', false);
assert(defaultBoolVar2 != null, 'Boolean should have defaulted');
assert(typeof defaultBoolVar2 == 'boolean');
assert(defaultBoolVar2 == false, 'Boolean is wrong default');

const defaultIntVar = getVar('noSuchVar', 12);
assert(defaultIntVar != null, 'Number should have defaulted');
assert(typeof defaultIntVar == 'number');
assert(defaultIntVar == 12, 'Number is wrong default');

const defaultFloatVar = getVar('noSuchVar', 15.7);
assert(defaultFloatVar != null, 'Number should have defaulted');
assert(typeof defaultFloatVar == 'number');
assert(defaultFloatVar == 15.7, 'Number is wrong default');

const defaultStringVar = getVar('noSuchVar', 'test text');
assert(defaultStringVar != null, 'String should have defaulted');
assert(typeof defaultStringVar == 'string');
assert(defaultStringVar == 'test text', 'String is wrong default');

// getVar(String, null)
const defaultNullVar = getVar('noSuchVar', null);
assert(defaultNullVar == null, 'Null was not returned as default value');

const boolVar2 = getVar('testBoolVar', null);
assert(boolVar2 != null, 'Boolean variable should have been found');
assert(typeof boolVar2 == 'boolean', 'Boolean type mismatch');
assert(boolVar2 == true);

const intVar2 = getVar('testIntVar', null);
assert(intVar2 != null, 'Number variable should have been found');
assert(typeof intVar2 == 'number', 'Number type mismatch');
assert(intVar2 == 8);

const floatVar2 = getVar('testFloatVar', null);
assert(floatVar2 != null, 'Number variable should have been found');
assert(typeof floatVar2 == 'number', 'Number type mismatch');
assert(floatVar2 == 5.6);

const stringVar2 = getVar('testStringVar', null);
assert(stringVar2 != null, 'String variable should have been found');
assert(typeof stringVar2 == 'string', 'String type mismatch');
assert(stringVar2 == 'Puppy');

// Bad calls
const bad1 = getVar();
assert(bad1 == null, 'Bad call should return null');
const bad2 = getVar(null);
assert(bad2 == null, 'Bad call should return null');
const bad3 = getVar(null, null);
assert(bad3 == null, 'Bad call should return null');
const bad4 = getVar(null, "text");
assert(bad4 == null, 'Bad call should return null');

createInput('Done.');
"
Refactor some API functions to reduce complexity
…ection

Protect against possibility of no tease media
Just a small precedence issue where the percentage would remain at zero
while minutesPassed < preferredSessionDuration.
Fix picture selection algorithm
If there is a desire to remove the current image without having to
specify a specify an explicit blank image.
MIDI sequencers take up system resources and need to be disposed of
when no longer in use.
Tested with:
    [email protected]:FrozenWolf4887/TeaseAIJava-TestPersonality.git

This separates the media handlers into three respective modules, video,
audio, and image.  Additionally it addresses various issues found with
testing, although most of the issues only pertain to error conditions.

Video playback issues addressed:
* Disposes of MediaPlayers when finished or failed
* Fix hanging when playing invalid files
* Fix images remaining locked when playing invalid files
* Fix crash calling stopVideo() when no video is playing
* Stop previously playing video before starting a new one

Audio playback issues addressed:
* Disposes of MediaPlayers when finished or failed
* Fix hanging when playing invalid files
* Fix images being unlocked when audio has finished playing
* Fix stopAllAudio() only stopping the last playing occurrence of a file
* Cleans up list of playing audio

There is an outstanding issue that was also present in TAJ 1.3 where
calling playVideo('http://...') would often hang.  The contained
MediaPlayer object fails to issue any callbacks when the video has
finished, and its status remains as PLAYING.  Calling stop() on the
MediaPlayer does nothing.  This causes a hang in TAJ when waiting for
the video to finish either successfully or in error.  This problem may
be limited to Linux and hasn't been evaluated in Windows.  It occurs
with both OpenJFX 15.0.1 and OpenJFX 16; other versions have not been
tested.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants