C# Creating, Saving, and Playing a Playlist using ListBox - c#

Beginner here with C# coding. I built a media player that allows the administrator to create and save a playlist. The guest should be able to load the playlist and play the songs on the said playlist. Unfortunately, every time the guest loads a playlist created, error pops out when trying to play any songs on the playlist. It seems to only load the path details but not the actual media.
"An unhandled exception of type 'System.IndexOutOfRangeException' occurred in WindowsFormsApplication1.exe
Additional information: Index was outside the bounds of the array."
This is the code under the list box I have:
axWindowsMediaPlayer1.URL = paths[lbPlaylist.SelectedIndex];
The code code below is coded under the "Create Playlist" button:
private void btnCreate_Click(object sender, EventArgs e)
{
OpenFileDialog newPlaylist = new OpenFileDialog();
newPlaylist.InitialDirectory = "C:\\Users\\mklsingh\\Documents\\Visual Studio 2013\\Projects\\Media Player\\WindowsFormsApplication1\\Media Files";
newPlaylist.Filter = "MP3 Audio File (*.mp3)|*.mp3| Windows Media File (*.wma)|*.wma|WAV Audio File (*.wav)|*.wav|All Files (*.*)|*.*";
newPlaylist.RestoreDirectory = false;
newPlaylist.Multiselect = true;
if (newPlaylist.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
files = newPlaylist.SafeFileNames;
paths = newPlaylist.FileNames;
for (int list = 0; list < files.Length; list++)
{
lbPlaylist.Items.Add(files[list]);
}
}
}
The code below saves the playlist as XML file:
private void btnSave_Click(object sender, EventArgs e)
{
StreamWriter Write;
SaveFileDialog savePlaylist = new SaveFileDialog();
savePlaylist.RestoreDirectory = false;
try
{
savePlaylist.InitialDirectory = "C:\\Users\\mklsingh\\Documents\\Visual Studio 2013\\Projects\\Media Player\\WindowsFormsApplication1\\Media Files\\Playlist";
savePlaylist.Filter = ("XML File|*.xml|All Files|*.*");
savePlaylist.ShowDialog();
Write = new StreamWriter(savePlaylist.FileName);
for (int I = 0; I < lbPlaylist.Items.Count; I++)
{
Write.WriteLine(lbPlaylist.Items[I]);
}
Write.Close();
MessageBox.Show("Playlist saved!");
}
catch //(Exception ex)
{
return;
}
}
The code below loads the saved XML playlist file:
private void btnLoad_Click(object sender, EventArgs e)
{
OpenFileDialog loadPlaylist = new OpenFileDialog();
loadPlaylist.Multiselect = false;
this.lbPlaylist.Items.Clear();
try
{
loadPlaylist.ShowDialog();
loadPlaylist.InitialDirectory = "C:\\Users\\mklsingh\\Documents\\Visual Studio 2013\\Projects\\Media Player\\WindowsFormsApplication1\\Media Files\\Playlist";
//txtLoad.Text = loadPlaylist.Filename;
StreamReader playlist = new StreamReader(loadPlaylist.FileName);
while (playlist.Peek() >= 0)
lbPlaylist.Items.Add(playlist.ReadLine());
txtLoad.Text = loadPlaylist.FileName;
}
catch
{
return;
}
}
Also, if a user selects a single song and play it, it'll work. If the user decides to add a song on the current playlist, the selected song will not play and same error will pop out. If I click "Clear List" and select a new song, it'll work though.
Please let me know your thoughts on my code. I am still a beginner and I find it hard to understand some of the codes I see online. Haha. Just want to make my Save Playlist and Create Playlist button work. Thanks.

Before you do
xWindowsMediaPlayer1.URL = paths[lbPlaylist.SelectedIndex];
Check to make sure selectedIndex actually exists in paths
if (lbPlaylist.SelectedIndex < paths.Length)
{
xWindowsMediaPlayer1.URL = paths[lbPlaylist.SelectedIndex];
}
else
{
// Display an error?
}
This should at least help you with debugging I would suggest putting a break point somewhere and checking to see what the value of paths is. It's possible you didn't initialize or add to it correct so you are trying to access an entry in the array that doesn't exist.

Related

Disable C# Form until external Excel application is closed

