WindowsMediaPlayer Playtime - c#

I have a windows form with a aXWindowsMediaPlayer which should play a random video/picture every 5 seconds using the method aXWindowsMediaPlayer.Url = <video/image file location>.
This works fine for pictures, but when a video is longer it'll only play the 5 seconds and not the full length, same for a shorter video, it'll play the full video and leaving the other seconds with a black screen.
Is there a way to configure the mediaPlayer to only go to the next picture/video when it has played the videos full length?
EDIT1:
Something like:
Timer_TickEvent()//Every 5 seconds it chooses a random given URL
{
axWindowsMediaPlayer1.URL = <Random URL>;
if(<Random URL> == 'A video?')
{
timer.Enabled = false;
PlayVideoLength();
}
}
Private void PlayVideoLength()
{
if('<Random URL.Length> ?' == 'the length of the played video in axWindowsMediaPlayer1 ?')
{
Timer.enabled = true;
}
}
This code obviously wont work. It's an idea of what I want it to do.

You can find if your URL is a video/audio/picture media with a IWMPMedia::getItemInfo, or getType.
instead of set Url in your axWindowsMediaPlayer component :
MyMediaComponent.Url = <MyMediaUrl>;
You can create a new with this URL:
WMPLib.IWMPMedia MyNewMedia = MyMediaComponent.newMedia(<MyMediaUrl>);
And I think you can get the type of your Media with :
MyNewMedia.getType();
You can Find the msdn documentation here.
When you find the type of your media, you can just test the type of your media before set your URL!
/* It is just a suggestion, this code don't work! */
if ( MyNewMedia.getType() == <A photo MEDIA code>)
{
// Set the URL for show the picture
MyMediaComponent.Url = <MyMediaUrl>;
return;
}
//else
// This media is not a picture!
Hope my idea help you.

Related

LibvclSharp winforms Go to specific Time

