Playing Background Music From Bundled File in Codenameone - codenameone

I'm trying to have a background sound play in codenameone from an mp3 file that's packaged with the app (beep-07.mp3 is just in the src folder).
I can make it work using MediaManager.createMedia, with code borrowed from this post: How to bundle sounds with Codename One?
But the MediaManager.createBackgroundMedia function only takes in a uri, so I try using MediaManager.createBackgroundMedia("file://beep-07.mp3"); but no sound plays.
Am I doing something wrong in the file string?

The src directory doesn't exist on the device. The files that are there are packaged as resources into the equivalent of a jar. So you need to extract them if you want a URL. Notice this might work with "jar://beep-07.mp3" but I'm not sure.
A more correct approach would be to extract it from the jar on first use then use this URL (the code below assumes static import of the CN class):
String fileName = getAppHomePath() + "beep-07.mp3";
if(!existsInFileSystem(fileName)) {
try(InputStream i = getResourceAsStream("/beep-07.mp3");
OutputStream o = openFileOutputStream(fileName)) {
copy(i, o);
}
}
Media m = MediaManager.createBackgroundMedia(fileName);
FYI since your app is running you don't need background media only foreground media.

Related

Stream YouTube video from extracted url

I am trying to find solution to play YouTube video from http stream. Not as embedded player or via website. The reason of that as I need to play some clips locally in app that prevented to be embedded.
So the first task to obtain http stream is easy to solve, e.g. using YouTubeExtractor. For example from this youtube url
https://www.youtube.com/watch?v=31crA53Dgu0
YouTubeExtractor extracts such url for downloading video. As you can see there is no piece of path to concrete .mp4 or .mov file. There is also binding to IP, so the url won't work on your side.
https://r3---sn-puu8-3c2e.googlevideo.com:443/videoplayback?sparams=dur,gcr,id,initcwndbps,ip,ipbits,itag,lmt,mime,mm,mn,ms,mv,pl,ratebypass,requiressl,source,upn,expire&source=youtube&initcwndbps=3147500&pl=19&upn=oYYkSNBwoc8&fexp=9412913,9416126,9416891,9422596,9428398,9429016,9431012,9431364,9431901,9432206,9432825,9433096,9433424,9433623,9433946,9434085,9435504,9435703,9435937&id=o-AGanAaajMgOmp4VrXIwo9jewJnqlsvZecDxCcRpSN3lS&expire=1462821352&gcr=ua&ip=12.34.56.149&lmt=1458705532562546&ms=au&mt=1462799507&mv=m&dur=217.849&sver=3&itag=22&key=yt6&mn=sn-puu8-3c2e&mm=31&ipbits=0&mime=video/mp4&ratebypass=yes&requiressl=yes&signature=A142619EBA90D00CC46FF05B9CF1E3469B0EF196.072B532670A4D833582F94CF9C46F1F7D298F230&fallback_host=tc.v1.cache5.googlevideo.com
private string ExtractVideoUrl(string youtubeUrl)
{
IEnumerable<VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(youtubeUrl, false);
var video = videoInfos.First();
if (video.RequiresDecryption)
{
DownloadUrlResolver.DecryptDownloadUrl(video);
}
return video.DownloadUrl; // videoInfos.First().DownloadUrl;
}
Then to download video this lib uses the code below. The interesting moment is in reading stream and writing to file the contents of youtube video.
var request = (HttpWebRequest)WebRequest.Create(this.Video.DownloadUrl);
if (this.BytesToDownload.HasValue)
{
request.AddRange(0, this.BytesToDownload.Value - 1);
}
// the following code is alternative, you may implement the function after your needs
using (WebResponse response = request.GetResponse())
{
using (Stream source = response.GetResponseStream())
{
**// HOW to Play source stream???**
using (FileStream target = File.Open(this.SavePath, FileMode.Create, FileAccess.Write))
{
var buffer = new byte[1024];
bool cancel = false;
int bytes;
int copiedBytes = 0;
while (!cancel && (bytes = source.Read(buffer, 0, buffer.Length)) > 0)
{
target.Write(buffer, 0, bytes);
....
So the general question is how to play video from that open stream? For example Chrome, Firefox and KMPlayer are doing this easily. The browsers generate a simple page with video tag, so it will be trivial to manage the player through JS. But...internal WebBrowser control can't, it suggests to download file. I tried CEFSharp (Chrome Embeded Framework) and no luck there. Maybe anybody know good video player WPF library which can streaming video? I also tried VLC.wpf and Shockwave Flash, but still unhappy with this extracted url. A lot of searching but results insufficient for now.
After 2 days researching I found the solution of how to play youtube video url directly from WPF application.
Some notes before:
WebBrowser component for WPF and the same for WinForms does not support HTML5. So no way to play video using <video> tag there
Chrome Embeded Framework (CEF)and its CEFSharp wrapper does not support <audio> and <video> tags by default. As I found on SO it is needed to recompile CEF to support audio and it seems video too. --enable-multimedia-streams option didn't work on my side at all to play video
WPF MediaElement component does not support playing video from streams. However there are workaroung exists, they are unsuitable to play youtube url's.
No .NET media player found which could play video from Stream object returned by HttpWebRequest
So the solution is in using GeckoFx webbrowser which is also available via nuget. As it is WinForms based component it is needed to use WinFormsHosting to use it in WPF. Final solution is:
<xmlns:gecko="clr-namespace:Gecko;assembly=Geckofx-Winforms">
....
<WindowsFormsHost Width="400" Height="300" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<gecko:GeckoWebBrowser x:Name="_geckoBrowser"/>
</WindowsFormsHost>
And simple code to use:
public void PlayVideo(string videoId)
{
var url = string.Format("https://www.youtube.com/watch?v={0}", videoId);
var videoUrl = ExtractVideoUrl(url);
_geckoBrowser.Navigate(videoUrl);
}
GeckoFx is depeneded on XulRunner runtime sdk. It is installed with nuget package though. One cons in this solution is the size of all app dependencies increased for over +70mb.

How to target a file (a path to it) in Java/JavaFX

It might be a simple one, but i can't seem to get it to work. I am making a video player in JavaFX but I don't know how to target the file that is going to be played (I don't know the correct syntax). Thank you in advance for your help. Here's a sample of code that i'm trying to run>
Media media = new Media("trailers/trailer.mp4");
MediaPlayer player = new MediaPlayer(media);
MediaView view = new MediaView(player);
btw, the file is in the project folder, then trailers/trailer.mp4. Oh, and I'm running Windows.
1 Use this if media source file in same project package.
Media media = new Media("trailer.mp4");
2 Use this if media source file in same project sub package [Packages with name "trailers" in project main package]
Media media = new Media("trailers/trailer.mp4");
3 Use this if media source file is other location [Using full path].
Media media = new Media("file:///e:/trailers/trailer.mp4");
OR
Media media = new Media("file:///E:/trailers/trailer.mp4");
Note: should use 3 slash i.e. "file:///" to avoid error "MediaException: MEDIA_INACCESSIBLE : e/E"
Put your file into the sources folder and load it as a resource:
Media media = new Media(getClass().getResource("trailer.mp4"));
or use the full path
Media media = new Media("file://c:/trailers/trailer.mp4"));
Also, note that JavaFX 2.0 supports only FLV codec. For mp4 (with H.264 codec) you need to use JavaFX 2.1 or later.
If you want to load media from your project package:
File file=new File("trailer.mp4");
Media media=new Media(file.toURI().toString())

Create a directory dynamically inside the "web pages" folder of a java web application

So I'm trying to dynamically create a folder inside the web pages folder.
I'm making a game database. Everytime a game is added I do this:
public void addGame(Game game) throws DatabaseException {
em.getTransaction().begin();
em.persist(game);
em.getTransaction().commit();
File file = new File("C:\\GameDatabaseTestFolder");
file.mkdir();
}
So everything works here.
The file get's created.
But I want to create the folder like this:
public void addGame(Game game) throws DatabaseException {
em.getTransaction().begin();
em.persist(game);
em.getTransaction().commit();
File file = new File(game.getId()+"/screenshots");
file.mkdir();
}
Or something like that. So it will be created where my jsp files are and it will have the id off the game.
I don't understand where the folder is created by default.
thank you in advance,
David
It's by default relative to the "current working directory", i.e. the directory which is currently open at the moment the Java Runtime Environment has started the server. That may be for example /path/to/tomcat/bin, or /path/to/eclipse/workspace/project, etc, depending on how the server is started.
You should now realize that this condition is not controllable from inside the web application.
You also don't want to store it in the expanded WAR folder (there where your JSPs are), because any changes will get lost whenever you redeploy the WAR (with the very simple reason that those files are not contained in the original WAR).
Rather use an absolute path instead. E.g.
String gameWorkFolder = "/path/to/game/work/folder";
new File(gameWorkFolder, game.getId()+"/screenshots");
You can make it configureable by supplying it as a properties file setting or a VM argument.
See also:
Image Upload and Display in JSP
getResourceAsStream() vs FileInputStream

Silverlight: Business Application Needs Access To Files To Print and Move

I have the following requirement for a business application:
(All of this could be on local or server)
Allow user to select folder location
Show contents of folder
Print selected items from folder (*.pdf)
Display which files have been printed
Potentially move printed files to new location (sub-folder of printed)
How can I make this happen in Silverlight?
Kind regards,
ribald
First of all, all but the last item can be done (the way you expect). Due to security protocols, silverlight cannot access the user's drive and manipulate it. The closest you can get is accessing silverlight's application storage which will be of no help to you whatsoever in this case. I will highlight how to do the first 4 items.
Allow user to select folder location & Show contents of folder
public void OnSelectPDF(object sender)
{
//create the open file dialog
OpenFileDialog ofg = new OpenFileDialog();
//filter to show only pdf files
ofg.Filter = "PDF Files|*.pdf";
ofg.ShowDialog();
byte[] _import_file = new byte[0];
//once a file is selected proceed
if (!object.ReferenceEquals(ofg.File, null))
{
try
{
fs = ofg.File.OpenRead();
_import_file = new byte[fs.Length];
fs.Read(_import_file, 0, (int)fs.Length);
}
catch (Exception ex)
{
}
finally
{
if (!object.ReferenceEquals(fs, null))
fs.Close();
}
//do stuff with file - such as upload the file to the server
};
}
If you noticed, in my example, once the file is retrieved, i suggest uploading it to a webserver or somewhere with temporary public access. I would recommend doing this via a web service. E.g
//configure the system file (customn class)
TSystemFile objFile = new TNetworkFile().Initialize();
//get the file description from the Open File Dialog (ofg)
objFile.Description = ofg.File.Extension.Contains(".") ? ofg.File.Extension : "." + ofg.File.Extension;
objFile.FileData = _import_file;
objFile.FileName = ofg.File.Name;
//upload the file
MasterService.ToolingInterface.UploadTemporaryFileAsync(objFile);
Once this file is uploaded, on the async result, most likely returning the temporary file name and upload location, I would foward the call to some javascript method in the browser for it to use the generic "download.aspx?fileName=givenFileName" technique to force a download on the users system which would take care of both saving to a new location and printing. Which is what your are seeking.
Example of the javascript technique (remember to include System.Windows.Browser):
public void OnInvokeDownload(string _destination)
{
//call the browser method/jquery method
//(I use constants to centralize the names of the respective browser methods)
try
{
HtmlWindow window = HtmlPage.Window;
//where BM_INVOKE_DOWNLOAD is something like "invokeDownload"
window.Invoke(Constants.TBrowserMethods.BM_INVOKE_DOWNLOAD, new object[] { _destination});
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); }
}
Ensure you have the javascript method existing either in an included javaScript file or in the same hosting page as your silverlight app. E.g:
function invokeDownload(_destination) {
//some fancy jquery or just the traditional document.location change here
//open a popup window to http://www.myurl.com/downloads/download.aspx? fileName=_destination
}
The code for download.aspx is outside the scope of my answer, as it varies per need and would just lengthen this post (A LOT MORE). But from what I've given, it will "work" for what you're looking for, but maybe not in exactly the way you expected. However, remember that this is primarily due to silverlight restrictions. What this approach does is rather than forcing you to need a pluging to view pdf files in your app, it allows the user computer to play it's part by using the existing adobe pdf reader. In silverlight, most printing, at least to my knowledge is done my using what you call and "ImageVisual" which is a UIElement. To print a pdf directly from silverlight, you need to either be viewing that PDF in a silverlight control, or ask a web service to render the PDF as an image and then place that image in a control. Only then could you print directly. I presented this approach as a lot more clean and direct approach.
One note - with the temp directory, i would recommend doing a clean up by some timespan of the files on the server side everytime a file is being added. Saves you the work of running some task periodically to check the folder and remove old files. ;)

How to access downloaded sound in IsolatedStorage via URI (WP7)?

I basically downloaded a file name custom.mp3 into my isolatedstorage and I can see it via isolatedstorage explorer....
The question here is... How can I access the particular custom.mp3 via URI?
So far I got this.. but I wonder why it is not working:
alarm.Sound = new Uri("isostore:/custom.mp3", UriKind.Absolute);
Your path is wrong. Nothing else is wrong with your code. Post the code you're using for saving the mp3 file in the first place, if you want further help.
For easier reading, the code to store the MP3 goes something like this..
string alarmfile = "custom.mp3";
isolatedStorageFileStream = new IsolatedStorageFileStream(alarmfile,FileMode.Create,isolatedStorageFile);
long songfilelength = (long) e.Result.Length;
byte[] songbyte = new byte[songfilelength];
e.Result.Read(songbyte, 0, songbyte.Length);
isolatedStorageFileStream.Write(songbyte, 0, songbyte.Length);
isolatedStorageFileStream.Flush();
Only files packaged in the XAML can be used as alarm sound:
Remarks
The Sound URI must point to a file packaged in the application’s .xap
file. Isolated storage is not supported. When the alarm is launched,
the sound is played quietly and then gradually increases in volume.
There is no way to modify this behavior.
From:
Alarm.Sound Property

Resources