I have a button on a C# Windows forms application that runs the code below:
private void btnAddDataToCSV_Click(object sender, EventArgs e)
{
string path = "D:\MyCsvFile.csv";
Process.Start(path);
}
Basically, the user needs to be able to make changes to a CSV file. The user is most comfortable making these changes in Microsoft Excel. I found the above code online from someone who has many years of experience working with MS Office products and C#. This guy explained that the code below works but is more error prone than using "Process.Start()" as shown above.
string path = "D:\MyCsvFile.csv";
var ExcelApp = new Excel.Application();
ExcelApp.Workbooks.OpenText(path, Comma: true);
ExcelApp.Visible = true;
This guy explains that "Process.Start()" works because Windows is set up to use Excel as the default program for opening CSV files.
Anyways, when the user clicks the button above (btnAddDataToCSV), I need my C# form to become disabled (all the buttons grayed out) until the user closes the Excel workbook that is displaying the CSV file. Potentially, I may need the C# program to read the CSV file immediately after the user closes Excel.
Ho do I do this?
I assume... I need to do something like... "disable C# form... then Wait for Excel close event... then once excel close event happens... enable C# form and read CSV file."
Below is the code I have for reading the CSV file:
string path = "D:\MyCsvFile.csv";
var reader = new StreamReader(File.OpenRead(path));
List<string> listA = new List<string>();
List<string> listB = new List<string>();
List<string> listC = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
listA.Add(values[0]);
listB.Add(values[1]);
listC.Add(values[2]);
}
I think that you need to use an event handler for process that exits.
Something like this:
private void btnAddDataToCSV_Click(object sender, EventArgs e)
{
//disable form
string path = "D:\MyCsvFile.csv";
using (myProcess = new Process())
{
myProcess.EnableRaisingEvents = true;
myProcess.Exited += new EventHandler(Excel_Exit);
myProcess.Start(path);
}
}
public void Excel_Exit(object sender, System.EventArgs e){
//enableForm
}
Process.Exited example in documentation: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process.exited?view=netcore-3.1
I was unable to get the solution above to work even though the solution is similar to Microsoft's solution.
https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process.exited?view=netcore-3.1
I found this:
Why is my process's Exited method not being called?
It says:
"I've come across examples that place new Process() in a using clause. Do not do that if you want to use the Exited feature. The using clause destroys the instance along with any event handles on Exited."
It says:
using(var process = new Process())
Should be:
var process = new Process();
This makes no since because the link above that I provided for Microsoft is an example of how to use the "Process.Exited Event" and it uses "using(var process = new Process())"
But sure enough... for some reason when I tried "var process = new Process();" it worked... This is the code that worked:
private void btnAddDataToCSV_Click(object sender, EventArgs e)
{
var myProcess = new Process();
myProcess.EnableRaisingEvents = true;
myProcess.Exited += new EventHandler(Excel_Exit);
myProcess.StartInfo.FileName = "D:\\MyCsvFile.csv";
myProcess.Start();
}
public void Excel_Exit(object sender, System.EventArgs e)
{
MessageBox.Show("Success!!");
}
Here is the code that does not work... But I don't understand why because it is similar to Microsoft's example.
private Process myProcess;
private void btnAddDataToCSV_Click(object sender, EventArgs e)
{
using (myProcess = new Process())
{
myProcess.EnableRaisingEvents = true;
myProcess.Exited += new EventHandler(Excel_Exit);
myProcess.StartInfo.FileName = "D:\\MyCsvFile.csv";
myProcess.Start();
}
}
public void Excel_Exit(object sender, System.EventArgs e)
{
MessageBox.Show("Success!!");
}
When you close excel... the event never fires... Can someone explain this? Surely Microsoft's example isn't wrong.

download audio from youtube c#

