I have a simple WinForms solution with 2 video players one is Vlc.DotNet and the second is libvlcsharp
and besides that, I have a simple button that plays both videos.
for libvlcsharp i followed this example
and for Vlc.DotNet i used this example
further more im attaching both logFiles
Loglibvlcsharp.txt and LogVlcDotNet
this is my code
public partial class QueueDisplayVideoView : Form
{
private string[] paths, files;
private int videoIndex = 0;
public LibVLC _libVLC;
public MediaPlayer _mp;
public LibVLCSharp.Shared.Media media;
public QueueDisplayVideoView()
{
InitializeComponent();
Core.Initialize();
_libVLC = new LibVLC(enableDebugLogs:true);
_libVLC.SetLogFile(#"C:\Temp\LogLib.txt");
_mp = new MediaPlayer(_libVLC);
videoView.MediaPlayer = _mp;
}
protected override void OnLoad(EventArgs e)
{
_presenter.OnViewReady();
base.OnLoad(e);
LoadVideoFiles();
SetPlayerAspectRatio();
//StartAutoPlay();
}
private void StartAutoPlay()
{
vlcControl.Play(new Uri(paths[videoIndex]));
_mp.Play(new LibVLCSharp.Shared.Media(_libVLC, new Uri(paths[videoIndex])));
}
private void LoadVideoFiles()
{
var path = some path
paths = Directory.GetFiles(path, "*", SearchOption.AllDirectories);
files = new string[paths.Length];
for (int i = 0; i < paths.Length; i++)
{
files[i] = Path.GetFileName(paths[i]);
}
}
private void SetPlayerAspectRatio()
{
var videoWidth = vlcControl.Width.ToString();
var videoHieght = vlcControl.Height.ToString();
vlcControl.Video.AspectRatio = videoWidth + ":" + videoHieght;
}
private void vlcControl_VlcLibDirectoryNeeded(object sender, Vlc.DotNet.Forms.VlcLibDirectoryNeededEventArgs e)
{
// var currentAssembly = System.Reflection.Assembly.GetEntryAssembly();
var currentDirectory = #"Q:\bin"; //new FileInfo(currentAssembly.Location).DirectoryName;
// Default installation path of VideoLAN.LibVLC.Windows
var fullPath = Path.Combine(currentDirectory, "libvlc", IntPtr.Size == 4 ? "win-x86" : "win-x64");
e.VlcLibDirectory = new DirectoryInfo(fullPath);
}
private void vlcControl_EndReached(object sender, Vlc.DotNet.Core.VlcMediaPlayerEndReachedEventArgs e)
{
GetNextVideoIndex();
ThreadPool.QueueUserWorkItem(_ => vlcControl.Play(new Uri(paths[videoIndex])));
}
private void button1_Click(object sender, EventArgs e)
{
StartAutoPlay();
}
private void GetNextVideoIndex()
{
if (videoIndex < files.Length - 1)
{
videoIndex = videoIndex + 1;
}
else
{
videoIndex = 0;
}
}
}
Have you tried using this?
it should be native to winforms,all you have to do choose the right .dll at toolbox-> choose items-> com compoents-> windows media player.
Related
I am writing a theater mode section in music player. The requirements is to loop through a folder containing images of any type(png, jpeg, gif) and show in a picture box with 5 seconds delay for images of type (png,jpeg) and delay time for gif should be the actual gif time duration. Also there should be fade transition between images when switch from one image to another in a single picture box. All need to be done when software is idle lets say for 60 seconds
Problem
Currently the playing song directory has 'img' folder containing 3 png
images and 3 gif. The first attempt to read
Helper.theaterImagesInfo.ToList() works pretty well
foreach (var img in Helper.theaterImagesInfo.ToList())
It starts to display 3 png images with 5 seconds delay and gif images
with the actual gif duration delay. but if i click picturebox to close theaterform as soon as the form is opened again after 60 seconds of idle state of software and loop continue
to iterate again. The default image is shown with
starting 2 png images from 'img' folder the 3rd png is skipped and then 4th gif starts
to play for few seconds not the actual gif duration and continued in wrong order as well as incorrect delay, Seems like while loop is always running in background. therfore it becomes choppy.
Desired Solution
Whenever i play song theaterform should be displayed and start to show images from folder ( in the same sequence and delay) even if the theaterform is opened again after 60 seconds if the song is still playing. Also if there is a way to show fade when changing image in a single picturebox
Code here
Program.cs
internal static class Program
{
public static Timer IdleTimer = new Timer();
readonly static int miliseconds =
Convert.ToInt32(TimeSpan.FromSeconds(60).TotalMilliseconds);
internal static MainForm f = null;
static public TheaterForm tf;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MessageFilter limf = new MessageFilter();
Application.AddMessageFilter(limf);
Application.Idle += new EventHandler(Application_Idle);
IdleTimer.Interval = miliseconds;
IdleTimer.Tick += TimeDone;
IdleTimer.Start();
f = new MainForm();
tf = new TheaterForm();
var app = new MyApplication();
app.Run(Environment.GetCommandLineArgs());
Application.Idle -= new EventHandler(Application_Idle);
}
static private void Application_Idle(Object sender, EventArgs e)
{
if (!IdleTimer.Enabled) // not yet idling?
IdleTimer.Start();
}
static private void TimeDone(object sender, EventArgs e)
{
IdleTimer.Stop();
if (MainForm.waveOut.PlaybackState == PlaybackState.Playing)
{
if (!Helper.IsTheaterOpen)
{
if (Form.ActiveForm == f)
{
Helper.IsTheaterOpen = true;
tf.WindowState = FormWindowState.Maximized;
tf.Bounds = Screen.PrimaryScreen.Bounds;
tf.x = 1;
tf.ShowDialog(f);
}
}
}
else
{
if (!Helper.IsTheaterOpen)
{
if (Form.ActiveForm == f)
{
Helper.IsTheaterOpen = true;
tf.WindowState = FormWindowState.Maximized;
tf.Bounds = Screen.PrimaryScreen.Bounds;
tf.x = 0;
tf.ShowDialog(f);
}
}
}
}
}
public class MyApplication : WindowsFormsApplicationBase
{
protected override void OnCreateMainForm()
{
MainForm = Program.f;
}
protected override void OnCreateSplashScreen()
{
SplashScreen = new SplashForm();
}
}
Helper.cs
internal class Helper
{
public static bool IsTheaterOpen { get; set; }
public struct ImageInfo
{
public bool IsAnimated;
public int durationInMilliseconds;
public Image ImageHere;
}
public static List<ImageInfo> theaterImagesInfo = new List<ImageInfo>(10);
}
MainForm.cs
/*
* Every song directory has one folder named img that contains images and gif relevant
to the song album
*/
private int GetGifDuration(Image img)
{
int delay = 0, this_delay = 0, index = 0;
FrameDimension frameDimension = new FrameDimension(img.FrameDimensionsList[0]);
int frameCount = img.GetFrameCount(frameDimension);
for (int f = 0; f < frameCount; f++)
{
this_delay = BitConverter.ToInt32(img.GetPropertyItem(20736).Value, index) * 10;
delay += (this_delay < 100 ? 100 : this_delay); // Minimum delay is 100 ms
index += 4;
}
return delay;
}
private void PlayAudio()
{
// Getting images from folder and storing in struct on every song play
if (Directory.Exists(Path.GetDirectoryName(CurrentPlayingMusicUrl) + "\\img"))
{
var files =
Directory.EnumerateFiles(Path.GetDirectoryName(CurrentPlayingMusicUrl) +
"\\img", "*", SearchOption.AllDirectories).Where(s => s.EndsWith(".png") ||
s.EndsWith(".jpg") || s.EndsWith(".jpeg") || s.EndsWith(".gif"));
Helper.theaterImagesInfo.Clear();
foreach (var imagePath in files.ToArray())
{
using (System.Drawing.Image image = System.Drawing.Image.FromFile(imagePath))
{
if (image.RawFormat.Equals(ImageFormat.Gif))
{
Helper.theaterImagesInfo.Add(new Helper.ImageInfo { IsAnimated = true, durationInMilliseconds = GetGifDuration(image), ImageHere = Image.FromFile(imagePath) });
}
else
{
Helper.theaterImagesInfo.Add(new Helper.ImageInfo { IsAnimated = false, durationInMilliseconds = 5000, ImageHere = Image.FromFile(imagePath) });
}
}
}
}
else
{
Helper.theaterImagesInfo.Clear();
Program.tf.x = 0;
}
}
TheaterForm.cs
public partial class TheaterForm : Form
{
public TheaterForm()
{
InitializeComponent();
SetDefaultImage();
}
/*
* Getting Default image from top(root) directory ex. AllMusic. If no 'img' folder
found in song album directory ex. AllMusic -> Justin Bieber -> (img folder not
exist)song1, song2, song3 etc.
*/
private async void SetDefaultImage()
{
string path = KJ_Player.Properties.Settings.Default["MusicFolder"] + "\\img";
if (Directory.Exists(path))
{
var files = Directory.EnumerateFiles(path, "*",
SearchOption.AllDirectories).Where(s => s.EndsWith(".png") ||
s.EndsWith(".jpg") || s.EndsWith(".jpeg"));
await Task.Run(() =>
{
if(files != null && files.Count()>0)
{
PictureBox1.Image = Image.FromFile(files.FirstOrDefault());
}
});
}
}
public int x=1;
private async void TheaterForm_Shown(object sender, EventArgs e)
{
if (this.PictureBox1.Image == null) SetDefaultImage();
if (Helper.theaterImagesInfo != null && Helper.theaterImagesInfo.Count > 0)
{
while (x == 1)
{
foreach (var img in Helper.theaterImagesInfo.ToList())
{
if (img.IsAnimated)
{
try
{
this.PictureBox1.Image = img.ImageHere;
await Task.Delay(img.durationInMilliseconds);
}
catch { }
}
else
{
try
{
await Task.Delay(img.durationInMilliseconds);
this.PictureBox1.Image = img.ImageHere;
}
catch { }
}
}
}
SetDefaultImage();
}
}
private void PictureBoxTheater_Click(object sender, EventArgs e)
{
this.x = 0;
if (this.PictureBox1.Image != null) this.PictureBox1.Image=null;
Helper.IsTheaterOpen = false;
this.Close();
}
}
Most likely you just need to break out of that foreach loop:
foreach (var img in Helper.theaterImagesInfo.ToList())
{
if (img.IsAnimated)
{
try
{
this.PictureBox1.Image = img.ImageHere;
await Task.Delay(img.durationInMilliseconds);
}
catch { }
}
else
{
try
{
await Task.Delay(img.durationInMilliseconds);
if (this.x == 1) {
this.PictureBox1.Image = img.ImageHere;
}
}
catch { }
}
if (this.x == 0) {
break; // exit the for loop early
}
}
I am trying to make a simple app that grabs all *.jpg files from a folder, and displays them in PictureBox.
However i'm trying to make Prev/Next buttons to show images one by one. Here's my code for the Next button so far:
string path = #"..\..\Resources\Wallpapers\";
int count = 0;
private void Form1_Load(object sender, EventArgs e)
{
DisplayNextFile(count);
}
private void next_Click(object sender, EventArgs e)
{
DisplayNextFile(count);
}
private void DisplayNextFile(int c)
{
var rand = new Random();
var files = Directory.GetFiles(path, "*.jpg");
var images = new Image[files.Length];
for (int i = c; i < files.Length; ++i)
{
images[i] = Image.FromFile(files[i]);
picBoxMainPreview.Image = images[i];
break;
}
count++;
if (count == files.Length)
count = 0;
}
It works fine, but how can I do it for the Previous button?
Remove count++; from DisplayNextFile.
private void next_Click(object sender, EventArgs e)
{
count = (++count) % files.Length;
DisplayNextFile(count);
}
private void previous_Click(object sender, EventArgs e)
{
count = (count - 1) >= 0 ? count - 1 ? files.Length - 1;
DisplayNextFile(count);
}
Replace the for loop with:
picBoxMainPreview.Image = Image.FromFile(c);
I would like that when the form loads and/or starts my picture slide will start automatically.I tried to put the path of where the folder is located but it keeps giving an error. When I use it a dialog box it works. I am trying to bypass the dialog box so it starts automatically.
public partial class Form1 : Form
{
private string[] folderFile = null;
private int selected = 0;
private int end = 0;
FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog();
// The folder is pre created
string path1 = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "\\Pictures";
public Form1()
{
InitializeComponent();
//This does not work when the form starts up.
if (!Directory.Exists(path1))
{
string[] part1 = null, part2 = null, part3 = null;
part1 = Directory.GetFiles(path1, "*.jpg");
part2 = Directory.GetFiles(path1, "*.jpeg");
part3 = Directory.GetFiles(path1, "*.bmp");
folderFile = new string[part1.Length + part2.Length + part3.Length];
Array.Copy(part1, 0, folderFile, 0, part1.Length);
Array.Copy(part2, 0, folderFile, part1.Length, part2.Length);
Array.Copy(part3, 0, folderFile, part1.Length + part2.Length, part3.Length);
selected = 0;
//begin = 0;
end = folderFile.Length;
showImage(folderFile[selected]);
// 5 to 10 second intervals
//timer1.Enabled = true;
}
else
{
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
nextImage();
}
private void btnFolder_Click(object sender, EventArgs e)
{
//Original
//This works!!
//while (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
//{
// string[] part1 = null, part2 = null, part3 = null;
// part1 = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.jpg");
// part2 = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.jpeg");
// part3 = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.bmp");
// folderFile = new string[part1.Length + part2.Length + part3.Length];
// Array.Copy(part1, 0, folderFile, 0, part1.Length);
// Array.Copy(part2, 0, folderFile, part1.Length, part2.Length);
// Array.Copy(part3, 0, folderFile, part1.Length + part2.Length, part3.Length);
// selected = 0;
// //begin = 0;
// end = folderFile.Length;
// showImage(folderFile[selected]);
// //btnPrev.Enabled = true;
// //btnNext.Enabled = true;
// //btnStartSlide.Enabled = true;
//}
}
private void showImage(string path)
{
Image imgtemp = Image.FromFile(path);
//pictureBox1.Width = imgtemp.Width / 2;
//pictureBox1.Height = imgtemp.Height / 2;
//pictureBox1.Image = imgtemp;
panel1.BackgroundImage = imgtemp;
}
private void prevImage()
{
if (selected == 0)
{
selected = folderFile.Length - 1;
showImage(folderFile[selected]);
}
else
{
selected = selected - 1;
showImage(folderFile[selected]);
}
}
private void nextImage()
{
if (selected == folderFile.Length - 1)
{
selected = 0;
showImage(folderFile[selected]);
}
else
{
selected = selected + 1;
showImage(folderFile[selected]);
}
}
private void btnPreviews_Click(object sender, EventArgs e)
{
prevImage();
}
private void btnNext_Click(object sender, EventArgs e)
{
nextImage();
}
private void btnStart_Click(object sender, EventArgs e)
{
if (timer1.Enabled == true)
{
timer1.Enabled = false;
btnStart.Text = "<< START >>";
}
else
{
timer1.Enabled = true;
btnStart.Text = "<< STOP >>";
}
}
}
}
Try
string path1 = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) + "\\Sample_Pictures";
or
string path1 = Environment.GetFolderPath(Environment.SpecialFolder.CommonPictures) + "\\Sample_Pictures";
Or use
string publicDesktopPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory);
var directory = new DirectoryInfo(publicDesktopPath);
string path1 = directory.Parent.FullName + "\\Pictures\\Sample_Pictures";
and fix your conditional
if (!Directory.Exists(path1)) {
to
if (Directory.Exists(path1)) {
so that you don't try operations on an non-existent directory.
To get it to cycle through your pictures, you could use a System.Timers.Timer:
In your Form1 class
private static Timer timer;
Declare the timer in your constructor:
timer = new System.Timers.Timer(5000); // change interval in milliseconds
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
Create the OnTimedEvent method in your Form1 class:
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
// Do what you want every time the timer elapses that interval
nextImage();
}
I'm quite new to this things. Actually it is my first work. I want a program that reads random file count from textbox. and it has a button to randomize files from selected path. I need to open files in the listbox.
My problem is when I double click on the listbox, it opens the last file in the list no matter what file I d.clicked. I tried to add lines that put two slash before below. But it also didnt work. What can I do?
public Form1()
{
InitializeComponent();
}
Random r = new Random();
string path1;
DirectoryInfo dif;
FileInfo[] files;
int randomchoose;
//FileInfo[] files2;
//int hoho;
int[] randomcount;
private void button1_Click(object sender, EventArgs e)
{
FolderBrowserDialog hoho = new FolderBrowserDialog();
hoho.ShowNewFolderButton = true;
if (hoho.ShowDialog() == DialogResult.OK)
{
path1 = hoho.SelectedPath;
textBox1.Text = path1;
dif = new DirectoryInfo(path1);
files = dif.GetFiles();
}
}
private void btnrasgele_Click(object sender, EventArgs e)
{
randomcount = new int[Convert.ToInt32(textBox3.Text)];
// int hoho=0;
foreach (int k in randomcount)
{
int pd = files.Length;
randomchoose = r.Next(0, Convert.ToInt32(pd + 1));
listBox1.Items.Add(files[randomchoose]);
//files2[hoho] = files[randomchoose].FullName;
}
}
private void listBox1_MouseDoubleClick(object sender, MouseEventArgs e)
{
//listBox1.SelectedIndex = hoho;
//Process.Start(files2[hoho].FullName);
Process.Start(files[randomchoose].FullName);
}
You passed in the randomchoose which is fixed at that point, try this instead:
private void listBox1_MouseDoubleClick(object sender, MouseEventArgs e)
{
if(listBox1.SelectedItem != null)
Process.Start(((FileInfo)listBox1.SelectedItem).FullName);
}
I'm trying to make a slideshow with a mediaElement that shows each image in listbox x seconds.
How do I make my code play each image x seconds before continuing?
This code adds all images to a listbox named Listbox1
Dictionary<string, string> Listbox1Dict = new Dictionary<string, string>();
private void SearchBtn_Click(object sender, RoutedEventArgs e)
{
Listbox1.Items.Clear();
FolderBrowserDialog folderDialog = new FolderBrowserDialog();
folderDialog.SelectedPath = "C:\\";
DialogResult result = folderDialog.ShowDialog();
if (result.ToString() == "OK")
FileNameTextBox.Text = folderDialog.SelectedPath;
string directory = FileNameTextBox.Text;
var files = Directory.GetFiles(directory).Where(name => !name.EndsWith(".ini"));
foreach (string file in files)
{
Listbox1.Items.Add(System.IO.Path.GetFileNameWithoutExtension(file));
Listbox1Dict.Add(System.IO.Path.GetFileNameWithoutExtension(file), file);
}
}
This code shows all images in fullscreen but it skips everyone to last image at start.
private void button1_Click_1(object sender, RoutedEventArgs e)
{
foreach (var selected in Listbox1.Items)
{
string s = selected.ToString();
if (Listbox1Dict.ContainsKey(s))
{
mediaElement1.Visibility = Visibility.Visible;
SearchBtn.Visibility = Visibility.Hidden;
Listbox1.Visibility = Visibility.Hidden;
FileNameTextBox.Visibility = Visibility.Hidden;
mediaElement1.Source = new Uri(Listbox1Dict[s]);
mediaElement1.Width = System.Windows.SystemParameters.PrimaryScreenWidth;
mediaElement1.Height = System.Windows.SystemParameters.PrimaryScreenHeight;
this.Background = new SolidColorBrush(Colors.Black);
this.WindowStyle = WindowStyle.None;
this.WindowState = WindowState.Maximized;
}
}
}
Tried this code to make the image play one by one but I get an error. Look on comment on code:
private int currentSongIndex = -1;
void mediaElement1next(object sender, EventArgs e)
{
if(currentSongIndex == -1)
{
currentSongIndex = Listbox1.SelectedIndex;
}
currentSongIndex++;
if(currentSongIndex < Listbox1.Items.Count)
{
mediaElement1.Play(Listbox1.Items[currentSongIndex]); // No overload for method 'Play' takes 1 arguments
}
else
{
// last song in listbox has been played
}
}
I think you need a timer to set your next image. Using the code you're currently using, it will iterate through your list and change the image until you get to the end.
Take a look at DispatcherTimer. You could set it so, at each tick, it would change to the next image. Something like this (just writing off my head)
dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
Then, inside your eventhandler:
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
// get the next image
}
Of course you can use other kinds of timers, but that's the main idea.
Hold your image paths in a list & use the tick event of a timer.
Something like:
List<string> paths = new List<string>();
private void timer1_Tick(object sender, EventArgs e)
{
pictureBox1.Image = getNextImage();
}
private string getNextImage()
{
//code...
}
enter code here
EDIT:
Add a class variable: int index = 0;
On the SearchBtn_Click event, add the results to the list.
//..
foreach (string file in files)
{
paths.Add(file);
}
//..
Then do as I did above and the content of the getNextImage method would be:
private string getNextImage()
{
if(index < paths.Count - 1)
{
index += 1;
}
else
{
index = 0;
}
return paths[index];
}
My idea would be to implement a thread that counted to X and then called a NextImage() function when done.
Something like this:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (Listbox1.Items.Count > 0)
{
if (dispatcherTimer.IsEnabled)
dispatcherTimer.Stop();
else
{
curImage = 0;
dispatcherTimer.Start();
}
}
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
Dispatcher.Invoke((Action)delegate
{
ShowNextImage();
}, null);
}
private void ShowNextImage()
{
if (curImage >= Listbox1.Items.Count)
curImage = 0;
var selected = Listbox1.Items[curImage];
string s = selected.ToString();
if (Listbox1Dict.ContainsKey(s))
{
mediaElement1.Visibility = Visibility.Visible;
SearchBtn.Visibility = Visibility.Hidden;
Listbox1.Visibility = Visibility.Hidden;
FileNameTextBox.Visibility = Visibility.Hidden;
mediaElement1.Source = new Uri(Listbox1Dict[s]);
mediaElement1.Width = System.Windows.SystemParameters.PrimaryScreenWidth;
mediaElement1.Height = System.Windows.SystemParameters.PrimaryScreenHeight;
this.Background = new SolidColorBrush(Colors.Black);
this.WindowStyle = WindowStyle.None;
this.WindowState = WindowState.Maximized;
}
}
and declaration
DispatcherTimer dispatcherTimer = new DispatcherTimer();
int x = 2; //seconds
private int curImage = 0;
and some construct
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, x);