Using dart:js to stream audio through the SoundCloud JavaScript API - dart

I'm trying to write a library that will make it easer for dartisans to use the SoundCloud JavaScript SDK (http://developers.soundcloud.com/docs/api/sdks#javascript).
I'm using the 'dart:js' library, and
I'm only using one class to handle the proxy.
class SCproxy {
JsObject proxy = context['SC'];
String client_id;
SCproxy(this.client_id) {}
initialize() {
proxy.callMethod('initialize', [client_id]);
}
stream(String track_id){
var track = new JsObject(proxy.callMethod('stream',[track_id]));
print(track); // track should be the soundmanager2 object that we can call '.play' on.
}
The repo I'm hosting this from is (https://github.com/darkkiero/scproxy)
My problem occurs when I try to run my 'stream' method.
main() {
SCproxy SC = new SCproxy('Your SoundCloud API client_ID');
SC.initialize();
SC.stream('/tracks/111477464');
}
When I try to grab and use the soundmanager2 object returned by the javascript 'SC.stream' method, the dart editor gives me this exception :
Breaking on exception: type 'ScriptElement' is not a subtype of type 'JsFunction' of 'constructor'.
I am under the impression that I should be able to get the dart JsObject for the soundmanager2 object by collecting the callback of the 'SC.stream', But I'm not sure how.However I could be completely misusing 'dart:js' and that would be helpful information as well.

You don't seem to follow the SoundCloud JavaScript SDK documentation. Particularly for the stream method that takes a callback as parameter and doesn't return.
The following Dart code :
context['SC'].callMethod('stream', ['/tracks/293', (sound) {
sound.callMethod('play');
}]);
will do the same as this JS code :
SC.stream("/tracks/293", function(sound){
sound.play();
});
You can have a look at Using JavaScript from Dart for more explanations.

Related

How to call a Function from a Function in Twilio Serverless?

I'm trying to see about using Twilio Serverless to replace my IVR. I would like to have some centralized functions to use within the functions.
For example, My main may be something like /MainMenu, which will have all the Twml.
but it will also need to call a function like /LogStats, which will be a function that does a REST Call to my API to collect Stats.
I'd appreciate your guidance in this. I'm also a little confused about why there's a Functions Classic, and a Functions Services. Am I to assume that Functions Classic will go away?
Thanks
Update from comments
Hi Lizzie, thanks for your response. I have it working with the zoltar example.. but when I try to use it for creating a call to a REST API, it's not consistently calling the API.. Any Ideas?
Here's what I'm talking about..
const axios = require('axios');
const log = {
ask: async function(event){
try{
const res = await axios.post('https://myid.ngrok.io/api/calllogger/lognewcall', {
CallSid: event.CallSid,
Caller: event.Caller,
App: "EmgLine",
CallerCity: event.CallerCity,
CallerState: event.CallerState
});
if(!res.ok){
throw new Error(`HTTP error! Status ${res.status}`);
}
const data = await res.Message;
return data;
} catch(err){
const errMessage = `test: ${err}`;
return errMessage;
}
}
};
module.exports = log;
Twilio developer evangelist here.
The Functions Classic are the older Functions with the older Functions UI. It still works, but Functions Services are newer and recommended to use. A Service is an application container to store all your Functions and Assets, and used to manage deployments and separate environments. You will likely create a new Service for each new project you work on.
You can use code from another Function in another Function with code like this
exports.handler = function (context, event, callback) {
// First, get the path for the Function. Note that the key of the function
// is not preceded by a "/" as is the case with Assets
const zoltarPath = Runtime.getFunctions()['zoltar'].path;
// Next, use require() to import the library
const zoltar = require(zoltarPath);
// Finally, use the module as you would any other!
console.log('The answer to your riddle is: ' + zoltar.ask());
return callback();
}
Let me know if this helps at all!

Returning anonymous JS function which returns javascript plain object from Dart

Dart Code
import 'dart:html' as html;
import 'dart:js' as js;
import 'package:js/js.dart';
void main() {
var data = new AddLocationData(locationName: "Location1", locationPath: "ThisFolder");
var func = () => data;
html.window.console.log(func);
html.window.console.log(func());
}
#JS("")
#anonymous
class AddLocationData {
external String get locationName;
external String get locationPath;
external factory AddLocationData({String locationName, String locationPath});
}
You would assume that func will be a js function but its not. Its type/name is main_closure. See the screenshot
So the first two lines were printed from Dart code then I used Chrome Inspect Element window and right clicked on main_closure' and selected "Store as global variable" which then printedtemp1` and then I used it to display some information about the generated code.
So it is clear Dart returned an object and not a js function and so is the reason of asking this question.
So I want temp1 to be a function instead of temp1.call$0 so that I can get the data by calling temp1() and not temp1.call$0().
See js package doc:
Passing functions to JavaScript.
If you are passing a Dart function to a JavaScript API, you must wrap it using allowInterop or allowInteropCaptureThis.

sun.org.mozilla.javascript.internal.NativeObject vs org.mozilla.javascript.NativeObject

I am really stuck at this now..
Essentially I have a Java Map, which I would like to pass it to a Javascript Code, so that in my JS code I can use dot notation to refer the keys in this Map. ( I know I can serialize the map into JSON and deserialize it back and pass it into JS, but I don't like that ) I have this piece of the unit code
#Test
public void mapToJsTest() throws Exception{
Map m = Maps.newHashMap();
m.put("name", "john");
NativeObject nobj = new NativeObject();
for (Object k : m.keySet()) {
nobj.defineProperty((String)k, m.get(k), NativeObject.READONLY);
}
engine.eval("function test(obj){ return obj.name;}");
Object obj = ((Invocable)engine).invokeFunction("test", nobj);
Assert.assertEquals(obj, "john");
}
If I am using
org.mozilla.javascript.NativeObject
then the test won't pass,
However, if I am using
sun.org.mozilla.javascript.internal.NativeObject
then the test will pass.
However, we all know that we shouldn't rely on these internal classes, and when I deploy my code on the server side, trying to access
this internal class will cause other problems.
So how do I achieve this with just "org.mozilla.javascript.NativeObject"?
BTW, I am using Rhino
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
For Nashorn, it is much easier, I can pass Map directly into JS code.
Unless you're stuck with older JDK (jdk7 or below) for some reason, I'd recommend moving to jdk8u. You've ES 5.1 compliant JS implementation (Nashorn) that is bundled with JDK8+.

Call C# from JavaScript in an Android WebView

I want to call a C# class/method from within the HTML loaded in my WebView.
I have defined a class JS2CS which contains a single method to show a Toast, as follows:
using Android.Content;
using Android.Widget;
using Java.Interop;
namespace CrossPlatformApp_Android
{
public class JS2CS : Java.Lang.Object
{
private Context context;
public JS2CS (Context context)
{
this.context = context;
}
[Export ("run")]
public void Run ()
{
Toast.MakeText (context, "Hello from C#", ToastLength.Short).Show ();
}
}
}
I have defined a button in my HomePage.html file as follows:
<button type="button" onclick="JS2CS.run()" >Call C#</button>
HomePage.html is saved in the Assets folder of my project and I load it into my WebView as follows:
myWebView.Settings.JavaScriptEnabled = true;
myWebView.SetWebChromeClient (new CustomWebChromeClient());
myWebView.LoadUrl ("file:///android_asset/Content/HomePage.html");
CustomWebChromeClient is a simple extension of WebChromeClient which offers no additional functionality over its parent.
Lastly, I inject my JS2CS object into my WebView after calling LoadUrl(...), as follows:
myWebView.AddJavascriptInterface (new JS2CS (this), "JS2CS");
Unfortunately this does not do the job. When I launch my application and click the html button, I get the following message:
[Web Console] Uncaught ReferenceError: JS2CS is not defined at
file:///android_asset/Content/HomePage.html:22
If I call the AddJavascriptInterface(...) method before LoadUrl(...) instead, I get the following error message:
[Web Console] Uncaught TypeError: Object [object Object] has no method
'run' at file:///android_asset/Content/HomePage.html:22
Any ideas anybody??!!
The above implementation is based on the following two urls:
Call C# from JavaScript
Monodroid Javascript Call-back
Hmm, after trying all kinds of things... I stumbled across this sentence in the Android WebView.addJavascriptInterface(Object, String) documentation:
...For applications targeted to API level JELLY_BEAN_MR1 and above, only
public methods that are annotated with JavascriptInterface can be
accessed from JavaScript...
And I lowered my Android Application's Target Version from API 19 to API 14 and made no other changes to the code in the question and it now works! Hurrah! That does now pose the question however of how to inject a JavaScript interface into a WebView for app's targeting API 17+ but that's another question for another thread...
Edit: To get it to work for an app targeting API 17+, all you have to do is add the [JavascriptInterface] annotation to the method being
exported.

When calling dart compiled Javascript from javascript how do I pass in a callback function into dart compiled Javascript?

I'm trying to convert my project to dart step by step. I have converted a stand alone library to Dart and I'm using the Dart compiled javascript in my project. Thanks for the help in my other question. I'm able to call Dart compiled javascript functions. Now I facing another puzzle. If my Dart function requires a callback, how do I passing a Javascript function into the Dart generated javascript function?
What I am trying to do is register a Dart event handler from Javascript, for example:
in my Dart, I have event bus, dart object can register event handler through:
bus.on('eventName', callbackFunc);
and Dart object fires a event through:
bus.fire('eventName', data);
I expose the bus to Javascript world, through:
js.context['registerEvent'] = bus.on;
In Javascript, I want to call
registerEvent('someEvent', function() { console.log('JS callback' });
to register an event handler, when Dart object fired an event, the JS callback will be invoked.
Can you try to just pass it as a parameter to Dart and call it with param.apply([])
from your previous question,
js.context["sayGreeting"] = (message) {
print("greeting: $message");
};
// pass js function which is already defined above.
someJsObject.callMethod('someOriginalJsFunction', [js.context['sayGreeting']]);

Resources