I'm trying to download audio from youtube using YoutubeExtractor but if click the button i have information "sequence has no elements". How i can solve it?
private void button2_Click(object sender, EventArgs e)
{
try
{
IEnumerable<VideoInfo> videos = DownloadUrlResolver.GetDownloadUrls(textBox1.Text);
VideoInfo video = videos.Where(info => info.CanExtractAudio).OrderByDescending(info => info.AudioBitrate).First();
if (video.RequiresDecryption)
{
DownloadUrlResolver.DecryptDownloadUrl(video);
}
AudioDownloader download = new AudioDownloader(video, Path.Combine(Application.StartupPath + "\\", video.Title + video.AudioExtension));
download.Execute();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The issues is the call to First(). This will throw an exception if your IEnumerable contains no items.
To correct this, you need to be sure of two things:
The DownloadUrlResolver.GetDownloadUrls() function returns at least 1 item.
That at least one item in the videos variable has CanExtractAudio set to true.

Play audio from Assets folder in W10 universal app

I have several .wav and .mp3 files in my app under Assets/Audio, and I'm trying to play them when something is tapped in the UI. I've written the following code (with the file name hardcoded for testing purposes), but when the function is triggered, no sound plays. If I replace attempting to play from a file to playing an audio stream created by Windows.Media.SpeechSynthesis.SpeechSynthesizer, everything works fine.
private async void SoundItem_Tapped(object sender, TappedRoutedEventArgs e)
{
ListViewItem soundItem = sender as ListViewItem;
if (soundItem.IsSelected)
{
Uri sourceUri = new Uri(String.Format("ms-appx:///Assets/Audio/151Cry.wav", UriKind.Absolute));
await PlayAudio(sourceUri, soundItem);
}
else if (inUsePlayers.ContainsKey(soundItem))
{
MediaElement player = inUsePlayers[soundItem];
player.Stop();
inUsePlayers.Remove(soundItem);
players.Enqueue(player);
}
else
{
}
}
private async Task PlayAudio(Uri sourceUri, ListViewItem soundItem)
{
MediaElement player = RequestPlayer(soundItem);
player.Source = sourceUri;
player.IsLooping = true;
await player.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
player.Stop();
player.Play();
});
}
Here's the location of the file within the tree:
Aside from dragging the sound files into the project, I've haven't done anything. Maybe they need to be added to a resource file or copied to the output folder as well? I expected that something would throw an exception if the item pointed to by the URI didn't exist, but nothing's being thrown, even when I give it a bogus filename.
You need to do following things to play you media element.
Your resource files should be set to "Copy to Output directory"
value to "Copy if newer" or "Copy always". to do this right
click your resource file go to Properties and set Copy to Output directory value to Copy always and Build action to
content
Your player(MediaElement) should be added somewhere to View xaml
tree. I do not know your RequestPlayer method is adding
mediaEelement to view xaml or not. e.g
layoutRoot.Children.Add(player)
You need to register Player_MediaOpened event to play your
audio file. If you call 'play' before player is opened media will
not play the sound... and if you want that if any thing is happend
to your player not playing than register Player_MediaFailed it
will give you the reason why it is filed to play.
here is the code.
private async Task PlayAudio(Uri sourceUri, ListViewItem soundItem)
{
MediaElement player = RequestPlayer(soundItem);
player.IsLooping = true;
player.AutoPlay = false;
player.MediaOpened += Player_MediaOpened;
player.MediaFailed += Player_MediaFailed;
player.Source = sourceUri;
player.IsLooping = true;
//Add media element to xaml tree if not added by your RequestPlayer Method..
this.LayoutRoot.Children.Add(player);
}
private void Player_MediaFailed(object sender, ExceptionRoutedEventArgs e)
{
}
private async void Player_MediaOpened(object sender, RoutedEventArgs e)
{
await player.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
player.Play();
});
}
Hope this helps...

Increase Performance Navigating Through Pages

