├── .editorconfig
├── .gitattributes
├── .github
├── FUNDING.yml
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── conversation-thread.md
│ ├── feature-request.md
│ └── improvement-request.md
├── .gitignore
├── EspionSpotify.FakeSpotify
├── App.config
├── EspionSpotify.FakeSpotify.csproj
├── EspionSpotify.FakeSpotify.csproj.DotSettings
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── frmSpotify.Designer.cs
├── frmSpotify.cs
├── frmSpotify.resx
├── icon.ico
└── packages.config
├── EspionSpotify.Tests
├── EspionSpotify.Tests.csproj
├── ExtensionsTests.cs
├── FileManagerTests.cs
├── LastFMAPITests.cs
├── MapperID3Tests.cs
├── Properties
│ └── AssemblyInfo.cs
├── RecorderTests.cs
├── SpotifyAPITests.cs
├── SpotifyHandlerTests.cs
├── SpotifyProcessTests.cs
├── SpotifyStatusTests.cs
├── TagLibTab.cs
├── TrackTests.cs
├── TranslationTests.cs
├── UserSettingTests.cs
├── WatcherTests.cs
├── app.config
└── packages.config
├── EspionSpotify.Updater
├── App.config
├── EspionSpotify.Updater.csproj
├── Models
│ └── GitHub
│ │ ├── Asset.cs
│ │ ├── Release.cs
│ │ └── User.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── Updater.cs
├── Utilities
│ ├── AssemblyInfo.cs
│ ├── CustomExceptions.cs
│ ├── Extensions.cs
│ ├── GitHub.cs
│ └── Web.cs
└── packages.config
├── EspionSpotify.sln
├── EspionSpotify
├── API
│ ├── ExternalAPI.cs
│ ├── IExternalAPI.cs
│ ├── ILastFMAPI.cs
│ ├── IMapperID3.cs
│ ├── ISpotifyAPI.cs
│ ├── LastFMAPI.cs
│ ├── MapperID3.cs
│ ├── NoneAPI.cs
│ └── SpotifyAPI.cs
├── Analytics.cs
├── App.config
├── AudioSessions
│ ├── AudioCircularBuffer.cs
│ ├── AudioLoopback.cs
│ ├── AudioMMDevicesManager.cs
│ ├── AudioThrottler.cs
│ ├── IAudioCircularBuffer.cs
│ ├── IAudioLoopback.cs
│ ├── IAudioThrottler.cs
│ ├── IMainAudioSession.cs
│ └── MainAudioSession.cs
├── Constants.cs
├── Controls
│ ├── MetroComboBox.cs
│ ├── MetroCredentialsForm.cs
│ ├── MetroCredentialsForm.resx
│ └── MetroTrackBar.cs
├── Drivers
│ ├── AudioVirtualCableDriver.cs
│ ├── VBCABLE_ControlPanel.exe
│ ├── VBCABLE_Setup.exe
│ ├── VBCABLE_Setup_x64.exe
│ ├── pin_in.ico
│ ├── pin_out.ico
│ ├── readme.txt
│ ├── vbMmeCable64_2003.inf
│ ├── vbMmeCable64_vista.inf
│ ├── vbMmeCable64_win7.inf
│ ├── vbMmeCable_2003.inf
│ ├── vbMmeCable_vista.inf
│ ├── vbMmeCable_win7.inf
│ ├── vbMmeCable_xp.inf
│ ├── vbaudio_cable64_2003.cat
│ ├── vbaudio_cable64_2003.sys
│ ├── vbaudio_cable64_vista.cat
│ ├── vbaudio_cable64_vista.sys
│ ├── vbaudio_cable64_win7.cat
│ ├── vbaudio_cable64_win7.sys
│ ├── vbaudio_cable_2003.cat
│ ├── vbaudio_cable_2003.sys
│ ├── vbaudio_cable_vista.cat
│ ├── vbaudio_cable_vista.sys
│ ├── vbaudio_cable_win7.cat
│ ├── vbaudio_cable_win7.sys
│ ├── vbaudio_cable_xp.cat
│ └── vbaudio_cable_xp.sys
├── Enums
│ ├── AlbumCoverSize.cs
│ ├── ExternalAPIType.cs
│ ├── LanguageType.cs
│ ├── LastFMNodeStatus.cs
│ ├── MediaFormat.cs
│ ├── OSVersions.cs
│ ├── RecordRecordingsStatus.cs
│ ├── SilenceAnalyzer.cs
│ ├── TitleSeparatorType.cs
│ ├── TranslationKeys.cs
│ └── WaveFormatMP3Restriction.cs
├── EspionSpotify.csproj
├── Events
│ ├── PlayStateEventArgs.cs
│ ├── TrackChangeEventArgs.cs
│ └── TrackTimeChangeEventArgs.cs
├── Exceptions
│ ├── DestinationPathNotFoundException.cs
│ └── SourceFileNotFoundException.cs
├── Extensions
│ ├── ClassPropertyExtensions.cs
│ ├── ColorExtensions.cs
│ ├── ControlExtensions.cs
│ ├── DictionaryExtensions.cs
│ ├── JsonObjectExtensions.cs
│ ├── LinqExtensions.cs
│ ├── NAudioExtensions.cs
│ ├── OperatingSystemExtensions.cs
│ ├── ResourceManagerExtensions.cs
│ ├── SettingExtensions.cs
│ ├── SpotifyWebAPIExtensions.cs
│ ├── StringExtensions.cs
│ └── WaveFormatExtensions.cs
├── GitHub.cs
├── IFrmEspionSpotify.cs
├── IRecorder.cs
├── IWatcher.cs
├── Models
│ ├── AudioWaveBuffer.cs
│ ├── GitHub
│ │ ├── Asset.cs
│ │ ├── Release.cs
│ │ └── User.cs
│ ├── LastFMNode.cs
│ ├── OutputFile.cs
│ ├── RecorderTask.cs
│ ├── SpotifyWindowInfo.cs
│ ├── Track.cs
│ └── UserSettings.cs
├── Native
│ ├── Combase.cs
│ ├── FileManager.cs
│ ├── IProcessManager.cs
│ ├── Models
│ │ ├── HRESULT.cs
│ │ ├── IProcess.cs
│ │ └── Process.cs
│ ├── NativeMethods.cs
│ └── ProcessManager.cs
├── Normalize.cs
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ ├── Settings.settings
│ └── app.manifest
├── RESET_APP_SETTINGS.BAT
├── Recorder.cs
├── Resources
│ ├── add_device.gif
│ ├── clear.gif
│ ├── faq.gif
│ ├── folder.gif
│ ├── heart.gif
│ ├── key.gif
│ ├── logo_en.gif
│ ├── minus.gif
│ ├── off.gif
│ ├── on.gif
│ ├── pause.gif
│ ├── play.gif
│ ├── plus.gif
│ ├── record.gif
│ ├── release.gif
│ ├── remove_device.gif
│ ├── spotify.gif
│ ├── spytify-logo.png
│ ├── spytify.ico
│ ├── voldown.gif
│ ├── volmute.gif
│ └── volup.gif
├── Router
│ ├── AudioRouter.cs
│ ├── Helpers
│ │ ├── AudioPolicyConfigFactory.cs
│ │ ├── AudioPolicyConfigFactoryImplFor21H2.cs
│ │ ├── AudioPolicyConfigFactoryImplForDownlevel.cs
│ │ └── IAudioPolicyConfigFactory.cs
│ ├── IAudioPolicyConfigFactory21H2.cs
│ ├── IAudioPolicyConfigFactoryDownlevel.cs
│ └── IAudioRouter.cs
├── Settings.cs
├── Spotify
│ ├── ISpotifyHandler.cs
│ ├── ISpotifyProcess.cs
│ ├── ISpotifyStatus.cs
│ ├── SpotifyConnect.cs
│ ├── SpotifyHandler.cs
│ ├── SpotifyProcess.cs
│ └── SpotifyStatus.cs
├── Translations
│ ├── I18nKeys.cs
│ ├── Languages.cs
│ ├── README.MD
│ ├── en.Designer.cs
│ ├── en.resx
│ ├── fr.Designer.cs
│ └── fr.resx
├── Updater.cs
├── Watcher.cs
├── frmEspionSpotify.Designer.cs
├── frmEspionSpotify.cs
├── frmEspionSpotify.resx
├── libmp3lame.32.dll
├── libmp3lame.64.dll
├── packages.config
└── setup-spotify-api.txt
├── LICENSE
├── README.md
├── appveyor.yml
└── psd
├── features_icons.psd
├── icons.psd
├── logo-en.png
├── logo-fr.png
├── logo.png
├── logo256px.png
├── logos_sp.psd
├── on-off.psd
├── spytify-espion-spotify-logo-small.png
├── spytify-espion-spotify-logo-small.psd
└── spytify-espion-spotify-logo.psd
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 |
3 | # CS0618: Type or member is obsolete
4 | dotnet_diagnostic.CS0618.severity = silent
5 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: jwallet
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: ['jwallet.github.io/spy-spotify/donate']
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a bug report to help fix Spytify
4 | title: ''
5 | labels: "bug \U0001F41E"
6 | assignees: ''
7 |
8 | ---
9 |
10 |
13 |
14 | **Track used**
15 |
18 |
19 | **Screenshots**
20 |
23 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/conversation-thread.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Conversation thread
3 | about: Create a new conversation thread that will be moved to the Discussions section under QA.
4 | title: ''
5 | labels: "question \U0001F4AC"
6 | assignees: ''
7 |
8 | ---
9 |
10 | You can now use the Discussions section
11 | https://github.com/jwallet/spy-spotify/discussions
12 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an new feature to improve Spytify that will be moved to the Discussions section under Idea
4 | title: ''
5 | labels: feature ✨
6 | assignees: ''
7 |
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/improvement-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Improvement request
3 | about: Suggest an enhancement of a current feature that will be moved to the Discussions section under Idea
4 | title: ''
5 | labels: task ⚒
6 | assignees: ''
7 |
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # The following command works for downloading when using Git for Windows:
2 | # curl -LOf http://gist.githubusercontent.com/kmorcinek/2710267/raw/.gitignore
3 | #
4 | # Download this file using PowerShell v3 under Windows with the following comand:
5 | # Invoke-WebRequest https://gist.githubusercontent.com/kmorcinek/2710267/raw/ -OutFile .gitignore
6 | #
7 | # or wget:
8 | # wget --no-check-certificate http://gist.githubusercontent.com/kmorcinek/2710267/raw/.gitignore
9 |
10 | # User-specific files
11 | *.suo
12 | *.user
13 | *.sln.docstates
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Rr]elease/
18 | x64/
19 | [Bb]in/
20 | [Oo]bj/
21 | # build folder is nowadays used for build scripts and should not be ignored
22 | #build/
23 |
24 | # NuGet Packages
25 | *.nupkg
26 | # The packages folder can be ignored because of Package Restore
27 | **/packages/*
28 | # except build/, which is used as an MSBuild target.
29 | !**/packages/build/
30 | # Uncomment if necessary however generally it will be regenerated when needed
31 | #!**/packages/repositories.config
32 |
33 | # MSTest test Results
34 | [Tt]est[Rr]esult*/
35 | [Bb]uild[Ll]og.*
36 |
37 | _site/
38 | .jekyll-cache/
39 |
40 | *_i.c
41 | *_p.c
42 | *.ilk
43 | *.meta
44 | *.obj
45 | *.pch
46 | *.pdb
47 | *.pgc
48 | *.pgd
49 | *.rsp
50 | *.sbr
51 | *.tlb
52 | *.tli
53 | *.tlh
54 | *.tmp
55 | *.tmp_proj
56 | *.log
57 | *.vspscc
58 | *.vssscc
59 | .builds
60 | *.pidb
61 | *.log
62 | *.scc
63 |
64 | # OS generated files #
65 | .DS_Store*
66 | Icon?
67 |
68 | # Visual C++ cache files
69 | ipch/
70 | *.aps
71 | *.ncb
72 | *.opensdf
73 | *.sdf
74 | *.cachefile
75 |
76 | # Visual Studio profiler
77 | *.psess
78 | *.vsp
79 | *.vspx
80 |
81 | # Guidance Automation Toolkit
82 | *.gpState
83 |
84 | # ReSharper is a .NET coding add-in
85 | _ReSharper*/
86 | *.[Rr]e[Ss]harper
87 |
88 | # TeamCity is a build add-in
89 | _TeamCity*
90 |
91 | # DotCover is a Code Coverage Tool
92 | *.dotCover
93 |
94 | # NCrunch
95 | *.ncrunch*
96 | .*crunch*.local.xml
97 |
98 | # Installshield output folder
99 | [Ee]xpress/
100 |
101 | # DocProject is a documentation generator add-in
102 | DocProject/buildhelp/
103 | DocProject/Help/*.HxT
104 | DocProject/Help/*.HxC
105 | DocProject/Help/*.hhc
106 | DocProject/Help/*.hhk
107 | DocProject/Help/*.hhp
108 | DocProject/Help/Html2
109 | DocProject/Help/html
110 |
111 | # Click-Once directory
112 | publish/
113 |
114 | # Publish Web Output
115 | *.Publish.xml
116 |
117 | # Windows Azure Build Output
118 | csx
119 | *.build.csdef
120 |
121 | # Windows Store app package directory
122 | AppPackages/
123 |
124 | # Others
125 | *.Cache
126 | ClientBin/
127 | [Ss]tyle[Cc]op.*
128 | ~$*
129 | *~
130 | *.dbmdl
131 | *.[Pp]ublish.xml
132 | *.pfx
133 | *.publishsettings
134 | modulesbin/
135 | tempbin/
136 |
137 | # EPiServer Site file (VPP)
138 | AppData/
139 |
140 | # RIA/Silverlight projects
141 | Generated_Code/
142 |
143 | # Backup & report files from converting an old project file to a newer
144 | # Visual Studio version. Backup files are not needed, because we have git ;-)
145 | _UpgradeReport_Files/
146 | Backup*/
147 | UpgradeLog*.XML
148 | UpgradeLog*.htm
149 |
150 | # vim
151 | *.txt~
152 | *.swp
153 | *.swo
154 |
155 | # Temp files when opening LibreOffice on ubuntu
156 | .~lock.*
157 |
158 | # svn
159 | .svn
160 |
161 | # CVS - Source Control
162 | **/CVS/
163 |
164 | # Remainings from resolving conflicts in Source Control
165 | *.orig
166 |
167 | # SQL Server files
168 | **/App_Data/*.mdf
169 | **/App_Data/*.ldf
170 | **/App_Data/*.sdf
171 |
172 |
173 | #LightSwitch generated files
174 | GeneratedArtifacts/
175 | _Pvt_Extensions/
176 | ModelManifest.xml
177 |
178 | # =========================
179 | # Windows detritus
180 | # =========================
181 |
182 | # Windows image file caches
183 | Thumbs.db
184 | ehthumbs.db
185 |
186 | # Folder config file
187 | Desktop.ini
188 |
189 | # Recycle Bin used on file shares
190 | $RECYCLE.BIN/
191 |
192 | # Mac desktop service store files
193 | .DS_Store
194 |
195 | # SASS Compiler cache
196 | .sass-cache
197 |
198 | # Visual Studio 2014 CTP
199 | **/*.sln.ide
200 |
201 | # Visual Studio temp something
202 | .vs/
203 |
204 | # dotnet stuff
205 | project.lock.json
206 |
207 | # VS 2015+
208 | *.vc.vc.opendb
209 | *.vc.db
210 |
211 | # Rider
212 | .idea/
213 |
214 | # Visual Studio Code
215 | .vscode/
216 |
217 | # Output folder used by Webpack or other FE stuff
218 | **/node_modules/*
219 | **/wwwroot/*
220 |
221 | # SpecFlow specific
222 | *.feature.cs
223 | *.feature.xlsx.*
224 | *.Specs_*.html
225 |
226 | #####
227 | # End of core ignore list, below put you custom 'per project' settings (patterns or path)
228 | #####
229 |
230 | docs/*
--------------------------------------------------------------------------------
/EspionSpotify.FakeSpotify/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/EspionSpotify.FakeSpotify/EspionSpotify.FakeSpotify.csproj.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | D:\dev\spy-spotify\packages\NAudio.1.10.0\lib\net35\NAudio.dll|*D:\dev\spy-spotify\packages\MetroModernUI.1.4.0.0\lib\net\MetroFramework.dll|MetroFramework.Components.MetroStyleExtender;MetroFramework.Components.MetroStyleManager;MetroFramework.Components.MetroToolTip;MetroFramework.Controls.MetroButton;MetroFramework.Controls.MetroCheckBox;MetroFramework.Controls.MetroComboBox;MetroFramework.Controls.MetroContextMenu;MetroFramework.Controls.MetroDateTime;MetroFramework.Controls.MetroGrid;MetroFramework.Controls.MetroLabel;MetroFramework.Controls.MetroLink;MetroFramework.Controls.MetroListView;MetroFramework.Controls.MetroPanel;MetroFramework.Controls.MetroProgressBar;MetroFramework.Controls.MetroProgressSpinner;MetroFramework.Controls.MetroRadioButton;MetroFramework.Controls.MetroScrollBar;MetroFramework.Controls.MetroTabControl;MetroFramework.Controls.MetroTextBox;MetroFramework.Controls.MetroTile;MetroFramework.Controls.MetroToggle;MetroFramework.Controls.MetroTrackBar;MetroFramework.Controls.MetroUserControl;MetroFramework.Drawing.Html.HtmlPanel;MetroFramework.Drawing.Html.HtmlLabel;MetroFramework.Drawing.Html.HtmlToolTip
--------------------------------------------------------------------------------
/EspionSpotify.FakeSpotify/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Windows.Forms;
4 |
5 | namespace EspionSpotify.FakeSpotify
6 | {
7 | static class Program
8 | {
9 | ///
10 | /// The main entry point for the application.
11 | ///
12 | [STAThread]
13 | static void Main()
14 | {
15 | Application.EnableVisualStyles();
16 | Application.SetCompatibleTextRenderingDefault(false);
17 | Application.Run(new FrmSpotify());
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/EspionSpotify.FakeSpotify/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Spotify")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Spotify")]
13 | [assembly: AssemblyCopyright("Copyright © 2022")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("AC6E7B02-7941-40B2-88D0-C53B50073073")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/EspionSpotify.FakeSpotify/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace EspionSpotify.FakeSpotify.Properties
12 | {
13 | ///
14 | /// A strongly-typed resource class, for looking up localized strings, etc.
15 | ///
16 | // This class was auto-generated by the StronglyTypedResourceBuilder
17 | // class via a tool like ResGen or Visual Studio.
18 | // To add or remove a member, edit your .ResX file then rerun ResGen
19 | // with the /str option, or rebuild your VS project.
20 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder",
21 | "4.0.0.0")]
22 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
23 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
24 | internal class Resources
25 | {
26 | private static global::System.Resources.ResourceManager resourceMan;
27 |
28 | private static global::System.Globalization.CultureInfo resourceCulture;
29 |
30 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance",
31 | "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources()
33 | {
34 | }
35 |
36 | ///
37 | /// Returns the cached ResourceManager instance used by this class.
38 | ///
39 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState
40 | .Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp =
48 | new global::System.Resources.ResourceManager("EspionSpotify.FakeSpotify.Properties.Resources",
49 | typeof(Resources).Assembly);
50 | resourceMan = temp;
51 | }
52 |
53 | return resourceMan;
54 | }
55 | }
56 |
57 | ///
58 | /// Overrides the current thread's CurrentUICulture property for all
59 | /// resource lookups using this strongly typed resource class.
60 | ///
61 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState
62 | .Advanced)]
63 | internal static global::System.Globalization.CultureInfo Culture
64 | {
65 | get { return resourceCulture; }
66 | set { resourceCulture = value; }
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/EspionSpotify.FakeSpotify/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace EspionSpotify.FakeSpotify.Properties
12 | {
13 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
14 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute(
15 | "Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
17 | {
18 | private static Settings defaultInstance =
19 | ((Settings) (global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
20 |
21 | public static Settings Default
22 | {
23 | get { return defaultInstance; }
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/EspionSpotify.FakeSpotify/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/EspionSpotify.FakeSpotify/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify.FakeSpotify/icon.ico
--------------------------------------------------------------------------------
/EspionSpotify.FakeSpotify/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/EspionSpotify.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | [assembly: AssemblyTitle("EspionSpotify.Tests")]
5 | [assembly: AssemblyDescription("")]
6 | [assembly: AssemblyConfiguration("")]
7 | [assembly: AssemblyCompany("")]
8 | [assembly: AssemblyProduct("EspionSpotify.Tests")]
9 | [assembly: AssemblyCopyright("Copyright © 2018")]
10 | [assembly: AssemblyTrademark("")]
11 | [assembly: AssemblyCulture("")]
12 |
13 | [assembly: ComVisible(false)]
14 |
15 | [assembly: Guid("9a936c14-6665-48a8-a79d-14347f50e215")]
16 |
17 | // [assembly: AssemblyVersion("1.0.*")]
18 | [assembly: AssemblyVersion("1.0.0.0")]
19 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/EspionSpotify.Tests/SpotifyStatusTests.cs:
--------------------------------------------------------------------------------
1 | using EspionSpotify.Extensions;
2 | using EspionSpotify.Models;
3 | using EspionSpotify.Spotify;
4 | using Xunit;
5 |
6 | namespace EspionSpotify.Tests
7 | {
8 | public class SpotifyStatusTests
9 | {
10 | [Theory]
11 | [InlineData(null, true)]
12 | [InlineData("", true)]
13 | [InlineData("Artist Name - Song Title", false)]
14 | [InlineData(Constants.ADVERTISEMENT, false)]
15 | [InlineData(Constants.SPOTIFY, true)]
16 | [InlineData(Constants.SPOTIFYFREE, true)]
17 | [InlineData(Constants.SPOTIFYPREMIUM, true)]
18 | [InlineData("SPOTIFY", true)]
19 | [InlineData("spotify", true)]
20 | internal void SpotifyStatusWindowTitleIsSpotify_ReturnsWhenItMatches(string value, bool expected)
21 | {
22 | var actual = value.IsNullOrSpotifyIdleState();
23 |
24 | Assert.Equal(expected, actual);
25 | }
26 |
27 | [Fact]
28 | internal void SpotifyStatusSpotifyStandingBy_ReturnsExpectingTrack()
29 | {
30 | var expectedTrack = new Track
31 | {
32 | Artist = Constants.SPOTIFY
33 | };
34 | var spotifyWindowInfo = new SpotifyWindowInfo
35 | {
36 | WindowTitle = Constants.SPOTIFY,
37 | IsPlaying = false
38 | };
39 |
40 | var status = new SpotifyStatus(spotifyWindowInfo);
41 |
42 | Assert.Equal(expectedTrack, status.CurrentTrack);
43 | Assert.Equal(Constants.SPOTIFY, status.CurrentTrack.ToString());
44 | }
45 |
46 | [Theory]
47 | [InlineData("Artist Name - Song Title", false)]
48 | [InlineData("Artist Name - Song Title - Live", true)]
49 | internal void SpotifyStatusTrackPlaying_ReturnsExpectingTrack(string windowTitle, bool isTitleExtended)
50 | {
51 | var expectedTrack = new Track
52 | {
53 | Artist = "Artist Name",
54 | Title = "Song Title",
55 | TitleExtended = isTitleExtended ? "Live" : "",
56 | Playing = true,
57 | Ad = false
58 | };
59 | var spotifyWindowInfo = new SpotifyWindowInfo
60 | {
61 | WindowTitle = windowTitle,
62 | IsPlaying = true
63 | };
64 |
65 | var status = new SpotifyStatus(spotifyWindowInfo);
66 |
67 | Assert.Equal(expectedTrack, status.CurrentTrack);
68 | Assert.Equal(windowTitle, status.CurrentTrack.ToString());
69 | }
70 |
71 | [Theory]
72 | [InlineData(Constants.SPOTIFY)]
73 | [InlineData("Spotify Sponsor")]
74 | [InlineData("#1337: DAILY NEWS")]
75 | internal void SpotifyStatusSpotifyPlayingAdOrUnknown_ReturnsExpectingTrack(string windowTitle)
76 | {
77 | var expectedTrack = new Track
78 | {
79 | Artist = windowTitle,
80 | Title = null,
81 | TitleExtended = null,
82 | Playing = true,
83 | Ad = true
84 | };
85 | var spotifyWindowInfo = new SpotifyWindowInfo
86 | {
87 | WindowTitle = windowTitle,
88 | IsPlaying = true
89 | };
90 |
91 | var status = new SpotifyStatus(spotifyWindowInfo);
92 |
93 | Assert.Equal(expectedTrack, status.CurrentTrack);
94 | Assert.Equal(expectedTrack.ToString(), status.CurrentTrack.ToString());
95 | }
96 | }
97 | }
--------------------------------------------------------------------------------
/EspionSpotify.Tests/TagLibTab.cs:
--------------------------------------------------------------------------------
1 | using TagLib;
2 |
3 | namespace EspionSpotify.Tests
4 | {
5 | public class TagLibTab : Tag
6 | {
7 | public override TagTypes TagTypes { get; }
8 |
9 | public override uint Track { get; set; }
10 |
11 | public override string Title { get; set; }
12 | public override string Subtitle { get; set; }
13 | public override string[] AlbumArtists { get; set; }
14 | public override string[] Performers { get; set; }
15 |
16 | public override string Album { get; set; }
17 | public override string[] Genres { get; set; }
18 |
19 | public override uint Year { get; set; }
20 | public override uint Disc { get; set; }
21 |
22 | public override IPicture[] Pictures { get; set; }
23 |
24 | public override void Clear()
25 | {
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/EspionSpotify.Tests/TrackTests.cs:
--------------------------------------------------------------------------------
1 | using EspionSpotify.Enums;
2 | using EspionSpotify.Models;
3 | using Xunit;
4 |
5 | namespace EspionSpotify.Tests
6 | {
7 | public class TrackTests
8 | {
9 | [Fact]
10 | internal void DefaultTrack_ReturnsEmptyTrack()
11 | {
12 | var track = new Track();
13 |
14 | Assert.False(track.IsNormalPlaying);
15 | Assert.Equal("Spotify", track.ToString());
16 | }
17 |
18 | [Fact]
19 | internal void MinimalTrack_ReturnsBasicInfo()
20 | {
21 | var track = new Track
22 | {
23 | Title = "Song Title",
24 | Artist = "Artist Name",
25 | Ad = false,
26 | Playing = true,
27 | TitleExtended = "Live",
28 | TitleExtendedSeparatorType = TitleSeparatorType.Dash
29 | };
30 |
31 | Assert.True(track.IsNormalPlaying);
32 | Assert.Equal("Artist Name - Song Title - Live", track.ToString());
33 | Assert.NotEqual(track, new Track());
34 | }
35 |
36 | [Theory]
37 | [InlineData("A", "B", false, true, true)]
38 | [InlineData("A", "", false, true, false)]
39 | [InlineData("", "B", false, true, false)]
40 | [InlineData("", "", false, true, false)]
41 | [InlineData(null, null, false, true, false)]
42 | [InlineData("A", "B", true, true, false)]
43 | [InlineData("A", "B", false, false, false)]
44 | internal void IsNormal_ReturnsExpectedNormalResults(string artist, string title, bool ad, bool playing,
45 | bool expected)
46 | {
47 | var track = new Track {Artist = artist, Title = title, Ad = ad, Playing = playing};
48 |
49 | Assert.Equal(expected, track.IsNormalPlaying);
50 | }
51 |
52 | [Fact]
53 | internal void TrackWithInitialTrack_ReturnsUpdatedTrack()
54 | {
55 | var initialTrack = new Track
56 | {
57 | Title = "Song Title",
58 | Artist = "Artist Name",
59 | Ad = false,
60 | Playing = true,
61 | TitleExtended = "Live",
62 | TitleExtendedSeparatorType = TitleSeparatorType.Dash
63 | };
64 |
65 | var track = new Track(initialTrack)
66 | {
67 | Album = "Album",
68 | AlbumPosition = 1,
69 | AlbumArtUrl = "http://logo.png"
70 | };
71 |
72 | Assert.Equal(initialTrack.ToString(), track.ToString());
73 | Assert.NotEqual(initialTrack.Album, track.Album);
74 | Assert.NotEqual(initialTrack.AlbumArtUrl, track.AlbumArtUrl);
75 | Assert.NotEqual(track, new Track());
76 | }
77 |
78 | [Fact]
79 | internal void ToTitleString_ReturnsTitleAndExtendedTitle()
80 | {
81 | Assert.Equal("", new Track().ToTitleString());
82 |
83 | Assert.Equal(
84 | "Title",
85 | new Track
86 | {
87 | Title = "Title",
88 | Artist = "Artist",
89 | TitleExtended = "Must Not Return",
90 | TitleExtendedSeparatorType = TitleSeparatorType.None
91 | }.ToTitleString());
92 |
93 | Assert.Equal(
94 | "Title - Remastered",
95 | new Track
96 | {
97 | Title = "Title",
98 | Artist = "Artist",
99 | TitleExtended = "Remastered",
100 | TitleExtendedSeparatorType = TitleSeparatorType.Dash
101 | }.ToTitleString());
102 |
103 | Assert.Equal(
104 | "Title (Featuring Other)",
105 | new Track
106 | {
107 | Title = "Title",
108 | Artist = "Artist",
109 | TitleExtended = "Featuring Other",
110 | TitleExtendedSeparatorType = TitleSeparatorType.Parenthesis
111 | }.ToTitleString());
112 |
113 | Assert.Equal(
114 | "Title (Featuring Other) - Remastered",
115 | new Track
116 | {
117 | Title = "Title (Featuring Other)",
118 | Artist = "Artist",
119 | TitleExtended = "Remastered",
120 | TitleExtendedSeparatorType = TitleSeparatorType.Dash
121 | }.ToTitleString());
122 | }
123 |
124 | [Fact]
125 | internal void TrackEquals_ReturnsAsExpected()
126 | {
127 | var trackEmpty = new Track();
128 | var trackDetailed = new Track
129 | {
130 | Title = "Title",
131 | Artist = "Artist",
132 | TitleExtended = "",
133 | Ad = false
134 | };
135 |
136 | Assert.True(trackEmpty.Equals(new Track()));
137 | Assert.True(trackDetailed.Equals(new Track {Title = "Title", Artist = "Artist"}));
138 |
139 | Assert.False(trackEmpty.Equals(null));
140 | Assert.False(trackEmpty.Equals(new OutputFile()));
141 | Assert.False(trackEmpty.Equals(new Track {Title = "Title"}));
142 | }
143 | }
144 | }
--------------------------------------------------------------------------------
/EspionSpotify.Tests/TranslationTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Globalization;
4 | using System.Linq;
5 | using System.Resources;
6 | using EspionSpotify.Enums;
7 | using EspionSpotify.Extensions;
8 | using EspionSpotify.Translations;
9 | using Xunit;
10 |
11 | namespace EspionSpotify.Tests
12 | {
13 | public class TranslationTests
14 | {
15 | private static ResourceManager RM;
16 | private readonly Type _en;
17 | private readonly Type _fr;
18 | private readonly int _keysCount;
19 |
20 | public TranslationTests()
21 | {
22 | _en = Languages.GetResourcesManagerLanguageType(LanguageType.en);
23 | _fr = Languages.GetResourcesManagerLanguageType(LanguageType.fr);
24 |
25 | _keysCount = Enum.GetNames(typeof(TranslationKeys)).Length;
26 | }
27 |
28 | [Fact]
29 | internal void TranslationSetup_ShouldBeReady()
30 | {
31 | Assert.NotNull(_en);
32 | Assert.NotNull(_fr);
33 | }
34 |
35 | private void ShouldGetTranslations(ResourceManager RM)
36 | {
37 | var resourceSet = RM.GetResourceSet(CultureInfo.InvariantCulture, true, true);
38 | var count = 0;
39 |
40 | foreach (DictionaryEntry o in resourceSet)
41 | {
42 | count++;
43 | var actual = (string) o.Key;
44 | var expected = actual.ToEnum(false)?.ToString();
45 | Assert.Equal(expected, actual);
46 | }
47 |
48 | Assert.Equal(count, _keysCount);
49 | }
50 |
51 | [Fact]
52 | internal void English_ShouldGetTranslations()
53 | {
54 | ShouldGetTranslations(new ResourceManager(_en));
55 | }
56 |
57 | [Fact]
58 | internal void French_ShouldGetTranslations()
59 | {
60 | ShouldGetTranslations(new ResourceManager(_fr));
61 | }
62 |
63 | [Fact]
64 | internal void Unsupported_ShouldNotGetTranslations()
65 | {
66 | RM = new ResourceManager(typeof(Languages));
67 | Assert.Throws(() =>
68 | RM.GetResourceSet(CultureInfo.InvariantCulture, true, true));
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/EspionSpotify.Tests/UserSettingTests.cs:
--------------------------------------------------------------------------------
1 | using EspionSpotify.Models;
2 | using Xunit;
3 |
4 | namespace EspionSpotify.Tests
5 | {
6 | public class UserSettingTests
7 | {
8 | [Fact]
9 | internal void DefaultUserSettings_ReturnsDefault()
10 | {
11 | var userSettings = new UserSettings();
12 |
13 | Assert.Equal(1, userSettings.InternalOrderNumber);
14 | Assert.False(userSettings.HasRecordingTimerEnabled);
15 | Assert.Equal(0.0, userSettings.RecordingTimerMilliseconds);
16 | Assert.Null(userSettings.OrderNumberAsFile);
17 | Assert.Null(userSettings.OrderNumberAsTag);
18 | Assert.False(userSettings.IsSpotifyAPISet);
19 | }
20 |
21 | [Fact]
22 | internal void RecordingTimer_ReturnsRecordingTimerEnabled()
23 | {
24 | Assert.False(new UserSettings {RecordingTimer = ""}.HasRecordingTimerEnabled);
25 | Assert.False(new UserSettings {RecordingTimer = "1337"}.HasRecordingTimerEnabled);
26 | Assert.False(new UserSettings {RecordingTimer = "000000"}.HasRecordingTimerEnabled);
27 |
28 | Assert.True(new UserSettings {RecordingTimer = "001337"}.HasRecordingTimerEnabled);
29 | }
30 |
31 | [Fact]
32 | internal void RecordingTimer_ReturnsRecordingTimerMilliseconds()
33 | {
34 | Assert.Equal(0, new UserSettings {RecordingTimer = "000000"}.RecordingTimerMilliseconds);
35 | Assert.Equal(1000, new UserSettings {RecordingTimer = "000001"}.RecordingTimerMilliseconds);
36 | Assert.Equal(817000, new UserSettings {RecordingTimer = "001337"}.RecordingTimerMilliseconds);
37 | Assert.Equal(43200000, new UserSettings {RecordingTimer = "120000"}.RecordingTimerMilliseconds);
38 | // invalid value to passed
39 | Assert.Equal(362439000, new UserSettings {RecordingTimer = "999999"}.RecordingTimerMilliseconds);
40 | }
41 |
42 | [Fact]
43 | internal void OrderNumberMask_ReturnsMaskAsMax()
44 | {
45 | Assert.Equal(99999, new UserSettings {OrderNumberMask = "00000"}.OrderNumberMax);
46 | }
47 |
48 | [Fact]
49 | internal void HasOrderNumberEnabled_ReturnsAsExpected()
50 | {
51 | Assert.True(new UserSettings {OrderNumberInfrontOfFileEnabled = true}.HasOrderNumberEnabled);
52 | Assert.True(new UserSettings {OrderNumberInMediaTagEnabled = true}.HasOrderNumberEnabled);
53 | Assert.False(new UserSettings().HasOrderNumberEnabled);
54 | }
55 |
56 | [Fact]
57 | internal void InternalOrderNumber_ReturnsOrderNumberAsFile()
58 | {
59 | Assert.Equal(1, new UserSettings {OrderNumberInfrontOfFileEnabled = true}.OrderNumberAsFile);
60 | }
61 |
62 | [Fact]
63 | internal void InternalOrderNumber_ReturnsOrderNumberAsTag()
64 | {
65 | Assert.Equal(1, new UserSettings {OrderNumberInMediaTagEnabled = true}.OrderNumberAsTag);
66 | }
67 |
68 | [Fact]
69 | internal void SpotifyAPISecrets_ReturnsIsSpotifyAPISet()
70 | {
71 | Assert.False(new UserSettings {SpotifyAPIClientId = "", SpotifyAPISecretId = ""}.IsSpotifyAPISet);
72 | Assert.False(new UserSettings {SpotifyAPIClientId = "abc123", SpotifyAPISecretId = ""}.IsSpotifyAPISet);
73 | Assert.False(new UserSettings {SpotifyAPIClientId = "", SpotifyAPISecretId = "abc123"}.IsSpotifyAPISet);
74 | Assert.True(new UserSettings {SpotifyAPIClientId = "abc123", SpotifyAPISecretId = "abc123"}
75 | .IsSpotifyAPISet);
76 | }
77 | }
78 | }
--------------------------------------------------------------------------------
/EspionSpotify.Tests/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/EspionSpotify.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/EspionSpotify.Updater/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/EspionSpotify.Updater/EspionSpotify.Updater.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {F20370C5-7613-452E-8FCD-06F7F5703C35}
8 | Exe
9 | EspionSpotify.Updater
10 | Updater
11 | v4.6.1
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | ..\EspionSpotify\bin\Debug\Updater\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | ..\EspionSpotify\bin\Release\Updater\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 | ..\packages\DotNetZip.1.11.0\lib\net20\DotNetZip.dll
38 |
39 |
40 | ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll
41 | True
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/EspionSpotify.Updater/Models/GitHub/Asset.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace EspionSpotify.Updater.Models.GitHub
4 | {
5 | [Serializable]
6 | internal class Asset
7 | {
8 | public string url { get; set; }
9 | public int id { get; set; }
10 | public string node_id { get; set; }
11 | public string name { get; set; }
12 | public string lable { get; set; }
13 | public User uploader { get; set; }
14 | public string content_type { get; set; }
15 | public string state { get; set; }
16 | public int? size { get; set; }
17 | public int? download_count { get; set; }
18 | public DateTime? created_at { get; set; }
19 | public DateTime? updated_at { get; set; }
20 | public string browser_download_url { get; set; }
21 | }
22 | }
--------------------------------------------------------------------------------
/EspionSpotify.Updater/Models/GitHub/Release.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace EspionSpotify.Updater.Models.GitHub
4 | {
5 | [Serializable]
6 | internal class Release
7 | {
8 | public string url { get; set; }
9 | public string assets_url { get; set; }
10 | public string upload_url { get; set; }
11 | public string html_url { get; set; }
12 | public int id { get; set; }
13 | public string node_id { get; set; }
14 | public string tag_name { get; set; }
15 | public string target_commitish { get; set; }
16 | public bool draft { get; set; }
17 | public User author { get; set; }
18 | public bool prerelease { get; set; }
19 | public DateTime? created_at { get; set; }
20 | public DateTime? published_at { get; set; }
21 | public Asset[] assets { get; set; }
22 | public string tarball_url { get; set; }
23 | public string zipball_url { get; set; }
24 | public string body { get; set; }
25 | }
26 | }
--------------------------------------------------------------------------------
/EspionSpotify.Updater/Models/GitHub/User.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace EspionSpotify.Updater.Models.GitHub
4 | {
5 | [Serializable]
6 | internal class User
7 | {
8 | public string login { get; set; }
9 | public int id { get; set; }
10 | public string node_id { get; set; }
11 | public string avatar_url { get; set; }
12 | public string gravatar_id { get; set; }
13 | public string url { get; set; }
14 | public string html_url { get; set; }
15 | public string followers_url { get; set; }
16 | public string following_url { get; set; }
17 | public string gists_url { get; set; }
18 | public string starred_url { get; set; }
19 | public string subscriptions_url { get; set; }
20 | public string organizations_url { get; set; }
21 | public string repos_url { get; set; }
22 | public string events_url { get; set; }
23 | public string received_events_url { get; set; }
24 | public string type { get; set; }
25 | public bool site_admin { get; set; }
26 | }
27 | }
--------------------------------------------------------------------------------
/EspionSpotify.Updater/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 |
3 | namespace EspionSpotify.Updater
4 | {
5 | public class Program
6 | {
7 | internal static void Main()
8 | {
9 | var t = new Thread(Run);
10 | t.SetApartmentState(ApartmentState.STA);
11 | t.IsBackground = true;
12 | t.Start();
13 | t.Join();
14 | }
15 |
16 | internal static void Run()
17 | {
18 | Updater.ProcessUpdateAsync().GetAwaiter().GetResult();
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/EspionSpotify.Updater/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // Allgemeine Informationen über eine Assembly werden über die folgenden
5 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
6 | // die einer Assembly zugeordnet sind.
7 | [assembly: AssemblyTitle("EspionSpotify.Updater")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("EspionSpotify.Updater")]
12 | [assembly: AssemblyCopyright("Copyright © 2021")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
17 | // für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
18 | // COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
19 | [assembly: ComVisible(false)]
20 |
21 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
22 | [assembly: Guid("f20370c5-7613-452e-8fcd-06f7f5703c35")]
23 |
24 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
25 | //
26 | // Hauptversion
27 | // Nebenversion
28 | // Buildnummer
29 | // Revision
30 | //
31 | // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
32 | // indem Sie "*" wie unten gezeigt eingeben:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/EspionSpotify.Updater/Updater.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using EspionSpotify.Updater.Models.GitHub;
7 | using EspionSpotify.Updater.Utilities;
8 | using Ionic.Zip;
9 |
10 | namespace EspionSpotify.Updater
11 | {
12 | internal static class Updater
13 | {
14 | private const string UPDATER_DIRECTORY = "Updater";
15 | private const string UPDATER_TMP_DIRECTORY = "tmp_updater";
16 | private const string APP = "spytify.exe";
17 | internal static readonly string ProjectDirectory = AppDomain.CurrentDomain.BaseDirectory + @"..\";
18 | private static readonly string UpdaterTempFullPath = $"{ProjectDirectory}{UPDATER_TMP_DIRECTORY}";
19 | internal static readonly string AppFullPath = $"{ProjectDirectory}{APP}";
20 |
21 | internal static async Task ProcessUpdateAsync()
22 | {
23 | DeleteTempFiles();
24 |
25 | try
26 | {
27 | var releases = await GitHub.GetReleases();
28 |
29 | if (!releases.Any()) return;
30 |
31 | foreach (var release in releases)
32 | {
33 | Console.WriteLine("Updating to release {0}...", release.tag_name);
34 | var fileName = await DownloadUpdateAsync(release);
35 | if (!string.IsNullOrEmpty(fileName))
36 | {
37 | ExtractDownloadedAsset(fileName);
38 | File.Delete(fileName);
39 | }
40 | }
41 |
42 | Console.WriteLine("Successfully updated!");
43 | Process.Start(new ProcessStartInfo(AppFullPath));
44 | }
45 | catch
46 | {
47 | Process.Start(new ProcessStartInfo(GitHub.LATEST_RELEASE_LINK));
48 | LeaveConsole();
49 | }
50 | finally
51 | {
52 | Environment.Exit(0);
53 | }
54 | }
55 |
56 | private static async Task DownloadUpdateAsync(Release release)
57 | {
58 | try
59 | {
60 | var asset = GitHub.GetZipAssetFromRelease(release);
61 | return await Web.DownloadFileAsync(asset.browser_download_url, release.tag_name);
62 | }
63 | catch (ReleaseAssetNotFoundException ex)
64 | {
65 | Console.WriteLine(
66 | "Something went wrong during the download. Make sure it was not blocked by your Antivirus Software.");
67 | Console.WriteLine("Error Message: {0}", ex.Message);
68 | throw;
69 | }
70 | catch (Exception ex)
71 | {
72 | Console.WriteLine("Something went wrong during the download.");
73 | Console.WriteLine("Error Message: {0}", ex.Message);
74 | throw;
75 | }
76 | }
77 |
78 | private static void ExtractDownloadedAsset(string fileName)
79 | {
80 | ZipFile zip = null;
81 | try
82 | {
83 | zip = ZipFile.Read(fileName);
84 | Console.WriteLine("Extracting...");
85 |
86 | foreach (var entry in zip.ToList())
87 | entry.Extract(
88 | (Path.GetDirectoryName(entry.FileName) ?? "").Equals(UPDATER_DIRECTORY)
89 | ? UpdaterTempFullPath
90 | : ProjectDirectory, ExtractExistingFileAction.OverwriteSilently);
91 | }
92 | catch (UnauthorizedAccessException ex)
93 | {
94 | Console.WriteLine(
95 | "An error occurred while extracting. Make sure Spytify is not running or Antivirus Software is interfering.");
96 | Console.WriteLine("You can extract the file manually at: {0}", fileName);
97 | Console.WriteLine("Error Message: {0}", ex.Message);
98 | throw;
99 | }
100 | catch (Exception ex)
101 | {
102 | Console.WriteLine("An error occurred while extracting");
103 | Console.WriteLine("Error Message: {0}", ex.Message);
104 | throw;
105 | }
106 | finally
107 | {
108 | DeleteTempFiles();
109 | zip?.Dispose();
110 | }
111 | }
112 |
113 | internal static void LeaveConsole()
114 | {
115 | Console.WriteLine("Press any key to exit");
116 | Console.ReadKey();
117 | }
118 |
119 | private static void DeleteTempFiles()
120 | {
121 | foreach (var filename in Directory
122 | .EnumerateFiles(ProjectDirectory, "*.*", SearchOption.AllDirectories)
123 | .Where(s => new[] {".tmp", ".pending-overwrite"}.Any(ext => s.ToLower().EndsWith(ext))))
124 | try
125 | {
126 | File.Delete(filename);
127 | }
128 | catch
129 | {
130 | // ignored
131 | }
132 | }
133 | }
134 | }
--------------------------------------------------------------------------------
/EspionSpotify.Updater/Utilities/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Text.RegularExpressions;
4 |
5 | namespace EspionSpotify.Updater.Utilities
6 | {
7 | internal class AssemblyInfo
8 | {
9 | internal static bool IsNewerVersionThanCurrent(string name)
10 | {
11 | var m = Regex.Match(name, @"^(\d+\.)?(\d+\.)?(\*|\d+\.)?(\*|\d+)$");
12 | var version = m.Groups[0];
13 |
14 | if (version.Success)
15 | {
16 | var availableVersion = new Version(version.Value);
17 | Version currentVersion;
18 | try
19 | {
20 | currentVersion = new Version(FileVersionInfo.GetVersionInfo(Updater.AppFullPath).FileVersion);
21 | }
22 | catch
23 | {
24 | return true;
25 | }
26 |
27 | return availableVersion > currentVersion;
28 | }
29 |
30 | return false;
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/EspionSpotify.Updater/Utilities/CustomExceptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace EspionSpotify.Updater.Utilities
4 | {
5 | internal class ReleaseAssetNotFoundException : ApplicationException
6 | {
7 | }
8 | }
--------------------------------------------------------------------------------
/EspionSpotify.Updater/Utilities/Extensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace EspionSpotify.Updater.Utilities
4 | {
5 | internal static class LongExtensions
6 | {
7 | private const int BYTES_IN_MEGABYTE = 1_000_000;
8 |
9 | internal static string ToMo(this long bytes)
10 | {
11 | return Math.Round(bytes / (double) BYTES_IN_MEGABYTE, 2).ToString("0.00");
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/EspionSpotify.Updater/Utilities/GitHub.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Text.RegularExpressions;
4 | using System.Threading.Tasks;
5 | using EspionSpotify.Updater.Models.GitHub;
6 | using Newtonsoft.Json;
7 |
8 | namespace EspionSpotify.Updater.Utilities
9 | {
10 | internal class GitHub
11 | {
12 | internal const string API_LATEST_RELEASES_LINK = "https://api.github.com/repos/jwallet/spy-spotify/releases";
13 | internal const string LATEST_RELEASE_LINK = "https://github.com/jwallet/spy-spotify/releases/latest";
14 |
15 | internal static async Task GetReleases()
16 | {
17 | Console.WriteLine("Getting missing releases...");
18 |
19 | var content = await Web.SendWebRequestAndGetContentAsync(API_LATEST_RELEASES_LINK);
20 | var releases = JsonConvert.DeserializeObject(content);
21 |
22 | if (releases == null)
23 | {
24 | Console.WriteLine("Releases were not found.");
25 | return null;
26 | }
27 |
28 | var relatedReleases = releases.Reverse().Where(r => AssemblyInfo.IsNewerVersionThanCurrent(r.tag_name))
29 | .ToArray();
30 |
31 | if (!relatedReleases.Any())
32 | {
33 | Console.WriteLine("You are already using the latest version.");
34 | Updater.LeaveConsole();
35 | }
36 |
37 | return relatedReleases;
38 | }
39 |
40 | internal static Asset GetZipAssetFromRelease(Release release)
41 | {
42 | var asset = release.assets
43 | .FirstOrDefault(a => Regex.IsMatch(a.name, @"^Spytify(-|\.)(v?)(\.)?\d+(\.\d+)?(\.\d+)?.zip$"));
44 |
45 | if (asset == null)
46 | {
47 | Console.WriteLine("This Release did not have any suitable asset to download. Try again later.");
48 | throw new ReleaseAssetNotFoundException();
49 | }
50 |
51 | Console.WriteLine("Release asset found: {0}", asset.name);
52 |
53 | return asset;
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/EspionSpotify.Updater/Utilities/Web.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.IO;
4 | using System.Net;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace EspionSpotify.Updater.Utilities
9 | {
10 | internal class Web
11 | {
12 | internal const string USER_AGENT =
13 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36";
14 |
15 | internal static async Task DownloadFileAsync(string url, string tag)
16 | {
17 | var uri = new Uri(url);
18 | Console.WriteLine("Downloading update {0}...", tag);
19 |
20 | var fileName = $"{Updater.ProjectDirectory}update-{tag}.zip";
21 |
22 | using (var wc = new WebClient())
23 | {
24 | wc.DownloadProgressChanged += WebClient_DownloadProgressChanged;
25 | wc.DownloadFileCompleted += WebClient_DownloadFileCompleted;
26 |
27 | await wc.DownloadFileTaskAsync(uri, fileName);
28 | }
29 |
30 | return fileName;
31 | }
32 |
33 | internal static void WebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
34 | {
35 | lock (e.UserState)
36 | {
37 | Console.SetCursorPosition(0, Console.CursorTop - 1);
38 | Console.WriteLine("{0} % completed ({1} of {2} Mo.)",
39 | e.ProgressPercentage,
40 | e.BytesReceived.ToMo(),
41 | e.TotalBytesToReceive.ToMo());
42 | }
43 | }
44 |
45 | internal static void WebClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
46 | {
47 | if (e.Cancelled) Console.WriteLine("File download cancelled.");
48 |
49 | if (e.Error != null) Console.WriteLine(e.Error.ToString());
50 | }
51 |
52 | internal static async Task SendWebRequestAndGetContentAsync(string address)
53 | {
54 | var result = string.Empty;
55 | var content = new MemoryStream();
56 | var myHttpWebRequest = SetHttpWebRequest(address);
57 | myHttpWebRequest.Method = WebRequestMethods.Http.Get;
58 |
59 | try
60 | {
61 | using (var myHttpWebResponse = (HttpWebResponse) await myHttpWebRequest.GetResponseAsync())
62 | {
63 | if (myHttpWebResponse.StatusCode == HttpStatusCode.OK)
64 | using (var reader = myHttpWebResponse.GetResponseStream())
65 | {
66 | await reader.CopyToAsync(content);
67 | result = Encoding.UTF8.GetString(content.ToArray());
68 | }
69 | }
70 | }
71 | catch
72 | {
73 | // ignored
74 | }
75 | finally
76 | {
77 | content.Dispose();
78 | }
79 |
80 | return result;
81 | }
82 |
83 | private static HttpWebRequest SetHttpWebRequest(string address)
84 | {
85 | if (!Uri.TryCreate(address, UriKind.Absolute, out var uriGitHub)) return null;
86 |
87 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
88 | var request = (HttpWebRequest) WebRequest.Create(uriGitHub);
89 | request.Method = WebRequestMethods.Http.Get;
90 | request.UserAgent = "Spytify";
91 |
92 | return request;
93 | }
94 | }
95 | }
--------------------------------------------------------------------------------
/EspionSpotify.Updater/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/EspionSpotify.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio Version 16
3 | VisualStudioVersion = 16.0.29609.76
4 | MinimumVisualStudioVersion = 10.0.40219.1
5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EspionSpotify", "EspionSpotify\EspionSpotify.csproj", "{A02571B8-7CE5-4865-84F0-87613F895204}"
6 | EndProject
7 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EspionSpotify.Tests", "EspionSpotify.Tests\EspionSpotify.Tests.csproj", "{9A936C14-6665-48A8-A79D-14347F50E215}"
8 | EndProject
9 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3CD407CC-3558-4008-B207-D69B7BF19AC4}"
10 | ProjectSection(SolutionItems) = preProject
11 | .editorconfig = .editorconfig
12 | EndProjectSection
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EspionSpotify.Updater", "EspionSpotify.Updater\EspionSpotify.Updater.csproj", "{F20370C5-7613-452E-8FCD-06F7F5703C35}"
15 | ProjectSection(ProjectDependencies) = postProject
16 | {A02571B8-7CE5-4865-84F0-87613F895204} = {A02571B8-7CE5-4865-84F0-87613F895204}
17 | EndProjectSection
18 | EndProject
19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EspionSpotify.FakeSpotify", "EspionSpotify.FakeSpotify\EspionSpotify.FakeSpotify.csproj", "{AC6E7B02-7941-40B2-88D0-C53B50073073}"
20 | EndProject
21 | Global
22 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
23 | Debug|Any CPU = Debug|Any CPU
24 | Release|Any CPU = Release|Any CPU
25 | EndGlobalSection
26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
27 | {A02571B8-7CE5-4865-84F0-87613F895204}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
28 | {A02571B8-7CE5-4865-84F0-87613F895204}.Debug|Any CPU.Build.0 = Debug|Any CPU
29 | {A02571B8-7CE5-4865-84F0-87613F895204}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {A02571B8-7CE5-4865-84F0-87613F895204}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {9A936C14-6665-48A8-A79D-14347F50E215}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
32 | {9A936C14-6665-48A8-A79D-14347F50E215}.Debug|Any CPU.Build.0 = Debug|Any CPU
33 | {9A936C14-6665-48A8-A79D-14347F50E215}.Release|Any CPU.ActiveCfg = Release|Any CPU
34 | {9A936C14-6665-48A8-A79D-14347F50E215}.Release|Any CPU.Build.0 = Release|Any CPU
35 | {F20370C5-7613-452E-8FCD-06F7F5703C35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36 | {F20370C5-7613-452E-8FCD-06F7F5703C35}.Debug|Any CPU.Build.0 = Debug|Any CPU
37 | {F20370C5-7613-452E-8FCD-06F7F5703C35}.Release|Any CPU.ActiveCfg = Release|Any CPU
38 | {F20370C5-7613-452E-8FCD-06F7F5703C35}.Release|Any CPU.Build.0 = Release|Any CPU
39 | {AC6E7B02-7941-40B2-88D0-C53B50073073}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40 | {AC6E7B02-7941-40B2-88D0-C53B50073073}.Debug|Any CPU.Build.0 = Debug|Any CPU
41 | {AC6E7B02-7941-40B2-88D0-C53B50073073}.Release|Any CPU.ActiveCfg = Release|Any CPU
42 | {AC6E7B02-7941-40B2-88D0-C53B50073073}.Release|Any CPU.Build.0 = Release|Any CPU
43 | EndGlobalSection
44 | GlobalSection(SolutionProperties) = preSolution
45 | HideSolutionNode = FALSE
46 | EndGlobalSection
47 | GlobalSection(ExtensibilityGlobals) = postSolution
48 | SolutionGuid = {9853ED7B-8ABA-4853-8C7F-35E528FD136D}
49 | EndGlobalSection
50 | EndGlobal
51 |
--------------------------------------------------------------------------------
/EspionSpotify/API/ExternalAPI.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.API
2 | {
3 | public static class ExternalAPI
4 | {
5 | public static IExternalAPI Instance { get; set; } = new NoneAPI();
6 | }
7 | }
--------------------------------------------------------------------------------
/EspionSpotify/API/IExternalAPI.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using EspionSpotify.Enums;
3 | using EspionSpotify.Models;
4 |
5 | namespace EspionSpotify.API
6 | {
7 | public interface IExternalAPI
8 | {
9 | ExternalAPIType GetTypeAPI { get; }
10 | bool IsAuthenticated { get; }
11 | Task Authenticate();
12 | void Reset();
13 |
14 | Task UpdateTrack(Track track);
15 | }
16 | }
--------------------------------------------------------------------------------
/EspionSpotify/API/ILastFMAPI.cs:
--------------------------------------------------------------------------------
1 | using EspionSpotify.Models;
2 |
3 | namespace EspionSpotify.API
4 | {
5 | public interface ILastFMAPI
6 | {
7 | string[] ApiKeys { get; }
8 |
9 | void MapLastFMTrackToTrack(Track track, LastFMTrack trackExtra);
10 | }
11 | }
--------------------------------------------------------------------------------
/EspionSpotify/API/IMapperID3.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using EspionSpotify.Models;
3 |
4 | namespace EspionSpotify.API
5 | {
6 | public interface IMapperID3
7 | {
8 | string CurrentFile { get; set; }
9 | int? Count { get; set; }
10 | bool OrderNumberInMediaTagEnabled { get; set; }
11 | Track Track { get; set; }
12 |
13 | Task SaveMediaTags();
14 | }
15 | }
--------------------------------------------------------------------------------
/EspionSpotify/API/ISpotifyAPI.cs:
--------------------------------------------------------------------------------
1 | using EspionSpotify.Models;
2 | using SpotifyAPI.Web.Models;
3 |
4 | namespace EspionSpotify.API
5 | {
6 | public interface ISpotifyAPI
7 | {
8 | void MapSpotifyTrackToTrack(Track track, FullTrack spotifyTrack);
9 |
10 | void MapSpotifyAlbumToTrack(Track track, FullAlbum spotifyAlbum);
11 | }
12 | }
--------------------------------------------------------------------------------
/EspionSpotify/API/NoneAPI.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using EspionSpotify.Enums;
3 | using EspionSpotify.Models;
4 |
5 | namespace EspionSpotify.API
6 | {
7 | public class NoneAPI: IExternalAPI
8 | {
9 | public ExternalAPIType GetTypeAPI => ExternalAPIType.None;
10 | public bool IsAuthenticated => true;
11 | public Task Authenticate()
12 | {
13 | return Task.CompletedTask;
14 | }
15 |
16 | public void Reset()
17 | {
18 | }
19 |
20 | public Task UpdateTrack(Track track)
21 | {
22 | return Task.FromResult(true);
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/EspionSpotify/Analytics.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Net.Http;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 | using PCLWebUtility;
8 |
9 | namespace EspionSpotify
10 | {
11 | #region analytics
12 |
13 | public class Analytics
14 | {
15 | private const string ANALYTICS_URL = "https://www.google-analytics.com/collect";
16 | private const string ANALYTICS_TID = "UA-125662919-1";
17 | private readonly string _cid;
18 |
19 | private readonly HttpClient _client = new HttpClient();
20 | private readonly string _cm;
21 | private readonly string _cs;
22 | private readonly string _sr;
23 | private readonly string _ua;
24 | private readonly string _ul;
25 |
26 | public Analytics(string clientId, string version)
27 | {
28 | var osArchitecture = Environment.Is64BitOperatingSystem ? "Win64; x64;" : "";
29 | var screenBoundaries = Screen.PrimaryScreen.Bounds;
30 | var osPlatform = $"Windows NT {Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor}";
31 |
32 | _cid = clientId;
33 | _cm = version;
34 | _cs = Environment.OSVersion.ToString();
35 | _ul = CultureInfo.CurrentCulture.Name;
36 | _ua = WebUtility.UrlEncode(
37 | $"Mozilla/5.0 ({osPlatform}; {osArchitecture}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36");
38 | _sr = $"{screenBoundaries.Width}x{screenBoundaries.Height}";
39 | }
40 |
41 | private DateTime LastRequest { get; set; }
42 | private string LastAction { get; set; } = string.Empty;
43 |
44 | public static string GenerateCid()
45 | {
46 | return Guid.NewGuid().ToString();
47 | }
48 |
49 | public async Task LogAction(string action)
50 | {
51 | if (LastAction.Equals(action) && DateTime.Now - LastRequest < TimeSpan.FromMinutes(5)) return false;
52 |
53 | var data = new Dictionary
54 | {
55 | {"v", "1"},
56 | {"tid", ANALYTICS_TID}, // App id
57 | {"t", "pageview"}, // Analytics type
58 | {"cid", _cid}, // Client id
59 | {"cm", _cm}, // Campaign medium, App version
60 | {"av", _cm}, // App version
61 | {"cn", Constants.SPYTIFY}, // Campaign name
62 | {"an", Constants.SPYTIFY}, // App name
63 | {"cs", WebUtility.UrlEncode(_cs)}, // Campaign source, OS Version
64 | {"ul", _ul}, // User Language
65 | {"sr", _sr}, // Screen resolution
66 | {"ua", _ua}, // User-Agent overwrite
67 | {"dh", "jwallet.github.io/spy-spotify"}, // Document host
68 | {"dl", $"/{action}"}, // Document link
69 | {"dt", action}, // Document title
70 | {"cd", action} // Screen name
71 | };
72 |
73 | var content = new FormUrlEncodedContent(data);
74 | var success = false;
75 |
76 | try
77 | {
78 | var resp = await _client.PostAsync(ANALYTICS_URL, content);
79 | success = resp.IsSuccessStatusCode;
80 | }
81 | catch
82 | {
83 | // ignored
84 | }
85 |
86 | LastAction = action;
87 | LastRequest = DateTime.Now;
88 |
89 | return success;
90 | }
91 | }
92 |
93 | #endregion analytics
94 | }
--------------------------------------------------------------------------------
/EspionSpotify/AudioSessions/AudioLoopback.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using NAudio.CoreAudioApi;
5 | using NAudio.Wave;
6 |
7 | namespace EspionSpotify.AudioSessions
8 | {
9 | public class AudioLoopback: IAudioLoopback, IDisposable
10 | {
11 | private readonly bool _canDo = false;
12 | private bool _isDisposed = false;
13 |
14 | private const int BUFFER_TOTAL_SIZE_MS = 10_000;
15 |
16 | private readonly BufferedWaveProvider _bufferedWaveProvider;
17 | private readonly WasapiLoopbackCapture _waveIn;
18 | private readonly WaveOut _waveOut;
19 |
20 | private CancellationTokenSource _cancellationTokenSource;
21 |
22 | public bool Running { get; set; }
23 |
24 | public AudioLoopback(MMDevice currentEndpointDevice, MMDevice defaultEndpointDevice)
25 | {
26 | _canDo = currentEndpointDevice.ID != defaultEndpointDevice.ID;
27 |
28 | _waveIn = new WasapiLoopbackCapture(currentEndpointDevice);
29 | _waveIn.DataAvailable += OnDataAvailable;
30 |
31 | _bufferedWaveProvider = new BufferedWaveProvider(_waveIn.WaveFormat)
32 | {
33 | DiscardOnBufferOverflow = true,
34 | BufferDuration = TimeSpan.FromMilliseconds(BUFFER_TOTAL_SIZE_MS)
35 | };
36 |
37 | _waveOut = new WaveOut();
38 | }
39 |
40 | public async Task Run(CancellationTokenSource cancellationTokenSource)
41 | {
42 | if (!_canDo) return;
43 |
44 | _cancellationTokenSource = cancellationTokenSource;
45 | Running = true;
46 |
47 | _waveIn.StartRecording();
48 | _waveOut.Init(_bufferedWaveProvider);
49 |
50 | _waveOut.Play();
51 |
52 | while (Running)
53 | {
54 | if (_cancellationTokenSource.IsCancellationRequested) return;
55 | await Task.Delay(100);
56 | }
57 |
58 | _waveOut.Stop();
59 | _waveIn.StopRecording();
60 | }
61 |
62 | private void OnDataAvailable(object sender, WaveInEventArgs waveInEventArgs)
63 | {
64 | _bufferedWaveProvider.AddSamples(waveInEventArgs.Buffer,0, waveInEventArgs.BytesRecorded);
65 | }
66 |
67 | public void Dispose()
68 | {
69 | if (!_isDisposed)
70 | {
71 | _isDisposed = true;
72 | _waveIn.Dispose();
73 | _waveOut.Dispose();
74 | }
75 | }
76 | }
77 | }
--------------------------------------------------------------------------------
/EspionSpotify/AudioSessions/IAudioCircularBuffer.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.AudioSessions
2 | {
3 | public interface IAudioCircularBuffer
4 | {
5 | int MaxLength { get; }
6 | int Count { get; }
7 | int ReadPosition { get; }
8 | int WritePosition { get; }
9 |
10 | int Write(byte[] data, int offset, int count);
11 | int Read(out byte[] data, int offset, int count);
12 | int Peek(out byte[] data, int offset, int count);
13 | void Advance(int count);
14 | void Reset();
15 | }
16 | }
--------------------------------------------------------------------------------
/EspionSpotify/AudioSessions/IAudioLoopback.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using System.Threading.Tasks;
3 |
4 | namespace EspionSpotify.AudioSessions
5 | {
6 | public interface IAudioLoopback
7 | {
8 | bool Running { get; set; }
9 |
10 | Task Run(CancellationTokenSource cancellationTokenSource);
11 | void Dispose();
12 | }
13 | }
--------------------------------------------------------------------------------
/EspionSpotify/AudioSessions/IAudioThrottler.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using System.Threading.Tasks;
3 | using EspionSpotify.Enums;
4 | using EspionSpotify.Models;
5 | using NAudio.Wave;
6 |
7 | namespace EspionSpotify.AudioSessions
8 | {
9 | public interface IAudioThrottler
10 | {
11 | bool Running { get; set; }
12 | WaveFormat WaveFormat { get; }
13 | bool BufferIsHalfFull { get; }
14 | bool BufferIsReady { get; }
15 |
16 | Task Run(CancellationTokenSource cancellationTokenSource);
17 | Task Read(SilenceAnalyzer silence = SilenceAnalyzer.None);
18 | Task WaitBufferReady();
19 | void Dispose();
20 | }
21 | }
--------------------------------------------------------------------------------
/EspionSpotify/AudioSessions/IMainAudioSession.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading.Tasks;
3 | using NAudio.CoreAudioApi;
4 |
5 | namespace EspionSpotify.AudioSessions
6 | {
7 | public interface IMainAudioSession
8 | {
9 | MMDeviceEnumerator AudioMMDevices { get; }
10 | AudioMMDevicesManager AudioMMDevicesManager { get; }
11 |
12 | void SetSpotifyProcesses();
13 | void RouteSpotifyAudioSessions(bool canRedirectPlayback);
14 | void UnrouteSpotifyAudioSessions();
15 | ICollection SpotifyAudioSessionControls { get; }
16 |
17 | int AudioDeviceVolume { get; }
18 | bool IsAudioEndPointDeviceIndexAvailable { get; }
19 | void ClearSpotifyAudioSessionControls();
20 |
21 | void SetAudioDeviceVolume(int volume);
22 |
23 | Task SleepWhileTheSongEnds();
24 | Task IsSpotifyCurrentlyPlaying();
25 | void SetSpotifyToMute(bool mute);
26 | Task WaitSpotifyAudioSessionToStart(bool running);
27 | void SetSpotifyVolumeToHighAndOthersToMute(bool mute = false);
28 |
29 | void Dispose();
30 | }
31 | }
--------------------------------------------------------------------------------
/EspionSpotify/Constants.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify
2 | {
3 | public static class Constants
4 | {
5 | public const string SPYTIFY = "Spytify";
6 |
7 | public const string SPOTIFY = "Spotify";
8 | public const string SPOTIFYFREE = "Spotify Free";
9 | public const string SPOTIFYPREMIUM = "Spotify Premium";
10 | public const string ADVERTISEMENT = "Advertisement";
11 |
12 | public const string UNTITLED_ALBUM = "Untitled";
13 | }
14 | }
--------------------------------------------------------------------------------
/EspionSpotify/Controls/MetroComboBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace EspionSpotify.Controls
5 | {
6 | public class MetroComboBox : MetroFramework.Controls.MetroComboBox
7 | {
8 | protected override void OnMouseWheel(MouseEventArgs e)
9 | {
10 | ((HandledMouseEventArgs) e).Handled = true;
11 | }
12 |
13 | protected override void OnSelectedIndexChanged(EventArgs e)
14 | {
15 | base.OnSelectedIndexChanged(e);
16 | base.OnLostFocus(e);
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/EspionSpotify/Controls/MetroTrackBar.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 | namespace EspionSpotify.Controls
4 | {
5 | public class MetroTrackBar : MetroFramework.Controls.MetroTrackBar
6 | {
7 | protected override void OnMouseWheel(MouseEventArgs e)
8 | {
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/AudioVirtualCableDriver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 |
7 | namespace EspionSpotify.Drivers
8 | {
9 | public static class AudioVirtualCableDriver
10 | {
11 | private const string DRIVER_NAME = "VB-Audio Virtual Cable";
12 |
13 | private static string Path =>
14 | $@"{Environment.CurrentDirectory}\Drivers\VBCABLE_Setup{(Environment.Is64BitOperatingSystem ? "_x64" : "")}.exe";
15 |
16 | public static bool IsFound => File.Exists(Path);
17 |
18 | public static bool ExistsInAudioEndPointDevices(IDictionary audioEndPointDeviceNames)
19 | {
20 | return audioEndPointDeviceNames.Any(x => x.Value.Contains(DRIVER_NAME));
21 | }
22 |
23 | public static bool SetupDriver()
24 | {
25 | try
26 | {
27 | var psi = new ProcessStartInfo
28 | {
29 | CreateNoWindow = false,
30 | UseShellExecute = true,
31 | Verb = "runas",
32 | FileName = Path
33 | };
34 | var process = new Process
35 | {
36 | StartInfo = psi
37 | };
38 | process.Start();
39 | process.WaitForExit();
40 | }
41 | catch
42 | {
43 | return false;
44 | }
45 |
46 | return true;
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/VBCABLE_ControlPanel.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/VBCABLE_ControlPanel.exe
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/VBCABLE_Setup.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/VBCABLE_Setup.exe
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/VBCABLE_Setup_x64.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/VBCABLE_Setup_x64.exe
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/pin_in.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/pin_in.ico
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/pin_out.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/pin_out.ico
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/readme.txt
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbMmeCable64_vista.inf:
--------------------------------------------------------------------------------
1 | [Version]
2 | Signature="$CHICAGO$"
3 | Class=MEDIA
4 | Provider=%Provider%
5 | ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318}
6 | DriverVer=09/02/2014,1.0.3.5
7 | CatalogFile=vbaudio_cable64_vista.cat
8 |
9 |
10 | [SourceDisksNames]
11 | 222=%DiskName%,"",222
12 |
13 | [SourceDisksFiles.x86]
14 | vbaudio_cable64_vista.sys=222
15 |
16 |
17 | [Manufacturer]
18 | %Provider%=VBCable,NTamd64, NTIA64
19 |
20 |
21 | [VBCable]
22 | %DeviceName%=VBCableInst,%HardwareId%
23 |
24 |
25 | [VBCable.NTamd64]
26 | %DeviceName%=VBCableInst,%HardwareId%
27 |
28 |
29 | [VBCable.NTIA64]
30 | %DeviceName%=VBCableInst,%HardwareId%
31 |
32 | [DestinationDirs]
33 | VBCableInst.CopyList=10,system32\drivers
34 |
35 |
36 | ;======================================================
37 | ; VB_CABLE
38 | ;======================================================
39 | [VBCableInst]
40 | AlsoInstall=ks.registration(ks.inf),wdmaudio.registration(wdmaudio.inf)
41 | CopyFiles=VBCableInst.CopyList
42 | AddReg=VBCableInst.AddReg
43 |
44 | [VBCableInst.CopyList]
45 | vbaudio_cable64_vista.sys
46 |
47 | [VBCableInst.Interfaces]
48 | AddInterface=%KSCATEGORY_AUDIO%,"Topo",VBCableInst.I.Topo
49 | AddInterface=%KSCATEGORY_AUDIO%,"Wave",VBCableInst.I.Wave
50 | AddInterface=%KSCATEGORY_CAPTURE%,"Wave",VBCableInst.I.Wave
51 | AddInterface=%KSCATEGORY_RENDER%,"Wave",VBCableInst.I.Wave
52 |
53 | [VBCableInst.AddReg]
54 | HKR,,AssociatedFilters,,"wdmaud,redbook"
55 | ;HKR,,SetupPreferredAudioDevices,3,01,00,00,00
56 | HKR,,Driver,,%DriverFile%
57 | HKR,,NTMPDriver,,"%DriverFile%,sbemul.sys"
58 |
59 | HKR,Drivers,SubClasses,,"wave,mixer"
60 |
61 | HKR,Drivers\wave\wdmaud.drv,Driver,,wdmaud.drv
62 | HKR,Drivers\mixer\wdmaud.drv,Driver,,wdmaud.drv
63 |
64 | HKR,Drivers\wave\wdmaud.drv,Description,,%DeviceName%
65 | HKR,Drivers\mixer\wdmaud.drv,Description,,%DeviceName%
66 |
67 | HKLM,%MediaCategories%\%VBCABLE.INPUTGUID%,Name,,%VBCABLE.INPUTNAME%
68 | HKLM,%MediaCategories%\%VBCABLE.INPUTGUID%,Display,1,00,00,00,00
69 |
70 | HKLM,%MediaCategories%\%VBCABLE.OUTPUTGUID%,Name,,%VBCABLE.OUTPUTNAME%
71 | HKLM,%MediaCategories%\%VBCABLE.OUTPUTGUID%,Display,1,00,00,00,00
72 |
73 | ;======================================================
74 | ; COMMON
75 | ;======================================================
76 | [VBCableInst.I.Topo]
77 | AddReg=VBCableInst.I.Topo.AddReg
78 |
79 | [VBCableInst.I.Topo.AddReg]
80 | HKR,,CLSID,,%CLSID_Proxy%
81 | HKR,,FriendlyName,,%VBCABLE.NAMELine1%
82 |
83 | [VBCableInst.I.Wave]
84 | AddReg=VBCableInst.I.Wave.AddReg
85 |
86 | [VBCableInst.I.Wave.AddReg]
87 | HKR,,CLSID,,%CLSID_Proxy%
88 | HKR,,FriendlyName,,%VBCABLE.NAMELine1%
89 |
90 |
91 |
92 | ;======================================================
93 | ; VB_CABLE NT
94 | ;======================================================
95 | [VBCableInst.NT]
96 | Include=ks.inf,wdmaudio.inf
97 | Needs=KS.Registration, WDMAUDIO.Registration
98 | CopyFiles=VBCableInst.CopyList
99 | AddReg=VBCableInst.AddReg
100 |
101 |
102 |
103 | [VBCableInst.NT.Interfaces]
104 | AddInterface=%KSCATEGORY_AUDIO%,"Topo",VBCableInst.I.Topo
105 | AddInterface=%KSCATEGORY_AUDIO%,"Wave",VBCableInst.I.Wave
106 | AddInterface=%KSCATEGORY_CAPTURE%,"Wave",VBCableInst.I.Wave
107 | AddInterface=%KSCATEGORY_RENDER%,"Wave",VBCableInst.I.Wave
108 |
109 |
110 |
111 | [VBCableInst.NT.Services]
112 | AddService=%ServiceName%,0x2,SrvInstSection
113 |
114 | [SrvInstSection]
115 | DisplayName=%DeviceName% (WDM)
116 | ServiceType=%SERVICE_KERNEL_DRIVER%
117 | StartType=%SERVICE_DEMAND_START%
118 | ErrorControl=%SERVICE_ERROR_NORMAL%
119 | ServiceBinary=%12%\%DriverFile%
120 |
121 |
122 | ;======================================================
123 | ;COMMON STRING
124 | ;======================================================
125 | [Strings]
126 |
127 | Provider="VB-Audio Software"
128 | DeviceName="VB-Audio Virtual Cable"
129 | HardwareId="VBAudioVACWDM"
130 | ServiceName="VBAudioVACMME"
131 | DriverFile="vbaudio_cable64_vista.sys"
132 | DiskName="vbcable Driver Disk"
133 |
134 | KSCATEGORY_AUDIO="{6994AD04-93EF-11D0-A3CC-00A0C9223196}"
135 | KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
136 | KSCATEGORY_RENDER="{65E8773E-8F56-11D0-A3B9-00A0C9223196}"
137 |
138 | CLSID_Proxy="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
139 |
140 | SERVICE_KERNEL_DRIVER=1
141 | SERVICE_DEMAND_START=3
142 | SERVICE_ERROR_NORMAL=1
143 |
144 | ;; FriendlyName
145 | VBCABLE.INPUTGUID ="{23208800-570C-4682-BB53-7F12CE497910}"
146 | VBCABLE.OUTPUTGUID ="{23208900-570C-4682-BB53-7F12CE497910}"
147 |
148 | VBCABLE.NAMELine1 ="VB-Audio Point"
149 | VBCABLE.INPUTNAME ="CABLE Output"
150 | VBCABLE.OUTPUTNAME ="CABLE Input"
151 |
152 | MediaCategories="SYSTEM\CurrentControlSet\Control\MediaCategories"
153 |
154 |
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbMmeCable64_win7.inf:
--------------------------------------------------------------------------------
1 | [Version]
2 | Signature="$CHICAGO$"
3 | Class=MEDIA
4 | Provider=%Provider%
5 | ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318}
6 | DriverVer=09/02/2014,1.0.3.5
7 | CatalogFile=vbaudio_cable64_win7.cat
8 |
9 |
10 | [SourceDisksNames]
11 | 222=%DiskName%,"",222
12 |
13 | [SourceDisksFiles.x86]
14 | vbaudio_cable64_win7.sys=222
15 |
16 |
17 | [Manufacturer]
18 | %Provider%=VBCable,NTamd64, NTIA64
19 |
20 |
21 | [VBCable]
22 | %DeviceName%=VBCableInst,%HardwareId%
23 |
24 |
25 | [VBCable.NTamd64]
26 | %DeviceName%=VBCableInst,%HardwareId%
27 |
28 |
29 | [VBCable.NTIA64]
30 | %DeviceName%=VBCableInst,%HardwareId%
31 |
32 | [DestinationDirs]
33 | VBCableInst.CopyList=10,system32\drivers
34 |
35 |
36 | ;======================================================
37 | ; VB_CABLE
38 | ;======================================================
39 | [VBCableInst]
40 | AlsoInstall=ks.registration(ks.inf),wdmaudio.registration(wdmaudio.inf)
41 | CopyFiles=VBCableInst.CopyList
42 | AddReg=VBCableInst.AddReg
43 |
44 | [VBCableInst.CopyList]
45 | vbaudio_cable64_win7.sys
46 |
47 | [VBCableInst.Interfaces]
48 | AddInterface=%KSCATEGORY_AUDIO%,"Topo",VBCableInst.I.Topo
49 | AddInterface=%KSCATEGORY_AUDIO%,"Wave",VBCableInst.I.Wave
50 | AddInterface=%KSCATEGORY_CAPTURE%,"Wave",VBCableInst.I.Wave
51 | AddInterface=%KSCATEGORY_RENDER%,"Wave",VBCableInst.I.Wave
52 |
53 | [VBCableInst.AddReg]
54 | HKR,,AssociatedFilters,,"wdmaud,redbook"
55 | ;HKR,,SetupPreferredAudioDevices,3,01,00,00,00
56 | HKR,,Driver,,%DriverFile%
57 | HKR,,NTMPDriver,,"%DriverFile%,sbemul.sys"
58 |
59 | HKR,Drivers,SubClasses,,"wave,mixer"
60 |
61 | HKR,Drivers\wave\wdmaud.drv,Driver,,wdmaud.drv
62 | HKR,Drivers\mixer\wdmaud.drv,Driver,,wdmaud.drv
63 |
64 | HKR,Drivers\wave\wdmaud.drv,Description,,%DeviceName%
65 | HKR,Drivers\mixer\wdmaud.drv,Description,,%DeviceName%
66 |
67 | HKLM,%MediaCategories%\%VBCABLE.INPUTGUID%,Name,,%VBCABLE.INPUTNAME%
68 | HKLM,%MediaCategories%\%VBCABLE.INPUTGUID%,Display,1,00,00,00,00
69 |
70 | HKLM,%MediaCategories%\%VBCABLE.OUTPUTGUID%,Name,,%VBCABLE.OUTPUTNAME%
71 | HKLM,%MediaCategories%\%VBCABLE.OUTPUTGUID%,Display,1,00,00,00,00
72 |
73 | ;======================================================
74 | ; COMMON
75 | ;======================================================
76 | [VBCableInst.I.Topo]
77 | AddReg=VBCableInst.I.Topo.AddReg
78 |
79 | [VBCableInst.I.Topo.AddReg]
80 | HKR,,CLSID,,%CLSID_Proxy%
81 | HKR,,FriendlyName,,%VBCABLE.NAMELine1%
82 |
83 | [VBCableInst.I.Wave]
84 | AddReg=VBCableInst.I.Wave.AddReg
85 |
86 | [VBCableInst.I.Wave.AddReg]
87 | HKR,,CLSID,,%CLSID_Proxy%
88 | HKR,,FriendlyName,,%VBCABLE.NAMELine1%
89 |
90 |
91 |
92 | ;======================================================
93 | ; VB_CABLE NT
94 | ;======================================================
95 | [VBCableInst.NT]
96 | Include=ks.inf,wdmaudio.inf
97 | Needs=KS.Registration, WDMAUDIO.Registration
98 | CopyFiles=VBCableInst.CopyList
99 | AddReg=VBCableInst.AddReg
100 |
101 |
102 |
103 | [VBCableInst.NT.Interfaces]
104 | AddInterface=%KSCATEGORY_AUDIO%,"Topo",VBCableInst.I.Topo
105 | AddInterface=%KSCATEGORY_AUDIO%,"Wave",VBCableInst.I.Wave
106 | AddInterface=%KSCATEGORY_CAPTURE%,"Wave",VBCableInst.I.Wave
107 | AddInterface=%KSCATEGORY_RENDER%,"Wave",VBCableInst.I.Wave
108 |
109 |
110 |
111 | [VBCableInst.NT.Services]
112 | AddService=%ServiceName%,0x2,SrvInstSection
113 |
114 | [SrvInstSection]
115 | DisplayName=%DeviceName% (WDM)
116 | ServiceType=%SERVICE_KERNEL_DRIVER%
117 | StartType=%SERVICE_DEMAND_START%
118 | ErrorControl=%SERVICE_ERROR_NORMAL%
119 | ServiceBinary=%12%\%DriverFile%
120 |
121 |
122 | ;======================================================
123 | ;COMMON STRING
124 | ;======================================================
125 | [Strings]
126 |
127 | Provider="VB-Audio Software"
128 | DeviceName="VB-Audio Virtual Cable"
129 | HardwareId="VBAudioVACWDM"
130 | ServiceName="VBAudioVACMME"
131 | DriverFile="vbaudio_cable64_win7.sys"
132 | DiskName="vbcable Driver Disk"
133 |
134 | KSCATEGORY_AUDIO="{6994AD04-93EF-11D0-A3CC-00A0C9223196}"
135 | KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
136 | KSCATEGORY_RENDER="{65E8773E-8F56-11D0-A3B9-00A0C9223196}"
137 |
138 | CLSID_Proxy="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
139 |
140 | SERVICE_KERNEL_DRIVER=1
141 | SERVICE_DEMAND_START=3
142 | SERVICE_ERROR_NORMAL=1
143 |
144 | ;; FriendlyName
145 | VBCABLE.INPUTGUID ="{23208800-570C-4682-BB53-7F12CE497910}"
146 | VBCABLE.OUTPUTGUID ="{23208900-570C-4682-BB53-7F12CE497910}"
147 |
148 | VBCABLE.NAMELine1 ="VB-Audio Point"
149 | VBCABLE.INPUTNAME ="CABLE Output"
150 | VBCABLE.OUTPUTNAME ="CABLE Input"
151 |
152 | MediaCategories="SYSTEM\CurrentControlSet\Control\MediaCategories"
153 |
154 |
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbMmeCable_vista.inf:
--------------------------------------------------------------------------------
1 | [Version]
2 | Signature="$CHICAGO$"
3 | Class=MEDIA
4 | Provider=%Provider%
5 | ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318}
6 | DriverVer=09/02/2014,1.0.3.5
7 | CatalogFile=vbaudio_cable_vista.cat
8 |
9 |
10 | [SourceDisksNames]
11 | 222=%DiskName%,"",222
12 |
13 | [SourceDisksFiles.x86]
14 | vbaudio_cable_vista.sys=222
15 |
16 |
17 | [Manufacturer]
18 | %Provider%=VBCable,NTamd64, NTIA64
19 |
20 |
21 | [VBCable]
22 | %DeviceName%=VBCableInst,%HardwareId%
23 |
24 |
25 | [VBCable.NTamd64]
26 | %DeviceName%=VBCableInst,%HardwareId%
27 |
28 |
29 | [VBCable.NTIA64]
30 | %DeviceName%=VBCableInst,%HardwareId%
31 |
32 | [DestinationDirs]
33 | VBCableInst.CopyList=10,system32\drivers
34 |
35 |
36 | ;======================================================
37 | ; VB_CABLE
38 | ;======================================================
39 | [VBCableInst]
40 | AlsoInstall=ks.registration(ks.inf),wdmaudio.registration(wdmaudio.inf)
41 | CopyFiles=VBCableInst.CopyList
42 | AddReg=VBCableInst.AddReg
43 |
44 | [VBCableInst.CopyList]
45 | vbaudio_cable_vista.sys
46 |
47 | [VBCableInst.Interfaces]
48 | AddInterface=%KSCATEGORY_AUDIO%,"Topo",VBCableInst.I.Topo
49 | AddInterface=%KSCATEGORY_AUDIO%,"Wave",VBCableInst.I.Wave
50 | AddInterface=%KSCATEGORY_CAPTURE%,"Wave",VBCableInst.I.Wave
51 | AddInterface=%KSCATEGORY_RENDER%,"Wave",VBCableInst.I.Wave
52 |
53 | [VBCableInst.AddReg]
54 | HKR,,AssociatedFilters,,"wdmaud,redbook"
55 | ;HKR,,SetupPreferredAudioDevices,3,01,00,00,00
56 | HKR,,Driver,,%DriverFile%
57 | HKR,,NTMPDriver,,"%DriverFile%,sbemul.sys"
58 |
59 | HKR,Drivers,SubClasses,,"wave,mixer"
60 |
61 | HKR,Drivers\wave\wdmaud.drv,Driver,,wdmaud.drv
62 | HKR,Drivers\mixer\wdmaud.drv,Driver,,wdmaud.drv
63 |
64 | HKR,Drivers\wave\wdmaud.drv,Description,,%DeviceName%
65 | HKR,Drivers\mixer\wdmaud.drv,Description,,%DeviceName%
66 |
67 | HKLM,%MediaCategories%\%VBCABLE.INPUTGUID%,Name,,%VBCABLE.INPUTNAME%
68 | HKLM,%MediaCategories%\%VBCABLE.INPUTGUID%,Display,1,00,00,00,00
69 |
70 | HKLM,%MediaCategories%\%VBCABLE.OUTPUTGUID%,Name,,%VBCABLE.OUTPUTNAME%
71 | HKLM,%MediaCategories%\%VBCABLE.OUTPUTGUID%,Display,1,00,00,00,00
72 |
73 | ;======================================================
74 | ; COMMON
75 | ;======================================================
76 | [VBCableInst.I.Topo]
77 | AddReg=VBCableInst.I.Topo.AddReg
78 |
79 | [VBCableInst.I.Topo.AddReg]
80 | HKR,,CLSID,,%CLSID_Proxy%
81 | HKR,,FriendlyName,,%VBCABLE.NAMELine1%
82 |
83 | [VBCableInst.I.Wave]
84 | AddReg=VBCableInst.I.Wave.AddReg
85 |
86 | [VBCableInst.I.Wave.AddReg]
87 | HKR,,CLSID,,%CLSID_Proxy%
88 | HKR,,FriendlyName,,%VBCABLE.NAMELine1%
89 |
90 |
91 |
92 | ;======================================================
93 | ; VB_CABLE NT
94 | ;======================================================
95 | [VBCableInst.NT]
96 | Include=ks.inf,wdmaudio.inf
97 | Needs=KS.Registration, WDMAUDIO.Registration
98 | CopyFiles=VBCableInst.CopyList
99 | AddReg=VBCableInst.AddReg
100 |
101 |
102 |
103 | [VBCableInst.NT.Interfaces]
104 | AddInterface=%KSCATEGORY_AUDIO%,"Topo",VBCableInst.I.Topo
105 | AddInterface=%KSCATEGORY_AUDIO%,"Wave",VBCableInst.I.Wave
106 | AddInterface=%KSCATEGORY_CAPTURE%,"Wave",VBCableInst.I.Wave
107 | AddInterface=%KSCATEGORY_RENDER%,"Wave",VBCableInst.I.Wave
108 |
109 |
110 |
111 | [VBCableInst.NT.Services]
112 | AddService=%ServiceName%,0x2,SrvInstSection
113 |
114 | [SrvInstSection]
115 | DisplayName=%DeviceName% (WDM)
116 | ServiceType=%SERVICE_KERNEL_DRIVER%
117 | StartType=%SERVICE_DEMAND_START%
118 | ErrorControl=%SERVICE_ERROR_NORMAL%
119 | ServiceBinary=%12%\%DriverFile%
120 |
121 |
122 | ;======================================================
123 | ;COMMON STRING
124 | ;======================================================
125 | [Strings]
126 |
127 | Provider="VB-Audio Software"
128 | DeviceName="VB-Audio Virtual Cable"
129 | HardwareId="VBAudioVACWDM"
130 | ServiceName="VBAudioVACMME"
131 | DriverFile="vbaudio_cable_vista.sys"
132 | DiskName="vbcable Driver Disk"
133 |
134 | KSCATEGORY_AUDIO="{6994AD04-93EF-11D0-A3CC-00A0C9223196}"
135 | KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
136 | KSCATEGORY_RENDER="{65E8773E-8F56-11D0-A3B9-00A0C9223196}"
137 |
138 | CLSID_Proxy="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
139 |
140 | SERVICE_KERNEL_DRIVER=1
141 | SERVICE_DEMAND_START=3
142 | SERVICE_ERROR_NORMAL=1
143 |
144 | ;; FriendlyName
145 | VBCABLE.INPUTGUID ="{23208800-570C-4682-BB53-7F12CE497910}"
146 | VBCABLE.OUTPUTGUID ="{23208900-570C-4682-BB53-7F12CE497910}"
147 |
148 | VBCABLE.NAMELine1 ="VB-Audio Point"
149 | VBCABLE.INPUTNAME ="CABLE Output"
150 | VBCABLE.OUTPUTNAME ="CABLE Input"
151 |
152 | MediaCategories="SYSTEM\CurrentControlSet\Control\MediaCategories"
153 |
154 |
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbMmeCable_win7.inf:
--------------------------------------------------------------------------------
1 | [Version]
2 | Signature="$CHICAGO$"
3 | Class=MEDIA
4 | Provider=%Provider%
5 | ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318}
6 | DriverVer=09/02/2014,1.0.3.5
7 | CatalogFile=vbaudio_cable_win7.cat
8 |
9 |
10 | [SourceDisksNames]
11 | 222=%DiskName%,"",222
12 |
13 | [SourceDisksFiles.x86]
14 | vbaudio_cable_win7.sys=222
15 |
16 |
17 | [Manufacturer]
18 | %Provider%=VBCable,NTamd64, NTIA64
19 |
20 |
21 | [VBCable]
22 | %DeviceName%=VBCableInst,%HardwareId%
23 |
24 |
25 | [VBCable.NTamd64]
26 | %DeviceName%=VBCableInst,%HardwareId%
27 |
28 |
29 | [VBCable.NTIA64]
30 | %DeviceName%=VBCableInst,%HardwareId%
31 |
32 | [DestinationDirs]
33 | VBCableInst.CopyList=10,system32\drivers
34 |
35 |
36 | ;======================================================
37 | ; VB_CABLE
38 | ;======================================================
39 | [VBCableInst]
40 | AlsoInstall=ks.registration(ks.inf),wdmaudio.registration(wdmaudio.inf)
41 | CopyFiles=VBCableInst.CopyList
42 | AddReg=VBCableInst.AddReg
43 |
44 | [VBCableInst.CopyList]
45 | vbaudio_cable_win7.sys
46 |
47 | [VBCableInst.Interfaces]
48 | AddInterface=%KSCATEGORY_AUDIO%,"Topo",VBCableInst.I.Topo
49 | AddInterface=%KSCATEGORY_AUDIO%,"Wave",VBCableInst.I.Wave
50 | AddInterface=%KSCATEGORY_CAPTURE%,"Wave",VBCableInst.I.Wave
51 | AddInterface=%KSCATEGORY_RENDER%,"Wave",VBCableInst.I.Wave
52 |
53 | [VBCableInst.AddReg]
54 | HKR,,AssociatedFilters,,"wdmaud,redbook"
55 | ;HKR,,SetupPreferredAudioDevices,3,01,00,00,00
56 | HKR,,Driver,,%DriverFile%
57 | HKR,,NTMPDriver,,"%DriverFile%,sbemul.sys"
58 |
59 | HKR,Drivers,SubClasses,,"wave,mixer"
60 |
61 | HKR,Drivers\wave\wdmaud.drv,Driver,,wdmaud.drv
62 | HKR,Drivers\mixer\wdmaud.drv,Driver,,wdmaud.drv
63 |
64 | HKR,Drivers\wave\wdmaud.drv,Description,,%DeviceName%
65 | HKR,Drivers\mixer\wdmaud.drv,Description,,%DeviceName%
66 |
67 | HKLM,%MediaCategories%\%VBCABLE.INPUTGUID%,Name,,%VBCABLE.INPUTNAME%
68 | HKLM,%MediaCategories%\%VBCABLE.INPUTGUID%,Display,1,00,00,00,00
69 |
70 | HKLM,%MediaCategories%\%VBCABLE.OUTPUTGUID%,Name,,%VBCABLE.OUTPUTNAME%
71 | HKLM,%MediaCategories%\%VBCABLE.OUTPUTGUID%,Display,1,00,00,00,00
72 |
73 | ;======================================================
74 | ; COMMON
75 | ;======================================================
76 | [VBCableInst.I.Topo]
77 | AddReg=VBCableInst.I.Topo.AddReg
78 |
79 | [VBCableInst.I.Topo.AddReg]
80 | HKR,,CLSID,,%CLSID_Proxy%
81 | HKR,,FriendlyName,,%VBCABLE.NAMELine1%
82 |
83 | [VBCableInst.I.Wave]
84 | AddReg=VBCableInst.I.Wave.AddReg
85 |
86 | [VBCableInst.I.Wave.AddReg]
87 | HKR,,CLSID,,%CLSID_Proxy%
88 | HKR,,FriendlyName,,%VBCABLE.NAMELine1%
89 |
90 |
91 |
92 | ;======================================================
93 | ; VB_CABLE NT
94 | ;======================================================
95 | [VBCableInst.NT]
96 | Include=ks.inf,wdmaudio.inf
97 | Needs=KS.Registration, WDMAUDIO.Registration
98 | CopyFiles=VBCableInst.CopyList
99 | AddReg=VBCableInst.AddReg
100 |
101 |
102 |
103 | [VBCableInst.NT.Interfaces]
104 | AddInterface=%KSCATEGORY_AUDIO%,"Topo",VBCableInst.I.Topo
105 | AddInterface=%KSCATEGORY_AUDIO%,"Wave",VBCableInst.I.Wave
106 | AddInterface=%KSCATEGORY_CAPTURE%,"Wave",VBCableInst.I.Wave
107 | AddInterface=%KSCATEGORY_RENDER%,"Wave",VBCableInst.I.Wave
108 |
109 |
110 |
111 | [VBCableInst.NT.Services]
112 | AddService=%ServiceName%,0x2,SrvInstSection
113 |
114 | [SrvInstSection]
115 | DisplayName=%DeviceName% (WDM)
116 | ServiceType=%SERVICE_KERNEL_DRIVER%
117 | StartType=%SERVICE_DEMAND_START%
118 | ErrorControl=%SERVICE_ERROR_NORMAL%
119 | ServiceBinary=%12%\%DriverFile%
120 |
121 |
122 | ;======================================================
123 | ;COMMON STRING
124 | ;======================================================
125 | [Strings]
126 |
127 | Provider="VB-Audio Software"
128 | DeviceName="VB-Audio Virtual Cable"
129 | HardwareId="VBAudioVACWDM"
130 | ServiceName="VBAudioVACMME"
131 | DriverFile="vbaudio_cable_win7.sys"
132 | DiskName="vbcable Driver Disk"
133 |
134 | KSCATEGORY_AUDIO="{6994AD04-93EF-11D0-A3CC-00A0C9223196}"
135 | KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
136 | KSCATEGORY_RENDER="{65E8773E-8F56-11D0-A3B9-00A0C9223196}"
137 |
138 | CLSID_Proxy="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
139 |
140 | SERVICE_KERNEL_DRIVER=1
141 | SERVICE_DEMAND_START=3
142 | SERVICE_ERROR_NORMAL=1
143 |
144 | ;; FriendlyName
145 | VBCABLE.INPUTGUID ="{23208800-570C-4682-BB53-7F12CE497910}"
146 | VBCABLE.OUTPUTGUID ="{23208900-570C-4682-BB53-7F12CE497910}"
147 |
148 | VBCABLE.NAMELine1 ="VB-Audio Point"
149 | VBCABLE.INPUTNAME ="CABLE Output"
150 | VBCABLE.OUTPUTNAME ="CABLE Input"
151 |
152 | MediaCategories="SYSTEM\CurrentControlSet\Control\MediaCategories"
153 |
154 |
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbMmeCable_xp.inf:
--------------------------------------------------------------------------------
1 | [Version]
2 |
3 | Signature="$CHICAGO$"
4 | Class=MEDIA
5 | Provider=%Provider%
6 | ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318}
7 | DriverVer=09/02/2014,1.0.3.5
8 | CatalogFile=vbaudio_cable_xp.cat
9 |
10 |
11 |
12 | [Manufacturer]
13 |
14 | %Provider%=DevSection,NTamd64
15 |
16 |
17 |
18 | [DevSection]
19 |
20 | %DeviceName%=DevInst,%HardwareId%
21 |
22 |
23 |
24 | [DevSection.NTamd64]
25 |
26 | %DeviceName%=DevInst,%HardwareId%
27 |
28 |
29 |
30 | ;[DevSection.NTia64]
31 |
32 | ;%DeviceName%=DevInst,%HardwareId%
33 |
34 |
35 |
36 | ;#####################################################################
37 | ;
38 | ; 2k+ Installation
39 | ; ================
40 | ;
41 | ;#####################################################################
42 |
43 |
44 | [DevInst.NT]
45 |
46 | Include=ks.inf,wdmaudio.inf
47 | Needs=KS.Registration, WDMAUDIO.Registration
48 | CopyFiles=DevInst.CopyList
49 | AddReg=DevInst.AddReg
50 |
51 |
52 |
53 | [DevInst.NT.Interfaces]
54 |
55 |
56 | AddInterface=%KSCATEGORY_AUDIO%,"Topo",DevInst.I.Topo
57 |
58 | AddInterface=%KSCATEGORY_AUDIO%,"Wave",DevInst.I.Wave
59 | AddInterface=%KSCATEGORY_CAPTURE%,"Wave",DevInst.I.Wave
60 | AddInterface=%KSCATEGORY_RENDER%,"Wave",DevInst.I.Wave
61 |
62 |
63 |
64 | [DevInst.NT.Services]
65 |
66 | AddService=%ServiceName%,0x2,SrvInstSection
67 |
68 | [SrvInstSection]
69 |
70 | DisplayName=%DeviceName% (WDM)
71 | ServiceType=%SERVICE_KERNEL_DRIVER%
72 | StartType=%SERVICE_DEMAND_START%
73 | ErrorControl=%SERVICE_ERROR_NORMAL%
74 | ServiceBinary=%12%\%DriverFile%
75 |
76 |
77 |
78 | ;#####################################################################
79 | ;
80 | ; 98SE+ Installation
81 | ; ==================
82 | ;
83 | ;#####################################################################
84 |
85 |
86 | [DevInst]
87 |
88 | AlsoInstall=ks.registration(ks.inf),wdmaudio.registration(wdmaudio.inf)
89 | CopyFiles=DevInst.CopyList
90 | AddReg=DevInst.AddReg
91 |
92 |
93 |
94 | [DevInst.Interfaces]
95 |
96 |
97 | AddInterface=%KSCATEGORY_AUDIO%,"Topo",DevInst.I.Topo
98 |
99 | AddInterface=%KSCATEGORY_AUDIO%,"Wave",DevInst.I.Wave
100 | AddInterface=%KSCATEGORY_CAPTURE%,"Wave",DevInst.I.Wave
101 | AddInterface=%KSCATEGORY_RENDER%,"Wave",DevInst.I.Wave
102 |
103 |
104 | ;#####################################################################
105 | ;
106 | ; Common registry data
107 | ; ====================
108 | ;
109 | ;#####################################################################
110 |
111 |
112 | [DevInst.AddReg]
113 |
114 | HKR,,AssociatedFilters,,"wdmaud,redbook"
115 | ;HKR,,SetupPreferredAudioDevices,3,01,00,00,00
116 | HKR,,Driver,,%DriverFile%
117 | HKR,,NTMPDriver,,"%DriverFile%,sbemul.sys"
118 |
119 | HKR,Drivers,SubClasses,,"wave,mixer"
120 |
121 | HKR,Drivers\wave\wdmaud.drv,Driver,,wdmaud.drv
122 | HKR,Drivers\mixer\wdmaud.drv,Driver,,wdmaud.drv
123 |
124 | HKR,Drivers\wave\wdmaud.drv,Description,,%DeviceName%
125 | HKR,Drivers\mixer\wdmaud.drv,Description,,%DeviceName%
126 |
127 | HKLM,%MediaCategories%\%VBCABLE.INPUTGUID%,Name,,%VBCABLE.INPUTNAME%
128 | HKLM,%MediaCategories%\%VBCABLE.INPUTGUID%,Display,1,00,00,00,00
129 |
130 | HKLM,%MediaCategories%\%VBCABLE.OUTPUTGUID%,Name,,%VBCABLE.OUTPUTNAME%
131 | HKLM,%MediaCategories%\%VBCABLE.OUTPUTGUID%,Display,1,00,00,00,00
132 |
133 | [DevInst.I.Topo]
134 | AddReg=DevInst.I.Topo.AddReg
135 |
136 | [DevInst.I.Topo.AddReg]
137 | HKR,,CLSID,,%CLSID_Proxy%
138 | HKR,,FriendlyName,,%VBCABLE.NAMELine1%
139 |
140 | [DevInst.I.Wave]
141 | AddReg=DevInst.I.Wave.AddReg
142 |
143 | [DevInst.I.Wave.AddReg]
144 | HKR,,CLSID,,%CLSID_Proxy%
145 | HKR,,FriendlyName,,%VBCABLE.NAMELine1%
146 |
147 |
148 | ;#####################################################################
149 | ;
150 | ; Files
151 | ; =====
152 | ;
153 | ;#####################################################################
154 |
155 |
156 |
157 | [SourceDisksNames]
158 | 222=%DiskName%,"",222
159 |
160 |
161 |
162 | [SourceDisksFiles.x86]
163 | vbaudio_cable_xp.sys=222
164 |
165 |
166 | [SourceDisksFiles.amd64]
167 | vbaudio_cable_xp.sys=222
168 |
169 |
170 | [DestinationDirs]
171 | DevInst.CopyList=10,system32\drivers
172 |
173 |
174 |
175 | [DevInst.CopyList]
176 | ;%DriverFile%
177 | vbaudio_cable_xp.sys
178 |
179 | ;#####################################################################
180 | ;
181 | ; Strings
182 | ; =======
183 | ;
184 | ;#####################################################################
185 | [Strings]
186 |
187 | Provider="VB-Audio Software"
188 | DeviceName="VB-Audio Virtual Cable"
189 | HardwareId=VBAudioVACWDM
190 | ServiceName=VBAudioVACMME
191 | DriverFile=vbaudio_cable_xp.sys
192 | DiskName="vbcable Driver Disk"
193 |
194 | KSCATEGORY_AUDIO="{6994AD04-93EF-11D0-A3CC-00A0C9223196}"
195 | KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
196 | KSCATEGORY_RENDER="{65E8773E-8F56-11D0-A3B9-00A0C9223196}"
197 |
198 |
199 |
200 | CLSID_Proxy="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
201 |
202 | SERVICE_KERNEL_DRIVER=1
203 | SERVICE_DEMAND_START=3
204 | SERVICE_ERROR_NORMAL=1
205 |
206 | ;; FriendlyName
207 | VBCABLE.INPUTGUID ="{23208800-570C-4682-BB53-7F12CE497910}"
208 | VBCABLE.OUTPUTGUID ="{23208900-570C-4682-BB53-7F12CE497910}"
209 |
210 | VBCABLE.NAMELine1 ="VB-Audio Point"
211 | VBCABLE.INPUTNAME ="CABLE Output"
212 | VBCABLE.OUTPUTNAME ="CABLE Input"
213 |
214 | MediaCategories="SYSTEM\CurrentControlSet\Control\MediaCategories"
215 |
216 |
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable64_2003.cat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable64_2003.cat
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable64_2003.sys:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable64_2003.sys
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable64_vista.cat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable64_vista.cat
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable64_vista.sys:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable64_vista.sys
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable64_win7.cat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable64_win7.cat
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable64_win7.sys:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable64_win7.sys
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable_2003.cat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable_2003.cat
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable_2003.sys:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable_2003.sys
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable_vista.cat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable_vista.cat
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable_vista.sys:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable_vista.sys
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable_win7.cat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable_win7.cat
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable_win7.sys:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable_win7.sys
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable_xp.cat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable_xp.cat
--------------------------------------------------------------------------------
/EspionSpotify/Drivers/vbaudio_cable_xp.sys:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwallet/spy-spotify/5a8f62c4c3144b1eebed9b90a3f544bfa2cea37f/EspionSpotify/Drivers/vbaudio_cable_xp.sys
--------------------------------------------------------------------------------
/EspionSpotify/Enums/AlbumCoverSize.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Enums
2 | {
3 | public enum AlbumCoverSize
4 | {
5 | small,
6 | medium,
7 | large,
8 | extralarge
9 | }
10 | }
--------------------------------------------------------------------------------
/EspionSpotify/Enums/ExternalAPIType.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Enums
2 | {
3 | public enum ExternalAPIType
4 | {
5 | None = - 1,
6 | LastFM = 0,
7 | Spotify
8 | }
9 | }
--------------------------------------------------------------------------------
/EspionSpotify/Enums/LanguageType.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Enums
2 | {
3 | public enum LanguageType
4 | {
5 | en = 0,
6 | fr // French
7 | }
8 | }
--------------------------------------------------------------------------------
/EspionSpotify/Enums/LastFMNodeStatus.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Enums
2 | {
3 | public enum LastFMNodeStatus
4 | {
5 | ok,
6 | failed
7 | }
8 | }
--------------------------------------------------------------------------------
/EspionSpotify/Enums/MediaFormat.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Enums
2 | {
3 | public enum MediaFormat
4 | {
5 | Mp3,
6 | Wav
7 | }
8 | }
--------------------------------------------------------------------------------
/EspionSpotify/Enums/OSVersions.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Enums
2 | {
3 | public enum OSVersions
4 | {
5 | RS3 = 16299,
6 | RS4 = 17134,
7 | RS5_1809 = 17763,
8 | Version21H2 = 21390,
9 | Windows11 = 22000
10 | }
11 | }
--------------------------------------------------------------------------------
/EspionSpotify/Enums/RecordRecordingsStatus.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Enums
2 | {
3 | public enum RecordRecordingsStatus
4 | {
5 | Skip = 0,
6 | Overwrite,
7 | Duplicate
8 | }
9 | }
--------------------------------------------------------------------------------
/EspionSpotify/Enums/SilenceAnalyzer.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Enums
2 | {
3 | public enum SilenceAnalyzer
4 | {
5 | None,
6 | TrimEnd,
7 | TrimStart
8 | }
9 | }
--------------------------------------------------------------------------------
/EspionSpotify/Enums/TitleSeparatorType.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Enums
2 | {
3 | public enum TitleSeparatorType
4 | {
5 | None,
6 | Dash,
7 | Parenthesis
8 | }
9 | }
--------------------------------------------------------------------------------
/EspionSpotify/Enums/TranslationKeys.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Enums
2 | {
3 | public enum TranslationKeys
4 | {
5 | cbOptBitRate128,
6 | cbOptBitRate160,
7 | cbOptBitRate256,
8 | cbOptBitRate320,
9 | cbOptBitRateSpotifyFree,
10 | cbOptBitRateSpotifyPremium,
11 | lblAddFolders,
12 | lblAddSeparators,
13 | lblAd,
14 | lblAds,
15 | lblAlbumTrackNumberToFilePrefix,
16 | lblAudioDevice,
17 | lblBitRate,
18 | lblClientId,
19 | lblDuplicate,
20 | lblExtraTitleToSubtitle,
21 | lblForceSpotifyToSkip,
22 | lblFormat,
23 | lblGeneral,
24 | lblID3,
25 | lblLanguage,
26 | lblListenToSpotifyPlayback,
27 | lblMinimizeToSystemTray,
28 | lblMinLength,
29 | lblMuteAds,
30 | lblCounterToFilePrefix,
31 | lblCounterToMediaTag,
32 | lblPath,
33 | lblRecorder,
34 | lblRecordEverything,
35 | lblRecordAds,
36 | lblRecordingNum,
37 | lblRecordingTimer,
38 | lblRecordOverRecordings,
39 | lblRedirectURL,
40 | lblSecretId,
41 | lblSpy,
42 | lblUpdateRecordingsID3Tags,
43 | logAd,
44 | logDeleting,
45 | logException,
46 | logMaxFileSequenceReached,
47 | logMissingDlls,
48 | logOutputPathNotFound,
49 | logPreviousLogs,
50 | logRecorded,
51 | logRecordedFileNotFound,
52 | logRecording,
53 | logRecordingTimerDone,
54 | logSpotifyConnecting,
55 | logSpotifyIsClosed,
56 | logSpotifyNotConnected,
57 | logSpotifyNotFound,
58 | logSpotifyPlayingOutsideOfSelectedAudioEndPoint,
59 | logStarting,
60 | logStoping,
61 | logStopRecordingWhenSongEnds,
62 | logTrackExists,
63 | logUnknownException,
64 | logUnsupportedNumberChannels,
65 | logUnsupportedRate,
66 | msgBodyCantQuit,
67 | msgBodyDriverInstallationFailed,
68 | msgBodyFailedToUseSpotifyAPI,
69 | msgBodyPathNotFound,
70 | msgBodyPathTooLong,
71 | msgFolderDialog,
72 | msgNewVersionContent,
73 | msgNewVersionTitle,
74 | msgTitleCantQuit,
75 | msgTitleFailedToUseSpotifyAPI,
76 | msgTitlePathNotFound,
77 | msgTitlePathTooLong,
78 | tabAdvanced,
79 | tabRecord,
80 | tabSettings,
81 | tipClear,
82 | tipDirectory,
83 | tipDonate,
84 | tipFAQ,
85 | tipFAQSpotifyAPI,
86 | tipInstallVirtualCableDriver,
87 | tipNumModifierHold,
88 | tipPath,
89 | tipRelease,
90 | tipSpotifyAPICredentials,
91 | tipSpotifyAPIDashboard,
92 | tipStartSpying,
93 | tipStopSying,
94 | tipUninstallVirtualCableDriver,
95 | titleSpotifyAPICredentials,
96 | watermarkClientId,
97 | watermarkSecretId,
98 | watermarkRedirectURL
99 | }
100 | }
--------------------------------------------------------------------------------
/EspionSpotify/Enums/WaveFormatMP3Restriction.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Enums
2 | {
3 | public enum WaveFormatMP3Restriction
4 | {
5 | Channel,
6 | SampleRate
7 | }
8 | }
--------------------------------------------------------------------------------
/EspionSpotify/Events/PlayStateEventArgs.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Events
2 | {
3 | ///
4 | /// Event gets triggered, when the Playin-state is changed (e.g Play --> Pause)
5 | ///
6 | public class PlayStateEventArgs
7 | {
8 | public bool Playing { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/EspionSpotify/Events/TrackChangeEventArgs.cs:
--------------------------------------------------------------------------------
1 | using EspionSpotify.Models;
2 |
3 | namespace EspionSpotify.Events
4 | {
5 | ///
6 | /// Event gets triggered, when the Track is changed
7 | ///
8 | public class TrackChangeEventArgs
9 | {
10 | public Track OldTrack { get; set; }
11 | public Track NewTrack { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/EspionSpotify/Events/TrackTimeChangeEventArgs.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Events
2 | {
3 | ///
4 | /// Event gets triggered, when the tracktime changes
5 | ///
6 | public class TrackTimeChangeEventArgs
7 | {
8 | public int TrackTime { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/EspionSpotify/Exceptions/DestinationPathNotFoundException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace EspionSpotify.Exceptions
4 | {
5 | public class DestinationPathNotFoundException : Exception
6 | {
7 | public DestinationPathNotFoundException()
8 | {
9 | }
10 |
11 | public DestinationPathNotFoundException(string message)
12 | : base(message)
13 | {
14 | }
15 |
16 | public DestinationPathNotFoundException(string message, Exception inner)
17 | : base(message, inner)
18 | {
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/EspionSpotify/Exceptions/SourceFileNotFoundException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace EspionSpotify.Exceptions
4 | {
5 | public class SourceFileNotFoundException : Exception
6 | {
7 | public SourceFileNotFoundException()
8 | {
9 | }
10 |
11 | public SourceFileNotFoundException(string message)
12 | : base(message)
13 | {
14 | }
15 |
16 | public SourceFileNotFoundException(string message, Exception inner)
17 | : base(message, inner)
18 | {
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/EspionSpotify/Extensions/ClassPropertyExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace EspionSpotify.Extensions
2 | {
3 | public static class ClassPropertyExtensions
4 | {
5 | public static void CopyAllTo(this TSource source, TTarget target)
6 | where TSource : class
7 | where TTarget : class
8 | {
9 | var parentProperties = source.GetType().GetProperties();
10 | var childProperties = target.GetType().GetProperties();
11 |
12 | foreach (var parentProperty in parentProperties)
13 | foreach (var childProperty in childProperties)
14 | {
15 | if (!childProperty.CanWrite || !parentProperty.CanRead) break;
16 | if (parentProperty.Name == childProperty.Name &&
17 | parentProperty.PropertyType == childProperty.PropertyType)
18 | {
19 | childProperty.SetValue(target, parentProperty.GetValue(source));
20 | break;
21 | }
22 | }
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/EspionSpotify/Extensions/ColorExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 |
3 | namespace EspionSpotify.Extensions
4 | {
5 | public static class ColorExtensions
6 | {
7 | public static Color SpotifyPrimaryText(this Color _)
8 | {
9 | return Color.FromArgb(32, 187, 88);
10 | }
11 |
12 | public static Color SpotifySecondaryText(this Color _)
13 | {
14 | return Color.White;
15 | }
16 |
17 | public static Color SpotifySecondaryTextAlternate(this Color _)
18 | {
19 | return Color.FromArgb(179, 179, 179);
20 | }
21 |
22 | public static Color SpotifyPrimaryBackground(this Color _)
23 | {
24 | return Color.FromArgb(18, 18, 18);
25 | }
26 |
27 | public static Color SpotifySecondaryBackground(this Color _)
28 | {
29 | return Color.FromArgb(24, 24, 24);
30 | }
31 |
32 | public static Color SpotifySecondaryBackgroundAlternate(this Color _)
33 | {
34 | return Color.FromArgb(40, 40, 40);
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/EspionSpotify/Extensions/ControlExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace EspionSpotify.Extensions
5 | {
6 | public static class ControlExtensions
7 | {
8 | public static TResult GetPropertyThreadSafe(this TControl control,
9 | Func getter)
10 | where TControl : Control
11 | {
12 | if (control.IsDisposed()) return default;
13 | if (control.InvokeRequired)
14 | return (TResult) control.Invoke(getter, control);
15 | return getter(control);
16 | }
17 |
18 | public static void SetPropertyThreadSafe(this TControl control, MethodInvoker setter)
19 | where TControl : Control
20 | {
21 | lock (control)
22 | {
23 | if (control.IsDisposed()) return;
24 | if (control.InvokeRequired)
25 | control.Invoke(setter);
26 | else
27 | setter();
28 | }
29 | }
30 |
31 | public static bool IsDisposed(this TControl control)
32 | where TControl : Control
33 | {
34 | return FrmEspionSpotify.Instance.IsDisposed || control.IsDisposed || control.Parent.IsDisposed;
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/EspionSpotify/Extensions/DictionaryExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using Newtonsoft.Json;
4 |
5 | namespace EspionSpotify.Extensions
6 | {
7 | public static class DictionaryExtensions
8 | {
9 | public static bool IncludesKey(this IDictionary dictionary, string key)
10 | {
11 | return dictionary.Any() && dictionary.ContainsKey(key ?? string.Empty);
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/EspionSpotify/Extensions/JsonObjectExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Newtonsoft.Json;
3 |
4 | namespace EspionSpotify.Extensions
5 | {
6 | public static class JsonObjectExtensions
7 | {
8 | public static IDictionary ToDictionary(this object obj)
9 | {
10 | var json = JsonConvert.SerializeObject(obj ?? new object());
11 | if (!json.StartsWith("{") && !json.EndsWith("}")) return new Dictionary();
12 | var dictionary = JsonConvert.DeserializeObject>(json);
13 | return dictionary;
14 | }
15 |
16 | public static KeyValuePair ToKeyValuePair(this object obj)
17 | {
18 | var json = JsonConvert.SerializeObject(obj ?? new object());
19 | if (!json.StartsWith("{") && !json.EndsWith("}")) return new KeyValuePair();
20 | var pair = JsonConvert.DeserializeObject>(json);
21 | return pair;
22 | }
23 |
24 | public static object[] ToArrayObject(this object obj)
25 | {
26 | var json = JsonConvert.SerializeObject(obj ?? new object());
27 | if (!json.StartsWith("[") && !json.EndsWith("]")) return null;
28 | return JsonConvert.DeserializeObject