I am new to C# and currently I am trying to make an audio player using BASS library. Right now I am creating the playlist using INI files like below:
[songs]
1=c:\lamfao.mp3
2=c:\test.mp3
[total_songs]
total=2
Everything is fine, but loading this type of INI file and showing it in ListView consumes a lot of time. Also there's no way to delete a song from this INI files. Hence, I am looking for help regarding loading and creating the playlists in C#. What I wanted to do is create a playlist with songs path and if possible with ID3 information like Album, Artist and Genre.
Also like other media players, for example WinAMP or MediaMonkey, they take no time to display the playlist, how this can be achieved. I am trying to show the playlist in ListView with Type=Details.
Is it possible to avoid the insertion of duplicate song in playlist?
Here's the current code which I am using to read INI files.
ListViewItem lvi;
ListViewItem.ListViewSubItem lvsi;
string name = "";
string album = "";
string artist = "";
string path = "";
if (File.Exists(CurrentPlaylistLocation))
{
this.progressBar1.Visible = true;
IniFile ini = new IniFile(CurrentPlaylistLocation); // INI Reading class in C# using Win32 API wrapper
string Total = ini.IniReadValue("Total_Files", "Total");
int items = Convert.ToInt32(Total);
this.progressBar1.Minimum = 0;
this.progressBar1.Maximum = items;
this.progressBar1.MarqueeAnimationSpeed = 100;
this.progressBar1.Style = ProgressBarStyle.Blocks;
int total = 0;
listView1.BeginUpdate();
for (int i = 1; i <= items; i++)
{
path = ini.IniReadValue("songs", Convert.ToString(i));
if(File.Exists(path))
{
// When user deletes a song from playlist, I add a .ignore in the last of song path
// so, check if a song is deleted by user, if deleted then do not add it
if (System.IO.Path.GetExtension(path).ToLower() != ".ignore")
{
PlayerEngine.GetTrackData(path, out name, out artist, out album); // Get META tag using Taglib sharp
lvi = new ListViewItem();
lvi.Text = name;
lvsi = new ListViewItem.ListViewSubItem();
lvsi.Text = album;
lvi.SubItems.Add(lvsi);
lvsi = new ListViewItem.ListViewSubItem();
lvsi.Text = artist;
lvi.SubItems.Add(lvsi);
lvsi = new ListViewItem.ListViewSubItem();
lvsi.Text = path;
lvi.SubItems.Add(lvsi);
this.listView1.BeginUpdate();
this.listView1.Items.Add(lvi);
this.listView1.EndUpdate();
total++;
this.progressBar1.Value = (i);
}
}
}
listView1.EndUpdate();
PlayerEngine.TotalTrackInTempPlaylist = listView1.Items.Count-1; // update the total number of songs loaded in player engine class
this.progressBar1.Visible = false;
MessageBox.Show("Playlist loading completed!");
Thanking you
Related
So, i followed a tutorial to "upload" files to a local path using ASP.net core,
this is the code:
public IActionResult About(IList<IFormFile> files)
{
foreach (var file in files)
{
var filename = ContentDispositionHeaderValue
.Parse(file.ContentDisposition)
.FileName
.Trim('"');
filename = hostingEnv.WebRootPath + $#"\{filename}";
using (FileStream fs = System.IO.File.Create(filename))
{
file.CopyTo(fs);
fs.Flush();
}
}
return View();
}
I want to read the extended properties of a file (file metadata)like:
name,
author,
date posted,
etc
and to sort the files using this data, is there a way using Iformfile?
If you want to access more file metadata then the .NET framework provides ootb, I guess you need to use a third party library.
Otherwise you need to write your own COM wrapper to access those details.
See this link for a pure C# sample.
Here an example how to read the properties of a file:
Add Reference to Shell32.dll from the "Windows/System32" folder to
your project
List<string> arrHeaders = new List<string>();
List<Tuple<int, string, string>> attributes = new List<Tuple<int, string, string>>();
Shell32.Shell shell = new Shell32.Shell();
var strFileName = #"C:\Users\Admin\Google Drive\image.jpg";
Shell32.Folder objFolder = shell.NameSpace(System.IO.Path.GetDirectoryName(strFileName));
Shell32.FolderItem folderItem = objFolder.ParseName(System.IO.Path.GetFileName(strFileName));
for (int i = 0; i < short.MaxValue; i++)
{
string header = objFolder.GetDetailsOf(null, i);
if (String.IsNullOrEmpty(header))
break;
arrHeaders.Add(header);
}
// The attributes list below will contain a tuple with attribute index, name and value
// Once you know the index of the attribute you want to get,
// you can get it directly without looping, like this:
var Authors = objFolder.GetDetailsOf(folderItem, 20);
for (int i = 0; i < arrHeaders.Count; i++)
{
var attrName = arrHeaders[i];
var attrValue = objFolder.GetDetailsOf(folderItem, i);
var attrIdx = i;
attributes.Add(new Tuple<int, string, string>(attrIdx, attrName, attrValue));
Debug.WriteLine("{0}\t{1}: {2}", i, attrName, attrValue);
}
Console.ReadLine();
You can enrich this code to create custom classes and then do sorting depending on your needs.
There are many paid versions out there, but there is a free one called WindowsApiCodePack
For example accessing image metadata, I think it supports
ShellObject picture = ShellObject.FromParsingName(file);
var camera = picture.Properties.GetProperty(SystemProperties.System.Photo.CameraModel);
newItem.CameraModel = GetValue(camera, String.Empty, String.Empty);
var company = picture.Properties.GetProperty(SystemProperties.System.Photo.CameraManufacturer);
newItem.CameraMaker = GetValue(company, String.Empty, String.Empty);
I'm trying to do a project for school, including both c# and databases. It basically is an Audio Player that takes the tracks from paths in a SQL Server
database locally.
My question is, since I can't solve my problem myself, how can I play a list of songs?
I am using a WaveOutEvent object called outputDevice and an AudioFileReader.
I tried getting the index of the list and playing it and it "works", or better, the debugging says that the PlaybackState of the outputDevice is 'Playing' but it doesn't actually play the music.
Here's some code:
The working part of it:
if (songsQueue.Count != 0)
{
//where nQueue is the position of the list
DataGridViewRow row = (DataGridViewRow)songsQueue[nQueue];
if (outputDevice == null)
{
outputDevice = new WaveOutEvent();
outputDevice.PlaybackStopped += OnPlaybackStopped;
}
if (audioReader == null)
{
string path = row.Cells[7].Value.ToString();
audioReader = new AudioFileReader(Application.StartupPath + #path);
outputDevice.Init(audioReader);
lblArtist.Text = row.Cells[2].Value.ToString();
lblTrack.Text = row.Cells[3].Value.ToString();
outputDevice.Play();
}
}
The part that is not working:
audioReader.Dispose();
outputDevice.Dispose();
DataGridViewRow row = (DataGridViewRow)songsQueue[nQueue + 1];
string path = row.Cells[7].Value.ToString();
audioReader = new AudioFileReader(Application.StartupPath + #path);
outputDevice = new WaveOutEvent();
outputDevice.Init(audioReader);
lblArtist.Text = row.Cells[2].Value.ToString();
lblTrack.Text = row.Cells[3].Value.ToString();
outputDevice.Play();
I'd expect it to play, since the labels lblArtist and lblTrack change and the outputDevice says that it's playing.
Thank you all for the help in advance! :D
i want to play the video which name is entered in text box. But it does not play the exact video it plays the first video present in folder. any help please..
Code
String vid_name = data.Text;
string complete_name = vid_name.ToLower() + ".mp4";
string root = System.IO.Path.GetDirectoryName("D:/abc");
string[] supportedExtensions = new[] { ".mp4" };
var files = Directory.GetFiles(Path.Combine(root, "Videos"), "*.*").Where(s => supportedExtensions.Contains(Path.GetExtension(s).ToLower()));
List<VideosDetail> videos = new List<VideosDetail>();
VideosDetail id;
foreach (var file in files)
{
id = new VideosDetail()
{
Path = file,
FileName = Path.GetFileName(file),
Extension = Path.GetExtension(file)
};
FileInfo fi = new FileInfo(file);
id.FileName = fi.Name;
id.Size = fi.Length;
videos.Add(id);
if (id.FileName == complete_name)
{
VideoList.ItemsSource = videos; //**Problem comes here
}
else
{
MessageBox.Show("no such video is available. ");
}
}
Since videos is a List, the line
VideoList.ItemsSource = videos;
Points to all the videos in the folder (up to the one that actually matches the filename you entered). Hence, the unwanted result.
You should probably pass the index of the video in your list, something like:
player.Source = videos[x];
Hope this helps!
This code takes photos with name face1.jpg, face2.jpg and so on from picture library and shows them. now the problem is that it works for first 9 pictures then it stops. but it is supposed to go through all the pictures in the gallery
StorageFolder picturesFolder = KnownFolders.PicturesLibrary;
IReadOnlyList<IStorageFile> file = await picturesFolder.GetFilesAsync(CommonFileQuery.OrderByDate);
string fname;
int picSize = 150;
int i = 0;
WriteableBitmap wv = new WriteableBitmap(picSize, picSize);
WriteableBitmap mypic = new WriteableBitmap(picSize, picSize);
if (file.Count > 0)
{
foreach (StorageFile f in file)
{
fname = "face" + i + ".jpg";
if (f.Name == fname)
{
i = i + 1;
ImageProperties properties = await f.Properties.GetImagePropertiesAsync();
WriteableBitmap wb = new WriteableBitmap((int)properties.Width, (int)properties.Height);
wb.SetSource((await f.OpenReadAsync()).AsStream());
reSize(wb, wv);
FilterWriteableBitmap(wv, mypic);
img.Source = mypic;
}
}
}
when I try to take photo directly mean when I write if(f.Name=="face10.jpg") then it works but inside the loop it stops at face9.
Change
int i = 0;
to
int i = 1;
Assuming there are 10 files in that folder the foreach will go through 10 times but the first time it will look for face0.jpg and only ever get to face9.jpg.
I am in the process to making an image gallery where i need to load more than 2 GB images from 1 directory to list view.
when i browse a folder above 200 mb its showing me the error OUT OF MEMORY.
my code is
_filenames = new List<string>();
DirectoryInfo dir = new DirectoryInfo(#root + "gallery");
foreach (FileInfo file in dir.GetFiles())
{
if (file.Name != "desktop.ini")
{
var image = Image.FromFile(file.FullName);
_filenames.Add(file.Name.ToLower());
imageList1.Images.Add(image);
}
else
{
break;
}
}
listView1.View = View.LargeIcon;
imageList1.ImageSize = new Size(75,75);
listView1.LargeImageList = imageList1;
for (int i = 0; i < imageList1.Images.Count; i++)
{
var item = new ListViewItem();
item.ImageIndex = i;
item.Text = _filenames[i];
listView1.Items.Add(item);
}
}
You need to (as a first), perform your image operations before adding them to the list:
Performing other operations, such as setting the ColorDepth or
ImageSize will cause the Handle to be recreated. Therefore, you should
perform these operations before you add images to the ImageList.
from MSDN
Update following clarifications:
In order to create your own file list then (assuming you have the directory name and file names within the directory) you could create a FileInfo[] array as follows:
// Prepare the directory and file names
var directoryName = "C:\\Temp\\MyFolder";
var filenames = new List<string>();
filenames.Add("0001.jpg");
filenames.Add("2345.jpg");
// Construct FileInfo array - using System.IO
var files = new FileInfo[filenames.Count];
for (var i = 0; i < filenames.Count; i++)
{
var fileName = filenames[i];
files[i] = new FileInfo(Path.Combine(directoryName, fileName));
}
There are many ways you could construct the FileInfo[] array (e.g. LINQ for example), but the above should work fine.