I’m using WinForms. My application works like a simple image document (tif) viewer. The tif/image documents I work with have multiple pages, so by pressing the next button my application goes to the next page. The problem with my application is that it is slow when I move to the next page. Previously, my application was slower. I’ve modified the application a little bit to make it faster, but it’s still not fast enough.
I’ve compared my application’s speed to Windows Photo Viewer and the result was that my application still needs improvement on performance. Does anyone know how I could make my application faster?
In the link below I’ve provided a sample tif document for testing purposes.
Link: http://www.filedropper.com/tiftestingdoc
My Code:
FileStream _stream;
Image _myImg; // setting the selected tiff
string _fileName;
private int intCurrPage = 0; // defining the current page
private void Open_Btn_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
lblFile.Text = openFileDialog1.FileName; //Shows the filename in the lable
Image img = Image.FromFile(openFileDialog1.FileName);
pictureBox1.Image = img;
Size size = new Size(img.Height, img.Width);
pictureBox1.Size = size;
Open_Image_Control();
}
}
public void Open_Image_Control()
{
Image myBmp;
if (_myImg == null) //I made a copy of the file because i want to be able to modify the file in the directory for example go to directory and delete the file while still having the ability to view it on the application
{
_fileName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
File.Copy(#"C:\my_Image_document", _fileName);
_stream = new FileStream(_fileName, FileMode.Open, FileAccess.Read);
_myImg = Image.FromStream(_stream);
}
int intPages = _myImg.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page); // getting the number of pages of this tiff
intPages--; // the first page is 0 so we must correct the number of pages to -1
lblNumPages.Text = Convert.ToString(intPages); // showing the number of pages
lblCurrPage.Text = Convert.ToString(intCurrPage); // showing the number of page on which we're on
_myImg.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, intCurrPage); // going to the selected page
myBmp = new Bitmap(_myImg, pictureBox1.Width, pictureBox1.Height);
//myBmp = new Bitmap(_myImg, pictureBox1.Height, pictureBox1.Width);
pictureBox1.Image = myBmp; // showing the page in the pictureBox1
}
private void NextPage_btn_Click(object sender, EventArgs e)
{
if (intCurrPage == Convert.ToInt32(lblNumPages.Text)) // if you have reached the last page it ends here
// the "-1" should be there for normalizing the number of pages
{ intCurrPage = Convert.ToInt32(lblNumPages.Text); }
else
{
intCurrPage++; //page increment (Goes to next page)
Open_Image_Control();
}
}
Load the image directly into the PictureBox, then to change pages call the pictureBox1.Image.SelectActiveFrame() method directly and refresh the PictureBox.
This prevents making new bitmaps copies of each page each time.
That was causing extra memory to be allocated each time and slowness while it copies all the pixels from the page.
Please see the code changes below:
// Variable to hold the current page number
private int intCurrPage = 0;
private int intTotalPages = 0;
private void Open_Btn_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
lblFile.Text = openFileDialog1.FileName;
// Before loading you should check the file type is an image
pictureBox1.Image = Image.FromFile(openFileDialog1.FileName);
pictureBox1.Size = new Size(pictureBox1.Image.Height, pictureBox1.Image.Width);
// Reset the current page when loading a new image
intCurrPage = 0;
intTotalPages = pictureBox1.Image.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);
lblNumPages.Text = intTotalPages.ToString();
}
}
private void NextPage_btn_Click(object sender, EventArgs e)
{
// Check that the current page is not going past the max page
if (intCurrPage < (intTotalPages-1))
{
//page increment (Go to next page)
intCurrPage++;
// Directly increment the active frame within the image already in the PictureBox
pictureBox1.Image.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, intCurrPage);
// Adjust the size of the picturebox control to the size of the current page.
// not sure if this is necessary, but including it due to prior example
pictureBox1.Size = new Size(pictureBox1.Image.Height, pictureBox1.Image.Width);
// Refresh the PictureBox so that it will show the currently active frame
pictureBox1.Refresh();
lblCurrPage.Text = intCurrPage.ToString();
}
}
Also, your code to copy the image had a hard coded directory name that was throwing errors for me, so I removed that.

C# Windows Forms: OpenFileDialog Strange Issues

This is kinda strange, let me try to explain it as best as possible:
When I create a new file and Save it, it saves correctly (test.xml).
When I make changes to this file and Save it, it saves correctly (to test.xml)
When I make changes again to this file or just choose Save As, it works correctly (newtest.xml)
However, when I do a file open, make changes to a file (test.xml) and click Save it is saving to (newtest.xml).
This is in my MainForm.cs
if (this.openEditorDialog1.ShowDialog(this) == DialogResult.OK && editForm != null)
{
editForm.Close();
editForm = new EditorForm(this);
editForm.OpenFile(this.openEditorDialog1.FileName);
editForm.Closing += new CancelEventHandler(EditorForm_Closing);
editForm.MdiParent = this;
editForm.Show();
}
private void biFileSave_Click(object sender, EventArgs e)
{
if (!editForm.HasFileName)
{
if (this.saveEditorDialog1.ShowDialog(this) == DialogResult.OK)
{
this.ActiveDiagram.SaveSoap(this.saveEditorDialog1.FileName);
editForm.FileName = this.saveEditorDialog1.FileName;
}
}
else
{
this.ActiveDiagram.SaveSoap(this.saveEditorDialog1.FileName);
}
This is in my EditorForm.cs
public void OpenFile(string strFileName)
{
diagramComponent.LoadSoap(mainForm.openEditorDialog1.FileName);
this.FileName = mainForm.openEditorDialog1.FileName;
this.tabControl1.SelectedTab = DiagramTab;
}
I'm sure it has to do with the what I'm doing in the EditoForm but I can't seem to figure it out.
else
{
this.ActiveDiagram.SaveSoap(this.saveEditorDialog1.FileName);
It looks like you want:
this.ActiveDiagram.SaveSoap(editForm.FileName);
It must have to do with mainForm.openEditorDialog1.FileName. Use a FileName property of the form that does the saving. When you open the file, set the fileName to mainForm.openEditorDialog1.FileName. When you SaveAs, set the FileName property there, too. This way, whenever the current file, changes you set the FileName property appropriately. Then, when it comes time to save the file, you always have the correct filename.
In summary, only use the .FileName property of the SaveAs dialog or the FileOpen dialog right after you use them.

Categories

Resources