Jelajahi Sumber

fix ASIO broken by MainForm Disable

Coder 8 bulan lalu
induk
melakukan
b35105f908

+ 13 - 16
Bmp.Core/Playback/Inputs/DffSourceStream.cs

@@ -22,7 +22,6 @@ public class DffSourceStream : DsdAbstractSourceStream
     private const string ID_DIIN = "DIIN";
     private const string ID_MARK = "MARK";
 
-
     private const int FILE_VERSION = 0x01050000;
 
     public static bool IsDffFile(Stream stream)
@@ -48,6 +47,7 @@ public class DffSourceStream : DsdAbstractSourceStream
     {
         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
         public string Id;
+
         private long chunkDataSize;
         public long DataSize => chunkDataSize.NetworkOrderToHostOrder();
     }
@@ -111,9 +111,11 @@ public class DffSourceStream : DsdAbstractSourceStream
                                     case (ID_FS, 4):
                                         _sampleRate = _underlyingStream.ReadStruct<int>().NetworkOrderToHostOrder();
                                         break;
+
                                     case (ID_LSCO, 2):
                                         _loudspeakerConfig = _underlyingStream.ReadStruct<short>().NetworkOrderToHostOrder();
                                         break;
+
                                     default:
 
                                         switch (ck.Id)
@@ -122,24 +124,24 @@ public class DffSourceStream : DsdAbstractSourceStream
                                                 _channelCount = _underlyingStream.ReadStruct<short>().NetworkOrderToHostOrder();
                                                 _channelIds = Enumerable.Range(0, _channelCount).Select(_ => _underlyingStream.ReadStruct<ID>().Value).ToArray();
                                                 break;
+
                                             case ID_CMPR:
                                                 var compressionId = _underlyingStream.ReadStruct<ID>().Value;
                                                 _isDstEncoded = compressionId == ID_DST;
                                                 var len = _underlyingStream.ReadStruct<byte>();
                                                 var text = Encoding.UTF8.GetString(_underlyingStream.ReadBytes(len));
                                                 break;
+
                                             default:
                                                 //skip unknown chunk
                                                 _underlyingStream.Seek(ck.DataSize, SeekOrigin.Current);
                                                 break;
                                         }
                                         break;
-
                                 }
 
-                                //align: pad byte char with value 0, used for making chunks an even length. 
+                                //align: pad byte char with value 0, used for making chunks an even length.
                                 _underlyingStream.Seek(_underlyingStream.Position % 2, SeekOrigin.Current);
-
                             }
                             break; //case ID_PROP:
 
@@ -157,9 +159,9 @@ public class DffSourceStream : DsdAbstractSourceStream
                                         var samples = _underlyingStream.ReadStruct<uint>().NetworkOrderToHostOrder();
                                         var offset = _underlyingStream.ReadStruct<int>().NetworkOrderToHostOrder();
 
-                                        // 0 TrackStart 
-                                        // 1 TrackStop 
-                                        // 2 ProgramStart 
+                                        // 0 TrackStart
+                                        // 1 TrackStop
+                                        // 2 ProgramStart
                                         // 4 Index  Entry point of an Index
                                         var type = _underlyingStream.ReadStruct<short>().NetworkOrderToHostOrder();
 
@@ -179,7 +181,6 @@ public class DffSourceStream : DsdAbstractSourceStream
                                 }
 
                                 _underlyingStream.Seek(_underlyingStream.Position % 2, SeekOrigin.Current);
-
                             }
 
                             break; // case ID_DIIN:
@@ -199,13 +200,12 @@ public class DffSourceStream : DsdAbstractSourceStream
                     break;
             }
 
-            //align: pad byte char with value 0, used for making chunks an even length. 
+            //align: pad byte char with value 0, used for making chunks an even length.
             _underlyingStream.Seek(_underlyingStream.Position % 2, SeekOrigin.Current);
 
             if (_isDstEncoded) throw new NotSupportedException("DST is not support");
 
             WaveFormat = WaveFormat.CreateCustomFormat(WaveFormatEncoding.Unknown, _sampleRate, _channelCount, _sampleRate / 8 * _channelCount, _channelCount, 1);
