├── .github └── workflows │ └── dotnet-core-desktop.yml ├── .gitignore ├── ChaturbatePlayer ├── ChaturbatePlayer.sln └── ChaturbatePlayer │ ├── App.xaml │ ├── App.xaml.cs │ ├── Base │ ├── IMediator.cs │ └── Mediator.cs │ ├── ChaturbatePlayer.csproj │ ├── Converters │ ├── GenderToImageConverter.cs │ ├── GenderToNameConverter.cs │ ├── IntegerToVisibilityConverter.cs │ ├── InverseBooleanConverter.cs │ ├── InverseBooleanToVisibilityConverter.cs │ ├── LiveStreamPlayerStateToVisibilityConverter.cs │ └── PlayerMuteStateToImageSourceConverter.cs │ ├── Icon.ico │ ├── Images │ ├── ApplicationExport.png │ ├── ArrowBack.png │ ├── ArrowCircle.png │ ├── ArrowForward.png │ ├── ArrowRefresh.png │ ├── FolderOpen.png │ ├── GenderCouple.png │ ├── GenderFemale.png │ ├── GenderMale.png │ ├── GenderTrans.png │ ├── Help.png │ ├── Icon.ico │ ├── Icon.png │ ├── Lock.png │ ├── Logo.png │ ├── PlayerMute.png │ ├── PlayerPause.png │ ├── PlayerPlay.png │ ├── PlayerStop.png │ ├── PlayerUnmute.png │ ├── Settings.png │ ├── Star.png │ ├── Unlock.png │ └── Webcam.png │ ├── Models │ ├── ChatRoomModel.cs │ ├── LicenseModel.cs │ └── SettingsModel.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Shared.cs │ ├── VLC.zip │ ├── ViewModels │ ├── ChatRoomsViewModel.cs │ ├── LicenseKeyGeneratorViewModel.cs │ ├── LiveStreamPlayerViewModel.cs │ ├── MainWindowViewModel.cs │ ├── SettingsViewModel.cs │ └── SplashViewModel.cs │ ├── Views │ ├── ChatRoomsView.xaml │ ├── ChatRoomsView.xaml.cs │ ├── LicenseKeyGeneratorWindowView.xaml │ ├── LicenseKeyGeneratorWindowView.xaml.cs │ ├── LiveStreamPlayerView.xaml │ ├── LiveStreamPlayerView.xaml.cs │ ├── MainWindowView.xaml │ ├── MainWindowView.xaml.cs │ ├── SettingsView.xaml │ ├── SettingsView.xaml.cs │ ├── SplashWindowView.xaml │ └── SplashWindowView.xaml.cs │ ├── app.config │ └── packages.config ├── README.md └── Screenshots ├── Capture0.PNG ├── Capture1.PNG └── Capture2.PNG /.github/workflows/dotnet-core-desktop.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | # This workflow will build, test, sign and package a WPF or Windows Forms desktop application 7 | # built on .NET Core. 8 | # To learn how to migrate your existing application to .NET Core, 9 | # refer to https://docs.microsoft.com/en-us/dotnet/desktop-wpf/migration/convert-project-from-net-framework 10 | # 11 | # To configure this workflow: 12 | # 13 | # 1. Configure environment variables 14 | # GitHub sets default environment variables for every workflow run. 15 | # Replace the variables relative to your project in the "env" section below. 16 | # 17 | # 2. Signing 18 | # Generate a signing certificate in the Windows Application 19 | # Packaging Project or add an existing signing certificate to the project. 20 | # Next, use PowerShell to encode the .pfx file using Base64 encoding 21 | # by running the following Powershell script to generate the output string: 22 | # 23 | # $pfx_cert = Get-Content '.\SigningCertificate.pfx' -Encoding Byte 24 | # [System.Convert]::ToBase64String($pfx_cert) | Out-File 'SigningCertificate_Encoded.txt' 25 | # 26 | # Open the output file, SigningCertificate_Encoded.txt, and copy the 27 | # string inside. Then, add the string to the repo as a GitHub secret 28 | # and name it "Base64_Encoded_Pfx." 29 | # For more information on how to configure your signing certificate for 30 | # this workflow, refer to https://github.com/microsoft/github-actions-for-desktop-apps#signing 31 | # 32 | # Finally, add the signing certificate password to the repo as a secret and name it "Pfx_Key". 33 | # See "Build the Windows Application Packaging project" below to see how the secret is used. 34 | # 35 | # For more information on GitHub Actions, refer to https://github.com/features/actions 36 | # For a complete CI/CD sample to get started with GitHub Action workflows for Desktop Applications, 37 | # refer to https://github.com/microsoft/github-actions-for-desktop-apps 38 | 39 | name: .NET Core Desktop 40 | 41 | on: 42 | push: 43 | branches: [ master ] 44 | pull_request: 45 | branches: [ master ] 46 | 47 | jobs: 48 | 49 | build: 50 | 51 | strategy: 52 | matrix: 53 | configuration: [Debug, Release] 54 | 55 | runs-on: windows-latest # For a list of available runner types, refer to 56 | # https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on 57 | 58 | env: 59 | Solution_Name: your-solution-name # Replace with your solution name, i.e. MyWpfApp.sln. 60 | Test_Project_Path: your-test-project-path # Replace with the path to your test project, i.e. MyWpfApp.Tests\MyWpfApp.Tests.csproj. 61 | Wap_Project_Directory: your-wap-project-directory-name # Replace with the Wap project directory relative to the solution, i.e. MyWpfApp.Package. 62 | Wap_Project_Path: your-wap-project-path # Replace with the path to your Wap project, i.e. MyWpf.App.Package\MyWpfApp.Package.wapproj. 63 | 64 | steps: 65 | - name: Checkout 66 | uses: actions/checkout@v2 67 | with: 68 | fetch-depth: 0 69 | 70 | # Install the .NET Core workload 71 | - name: Install .NET Core 72 | uses: actions/setup-dotnet@v1 73 | with: 74 | dotnet-version: 3.1.101 75 | 76 | # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild 77 | - name: Setup MSBuild.exe 78 | uses: microsoft/setup-msbuild@2008f912f56e61277eefaac6d1888b750582aa16 79 | 80 | # Execute all unit tests in the solution 81 | - name: Execute unit tests 82 | run: dotnet test 83 | 84 | # Restore the application to populate the obj folder with RuntimeIdentifiers 85 | - name: Restore the application 86 | run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration 87 | env: 88 | Configuration: ${{ matrix.configuration }} 89 | 90 | # Decode the base 64 encoded pfx and save the Signing_Certificate 91 | - name: Decode the pfx 92 | run: | 93 | $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.Base64_Encoded_Pfx }}") 94 | $certificatePath = Join-Path -Path $env:Wap_Project_Directory -ChildPath GitHubActionsWorkflow.pfx 95 | [IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte) 96 | 97 | # Create the app package by building and packaging the Windows Application Packaging project 98 | - name: Create the app package 99 | run: msbuild $env:Wap_Project_Path /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:Appx_Package_Build_Mode /p:AppxBundle=$env:Appx_Bundle /p:PackageCertificateKeyFile=GitHubActionsWorkflow.pfx /p:PackageCertificatePassword=${{ secrets.Pfx_Key }} 100 | env: 101 | Appx_Bundle: Always 102 | Appx_Bundle_Platforms: x86|x64 103 | Appx_Package_Build_Mode: StoreUpload 104 | Configuration: ${{ matrix.configuration }} 105 | 106 | # Remove the pfx 107 | - name: Remove the pfx 108 | run: Remove-Item -path $env:Wap_Project_Directory\$env:Signing_Certificate 109 | 110 | # Upload the MSIX package: https://github.com/marketplace/actions/upload-artifact 111 | - name: Upload build artifacts 112 | uses: actions/upload-artifact@v2 113 | with: 114 | name: MSIX Package 115 | path: ${{ env.Wap_Project_Directory }}\AppPackages 116 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | 24 | # Visual Studio 2015 cache/options directory 25 | .vs/ 26 | # Uncomment if you have tasks that create the project's static files in wwwroot 27 | #wwwroot/ 28 | 29 | # MSTest test Results 30 | [Tt]est[Rr]esult*/ 31 | [Bb]uild[Ll]og.* 32 | 33 | # NUNIT 34 | *.VisualState.xml 35 | TestResult.xml 36 | 37 | # Build Results of an ATL Project 38 | [Dd]ebugPS/ 39 | [Rr]eleasePS/ 40 | dlldata.c 41 | 42 | # DNX 43 | project.lock.json 44 | artifacts/ 45 | 46 | *_i.c 47 | *_p.c 48 | *_i.h 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.tmp_proj 63 | *.log 64 | *.vspscc 65 | *.vssscc 66 | .builds 67 | *.pidb 68 | *.svclog 69 | *.scc 70 | 71 | # Chutzpah Test files 72 | _Chutzpah* 73 | 74 | # Visual C++ cache files 75 | ipch/ 76 | *.aps 77 | *.ncb 78 | *.opendb 79 | *.opensdf 80 | *.sdf 81 | *.cachefile 82 | 83 | # Visual Studio profiler 84 | *.psess 85 | *.vsp 86 | *.vspx 87 | *.sap 88 | 89 | # TFS 2012 Local Workspace 90 | $tf/ 91 | 92 | # Guidance Automation Toolkit 93 | *.gpState 94 | 95 | # ReSharper is a .NET coding add-in 96 | _ReSharper*/ 97 | *.[Rr]e[Ss]harper 98 | *.DotSettings.user 99 | 100 | # JustCode is a .NET coding add-in 101 | .JustCode 102 | 103 | # TeamCity is a build add-in 104 | _TeamCity* 105 | 106 | # DotCover is a Code Coverage Tool 107 | *.dotCover 108 | 109 | # NCrunch 110 | _NCrunch_* 111 | .*crunch*.local.xml 112 | nCrunchTemp_* 113 | 114 | # MightyMoose 115 | *.mm.* 116 | AutoTest.Net/ 117 | 118 | # Web workbench (sass) 119 | .sass-cache/ 120 | 121 | # Installshield output folder 122 | [Ee]xpress/ 123 | 124 | # DocProject is a documentation generator add-in 125 | DocProject/buildhelp/ 126 | DocProject/Help/*.HxT 127 | DocProject/Help/*.HxC 128 | DocProject/Help/*.hhc 129 | DocProject/Help/*.hhk 130 | DocProject/Help/*.hhp 131 | DocProject/Help/Html2 132 | DocProject/Help/html 133 | 134 | # Click-Once directory 135 | publish/ 136 | 137 | # Publish Web Output 138 | *.[Pp]ublish.xml 139 | *.azurePubxml 140 | # TODO: Comment the next line if you want to checkin your web deploy settings 141 | # but database connection strings (with potential passwords) will be unencrypted 142 | *.pubxml 143 | *.publishproj 144 | 145 | # NuGet Packages 146 | *.nupkg 147 | # The packages folder can be ignored because of Package Restore 148 | **/packages/* 149 | # except build/, which is used as an MSBuild target. 150 | !**/packages/build/ 151 | # Uncomment if necessary however generally it will be regenerated when needed 152 | #!**/packages/repositories.config 153 | # NuGet v3's project.json files produces more ignoreable files 154 | *.nuget.props 155 | *.nuget.targets 156 | 157 | # Microsoft Azure Build Output 158 | csx/ 159 | *.build.csdef 160 | 161 | # Microsoft Azure Emulator 162 | ecf/ 163 | rcf/ 164 | 165 | # Microsoft Azure ApplicationInsights config file 166 | ApplicationInsights.config 167 | 168 | # Windows Store app package directory 169 | AppPackages/ 170 | BundleArtifacts/ 171 | 172 | # Visual Studio cache files 173 | # files ending in .cache can be ignored 174 | *.[Cc]ache 175 | # but keep track of directories ending in .cache 176 | !*.[Cc]ache/ 177 | 178 | # Others 179 | ClientBin/ 180 | ~$* 181 | *~ 182 | *.dbmdl 183 | *.dbproj.schemaview 184 | *.pfx 185 | *.publishsettings 186 | node_modules/ 187 | orleans.codegen.cs 188 | 189 | # RIA/Silverlight projects 190 | Generated_Code/ 191 | 192 | # Backup & report files from converting an old project file 193 | # to a newer Visual Studio version. Backup files are not needed, 194 | # because we have git ;-) 195 | _UpgradeReport_Files/ 196 | Backup*/ 197 | UpgradeLog*.XML 198 | UpgradeLog*.htm 199 | 200 | # SQL Server files 201 | *.mdf 202 | *.ldf 203 | 204 | # Business Intelligence projects 205 | *.rdl.data 206 | *.bim.layout 207 | *.bim_*.settings 208 | 209 | # Microsoft Fakes 210 | FakesAssemblies/ 211 | 212 | # GhostDoc plugin setting file 213 | *.GhostDoc.xml 214 | 215 | # Node.js Tools for Visual Studio 216 | .ntvs_analysis.dat 217 | 218 | # Visual Studio 6 build log 219 | *.plg 220 | 221 | # Visual Studio 6 workspace options file 222 | *.opt 223 | 224 | # Visual Studio LightSwitch build output 225 | **/*.HTMLClient/GeneratedArtifacts 226 | **/*.DesktopClient/GeneratedArtifacts 227 | **/*.DesktopClient/ModelManifest.xml 228 | **/*.Server/GeneratedArtifacts 229 | **/*.Server/ModelManifest.xml 230 | _Pvt_Extensions 231 | 232 | # Paket dependency manager 233 | .paket/paket.exe 234 | 235 | # FAKE - F# Make 236 | .fake/ 237 | /.gitattributes 238 | 239 | !VlcLib/* 240 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29123.88 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChaturbatePlayer", "ChaturbatePlayer\ChaturbatePlayer.csproj", "{F9AFA7E1-F72A-4AA7-95B2-5813337B984F}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F}.Debug|x64.ActiveCfg = Debug|x64 21 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F}.Debug|x64.Build.0 = Debug|x64 22 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F}.Debug|x86.ActiveCfg = Debug|x86 23 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F}.Debug|x86.Build.0 = Debug|x86 24 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F}.Release|x64.ActiveCfg = Release|x64 27 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F}.Release|x64.Build.0 = Release|x64 28 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F}.Release|x86.ActiveCfg = Release|x86 29 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F}.Release|x86.Build.0 = Release|x86 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {008E0EBB-72BF-422E-9835-27BEBD89C217} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/App.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.Views; 2 | using System.Diagnostics; 3 | using System.Windows; 4 | using WpfBindingErrors; 5 | 6 | namespace ChaturbatePlayer 7 | { 8 | public partial class App : Application 9 | { 10 | protected override void OnStartup(StartupEventArgs e) 11 | { 12 | base.OnStartup(e); 13 | if (Debugger.IsAttached) 14 | BindingExceptionThrower.Attach(); 15 | } 16 | 17 | protected override void OnExit(ExitEventArgs e) 18 | { 19 | Shared.Instance.SaveSettings(); 20 | base.OnExit(e); 21 | } 22 | 23 | void Application_Startup(object sender, StartupEventArgs e) 24 | { 25 | MainWindow = new MainWindowView(); 26 | MainWindow.Show(); 27 | 28 | var splash = new SplashWindowView(); 29 | splash.Show(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Base/IMediator.cs: -------------------------------------------------------------------------------- 1 | namespace ChaturbatePlayer.Base 2 | { 3 | public enum NotificationType: byte 4 | { 5 | ChatRoomSelected, 6 | LicenseChanged, 7 | TabPageChanged, 8 | Initialized 9 | } 10 | 11 | interface IMediator 12 | { 13 | void NotificationReceived(NotificationType type, params object[] data); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Base/Mediator.cs: -------------------------------------------------------------------------------- 1 | using NullVoidCreations.WpfHelpers.Base; 2 | using System.Collections.Generic; 3 | 4 | namespace ChaturbatePlayer.Base 5 | { 6 | sealed class Mediator: NotificationBase 7 | { 8 | static Mediator _instance; 9 | static object _syncLock; 10 | readonly List _colleagues; 11 | 12 | #region constructor/destructor 13 | 14 | static Mediator() 15 | { 16 | _syncLock = new object(); 17 | } 18 | 19 | private Mediator() 20 | { 21 | _colleagues = new List(); 22 | } 23 | 24 | #endregion 25 | 26 | #region properties 27 | 28 | public static Mediator Instance 29 | { 30 | get 31 | { 32 | lock(_syncLock) 33 | { 34 | if (_instance == null) 35 | _instance = new Mediator(); 36 | 37 | return _instance; 38 | } 39 | } 40 | } 41 | 42 | #endregion 43 | 44 | public bool RegisterColleague(IMediator colleague) 45 | { 46 | if (_colleagues.Contains(colleague)) 47 | return false; 48 | else 49 | { 50 | _colleagues.Add(colleague); 51 | return true; 52 | } 53 | } 54 | 55 | public void UnregisterColleague(IMediator colleague) 56 | { 57 | var index = _colleagues.IndexOf(colleague); 58 | if (index > -1) 59 | _colleagues.RemoveAt(index); 60 | } 61 | 62 | public void RaiseNotification(IMediator sender, NotificationType type, params object[] data) 63 | { 64 | foreach (var colleague in _colleagues) 65 | { 66 | if (!colleague.Equals(sender)) 67 | { 68 | colleague.NotificationReceived(type, data); 69 | } 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/ChaturbatePlayer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F9AFA7E1-F72A-4AA7-95B2-5813337B984F} 8 | WinExe 9 | Properties 10 | ChaturbatePlayer 11 | ChaturbatePlayer 12 | v4.0 13 | 512 14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 15 | 4 16 | 17 | false 18 | publish\ 19 | true 20 | Disk 21 | false 22 | Foreground 23 | 7 24 | Days 25 | false 26 | false 27 | true 28 | 0 29 | 1.0.0.0 30 | false 31 | true 32 | 33 | 34 | x86 35 | true 36 | full 37 | false 38 | bin\Debug\ 39 | DEBUG;TRACE 40 | prompt 41 | 4 42 | false 43 | 44 | 45 | x86 46 | pdbonly 47 | true 48 | bin\Release\ 49 | TRACE 50 | prompt 51 | 4 52 | false 53 | 54 | 55 | false 56 | 57 | 58 | 59 | 60 | 61 | 62 | Images\Icon.ico 63 | 64 | 65 | true 66 | bin\x86\Debug\ 67 | DEBUG;TRACE 68 | full 69 | x86 70 | prompt 71 | MinimumRecommendedRules.ruleset 72 | 73 | 74 | bin\x86\Release\ 75 | TRACE 76 | true 77 | pdbonly 78 | x86 79 | prompt 80 | MinimumRecommendedRules.ruleset 81 | 82 | 83 | true 84 | bin\x64\Debug\ 85 | DEBUG;TRACE 86 | full 87 | x64 88 | prompt 89 | MinimumRecommendedRules.ruleset 90 | 91 | 92 | bin\x64\Release\ 93 | TRACE 94 | true 95 | pdbonly 96 | x64 97 | prompt 98 | MinimumRecommendedRules.ruleset 99 | 100 | 101 | ChaturbatePlayer.App 102 | 103 | 104 | true 105 | 106 | 107 | 108 | ..\packages\HtmlAgilityPack.1.11.17\lib\Net40\HtmlAgilityPack.dll 109 | 110 | 111 | ..\packages\NullVoidCreations.WpfHelpers.19.8.7.1139\lib\net40\Microsoft.Expression.Interactions.dll 112 | 113 | 114 | ..\packages\NullVoidCreations.WpfHelpers.19.8.7.1139\lib\net40\NullVoidCreations.WpfHelpers.dll 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | ..\packages\NullVoidCreations.WpfHelpers.19.8.7.1139\lib\net40\System.Windows.Interactivity.dll 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 4.0 132 | 133 | 134 | ..\packages\Vlc.DotNet.Core.3.0.0\lib\net40\Vlc.DotNet.Core.dll 135 | 136 | 137 | ..\packages\Vlc.DotNet.Core.Interops.3.0.0\lib\net40\Vlc.DotNet.Core.Interops.dll 138 | 139 | 140 | ..\packages\Vlc.DotNet.Forms.3.0.0\lib\net40\Vlc.DotNet.Forms.dll 141 | 142 | 143 | ..\packages\Vlc.DotNet.Wpf.3.0.0\lib\net40\Vlc.DotNet.Wpf.dll 144 | 145 | 146 | 147 | 148 | 149 | 150 | ..\packages\WpfBindingErrors.1.1.0\lib\net40\WpfBindingErrors.dll 151 | 152 | 153 | 154 | 155 | MSBuild:Compile 156 | Designer 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | ChatRoomsView.xaml 176 | 177 | 178 | LiveStreamPlayerView.xaml 179 | 180 | 181 | SettingsView.xaml 182 | 183 | 184 | LicenseKeyGeneratorWindowView.xaml 185 | 186 | 187 | SplashWindowView.xaml 188 | 189 | 190 | MSBuild:Compile 191 | Designer 192 | 193 | 194 | App.xaml 195 | Code 196 | 197 | 198 | 199 | 200 | 201 | MainWindowView.xaml 202 | Code 203 | 204 | 205 | Designer 206 | MSBuild:Compile 207 | 208 | 209 | Designer 210 | MSBuild:Compile 211 | 212 | 213 | Designer 214 | MSBuild:Compile 215 | 216 | 217 | Designer 218 | MSBuild:Compile 219 | 220 | 221 | Designer 222 | MSBuild:Compile 223 | 224 | 225 | 226 | 227 | Code 228 | 229 | 230 | 231 | 232 | 233 | PreserveNewest 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | False 304 | .NET Framework 3.5 SP1 305 | false 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | REM xcopy "$(SolutionDir)VlcLib\*.*" "$(TargetDir)VlcLib" /Y/D/E/I 315 | 316 | 323 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Converters/GenderToImageConverter.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.Models; 2 | using System; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | 6 | namespace ChaturbatePlayer.Converters 7 | { 8 | [ValueConversion(typeof(Gender), typeof(string))] 9 | public class GenderToImageConverter : IValueConverter 10 | { 11 | internal const string IMAGE_URL = "/ChaturbatePlayer;component/Images/{0}"; 12 | 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | switch((Gender)value) 16 | { 17 | case Gender.Male: 18 | return string.Format(IMAGE_URL, "GenderMale.png"); 19 | 20 | case Gender.Female: 21 | return string.Format(IMAGE_URL, "GenderFemale.png"); 22 | 23 | case Gender.Couple: 24 | return string.Format(IMAGE_URL, "GenderCouple.png"); 25 | 26 | case Gender.Trans: 27 | return string.Format(IMAGE_URL, "GenderTrans.png"); 28 | 29 | default: 30 | return string.Format(IMAGE_URL, "Star.png"); 31 | } 32 | } 33 | 34 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 35 | { 36 | throw new NotImplementedException(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Converters/GenderToNameConverter.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.Models; 2 | using System; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | 6 | namespace ChaturbatePlayer.Converters 7 | { 8 | [ValueConversion(typeof(Gender), typeof(string))] 9 | public class GenderToNameConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | switch ((Gender)value) 14 | { 15 | case Gender.Male: 16 | return "MALE"; 17 | 18 | case Gender.Female: 19 | return "FEMALE"; 20 | 21 | case Gender.Couple: 22 | return "COUPLE"; 23 | 24 | case Gender.Trans: 25 | return "TRANS"; 26 | 27 | default: 28 | return "FEATURED"; 29 | } 30 | } 31 | 32 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 33 | { 34 | throw new NotImplementedException(); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Converters/IntegerToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace ChaturbatePlayer.Converters 7 | { 8 | /// 9 | /// This converter returns Visibility.Visible if value passed is 0. 10 | /// 11 | [ValueConversion(typeof(int), typeof(Visibility))] 12 | public class IntegerToVisibilityConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | if (int.Parse(value.ToString()) > 0) 17 | return Visibility.Collapsed; 18 | else 19 | return Visibility.Visible; 20 | } 21 | 22 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Converters/InverseBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace ChaturbatePlayer.Converters 6 | { 7 | [ValueConversion(typeof(bool), typeof(bool))] 8 | public class InverseBooleanConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | return !(bool)value; 13 | } 14 | 15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | throw new NotImplementedException(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Converters/InverseBooleanToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace ChaturbatePlayer.Converters 7 | { 8 | [ValueConversion(typeof(bool), typeof(Visibility))] 9 | public class InverseBooleanToVisibilityConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | return !(bool)value ? Visibility.Visible : Visibility.Collapsed; 14 | } 15 | 16 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 17 | { 18 | throw new NotImplementedException(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Converters/LiveStreamPlayerStateToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.ViewModels; 2 | using System; 3 | using System.Globalization; 4 | using System.Windows; 5 | using System.Windows.Data; 6 | 7 | namespace ChaturbatePlayer.Converters 8 | { 9 | [ValueConversion(typeof(LiveStreamPlayerState), typeof(Visibility))] 10 | public class LiveStreamPlayerStateToVisibilityConverter : IValueConverter 11 | { 12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 13 | { 14 | switch((LiveStreamPlayerState)value) 15 | { 16 | case LiveStreamPlayerState.Playing: 17 | return Visibility.Visible; 18 | 19 | default: 20 | return Visibility.Hidden; 21 | } 22 | } 23 | 24 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 25 | { 26 | throw new NotImplementedException(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Converters/PlayerMuteStateToImageSourceConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace ChaturbatePlayer.Converters 6 | { 7 | [ValueConversion(typeof(bool), typeof(string))] 8 | public class PlayerMuteStateToImageSourceConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | if ((bool)value) 13 | return string.Format(GenderToImageConverter.IMAGE_URL, "PlayerUnmute.png"); 14 | else 15 | return string.Format(GenderToImageConverter.IMAGE_URL, "PlayerMute.png"); 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Icon.ico -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/ApplicationExport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/ApplicationExport.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/ArrowBack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/ArrowBack.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/ArrowCircle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/ArrowCircle.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/ArrowForward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/ArrowForward.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/ArrowRefresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/ArrowRefresh.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/FolderOpen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/FolderOpen.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/GenderCouple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/GenderCouple.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/GenderFemale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/GenderFemale.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/GenderMale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/GenderMale.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/GenderTrans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/GenderTrans.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/Help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/Help.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/Icon.ico -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/Icon.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/Lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/Lock.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/Logo.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/PlayerMute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/PlayerMute.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/PlayerPause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/PlayerPause.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/PlayerPlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/PlayerPlay.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/PlayerStop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/PlayerStop.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/PlayerUnmute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/PlayerUnmute.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/Settings.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/Star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/Star.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/Unlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/Unlock.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Images/Webcam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/Images/Webcam.png -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Models/ChatRoomModel.cs: -------------------------------------------------------------------------------- 1 | using NullVoidCreations.WpfHelpers.Base; 2 | 3 | namespace ChaturbatePlayer.Models 4 | { 5 | public enum Gender : byte 6 | { 7 | Male, 8 | Female, 9 | Couple, 10 | Trans, 11 | NotSpecified 12 | } 13 | 14 | public class ChatRoomModel : NotificationBase 15 | { 16 | string _camsCount, _videoFeedUrl; 17 | bool _isVideoFeedHd; 18 | 19 | public ChatRoomModel( 20 | string name, 21 | int age, 22 | Gender gender, 23 | string roomTitle, 24 | string profileUrl, 25 | string profileImageUrl, 26 | int height, 27 | int width) 28 | { 29 | Name = name; 30 | Age = age; 31 | Gender = gender; 32 | RoomTitle = roomTitle; 33 | ProfileUrl = profileUrl; 34 | ProfileImageUrl = profileImageUrl; 35 | Height = height; 36 | Width = width; 37 | } 38 | 39 | #region properties 40 | 41 | public string Name { get; } 42 | 43 | public int Age { get; } 44 | 45 | public Gender Gender { get; } 46 | 47 | public string ProfileUrl { get; } 48 | 49 | public int Height { get; } 50 | 51 | public int Width { get; } 52 | 53 | public string ProfileImageUrl { get; } 54 | 55 | public string RoomTitle { get; } 56 | 57 | public string VideoFeedUrl 58 | { 59 | get => _videoFeedUrl; 60 | set => Set(nameof(VideoFeedUrl), ref _videoFeedUrl, value); 61 | } 62 | 63 | public bool IsVideoFeedHd 64 | { 65 | get => _isVideoFeedHd; 66 | set => Set(nameof(IsVideoFeedHd), ref _isVideoFeedHd, value); 67 | } 68 | 69 | public string CamsCount 70 | { 71 | get => _camsCount; 72 | set => Set(nameof(CamsCount), ref _camsCount, value); 73 | } 74 | 75 | #endregion 76 | 77 | #region methods 78 | 79 | public override string ToString() 80 | { 81 | return Name; 82 | } 83 | 84 | public override int GetHashCode() 85 | { 86 | return Name.GetHashCode(); 87 | } 88 | 89 | public override bool Equals(object obj) 90 | { 91 | var compareWith = obj as ChatRoomModel; 92 | if (compareWith == null) 93 | return false; 94 | 95 | return compareWith.Name.Equals(Name); 96 | } 97 | 98 | #endregion 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Models/LicenseModel.cs: -------------------------------------------------------------------------------- 1 | using NullVoidCreations.WpfHelpers; 2 | using NullVoidCreations.WpfHelpers.Base; 3 | using System; 4 | 5 | namespace ChaturbatePlayer.Models 6 | { 7 | public class LicenseModel : NotificationBase 8 | { 9 | bool _isTrial; 10 | DateTime _issueDate, _expirationDate; 11 | string _registeredEmail, _licenseKey; 12 | 13 | public LicenseModel() 14 | { 15 | Rest(); 16 | } 17 | 18 | internal void Rest() 19 | { 20 | IssueDate = new DateTime(1900, 1, 1); 21 | ExpirationDate = new DateTime(1900, 1, 1); 22 | IsTrial = true; 23 | } 24 | 25 | #region properties 26 | 27 | public string LicenseKey 28 | { 29 | get { return _licenseKey; } 30 | set 31 | { 32 | Set(nameof(LicenseKey), ref _licenseKey, value); 33 | } 34 | } 35 | 36 | public bool IsTrial 37 | { 38 | get { return _isTrial; } 39 | private set 40 | { 41 | Set(nameof(IsTrial), ref _isTrial, value); 42 | } 43 | } 44 | 45 | public string RegisteredEmail 46 | { 47 | get { return _registeredEmail; } 48 | set 49 | { 50 | Set(nameof(RegisteredEmail), ref _registeredEmail, value); 51 | } 52 | } 53 | 54 | public DateTime IssueDate 55 | { 56 | get { return _issueDate; } 57 | set 58 | { 59 | Set(nameof(IssueDate), ref _issueDate, value); 60 | } 61 | } 62 | 63 | public DateTime ExpirationDate 64 | { 65 | get { return _expirationDate; } 66 | private set 67 | { 68 | Set(nameof(ExpirationDate), ref _expirationDate, value); 69 | } 70 | } 71 | 72 | #endregion 73 | 74 | #region private methods 75 | 76 | bool IsExpired(LicenseModel license) 77 | { 78 | var currentDate = DateTime.Now; 79 | if (currentDate.Date < license.IssueDate.Date) 80 | return true; 81 | if (currentDate.Date > license.ExpirationDate.Date) 82 | return true; 83 | 84 | return false; 85 | } 86 | 87 | DateTime ExtractDate(string text, int startIndex) 88 | { 89 | var date = new DateTime( 90 | int.Parse(text.Substring(startIndex, 4)), 91 | int.Parse(text.Substring(startIndex + 4, 2)), 92 | int.Parse(text.Substring(startIndex + 6, 2))); 93 | return date; 94 | } 95 | 96 | #endregion 97 | 98 | internal void Generate(string registeredEmail, DateTime issueDate, int numberOfDays) 99 | { 100 | RegisteredEmail = registeredEmail; 101 | IssueDate = issueDate; 102 | ExpirationDate = IssueDate.AddDays(numberOfDays); 103 | LicenseKey = string.Format("{0:0000}{1:00}{2:00}{3:0000}{4:00}{5:00}{6}", 104 | IssueDate.Year, 105 | IssueDate.Month, 106 | IssueDate.Day, 107 | ExpirationDate.Year, 108 | ExpirationDate.Month, 109 | ExpirationDate.Day, 110 | RegisteredEmail); 111 | LicenseKey = LicenseKey.Encrypt(Shared.ENCRYPTION_KEY); 112 | } 113 | 114 | public bool Validate() 115 | { 116 | try 117 | { 118 | var key = LicenseKey.Decrypt(Shared.ENCRYPTION_KEY); 119 | IssueDate = ExtractDate(key, 0); 120 | ExpirationDate = ExtractDate(key, 8); 121 | RegisteredEmail = key.Substring(16, key.Length - 16); 122 | IsTrial = IsExpired(this); 123 | return true; 124 | } 125 | catch 126 | { 127 | Rest(); 128 | } 129 | 130 | return false; 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Models/SettingsModel.cs: -------------------------------------------------------------------------------- 1 | using NullVoidCreations.WpfHelpers; 2 | using NullVoidCreations.WpfHelpers.Base; 3 | using System.IO; 4 | 5 | namespace ChaturbatePlayer.Models 6 | { 7 | public class SettingsModel: NotificationBase 8 | { 9 | readonly SettingsManager _manager; 10 | LicenseModel _license; 11 | 12 | public SettingsModel(ref SettingsManager manager) 13 | { 14 | _manager = manager; 15 | } 16 | 17 | internal void Reset() 18 | { 19 | MediaPlayer = "VLC"; 20 | RefreshInterval = 2; 21 | IsMinutesLiveShown = false; 22 | IsAutoRefreshEnabled = false; 23 | IsExternalMediaPlayerAllowed = false; 24 | IsExternalMediaPlayerControlsHidden = false; 25 | IsExternalMediaPlayerFullScreen = false; 26 | IsAutoPauseEnabled = false; 27 | IsAutoSaveVideosEnabled = false; 28 | AutoSaveDirectory = Shared.Instance.DataPath; 29 | IsUrlShown = false; 30 | } 31 | 32 | #region properties 33 | 34 | public string LicenseKey 35 | { 36 | get { return _manager.GetValue(nameof(LicenseKey)); } 37 | set 38 | { 39 | _manager.SetValue(nameof(LicenseKey), value); 40 | RaisePropertyChanged(nameof(LicenseKey)); 41 | } 42 | } 43 | 44 | public LicenseModel License 45 | { 46 | get { return _license; } 47 | private set 48 | { 49 | _license = value; 50 | RaisePropertyChanged(nameof(License)); 51 | } 52 | } 53 | 54 | public string MediaPlayer 55 | { 56 | get 57 | { 58 | var value = _manager.GetValue(nameof(MediaPlayer)); 59 | if (default(string) == value) 60 | value = "VLC"; 61 | 62 | return value; 63 | } 64 | set 65 | { 66 | _manager.SetValue(nameof(MediaPlayer), value); 67 | RaisePropertyChanged(nameof(MediaPlayer)); 68 | } 69 | } 70 | 71 | public int RefreshInterval 72 | { 73 | get 74 | { 75 | var value = _manager.GetValue(nameof(RefreshInterval)); 76 | if (default(int) == value) 77 | value = 2; 78 | 79 | return value; 80 | } 81 | set 82 | { 83 | _manager.SetValue(nameof(RefreshInterval), value); 84 | RaisePropertyChanged(nameof(RefreshInterval)); 85 | } 86 | } 87 | 88 | public bool IsMinutesLiveShown 89 | { 90 | get { return _manager.GetValue(nameof(IsMinutesLiveShown)); } 91 | set 92 | { 93 | _manager.SetValue(nameof(IsMinutesLiveShown), value); 94 | RaisePropertyChanged(nameof(IsMinutesLiveShown)); 95 | } 96 | } 97 | 98 | public bool IsAutoRefreshEnabled 99 | { 100 | get { return _manager.GetValue(nameof(IsAutoRefreshEnabled)); } 101 | set 102 | { 103 | _manager.SetValue(nameof(IsAutoRefreshEnabled), value); 104 | RaisePropertyChanged(nameof(IsAutoRefreshEnabled)); 105 | } 106 | } 107 | 108 | public bool IsExternalMediaPlayerAllowed 109 | { 110 | get { return _manager.GetValue(nameof(IsExternalMediaPlayerAllowed)); } 111 | set 112 | { 113 | _manager.SetValue(nameof(IsExternalMediaPlayerAllowed), value); 114 | RaisePropertyChanged(nameof(IsExternalMediaPlayerAllowed)); 115 | } 116 | } 117 | 118 | public bool IsExternalMediaPlayerControlsHidden 119 | { 120 | get { return _manager.GetValue(nameof(IsExternalMediaPlayerControlsHidden)); } 121 | set 122 | { 123 | _manager.SetValue(nameof(IsExternalMediaPlayerControlsHidden), value); 124 | RaisePropertyChanged(nameof(IsExternalMediaPlayerControlsHidden)); 125 | } 126 | } 127 | 128 | public bool IsExternalMediaPlayerFullScreen 129 | { 130 | get { return _manager.GetValue(nameof(IsExternalMediaPlayerFullScreen)); } 131 | set 132 | { 133 | _manager.SetValue(nameof(IsExternalMediaPlayerFullScreen), value); 134 | RaisePropertyChanged(nameof(IsExternalMediaPlayerFullScreen)); 135 | } 136 | } 137 | 138 | public bool IsAutoPauseEnabled 139 | { 140 | get { return _manager.GetValue(nameof(IsAutoPauseEnabled)); } 141 | set 142 | { 143 | _manager.SetValue(nameof(IsAutoPauseEnabled), value); 144 | RaisePropertyChanged(nameof(IsAutoPauseEnabled)); 145 | } 146 | } 147 | 148 | public bool IsAutoSaveVideosEnabled 149 | { 150 | get { return _manager.GetValue(nameof(IsAutoSaveVideosEnabled)); } 151 | set 152 | { 153 | _manager.SetValue(nameof(IsAutoSaveVideosEnabled), value); 154 | RaisePropertyChanged(nameof(IsAutoSaveVideosEnabled)); 155 | } 156 | } 157 | 158 | public string AutoSaveDirectory 159 | { 160 | get { return _manager.GetValue(nameof(AutoSaveDirectory)); } 161 | set 162 | { 163 | // always end directory name with '\' 164 | if (!string.IsNullOrEmpty(AutoSaveDirectory) && value[value.Length - 1] != (Path.DirectorySeparatorChar)) 165 | value = string.Format("{0}{1}", value, Path.DirectorySeparatorChar); 166 | 167 | _manager.SetValue(nameof(AutoSaveDirectory), value); 168 | RaisePropertyChanged(nameof(AutoSaveDirectory)); 169 | } 170 | } 171 | 172 | public bool IsUrlShown 173 | { 174 | get { return _manager.GetValue(nameof(IsUrlShown)); } 175 | set 176 | { 177 | _manager.SetValue(nameof(IsUrlShown), value); 178 | RaisePropertyChanged(nameof(IsUrlShown)); 179 | } 180 | } 181 | 182 | #endregion 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using System.Windows; 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("Chaturbate Cams Viewer")] 9 | [assembly: AssemblyDescription("Enjoying Chaturbate Live Cams Redefined")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Chaturbate Cams Viewer")] 13 | [assembly: AssemblyCopyright("Copyright © 2018 Rubal Walia. All rights reserved.")] 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 | //In order to begin building localizable applications, set 23 | //CultureYouAreCodingWith in your .csproj file 24 | //inside a . For example, if you are using US english 25 | //in your source files, set the to en-US. Then uncomment 26 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 27 | //the line below to match the UICulture setting in the project file. 28 | 29 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 30 | 31 | 32 | [assembly: ThemeInfo( 33 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 34 | //(used if a resource is not found in the page, 35 | // or application resource dictionaries) 36 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 37 | //(used if a resource is not found in the page, 38 | // app, or any theme specific resource dictionaries) 39 | )] 40 | 41 | 42 | // Version information for an assembly consists of the following four values: 43 | // 44 | // Major Version 45 | // Minor Version 46 | // Build Number 47 | // Revision 48 | // 49 | // You can specify all the values or you can default the Build and Revision Numbers 50 | // by using the '*' as shown below: 51 | // [assembly: AssemblyVersion("1.0.*")] 52 | [assembly: AssemblyVersion("0.0.0.0")] 53 | [assembly: AssemblyFileVersion("0.0.0.0")] 54 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Shared.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.Models; 2 | using NullVoidCreations.WpfHelpers; 3 | using System; 4 | using System.IO; 5 | using System.Reflection; 6 | 7 | namespace ChaturbatePlayer 8 | { 9 | class Shared 10 | { 11 | public const string ENCRYPTION_KEY = "QFByb3Blcl9QYXRvbGEhMjAxNQ=="; 12 | 13 | static object _syncRoot; 14 | static Shared _instance; 15 | 16 | SettingsManager _settingsManager; 17 | string _settingsFile, _libVlcPath, _dataPath; 18 | AssemblyInformation _info; 19 | SettingsModel _settings; 20 | 21 | #region constructor 22 | 23 | static Shared() 24 | { 25 | _syncRoot = new object(); 26 | } 27 | 28 | private Shared() 29 | { 30 | 31 | } 32 | 33 | #endregion 34 | 35 | #region properties 36 | 37 | public static Shared Instance 38 | { 39 | get 40 | { 41 | lock(_syncRoot) 42 | { 43 | if (_instance == null) 44 | _instance = new Shared(); 45 | 46 | return _instance; 47 | } 48 | } 49 | } 50 | 51 | public LicenseModel License { get; set; } 52 | 53 | public SettingsModel Settings 54 | { 55 | get 56 | { 57 | if (_settings == null) 58 | { 59 | _settingsManager = new SettingsManager(); 60 | _settingsManager.Load(SettingsFile, ENCRYPTION_KEY); 61 | 62 | _settings = new SettingsModel(ref _settingsManager); 63 | } 64 | 65 | return _settings; 66 | } 67 | } 68 | 69 | public AssemblyInformation Information 70 | { 71 | get 72 | { 73 | if (_info == null) 74 | _info = new AssemblyInformation(Assembly.GetExecutingAssembly()); 75 | 76 | return _info; 77 | } 78 | } 79 | 80 | string SettingsFile 81 | { 82 | get 83 | { 84 | if (_settingsFile == null) 85 | _settingsFile = Path.Combine(DataPath, string.Format("{0}.setting", Information.Product)); 86 | 87 | return _settingsFile; 88 | } 89 | } 90 | 91 | public string LibVlcPath 92 | { 93 | get 94 | { 95 | if (_libVlcPath == null) 96 | _libVlcPath = Path.Combine(DataPath, "VLC"); 97 | 98 | return _libVlcPath; 99 | } 100 | } 101 | 102 | public string DataPath 103 | { 104 | get 105 | { 106 | if (_dataPath == null) 107 | _dataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Information.Product); 108 | 109 | return _dataPath; 110 | } 111 | } 112 | 113 | #endregion 114 | 115 | public void SaveSettings() 116 | { 117 | _settingsManager.Save(SettingsFile, ENCRYPTION_KEY); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/VLC.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/ChaturbatePlayer/ChaturbatePlayer/VLC.zip -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/ViewModels/ChatRoomsViewModel.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.Base; 2 | using ChaturbatePlayer.Models; 3 | using HtmlAgilityPack; 4 | using NullVoidCreations.WpfHelpers.Base; 5 | using NullVoidCreations.WpfHelpers.Commands; 6 | using NullVoidCreations.WpfHelpers.Helpers; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel; 10 | using System.Net; 11 | using System.Timers; 12 | using System.Windows; 13 | using System.Windows.Input; 14 | 15 | namespace ChaturbatePlayer.ViewModels 16 | { 17 | public enum NavigationDirection: byte 18 | { 19 | Forward, 20 | Backward, 21 | Refresh 22 | } 23 | 24 | public class ChatRoomsViewModel: ViewModelBase, IMediator 25 | { 26 | ICommand _getChatRooms, _getVideoFeed; 27 | 28 | Gender _gender; 29 | IList _chatRooms; 30 | ChatRoomModel _selectedRoom; 31 | Timer _refreshTimer; 32 | volatile int _page; 33 | 34 | const string CHATURBATE = "https://www.chaturbate.com"; 35 | const string HOST = "chaturbate.com"; 36 | 37 | #region constructor/destructor 38 | 39 | public ChatRoomsViewModel() 40 | { 41 | _refreshTimer = new Timer(); 42 | _refreshTimer.Elapsed += RefreshTimer_Elapsed; 43 | 44 | Settings.PropertyChanged += Settings_Changed; 45 | 46 | ResetRefreshTimer(); 47 | } 48 | 49 | ~ChatRoomsViewModel() 50 | { 51 | _refreshTimer.Elapsed -= RefreshTimer_Elapsed; 52 | _refreshTimer.Dispose(); 53 | 54 | Settings.PropertyChanged -= Settings_Changed; 55 | } 56 | 57 | #endregion 58 | 59 | #region properties 60 | 61 | public int Page 62 | { 63 | get { return _page; } 64 | private set 65 | { 66 | _page = value; 67 | RaisePropertyChanged(nameof(Page)); 68 | } 69 | } 70 | 71 | public SettingsModel Settings 72 | { 73 | get { return Shared.Instance.Settings; } 74 | } 75 | 76 | public IList ChatRooms 77 | { 78 | get { return _chatRooms; } 79 | set 80 | { 81 | _chatRooms = value; 82 | RaisePropertyChanged(nameof(ChatRooms)); 83 | } 84 | } 85 | 86 | public Gender RoomsGender 87 | { 88 | get { return _gender; } 89 | set 90 | { 91 | _gender = value; 92 | RaisePropertyChanged(nameof(RoomsGender)); 93 | } 94 | } 95 | 96 | public ChatRoomModel SelectedRoom 97 | { 98 | get { return _selectedRoom; } 99 | set 100 | { 101 | _selectedRoom = value; 102 | RaisePropertyChanged(nameof(SelectedRoom)); 103 | Mediator.Instance.RaiseNotification(this, NotificationType.ChatRoomSelected, SelectedRoom); 104 | } 105 | } 106 | 107 | #endregion 108 | 109 | #region commands 110 | 111 | public ICommand GetChatRoomsCommand 112 | { 113 | get 114 | { 115 | if (_getChatRooms == null) 116 | _getChatRooms = new RelayCommand>(GetChatRooms, GetChatRoomsCallback); 117 | 118 | return _getChatRooms; 119 | } 120 | } 121 | 122 | public ICommand GetVideoFeedUrlCommand 123 | { 124 | get 125 | { 126 | if (_getVideoFeed == null) 127 | _getVideoFeed = new RelayCommand(GetVideoFeedUrl); 128 | 129 | return _getVideoFeed; 130 | } 131 | } 132 | 133 | #endregion 134 | 135 | void RefreshTimer_Elapsed(object sender, ElapsedEventArgs e) 136 | { 137 | Application.Current.Dispatcher.BeginInvoke(new Action(() => GetChatRoomsCommand.Execute(NavigationDirection.Refresh))); 138 | } 139 | 140 | void ResetRefreshTimer() 141 | { 142 | if (_refreshTimer.Enabled) 143 | _refreshTimer.Stop(); 144 | 145 | if (Shared.Instance.Settings.IsAutoRefreshEnabled) 146 | { 147 | _refreshTimer.Interval = Shared.Instance.Settings.RefreshInterval * 60 * 1000; 148 | _refreshTimer.Start(); 149 | } 150 | } 151 | 152 | void Settings_Changed(object sender, PropertyChangedEventArgs e) 153 | { 154 | switch (e.PropertyName) 155 | { 156 | case "RefreshInterval": 157 | case "IsAutoRefreshEnabled": 158 | ResetRefreshTimer(); 159 | break; 160 | } 161 | 162 | } 163 | 164 | void GetChatRoomsCallback(IList chatRooms) 165 | { 166 | ChatRooms = chatRooms; 167 | RaisePropertyChanged(nameof(Page)); 168 | } 169 | 170 | IList GetChatRooms(NavigationDirection parameter) 171 | { 172 | var chatRooms = new List(); 173 | 174 | switch (parameter) 175 | { 176 | case NavigationDirection.Forward: 177 | Page += 1; 178 | break; 179 | 180 | case NavigationDirection.Backward: 181 | if (Page > 1) 182 | Page -= 1; 183 | break; 184 | 185 | case NavigationDirection.Refresh: 186 | default: 187 | if (Page == 0) 188 | Page = 1; 189 | break; 190 | } 191 | 192 | var url = string.Format("{0}/?page={1}", CHATURBATE, Page); 193 | switch (RoomsGender) 194 | { 195 | case Gender.Male: 196 | url = string.Format("{0}/male-cams/?page={1}", CHATURBATE, Page); 197 | break; 198 | 199 | case Gender.Female: 200 | url = string.Format("{0}/female-cams/?page={1}", CHATURBATE, Page); 201 | break; 202 | 203 | case Gender.Couple: 204 | url = string.Format("{0}/couple-cams/?page={1}", CHATURBATE, Page); 205 | break; 206 | 207 | case Gender.Trans: 208 | url = string.Format("{0}/trans-cams/?page={1}", CHATURBATE, Page); 209 | break; 210 | } 211 | 212 | string html; 213 | using (var client = new ExtendedWebClient()) 214 | { 215 | client.Host = HOST; 216 | try 217 | { 218 | html = client.DownloadString(new Uri(url, UriKind.Absolute)); 219 | } 220 | catch (WebException) 221 | { 222 | return chatRooms; 223 | } 224 | } 225 | 226 | var parser = new HtmlDocument(); 227 | parser.LoadHtml(html); 228 | 229 | HtmlNode tempNode; 230 | foreach (var node in parser.DocumentNode.SelectNodes("//ul[@class='list']/li")) 231 | { 232 | tempNode = node.SelectSingleNode("./a/img[@class='png']"); 233 | var profileImageUrl = tempNode.Attributes["src"].Value; 234 | var profileImageHeight = int.Parse(tempNode.Attributes["height"].Value); 235 | var profileImageWidth = int.Parse(tempNode.Attributes["width"].Value); 236 | 237 | tempNode = node.SelectSingleNode("./div[contains(@class,'thumbnail_label')]"); 238 | var isVideoFeedHd = tempNode.InnerText.Equals("HD", StringComparison.InvariantCultureIgnoreCase); 239 | 240 | tempNode = node.SelectSingleNode("./div/ul[@class='subject']/li"); 241 | var title = tempNode.Attributes["title"].Value; 242 | 243 | tempNode = node.SelectSingleNode("./div[@class='details']/div[@class='title']/a"); 244 | var name = tempNode.InnerText.Trim(); 245 | var profileUrl = string.Format("{0}{1}", CHATURBATE, tempNode.Attributes["href"].Value); 246 | 247 | tempNode = node.SelectSingleNode("./div[@class='details']/div[@class='title']/span[contains(@class,'age')]"); 248 | int.TryParse(tempNode.InnerText, out int age); 249 | var genderString = tempNode.Attributes["class"].Value; 250 | Gender gender; 251 | if (genderString.Contains("genderm")) 252 | gender = Gender.Male; 253 | else if (genderString.Contains("genderf")) 254 | gender = Gender.Female; 255 | else if (genderString.Contains("genderc")) 256 | gender = Gender.Couple; 257 | else 258 | gender = Gender.Trans; 259 | 260 | tempNode = node.SelectSingleNode("./div[@class='details']/ul[@class='sub-info']/li[@class='cams']"); 261 | var cams = tempNode.InnerText; 262 | 263 | var chatRoom = new ChatRoomModel(name, age, gender, title, profileUrl, profileImageUrl, profileImageHeight, profileImageWidth); 264 | chatRoom.IsVideoFeedHd = isVideoFeedHd; 265 | chatRoom.CamsCount = cams; 266 | chatRooms.Add(chatRoom); 267 | } 268 | 269 | return chatRooms; 270 | } 271 | 272 | void GetVideoFeedUrl(ChatRoomModel parameter) 273 | { 274 | if (parameter == null) 275 | return; 276 | 277 | if (string.IsNullOrEmpty(parameter.VideoFeedUrl)) 278 | { 279 | const string VIDEO_URL_START = "initHlsPlayer(jsplayer, '"; 280 | const string VIDEO_URL_END = "');"; 281 | 282 | using (var webClient = new ExtendedWebClient()) 283 | { 284 | string html; 285 | try 286 | { 287 | html = webClient.DownloadString(new Uri(parameter.ProfileUrl, UriKind.Absolute)); 288 | } 289 | catch (WebException) 290 | { 291 | return; 292 | } 293 | 294 | if (string.IsNullOrEmpty(html)) 295 | return; 296 | 297 | var start = html.IndexOf(VIDEO_URL_START); 298 | if (start > -1) 299 | { 300 | var end = html.IndexOf(VIDEO_URL_END, start + VIDEO_URL_START.Length); 301 | var url = html.Substring(start + VIDEO_URL_START.Length, end - start - VIDEO_URL_START.Length); 302 | parameter.VideoFeedUrl = url; 303 | SelectedRoom = parameter; 304 | } 305 | } 306 | } 307 | else 308 | SelectedRoom = parameter; 309 | 310 | } 311 | 312 | public void NotificationReceived(NotificationType type, params object[] data) 313 | { 314 | // do nothing 315 | } 316 | } 317 | } 318 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/ViewModels/LicenseKeyGeneratorViewModel.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.Models; 2 | using NullVoidCreations.WpfHelpers.Base; 3 | using NullVoidCreations.WpfHelpers.Commands; 4 | using System.Windows.Input; 5 | 6 | namespace ChaturbatePlayer.ViewModels 7 | { 8 | public class LicenseKeyGeneratorViewModel : ViewModelBase 9 | { 10 | LicenseModel _license; 11 | ICommand _generateLicense; 12 | 13 | #region properties 14 | 15 | public LicenseModel License 16 | { 17 | get 18 | { 19 | if (_license == null) 20 | _license = new LicenseModel(); 21 | 22 | return _license; 23 | } 24 | } 25 | 26 | #endregion 27 | 28 | #region commands 29 | 30 | public ICommand GenerateLicenseCommand 31 | { 32 | get 33 | { 34 | if (_generateLicense == null) 35 | _generateLicense = new RelayCommand(GenerateLicense); 36 | 37 | return _generateLicense; 38 | } 39 | } 40 | 41 | #endregion 42 | 43 | void GenerateLicense(int daysToAdd) 44 | { 45 | if (License == null) 46 | return; 47 | 48 | License.Generate(License.RegisteredEmail, License.IssueDate, daysToAdd); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/ViewModels/LiveStreamPlayerViewModel.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.Base; 2 | using ChaturbatePlayer.Models; 3 | using Microsoft.Win32; 4 | using NullVoidCreations.WpfHelpers.Base; 5 | using NullVoidCreations.WpfHelpers.Commands; 6 | using System; 7 | using System.Diagnostics; 8 | using System.IO; 9 | using System.Text; 10 | using System.Windows.Input; 11 | 12 | namespace ChaturbatePlayer.ViewModels 13 | { 14 | public enum LiveStreamPlayerState : byte 15 | { 16 | Play, 17 | Playing, 18 | Pause, 19 | Paused, 20 | Stop, 21 | Stopped, 22 | ExternalMediaPlayer 23 | } 24 | 25 | public class LiveStreamPlayerViewModel : ViewModelBase, IMediator 26 | { 27 | ICommand _toggleMute, _playerCommand; 28 | LiveStreamPlayerState _state; 29 | ChatRoomModel _selectedRoom; 30 | bool _isMuted; 31 | 32 | public LiveStreamPlayerViewModel() 33 | { 34 | Mediator.Instance.RegisterColleague(this); 35 | } 36 | 37 | #region commands 38 | 39 | public ICommand PlayerCommand 40 | { 41 | get 42 | { 43 | if (_playerCommand == null) 44 | _playerCommand = new RelayCommand(Player); 45 | 46 | return _playerCommand; 47 | } 48 | } 49 | 50 | public ICommand ToggleMuteCommand 51 | { 52 | get 53 | { 54 | if (_toggleMute == null) 55 | _toggleMute = new RelayCommand(ToggleMute); 56 | 57 | return _toggleMute; 58 | } 59 | } 60 | 61 | #endregion 62 | 63 | #region properties 64 | 65 | public LiveStreamPlayerState State 66 | { 67 | get { return _state; } 68 | set 69 | { 70 | _state = value; 71 | RaisePropertyChanged(nameof(State)); 72 | } 73 | } 74 | 75 | public bool IsMuted 76 | { 77 | get { return _isMuted; } 78 | set 79 | { 80 | _isMuted = value; 81 | RaisePropertyChanged(nameof(IsMuted)); 82 | } 83 | } 84 | 85 | public SettingsModel Settings 86 | { 87 | get { return Shared.Instance.Settings; } 88 | } 89 | 90 | public ChatRoomModel SelectedRoom 91 | { 92 | get { return _selectedRoom; } 93 | set 94 | { 95 | if (value == _selectedRoom) 96 | return; 97 | 98 | _selectedRoom = value; 99 | RaisePropertyChanged(nameof(SelectedRoom)); 100 | State = LiveStreamPlayerState.Play; 101 | } 102 | } 103 | 104 | #endregion 105 | 106 | string GetWmpExecutablePath() 107 | { 108 | using (var view = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)) 109 | { 110 | using (var key = view.OpenSubKey(@"Software\Microsoft\Active Setup\Installed Components\{22d6f312-b0f6-11d0-94ab-0080c74c7e95}", false)) 111 | { 112 | if ((int)key.GetValue("IsInstalled") == 1) 113 | return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Windows Media Player\wmplayer.exe"); 114 | else 115 | return string.Empty; 116 | } 117 | } 118 | } 119 | 120 | string GetVlcExecutablePath() 121 | { 122 | using (var view = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)) 123 | { 124 | using (var key = view.OpenSubKey(@"Software\VideoLAN\VLC\", false)) 125 | { 126 | if (key == null) 127 | return Path.Combine(Shared.Instance.LibVlcPath, "vlc.exe"); 128 | else 129 | return key.GetValue(string.Empty).ToString(); 130 | } 131 | } 132 | } 133 | 134 | void PlayVideoFeed(ChatRoomModel chatRoom) 135 | { 136 | string playerPath, arguments; 137 | 138 | var useVlc = "VLC".Equals(Settings.MediaPlayer); 139 | if (useVlc) 140 | { 141 | playerPath = GetVlcExecutablePath(); 142 | 143 | var VlcArgumentsBuilder = new StringBuilder(); 144 | 145 | // hide controls 146 | if (Settings.IsExternalMediaPlayerControlsHidden) 147 | VlcArgumentsBuilder.Append(" --qt-minimal-view"); 148 | 149 | // full screen 150 | if (Settings.IsExternalMediaPlayerFullScreen) 151 | VlcArgumentsBuilder.Append(" --fullscreen"); 152 | 153 | // show URL in title bar 154 | if (!Settings.IsUrlShown) 155 | VlcArgumentsBuilder.AppendFormat(" --meta-title=\"{0}\"", chatRoom.Name); 156 | 157 | // video feed URL 158 | VlcArgumentsBuilder.AppendFormat(" {0}", chatRoom.VideoFeedUrl); 159 | 160 | // recording options 161 | if (Settings.IsAutoSaveVideosEnabled) 162 | { 163 | var videoDirectory = Settings.AutoSaveDirectory; 164 | if (string.IsNullOrEmpty(videoDirectory)) 165 | videoDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos); 166 | if (Directory.Exists(videoDirectory)) 167 | VlcArgumentsBuilder.AppendFormat(" --sout=\"#duplicate{{dst=std{{access=file,dst='{0}{1}.mp4'}},dst=display}}\"", videoDirectory, chatRoom.Name); 168 | } 169 | 170 | arguments = VlcArgumentsBuilder.ToString().Trim(); 171 | } 172 | else 173 | { 174 | playerPath = GetWmpExecutablePath(); 175 | arguments = string.Format("\"{0}\"", chatRoom.VideoFeedUrl, chatRoom.Name); 176 | } 177 | 178 | if (string.IsNullOrEmpty(playerPath) || string.IsNullOrEmpty(arguments)) 179 | return; 180 | 181 | var process = new Process(); 182 | process.StartInfo.FileName = playerPath; 183 | process.StartInfo.Arguments = arguments; 184 | process.Start(); 185 | } 186 | 187 | void Player(LiveStreamPlayerState state) 188 | { 189 | if (SelectedRoom == null) 190 | return; 191 | 192 | switch (state) 193 | { 194 | case LiveStreamPlayerState.Play: 195 | State = LiveStreamPlayerState.Play; 196 | break; 197 | 198 | case LiveStreamPlayerState.Pause: 199 | State = LiveStreamPlayerState.Pause; 200 | break; 201 | 202 | case LiveStreamPlayerState.Stop: 203 | State = LiveStreamPlayerState.Stop; 204 | break; 205 | 206 | case LiveStreamPlayerState.ExternalMediaPlayer: 207 | State = LiveStreamPlayerState.ExternalMediaPlayer; 208 | PlayVideoFeed(SelectedRoom); 209 | break; 210 | } 211 | } 212 | 213 | void ToggleMute() 214 | { 215 | IsMuted = !IsMuted; 216 | } 217 | 218 | public void NotificationReceived(NotificationType type, params object[] data) 219 | { 220 | switch(type) 221 | { 222 | case NotificationType.TabPageChanged: 223 | if (Shared.Instance.Settings.IsAutoPauseEnabled) 224 | { 225 | var index = (int)data[0]; 226 | if (index == 5 && (State == LiveStreamPlayerState.Paused || State == LiveStreamPlayerState.Pause)) 227 | State = LiveStreamPlayerState.Play; 228 | else if (index != 5 && State == LiveStreamPlayerState.Playing) 229 | State = LiveStreamPlayerState.Pause; 230 | } 231 | break; 232 | 233 | case NotificationType.ChatRoomSelected: 234 | SelectedRoom = (ChatRoomModel)data[0]; 235 | break; 236 | } 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/ViewModels/MainWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.Base; 2 | using ChaturbatePlayer.Models; 3 | using NullVoidCreations.WpfHelpers.Base; 4 | 5 | namespace ChaturbatePlayer.ViewModels 6 | { 7 | public class MainWindowViewModel: ViewModelBase, IMediator 8 | { 9 | ChatRoomModel _selectedRoom; 10 | int _selectedTabIndex; 11 | 12 | public MainWindowViewModel() 13 | { 14 | SelectedRoom = null; 15 | SelectedTabIndex = 0; 16 | 17 | Mediator.Instance.RegisterColleague(this); 18 | } 19 | 20 | #region properties 21 | 22 | public Gender Featured 23 | { 24 | get { return Gender.NotSpecified; } 25 | } 26 | 27 | public Gender Female 28 | { 29 | get { return Gender.Female; } 30 | } 31 | 32 | public Gender Male 33 | { 34 | get { return Gender.Male; } 35 | } 36 | 37 | public Gender Couple 38 | { 39 | get { return Gender.Couple; } 40 | } 41 | 42 | public Gender Trans 43 | { 44 | get { return Gender.Trans; } 45 | } 46 | 47 | public LicenseModel License 48 | { 49 | get { return Shared.Instance.License; } 50 | } 51 | 52 | public ChatRoomModel SelectedRoom 53 | { 54 | get { return _selectedRoom; } 55 | set 56 | { 57 | if (value == _selectedRoom) 58 | return; 59 | 60 | _selectedRoom = value; 61 | RaisePropertyChanged(nameof(SelectedRoom)); 62 | SelectedTabIndex = 5; 63 | } 64 | } 65 | 66 | public int SelectedTabIndex 67 | { 68 | get { return _selectedTabIndex; } 69 | set 70 | { 71 | if (value == _selectedTabIndex) 72 | return; 73 | 74 | _selectedTabIndex = value; 75 | RaisePropertyChanged(nameof(SelectedTabIndex)); 76 | Mediator.Instance.RaiseNotification(this, NotificationType.TabPageChanged, _selectedTabIndex); 77 | } 78 | } 79 | 80 | #endregion 81 | 82 | public void NotificationReceived(NotificationType type, params object[] data) 83 | { 84 | switch(type) 85 | { 86 | case NotificationType.ChatRoomSelected: 87 | SelectedRoom = (ChatRoomModel)data[0]; 88 | break; 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/ViewModels/SettingsViewModel.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.Models; 2 | using NullVoidCreations.WpfHelpers.Base; 3 | using NullVoidCreations.WpfHelpers.Commands; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Windows.Forms; 8 | using System.Windows.Input; 9 | 10 | namespace ChaturbatePlayer.ViewModels 11 | { 12 | public class SettingsViewModel: ViewModelBase 13 | { 14 | ICommand _selectDirectory; 15 | 16 | IEnumerable _mediaPlayers; 17 | IEnumerable _refreshIntervals; 18 | 19 | #region properties 20 | 21 | public IEnumerable MediaPlayers 22 | { 23 | get 24 | { 25 | if (_mediaPlayers == null) 26 | _mediaPlayers = new List { "VLC", "Windows" }; 27 | 28 | return _mediaPlayers; 29 | } 30 | } 31 | 32 | public IEnumerable RefreshIntervals 33 | { 34 | get 35 | { 36 | if (_refreshIntervals == null) 37 | { 38 | var refreshIntervals = new List(); 39 | for (var interval = 2; interval <= 15; interval += 2) 40 | refreshIntervals.Add(interval); 41 | _refreshIntervals = refreshIntervals; 42 | } 43 | 44 | return _refreshIntervals; 45 | } 46 | 47 | } 48 | 49 | public string ProductName 50 | { 51 | get { return Shared.Instance.Information.ProductTitle; } 52 | } 53 | 54 | public string ProductDescription 55 | { 56 | get { return Shared.Instance.Information.Description; } 57 | } 58 | 59 | public string ProductCopyright 60 | { 61 | get { return Shared.Instance.Information.Copyright; } 62 | } 63 | 64 | public Version ProductVersion 65 | { 66 | get { return Shared.Instance.Information.Version; } 67 | } 68 | 69 | public SettingsModel Settings 70 | { 71 | get { return Shared.Instance.Settings; } 72 | } 73 | 74 | public LicenseModel License 75 | { 76 | get { return Shared.Instance.License; } 77 | } 78 | 79 | #endregion 80 | 81 | #region commands 82 | 83 | public ICommand SelectDirectoryCommand 84 | { 85 | get 86 | { 87 | if (_selectDirectory == null) 88 | _selectDirectory = new RelayCommand(SelectDirectory) { IsSynchronous = true }; 89 | 90 | return _selectDirectory; 91 | 92 | } 93 | } 94 | 95 | #endregion 96 | 97 | void SelectDirectory(string dialogDescription) 98 | { 99 | if (dialogDescription == null) 100 | dialogDescription = "Please select a directory below and click OK."; 101 | 102 | var dialog = new FolderBrowserDialog(); 103 | dialog.Description = dialogDescription; 104 | dialog.ShowNewFolderButton = true; 105 | if (dialog.ShowDialog() == DialogResult.OK) 106 | Settings.AutoSaveDirectory = dialog.SelectedPath.EndsWith(Path.DirectorySeparatorChar.ToString()) ? dialog.SelectedPath : string.Format("{0}{1}", dialog.SelectedPath, Path.DirectorySeparatorChar); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/ViewModels/SplashViewModel.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.Base; 2 | using NullVoidCreations.WpfHelpers; 3 | using NullVoidCreations.WpfHelpers.Base; 4 | using NullVoidCreations.WpfHelpers.Commands; 5 | using System; 6 | using System.IO; 7 | using System.IO.Compression; 8 | using System.Windows; 9 | using System.Windows.Input; 10 | 11 | namespace ChaturbatePlayer.ViewModels 12 | { 13 | public class SplashViewModel: ViewModelBase, IMediator 14 | { 15 | ICommand _initialize; 16 | const string VLC_LIB_ARCHIVE = "VLC.zip"; 17 | 18 | #region properties 19 | 20 | public string ProductName 21 | { 22 | get { return Shared.Instance.Information.Product; } 23 | } 24 | 25 | public string ProductDescription 26 | { 27 | get { return Shared.Instance.Information.Description; } 28 | } 29 | 30 | public string ProductCopyright 31 | { 32 | get { return Shared.Instance.Information.Copyright; } 33 | } 34 | 35 | public Version ProductVersion 36 | { 37 | get { return Shared.Instance.Information.Version; } 38 | } 39 | 40 | #endregion 41 | 42 | #region commands 43 | 44 | public ICommand InitializeCommand 45 | { 46 | get 47 | { 48 | if (_initialize == null) 49 | _initialize = new RelayCommand(Initialize); 50 | 51 | return _initialize; 52 | } 53 | } 54 | 55 | #endregion 56 | 57 | void Initialize() 58 | { 59 | if (Directory.Exists(Shared.Instance.LibVlcPath)) 60 | { 61 | Mediator.Instance.RaiseNotification(this, NotificationType.Initialized); 62 | return; 63 | } 64 | 65 | var archivePath = Path.Combine(Application.Current.GetStartupDirectory(), VLC_LIB_ARCHIVE); 66 | if (!File.Exists(archivePath)) 67 | { 68 | Application.Current.Shutdown(1); 69 | return; 70 | } 71 | 72 | if (!Directory.Exists(Shared.Instance.DataPath)) 73 | Directory.CreateDirectory(Shared.Instance.DataPath); 74 | 75 | using (var zip = ZipStorer.Open(archivePath, FileAccess.Read)) 76 | { 77 | foreach (ZipStorer.ZipFileEntry zipEntry in zip.ReadCentralDir()) 78 | zip.ExtractFile(zipEntry, Path.Combine(Shared.Instance.DataPath, zipEntry.FilenameInZip)); 79 | } 80 | 81 | Mediator.Instance.RaiseNotification(this, NotificationType.Initialized); 82 | } 83 | 84 | public void NotificationReceived(NotificationType type, params object[] data) 85 | { 86 | // do nothing 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Views/ChatRoomsView.xaml: -------------------------------------------------------------------------------- 1 |  13 | 14 | 15 | 16 | 17 | 18 | 50 | 51 | 52 | 53 | 58 | 59 | 64 | 65 | 66 | 70 | 75 | 76 | 82 | 88 | 94 | 95 | 96 | 97 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 200 | 201 | 206 | 207 | 208 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 226 | 231 | 232 | 233 | 234 | 240 | 241 | 245 | 249 | 253 | 254 | 255 | 261 | 262 | 268 | 269 | 275 | 276 | 277 | 278 | 279 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Views/ChatRoomsView.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ChaturbatePlayer.Views 2 | { 3 | /// 4 | /// Interaction logic for ChatRoomsView.xaml 5 | /// 6 | public partial class ChatRoomsView 7 | { 8 | public ChatRoomsView() 9 | { 10 | InitializeComponent(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Views/LicenseKeyGeneratorWindowView.xaml: -------------------------------------------------------------------------------- 1 |  18 | 19 | 20 | 21 | 22 | 23 | 27 | 31 | 37 | 42 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 69 | 70 | 71 | 76 | 77 | 78 | 83 | 84 | 88 | 95 | 96 | 69 | 76 | 83 | 89 | 97 | 98 | 99 | 105 | 115 | 116 | 117 | 118 | 119 | 120 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Views/LiveStreamPlayerView.xaml.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.Base; 2 | using ChaturbatePlayer.ViewModels; 3 | using System; 4 | using System.IO; 5 | using Vlc.DotNet.Core; 6 | using Vlc.DotNet.Core.Interops.Signatures; 7 | 8 | namespace ChaturbatePlayer.Views 9 | { 10 | public partial class LiveStreamPlayerView: IMediator 11 | { 12 | readonly LiveStreamPlayerViewModel _viewModel; 13 | string _currentVideoUrl; 14 | 15 | public LiveStreamPlayerView() 16 | { 17 | InitializeComponent(); 18 | 19 | Mediator.Instance.RegisterColleague(this); 20 | 21 | _viewModel = DataContext as LiveStreamPlayerViewModel; 22 | _viewModel.State = LiveStreamPlayerState.Stopped; 23 | _viewModel.PropertyChanged += LiveStreamPlayerView_PropertyChanged; 24 | } 25 | 26 | ~LiveStreamPlayerView() 27 | { 28 | //Player.Dispose(); 29 | 30 | _viewModel.PropertyChanged -= LiveStreamPlayerView_PropertyChanged; 31 | } 32 | 33 | void LiveStreamPlayerView_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 34 | { 35 | if (_viewModel.SelectedRoom == null || Player.SourceProvider.MediaPlayer == null) 36 | return; 37 | 38 | if (e.PropertyName.Equals("State")) 39 | { 40 | switch (_viewModel.State) 41 | { 42 | case LiveStreamPlayerState.Play: 43 | ChangePlayerState(_viewModel.SelectedRoom.VideoFeedUrl, LiveStreamPlayerState.Play); 44 | break; 45 | 46 | case LiveStreamPlayerState.Pause: 47 | ChangePlayerState(_viewModel.SelectedRoom.VideoFeedUrl, LiveStreamPlayerState.Pause); 48 | break; 49 | 50 | case LiveStreamPlayerState.Stop: 51 | case LiveStreamPlayerState.ExternalMediaPlayer: 52 | ChangePlayerState(_viewModel.SelectedRoom.VideoFeedUrl, LiveStreamPlayerState.Stop); 53 | break; 54 | } 55 | } 56 | else if (e.PropertyName.Equals("IsMuted")) 57 | { 58 | Player.SourceProvider.MediaPlayer.Audio.IsMute = _viewModel.IsMuted; 59 | } 60 | } 61 | 62 | void MediaPlayer_Stopped(object sender, VlcMediaPlayerStoppedEventArgs e) 63 | { 64 | _viewModel.State = LiveStreamPlayerState.Stopped; 65 | } 66 | 67 | void MediaPlayer_Buffering(object sender, VlcMediaPlayerBufferingEventArgs e) 68 | { 69 | _viewModel.State = LiveStreamPlayerState.Playing; 70 | } 71 | 72 | void MediaPlayer_Opening(object sender, VlcMediaPlayerOpeningEventArgs e) 73 | { 74 | _viewModel.State = LiveStreamPlayerState.Playing; 75 | } 76 | 77 | void MediaPlayer_Playing(object sender, VlcMediaPlayerPlayingEventArgs e) 78 | { 79 | _viewModel.State = LiveStreamPlayerState.Playing; 80 | } 81 | 82 | void MediaPlayer_EncounteredError(object sender, VlcMediaPlayerEncounteredErrorEventArgs e) 83 | { 84 | _viewModel.State = LiveStreamPlayerState.Stopped; 85 | } 86 | 87 | void MediaPlayer_Paused(object sender, VlcMediaPlayerPausedEventArgs e) 88 | { 89 | _viewModel.State = LiveStreamPlayerState.Paused; 90 | } 91 | 92 | void ChangePlayerState(string url, LiveStreamPlayerState state) 93 | { 94 | switch(state) 95 | { 96 | case LiveStreamPlayerState.Play: 97 | if (string.IsNullOrEmpty(url)) 98 | { 99 | if (Player.SourceProvider.MediaPlayer.State == MediaStates.Playing) 100 | Player.SourceProvider.MediaPlayer.Stop(); 101 | _currentVideoUrl = null; 102 | } 103 | else 104 | { 105 | if (_currentVideoUrl == url) 106 | { 107 | if (Player.SourceProvider.MediaPlayer.State == MediaStates.Paused) 108 | Player.SourceProvider.MediaPlayer.Play(); 109 | } 110 | else 111 | { 112 | if (Player.SourceProvider.MediaPlayer.State == MediaStates.Playing) 113 | Player.SourceProvider.MediaPlayer.Stop(); 114 | 115 | Player.SourceProvider.MediaPlayer.Play(new Uri(url, UriKind.Absolute)); 116 | _currentVideoUrl = url; 117 | } 118 | } 119 | 120 | break; 121 | 122 | case LiveStreamPlayerState.ExternalMediaPlayer: 123 | if (Player.SourceProvider.MediaPlayer.State == MediaStates.Playing || Player.SourceProvider.MediaPlayer.State == MediaStates.Paused) 124 | Player.SourceProvider.MediaPlayer.Stop(); 125 | break; 126 | 127 | case LiveStreamPlayerState.Stop: 128 | if (Player.SourceProvider.MediaPlayer.State == MediaStates.Playing || Player.SourceProvider.MediaPlayer.State == MediaStates.Paused) 129 | Player.SourceProvider.MediaPlayer.Stop(); 130 | _currentVideoUrl = null; 131 | break; 132 | 133 | case LiveStreamPlayerState.Pause: 134 | if (Player.SourceProvider.MediaPlayer.State == MediaStates.Playing) 135 | Player.SourceProvider.MediaPlayer.Pause(); 136 | break; 137 | } 138 | } 139 | 140 | public void NotificationReceived(NotificationType type, params object[] data) 141 | { 142 | switch(type) 143 | { 144 | case NotificationType.Initialized: 145 | Player.SourceProvider.CreatePlayer(new DirectoryInfo(Shared.Instance.LibVlcPath)); 146 | Player.SourceProvider.MediaPlayer.Opening += MediaPlayer_Opening; 147 | Player.SourceProvider.MediaPlayer.Buffering += MediaPlayer_Buffering; 148 | Player.SourceProvider.MediaPlayer.Playing += MediaPlayer_Playing; 149 | Player.SourceProvider.MediaPlayer.EncounteredError += MediaPlayer_EncounteredError; 150 | Player.SourceProvider.MediaPlayer.Stopped += MediaPlayer_Stopped; 151 | Player.SourceProvider.MediaPlayer.Paused += MediaPlayer_Paused; 152 | break; 153 | } 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Views/MainWindowView.xaml: -------------------------------------------------------------------------------- 1 |  21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 52 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 191 | 192 | 193 | 194 | 195 | 196 | 200 | 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Views/MainWindowView.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ChaturbatePlayer.Views 2 | { 3 | /// 4 | /// Interaction logic for MainWindow.xaml 5 | /// 6 | public partial class MainWindowView 7 | { 8 | public MainWindowView() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Views/SettingsView.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 47 | 48 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 74 | 75 | 80 | 81 | 82 | 83 | 87 | 91 | 94 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 144 | 145 | 146 | 147 | 148 | 149 | 156 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Views/SettingsView.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace ChaturbatePlayer.Views 2 | { 3 | /// 4 | /// Interaction logic for SettingsView.xaml 5 | /// 6 | public partial class SettingsView 7 | { 8 | public SettingsView() 9 | { 10 | InitializeComponent(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Views/SplashWindowView.xaml: -------------------------------------------------------------------------------- 1 |  19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 53 | 54 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 70 | 71 | 72 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/Views/SplashWindowView.xaml.cs: -------------------------------------------------------------------------------- 1 | using ChaturbatePlayer.Base; 2 | using System; 3 | using System.Windows; 4 | 5 | namespace ChaturbatePlayer.Views 6 | { 7 | /// 8 | /// Interaction logic for SplashWindowView.xaml 9 | /// 10 | public partial class SplashWindowView: IMediator 11 | { 12 | public SplashWindowView() 13 | { 14 | InitializeComponent(); 15 | Mediator.Instance.RegisterColleague(this); 16 | } 17 | 18 | public void NotificationReceived(NotificationType type, params object[] data) 19 | { 20 | switch(type) 21 | { 22 | case NotificationType.Initialized: 23 | var action = (Action)(() => Close()); 24 | Application.Current.Dispatcher.BeginInvoke(action); 25 | break; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/app.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 | 27 | 28 | -------------------------------------------------------------------------------- /ChaturbatePlayer/ChaturbatePlayer/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ChaturbatePlayer 2 | A redefined way to view live cam feeds from chaturbate.com without opening it in web browser. 3 | -------------------------------------------------------------------------------- /Screenshots/Capture0.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/Screenshots/Capture0.PNG -------------------------------------------------------------------------------- /Screenshots/Capture1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/Screenshots/Capture1.PNG -------------------------------------------------------------------------------- /Screenshots/Capture2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliarubal/ChaturbatePlayer/eabc83518e59d49a019cdd24b5d3dfd13848c813/Screenshots/Capture2.PNG --------------------------------------------------------------------------------