mirror of
https://github.com/Sarsoo/Spotify.NET.git
synced 2024-12-23 22:56:25 +00:00
Fixed occasional COMException in GetSpotifyVolumeObject (#222)
* Added volume controls in Example app * Fixed occasional COMException when using Get- or SetSpotifyVolume This exception only happens if Spotify is using an audio device different from the default one. Such a thing is only possible (as of v1.0.75.483.g7ff4a0dc) when using the "--enable-audio-graph" command line argument, that makes available the "Playback device" advanced option in Spotify.
This commit is contained in:
parent
4b40a1b477
commit
159b60331e
58
SpotifyAPI.Example/LocalControl.Designer.cs
generated
58
SpotifyAPI.Example/LocalControl.Designer.cs
generated
@ -61,6 +61,10 @@
|
||||
this.artistLinkLabel = new System.Windows.Forms.LinkLabel();
|
||||
this.titleLinkLabel = new System.Windows.Forms.LinkLabel();
|
||||
this.smallAlbumPicture = new System.Windows.Forms.PictureBox();
|
||||
this.volumeDownBtn = new System.Windows.Forms.Button();
|
||||
this.volumeUpBtn = new System.Windows.Forms.Button();
|
||||
this.label9 = new System.Windows.Forms.Label();
|
||||
this.volumeMixerLabel = new System.Windows.Forms.Label();
|
||||
((System.ComponentModel.ISupportInitialize)(this.bigAlbumPicture)).BeginInit();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.trackInfoBox.SuspendLayout();
|
||||
@ -69,7 +73,7 @@
|
||||
//
|
||||
// bigAlbumPicture
|
||||
//
|
||||
this.bigAlbumPicture.Location = new System.Drawing.Point(327, 13);
|
||||
this.bigAlbumPicture.Location = new System.Drawing.Point(330, 13);
|
||||
this.bigAlbumPicture.Name = "bigAlbumPicture";
|
||||
this.bigAlbumPicture.Size = new System.Drawing.Size(640, 640);
|
||||
this.bigAlbumPicture.TabIndex = 2;
|
||||
@ -77,6 +81,10 @@
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.volumeMixerLabel);
|
||||
this.groupBox1.Controls.Add(this.label9);
|
||||
this.groupBox1.Controls.Add(this.volumeUpBtn);
|
||||
this.groupBox1.Controls.Add(this.volumeDownBtn);
|
||||
this.groupBox1.Controls.Add(this.repeatShuffleLabel);
|
||||
this.groupBox1.Controls.Add(this.label6);
|
||||
this.groupBox1.Controls.Add(this.versionLabel);
|
||||
@ -428,6 +436,50 @@
|
||||
this.smallAlbumPicture.TabIndex = 5;
|
||||
this.smallAlbumPicture.TabStop = false;
|
||||
//
|
||||
// volumeDownBtn
|
||||
//
|
||||
this.volumeDownBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.volumeDownBtn.Location = new System.Drawing.Point(247, 134);
|
||||
this.volumeDownBtn.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.volumeDownBtn.Name = "volumeDownBtn";
|
||||
this.volumeDownBtn.Size = new System.Drawing.Size(65, 24);
|
||||
this.volumeDownBtn.TabIndex = 32;
|
||||
this.volumeDownBtn.Text = "Volume-";
|
||||
this.volumeDownBtn.UseVisualStyleBackColor = true;
|
||||
this.volumeDownBtn.Click += new System.EventHandler(this.volumeDownBtn_Click);
|
||||
//
|
||||
// volumeUpBtn
|
||||
//
|
||||
this.volumeUpBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.volumeUpBtn.Location = new System.Drawing.Point(247, 110);
|
||||
this.volumeUpBtn.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.volumeUpBtn.Name = "volumeUpBtn";
|
||||
this.volumeUpBtn.Size = new System.Drawing.Size(65, 24);
|
||||
this.volumeUpBtn.TabIndex = 33;
|
||||
this.volumeUpBtn.Text = "Volume+";
|
||||
this.volumeUpBtn.UseVisualStyleBackColor = true;
|
||||
this.volumeUpBtn.Click += new System.EventHandler(this.volumeUpBtn_Click);
|
||||
//
|
||||
// label9
|
||||
//
|
||||
this.label9.AutoSize = true;
|
||||
this.label9.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label9.Location = new System.Drawing.Point(7, 117);
|
||||
this.label9.Name = "label9";
|
||||
this.label9.Size = new System.Drawing.Size(155, 17);
|
||||
this.label9.TabIndex = 34;
|
||||
this.label9.Text = "Volume Mixer\'s volume:";
|
||||
//
|
||||
// volumeMixerLabel
|
||||
//
|
||||
this.volumeMixerLabel.AutoSize = true;
|
||||
this.volumeMixerLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.volumeMixerLabel.Location = new System.Drawing.Point(168, 117);
|
||||
this.volumeMixerLabel.Name = "volumeMixerLabel";
|
||||
this.volumeMixerLabel.Size = new System.Drawing.Size(13, 17);
|
||||
this.volumeMixerLabel.TabIndex = 35;
|
||||
this.volumeMixerLabel.Text = "-";
|
||||
//
|
||||
// LocalControl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
@ -483,5 +535,9 @@
|
||||
private System.Windows.Forms.Label label6;
|
||||
private System.Windows.Forms.Label repeatShuffleLabel;
|
||||
private System.Windows.Forms.Label advertLabel;
|
||||
private System.Windows.Forms.Button volumeUpBtn;
|
||||
private System.Windows.Forms.Button volumeDownBtn;
|
||||
private System.Windows.Forms.Label volumeMixerLabel;
|
||||
private System.Windows.Forms.Label label9;
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,8 @@ namespace SpotifyAPI.Example
|
||||
|
||||
if (status.Track != null) //Update track infos
|
||||
UpdateTrack(status.Track);
|
||||
|
||||
RefreshVolumeMixerVolume();
|
||||
}
|
||||
|
||||
public async void UpdateTrack(Track track)
|
||||
@ -106,6 +108,11 @@ namespace SpotifyAPI.Example
|
||||
isPlayingLabel.Text = playing.ToString();
|
||||
}
|
||||
|
||||
public void RefreshVolumeMixerVolume()
|
||||
{
|
||||
volumeMixerLabel.Text = _spotify.GetSpotifyVolume().ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private void _spotify_OnVolumeChange(object sender, VolumeChangeEventArgs e)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
@ -178,6 +185,24 @@ namespace SpotifyAPI.Example
|
||||
_spotify.Skip();
|
||||
}
|
||||
|
||||
private void volumeUpBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
float currentVolume = _spotify.GetSpotifyVolume();
|
||||
float newVolume = currentVolume + 2.0f;
|
||||
_spotify.SetSpotifyVolume(newVolume >= 100.0f ? 100.0f : newVolume);
|
||||
|
||||
RefreshVolumeMixerVolume();
|
||||
}
|
||||
|
||||
private void volumeDownBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
float currentVolume = _spotify.GetSpotifyVolume();
|
||||
float newVolume = currentVolume - 2.0f;
|
||||
_spotify.SetSpotifyVolume(newVolume <= 0.0f ? 0.0f : newVolume);
|
||||
|
||||
RefreshVolumeMixerVolume();
|
||||
}
|
||||
|
||||
private static String FormatTime(double sec)
|
||||
{
|
||||
TimeSpan span = TimeSpan.FromSeconds(sec);
|
||||
|
@ -67,11 +67,13 @@ namespace SpotifyAPI.Local
|
||||
Marshal.ReleaseComObject(volume);
|
||||
}
|
||||
|
||||
private static ISimpleAudioVolume GetSpotifyVolumeObject() {
|
||||
return (from p in Process.GetProcessesByName(SpotifyProcessName)
|
||||
let vol = GetVolumeObject(p.Id)
|
||||
where vol != null
|
||||
select vol).FirstOrDefault();
|
||||
private static ISimpleAudioVolume GetSpotifyVolumeObject()
|
||||
{
|
||||
var audioVolumeObjects = from p in Process.GetProcessesByName(SpotifyProcessName)
|
||||
let vol = GetVolumeObject(p.Id)
|
||||
where vol != null
|
||||
select vol;
|
||||
return audioVolumeObjects.FirstOrDefault();
|
||||
}
|
||||
|
||||
private static ISimpleAudioVolume GetVolumeObject(int pid)
|
||||
@ -81,10 +83,59 @@ namespace SpotifyAPI.Local
|
||||
IMmDevice speakers;
|
||||
deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.ERender, ERole.EMultimedia, out speakers);
|
||||
|
||||
string defaultDeviceId;
|
||||
speakers.GetId(out defaultDeviceId);
|
||||
|
||||
ISimpleAudioVolume volumeControl = GetVolumeObject(pid, speakers);
|
||||
Marshal.ReleaseComObject(speakers);
|
||||
|
||||
if (volumeControl == null)
|
||||
{
|
||||
// If volumeControl is null, then the process's volume object might be on a different device.
|
||||
// This happens if the process doesn't use the default device.
|
||||
//
|
||||
// As far as Spotify is concerned, if using the "--enable-audio-graph" command line argument,
|
||||
// a new option becomes available in the Settings that makes it possible to change the playback device.
|
||||
|
||||
IMmDeviceCollection deviceCollection;
|
||||
deviceEnumerator.EnumAudioEndpoints(EDataFlow.ERender, EDeviceState.Active, out deviceCollection);
|
||||
|
||||
int count;
|
||||
deviceCollection.GetCount(out count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
IMmDevice device;
|
||||
deviceCollection.Item(i, out device);
|
||||
|
||||
string deviceId;
|
||||
device.GetId(out deviceId);
|
||||
|
||||
try
|
||||
{
|
||||
if (deviceId == defaultDeviceId)
|
||||
continue;
|
||||
|
||||
volumeControl = GetVolumeObject(pid, device);
|
||||
if (volumeControl != null)
|
||||
break;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.ReleaseComObject(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Marshal.ReleaseComObject(deviceEnumerator);
|
||||
return volumeControl;
|
||||
}
|
||||
|
||||
private static ISimpleAudioVolume GetVolumeObject(int pid, IMmDevice device)
|
||||
{
|
||||
// activate the session manager. we need the enumerator
|
||||
Guid iidIAudioSessionManager2 = typeof(IAudioSessionManager2).GUID;
|
||||
object o;
|
||||
speakers.Activate(ref iidIAudioSessionManager2, 0, IntPtr.Zero, out o);
|
||||
device.Activate(ref iidIAudioSessionManager2, 0, IntPtr.Zero, out o);
|
||||
IAudioSessionManager2 mgr = (IAudioSessionManager2)o;
|
||||
|
||||
// enumerate sessions for on this device
|
||||
@ -105,15 +156,13 @@ namespace SpotifyAPI.Local
|
||||
|
||||
if (cpid == pid)
|
||||
{
|
||||
volumeControl = (ISimpleAudioVolume) ctl;
|
||||
volumeControl = (ISimpleAudioVolume)ctl;
|
||||
break;
|
||||
}
|
||||
Marshal.ReleaseComObject(ctl);
|
||||
}
|
||||
Marshal.ReleaseComObject(sessionEnumerator);
|
||||
Marshal.ReleaseComObject(mgr);
|
||||
Marshal.ReleaseComObject(speakers);
|
||||
Marshal.ReleaseComObject(deviceEnumerator);
|
||||
return volumeControl;
|
||||
}
|
||||
|
||||
@ -121,7 +170,6 @@ namespace SpotifyAPI.Local
|
||||
[Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
|
||||
private class MMDeviceEnumerator
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private enum EDataFlow
|
||||
@ -140,10 +188,21 @@ namespace SpotifyAPI.Local
|
||||
ERoleEnumCount
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum EDeviceState
|
||||
{
|
||||
Active = 0x00000001,
|
||||
Disabled = 0x00000002,
|
||||
NotPresent = 0x00000004,
|
||||
UnPlugged = 0x00000008,
|
||||
All = 0x0000000F
|
||||
}
|
||||
|
||||
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
private interface IMmDeviceEnumerator
|
||||
{
|
||||
int NotImpl1();
|
||||
[PreserveSig]
|
||||
int EnumAudioEndpoints(EDataFlow dataFlow, EDeviceState stateMask, [Out] out IMmDeviceCollection deviceCollection);
|
||||
|
||||
[PreserveSig]
|
||||
int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMmDevice ppDevice);
|
||||
@ -154,6 +213,21 @@ namespace SpotifyAPI.Local
|
||||
{
|
||||
[PreserveSig]
|
||||
int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
|
||||
|
||||
int OpenPropertyStore_NotImpl();
|
||||
|
||||
[PreserveSig]
|
||||
int GetId([Out, MarshalAs(UnmanagedType.LPWStr)] out string ppstrId);
|
||||
}
|
||||
|
||||
[Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
private interface IMmDeviceCollection
|
||||
{
|
||||
[PreserveSig]
|
||||
int GetCount(out int deviceCount);
|
||||
|
||||
[PreserveSig]
|
||||
int Item(int deviceIndex, [Out] out IMmDevice device);
|
||||
}
|
||||
|
||||
[Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
|
Loading…
Reference in New Issue
Block a user