-
         }
 
         _underlyingStream.Position = _dataOffset;
@@ -224,20 +224,18 @@ public class DffSourceStream : DsdAbstractSourceStream
         if (mod != 0) count -= mod;
 
         var read = _underlyingStream.Read(buffer, offset, count);
-        
+
         // MSB / LSB Convert?
         for (var i = 0; i < read; i++) buffer[i] = BitReverseTable[buffer[i]];
 
         return read;
     }
 
-
-
     public override WaveFormat WaveFormat { get; }
     public override long Length => _dataSize;
     public override long Position { get => _underlyingStream.Position - _dataOffset; set => _underlyingStream.Position = _dataOffset + value - value % _channelCount; }
 
-    public static byte[] BitReverseTable =
+    private static readonly byte[] BitReverseTable =
     {
         0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
         0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
@@ -272,5 +270,4 @@ public class DffSourceStream : DsdAbstractSourceStream
         0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
         0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
     };
-
-}
+}

+ 44 - 29
Bmp.WinForms/MainForm.Designer.cs

@@ -29,10 +29,10 @@
         private void InitializeComponent()
         {
             components = new System.ComponentModel.Container();
-            ListViewItem listViewItem1 = new ListViewItem(new string[] { "1", "12:34:56" }, -1);
-            ListViewItem listViewItem2 = new ListViewItem(new string[] { "2", "", "▶" }, -1);
-            ListViewItem listViewItem3 = new ListViewItem("3");
-            ListViewItem listViewItem4 = new ListViewItem("4");
+            ListViewItem listViewItem5 = new ListViewItem(new string[] { "1", "12:34:56" }, -1);
+            ListViewItem listViewItem6 = new ListViewItem(new string[] { "2", "", "▶" }, -1);
+            ListViewItem listViewItem7 = new ListViewItem("3");
+            ListViewItem listViewItem8 = new ListViewItem("4");
             SeekTrackBar = new TrackBar();
             StopButton = new Button();
             PlayButton = new Button();
@@ -50,19 +50,21 @@
             MainStatusBar = new StatusStrip();
             StatusBarLabel = new ToolStripStatusLabel();
             SettingButtonToolTip = new ToolTip(components);
+            MainPanel = new Panel();
             ((System.ComponentModel.ISupportInitialize)SeekTrackBar).BeginInit();
             MainStatusBar.SuspendLayout();
+            MainPanel.SuspendLayout();
             SuspendLayout();
             // 
             // SeekTrackBar
             // 
             SeekTrackBar.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
-            SeekTrackBar.LargeChange = 200;
+            SeekTrackBar.LargeChange = 1;
             SeekTrackBar.Location = new Point(407, 12);
             SeekTrackBar.Name = "SeekTrackBar";
-            SeekTrackBar.Size = new Size(400, 69);
-            SeekTrackBar.SmallChange = 200;
-            SeekTrackBar.TabIndex = 0;
+            SeekTrackBar.Size = new Size(513, 69);
+            SeekTrackBar.SmallChange = 1;
+            SeekTrackBar.TabIndex = 5;
             SeekTrackBar.TickFrequency = 0;
             SeekTrackBar.TickStyle = TickStyle.Both;
             SeekTrackBar.MouseDown += SeekTrackBar_MouseDown;
@@ -74,7 +76,7 @@
             StopButton.Location = new Point(12, 12);
             StopButton.Name = "StopButton";
             StopButton.Size = new Size(73, 69);
-            StopButton.TabIndex = 1;
+            StopButton.TabIndex = 0;
             StopButton.Text = "⏹️";
             StopButton.UseVisualStyleBackColor = true;
             StopButton.Click += StopButton_Click;
@@ -85,7 +87,7 @@
             PlayButton.Location = new Point(91, 12);
             PlayButton.Name = "PlayButton";
             PlayButton.Size = new Size(73, 69);
-            PlayButton.TabIndex = 2;
+            PlayButton.TabIndex = 1;
             PlayButton.Text = "▶️";
             PlayButton.UseVisualStyleBackColor = true;
             PlayButton.Click += PlayButton_Click;
@@ -96,7 +98,7 @@
             PauseButton.Location = new Point(170, 12);
             PauseButton.Name = "PauseButton";
             PauseButton.Size = new Size(73, 69);
-            PauseButton.TabIndex = 3;
+            PauseButton.TabIndex = 2;
             PauseButton.Text = "⏸";
             PauseButton.UseVisualStyleBackColor = true;
             PauseButton.Click += PauseButton_Click;
@@ -107,7 +109,7 @@
             PrevButton.Location = new Point(249, 12);
             PrevButton.Name = "PrevButton";
             PrevButton.Size = new Size(73, 69);
-            PrevButton.TabIndex = 4;
+            PrevButton.TabIndex = 3;
             PrevButton.Text = "⏮";
             PrevButton.UseVisualStyleBackColor = true;
             PrevButton.Click += PrevButton_Click;
@@ -118,7 +120,7 @@
             NextButton.Location = new Point(328, 12);
             NextButton.Name = "NextButton";
             NextButton.Size = new Size(73, 69);
-            NextButton.TabIndex = 5;
+            NextButton.TabIndex = 4;
             NextButton.Text = "⏭";
             NextButton.UseVisualStyleBackColor = true;
             NextButton.Click += NextButton_Click;
@@ -131,12 +133,12 @@
             MainListView.ContextMenuStrip = MainContextMenu;
             MainListView.FullRowSelect = true;
             MainListView.GroupImageList = AlbumImageList;
-            MainListView.Items.AddRange(new ListViewItem[] { listViewItem1, listViewItem2, listViewItem3, listViewItem4 });
+            MainListView.Items.AddRange(new ListViewItem[] { listViewItem5, listViewItem6, listViewItem7, listViewItem8 });
             MainListView.Location = new Point(12, 87);
             MainListView.Name = "MainListView";
             MainListView.ShowItemToolTips = true;
-            MainListView.Size = new Size(874, 523);
-            MainListView.TabIndex = 6;
+            MainListView.Size = new Size(982, 428);
+            MainListView.TabIndex = 7;
             MainListView.UseCompatibleStateImageBehavior = false;
             MainListView.View = View.Details;
             MainListView.ColumnWidthChanging += MainListView_ColumnWidthChanging;
@@ -185,10 +187,10 @@
             // 
             SettingButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
             SettingButton.Font = new Font("Microsoft YaHei UI", 19F);
-            SettingButton.Location = new Point(813, 12);
+            SettingButton.Location = new Point(921, 12);
             SettingButton.Name = "SettingButton";
             SettingButton.Size = new Size(73, 69);
-            SettingButton.TabIndex = 5;
+            SettingButton.TabIndex = 6;
             SettingButton.Text = "🛠️";
             SettingButton.UseVisualStyleBackColor = true;
             SettingButton.Click += SettingButton_Click;
@@ -203,9 +205,9 @@
             // 
             MainStatusBar.ImageScalingSize = new Size(24, 24);
             MainStatusBar.Items.AddRange(new ToolStripItem[] { StatusBarLabel });
-            MainStatusBar.Location = new Point(0, 613);
+            MainStatusBar.Location = new Point(0, 518);
             MainStatusBar.Name = "MainStatusBar";
-            MainStatusBar.Size = new Size(898, 22);
+            MainStatusBar.Size = new Size(1006, 22);
             MainStatusBar.TabIndex = 7;
             MainStatusBar.Text = "statusStrip1";
             // 
@@ -219,26 +221,37 @@
             SettingButtonToolTip.IsBalloon = true;
             SettingButtonToolTip.ShowAlways = true;
             // 
+            // MainPanel
+            // 
+            MainPanel.Controls.Add(StopButton);
+            MainPanel.Controls.Add(SeekTrackBar);
+            MainPanel.Controls.Add(MainListView);
+            MainPanel.Controls.Add(PlayButton);
+            MainPanel.Controls.Add(SettingButton);
+            MainPanel.Controls.Add(PauseButton);
+            MainPanel.Controls.Add(NextButton);
+            MainPanel.Controls.Add(PrevButton);
+            MainPanel.Dock = DockStyle.Fill;
+            MainPanel.Location = new Point(0, 0);
+            MainPanel.Name = "MainPanel";
+            MainPanel.Size = new Size(1006, 518);
+            MainPanel.TabIndex = 8;
+            // 
             // MainForm
             // 
             AutoScaleDimensions = new SizeF(11F, 24F);
             AutoScaleMode = AutoScaleMode.Font;
-            ClientSize = new Size(898, 635);
+            ClientSize = new Size(1006, 540);
+            Controls.Add(MainPanel);
             Controls.Add(MainStatusBar);
-            Controls.Add(MainListView);
-            Controls.Add(SettingButton);
-            Controls.Add(NextButton);
-            Controls.Add(PrevButton);
-            Controls.Add(PauseButton);
-            Controls.Add(PlayButton);
-            Controls.Add(StopButton);
-            Controls.Add(SeekTrackBar);
             Name = "MainForm";
             FormClosed += MainForm_FormClosed;
             Shown += MainForm_Shown;
             ((System.ComponentModel.ISupportInitialize)SeekTrackBar).EndInit();
             MainStatusBar.ResumeLayout(false);
             MainStatusBar.PerformLayout();
+            MainPanel.ResumeLayout(false);
+            MainPanel.PerformLayout();
             ResumeLayout(false);
             PerformLayout();
         }
