How to do you get output from Javascript into Java using ScriptEngine - java

With this simple piece of applescript I can list the names of all songs within iTunes
tell application "iTunes"
set mainLibrary to library playlist 1
repeat with nexttrack in (get every track of mainLibrary)
try
name of nexttrack
end try
end repeat
end tell
I then run it as Java 7 code using ScriptEngine, however it is only obvious how to get the result of the script which in this case is the name of the last track only.
StringBuilder script =new StringBuilder();
script.append("tell application \"iTunes\"\n");
script.append("set mainLibrary to library playlist 1\n");
script.append("repeat with nexttrack in (get every track of mainLibrary)\n");
script.append("try\n");
script.append("name of nexttrack\n");
script.append("end try\n");
script.append("end repeat\n");
script.append("end tell\n");
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("AppleScript");
System.out.println(engine.eval(script.toString()));
How do can I capture the name of all tracks , i.e all output from the script. I assume I have to redirect standard out to a Reader, but cannot see how to do it.
Update:
I found this article
http://www.informit.com/articles/article.aspx?p=696621&seqNum=6
But updating by code to
StringBuilder script =new StringBuilder();
script.append("tell application \"iTunes\"\n");
script.append("set mainLibrary to library playlist 1\n");
script.append("repeat with nexttrack in (get every track of mainLibrary)\n");
script.append("try\n");
script.append("name of nexttrack\n");
script.append("end try\n");
script.append("end repeat\n");
script.append("end tell\n");
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("AppleScript");
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
StringWriter swError = new StringWriter();
PrintWriter pwError = new PrintWriter(swError);
engine.getContext().setWriter(pw);
engine.getContext().setErrorWriter(pwError);
System.out.println(engine.eval(script.toString()));
System.out.println("************* engine:"+sw.getBuffer());
System.out.println("************* engine error:"+swError.getBuffer());
Just outputs
See You on the Other Side (short)
************* engine:
************* engine error:
So you can clearly see the script works as the eval shows the name of the last track , but I'm getting nothing back from the redirected writers. Wondering does this actually work for applescript ?
Update 2
I wrote a test in Javascript and found setting the writers DID WORK for that so Im thinking that either
There is something broken in script engine for Applescript ( Im using a recent build 1.7.0_40-ea-b29) of the early access version of Java 7 on OSX)
My Applescript is wrong, i.e rather than just name of nexttrack I should be doing something like echo name of nexttrack to actually make it go to to stdout.
I'd like to think (2) was the problem, but I canot find any reference to outputting text in Applescript, echo is not a valid command and the print command does actually try to print to a printer rather than print to stdout as it would in Java or C.
Update 3
So I couldn't get this working, and now wondering if Applescript only ever writes the return value. I found an example of using stdout ( or so i thought) but I think that was just a naming convention, and in fact all it does is continually append data to a variable, and eventually return that.
So I did it get something working by using the following script stored in a file, and then used in Java with engine.eval(new java.io.FileReader("filename")
tell application "iTunes"
set output to ""
set mainLibrary to library playlist 1
repeat with nexttrack in (get every track of mainLibrary)
if (class of nexttrack is file track) then
try
set trackname to name of nexttrack
set loc to location of nexttrack
set locpath to POSIX path of loc
set persistid to persistent ID of nexttrack
set nextline to trackname & "::" & locpath & "::" & persistid
set output to output & "\n" & nextline
end try
end if
end repeat
copy output to stdout
end tell
but this doesnt actually resolve the original question, and the one problem with it is that if there is any error then I wont get anything back, whereas if it failed halfway through reading my iTuneslibrary and I was using stdout I would at least get half the data back.

To answer you original question, you get back whatever you "return" at the end of the script. If you do not have a specific "return" statement then by default you get back the result from the last action (which in your case is the last iteration of the repeat loop). Therefore if you need more than the last action returned you must create the return value in your script and then return it at the end.
but this doesnt actually resolve the original question, and the one
problem with it is that if there is any error then I wont get anything
back, whereas if it failed halfway through reading my iTuneslibrary
and I was using stdout I would at least get half the data back.
This is incorrect. The try block around your code will make applescript ignore the errors and continue, so anything you collect that doesn't error will still get returned.
Note that you have some errors in your latest applescript code. Especially this line makes no sense as applescript doesn't know what stdout is. So your comment is incorrect.
copy output to stdout
Here's what you need to do. As mentioned, you use "return" to return something. So I cleaned up your code. This will put each line of the repeat loop on a separate line of the output variable, which you return at the end of your code, which you can then parse once you bring it into your javascript code. Try this...
tell application "iTunes"
set output to ""
set mainLibrary to library playlist 1
repeat with nexttrack in (get every track of mainLibrary)
if (class of nexttrack is file track) then
try
set trackname to name of nexttrack
set loc to location of nexttrack
set locpath to POSIX path of loc
set persistid to (persistent ID of nexttrack) as text
set nextline to trackname & "::" & locpath & "::" & persistid & return
set output to output & nextline
end try
end if
end repeat
end tell
return output

Related

How to have only one instance of the CHM file opened?

I want to set up only one instance of the CHM file when clicking on "Help" in the menubar and stopping it from opening twice when clicked again - therefore how do I code it?
I've tried to use it with process.isAlive(), but after I close it I want a counter set to zero, which only opens another CHM file when the counter is 0.
helpMenu.addMouseListener(new MouseAdapter() {
// do this after clicked
openCHM();
});
So MouseEvent is fired once.
openCHM() {
Process p;
if(cnt == 0) {
p = Runtime.getRuntime().exec("hh.exe Help.chm");
cnt++;
if(!p.isAlive()) {
cnt = 0;
}
}
I expected the counter to be 0, but then came to the conclusion that MouseEvent already fired once and the code got already executed, therefore it never goes to the second if-statement and sets my counter to 0.
EDIT
There is no correct answer how to open a CHM file once, but there is a workaround that makes it possible, we just need to look if the file is renamable or not.
protected void openCHM() {
try {
File file = new File("YOURNAME.chm");
boolean renamable = file.renameTo(file); // can't rename if file is already open, returns true if renaming is possible
if(renamable) {
Runtime.getRuntime().exec("hh.exe YOURNAME.chm");
} else if(!file.exists() ){
// message: file doesn't exist (in path)
} else {
// file is already open
}
} catch () {
}
}
I'm not a Java programmer but the short story - not possible (AFAIK).
You know, hh.exe is the HTMLHelp executable and associated with *.CHM files. It's just a shell that uses the HTML Help API and is really just hosting a browser window.
HH.EXE is not single instance, if you open a CHM or another file three times using HH.EXE, then three help windows will appear. Try it using PowerShell:
PS D:\_working> hh.exe C:\Windows\Help\htmlhelp.chm
Several client-side command line switches are available to help authors that are part of the HTML Help executable program (hh.exe) and therefore work when HTML Help Workshop is not set up.
KeyHH.exe was running years ago with special parameters.
If you call the HH API directly from your application, and not via a second helper program like HH.EXE or KEYHH.EXE, then you MUST close any open help windows before shutting down the application or you will probably crash Windows.
For some information related to the problem you maybe interested in Open CHM File Once.
Some quoted info from the link above:
When you do that you are just calling the help viewer again and again from the command line, you're not using the HTML Help API which is what you need to access the CHM once it is open. You need to check whether your flavors of Java and Smalltalk support calls to the HTML Help API. This API is documented in detail in the help file of Microsoft HTML Help Workshop, which is the compiler package you installed to be able to generate CHMs.

Validate subtitles file using vlcj (Java)

I am using an instance of vlcj DefaultEmbeddedMediaPlayer to play video. When adding subtitles to the video I want to see if the subtitle file is valid, and throw an Exception if it is not. This is my code:
File subtitlesFile = new File("subs.srt");
player.setSubTitleFile(subTitleFile);
The method setSubTitleFile(File subTitleFile) doesn't have a return value, but looking into its implementation I can see that it passes the call to libvlc, calling libvlc_video_subtitle_file(libvlc_media_player_t p_mi, String psz_subtitle), which returns 1 or 0 depending on if the subtitles have been added successfully or not. So I inherited from DefaultEmbeddedMediaPlayer and wrote my own version of that method:
public void setSubTitleFile(String subTitleFileName) {
final int status = libvlc.libvlc_video_set_subtitle_file(mediaPlayerInstance(), subTitleFileName);
System.out.println(status);
// throw Exception if status is false
}
Surprisingly this always gives me status 1, which means success. Even if I am passing an empty text file. Is this a bug? I really do not want to parse the subtitle file manually beforehand. Using the native VLC Player, I am getting an error as expected if the subtitles are invalid. Anything I could do here?
EDIT:
This is a screenshot from the native VLC player when adding an empty SRT file during play.
VLC subtitles file error
As far as I know, LibVLC/VLC is not parsing the subtitle file when you call libvlc_video_set_subtitle_file. All it is basically doing is setting a string value on some native structure that will be used later. So, you get a status of "success" because that call did its job of setting that string value.
Therefore, you will only know if the subtitle file is valid when VLC starts playing your media and it attempts to load the file at that point. Even then, I do not think you will get a specific error message - there will simply be an absence of a subtitle track.

Programatically embed a video in a slideshow using Apache Open Office API

I want to create a plugin that adds a video on the current slide in an open instance of Open Office Impress by specifying the location of the video automatically. I have successfully added shapes to the slide. But I cannot find a way to embed a video.
Using the .uno:InsertAVMedia I can take user input to choose a file and it works. How do I want to specify the location of the file programmatically?
CONCLUSION:
This is not supported by the API. Images and audio can be inserted without user intervention but videos cannot be done this way. Hope this feature is released in subsequent versions.
You requested information about an extension, even though the code you are using is quite different, using a file stream reader and POI.
If you really do want to develop an extension, then start with one of the Java samples. An example that uses Impress is https://wiki.openoffice.org/wiki/File:SDraw.zip.
Inserting videos into an Impress presentation can be difficult. First be sure you can get it to work manually. The most obvious way to do that seems to be Insert -> Media -> Audio or Video. However many people use links to files instead of actually embedding the file. See also https://ask.libreoffice.org/en/question/1898/how-to-embed-video-into-impress-presentation/.
If embedding is working for your needs and you want to automate the embedding by using an extension (which seems to be what your question is asking), then there is a dispatcher method called InsertAVMedia that does this.
I do not know offhand what the parameters are for the call. See https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=61127 for how to look up parameters for dispatcher calls.
EDIT
Here is some Basic code that inserts a video.
sub insert_video
dim document as object
dim dispatcher as object
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
dispatcher.executeDispatch(document, ".uno:InsertAVMedia", "", 0, Array())
end sub
From looking at InsertAVMedia in sfx.sdi, it seems that this call does not take any parameters.
EDIT 2
Sorry but InsertVideo and InsertImage do not take parameters either. From svx.sdi it looks like the following calls take parameters of some sort: InsertGalleryPic, InsertGraphic, InsertObject, InsertPlugin, AVMediaToolBox.
However according to https://wiki.openoffice.org/wiki/Documentation/OOoAuthors_User_Manual/Getting_Started/Sometimes_the_macro_recorder_fails, it is not possible to specify a file for InsertObject. That documentation also mentions that you never know what will work until you try it.
InsertGraphic takes a FileName parameter, so I would think that should work.
It is possible to add an XPlayer on the current slide. It looks like this will allow you to play a video, and you can specify the file's URL automatically.
Here is an example using createPlayer: https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=57699.
EDIT:
This Basic code works on my system. To play the video, simply call the routine.
sub play_video
If Video_flag = 0 Then
video =converttoURL( _
"C:\Users\JimStandard\Downloads\H264_test1_Talkinghead_avi_480x360.avi")
Video_flag = 1
'for windows:
oManager = CreateUnoService("com.sun.star.media.Manager_DirectX")
' for Linux
' oManager = CreateUnoService("com.sun.star.media.Manager_GStreamer")
oPlayer = oManager.createPlayer( video )
' oPlayer.CreatePlayerwindow(array()) ' crashes?
'oPlayer.setRate(1.1)
oPlayer.setPlaybackLoop(False)
oPlayer.setMediaTime(0.0)
oPlayer.setVolumeDB(GetSoundVolume())
oPlayer.start() ' Lecture
Player_flag = 1
Else
oPlayer.start() ' Lecture
Player_flag = 1
End If
End Sub

Testing HLS using JMeter

I am using JMeter to test HLS playback from a Streaming Server. So, the first HTTP request is for a master manifest file(m3u8). Say,
http://myserver/application1/subpath1/file1.m3u8
The reply to this will result in a playlist something like,
subsubFolder/360p/file1.m3u8
subsubFolder/480p/file1.m3u8
subsubFolder/720p/file1.m3u8
So, next set of URLs become
http://myserver/application1/subpath1/subsubFolder/360p/file1.m3u8
http://myserver/application1/subpath1/subsubFolder/480p/file1.m3u8
http://myserver/application1/subpath1/subsubFolder/720p/file1.m3u8
Now, individual reply to these further will be an index of chunks, like
0/file1.ts
1/file1.ts
2/file2.ts
3/file3.ts
Again, we have next set of URLs as
http://myserver/application1/subpath1/subsubFolder/360p/0/file1.ts
http://myserver/application1/subpath1/subsubFolder/360p/1/file1.ts
http://myserver/application1/subpath1/subsubFolder/360p/2/file1.ts
http://myserver/application1/subpath1/subsubFolder/360p/3/file1.ts
This is just the case of one set(360p). There will be 2 more sets like these(for 480p, 720p).
I hope the requirement statement is clear uptill this.
Now, the problem statement.
Using http://myserver/application1 as static part, regex(.+?).m3u8 is applied at 1st reply which gives subpath1/subsubFolder/360p/file1. This, is then added to the static part again, to get http://myserver/application1/subpath1/subsubFolder/360p/file1 + .m3u8
The problem comes at the next stage. As, you can see, with parts extracted previously, all I'm getting is
http://myserver/application1/subpath1/subsubFolder/360p/file1/0/file1.ts
The problem is obvious, an extra file1, 360p/file1 in place of 360p/0.
Any suggestions, inputs or alternate approaches appreciated.
If I understood the problem correctly, all you need is the file name as the other URLs can be constructed with it. Rather than using http://myserver/application1 as static part of your regex, I would try to get the filename directly:
([^\/.]+)\.m3u8$
# match one or more characters that are not a forward slash or a period
# followed by a period
# followed by the file extension (m3u8)
# anchor the whole match to the end
Now consider your urls, e.g. http://myserver/application1/subpath1/subsubFolder/360p/file1.m3u8, the above regex will capture file1, see a working demo here. Now you can construct the other URLs, e.g. (pseudo code):
http://myserver/application1/subpath1/subsubFolder/360p/ + filename + .m3u8
http://myserver/application1/subpath1/subsubFolder/360p/ + filename + /0/ + filename + .ts
Is this what you were after?
Make sure you use:
(.*?) - as Regular Expression (change plus to asterisk in your regex)
-1 - as Match No.
$1$- as template
See How to Load Test HTTP Live Media Streaming (HLS) with JMeter article for detailed instructions.
If you are ready to pay for a commercial plugin, then there is an easy and much more realistic solution which is a plugin for Apache JMeter provided by UbikLoadPack:
Besides doing this job for you, it will simulate the way a player would read the file. It will also scale much better than any custom script or player solution.
It supports VOD and Live which are quite difficult to script.
See:
http://www.ubik-ingenierie.com/blog/easy-and-realistic-load-testing-of-http-live-streaming-hls-with-apache-jmeter/
http://www.ubik-ingenierie.com/blog/ubikloadpack-http-live-streaming-plugin-jmeter-videostreaming-mpegdash/
Disclaimer, we are the providers of this solution

can't find file... using eclipse and file/filereader/bufferedreader

http://pastebin.com/m5fa7685e
It seems to fail when getting f3.. Output is:
not ready
File is null
Exception in thread "main" java.lang.NullPointerException
at BuabFile.parseBUAB(BuabFile.java:93)
at AddressBook.createBrowseForm(AddressBook.java:232)
at AddressBook.(AddressBook.java:51)
at Main.main(Main.java:4)"
But not before then - no file not found errors or anything...
My guess would be that the parseBUAB() method receives a "null" argument. Which means that it could be that it is the AddressBook class is responsible for the error.
It looks like you forgot to assign a value to BuabFile.file static field. You may want to add this to the end of your readFile() method:
BuabFile.file = f3;
I am guessing your AddressBook.createBrowseForm method looks something like this:
String filename = ...;
BuabFile buab = new BuabFile(filename);
buab.readFile();
ArrayList<String> buabLines = buab.returnFile(); // Returns null because readFile() never assigned a value to BuabFile.file
ArrayList<Buab> buabList = buab.parseBUAB(buabLines);
From all I can see, you just call parseBUAB(..) with a null value. I can't see the call to that method so you have to check the rest of your code.
For your 'not ready' output, which is created because your BufferedReader f3 is 'not ready', the API says
True if the next read() is guaranteed not to block for input, false otherwise.
Maybe you just call it too fast and the file is not loaded yet. Play with Thread.sleep() before calling ready() on the stream. Maybe a some-milliseconds blocking is just normal for File I/O.
And third - if f3 is the BufferedReader you want to keep, you have to assign it to the member file in the readFile() method. But now that's all I found ;)
I'm confused further but have found an answer sort of - I'm using windows 7 and have tried it on a windows xp computer and the code compiles fine and reads in the file (other errors you lot have noted are to be changed anyway through development - this was just one stick in the way...).
I'm wondering if there is some Windows 7 error with eclipse and opening/reading files...

Categories

Resources