mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
bug fixes
This commit is contained in:
@@ -8,12 +8,9 @@ using System.IO;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using System.Diagnostics;
|
||||
using NAudio.CoreAudioApi;
|
||||
using CUEControls;
|
||||
using CUETools.Codecs;
|
||||
using CUETools.Codecs.CoreAudio;
|
||||
using CUETools.DSP.Mixer;
|
||||
using CUETools.DSP.Resampler;
|
||||
using CUETools.Processor;
|
||||
|
||||
namespace CUEPlayer
|
||||
@@ -22,12 +19,10 @@ namespace CUEPlayer
|
||||
{
|
||||
private ShellIconMgr _icon_mgr;
|
||||
private CUEConfig _config;
|
||||
private IWavePlayer _player;
|
||||
DataSet1TableAdapters.PlaylistTableAdapter adapterPlayList = new DataSet1TableAdapters.PlaylistTableAdapter();
|
||||
private DataSet1 dataSet = new DataSet1();
|
||||
private Thread mixThread;
|
||||
private MixingSource _mixer;
|
||||
private SOXResampler _resampler;
|
||||
|
||||
internal Playlist wndPlaylist
|
||||
{
|
||||
@@ -85,236 +80,42 @@ namespace CUEPlayer
|
||||
|
||||
private void frmCUEPlayer_Load(object sender, EventArgs e)
|
||||
{
|
||||
int delay = 100;
|
||||
AudioPCMConfig mixerPCM = AudioPCMConfig.RedBook;
|
||||
if (Properties.Settings.Default.AppSettings == null)
|
||||
{
|
||||
Properties.Settings.Default.AppSettings = new CUEPlayerSettings();
|
||||
Properties.Settings.Default.AppSettings.IcecastServers.Add(new CUETools.Codecs.Icecast.IcecastSettingsData());
|
||||
}
|
||||
|
||||
//System.Data.SqlServerCe.SqlCeDataAdapter ad = new System.Data.SqlServerCe.SqlCeDataAdapter();
|
||||
//ad.SelectCommand = new System.Data.SqlServerCe.SqlCeCommand("SELECT * FROM Playlist WHERE track=1", adapterPlayList.Connection);
|
||||
//ad.Fill(dataSet.Playlist);
|
||||
adapterPlayList.Fill(dataSet.Playlist);
|
||||
|
||||
_mixer = new MixingSource(mixerPCM, delay, 2);
|
||||
_mixer = new MixingSource(new AudioPCMConfig(32, 2, 44100), 100, 2);
|
||||
|
||||
outputA.Init(this);
|
||||
browser.Init(this);
|
||||
playlist.Init(this);
|
||||
deckB.Init(this, null);
|
||||
deckA.Init(this, deckB);
|
||||
Icecast icecast = new Icecast();
|
||||
icecast.Init(this);
|
||||
//LayoutMdi(MdiLayout.TileHorizontal);
|
||||
|
||||
|
||||
browser.Location = new Point(0, 0);
|
||||
browser.Height = ClientRectangle.Height - 5;
|
||||
browser.Height = ClientRectangle.Height - 5 - menuStrip1.Height;
|
||||
playlist.Location = new Point(browser.Location.X + browser.Width, 0);
|
||||
playlist.Height = ClientRectangle.Height - 5;
|
||||
playlist.Height = ClientRectangle.Height - 5 - menuStrip1.Height;
|
||||
deckA.Location = new Point(playlist.Location.X + playlist.Width, 0);
|
||||
deckB.Location = new Point(playlist.Location.X + playlist.Width, deckA.Height);
|
||||
outputA.Location = new Point(deckA.Location.X + deckA.Width, 0);
|
||||
icecast.Location = new Point(deckA.Location.X + deckA.Width, outputA.Height);
|
||||
|
||||
try
|
||||
{
|
||||
_player = new WasapiOut(outputA.Device, NAudio.CoreAudioApi.AudioClientShareMode.Shared, true, delay, new AudioPCMConfig(32, 2, 44100));
|
||||
}
|
||||
catch
|
||||
{
|
||||
_player = null;
|
||||
}
|
||||
if (_player == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_player = new WasapiOut(outputA.Device, NAudio.CoreAudioApi.AudioClientShareMode.Shared, true, delay, new AudioPCMConfig(32, 2, 48000));
|
||||
SOXResamplerConfig cfg;
|
||||
cfg.quality = SOXResamplerQuality.Very;
|
||||
cfg.phase = 50;
|
||||
cfg.allow_aliasing = false;
|
||||
cfg.bandwidth = 0;
|
||||
_resampler = new SOXResampler(mixerPCM, _player.PCM, cfg);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_player = null;
|
||||
Trace.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
if (_player != null)
|
||||
{
|
||||
_player.Play();
|
||||
|
||||
mixThread = new Thread(MixThread);
|
||||
mixThread.Priority = ThreadPriority.AboveNormal;
|
||||
mixThread.IsBackground = true;
|
||||
mixThread.Name = "Mixer";
|
||||
mixThread.Start();
|
||||
}
|
||||
}
|
||||
|
||||
Thread playThread;
|
||||
|
||||
int playingRow;
|
||||
|
||||
private void PlayThread()
|
||||
{
|
||||
AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, 0x2000);
|
||||
IAudioSource playingSource = null;
|
||||
CUESheet playingCue = null;
|
||||
long playingOffs = 0;
|
||||
long playingFin = 0;
|
||||
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
// End of playlist entry or source file
|
||||
if (playingSource != null && (playingOffs == playingFin || playingSource.Remaining == 0))
|
||||
{
|
||||
this.Invoke((MethodInvoker)delegate()
|
||||
{
|
||||
playlist.List.Items[playingRow].BackColor = Color.White;
|
||||
});
|
||||
playingRow++;
|
||||
playingOffs = 0;
|
||||
if (playingRow >= dataSet.Playlist.Rows.Count)
|
||||
break;
|
||||
string path = dataSet.Playlist[playingRow].path;
|
||||
int track = dataSet.Playlist[playingRow].track;
|
||||
|
||||
if (playingCue == null ||
|
||||
playingSource == null ||
|
||||
playingCue.InputPath != path ||
|
||||
playingSource.Position != (long)playingCue.TOC[track].Start * 588)
|
||||
{
|
||||
if (playingSource != null)
|
||||
{
|
||||
playingSource.Close();
|
||||
playingSource = null;
|
||||
}
|
||||
if (playingCue != null)
|
||||
{
|
||||
playingCue.Close();
|
||||
playingCue = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
playingFin = (long)playingCue.TOC[track].Length * 588;
|
||||
this.Invoke((MethodInvoker)delegate()
|
||||
{
|
||||
playlist.List.Items[playingRow].BackColor = Color.AliceBlue;
|
||||
//deckA.UpdateDeck(dataSet, playingRow, playingCue, playingFin);
|
||||
});
|
||||
}
|
||||
}
|
||||
// Open it
|
||||
if (playingSource == null)
|
||||
{
|
||||
string path = dataSet.Playlist[playingRow].path;
|
||||
int track = dataSet.Playlist[playingRow].track;
|
||||
|
||||
try
|
||||
{
|
||||
playingCue = new CUESheet(_config);
|
||||
playingCue.Open(path);
|
||||
playingSource = new CUESheetAudio(playingCue);
|
||||
playingSource.Position = (long)playingCue.TOC[track].Start * 588 + playingOffs;
|
||||
playingSource = new AudioPipe(playingSource, 0x2000);
|
||||
playingFin = (long)playingCue.TOC[track].Length * 588;
|
||||
this.Invoke((MethodInvoker)delegate()
|
||||
{
|
||||
playlist.List.Items[playingRow].BackColor = Color.AliceBlue;
|
||||
//deckA.UpdateDeck(dataSet, playingRow, playingCue, playingFin);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// skip it
|
||||
playingOffs = playingFin = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
playingSource.Read(buff, (int)(playingFin - playingOffs));
|
||||
|
||||
this.Invoke((MethodInvoker)delegate()
|
||||
{
|
||||
deckA.PlayingOffset = (int)playingOffs;
|
||||
});
|
||||
|
||||
_player.Write(buff);
|
||||
playingOffs += buff.Length;
|
||||
} while (_player.PlaybackState != PlaybackState.Stopped);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Can't invoke while joining
|
||||
|
||||
//if (playingRow < dataSet.Playlist.Rows.Count)
|
||||
// this.Invoke((MethodInvoker)delegate()
|
||||
// {
|
||||
// listViewTracks.Items[playingRow].BackColor = Color.White;
|
||||
// });
|
||||
}
|
||||
|
||||
if (playingCue != null)
|
||||
{
|
||||
playingCue.Close();
|
||||
playingCue = null;
|
||||
}
|
||||
if (playingSource != null)
|
||||
{
|
||||
playingSource.Close();
|
||||
playingSource = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal void buttonPlay_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_player.Stop();
|
||||
if (playThread != null)
|
||||
{
|
||||
playThread.Join();
|
||||
playThread = null;
|
||||
}
|
||||
|
||||
if (playlist.List.SelectedIndices.Count < 0)
|
||||
return;
|
||||
|
||||
playingRow = playlist.List.SelectedIndices[0];
|
||||
playlist.List.Items[playingRow].BackColor = Color.AliceBlue;
|
||||
|
||||
_player.Play();
|
||||
|
||||
playThread = new Thread(new ThreadStart(PlayThread));
|
||||
playThread.Priority = ThreadPriority.AboveNormal;
|
||||
playThread.IsBackground = true;
|
||||
playThread.Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
internal void buttonStop_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_player.Stop();
|
||||
if (playThread != null)
|
||||
{
|
||||
playThread.Join();
|
||||
playThread = null;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
internal void buttonPause_Click(object sender, EventArgs e)
|
||||
{
|
||||
_player.Pause();
|
||||
mixThread = new Thread(MixThread);
|
||||
mixThread.Priority = ThreadPriority.AboveNormal;
|
||||
mixThread.IsBackground = true;
|
||||
mixThread.Name = "Mixer";
|
||||
mixThread.Start();
|
||||
}
|
||||
|
||||
private void frmCUEPlayer_FormClosing(object sender, FormClosingEventArgs e)
|
||||
@@ -331,23 +132,55 @@ namespace CUEPlayer
|
||||
|
||||
private void MixThread()
|
||||
{
|
||||
AudioBuffer result = new AudioBuffer(
|
||||
new AudioPCMConfig(_player.PCM.BitsPerSample, _player.PCM.ChannelCount, _mixer.PCM.SampleRate), _mixer.BufferSize);
|
||||
AudioBuffer resampled = _resampler == null ? null : new AudioBuffer(_player.PCM, _mixer.BufferSize * 2 * _mixer.PCM.SampleRate / _player.PCM.SampleRate);
|
||||
AudioBuffer result = new AudioBuffer(_mixer.PCM, _mixer.BufferSize);
|
||||
while (true)
|
||||
{
|
||||
//Trace.WriteLine(string.Format("Read"));
|
||||
_mixer.Read(result, -1);
|
||||
if (_resampler == null)
|
||||
_player.Write(result);
|
||||
else
|
||||
{
|
||||
//Trace.WriteLine(string.Format("Flow: {0}", result.Length));
|
||||
_resampler.Flow(result, resampled);
|
||||
//Trace.WriteLine(string.Format("Play: {0}", resampled.Length));
|
||||
if (resampled.Length != 0)
|
||||
_player.Write(resampled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<UpdateMetadataEvent> updateMetadata;
|
||||
|
||||
public void UpdateMetadata(string artist, string title)
|
||||
{
|
||||
UpdateMetadataEvent e = new UpdateMetadataEvent();
|
||||
e.artist = artist;
|
||||
e.title = title;
|
||||
if (updateMetadata != null)
|
||||
updateMetadata(this, e);
|
||||
}
|
||||
|
||||
private void icecastToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Icecast icecast = new Icecast();
|
||||
icecast.Init(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateMetadataEvent: EventArgs
|
||||
{
|
||||
public string artist;
|
||||
public string title;
|
||||
}
|
||||
|
||||
public class CUEPlayerSettings
|
||||
{
|
||||
private BindingList<CUETools.Codecs.Icecast.IcecastSettingsData> icecastServers;
|
||||
|
||||
public CUEPlayerSettings()
|
||||
{
|
||||
icecastServers = new BindingList<CUETools.Codecs.Icecast.IcecastSettingsData>();
|
||||
}
|
||||
|
||||
public BindingList<CUETools.Codecs.Icecast.IcecastSettingsData> IcecastServers
|
||||
{
|
||||
get
|
||||
{
|
||||
return icecastServers;
|
||||
}
|
||||
set
|
||||
{
|
||||
icecastServers = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user