@@ -262,5 +275,7 @@
         private ToolStripStatusLabel StatusBarLabel;
         private ContextMenuStrip MainContextMenu;
         private ToolTip SettingButtonToolTip;
+        private Panel panel1;
+        private Panel MainPanel;
     }
 }

+ 44 - 23
Bmp.WinForms/MainForm.cs

@@ -60,6 +60,7 @@ namespace Bmp.WinForms
 
         private async Task LoadItemAsync(ListViewItem item)
         {
+            MainPanel.Enabled = false;
             await StopAsync();
 
             _playbackState = UIPlaybackState.Loading;
@@ -132,8 +133,16 @@ namespace Bmp.WinForms
 
                 await PlayAsync();
             }
+            catch (Exception ex)
+            {
+                finalState = EMOJI_X;
+                _playbackState = UIPlaybackState.Error;
+                Console.WriteLine(ex);
+            }
             finally
             {
+                MainPanel.Enabled = true;
+
                 item.SubItems[StateColumnHeader.Index].Text = finalState;
                 if (balloonShow)
                 {
@@ -159,7 +168,7 @@ namespace Bmp.WinForms
             if (local != null)
             {
                 local.PlaybackStopped -= _outputDevice_PlaybackStopped;
-                local.Stop();
+                Invoke(() => local.Stop());
                 local.Dispose();
             }
         }
@@ -252,7 +261,7 @@ namespace Bmp.WinForms
 
                 try
                 {
-                    _outputDevice = OutputDeviceProvider.CreateWavePlayer(_selectedOutputDevice, _nativeDsd);
+                    Invoke(() => _outputDevice = OutputDeviceProvider.CreateWavePlayer(_selectedOutputDevice, _nativeDsd));
                 }
                 catch (Exception e)
                 {
@@ -331,11 +340,12 @@ namespace Bmp.WinForms
             {
                 try
                 {
-                    _outputDevice?.Play();
+                    Invoke(() => _outputDevice?.Play());
                 }
                 catch (Exception e)
                 {
                     //TODO: 异常处理
+                    Console.WriteLine(e);
                     _playbackState = UIPlaybackState.Error;
                 }
             }
@@ -537,7 +547,7 @@ namespace Bmp.WinForms
                     if (_playbackState == UIPlaybackState.Playing)
                     {
                         toolStripItem.Enabled = false;
-                        toolStripItem.Text += "(需要暂停播放)";
+                        toolStripItem.Text += "(播放时不可用)";
                     }
                     toolStripItem.Click += delegate
                     {
@@ -563,7 +573,7 @@ namespace Bmp.WinForms
                     if (_playbackState == UIPlaybackState.Playing)
                     {
                         toolStripItem.Enabled = false;
-                        toolStripItem.Text += "(需要暂停播放)";
+                        toolStripItem.Text += "(播放时不可用)";
                     }
                     toolStripItem.Click += delegate
                     {
@@ -984,8 +994,8 @@ namespace Bmp.WinForms
                 {
                     try
                     {
-                        var type = asioOut.Driver.Capabilities.OutputChannelInfos.First().type;
-                        sb.Append($"{type} ");
+                        var type = asioOut.Driver.Capabilities.OutputChannelInfos.Select(p => (object)p.type).FirstOrDefault();
+                        if (type != null) sb.Append($"{type} ");
                     }
                     catch (Exception exception)
                     {
@@ -1008,30 +1018,41 @@ namespace Bmp.WinForms
         {
             if (_inputSource != null)
             {
-                await PauseAsync();
+                try
+                {
+                    await PauseAsync();
 
-                _playbackState = UIPlaybackState.Seeking;
+                    _playbackState = UIPlaybackState.Seeking;
 
-                var ms = SeekTrackBar.Value;
-                var seekTo = TimeSpan.FromMilliseconds(ms);
+                    var ms = SeekTrackBar.Value;
+                    var seekTo = TimeSpan.FromMilliseconds(ms);
 
-                await Task.Run(() => _inputSource.CurrentTime = seekTo);
+                    MainPanel.Enabled = false;
+                    await Task.Run(() => _inputSource.CurrentTime = seekTo);
+                    MainPanel.Enabled = true;
 
-                var bytesOf50Ms = (int)((double)_inputSource.WaveFormat.BitsPerSample / 8 * _inputSource.WaveFormat.Channels * _inputSource.WaveFormat.SampleRate / 20);
+                    var bytesOf100Ms = (int)((double)_inputSource.WaveFormat.BitsPerSample / 8 * _inputSource.WaveFormat.Channels * _inputSource.WaveFormat.SampleRate / 10);
 
-                var mod = bytesOf50Ms % _inputSource.BlockAlign;
-                if (mod != 0) bytesOf50Ms -= mod;
-                if (bytesOf50Ms == 0) bytesOf50Ms = _inputSource.BlockAlign;
+                    var mod = bytesOf100Ms % _inputSource.BlockAlign;
+                    if (mod != 0) bytesOf100Ms -= mod;
+                    if (bytesOf100Ms == 0) bytesOf100Ms = _inputSource.BlockAlign;
 
-                var buf = new byte[bytesOf50Ms];
+                    var buf = new byte[bytesOf100Ms];
 
-                do
-                {
-                    var count = await _inputSource.ReadAsync(buf, 0, bytesOf50Ms);
-                    if (count == 0) break;
-                } while (_inputSource.CurrentTime < seekTo);
+                    do
+                    {
+                        var count = await _inputSource.ReadAsync(buf, 0, bytesOf100Ms);
+                        if (count == 0) break;
+                    } while (_inputSource.CurrentTime < seekTo);
 
-                await PlayAsync();
+                    await PlayAsync();
+                }
+                catch (Exception exception)
+                {
+                    //TODO: 异常处理
+                    Console.WriteLine(exception);
+                    _playbackState = UIPlaybackState.Error;
+                }
             }
 
             _trackBarHolding = false;