289 lines
11 KiB
C#
289 lines
11 KiB
C#
using NAudio.Wave;
|
|
using System;
|
|
using System.Windows.Forms;
|
|
using YoutubeExplode;
|
|
using YoutubeExplode.Videos;
|
|
using YoutubeExplode.Videos.Streams;
|
|
|
|
namespace Projector
|
|
{
|
|
public partial class FrmMain : Form
|
|
{
|
|
private Video? _video = null;
|
|
private StreamManifest? _streamManifest = null;
|
|
FourChannelToStereoSampleProvider? mixer = null;
|
|
string musicPath = "C:\\Hymnal\\Music";
|
|
string editsPath = "C:\\Hymnal\\Edits";
|
|
string LyricsPath = "C:\\Hymnal\\Lyrics";
|
|
FrmPreview frmPreview = new FrmPreview();
|
|
|
|
public FrmMain()
|
|
{
|
|
InitializeComponent();
|
|
|
|
DgvHymns.CellContentClick += DgvHymns_CellContentClick;
|
|
}
|
|
|
|
private void FrmMain_Load(object sender, EventArgs e)
|
|
{
|
|
FrmMain_Resize(null, null);
|
|
|
|
if (!System.IO.Directory.Exists(musicPath))
|
|
{
|
|
MessageBox.Show("Hymns directory does not exist: " + musicPath);
|
|
return;
|
|
}
|
|
|
|
var hymns = System.IO.Directory.GetFiles(musicPath, "*.m4a");
|
|
foreach (var hymn in hymns)
|
|
{
|
|
var fileName = System.IO.Path.GetFileNameWithoutExtension(hymn);
|
|
DgvHymns.Rows.Add(fileName, "");
|
|
}
|
|
}
|
|
|
|
private void DgvHymns_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
|
|
{
|
|
if (DgvHymns.Columns[e.ColumnIndex].Name == "CnPlay" && e.RowIndex >= 0)
|
|
{
|
|
e.Paint(e.CellBounds, DataGridViewPaintParts.All);
|
|
var icon = Properties.Resources.Play; // Assuming you have a play icon in resources
|
|
var iconRect = new Rectangle(e.CellBounds.X + 2, e.CellBounds.Y + 2, e.CellBounds.Height - 4, e.CellBounds.Height - 4);
|
|
e.Graphics?.DrawImage(icon, iconRect);
|
|
e.Handled = true; // Prevent default painting
|
|
}
|
|
}
|
|
|
|
// 3. Handle the Play button click:
|
|
private void DgvHymns_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
// Check if PlayButton column and not header row
|
|
if (e.RowIndex >= 0 && DgvHymns.Columns[e.ColumnIndex].Name == "CnPlay")
|
|
{
|
|
var hymnName = DgvHymns.Rows[e.RowIndex].Cells["CnHymn"].Value?.ToString();
|
|
if (!string.IsNullOrEmpty(hymnName))
|
|
{
|
|
PlayHymn(hymnName);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void PlayHymn(string name)
|
|
{
|
|
string audioFilePath = Path.Combine(editsPath, name + ".m4a");
|
|
if (!File.Exists(audioFilePath))
|
|
{
|
|
audioFilePath = Path.Combine(musicPath, name + ".m4a");
|
|
}
|
|
|
|
string number = name.Substring(0, 3).Trim(); // Extract the first 3 characters
|
|
|
|
try
|
|
{
|
|
// Open the audio file
|
|
var reader = new MediaFoundationReader(audioFilePath);
|
|
|
|
// Check for 4 channels
|
|
if (reader.WaveFormat.Channels != 4)
|
|
{
|
|
MessageBox.Show("Audio file does not have 4 channels.");
|
|
reader.Dispose();
|
|
return;
|
|
}
|
|
|
|
// Create a custom sample provider to mix channels 0+2 to left, 1+3 to right
|
|
mixer = new FourChannelToStereoSampleProvider(reader.ToSampleProvider());
|
|
|
|
// Search the folder in LyricsPath that starts with the hymn number
|
|
string lyricsFilePath = Directory.GetDirectories(LyricsPath).ToList().ConvertAll(d => Path.GetFileName(d))
|
|
.FirstOrDefault(dir => dir.StartsWith(number, StringComparison.OrdinalIgnoreCase));
|
|
|
|
// Get all the jpg files in the lyrics folder
|
|
if (lyricsFilePath != null)
|
|
{
|
|
string lyricsFolderPath = Path.Combine(LyricsPath, lyricsFilePath);
|
|
var jpgFiles = Directory.GetFiles(lyricsFolderPath, "*.jpg");
|
|
|
|
// Order the jpg files by name
|
|
Array.Sort(jpgFiles, StringComparer.OrdinalIgnoreCase);
|
|
|
|
// Display the first jpg file in a PictureBox or similar control
|
|
if (jpgFiles.Length > 0)
|
|
{
|
|
// Assuming you have a PictureBox named pictureBoxLyrics
|
|
frmPreview.SetImages(jpgFiles, mixer);
|
|
}
|
|
}
|
|
|
|
var waveOut = new WaveOutEvent();
|
|
waveOut.Init(mixer);
|
|
waveOut.Play();
|
|
frmPreview.ShowDialog(this);
|
|
TbFilter.SelectAll();
|
|
TbFilter.Focus();
|
|
|
|
// Crate a task to handle the transition
|
|
Task.Run(() =>
|
|
{
|
|
mixer.SetOff();
|
|
while (!mixer.IsOff)
|
|
{
|
|
Thread.Sleep(100); // Check every 100ms
|
|
}
|
|
waveOut.Stop();
|
|
});
|
|
|
|
// Optionally, store waveOut and reader as fields to stop/dispose later
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show("Error playing audio: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
private void TbFilter_TextChanged(object sender, EventArgs e)
|
|
{
|
|
// Filter the DataGridView based on the text in the filter TextBox
|
|
string filterText = TbFilter.Text.ToLower();
|
|
foreach (DataGridViewRow row in DgvHymns.Rows)
|
|
{
|
|
if (row.Cells["CnHymn"].Value != null)
|
|
{
|
|
row.Visible = row.Cells["CnHymn"].Value.ToString().ToLower().Contains(filterText);
|
|
}
|
|
}
|
|
|
|
var visibleRows = DgvHymns.Rows
|
|
.Cast<DataGridViewRow>()
|
|
.Where(row => row.Visible)
|
|
.ToList();
|
|
if (visibleRows.Count > 0)
|
|
{
|
|
int firstVisibleRowIndex = visibleRows[0].Index;
|
|
DgvHymns.Rows[firstVisibleRowIndex].Selected = true;
|
|
DgvHymns.FirstDisplayedScrollingRowIndex = firstVisibleRowIndex;
|
|
}
|
|
}
|
|
|
|
private void FrmMain_Resize(object sender, EventArgs e)
|
|
{
|
|
DgvHymns.Columns["CnHymn"].Width = Width - 80;
|
|
}
|
|
|
|
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
|
|
{
|
|
if (keyData == Keys.Down)
|
|
{
|
|
var visibleRows = DgvHymns.Rows
|
|
.Cast<DataGridViewRow>()
|
|
.Where(row => row.Visible)
|
|
.ToList();
|
|
|
|
if (visibleRows.Count > 0)
|
|
{
|
|
int selectedRowIndex = visibleRows.FindIndex(row => row.Selected);
|
|
selectedRowIndex++;
|
|
if (selectedRowIndex < visibleRows.Count)
|
|
{
|
|
visibleRows[selectedRowIndex].Selected = true;
|
|
|
|
int firstDisplayed = DgvHymns.FirstDisplayedScrollingRowIndex;
|
|
int displayedCount = DgvHymns.DisplayedRowCount(false); // false = only fully visible rows
|
|
int lastDisplayed = firstDisplayed + displayedCount - 1;
|
|
if (selectedRowIndex >= lastDisplayed)
|
|
{
|
|
DgvHymns.FirstDisplayedScrollingRowIndex = visibleRows[selectedRowIndex - displayedCount + 1].Index;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else if (keyData == Keys.Up)
|
|
{
|
|
var visibleRows = DgvHymns.Rows
|
|
.Cast<DataGridViewRow>()
|
|
.Where(row => row.Visible)
|
|
.ToList();
|
|
|
|
if (visibleRows.Count > 0)
|
|
{
|
|
int selectedRowIndex = visibleRows.FindIndex(row => row.Selected);
|
|
selectedRowIndex--;
|
|
if (selectedRowIndex >= 0)
|
|
{
|
|
visibleRows[selectedRowIndex].Selected = true;
|
|
|
|
int firstDisplayed = DgvHymns.FirstDisplayedScrollingRowIndex;
|
|
int displayedCount = DgvHymns.DisplayedRowCount(false); // false = only fully visible rows
|
|
|
|
if (selectedRowIndex < firstDisplayed)
|
|
{
|
|
DgvHymns.FirstDisplayedScrollingRowIndex = visibleRows[selectedRowIndex].Index;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else if (keyData == Keys.Enter)
|
|
{
|
|
// Handle Enter key to simulate Play button click
|
|
var selectedRow = DgvHymns.SelectedRows.Cast<DataGridViewRow>().FirstOrDefault();
|
|
if (selectedRow != null && selectedRow.Cells["CnPlay"].Value != null)
|
|
{
|
|
DgvHymns_CellContentClick(sender: null, e: new DataGridViewCellEventArgs(1, selectedRow.Index));
|
|
return true; // Indicate that the key press has been handled
|
|
}
|
|
}
|
|
else if (keyData == Keys.Home)
|
|
{
|
|
var visibleRows = DgvHymns.Rows
|
|
.Cast<DataGridViewRow>()
|
|
.Where(row => row.Visible)
|
|
.ToList();
|
|
|
|
if (visibleRows.Count > 0)
|
|
{
|
|
visibleRows.First().Selected = true;
|
|
int selectedRowIndex = visibleRows.First().Index;
|
|
|
|
int firstDisplayed = DgvHymns.FirstDisplayedScrollingRowIndex;
|
|
int displayedCount = DgvHymns.DisplayedRowCount(false); // false = only fully visible rows
|
|
|
|
if (selectedRowIndex < firstDisplayed)
|
|
{
|
|
DgvHymns.FirstDisplayedScrollingRowIndex = visibleRows[selectedRowIndex].Index;
|
|
}
|
|
}
|
|
return true; // Indicate that the key press has been handled
|
|
}
|
|
else if (keyData == Keys.End)
|
|
{
|
|
var visibleRows = DgvHymns.Rows
|
|
.Cast<DataGridViewRow>()
|
|
.Where(row => row.Visible)
|
|
.ToList();
|
|
|
|
if (visibleRows.Count > 0)
|
|
{
|
|
visibleRows.Last().Selected = true;
|
|
int selectedRowIndex = visibleRows.Last().Index;
|
|
|
|
int firstDisplayed = DgvHymns.FirstDisplayedScrollingRowIndex;
|
|
int displayedCount = DgvHymns.DisplayedRowCount(false); // false = only fully visible rows
|
|
int lastDisplayed = firstDisplayed + displayedCount - 1;
|
|
if (selectedRowIndex >= lastDisplayed)
|
|
{
|
|
DgvHymns.FirstDisplayedScrollingRowIndex = visibleRows[selectedRowIndex - displayedCount + 1].Index;
|
|
}
|
|
}
|
|
|
|
return true; // Indicate that the key press has been handled
|
|
}
|
|
|
|
return base.ProcessCmdKey(ref msg, keyData); // Allow default processing if not an arrow key
|
|
}
|
|
}
|
|
}
|