I am putting together a winforms app using libvclsharp wrapper.
It is a basic app that hosts 4 x VideoView windows and plays 4 different mp4 videos.
It plays ok and seems stable mostly, but the lib has some odd quirks that i cant seem to find an answer to
I need to click a button on the form and sent all the videos to a specific time, they are all the same length at the moment
using
_mediaPlayer1 = new MediaPlayer(_libVLC1);
_mediaPlayer2 = new MediaPlayer(_libVLC1);
_mediaPlayer3 = new MediaPlayer(_libVLC1);
_mediaPlayer4 = new MediaPlayer(_libVLC1);
media1 = new Media(_libVLC1, #"D:Video.mp4", FromType.FromPath);
media2 = new Media(_libVLC1, #"D:Video2.mp4", FromType.FromPath);
media3 = new Media(_libVLC1, #"D:Video3.mp4", FromType.FromPath);
media4 = new Media(_libVLC1, #"D:Video4.mp4", FromType.FromPath);
_mediaPlayer1.Media = media1;
_mediaPlayer2.Media = media2;
_mediaPlayer3.Media = media3;
_mediaPlayer4.Media = media4;
videoView1.MediaPlayer = _mediaPlayer1;
videoView2.MediaPlayer = _mediaPlayer2;
videoView3.MediaPlayer = _mediaPlayer3;
videoView4.MediaPlayer = _mediaPlayer4;
so to send all 4 to same time i use
foreach (var player in _PlayersCollection)
{
player.Time = 12000);
}
the problem is when click button the if the videos are playing it moves straight to the new time location.
if the videos are paused the videos twitch like they are moving just one frame, then you if click again they jump to the right time location.
this is very annoying and i cant see a reason why.
I saw a tip online to suggest setting the output renderer for the lib to D3d9 instead of D3d11 but i cant find any examples of how to change that for this lib.
Does anyone have any suggestions please who is familiar with lib on winforms.
thanks
I also noticed this problem in vlc.dotnet
Looks like the player does not like it's time too be changed to fast.
My solution was to limit the update rate of my tracker.
Some thing similar may work for you.
long lngLastScrollTimeStamp=0;
private void trkVideo_Scroll(object sender, EventArgs e)
{
if (((Stopwatch.GetTimestamp() / TimeSpan.TicksPerMillisecond) - lngLastScrollTimeStamp) > 250)
{
vlcControl1.Time = trkVideo.Value;
lngLastScrollTimeStamp = Stopwatch.GetTimestamp() / TimeSpan.TicksPerMillisecond;
}
}

c# - how to remove the interval between two timer ticks

I am using timer to connect several audio files together. There are a list of audio files and the timer will read files one by one. Once there is an audio read, it will be played. The goal is to play the audio file right after the previous one when it is finished(without any break).
(I am using Naudio)
Here is the code:
private void timer_key_Tick(object sender, EventArgs e)
{
if(!isPlaying)
{
//play the current audio
DirectSoundOut dso = sounds2[key_indexer];
dso.Play();
targetMusics.Add(dso);
}
else
{
foreach (DirectSoundOut dso in targetMusics)
{//stop the current audio
dso.Stop();
}
targetMusics.Clear();
key_indexer++; //switch to the next audio
if (key_indexer >= myMT.Keys.Count)
{
key_indexer = 0;
timer_key.Stop();
}
}
isPlaying = !isPlaying;
}
However, the fact is, when the first music finished, the second one didn't play at once. It comes after one second break. Is this the problem about timer itself? How should I change it?
Thanks for the help from #HansPassant. I made a mistake about logic in this timer. Here is the correct code after I applied his suggestion:
//stop the current playing
foreach(DirectSoundOut d in targetMusics)
{
d.Stop();
}
targetMusics.Clear();
//stop the entire process
if (key_indexer >= myMT.Keys.Count)
{
key_indexer = 0;
timer_key.Stop();
}
else
{ //play the current audio
DirectSoundOut dso = sounds2[key_indexer];
targetMusics.Add(dso);
dso.Play();
key_indexer++;
}

How to get current time while streaming mp3 using NAudio?

I have a code to stream mp3 from url. I want to show the current time of the mp3 player in UI. I tried it using WaveOut.GetPosition, but it couldn't work for me.
How can I do that?
My code:
do
{
//..codes to get url stream,to create BufferedWaveProvider
int decompressed = decompressor.DecompressFrame(frame, buffer, 0);
provider.AddSamples(buffer, 0, decompressed);
if (provider.BufferedDuration.Seconds > 2 && waveOut == null)
{
waveOut = new WaveOut();
waveOut.Init(provider);
waveOut.Play();
}
if (waveOut != null)
{
currentTime = (int)(waveOut.GetPosition() * 1d / AvgBytesPerSec);
}
}
while (bytesRead > 0 || waveOut.PlaybackState == PlaybackState.Playing);
I think the only change you need to make to your code is to use waveOut.OutputWaveFormat.AverageBytesPerSecond instead of the AvgBytesPerSec property you are currently using. The IWavePosition interface (which is what you are actually using here) "thinks" in hardware terms, so if you are using a format that has to be converted before the hardware can use it, the hardware byte rate will be different than your source byte rate.
Note that the position returned by GetPosition() is only since playback was last started. If waveOut.Stop() is called, the position is reset to 0 when playback is started again. Mapping the position to the source is up to the caller (which is really simple; just track where you last started playback on the source and add it to the position returned. Buffering makes it more complicated, but still completely doable).
I wrote the original IWavePosition interface & implementations for NAudio. It works great in the project I built it for. :)
did you try the property current time and property position?
mp3Reader = new Mp3FileReader("example.mp3");
waveOut.Init(mp3Reader);
waveOut.Play();
// reposition to five seconds in
mp3Reader.CurrentTime = TimeSpan.FromSeconds(5.0);
so mp3Reader.CurrentTime should give you what you need I think
Hope this will help you

Unity3D access variable set through Xcode

I am creating an app that uses the devices camera.
I need to implement a function that checks if the user has allowed the app to access the devices camera, if they have not, the scene that uses the camera just shows a black screen.
Because Unity only supports Application.HasUserAuthorization in the webplayer platform I need to add the authorization check to the project through XCode after build.
Firstly I added the following code to didFinishLaunchingWithOptions in the UnityAppController.mm file:
// Determine camera access on iOS >= 7
if ([AVCaptureDevice respondsToSelector:#selector(requestAccessForMediaType:completionHandler:)]) {
// Completion handler will be dispatched on a separate thread
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (YES == granted) {
// User granted access to the camera, continue with app launch
CameraIsAvailable = YES;
CameraCheckDone = YES;
}
else {
CameraIsAvailable = NO;
CameraCheckDone = YES;
}
}];
}
else {
// iOS < 7 (camera access always OK)
CameraCheckDone = YES;
// Continue with app launch...
}
and the follwoing code to applicationDidBecomeActive
while (!CameraCheckDone) { }
if(!CameraIsAvailable){
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Authorize Camera"
message:#"Instructions go here"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
The result is that every time the app is run, a popup appears instructing the user to activate the camera, which is progress, but they still have access to the scene that shows the black screen instead of the camera view.
Is there any way that I can access the CameraIsAvilable variable from within Unity?
Any suggestions would be greatly appreciated! TIA!
I solved the problem by using the UnitySendMessage function.
Firstly I updated didFinishLaunchingWithOptions in UnityAppController.mm, here is the modified code:
// Determine camera access on iOS >= 7
if ([AVCaptureDevice respondsToSelector:#selector(requestAccessForMediaType:completionHandler:)]) {
// Completion handler will be dispatched on a separate thread
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (YES == granted) {
// User granted access to the camera, continue with app launch
CameraIsAvailable = YES;
CameraCheckDone = YES;
// ADDED THE FOLLOWING LINE THAT SENDS VALUE "YES" WHEN CAMERA ALLOWED
UnitySendMessage("iOSManager", "cameraCheck", "YES");
}
else {
CameraIsAvailable = NO;
CameraCheckDone = YES;
// ADDED THE FOLLOWING LINE THAT SENDS VALUE "NO" WHEN CAMERA IS NOT ALLOWED
UnitySendMessage("iOSManager", "cameraCheck", "NO");
}
}];
}
else {
// iOS < 7 (camera access always OK)
CameraCheckDone = YES;
// Continue with app launch...
}
Then in Unity3D, I added a GameObject called "iOSManager" to the first scene of my game (note: the GameObject name must match the first parameter of the UnitySendMessage function).
I created the following script with the cameraCheck() function (the function name matches the second parameter of the UnitySendMessage function):
#if UNITY_IOS
void cameraCheck(string value)
{
// DO SOMETHING WITH VALUE
}
#endif
Where the string "value" is the value sent from UnitySendMessage
Now I can use this value in Unity3D

How to get the duration of mp3 file without playing or storing them

I am building a wp8 app which could play poems line by line displayed in listbox.
Say I have 20 lines of Poems showing as 20 items in listbox. I have 20 mp3 files (one for each line), I used BackgroundAudioPlayer to play individual files and select each item (poem) in listbox. During playback of these mp3 files, there were delays of 1-3 seconds, so I found the full version of these mp3 files (20 files merged into one), reading poems line by line.
I am playing this mp3 file using BackgroundAudioPlayer. Playing as one file, I cannot select each item in listbox as I don't know the line number by playing one mp3 file.
Now what I want is to store the duration of 20 files in seconds, without storing and playing. The files are located in a link (http:123.com/1.mp3, /2.mp3, ...)
I used AudioTrack with absolute path and then used duration property, but it always returns zero. How can I get the duration of an mp3 file without playing them?
Edited:
In the background Agent I did below:
protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)
{
switch (playState)
{
case PlayState.TrackReady:
TrackDuration tr = DataSource.Connection.Table<TrackDuration>().SingleOrDefault();
if (tr.IsGetTrackDuration)
{
if (player.Track != null)
{
player.Position = TimeSpan.FromSeconds(player.Track.Duration.TotalSeconds);
Recitation r = DataSource.Connection.Query<Recitation>("select * from Recitation where ID = " + player.Track.Title).SingleOrDefault();
r.AyaDuration = player.Track.Duration.TotalSeconds;
DataSource.saveRecitionDownloaded(r);
PlayNextTrack(player);
}
}
break;
}
NotifyComplete();
}
protected override void OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param)
{
switch (action)
{
case UserAction.Play:
PlayTrack(player);
break;
case UserAction.Seek:
if (null!=player.Track)
player.Position = (TimeSpan)param;
break;
}
NotifyComplete();
}
private void PlayNextTrack(BackgroundAudioPlayer player)
{
if (++currentTrackNumber >= audioTrack.Count)
return;
PlayTrack(player);
}
private void PlayTrack(BackgroundAudioPlayer player)
{
//If No Track then load Track
if (audioTrack.Count == 0)
{
//Load Tracks and Add them into Track Play List
}
if ((player.Track == null) || (player.Track.Title != audioTrack[currentTrackNumber].Title))
player.Track = audioTrack[currentTrackNumber];
if ((player.Track != null) && (player.PlayerState != PlayState.Playing))
player.Play();
}
The question is It plays some of the files which I don't want. (tr.IsGetTrackDuration) is always true, but I don't know why it plays some?
MusicProperties class has a property for the duration
MusicProperties musicProperties = await file.Properties.GetMusicPropertiesAsync();
outputText.AppendLine("Duration: " + musicProperties.Duration);
Ok I have a thought here. Under the AudioPlayer class, there is a TrackReady event that is set by default to play the track. Instead of playing by default, set a bool to true if you're simply wanting to obtain the duration, and false if you actually wish to play a track (when you're wanting to play the full mp3).
The bool value would have to be set in the main app before the track is set, and then read in the AudioPlayer each time the OnPlayStateChanged is called.
protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)
{
//read GettingDuration value here
try
{
switch (playState)
{
case PlayState.TrackReady:
if (GettingDuration)
{
//store duration somehow and get the next track in line
}
else
{
player.Play();
}
break;
}
}
}

Categories