Repository: Stealth2012/meridian
Branch: master
Commit: 0b46d1f46add
Files: 340
Total size: 1.7 MB
Directory structure:
gitextract_zxoun8e2/
├── .gitattributes
├── .gitignore
├── .gitmodules
├── .nuget/
│ ├── NuGet.Config
│ └── NuGet.targets
├── LICENSE.txt
├── LastFmLibPortable/
│ └── Trunk/
│ ├── Core/
│ │ ├── Album/
│ │ │ ├── LastFmAlbum.cs
│ │ │ └── LastFmAlbumRequest.cs
│ │ ├── Artist/
│ │ │ ├── LastFmArtist.cs
│ │ │ └── LastFmArtistRequest.cs
│ │ ├── Auth/
│ │ │ ├── LastFmAuthRequest.cs
│ │ │ └── LastFmAuthResult.cs
│ │ ├── Chart/
│ │ │ └── LastFmChartRequest.cs
│ │ ├── CoreRequest.cs
│ │ ├── Image/
│ │ │ └── LastFmImage.cs
│ │ ├── LastFmErrorProcessor.cs
│ │ ├── Tag/
│ │ │ └── LastFmTagRequest.cs
│ │ ├── Track/
│ │ │ ├── LastFmTrack.cs
│ │ │ └── LastFmTrackRequest.cs
│ │ └── User/
│ │ └── LastFmUserRequest.cs
│ ├── Error/
│ │ └── LastFmLoginException.cs
│ ├── Extensions/
│ │ ├── CommonExtensions.cs
│ │ └── StreamExtensions.cs
│ ├── LastFM.cs
│ ├── LastFmConst.cs
│ ├── LastFmLibPortable.csproj
│ ├── LastFmUtils.cs
│ ├── app.config
│ └── project.json
├── Meridian/
│ ├── App.config
│ ├── App.xaml
│ ├── App.xaml.cs
│ ├── Behaviours/
│ │ ├── AutoScrollToCurrentItemBehaviour.cs
│ │ ├── FocusBehaviour.cs
│ │ ├── TransitionBehaviour.cs
│ │ └── VisibilityTransitionBehaviour.cs
│ ├── Controls/
│ │ ├── BindablePasswordBox.cs
│ │ ├── BusyIndicator.cs
│ │ ├── ContentTransitionControl.xaml
│ │ ├── ContentTransitionControl.xaml.cs
│ │ ├── ExtendedListBox.cs
│ │ ├── FlyoutContent.cs
│ │ ├── FlyoutControl.xaml
│ │ ├── FlyoutControl.xaml.cs
│ │ ├── ImageTransitionControl.xaml
│ │ ├── ImageTransitionControl.xaml.cs
│ │ ├── LocalSearchControl.xaml
│ │ ├── LocalSearchControl.xaml.cs
│ │ ├── NotificationControl.xaml
│ │ ├── NotificationControl.xaml.cs
│ │ ├── PageBase.cs
│ │ ├── PlayerControl.xaml
│ │ ├── PlayerControl.xaml.cs
│ │ ├── ShareBarControl.xaml
│ │ ├── ShareBarControl.xaml.cs
│ │ ├── TextBoxWithHint.cs
│ │ ├── VirtualizingWrapPanel.cs
│ │ ├── VolumeControl.xaml
│ │ └── VolumeControl.xaml.cs
│ ├── Converters/
│ │ ├── AlbumContextMenuVisibilityConverter.cs
│ │ ├── AlbumListItemContainerSelector.cs
│ │ ├── AudioTemplateSelector.cs
│ │ ├── AudioTimeSpanConverter.cs
│ │ ├── BooleanToValueConverter.cs
│ │ ├── MainMenuGroupStyleSelector.cs
│ │ └── SearchResultTemplateSelector.cs
│ ├── Domain/
│ │ └── Settings.cs
│ ├── Extensions/
│ │ ├── AudioExtensions.cs
│ │ ├── CommonExtensions.cs
│ │ ├── ListExtensions.cs
│ │ └── SocketExtensions.cs
│ ├── Helpers/
│ │ ├── AlbumCoversHelper.cs
│ │ ├── ArtistImageHelper.cs
│ │ ├── DateTimeConverter.cs
│ │ ├── FilesHelper.cs
│ │ ├── HotKeyManager.cs
│ │ ├── ImageAsyncHelper.cs
│ │ ├── LongRunningOperation.cs
│ │ ├── Md5Helper.cs
│ │ ├── NativeMethods.cs
│ │ ├── NetworkHelper.cs
│ │ └── StringHelper.cs
│ ├── Layout/
│ │ ├── Controls/
│ │ │ ├── HeaderControl.xaml
│ │ │ ├── HeaderControl.xaml.cs
│ │ │ └── PageTabControl.cs
│ │ ├── LayoutBase.cs
│ │ ├── PageBase.cs
│ │ ├── Templates/
│ │ │ ├── PageBaseTemplate.xaml
│ │ │ └── TwoColumnPageLayoutTemplate.xaml
│ │ └── TwoColumnPageLayout.cs
│ ├── MainWindow.xaml
│ ├── MainWindow.xaml.cs
│ ├── Meridian.csproj
│ ├── Model/
│ │ ├── Account.cs
│ │ ├── Audio.cs
│ │ ├── AudioAlbum.cs
│ │ ├── AudioArtist.cs
│ │ ├── AudioPost.cs
│ │ ├── ColorScheme.cs
│ │ ├── ItemsResponse.cs
│ │ ├── MainMenuItem.cs
│ │ ├── NewsItemsResponse.cs
│ │ ├── Recommendation.cs
│ │ ├── SearchMenuItem.cs
│ │ ├── Settings/
│ │ │ ├── SettingsEngine.cs
│ │ │ ├── SettingsHotKey.cs
│ │ │ └── SettingsLanguage.cs
│ │ └── UIMode.cs
│ ├── Properties/
│ │ ├── Resources.Designer.cs
│ │ ├── Resources.resx
│ │ ├── Settings.Designer.cs
│ │ └── Settings.settings
│ ├── RemotePlay/
│ │ ├── RemotePlayService.cs
│ │ ├── SimpleHttpRequest.cs
│ │ ├── SimpleHttpResponse.cs
│ │ ├── SimpleWebServer.cs
│ │ └── web/
│ │ ├── index.html
│ │ ├── js/
│ │ │ ├── index.js
│ │ │ └── utils.js
│ │ ├── lib/
│ │ │ └── svg4everybody.js
│ │ └── styles/
│ │ ├── index.css
│ │ └── player.css
│ ├── Resources/
│ │ ├── Localization/
│ │ │ ├── ErrorResources.Designer.cs
│ │ │ ├── ErrorResources.resx
│ │ │ ├── ErrorResources.ru.resx
│ │ │ ├── MainResources.Designer.cs
│ │ │ ├── MainResources.resx
│ │ │ └── MainResources.ru.resx
│ │ ├── Styles/
│ │ │ ├── Animations.xaml
│ │ │ ├── AudioControlStyles.xaml
│ │ │ ├── ButtonStyles.xaml
│ │ │ ├── CheckBoxStyles.xaml
│ │ │ ├── ComboBoxStyles.xaml
│ │ │ ├── ContextMenuStyles.xaml
│ │ │ ├── DataTemplates.xaml
│ │ │ ├── ExpanderStyles.xaml
│ │ │ ├── Icons.xaml
│ │ │ ├── ListBoxStyles.xaml
│ │ │ ├── ProgressBarStyles.xaml
│ │ │ ├── ScrollbarStyles.xaml
│ │ │ ├── SliderStyles.xaml
│ │ │ ├── Styles.xaml
│ │ │ ├── TabControlStyles.xaml
│ │ │ ├── TextBoxStyles.xaml
│ │ │ └── WindowButtons.xaml
│ │ └── Themes/
│ │ ├── Accent.xaml
│ │ ├── Accents/
│ │ │ ├── Blue.xaml
│ │ │ ├── Emerald.xaml
│ │ │ ├── Magenta.xaml
│ │ │ ├── Mango.xaml
│ │ │ ├── Pink.xaml
│ │ │ ├── Purple.xaml
│ │ │ ├── Red.xaml
│ │ │ ├── Sea.xaml
│ │ │ └── Sky.xaml
│ │ ├── Dark.xaml
│ │ ├── Graphite.xaml
│ │ └── Light.xaml
│ ├── SQLite.cs
│ ├── SQLiteAsync.cs
│ ├── Services/
│ │ ├── AccountManager.cs
│ │ ├── CacheService.cs
│ │ ├── DataBaseService.cs
│ │ ├── DataService.cs
│ │ ├── HostService.cs
│ │ ├── LoggingService.cs
│ │ ├── Media/
│ │ │ ├── AudioService.cs
│ │ │ └── Core/
│ │ │ ├── MediaPlayerBase.cs
│ │ │ ├── NaudioMediaPlayer.cs
│ │ │ ├── UwpMediaPlayer.cs
│ │ │ └── WmpMediaPlayer.cs
│ │ ├── Music/
│ │ │ ├── LocalMusicService.cs
│ │ │ └── Repositories/
│ │ │ ├── LocalAlbumsRepository.cs
│ │ │ ├── LocalArtistsRepository.cs
│ │ │ └── LocalTracksRepository.cs
│ │ ├── NotificationService.cs
│ │ ├── ServiceLocator.cs
│ │ └── UpdateService.cs
│ ├── View/
│ │ ├── Compact/
│ │ │ ├── CompactLandscapeView.xaml
│ │ │ ├── CompactLandscapeView.xaml.cs
│ │ │ ├── CompactView.xaml
│ │ │ └── CompactView.xaml.cs
│ │ ├── Flyouts/
│ │ │ ├── AddSocietyFlyout.xaml
│ │ │ ├── AddSocietyFlyout.xaml.cs
│ │ │ ├── AddToAlbumView.xaml
│ │ │ ├── AddToAlbumView.xaml.cs
│ │ │ ├── CaptchaRequestView.xaml
│ │ │ ├── CaptchaRequestView.xaml.cs
│ │ │ ├── CommonErrorView.xaml
│ │ │ ├── CommonErrorView.xaml.cs
│ │ │ ├── CommonMessageView.xaml
│ │ │ ├── CommonMessageView.xaml.cs
│ │ │ ├── EditAlbumView.xaml
│ │ │ ├── EditAlbumView.xaml.cs
│ │ │ ├── EditAudioView.xaml
│ │ │ ├── EditAudioView.xaml.cs
│ │ │ ├── Local/
│ │ │ │ ├── MusicScanView.xaml
│ │ │ │ └── MusicScanView.xaml.cs
│ │ │ ├── LoginLastFmMessageView.xaml
│ │ │ ├── LoginLastFmMessageView.xaml.cs
│ │ │ ├── LoginLastFmView.xaml
│ │ │ ├── LoginLastFmView.xaml.cs
│ │ │ ├── LyricsView.xaml
│ │ │ ├── LyricsView.xaml.cs
│ │ │ ├── ShareView.xaml
│ │ │ ├── ShareView.xaml.cs
│ │ │ ├── TellFriendsRequestView.xaml
│ │ │ ├── TellFriendsRequestView.xaml.cs
│ │ │ ├── TellResultView.xaml
│ │ │ ├── TellResultView.xaml.cs
│ │ │ ├── WebValidationView.xaml
│ │ │ └── WebValidationView.xaml.cs
│ │ ├── Local/
│ │ │ ├── LocalAlbumView.xaml
│ │ │ ├── LocalAlbumView.xaml.cs
│ │ │ ├── LocalCollectionView.xaml
│ │ │ └── LocalCollectionView.xaml.cs
│ │ ├── Main/
│ │ │ ├── FeedView.xaml
│ │ │ ├── FeedView.xaml.cs
│ │ │ ├── LoginView.xaml
│ │ │ ├── LoginView.xaml.cs
│ │ │ ├── MusicView.xaml
│ │ │ ├── MusicView.xaml.cs
│ │ │ ├── NowPlayingView.xaml
│ │ │ ├── NowPlayingView.xaml.cs
│ │ │ ├── PopularAudioView.xaml
│ │ │ ├── PopularAudioView.xaml.cs
│ │ │ ├── RecommendationsView.xaml
│ │ │ └── RecommendationsView.xaml.cs
│ │ ├── People/
│ │ │ ├── FriendsAudioView.xaml
│ │ │ ├── FriendsAudioView.xaml.cs
│ │ │ ├── FriendsView.xaml
│ │ │ ├── FriendsView.xaml.cs
│ │ │ ├── SocietiesView.xaml
│ │ │ ├── SocietiesView.xaml.cs
│ │ │ ├── SocietyAudioView.xaml
│ │ │ ├── SocietyAudioView.xaml.cs
│ │ │ ├── SubscriptionsView.xaml
│ │ │ └── SubscriptionsView.xaml.cs
│ │ ├── Search/
│ │ │ ├── AlbumView.xaml
│ │ │ ├── AlbumView.xaml.cs
│ │ │ ├── ArtistAlbumsView.xaml
│ │ │ ├── ArtistAlbumsView.xaml.cs
│ │ │ ├── ArtistAudioView.xaml
│ │ │ ├── ArtistAudioView.xaml.cs
│ │ │ ├── ArtistView.xaml
│ │ │ ├── ArtistView.xaml.cs
│ │ │ ├── SearchResultsView.xaml
│ │ │ └── SearchResultsView.xaml.cs
│ │ ├── Settings/
│ │ │ ├── SettingsAboutView.xaml
│ │ │ ├── SettingsAboutView.xaml.cs
│ │ │ ├── SettingsAccountsView.xaml
│ │ │ ├── SettingsAccountsView.xaml.cs
│ │ │ ├── SettingsHotkeysView.xaml
│ │ │ ├── SettingsHotkeysView.xaml.cs
│ │ │ ├── SettingsRemotePlayView.xaml
│ │ │ ├── SettingsRemotePlayView.xaml.cs
│ │ │ ├── SettingsUIView.xaml
│ │ │ ├── SettingsUIView.xaml.cs
│ │ │ ├── SettingsUpdatesView.xaml
│ │ │ ├── SettingsUpdatesView.xaml.cs
│ │ │ ├── SettingsView.xaml
│ │ │ └── SettingsView.xaml.cs
│ │ ├── TrackNotifcationView.xaml
│ │ └── TrackNotifcationView.xaml.cs
│ └── ViewModel/
│ ├── Flyouts/
│ │ ├── EditAudioViewModel.cs
│ │ ├── LoginLastFmViewModel.cs
│ │ ├── LyricsViewModel.cs
│ │ └── ShareViewModel.cs
│ ├── Local/
│ │ ├── LocalAlbumViewModel.cs
│ │ └── LocalMusicViewModel.cs
│ ├── Main/
│ │ ├── FeedViewModel.cs
│ │ ├── LoginViewModel.cs
│ │ ├── MusicViewModel.cs
│ │ ├── NowPlayingViewModel.cs
│ │ ├── PopularAudioViewModel.cs
│ │ └── RecommendationsViewModel.cs
│ ├── MainViewModel.cs
│ ├── Messages/
│ │ ├── CurrentAudioChangedMessage.cs
│ │ ├── LocalRepositoryUpdatedMessage.cs
│ │ ├── LoginMessage.cs
│ │ ├── PlayStateChangedMessage.cs
│ │ ├── PlayerPositionChangedMessage.cs
│ │ └── UserTracksChangedMessage.cs
│ ├── People/
│ │ ├── FriendAudioViewModel.cs
│ │ ├── FriendsViewModel.cs
│ │ ├── SocietiesViewModel.cs
│ │ ├── SocietyAudioViewModel.cs
│ │ └── SubscriptionsViewModel.cs
│ ├── Search/
│ │ ├── AlbumViewModel.cs
│ │ ├── ArtistViewModel.cs
│ │ └── SearchViewModel.cs
│ ├── SettingsViewModel.cs
│ ├── ViewModelBase.cs
│ └── ViewModelLocator.cs
├── Meridian.Core/
│ └── Services/
│ └── AccountsService.cs
├── MeridianDesktop.sln
├── Neptune/
│ └── Trunk/
│ ├── Neptune.Base/
│ │ ├── Collections/
│ │ │ └── IAsyncCollection.cs
│ │ ├── Extensions/
│ │ │ ├── CommonExtensions.cs
│ │ │ └── StreamExtensions.cs
│ │ ├── Helpers/
│ │ │ └── TaskQueue.cs
│ │ ├── Messages/
│ │ │ ├── GoHomeMessage.cs
│ │ │ └── NavigateToPageMessage.cs
│ │ ├── Neptune.Base.csproj
│ │ ├── Properties/
│ │ │ └── AssemblyInfo.cs
│ │ ├── Storage/
│ │ │ └── IFileStorage.cs
│ │ ├── View/
│ │ │ └── IVisualViewModel.cs
│ │ ├── app.config
│ │ └── project.json
│ ├── Neptune.Desktop/
│ │ ├── Behaviours/
│ │ │ ├── IgnoreMouseWheelBehavior.cs
│ │ │ ├── TriggerTransitionBehaviour.cs
│ │ │ ├── UpdateTextBindingOnPropertyChanged.cs
│ │ │ └── VisiblityTransitionBehaviour.cs
│ │ ├── Converters/
│ │ │ ├── BooleanToObjectConverter.cs
│ │ │ ├── BooleanToVisibilityConverter.cs
│ │ │ ├── InvertBooleanConverter.cs
│ │ │ ├── NullToBooleanConverter.cs
│ │ │ ├── NullToVisibilityConverter.cs
│ │ │ ├── StringToUpperConverter.cs
│ │ │ └── TimeSpanConverter.cs
│ │ ├── Domain/
│ │ │ └── AppSettings.cs
│ │ ├── Extensions/
│ │ │ └── VisualTreeHelperExtensions.cs
│ │ ├── Neptune.Desktop.csproj
│ │ └── Storage/
│ │ └── FileStorage.cs
│ └── Neptune.UI.Desktop/
│ ├── Behaviours/
│ │ ├── IgnoreMouseWheelBehavior.cs
│ │ ├── TriggerTransitionBehaviour.cs
│ │ ├── UpdateTextBindingOnPropertyChanged.cs
│ │ └── VisiblityTransitionBehaviour.cs
│ ├── Converters/
│ │ ├── BooleanToObjectConverter.cs
│ │ ├── BooleanToVisibilityConverter.cs
│ │ ├── InvertBooleanConverter.cs
│ │ ├── NullToBooleanConverter.cs
│ │ ├── NullToVisibilityConverter.cs
│ │ ├── StringToUpperConverter.cs
│ │ └── TimeSpanConverter.cs
│ ├── Extensions/
│ │ └── VisualTreeHelperExtensions.cs
│ ├── Neptune.UI.Desktop.csproj
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ └── packages.config
├── README.md
└── refs/
└── GongSolutions.Wpf.DragDrop.XML
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
.idea/
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
## TODO: Comment the next line if you want to checkin your
## web deploy settings but do note that will include unencrypted
## passwords
#*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# LightSwitch generated files
GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml
================================================
FILE: .gitmodules
================================================
[submodule "VkLib"]
path = VkLib
url = https://github.com/artemshuba/VkLib.git
================================================
FILE: .nuget/NuGet.Config
================================================
================================================
FILE: .nuget/NuGet.targets
================================================
$(MSBuildProjectDirectory)\..\falsefalsetruefalse$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))$(SolutionDir).nuget$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config$(MSBuildProjectDirectory)\packages.config$(PackagesProjectConfig)$(NuGetToolsPath)\NuGet.exe@(PackageSource)"$(NuGetExePath)"mono --runtime=v4.0.30319 "$(NuGetExePath)"$(TargetDir.Trim('\\'))-RequireConsent-NonInteractive"$(SolutionDir) ""$(SolutionDir)"$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols
RestorePackages;
$(BuildDependsOn);
$(BuildDependsOn);
BuildPackage;
================================================
FILE: LICENSE.txt
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2014 Artem Shuba
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: LastFmLibPortable/Trunk/Core/Album/LastFmAlbum.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using LastFmLib.Core.Track;
using Newtonsoft.Json.Linq;
namespace LastFmLib.Core.Album
{
public class LastFmAlbum
{
public string Mbid { get; set; }
public string Name { get; set; }
public string Artist { get; set; }
public string ImageSmall { get; set; }
public string ImageMedium { get; set; }
public string ImageLarge { get; set; }
public string ImageExtraLarge { get; set; }
public string ImageMega { get; set; }
public List Tracks { get; set; }
public List TopTags { get; set; }
public static LastFmAlbum FromJson(JToken json)
{
if (json == null)
throw new ArgumentException("Json can not be null.");
var result = new LastFmAlbum();
if (json["mbid"] != null)
result.Mbid = json["mbid"].Value();
result.Name = json["name"].Value();
if (json["artist"] != null)
{
if (!json["artist"].HasValues)
result.Artist = json["artist"].Value();
else
{
result.Artist = json["artist"]["name"].Value();
}
}
var imageToken = json["image"];
if (imageToken != null)
{
foreach (var image in imageToken.Children())
{
switch (image["size"].Value())
{
case "small":
result.ImageSmall = image["#text"].Value();
break;
case "medium":
result.ImageMedium = image["#text"].Value();
break;
case "large":
result.ImageLarge = image["#text"].Value();
break;
case "extralarge":
result.ImageExtraLarge = image["#text"].Value();
break;
}
}
}
if (json.SelectToken("tracks.track") != null)
{
result.Tracks = new List();
var trackJson = json.SelectToken("tracks.track");
if (trackJson is JArray)
result.Tracks.AddRange((from a in trackJson select LastFmTrack.FromJson(a)).ToList());
else
result.Tracks.Add(LastFmTrack.FromJson(trackJson));
}
if (json.SelectToken("toptags.tag") != null)
{
result.TopTags = new List();
foreach (var tagToken in json.SelectToken("toptags.tag"))
{
if (tagToken is JProperty)
result.TopTags.Add(((JProperty)tagToken).Value.Value());
else
result.TopTags.Add(tagToken["name"].Value());
}
}
return result;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/Album/LastFmAlbumRequest.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace LastFmLib.Core.Album
{
public class LastFmAlbumRequest
{
private readonly LastFm _lastFm;
public LastFmAlbumRequest(LastFm lastFm)
{
_lastFm = lastFm;
}
public async Task> Search(string album)
{
var parameters = new Dictionary();
parameters.Add("album", album);
parameters.Add("api_key", _lastFm.ApiKey);
var response = await (new CoreRequest(new Uri(LastFmConst.MethodBase + "album.search"), parameters).Execute());
LastFmErrorProcessor.ProcessError(response);
if (response.SelectToken("results.albummatches.album") != null)
{
var albumJson = response.SelectToken("results.albummatches.album");
if (albumJson is JArray)
return
(from a in response.SelectToken("results.albummatches.album") select LastFmAlbum.FromJson(a)).ToList();
else
return new List() { LastFmAlbum.FromJson(albumJson) };
}
return null;
}
public async Task GetInfo(string mbid, string album, string artist, bool autoCorrect = true)
{
var parameters = new Dictionary();
if (!string.IsNullOrEmpty(mbid))
parameters.Add("mbid", mbid);
else
{
parameters.Add("album", album);
parameters.Add("artist", artist);
}
if (autoCorrect)
parameters.Add("autocorrect", "1");
parameters.Add("api_key", _lastFm.ApiKey);
var response = await (new CoreRequest(new Uri(LastFmConst.MethodBase + "album.getInfo"), parameters).Execute());
LastFmErrorProcessor.ProcessError(response);
if (response["album"] != null)
{
return LastFmAlbum.FromJson(response["album"]);
}
return null;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/Artist/LastFmArtist.cs
================================================
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
namespace LastFmLib.Core.Artist
{
public class LastFmArtist
{
public string Name { get; set; }
public string Mbid { get; set; }
public string ImageSmall { get; set; }
public string ImageMedium { get; set; }
public string ImageLarge { get; set; }
public string ImageExtraLarge { get; set; }
public string ImageMega { get; set; }
public List TopTags { get; set; }
public List SimilarArtists { get; set; }
public string Bio { get; set; }
public static LastFmArtist FromJson(JToken json)
{
if (json == null)
throw new ArgumentException("Json can not be null.");
var result = new LastFmArtist();
result.Name = json["name"].Value();
if (json["mbid"] != null)
result.Mbid = json["mbid"].Value();
var imageToken = json["image"];
if (imageToken != null)
{
foreach (var image in imageToken.Children())
{
if (image["#text"] == null)
continue;
switch (image["size"].Value())
{
case "small":
result.ImageSmall = image["#text"].Value();
break;
case "medium":
result.ImageMedium = image["#text"].Value();
break;
case "large":
result.ImageLarge = image["#text"].Value();
break;
case "extralarge":
result.ImageExtraLarge = image["#text"].Value();
break;
case "mega":
result.ImageMega = image["#text"].Value();
break;
}
}
}
if (json.SelectToken("tags.tag") != null)
{
result.TopTags = new List();
var tagToken = json.SelectToken("tags.tag");
if (tagToken is JArray)
{
foreach (var t in tagToken)
{
result.TopTags.Add(t["name"].Value());
}
}
else
{
result.TopTags.Add(tagToken["name"].Value());
}
}
if (json.SelectToken("similar.artist") != null)
{
result.SimilarArtists = new List();
var similarToken = json.SelectToken("similar.artist");
if (similarToken is JArray)
{
foreach (var artistToken in similarToken)
{
result.SimilarArtists.Add(FromJson(artistToken));
}
}
else
{
result.SimilarArtists.Add(FromJson(similarToken));
}
}
if (json.SelectToken("bio.summary") != null)
{
result.Bio = json.SelectToken("bio.summary").Value().Trim();
}
return result;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/Artist/LastFmArtistRequest.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LastFmLib.Core.Album;
using LastFmLib.Core.Image;
using LastFmLib.Core.Track;
using Newtonsoft.Json.Linq;
namespace LastFmLib.Core.Artist
{
public class LastFmArtistRequest
{
private readonly LastFm _lastFm;
public LastFmArtistRequest(LastFm lastFm)
{
_lastFm = lastFm;
}
[Obsolete("Last.FM no longer provides method artist.getImages.", true)]
public async Task> GetImages(string artist, string mbid, int limit, bool autoCorrect = true, int minWidth = 500, int minHeight = 200)
{
var parameters = new Dictionary();
if (!string.IsNullOrEmpty(mbid))
parameters.Add("mbid", mbid);
else
parameters.Add("artist", artist);
if (autoCorrect)
parameters.Add("autocorrect", "1");
if (limit > 0)
parameters.Add("limit", limit.ToString());
parameters.Add("api_key", _lastFm.ApiKey);
var response = await (new CoreRequest(new Uri(LastFmConst.MethodBase + "artist.getImages"), parameters).Execute());
LastFmErrorProcessor.ProcessError(response);
if (response["images"] != null && response["images"]["image"] != null)
{
var ie = new List();
foreach (var image in response["images"]["image"])
{
ie.Add(LastFmImage.FromJson(image));
}
return ie;
}
return null;
}
public async Task> Search(string artist)
{
var parameters = new Dictionary();
parameters.Add("artist", artist);
parameters.Add("api_key", _lastFm.ApiKey);
var response = await (new CoreRequest(new Uri(LastFmConst.MethodBase + "artist.search"), parameters).Execute());
LastFmErrorProcessor.ProcessError(response);
if (response.SelectToken("results.artistmatches.artist") != null)
{
var artistJson = response.SelectToken("results.artistmatches.artist");
if (artistJson is JArray)
return (from a in response.SelectToken("results.artistmatches.artist")
select LastFmArtist.FromJson(a)).ToList();
else
return new List() { LastFmArtist.FromJson(artistJson) };
}
return null;
}
public async Task> GetSimilar(string artist, int count = 0)
{
var parameters = new Dictionary();
parameters.Add("artist", artist);
if (count > 0)
parameters.Add("limit", count.ToString());
parameters.Add("api_key", _lastFm.ApiKey);
var response = await (new CoreRequest(new Uri(LastFmConst.MethodBase + "artist.getSimilar"), parameters).Execute());
LastFmErrorProcessor.ProcessError(response);
if (response.SelectToken("similarartists.artist") != null)
{
return (from a in response.SelectToken("similarartists.artist") select LastFmArtist.FromJson(a)).ToList();
}
return null;
}
public async Task> GetTopAlbums(string mbid, string artist, int count = 0)
{
var parameters = new Dictionary();
if (!string.IsNullOrEmpty(mbid))
parameters.Add("mbid", mbid);
else
parameters.Add("artist", artist);
if (count > 0)
parameters.Add("limit", count.ToString());
parameters.Add("api_key", _lastFm.ApiKey);
var response = await (new CoreRequest(new Uri(LastFmConst.MethodBase + "artist.getTopAlbums"), parameters).Execute());
LastFmErrorProcessor.ProcessError(response);
if (response.SelectToken("topalbums.album") != null)
{
var albumToken = response.SelectToken("topalbums.album");
if (albumToken.GetType() == typeof(JArray))
return (from a in albumToken select LastFmAlbum.FromJson(a)).ToList();
else if (albumToken.GetType() == typeof(JObject))
{
var result = new List();
result.Add(LastFmAlbum.FromJson(albumToken));
return result;
}
}
return null;
}
public async Task> GetTopTracks(string mbid, string artist, int count = 0)
{
var parameters = new Dictionary();
if (!string.IsNullOrEmpty(mbid))
parameters.Add("mbid", mbid);
else
parameters.Add("artist", artist);
if (count > 0)
parameters.Add("limit", count.ToString());
parameters.Add("api_key", _lastFm.ApiKey);
var response = await (new CoreRequest(new Uri(LastFmConst.MethodBase + "artist.getTopTracks"), parameters).Execute());
LastFmErrorProcessor.ProcessError(response);
if (response.SelectToken("toptracks.track") != null)
{
var tracksJson = response.SelectToken("toptracks.track");
if (tracksJson is JArray)
return (from a in tracksJson select LastFmTrack.FromJson(a)).ToList();
else
return new List() { LastFmTrack.FromJson(tracksJson) };
}
return null;
}
public async Task GetInfo(string mbid, string artist)
{
var parameters = new Dictionary();
if (!string.IsNullOrEmpty(mbid))
parameters.Add("mbid", mbid);
else
parameters.Add("artist", artist);
if (!string.IsNullOrEmpty(_lastFm.Lang))
parameters.Add("lang", _lastFm.Lang);
parameters.Add("api_key", _lastFm.ApiKey);
var response = await (new CoreRequest(new Uri(LastFmConst.MethodBase + "artist.getInfo"), parameters).Execute());
LastFmErrorProcessor.ProcessError(response);
if (response["artist"] != null)
{
return LastFmArtist.FromJson(response["artist"]);
}
return null;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/Auth/LastFmAuthRequest.cs
================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LastFmLib.Core.Auth
{
public class LastFmAuthRequest
{
private readonly LastFm _lastFm;
public LastFmAuthRequest(LastFm lastFm)
{
_lastFm = lastFm;
}
public async Task GetMobileSession(string username, string password)
{
var parameters = new Dictionary();
parameters.Add("username", username);
parameters.Add("password", password);
parameters.Add("api_key", _lastFm.ApiKey);
parameters.Add("api_sig", LastFmUtils.BuildSig(_lastFm.ApiSecret, "auth.getMobileSession", parameters));
var response = await new CoreRequest(new Uri(LastFmConst.MethodBaseSecure), null, "POST", parameters).Execute();
if (!LastFmErrorProcessor.ProcessError(response))
return null;
if (response["session"] != null)
{
return LastFmAuthResult.FromJson(response["session"]);
}
return null;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/Auth/LastFmAuthResult.cs
================================================
using System;
using Newtonsoft.Json.Linq;
namespace LastFmLib.Core.Auth
{
public class LastFmAuthResult
{
public string Username { get; set; }
public string Key { get; set; }
public static LastFmAuthResult FromJson(JToken json)
{
if (json == null)
throw new ArgumentException("Json can not be null.");
var result = new LastFmAuthResult();
result.Username = json["name"].Value();
result.Key = json["key"].Value();
return result;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/Chart/LastFmChartRequest.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LastFmLib.Core.Track;
namespace LastFmLib.Core.Chart
{
public class LastFmChartRequest
{
private readonly LastFm _lastFm;
public LastFmChartRequest(LastFm lastFm)
{
_lastFm = lastFm;
}
public async Task> GetTopTracks(int count = 0)
{
var parameters = new Dictionary();
if (count > 0)
parameters.Add("limit", count.ToString());
parameters.Add("api_key", _lastFm.ApiKey);
var response = await (new CoreRequest(new Uri(LastFmConst.MethodBase + "chart.getTopTracks"), parameters).Execute());
LastFmErrorProcessor.ProcessError(response);
if (response.SelectToken("tracks.track") != null)
{
return from a in response.SelectToken("tracks.track") select LastFmTrack.FromJson(a);
}
return null;
}
public async Task> GetHypedTracks(int count = 0)
{
var parameters = new Dictionary();
if (count > 0)
parameters.Add("limit", count.ToString());
parameters.Add("api_key", _lastFm.ApiKey);
var response = await (new CoreRequest(new Uri(LastFmConst.MethodBase + "chart.getHypedTracks"), parameters).Execute());
LastFmErrorProcessor.ProcessError(response);
if (response.SelectToken("tracks.track") != null)
{
return from a in response.SelectToken("tracks.track") select LastFmTrack.FromJson(a);
}
return null;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/CoreRequest.cs
================================================
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using LastFmLib.Extensions;
using Newtonsoft.Json.Linq;
using System.Net.NetworkInformation;
namespace LastFmLib.Core
{
///
/// An object that performs request to server
///
internal class CoreRequest
{
private readonly Uri _uri;
private readonly string _method;
private readonly Dictionary _parameters;
private readonly Dictionary _postParameters;
public CoreRequest(Uri uri)
{
_uri = uri;
_method = "GET";
}
public CoreRequest(Uri uri, Dictionary parameters, string method = "GET", Dictionary postParameters = null)
{
_uri = uri;
_method = method;
_parameters = parameters;
_postParameters = postParameters;
}
public async Task Execute()
{
if (!NetworkInterface.GetIsNetworkAvailable())
throw new Exception("Network is not available.");
var uri = GetFullUri(_parameters);
var request = WebRequest.CreateHttp(uri);
request.Method = _method;
Debug.WriteLine("Invoking " + uri);
JObject response = null;
var httpClient = new HttpClient();
if (_method == "GET")
{
HttpResponseMessage responseMessage = await httpClient.GetAsync(uri);
string content = await responseMessage.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
response = JObject.Parse(content);
}
else if (_method == "POST")
{
var postContent = new StringContent(_postParameters.ConstructQueryString());
postContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
HttpResponseMessage responseMessage = await httpClient.PostAsync(uri, postContent);
string content = await responseMessage.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
response = JObject.Parse(content);
}
return response;
}
private Uri GetFullUri(Dictionary parameters)
{
if (parameters != null && parameters.Count > 0)
{
var paramStr = string.Join("&",
parameters.Select(
kp => string.Format("{0}={1}", Uri.EscapeDataString(kp.Key), Uri.EscapeDataString(kp.Value))));
return new Uri(string.Concat(_uri, "&", paramStr));
}
return _uri;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/Image/LastFmImage.cs
================================================
using System;
using System.Diagnostics;
using Newtonsoft.Json.Linq;
namespace LastFmLib.Core.Image
{
public class LastFmImage
{
public double Width { get; set; }
public double Height { get; set; }
public double OriginalWidth { get; set; }
public double OriginalHeight { get; set; }
public string Original { get; set; }
public string Large { get; set; }
public string LargeSquare { get; set; }
public string Medium { get; set; }
public string Small { get; set; }
public string ExtraLarge { get; set; }
internal static LastFmImage FromJson(JToken json)
{
if (json == null)
throw new ArgumentException("Json can not be null.");
var result = new LastFmImage();
var sizeToken = json.SelectToken("sizes.size");
if (sizeToken != null)
{
foreach (var size in sizeToken.Children())
{
switch (size["name"].Value())
{
case "small":
result.Small = size["#text"].Value();
result.Width = Convert.ToDouble(size["width"].Value());
result.Height = Convert.ToDouble(size["height"].Value());
break;
case "medium":
result.Medium = size["#text"].Value();
result.Width = Convert.ToDouble(size["width"].Value());
result.Height = Convert.ToDouble(size["height"].Value());
break;
case "large":
result.Large = size["#text"].Value();
result.Width = Convert.ToDouble(size["width"].Value());
result.Height = Convert.ToDouble(size["height"].Value());
break;
case "extralarge":
result.ExtraLarge = size["#text"].Value();
result.Width = Convert.ToDouble(size["width"].Value());
result.Height = Convert.ToDouble(size["height"].Value());
break;
case "original":
result.Original = size["#text"].Value();
result.Width = Convert.ToDouble(size["width"].Value());
result.Height = Convert.ToDouble(size["height"].Value());
result.OriginalWidth = Convert.ToDouble(size["width"].Value());
result.OriginalHeight = Convert.ToDouble(size["height"].Value());
break;
}
}
}
return result;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/LastFmErrorProcessor.cs
================================================
using System.Diagnostics;
using LastFmLib.Error;
using Newtonsoft.Json.Linq;
namespace LastFmLib.Core
{
internal static class LastFmErrorProcessor
{
public static bool ProcessError(JToken response)
{
if (response["error"] != null)
{
Debug.WriteLine("Last FM: " + response["message"].Value());
switch (response["error"].Value())
{
case "9":
case "4": //login error
throw new LastFmLoginException();
case "6": //artist not found
return false;
}
return false;
}
return true;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/Tag/LastFmTagRequest.cs
================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using LastFmLib.Core.Track;
using System.Linq;
namespace LastFmLib.Core.Tag
{
public class LastFmTagRequest
{
private readonly LastFm _lastFm;
public LastFmTagRequest(LastFm lastFm)
{
_lastFm = lastFm;
}
public async Task> GetTopTracks(string tag, int limit = 20, int page = 0)
{
var parameters = new Dictionary();
parameters.Add("tag", tag);
if (limit > 0)
parameters.Add("limit", limit.ToString());
if (page > 0)
parameters.Add("page", page.ToString());
parameters.Add("api_key", _lastFm.ApiKey);
var response = await new CoreRequest(new Uri(LastFmConst.MethodBase + "tag.getTopTracks"), parameters).Execute();
LastFmErrorProcessor.ProcessError(response);
if (response.SelectToken("tracks.track") != null)
{
return from t in response.SelectToken("tracks.track") select LastFmTrack.FromJson(t);
}
return null;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/Track/LastFmTrack.cs
================================================
using System;
using Newtonsoft.Json.Linq;
namespace LastFmLib.Core.Track
{
public class LastFmTrack
{
public string Id { get; set; }
public string Title { get; set; }
public int Duration { get; set; }
public string Artist { get; set; }
public string Album { get; set; }
public string ImageSmall { get; set; }
public string ImageMedium { get; set; }
public string ImageLarge { get; set; }
public string ImageExtraLarge { get; set; }
public string ImageMega { get; set; }
internal static LastFmTrack FromJson(JToken json)
{
if (json == null)
throw new ArgumentException("Json can not be null.");
var result = new LastFmTrack();
if (json["name"] != null)
result.Title = json["name"].Value();
if (json["artist"] != null)
{
if (json.SelectToken("artist.name") != null)
result.Artist = json["artist"]["name"].Value();
else
result.Artist = json["artist"].Value();
}
if (json["duration"] != null && !string.IsNullOrEmpty(json["duration"].Value()))
{
result.Duration = json["duration"].Value();
}
if (json["album"] != null)
{
result.Album = json["album"]["title"].Value();
var imageToken = json["album"]["image"];
if (imageToken != null)
{
foreach (var image in imageToken.Children())
{
switch (image["size"].Value())
{
case "small":
result.ImageSmall = image["#text"].Value();
break;
case "medium":
result.ImageMedium = image["#text"].Value();
break;
case "large":
result.ImageLarge = image["#text"].Value();
break;
case "extralarge":
result.ImageExtraLarge = image["#text"].Value();
break;
}
}
}
}
var imgToken = json["image"];
if (imgToken != null)
{
foreach (var image in imgToken.Children())
{
switch (image["size"].Value())
{
case "small":
result.ImageSmall = image["#text"].Value();
break;
case "medium":
result.ImageMedium = image["#text"].Value();
break;
case "large":
result.ImageLarge = image["#text"].Value();
break;
case "extralarge":
result.ImageExtraLarge = image["#text"].Value();
break;
}
}
}
return result;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/Track/LastFmTrackRequest.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace LastFmLib.Core.Track
{
public class LastFmTrackRequest
{
private readonly LastFm _lastFm;
public LastFmTrackRequest(LastFm lastFm)
{
_lastFm = lastFm;
}
public async Task GetInfo(string title, string artist, bool autoCorrect = true, string mbid = null)
{
var parameters = new Dictionary();
if (!string.IsNullOrEmpty(mbid))
parameters.Add("mbid", mbid);
else
{
parameters.Add("artist", artist);
parameters.Add("track", title);
}
if (autoCorrect)
parameters.Add("autocorrect", "1");
parameters.Add("api_key", _lastFm.ApiKey);
var response = await new CoreRequest(new Uri(LastFmConst.MethodBase + "track.getInfo"), parameters).Execute();
LastFmErrorProcessor.ProcessError(response);
if (response["track"] != null)
{
return LastFmTrack.FromJson(response["track"]);
}
return null;
}
public async Task UpdateNowPlaying(string artist, string track, string mbid = null, int duration = 0,
string album = null, int trackNumber = -1, string albumArtist = null)
{
const string method = "track.updateNowPlaying";
var parameters = new Dictionary();
parameters.Add("artist", artist);
parameters.Add("track", track);
if (album != null)
parameters.Add("album", album);
if (trackNumber > -1)
parameters.Add("trackNumber", trackNumber.ToString());
if (mbid != null)
parameters.Add("mbid", mbid);
if (duration > 0)
parameters.Add("duration", duration.ToString());
if (albumArtist != null)
parameters.Add("albumArtist", albumArtist);
parameters.Add("api_key", _lastFm.ApiKey);
parameters.Add("sk", _lastFm.SessionKey);
parameters.Add("api_sig", LastFmUtils.BuildSig(_lastFm.ApiSecret, method, parameters));
parameters["track"] = Uri.EscapeDataString(track); //fix ampersand scrobbling
parameters["artist"] = Uri.EscapeDataString(artist); //fix ampersand scrobbling
var response = await new CoreRequest(new Uri(LastFmConst.UrlBaseSecure), null, "POST", parameters).Execute();
LastFmErrorProcessor.ProcessError(response);
}
public async Task Scrobble(string artist, string track, string timeStamp, string mbid = null, int duration = 0,
string album = null, int trackNumber = -1, string albumArtist = null)
{
const string method = "track.scrobble";
var parameters = new Dictionary();
parameters.Add("artist", artist);
parameters.Add("track", track);
parameters.Add("timestamp", timeStamp);
if (album != null)
parameters.Add("album", album);
if (trackNumber > -1)
parameters.Add("trackNumber", trackNumber.ToString());
if (mbid != null)
parameters.Add("mbid", mbid);
if (albumArtist != null)
parameters.Add("albumArtist", albumArtist);
if (duration > 0)
parameters.Add("duration", duration.ToString());
parameters.Add("api_key", _lastFm.ApiKey);
parameters.Add("sk", _lastFm.SessionKey);
parameters.Add("api_sig", LastFmUtils.BuildSig(_lastFm.ApiSecret, method, parameters));
parameters["track"] = Uri.EscapeDataString(track); //fix ampersand scrobbling
parameters["artist"] = Uri.EscapeDataString(artist); //fix ampersand scrobbling
var response = await new CoreRequest(new Uri(LastFmConst.UrlBaseSecure), null, "POST", parameters).Execute();
LastFmErrorProcessor.ProcessError(response);
}
public async Task> Search(string track, string artist)
{
var parameters = new Dictionary();
parameters.Add("track", track);
if (!string.IsNullOrEmpty(artist))
parameters.Add("artist", artist);
parameters.Add("api_key", _lastFm.ApiKey);
var response = await new CoreRequest(new Uri(LastFmConst.MethodBase + "track.search"), parameters).Execute();
LastFmErrorProcessor.ProcessError(response);
if (response.SelectToken("results.trackmatches.track") != null)
{
var trackJson = response.SelectToken("results.trackmatches.track");
if (trackJson is JArray)
return (from t in response.SelectToken("results.trackmatches.track")
select LastFmTrack.FromJson(t)).ToList();
else
return new List() { LastFmTrack.FromJson(trackJson) };
}
return null;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Core/User/LastFmUserRequest.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LastFmLib.Core.Artist;
namespace LastFmLib.Core.User
{
public class LastFmUserRequest
{
private readonly LastFm _lastFm;
public LastFmUserRequest(LastFm lastFm)
{
_lastFm = lastFm;
}
public async Task> GetRecommendedArtists(int count = 0)
{
var parameters = new Dictionary();
if (count > 0)
parameters.Add("limit", count.ToString());
parameters.Add("api_key", _lastFm.ApiKey);
parameters.Add("sk", _lastFm.SessionKey);
parameters.Add("api_sig", LastFmUtils.BuildSig(_lastFm.ApiSecret, "user.getRecommendedArtists", parameters));
var response = await new CoreRequest(new Uri(LastFmConst.UrlBase), parameters, "POST").Execute();
LastFmErrorProcessor.ProcessError(response);
if (response.SelectToken("recommendations.artist") != null)
{
return from a in response.SelectToken("recommendations.artist") select LastFmArtist.FromJson(a);
}
return null;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Error/LastFmLoginException.cs
================================================
using System;
namespace LastFmLib.Error
{
public class LastFmLoginException : Exception
{
}
}
================================================
FILE: LastFmLibPortable/Trunk/Extensions/CommonExtensions.cs
================================================
using System.Collections.Generic;
using System.Linq;
using System.Net;
namespace LastFmLib.Extensions
{
public static class CommonExtensions
{
///
/// Constructs a QueryString (string).
/// Consider this method to be the opposite of "System.Web.HttpUtility.ParseQueryString"
///
/// NameValueCollection
/// string
public static string ConstructQueryString(this Dictionary parameters)
{
return string.Join("&", parameters.Select(pair => pair.Key).Distinct().Select(name => string.Concat(name, "=", WebUtility.HtmlEncode(parameters[name]))).ToArray());
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/Extensions/StreamExtensions.cs
================================================
using System.Diagnostics;
using System.IO;
namespace LastFmLib.Extensions
{
internal static class StreamExtensions
{
public static int CopyStream(this Stream source, Stream dest)
{
Debug.Assert(source != null);
Debug.Assert(dest != null);
var positionSource = source.Position;
var positionDest = dest.Position;
var buffer = new byte[4096];
var read = 0;
var total = 0;
while ((read = source.Read(buffer, 0, buffer.Length)) > 0)
{
total += read;
dest.Write(buffer, 0, read);
}
if (source.CanSeek)
source.Seek(positionSource, SeekOrigin.Begin);
if (dest.CanSeek)
dest.Seek(positionDest, SeekOrigin.Begin);
return total;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/LastFM.cs
================================================
using LastFmLib.Core.Album;
using LastFmLib.Core.Artist;
using LastFmLib.Core.Auth;
using LastFmLib.Core.Chart;
using LastFmLib.Core.Tag;
using LastFmLib.Core.Track;
using LastFmLib.Core.User;
namespace LastFmLib
{
public class LastFm
{
private readonly string _apiKey;
private readonly string _apiSecret;
private LastFmArtistRequest _artist;
private LastFmAlbumRequest _album;
private LastFmTrackRequest _track;
private LastFmChartRequest _chart;
private LastFmAuthRequest _auth;
private LastFmUserRequest _user;
private LastFmTagRequest _tag;
internal string ApiKey
{
get { return _apiKey; }
}
internal string ApiSecret
{
get { return _apiSecret; }
}
public LastFmArtistRequest Artist
{
get
{
if (_artist == null)
_artist = new LastFmArtistRequest(this);
return _artist;
}
}
public LastFmAlbumRequest Album
{
get
{
if (_album == null)
_album = new LastFmAlbumRequest(this);
return _album;
}
}
public LastFmTrackRequest Track
{
get
{
if (_track == null)
_track = new LastFmTrackRequest(this);
return _track;
}
}
public LastFmChartRequest Chart
{
get
{
if (_chart == null)
_chart = new LastFmChartRequest(this);
return _chart;
}
}
public LastFmUserRequest User
{
get
{
if (_user == null)
_user = new LastFmUserRequest(this);
return _user;
}
}
public LastFmTagRequest Tag
{
get
{
if (_tag == null)
_tag = new LastFmTagRequest(this);
return _tag;
}
}
public LastFmAuthRequest Auth
{
get
{
if (_auth == null)
_auth = new LastFmAuthRequest(this);
return _auth;
}
}
public string Lang { get; set; }
public string SessionKey { get; set; }
public LastFm(string apiKey, string apiSecret, string lang = null)
{
_apiKey = apiKey;
_apiSecret = apiSecret;
Lang = lang;
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/LastFmConst.cs
================================================
namespace LastFmLib
{
internal static class LastFmConst
{
internal const string AuthorizationUrlBase = "http://www.last.fm/api/auth/?";
internal const string MethodBase = "http://ws.audioscrobbler.com/2.0/?format=json&method=";
internal const string UrlBase = "http://ws.audioscrobbler.com/2.0/?format=json";
internal const string UrlBaseSecure = "https://ws.audioscrobbler.com/2.0/?format=json";
internal const string MethodBaseSecure = "https://ws.audioscrobbler.com/2.0/?format=json";
}
}
================================================
FILE: LastFmLibPortable/Trunk/LastFmLibPortable.csproj
================================================
netstandard2.01.0.2Artem ShubaLastFmLibLastFmLib
================================================
FILE: LastFmLibPortable/Trunk/LastFmUtils.cs
================================================
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace LastFmLib
{
internal class LastFmUtils
{
public static string BuildSig(string secretKey, string method, IDictionary parameters)
{
parameters.Add("method", method);
var temp = parameters.OrderBy(x => x.Key);
var s = new StringBuilder();
foreach (var p in temp)
{
s.Append(p.Key);
s.Append(p.Value);
}
s.Append(secretKey);
return Md5(s.ToString());
}
public static string Md5(string input)
{
using(var md5 = MD5.Create())
{
return GetMd5Hash(md5, input);
}
}
private static string GetMd5Hash(MD5 md5Hash, string input)
{
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
}
}
================================================
FILE: LastFmLibPortable/Trunk/app.config
================================================
================================================
FILE: LastFmLibPortable/Trunk/project.json
================================================
{
"supports": {
"net46.app": {},
"dnxcore50.app": {}
},
"dependencies": {
"Microsoft.NETCore": "5.0.0",
"Microsoft.NETCore.Portable.Compatibility": "1.0.0"
},
"frameworks": {
"dotnet": {
"imports": "portable-net452"
}
}
}
================================================
FILE: Meridian/App.config
================================================
================================================
FILE: Meridian/App.xaml
================================================
================================================
FILE: Meridian/App.xaml.cs
================================================
using System;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Threading;
using Meridian.Controls;
using Meridian.Domain;
using Meridian.Model;
using Meridian.Resources.Localization;
using Meridian.Services;
using Meridian.View.Flyouts;
using Meridian.ViewModel;
using Yandex.Metrica;
using Application = System.Windows.Application;
namespace Meridian
{
///
/// Interaction logic for App.xaml
///
public partial class App : Application
{
private NotifyIcon _trayIcon;
public static readonly string Root = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
private async void App_OnStartup(object sender, StartupEventArgs e)
{
LoggingService.Log("Meridian v" + Assembly.GetExecutingAssembly().GetName().Version + " started. OS: " + Environment.OSVersion);
//DispatcherHelper.Initialize();
Settings.Load();
if (Settings.Instance.SendStats)
{
YandexMetricaFolder.SetCurrent(Directory.GetCurrentDirectory());
YandexMetrica.Activate("60fb8ba9-ab3c-4ee8-81ac-559c8aeb305e"); //Yandex Metrica
}
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(Settings.Instance.Language);
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;
if (Settings.Instance.Accounts.Count == 0)
{
Settings.Instance.Accounts.Add(new Account() { Id = "vk", Title = MainResources.SettingsAccountsVk });
Settings.Instance.Accounts.Add(new Account() { Id = "lasfm", Title = MainResources.SettingsAccountsLastFm });
}
ServiceLocator.DataBaseService.Initialize();
if (Settings.Instance.NeedClean)
{
ViewModelLocator.UpdateService.Clean();
Settings.Instance.NeedClean = false;
}
switch (Settings.Instance.AccentColor)
{
case "Red":
case "Emerald":
case "Magenta":
case "Mango":
case "Sea":
case "Sky":
case "Purple":
case "Pink":
Resources.MergedDictionaries[0].Source = new Uri(string.Format("/Resources/Themes/Accents/{0}.xaml", Settings.Instance.AccentColor), UriKind.Relative);
break;
default:
Resources.MergedDictionaries[0].Source = new Uri("/Resources/Themes/Accents/Blue.xaml", UriKind.Relative);
break;
}
switch (Settings.Instance.Theme)
{
case "Light":
case "Dark":
case "Graphite":
case "Accent":
Resources.MergedDictionaries[1].Source = new Uri(string.Format("/Resources/Themes/{0}.xaml", Settings.Instance.Theme), UriKind.Relative);
break;
default:
Resources.MergedDictionaries[1].Source = new Uri("/Resources/Themes/Light.xaml", UriKind.Relative);
break;
}
if (Settings.Instance.EnableTrayIcon)
AddTrayIcon();
ViewModelLocator.Vkontakte.UseHttps = Settings.Instance.UseHttps;
AudioService.Load();
}
private void App_OnExit(object sender, ExitEventArgs e)
{
RemoveTrayIcon();
AudioService.Save();
AudioService.Dispose();
}
private void App_OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
LoggingService.Log(e.Exception);
Dispatcher.Invoke(async () =>
{
e.Handled = true;
var flyout = new FlyoutControl();
flyout.FlyoutContent = new CommonErrorView();
var restart = (bool)await flyout.ShowAsync();
if (restart)
{
Process.Start(Application.ResourceAssembly.Location);
}
Shutdown();
});
}
public void AddTrayIcon()
{
if (_trayIcon != null)
{
return;
}
_trayIcon = new NotifyIcon
{
Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location),
Text = "Meridian " + Assembly.GetExecutingAssembly().GetName().Version.ToString(2)
};
_trayIcon.MouseClick += TrayIconOnMouseClick;
_trayIcon.Visible = true;
_trayIcon.ContextMenuStrip = new ContextMenuStrip();
var closeItem = new System.Windows.Forms.ToolStripMenuItem();
closeItem.Text = MainResources.Close;
closeItem.Click += (s, e) =>
{
foreach (Window window in Windows)
{
window.Close();
}
};
_trayIcon.ContextMenuStrip.Items.Add(closeItem);
}
private void TrayIconOnMouseClick(object sender, MouseEventArgs mouseEventArgs)
{
foreach (Window window in Windows)
{
if (window.Visibility == Visibility.Collapsed)
{
window.Visibility = Visibility.Visible;
window.Show();
}
window.Activate();
if (window.WindowState == WindowState.Minimized)
window.WindowState = WindowState.Normal;
}
}
public void RemoveTrayIcon()
{
if (_trayIcon != null)
{
_trayIcon.MouseClick -= TrayIconOnMouseClick;
_trayIcon.Visible = false;
_trayIcon.Dispose();
_trayIcon = null;
}
}
}
}
================================================
FILE: Meridian/Behaviours/AutoScrollToCurrentItemBehaviour.cs
================================================
using System;
using System.Windows.Controls;
using GalaSoft.MvvmLight.Messaging;
using Meridian.Services;
using Meridian.ViewModel.Messages;
using Microsoft.Xaml.Behaviors;
namespace Meridian.Behaviours
{
public class AutoScrollToCurrentItemBehaviour : Behavior
{
protected override void OnAttached()
{
Messenger.Default.Register(this, OnCurrentAudioChanged);
if (AudioService.CurrentAudio != null)
AssociatedObject.ScrollIntoView(AudioService.CurrentAudio);
}
protected override void OnDetaching()
{
Messenger.Default.Unregister(this, OnCurrentAudioChanged);
}
private void OnCurrentAudioChanged(CurrentAudioChangedMessage message)
{
Dispatcher.BeginInvoke(new Action(() =>
{
if (AssociatedObject != null && message.NewAudio != null)
{
AssociatedObject.ScrollIntoView(message.NewAudio);
}
}));
}
}
}
================================================
FILE: Meridian/Behaviours/FocusBehaviour.cs
================================================
using Microsoft.Xaml.Behaviors;
using System.Windows;
using System.Windows.Controls;
namespace Meridian.Behaviours
{
public class FocusBehavior : Behavior
{
///
/// IsFocused dependency property
///
public static readonly DependencyProperty IsFocusedProperty =
DependencyProperty.Register(
"IsFocused",
typeof(bool),
typeof(FocusBehavior),
new PropertyMetadata(false, (d, e) =>
{
if ((bool)e.NewValue && ((FocusBehavior)d).AssociatedObject != null)
((FocusBehavior)d).AssociatedObject.Focus();
}));
///
/// HasInitialFocus dependency property
///
public static readonly DependencyProperty HasInitialFocusProperty =
DependencyProperty.Register(
"HasInitialFocus",
typeof(bool),
typeof(FocusBehavior),
new PropertyMetadata(false, null));
///
/// Имеет ли контрол фокус
///
public bool IsFocused
{
get { return (bool)GetValue(IsFocusedProperty); }
set { SetValue(IsFocusedProperty, value); }
}
///
/// Имеет ли контрол фокус при инициализации
///
public bool HasInitialFocus
{
get { return (bool)GetValue(HasInitialFocusProperty); }
set { SetValue(HasInitialFocusProperty, value); }
}
protected override void OnAttached()
{
AssociatedObject.GotFocus += (sender, args) => IsFocused = true;
AssociatedObject.LostFocus += (sender, a) => IsFocused = false;
AssociatedObject.Loaded += (o, a) =>
{
if (HasInitialFocus || IsFocused)
AssociatedObject.Focus();
};
base.OnAttached();
}
}
}
================================================
FILE: Meridian/Behaviours/TransitionBehaviour.cs
================================================
using Microsoft.Xaml.Behaviors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media.Animation;
namespace Meridian.Behaviours
{
public class TransitionBehaviour : Behavior
{
public static readonly DependencyProperty TransitionProperty =
DependencyProperty.Register("Transition", typeof(Storyboard), typeof(TransitionBehaviour), new PropertyMetadata(default(Storyboard)));
public Storyboard Transition
{
get { return (Storyboard)GetValue(TransitionProperty); }
set { SetValue(TransitionProperty, value); }
}
public static readonly DependencyProperty TransitionDelayProperty =
DependencyProperty.Register("TransitionDelay", typeof(int), typeof(TransitionBehaviour), new PropertyMetadata(300));
public int TransitionDelay
{
get { return (int)GetValue(TransitionDelayProperty); }
set { SetValue(TransitionDelayProperty, value); }
}
public static readonly DependencyProperty TransitionIndexProperty =
DependencyProperty.RegisterAttached("TransitionIndex", typeof(int), typeof(TransitionBehaviour), new PropertyMetadata(default(int)));
public static void SetTransitionIndex(UIElement element, int value)
{
element.SetValue(TransitionIndexProperty, value);
}
public static int GetTransitionIndex(UIElement element)
{
return (int)element.GetValue(TransitionIndexProperty);
}
public static readonly DependencyProperty IgnoreTransitionProperty =
DependencyProperty.RegisterAttached("IgnoreTransition", typeof(bool), typeof(TransitionBehaviour), new PropertyMetadata(default(bool)));
public static void SetIgnoreTransition(UIElement element, bool value)
{
element.SetValue(IgnoreTransitionProperty, value);
}
public static bool GetIgnoreTransition(UIElement element)
{
return (bool)element.GetValue(IgnoreTransitionProperty);
}
protected override void OnAttached()
{
AssociatedObject.Loaded += AssociatedObject_Loaded;
if (AssociatedObject is ListBox)
{
var listBox = (ListBox)AssociatedObject;
listBox.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
}
base.OnAttached();
}
protected override void OnDetaching()
{
AssociatedObject.Loaded -= AssociatedObject_Loaded;
if (AssociatedObject is ListBox)
{
var listBox = (ListBox)AssociatedObject;
listBox.ItemContainerGenerator.StatusChanged -= ItemContainerGenerator_StatusChanged;
}
base.OnDetaching();
}
private List _lastTargets;
void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
if (((ItemContainerGenerator)sender).Status == GeneratorStatus.ContainersGenerated)
{
var targets = GetTargets();
if (targets == null)
return;
var newItems = targets.Where(t => !_lastTargets.Contains(t)).ToList();
if (newItems.Count == 0)
{
_lastTargets.Clear();
}
for (var index = 0; index < newItems.Count; index++)
{
if ((bool)targets[index].GetValue(IgnoreTransitionProperty))
continue;
var transitionIndex = Convert.ToInt32(targets[index].GetValue(TransitionIndexProperty));
for (var i = 1; i < Transition.Children.Count; i++)
{
Transition.Children[i].BeginTime = TimeSpan.FromMilliseconds(TransitionDelay * (transitionIndex != 0 ? transitionIndex : index));
}
Transition.Begin(newItems[index]);
}
}
else if (((ItemContainerGenerator)sender).Status == GeneratorStatus.GeneratingContainers)
{
_lastTargets = GetTargets();
}
}
void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
var targets = GetTargets();
if (targets == null)
return;
for (var index = 0; index < targets.Count; index++)
{
if ((bool)targets[index].GetValue(IgnoreTransitionProperty))
continue;
var transitionIndex = Convert.ToInt32(targets[index].GetValue(TransitionIndexProperty));
for (var i = 1; i < Transition.Children.Count; i++)
{
Transition.Children[i].BeginTime = TimeSpan.FromMilliseconds(TransitionDelay * (transitionIndex != 0 ? transitionIndex : index));
}
Transition.Begin(targets[index]);
}
}
List GetTargets()
{
var result = new List();
if (AssociatedObject is ListBox)
{
var itemsControl = ((ListBox)AssociatedObject);
var count = itemsControl.Items.Count;
for (int i = 0; i < count; i++)
{
var container = (FrameworkElement)itemsControl.ItemContainerGenerator.ContainerFromIndex(i);
if (container != null)
result.Add(container);
}
}
else if (AssociatedObject is ItemsControl)
{
var itemsControl = ((ItemsControl)AssociatedObject);
var count = itemsControl.Items.Count;
for (int i = 0; i < count; i++)
{
var container = (FrameworkElement)itemsControl.ItemContainerGenerator.ContainerFromIndex(i);
if (container != null)
result.Add(container);
}
}
else if (AssociatedObject is Panel)
{
var panel = (Panel)AssociatedObject;
var count = panel.Children.Count;
for (int i = 0; i < count; i++)
{
result.Add((FrameworkElement)panel.Children[i]);
}
}
return result;
}
}
}
================================================
FILE: Meridian/Behaviours/VisibilityTransitionBehaviour.cs
================================================
using Microsoft.Xaml.Behaviors;
using System.Windows;
using System.Windows.Media.Animation;
namespace Meridian.Behaviours
{
public class VisibilityTransitionBehaviour : Behavior
{
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(Visibility), typeof(VisibilityTransitionBehaviour), new PropertyMetadata(default(Visibility), PropertyChangedCallback));
public Visibility Value
{
get { return (Visibility)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var b = (VisibilityTransitionBehaviour)d;
b.TransitionOut((Visibility)e.OldValue);
}
public static readonly DependencyProperty AnimationOutProperty =
DependencyProperty.Register("AnimationOut", typeof(Storyboard), typeof(VisibilityTransitionBehaviour), new PropertyMetadata(default(Storyboard)));
public Storyboard AnimationOut
{
get { return (Storyboard)GetValue(AnimationOutProperty); }
set { SetValue(AnimationOutProperty, value); }
}
public static readonly DependencyProperty AnimationInProperty =
DependencyProperty.Register("AnimationIn", typeof(Storyboard), typeof(VisibilityTransitionBehaviour), new PropertyMetadata(default(Storyboard)));
public Storyboard AnimationIn
{
get { return (Storyboard)GetValue(AnimationInProperty); }
set { SetValue(AnimationInProperty, value); }
}
protected override void OnAttached()
{
AssociatedObject.Visibility = Value;
base.OnAttached();
}
private void TransitionOut(Visibility oldValue)
{
if (AssociatedObject == null)
return;
if (AnimationOut == null || oldValue == Visibility.Collapsed)
{
TransitionIn();
}
else
{
AnimationOut.Completed += AnimationOutCompleted;
AnimationOut.Begin(AssociatedObject);
}
}
private void TransitionIn()
{
if (AssociatedObject == null)
return;
AssociatedObject.Visibility = Value;
if (AnimationIn != null)
{
AnimationIn.Begin(AssociatedObject);
}
}
void AnimationOutCompleted(object sender, object e)
{
AnimationOut.Completed -= AnimationOutCompleted;
TransitionIn();
}
}
}
================================================
FILE: Meridian/Controls/BindablePasswordBox.cs
================================================
using System.Windows;
using System.Windows.Controls;
namespace Meridian.Controls
{
public sealed class BindablePasswordBox : Decorator
{
///
/// The password dependency property.
///
public static readonly DependencyProperty PasswordProperty;
private bool _isPreventCallback;
private readonly RoutedEventHandler _savedCallback;
///
/// Static constructor to initialize the dependency properties.
///
static BindablePasswordBox()
{
PasswordProperty = DependencyProperty.Register(
"Password",
typeof(string),
typeof(BindablePasswordBox),
new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnPasswordPropertyChanged))
);
}
///
/// Saves the password changed callback and sets the child element to the password box.
///
public BindablePasswordBox()
{
_savedCallback = HandlePasswordChanged;
var passwordBox = new PasswordBox();
passwordBox.Style = Application.Current.Resources["CommonPasswordBoxStyle"] as Style;
passwordBox.PasswordChanged += _savedCallback;
Child = passwordBox;
}
///
/// The password dependency property.
///
public string Password
{
get { return GetValue(PasswordProperty) as string; }
set { SetValue(PasswordProperty, value); }
}
///
/// Handles changes to the password dependency property.
///
/// the dependency object
/// the event args
private static void OnPasswordPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs eventArgs)
{
var bindablePasswordBox = (BindablePasswordBox)d;
var passwordBox = (PasswordBox)bindablePasswordBox.Child;
if (bindablePasswordBox._isPreventCallback)
{
return;
}
passwordBox.PasswordChanged -= bindablePasswordBox._savedCallback;
passwordBox.Password = (eventArgs.NewValue != null) ? eventArgs.NewValue.ToString() : "";
passwordBox.PasswordChanged += bindablePasswordBox._savedCallback;
}
///
/// Handles the password changed event.
///
/// the sender
/// the event args
private void HandlePasswordChanged(object sender, RoutedEventArgs eventArgs)
{
var passwordBox = (PasswordBox)sender;
_isPreventCallback = true;
Password = passwordBox.Password;
_isPreventCallback = false;
}
}
}
================================================
FILE: Meridian/Controls/BusyIndicator.cs
================================================
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
namespace Meridian.Controls
{
///
/// A control to provide a visual indicator when an application is busy.
///
[TemplateVisualState(Name = "Idle", GroupName = "BusyStates")]
[TemplateVisualState(Name = "Busy", GroupName = "BusyStates")]
[TemplateVisualState(Name = "Error", GroupName = "BusyStates")]
[TemplateVisualState(Name = "Visible", GroupName = "VisibilityStates")]
[TemplateVisualState(Name = "Hidden", GroupName = "VisibilityStates")]
[StyleTypedProperty(Property = "BusyContentStyle", StyleTargetType = typeof(ContentPresenter))]
public class BusyIndicator : ContentControl
{
///
/// Identifies the IsBusy dependency property.
///
public static readonly DependencyProperty IsBusyProperty = DependencyProperty.Register(
"IsBusy",
typeof(bool),
typeof(BusyIndicator),
new PropertyMetadata(false, new PropertyChangedCallback(OnIsBusyChanged)));
///
/// Gets or sets a value indicating whether the busy indicator should show.
///
public bool IsBusy
{
get
{
return (bool)GetValue(IsBusyProperty);
}
set
{
SetValue(IsBusyProperty, value);
}
}
///
/// Identifies the FocusAferBusy dependency property.
///
public static readonly DependencyProperty FocusAferBusyProperty = DependencyProperty.Register(
"FocusAferBusy",
typeof(Control),
typeof(BusyIndicator),
new PropertyMetadata(null));
///
/// Gets or sets a Control that should get focus when the busy indicator disapears.
///
public Control FocusAferBusy
{
get
{
return (Control)GetValue(FocusAferBusyProperty);
}
set
{
SetValue(FocusAferBusyProperty, value);
}
}
///
/// Identifies the BusyContent dependency property.
///
public static readonly DependencyProperty BusyContentProperty = DependencyProperty.Register(
"BusyContent",
typeof(object),
typeof(BusyIndicator),
new PropertyMetadata(null));
///
/// Gets or sets a value indicating the busy content to display to the user.
///
public object BusyContent
{
get
{
return (object)GetValue(BusyContentProperty);
}
set
{
SetValue(BusyContentProperty, value);
}
}
///
/// Identifies the BusyTemplate dependency property.
///
public static readonly DependencyProperty BusyContentTemplateProperty = DependencyProperty.Register(
"BusyContentTemplate",
typeof(DataTemplate),
typeof(BusyIndicator),
new PropertyMetadata(null));
///
/// Gets or sets a value indicating the template to use for displaying the busy content to the user.
///
public DataTemplate BusyContentTemplate
{
get
{
return (DataTemplate)GetValue(BusyContentTemplateProperty);
}
set
{
SetValue(BusyContentTemplateProperty, value);
}
}
public static readonly DependencyProperty ErrorProperty = DependencyProperty.Register(
"Error", typeof(string), typeof(BusyIndicator), new PropertyMetadata(default(string), OnErrorPropertyChanged));
private static void OnErrorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((BusyIndicator)d).ChangeVisualState(true);
}
public string Error
{
get { return (string)GetValue(ErrorProperty); }
set { SetValue(ErrorProperty, value); }
}
///
/// Identifies the ProgressBarStyle dependency property.
///
public static readonly DependencyProperty BusyContentStyleProperty = DependencyProperty.Register(
"BusyContentStyle",
typeof(Style),
typeof(BusyIndicator),
new PropertyMetadata(null));
///
/// Gets or sets a value indicating the style to use for the progress bar.
///
public Style BusyContentStyle
{
get
{
return (Style)GetValue(BusyContentStyleProperty);
}
set
{
SetValue(BusyContentStyleProperty, value);
}
}
///
/// Gets or sets a value indicating whether the BusyContent is visible.
///
protected bool IsContentVisible
{
get;
set;
}
static BusyIndicator()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(BusyIndicator), new FrameworkPropertyMetadata(typeof(BusyIndicator)));
}
///
/// Overrides the OnApplyTemplate method.
///
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
ChangeVisualState(false);
}
///
/// Changes the control's visual state(s).
///
/// True if state transitions should be used.
protected virtual void ChangeVisualState(bool useTransitions)
{
if (string.IsNullOrEmpty(Error))
VisualStateManager.GoToState(this, IsBusy ? "Busy" : "Idle", useTransitions);
else
VisualStateManager.GoToState(this, "Error", useTransitions);
VisualStateManager.GoToState(this, IsContentVisible ? "Visible" : "Hidden", useTransitions);
}
///
/// IsBusyProperty property changed handler.
///
/// BusyIndicator that changed its IsBusy.
/// Event arguments.
private static void OnIsBusyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((BusyIndicator)d).OnIsBusyChanged(e);
}
///
/// IsBusyProperty property changed handler.
///
/// Event arguments.
protected virtual void OnIsBusyChanged(DependencyPropertyChangedEventArgs e)
{
if (IsBusy)
{
// Go visible now
IsContentVisible = true;
}
else
{
// No longer visible
if (string.IsNullOrEmpty(Error))
{
IsContentVisible = false;
if (this.FocusAferBusy != null)
{
this.FocusAferBusy.Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
{
this.FocusAferBusy.Focus();
this.FocusAferBusy = null;
}
));
}
}
else
{
IsContentVisible = true;
}
}
ChangeVisualState(true);
}
}
}
================================================
FILE: Meridian/Controls/ContentTransitionControl.xaml
================================================
================================================
FILE: Meridian/Controls/ContentTransitionControl.xaml.cs
================================================
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
namespace Meridian.Controls
{
///
/// Interaction logic for ContentTransitionControl.xaml
///
public partial class ContentTransitionControl : UserControl
{
private ContentControl _currentControl;
private ContentControl _newControl;
public new static readonly DependencyProperty ContentTemplateProperty =
DependencyProperty.Register("ContentTemplate", typeof(DataTemplate), typeof(ContentTransitionControl), new PropertyMetadata(default(DataTemplate), ContentTemplatePropertyChanged));
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(object), typeof(ContentTransitionControl), new PropertyMetadata(default(object), SourcePropertyChanged));
private static void SourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (ContentTransitionControl)d;
control._currentControl.Content = e.NewValue;
control.Swap();
if (e.OldValue != null)
control.AnimateOut();
if (e.NewValue != null)
control.AnimateIn();
}
public object Source
{
get { return GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
private static void ContentTemplatePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (ContentTransitionControl)d;
control._currentControl.ContentTemplate = (DataTemplate)e.NewValue;
control._newControl.ContentTemplate = (DataTemplate)e.NewValue;
}
public new DataTemplate ContentTemplate
{
get { return (DataTemplate)GetValue(ContentTemplateProperty); }
set { SetValue(ContentTemplateProperty, value); }
}
public ContentTransitionControl()
{
InitializeComponent();
_currentControl = Control1;
_newControl = Control2;
}
private void Swap()
{
var x = _currentControl;
_currentControl = _newControl;
_newControl = x;
}
private void AnimateOut()
{
var s = (Storyboard)Resources["TransitionOut"];
s.Begin(_currentControl);
}
private void AnimateIn()
{
var s = (Storyboard)Resources["TransitionIn"];
s.Begin(_newControl);
}
}
}
================================================
FILE: Meridian/Controls/ExtendedListBox.cs
================================================
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Meridian.Controls
{
public class ExtendedListBox : ListBox
{
private ScrollViewer _scrollViewer;
public static readonly DependencyProperty LoadMoreCommandProperty =
DependencyProperty.Register("LoadMoreCommand", typeof(ICommand), typeof(ExtendedListBox), new PropertyMetadata(default(ICommand)));
public ICommand LoadMoreCommand
{
get { return (ICommand)GetValue(LoadMoreCommandProperty); }
set { SetValue(LoadMoreCommandProperty, value); }
}
public ExtendedListBox()
{
Unloaded += ExtendedListBox_Unloaded;
}
void ExtendedListBox_Unloaded(object sender, RoutedEventArgs e)
{
if (_scrollViewer != null)
_scrollViewer.ScrollChanged -= _scrollViewer_ScrollChanged;
}
public override void OnApplyTemplate()
{
_scrollViewer = (ScrollViewer)FindElementRecursive(this, typeof(ScrollViewer));
_scrollViewer.ScrollChanged += _scrollViewer_ScrollChanged;
base.OnApplyTemplate();
}
void _scrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (_scrollViewer == null || LoadMoreCommand == null)
return;
if (e.VerticalOffset == _scrollViewer.ScrollableHeight && e.VerticalChange != 0)
LoadMoreCommand.Execute(null);
}
private UIElement FindElementRecursive(FrameworkElement parent, Type targetType)
{
int childCount = VisualTreeHelper.GetChildrenCount(parent);
UIElement returnElement = null;
if (childCount > 0)
{
for (int i = 0; i < childCount; i++)
{
var element = VisualTreeHelper.GetChild(parent, i);
if (element.GetType() == targetType)
{
return element as UIElement;
}
else
{
returnElement = FindElementRecursive(VisualTreeHelper.GetChild(parent, i) as FrameworkElement, targetType);
}
}
}
return returnElement;
}
}
}
================================================
FILE: Meridian/Controls/FlyoutContent.cs
================================================
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using GalaSoft.MvvmLight.Command;
using Neptune.UI.Extensions;
namespace Meridian.Controls
{
public class FlyoutContent : UserControl
{
#region Commands
public RelayCommand CloseCommand { get; private set; }
#endregion
public FlyoutContent()
{
InitializeCommand();
}
private void InitializeCommand()
{
CloseCommand = new RelayCommand(Close);
}
protected void Close()
{
var flyout = Application.Current.MainWindow.GetVisualDescendents().FirstOrDefault(c => c is FlyoutControl) as FlyoutControl;
if (flyout != null)
flyout.Close();
}
}
}
================================================
FILE: Meridian/Controls/FlyoutControl.xaml
================================================
================================================
FILE: Meridian/Controls/FlyoutControl.xaml.cs
================================================
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media.Animation;
using GongSolutions.Wpf.DragDrop.Utilities;
using Application = System.Windows.Application;
using MessageBox = System.Windows.MessageBox;
using Panel = System.Windows.Controls.Panel;
using UserControl = System.Windows.Controls.UserControl;
namespace Meridian.Controls
{
///
/// Interaction logic for FlyoutControl.xaml
///
public partial class FlyoutControl : UserControl
{
private object _result = null;
public static readonly DependencyProperty FlyoutContentProperty =
DependencyProperty.Register("FlyoutContent", typeof(object), typeof(FlyoutControl), new PropertyMetadata(default(object)));
public object FlyoutContent
{
get { return (object)GetValue(FlyoutContentProperty); }
set { SetValue(FlyoutContentProperty, value); }
}
public static readonly DependencyProperty FlyoutContentTemplateProperty =
DependencyProperty.Register("FlyoutContentTemplate", typeof(DataTemplate), typeof(FlyoutControl), new PropertyMetadata(default(DataTemplate)));
public DataTemplate FlyoutContentTemplate
{
get { return (DataTemplate)GetValue(FlyoutContentTemplateProperty); }
set { SetValue(FlyoutContentTemplateProperty, value); }
}
public delegate void ClosedEventHandler(object result);
public event ClosedEventHandler Closed;
public FlyoutControl()
{
InitializeComponent();
}
public void Show()
{
var mainWindow = Application.Current.MainWindow;
if (mainWindow.Content == null)
return;
var panel = mainWindow.GetVisualDescendent(); //mainWindow.Content as Panel;
if (panel == null)
{
return;
}
panel.Children.Add(this);
}
public Task