using Microsoft.VisualBasic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.DirectoryServices.ActiveDirectory;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
namespace PlaylistManager
{
public partial class frmMain : Form
{
private DataTable dtReplacePaths = null!;
private DataTable dtPLPaths = null!;
private DataView dvPLPaths = null!;
private System.Text.Encoding Enc = System.Text.Encoding.UTF8;
private string settingsfile = Application.StartupPath + @"\settings.json";
private Settings settings = null!;
public enum SortType
{
[Description("Titel")]
Title,
[Description("Titelnr.")]
TitleNo,
[Description("Dateiname")]
Filename,
[Description("Künstler")]
Artist
}
public frmMain()
{
InitializeComponent();
}
private void frmMain_Load(object sender, EventArgs e)
{
Text += " v." + Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "";
prepareReplacePath();
settings = Settings.Load(settingsfile);
/* TODO ERROR: Skipped IfDirectiveTrivia
#If DEBUG Then
*/
txtList.Text = @"D:\Privat\Mixed";
SFD.FileName = "test.xls";
/* TODO ERROR: Skipped EndIfDirectiveTrivia
#End If
*/
}
private void btnPlaylist_Click(object sender, EventArgs e)
{
if (OFD.ShowDialog() == DialogResult.OK)
{
string prevPlaylistFolder = GetPlaylistFolderName(txtExtractPlaylist.Text);
txtExtractPlaylist.Text = OFD.FileName;
if (txtExtractTargetfolder.Text == "" || txtExtractTargetfolder.Text == prevPlaylistFolder) txtExtractTargetfolder.Text = GetPlaylistFolderName(OFD.FileName);
}
}
///
/// Generiert einen Ordnernamen der dem Namen der Playlist entspricht, als Zielordner-Vorschlag
///
///
///
private string GetPlaylistFolderName(string playlistfile)
{
return Path.Combine(Path.GetDirectoryName(playlistfile) ?? "", Path.GetFileNameWithoutExtension(playlistfile));
}
private void lblPlaylistOpen_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
OpenFile(txtExtractPlaylist.Text);
}
private void OpenFile(string datei)
{
if (File.Exists(datei))
{
Process.Start("notepad.exe", datei);
}
}
private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
settings.Save(settingsfile);
}
private void frmMain_DragEnter(object sender, DragEventArgs e)
{
if (e.Data == null) return;
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
switch (tcMain.SelectedTab?.Name ?? "")
{
case var @case when @case == (tpExtract.Name ?? ""):
{
e.Effect = DragDropEffects.Copy;
break;
}
case var case1 when case1 == (tpChangepath.Name ?? ""):
{
e.Effect = DragDropEffects.Copy;
break;
}
default:
{
e.Effect = DragDropEffects.None;
break;
}
}
}
}
private void frmMain_DragDrop(object sender, DragEventArgs e)
{
if (e.Data == null) return;
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[]? files = (string[]?)e.Data.GetData(DataFormats.FileDrop);
if (files == null) return;
switch (tcMain.SelectedTab?.Name ?? "")
{
case var @case when @case == (tpExtract.Name ?? ""):
{
foreach (string datei in files)
{
if (datei.EndsWith(".m3u8") | datei.EndsWith(".m3u") | datei.EndsWith("bak")) // beim letzten kein Punkt is absicht, da die backupdateien mit .m3ubak und .m3u8bak enden!
{
txtExtractPlaylist.Text = datei;
break;
}
}
break;
}
case var case1 when case1 == (tpChangepath.Name ?? ""):
{
foreach (string datei in files)
{
if (datei.EndsWith(".m3u8") | datei.EndsWith(".m3u") | datei.EndsWith("bak")) // beim letzten kein Punkt is absicht, da die backupdateien mit .m3ubak und .m3u8bak enden!
{
lstCPPlaylists.Items.Add(datei);
}
}
readPlaylistpaths();
break;
}
}
}
}
private void btnOK_Click(object sender, EventArgs e)
{
switch (tcMain.SelectedTab?.Name ?? "")
{
case var @case when @case == (tpExtract.Name ?? ""):
{
ExtractPlaylist(txtExtractPlaylist.Text, txtExtractTargetfolder.Text);
break;
}
case var case1 when case1 == (tpChangepath.Name ?? ""):
{
ChangePaths();
break;
}
case var case2 when case2 == (tpList.Name ?? ""):
{
CreateTracklist();
break;
}
}
}
#region Playlist extrahieren
private void btnMP3_Click(object sender, EventArgs e)
{
if (FBD.ShowDialog() == DialogResult.OK)
{
txtExtractTargetfolder.Text = FBD.SelectedPath;
}
}
private void ExtractPlaylist(string PlaylistFile, string TargetFolder)
{
if (!TargetFolder.EndsWith("\\")) TargetFolder += "\\";
try
{
if (!Directory.Exists(TargetFolder)) Directory.CreateDirectory(TargetFolder);
}
catch (Exception ex)
{
MessageBox.Show($"Unable to create folder '{TargetFolder}':\r\n{ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var sr = new StreamReader(PlaylistFile, Enc);
string? line;
string alternativePath;
var frm = new frmList();
while (sr.EndOfStream == false)
{
line = sr.ReadLine();
if (line is not null & line.Substring(0, 1) != "#")
{
alternativePath = Path.GetDirectoryName(PlaylistFile) ?? "";
if (alternativePath.LastIndexOf(@"\") < alternativePath.Length - 1)
alternativePath += @"\";
alternativePath += line;
if (File.Exists(line))
{
frm.lstGefunden.Items.Add(line);
}
else if (File.Exists(alternativePath))
{
frm.lstGefunden.Items.Add(alternativePath);
}
else
{
frm.lstNichtGefunden.Items.Add(line);
}
}
}
sr.Close();
sr = null;
int i = 1;
if (frm.ShowDialog() == DialogResult.OK)
{
var frm2 = new frmProgress();
string datei;
frm2.prgStatus.Maximum = frm.lstGefunden.Items.Count;
frm2.prgStatus.Value = 0;
frm2.Show();
Application.DoEvents();
foreach (string itm in frm.lstGefunden.Items)
{
if (frm2.cancelled == false)
{
datei = Path.GetFileName(itm);
frm2.lblFile.Text = datei;
if (chkExtractSortFiles.Checked)
{
File.Copy(itm, TargetFolder + Strings.Format(i, "000") + "." + datei, true);
i += 1;
}
else
{
File.Copy(itm, TargetFolder + datei, true);
}
frm2.prgStatus.PerformStep();
Application.DoEvents();
}
else
{
Application.DoEvents();
break;
}
}
frm2.Close();
}
}
#endregion
#region Pfad ändern
private void prepareReplacePath()
{
dtReplacePaths = new DataTable();
{
var withBlock = dtReplacePaths.Columns;
withBlock.Add("originalpath", typeof(string));
withBlock.Add("replacepath", typeof(string));
}
dgvRep.DataSource = dtReplacePaths;
dtPLPaths = new DataTable();
{
var withBlock1 = dtPLPaths.Columns;
withBlock1.Add("Path", typeof(string));
withBlock1.Add("Length", typeof(int));
withBlock1.Add("Matchcount", typeof(int));
withBlock1.Add("Matchresult", typeof(bool));
}
dvPLPaths = new DataView(dtPLPaths);
dvPLPaths.Sort = "Matchresult, Matchcount, Length, Path";
dgvFoundPaths.DataSource = dvPLPaths;
}
private void readPlaylistpaths()
{
dtPLPaths.Rows.Clear();
DataRow dr;
foreach (string datei in lstCPPlaylists.Items)
{
if (File.Exists(datei))
{
var sr = new StreamReader(datei, Enc);
string? line;
bool lineexists;
while (!sr.EndOfStream)
{
line = sr.ReadLine();
if (line == null) break;
if (line.StartsWith("#") == false & line.Trim().Length > 0)
{
line = Path.GetDirectoryName(line);
lineexists = false;
foreach (DataRow row in dtPLPaths.Rows)
{
if ((string)row["Path"] == line)
{
lineexists = true;
break;
}
}
if (lineexists == false)
{
dr = dtPLPaths.NewRow();
dr["Path"] = line;
dr["Length"] = line.Length;
dr["Matchcount"] = 0;
dr["Matchresult"] = false;
dtPLPaths.Rows.Add(dr);
}
}
}
sr.Close();
}
}
checkMatches();
}
private void checkMatches()
{
if (dgvFoundPaths.DataSource is DataView)
{
dgvFoundPaths.EndEdit();
DataView dv;
dv = (DataView)dgvFoundPaths.DataSource;
// Matchcount clearen
foreach (DataRowView pathrow in dv)
{
pathrow["Matchcount"] = 0;
pathrow["Matchresult"] = false;
}
foreach (DataRowView pathrow in dv)
{
foreach (DataRow replrow in dtReplacePaths.Rows)
{
if (replrow["originalpath"] == DBNull.Value) continue;
string origpath = (string)replrow["originalpath"];
string path = (string)pathrow["path"];
if (path.ToLower().StartsWith(origpath.ToLower()))
{
pathrow["Matchcount"] = (int)pathrow["Matchcount"] + 1;
}
}
}
// Matchresult überprüfen
// 0 = Keinen Ersetzungspfad gefunden, evtl ist er ja schon korrekt (einer der neuen Pfade?)
// 1 = Genau ein Ergebnis gefunden, passt - wird so ersetzt
// >1 =Mehr als ein Ersetzergebnis - Ersetzliste kontrollieren
foreach (DataRowView row in dv)
{
switch ((int)row["Matchcount"])
{
case 0:
{
// Neue Pfade überprüfen. Evtl müssen die Pfade ja nicht ersetzt werden, weil es schon Replace-Pfade sind.
foreach (DataRow replrow in dtReplacePaths.Rows)
{
if (replrow["replacepath"] == DBNull.Value) continue;
string replpath = (string)replrow["replacepath"];
string path = (string)row["Path"];
if (replpath.Trim().Length > 0)
{
if (path.ToLower().StartsWith(replpath.ToLower()))
{
row["Matchresult"] = true;
break;
}
}
}
break;
}
// Matchresult wurde oben schon auf false gesetzt, deshalb hier nicht mehr nötig
case 1:
{
row["Matchresult"] = true;
break;
}
default:
{
row["Matchresult"] = false;
break;
}
}
}
}
}
private void dgvRep_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
DataGridView grd = (DataGridView)sender;
if (grd.Columns[e.ColumnIndex] is DataGridViewButtonColumn & e.RowIndex >= 0)
{
if (FBD.ShowDialog() == DialogResult.OK)
{
string path = FBD.SelectedPath;
if (!path.EndsWith("\\")) path += "\\";
switch (grd.Columns[e.ColumnIndex].Name ?? "")
{
case var @case when @case == colOriginalPathBrowse.Name:
{
grd.Rows[e.RowIndex].Cells[colOriginalPath.Name].Value = path;
break;
}
case var case1 when case1 == colReplaceToBrowse.Name:
{
grd.Rows[e.RowIndex].Cells[colReplaceTo.Name].Value = path;
break;
}
}
}
}
dtReplacePaths.AcceptChanges();
}
private void dgvRep_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
checkMatches();
}
private void ChangePaths()
{
dtReplacePaths.AcceptChanges();
var notfoundplaylists = new List();
foreach (string playlistfile in lstCPPlaylists.Items)
{
if (File.Exists(playlistfile))
{
// Backup anlegen
string backupfile = Path.GetDirectoryName(playlistfile) + @"\" + Path.GetFileNameWithoutExtension(playlistfile) + "_" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + Path.GetExtension(playlistfile) + "bak";
File.Copy(playlistfile, backupfile, true);
// Erst alle Einträge einlesen
string? line;
var lines = new List();
var reader = new StreamReader(playlistfile, Enc);
while (reader.EndOfStream == false)
{
line = reader.ReadLine();
if (line == null) break;
char CommentChar = Convert.ToChar("#");
if (line[0] != CommentChar)
{
// Jeden Replace-Eintrag durchgehen bis der erste passende gefunden wurde
foreach (DataRow row in dtReplacePaths.Rows)
{
if (row["originalpath"] == DBNull.Value) continue;
string origpath = (string)row["originalpath"];
string replpath = row["replacepath"] == DBNull.Value ? "" : (string)row["replacepath"];
if (line.ToLower().StartsWith(origpath.ToLower()))
{
line = line.Replace(origpath, replpath);
break;
}
}
}
lines.Add(line);
}
reader.Close();
// Dann alle Einträge reinschreiben
var writer = new StreamWriter(playlistfile, false, Enc);
foreach (string readline in lines)
writer.WriteLine(readline);
writer.Close();
}
else
{
notfoundplaylists.Add(playlistfile);
}
}
if (notfoundplaylists.Count > 0)
{
MessageBox.Show($"Eine oder mehrere Playlistdateien wurden nicht gefunden: {Constants.vbCrLf} {string.Join(Constants.vbCrLf, notfoundplaylists.ToArray())}");
}
else
{
MessageBox.Show("Vorgang erfolgreich abgeschlossen");
}
}
private void dgvFoundPaths_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
dtReplacePaths.AcceptChanges();
string pathToAdd = (string)dgvFoundPaths.SelectedCells[0].Value;
foreach (DataRow row in dtReplacePaths.Rows)
{
if (row["originalpath"] == DBNull.Value) continue;
string origpath = (string)row["originalpath"];
if (pathToAdd.ToLower().StartsWith(origpath.ToLower()))
{
// Der Pfad, der durch doppelklick hinuzgefügt werden soll, existiert bereits in einer Form in ReplacePaths
return;
}
}
var dr = dtReplacePaths.NewRow();
dr["originalpath"] = pathToAdd.Trim();
dtReplacePaths.Rows.Add(dr);
}
#endregion
#region Tracklist erzeugen
private void btnList_Click(object sender, EventArgs e)
{
if (FBD.ShowDialog() == DialogResult.OK)
{
txtList.Text = FBD.SelectedPath;
}
}
private void CreateTracklist()
{
SFD.Title = "Neue Tracklist speichern";
SFD.Filter = "Excel-Dateien (*.xls, *.xlsx)|*.xlsx;*.xls|Alle Dateien (*.*)|*.*";
SFD.InitialDirectory = txtList.Text;
if (SFD.ShowDialog() == DialogResult.OK)
{
// Dateien auslesen
var mp3list = new List();
foreach (string datei in Directory.GetFiles(txtList.Text, "*.mp3", SearchOption.TopDirectoryOnly))
mp3list.Add(Mp3File.FromFile(datei));
DataTable dtTracklist = new DataTable();
dtTracklist.Columns.Add("Title");
dtTracklist.Columns.Add("TitleNo");
dtTracklist.Columns.Add("Interpret");
dtTracklist.Columns.Add("Filename");
DataRow dr;
foreach (Mp3File mp3 in mp3list)
{
dr = dtTracklist.NewRow();
dr["TitleNo"] = mp3.Track;
dr["Title"] = mp3.Title;
dr["Interpret"] = mp3.Artist;
dr["Filename"] = mp3.Filename;
dtTracklist.Rows.Add(dr);
}
XLSX.Serialize(SFD.FileName, dtTracklist);
MessageBox.Show("Vorgang abgeschlossen");
}
}
private void lstCPPlaylists_DoubleClick(object sender, EventArgs e)
{
if (lstCPPlaylists.SelectedItem is not null)
{
OpenFile((string)lstCPPlaylists.SelectedItem);
}
}
private void DateiHinzufügenToolStripMenuItem_Click(object sender, EventArgs e)
{
if (OFD.ShowDialog() == DialogResult.OK)
{
lstCPPlaylists.Items.Add(OFD.FileName);
readPlaylistpaths();
}
}
private void AusListeEntfernenToolStripMenuItem_Click(object sender, EventArgs e)
{
if (lstCPPlaylists.SelectedItems.Count > 0)
{
foreach (string itm in lstCPPlaylists.SelectedItems)
lstCPPlaylists.Items.Remove(itm);
readPlaylistpaths();
}
}
private void DateiÖffnenToolStripMenuItem_Click(object sender, EventArgs e)
{
if (lstCPPlaylists.SelectedItem is not null)
{
OpenFile((string)lstCPPlaylists.SelectedItem);
}
}
#endregion
}
}