From: Amritanshu Date: Wed, 15 Sep 2021 07:30:40 +0000 (+0530) Subject: Modified Folder structure for GBS build to include app in the image X-Git-Tag: submit/tizen/20210915.141722~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=75fbfdd1843f2613ed907049d426868b791538fa;p=profile%2Fiot%2Fapps%2Fdotnet%2Fmusic-player.git Modified Folder structure for GBS build to include app in the image Change-Id: I3ddbdba2217b411b32cc622291c90b86d80aa7c7 Signed-off-by: Amritanshu --- diff --git a/Common/AppConstants.cs b/Common/AppConstants.cs deleted file mode 100755 index 104322b..0000000 --- a/Common/AppConstants.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace MusicPlayer.Common -{ - class AppConstants - { - // LogTag - public const string LogTag = "MUSIC_PLAYER"; - // KeyCodes - public const string BackKeyCode = "XF86Back"; - public const string EscapeKeyCode = "Escape"; - - // string literals - public const string TimeFormat = @"mm\:ss"; - public const string LightPlatformThemeId = "org.tizen.default-light-theme"; - public const string DarkPlatformThemeId = "org.tizen.default-dark-theme"; - } -} diff --git a/Common/PlayerCommon.cs b/Common/PlayerCommon.cs deleted file mode 100755 index 04ba5a2..0000000 --- a/Common/PlayerCommon.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace MusicPlayer.Common -{ - public enum ThemeType - { - Light, - Dark - }; - public enum RepeatMode - { - Off, - RepeatOne, - RepeatAll, - } - - public enum PlayingStatus - { - None, - Playing, - Paused, - Stopped, - } - - public enum ShuffleMode - { - On, - Off, - } - - public enum Favourite - { - On, - Off, - } - - public enum EventType - { - Error, - PlaybackCompleted, - } - - public class PlayerEventArgs : EventArgs - { - private readonly EventType type; - private readonly string description; - - internal PlayerEventArgs(EventType eventType, string desc) - { - type = eventType; - description = desc; - } - - public EventType Type - { - get => type; - } - public string Description - { - get => description; - } - } -} diff --git a/Common/PropertyNotifier.cs b/Common/PropertyNotifier.cs deleted file mode 100755 index de87064..0000000 --- a/Common/PropertyNotifier.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.ComponentModel; -using System.Runtime.CompilerServices; - -namespace MusicPlayer.Common -{ - class PropertyNotifier : INotifyPropertyChanged - { - public event PropertyChangedEventHandler PropertyChanged; - - protected bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null) - { - if (Equals(storage, value)) - { - return false; - } - - storage = value; - OnPropertyChanged(propertyName); - return true; - } - - protected void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - } -} diff --git a/Common/Resources.cs b/Common/Resources.cs deleted file mode 100644 index 361c2da..0000000 --- a/Common/Resources.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace MusicPlayer.Common -{ - public class Resources - { - public static string GetImagePath() - { - return Tizen.Applications.Application.Current.DirectoryInfo.Resource + "images/"; - } - - public static string GetThemePath() - { - return Tizen.Applications.Application.Current.DirectoryInfo.Resource + "themes/"; - } - } -} diff --git a/Common/UIColors.cs b/Common/UIColors.cs deleted file mode 100755 index dd3026a..0000000 --- a/Common/UIColors.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Tizen.NUI; - -namespace MusicPlayer.Common -{ - class UIColors - { - public static readonly Color HEX000209 = new Color(0.0f, 0.0078f, 0.0353f, 1.0f); - public static readonly Color HEX001447 = new Color(0.0f, 0.0784f, 0.2784f, 1.0f); - public static readonly Color HEXEEEFF1 = new Color(0.9333f, 0.9373f, 0.9450f, 1.0f); - - public static readonly Color LyricsBackground = new Color(0.0f, 0.0f, 0.0f, 0.85f); - public static readonly Color ItemSeperator = new Color(0.75f, 0.79f, 0.82f, 1.0f); - - } -} diff --git a/Core/ColorExtractor.cs b/Core/ColorExtractor.cs deleted file mode 100644 index db4a86d..0000000 --- a/Core/ColorExtractor.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Tizen.NUI; -using MusicPlayer.Common; - -namespace MusicPlayer.Core -{ - static class ColorExtractor - { - public static async Task GetPaletteAsync(string imagePath) - { - Tizen.Log.Debug(AppConstants.LogTag, "Main Thread Id: " + Thread.CurrentThread.ManagedThreadId); - return await Task.Run(() => GeneratePalette(imagePath)); - } - - private static Palette GeneratePalette(string imagePath) - { - PixelBuffer pixelBuffer = ImageLoading.LoadImageFromFile(imagePath); - if(pixelBuffer == null) - { - Tizen.Log.Error(AppConstants.LogTag, "Pixel buffer is null"); - return null; - } - - Palette palette = null; - - try - { - palette = Palette.Generate(pixelBuffer); - } - catch(System.ArgumentNullException e) - { - Tizen.Log.Error(AppConstants.LogTag, "ArgumentNullException: " + e.Message); - } - - return palette; - } - } -} diff --git a/Core/MusicPlayer.cs b/Core/MusicPlayer.cs deleted file mode 100644 index 30942d5..0000000 --- a/Core/MusicPlayer.cs +++ /dev/null @@ -1,180 +0,0 @@ -using System; -using System.Threading.Tasks; -using Tizen.Multimedia; -using MusicPlayer.Common; - -namespace MusicPlayer.Core -{ - public class MusicPlayer - { - private readonly Player player = new Player(); - - public MusicPlayer() - { - player.ErrorOccurred += OnErrorOccurred; - player.PlaybackCompleted += OnPlayBackCompleted; - } - - public event EventHandler PlayerEvent; - - private enum PlayerValidationState - { - Start, - Stop, - Pause, - Resume, - Position, - } - - public PlayerState State - { - get => player.State; - } - - public void SetSource(string uri) - { - if(State != PlayerState.Idle) - { - Tizen.Log.Error(AppConstants.LogTag, "Player is not in idle state, can't set source"); - return; - } - try - { - Tizen.Log.Error(AppConstants.LogTag, "setting uri: " + uri); - player.SetSource(new MediaUriSource(uri)); - } - catch (UnauthorizedAccessException ex) - { - Tizen.Log.Error(AppConstants.LogTag, "UnauthorizedAccessException: " + ex.Message); - } - catch (ObjectDisposedException ex) - { - Tizen.Log.Error(AppConstants.LogTag, "ObjectDisposed: " + ex.Message); - } - catch (InvalidOperationException ex) - { - Tizen.Log.Error(AppConstants.LogTag, "InvalidOperationException: " + ex.Message); - } - } - - public async Task PreparePlayer() - { - try - { - await player.PrepareAsync(); - } - catch (ObjectDisposedException ex) - { - Tizen.Log.Error("MusicPlayer", "ObjectDisposedException: "+ex.Message); - } - catch (InvalidOperationException ex) - { - Tizen.Log.Error("MusicPlayer", "InvalidOperationException: "+ex.Message); - } - finally // TODO do we really need this - { - //DisposePlayer(); - } - } - - public void Play() - { - if (ValidatePlayerState(PlayerValidationState.Start)) - { - player.Start(); - } - else - { - Tizen.Log.Error(AppConstants.LogTag, "Invalid player state for playing: " + player.State.ToString()); - } - } - - public void Pause() - { - if(ValidatePlayerState(PlayerValidationState.Pause)) - { - player.Pause(); - } - } - - public void Resume() - { - if (ValidatePlayerState(PlayerValidationState.Resume)) - { - player.Start(); - } - } - - public void Stop() - { - if(ValidatePlayerState(PlayerValidationState.Stop)) - { - player.Stop(); - } - } - - public int GetPosition() - { - if (ValidatePlayerState(PlayerValidationState.Position)) - { - return player.GetPlayPosition(); - } - else - { - return 0; - } - } - - public void Unprepare() - { - player.Unprepare(); - } - - public void DisposePlayer() - { - player.Dispose(); - } - - public async Task SetPosition(int pos) - { - await player.SetPlayPositionAsync(pos, false); - } - - private bool ValidatePlayerState(PlayerValidationState state) - { - if(state == PlayerValidationState.Start || state == PlayerValidationState.Position) - { - return (State == PlayerState.Ready || State == PlayerState.Playing || State == PlayerState.Paused); - } - else if(state == PlayerValidationState.Pause) - { - return (State == PlayerState.Playing); - } - else if(state == PlayerValidationState.Resume) - { - return (State == PlayerState.Paused); - } - else if(state == PlayerValidationState.Stop) - { - return (State == PlayerState.Paused || State == PlayerState.Playing); - } - else - { - return false; - } - } - - private void OnPlayBackCompleted(object sender, EventArgs e) - { - PlayerEvent?.Invoke(this, new PlayerEventArgs(EventType.PlaybackCompleted, "Playback Completed")); - Tizen.Log.Error(AppConstants.LogTag, "Playback completed"); - } - - // TODO this event is called on a differnt thread..need to handle it - private void OnErrorOccurred(object sender, PlayerErrorOccurredEventArgs e) - { - PlayerEvent.Invoke(this, new PlayerEventArgs(EventType.Error, e.Error.ToString())); - Tizen.Log.Error(AppConstants.LogTag, "Error Occurred: " + e.Error.ToString()); - } - } -} diff --git a/Core/PlayerController.cs b/Core/PlayerController.cs deleted file mode 100644 index 4cd4a80..0000000 --- a/Core/PlayerController.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using Tizen.Multimedia; -using MusicPlayer.Common; - -namespace MusicPlayer.Core -{ - class PlayerController - { - private readonly MusicPlayer musicPlayer; - private static PlayerController instance = instance ??= new PlayerController(); - - private PlayerController() - { - musicPlayer = new MusicPlayer(); - musicPlayer.PlayerEvent += OnPlayerEvent; - } - - public event EventHandler PlayerEventOccurred; - - public static PlayerController Instance - { - get => instance; - } - - private string uri; - - public string Uri - { - get => uri; - set => uri = value; - } - - public async void Play() - { - if(Uri == null) - { - Tizen.Log.Error(AppConstants.LogTag, "Please set the uri to play"); - return; - } - Tizen.Log.Error(AppConstants.LogTag, "Current player state: "+musicPlayer.State.ToString()); - if (musicPlayer.State == PlayerState.Paused || musicPlayer.State == PlayerState.Playing) - { - musicPlayer.Stop(); - } - if(musicPlayer.State == PlayerState.Ready) - { - musicPlayer.Unprepare(); - } - musicPlayer.SetSource(Uri); - if(musicPlayer.State == PlayerState.Idle) - { - await musicPlayer.PreparePlayer(); - } - musicPlayer.Play(); - } - - public void Destroy() - { - musicPlayer?.DisposePlayer(); - } - - public void SetSource() - { - musicPlayer.SetSource(Uri); - } - - public void Pause() - { - musicPlayer.Pause(); - } - - public void Resume() - { - if (musicPlayer.State == PlayerState.Paused) - { - musicPlayer.Resume(); - } - else - { - Play(); - } - } - - public void Stop() - { - musicPlayer.Stop(); - } - - public int GetPosition() - { - return musicPlayer.GetPosition(); - } - - public async void SetPosition(int pos) - { - await musicPlayer.SetPosition(pos); - } - - private void OnPlayerEvent(object sender, PlayerEventArgs e) - { - PlayerEventOccurred?.Invoke(this, e); - } - } -} diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..54b213e --- /dev/null +++ b/LICENSE @@ -0,0 +1,204 @@ +Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved. + + 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 + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + diff --git a/MediaContent/AlbumContents.cs b/MediaContent/AlbumContents.cs deleted file mode 100755 index 2e86e50..0000000 --- a/MediaContent/AlbumContents.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Specialized; -using Tizen.Content.MediaContent; -using MusicPlayer.Common; - -namespace MusicPlayer.Media -{ - public static partial class Contents - { - public static OrderedDictionary GetAlbumList() - { - OrderedDictionary albumList = new OrderedDictionary(); - - SelectArguments albumSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, AlbumColumns.Name + MEDIA_SORT_ORDER_ASC); - MediaDataReader dataReader = albumInfo.Select(albumSelectArguments); - - while (dataReader.Read()) - { - Album info = dataReader.Current; - SelectArguments audioSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); - MediaDataReader albumDataReader = albumInfo.SelectMember(info.Id, audioSelectArguments); - if (albumDataReader.Read()) - albumList.Add(info.Id, info); - } - Tizen.Log.Debug(AppConstants.LogTag, "Total album retrived from database: " + albumList.Count); - dataReader.Dispose(); - return albumList; - } - - public static int GetAlbumMemberCount(int albumId) - { - return albumInfo.CountMember(albumId); - } - - public static OrderedDictionary GetAlbumMemberList(int albumId) - { - OrderedDictionary mediaList = new OrderedDictionary(); - SelectArguments audioSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); - MediaDataReader dataReader = albumInfo.SelectMember(albumId, audioSelectArguments); - - while (dataReader.Read()) - { - MediaInfo info = dataReader.Current; - mediaList.Add(info.Id, info); - } - Tizen.Log.Debug(AppConstants.LogTag, "Total track retrived from currentAlbum: " + mediaList.Count); - dataReader.Dispose(); - return mediaList; - } - - public static string GetAlbumArtPath(int albumId) - { - string path = ""; - SelectArguments audioSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); - MediaDataReader dataReader = albumInfo.SelectMember(albumId, audioSelectArguments); - while (dataReader.Read()) - { - MediaInfo info = dataReader.Current; - if (!string.IsNullOrEmpty(info.ThumbnailPath)) - path = info.ThumbnailPath; - } - dataReader.Dispose(); - return path; - } - } -} diff --git a/MediaContent/ArtistContents.cs b/MediaContent/ArtistContents.cs deleted file mode 100755 index f6da163..0000000 --- a/MediaContent/ArtistContents.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System.Collections.Specialized; -using System.Collections.Generic; -using Tizen.Content.MediaContent; -using System; -using MusicPlayer.Common; - - -namespace MusicPlayer.Media -{ - public static partial class Contents - { - public static List GetArtistList() - { - List artistList = new List(); - - SelectArguments artistSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Artist + MEDIA_SORT_ORDER_ASC); - MediaDataReader dataReader = mediaInfo.SelectGroupBy(MediaInfoColumnKey.Artist, artistSelectArguments); - - while (dataReader.Read()) - { - string info = (string)dataReader.Current; - artistList.Add(info); - } - Tizen.Log.Debug(AppConstants.LogTag, "Total artists retrived from database: " + artistList.Count); - dataReader.Dispose(); - return artistList; - } - - public static OrderedDictionary GetAlbumListForArtist(string artistName) - { - OrderedDictionary albumList = new OrderedDictionary(); - string expression = MEDIA_STORAGE_TYPE_QUERY + "AND " + AlbumColumns.Artist + "=\"" + artistName + "\""; - SelectArguments albumSelectArguments = CreateSelectArgument(expression, AlbumColumns.Name + MEDIA_SORT_ORDER_ASC); - MediaDataReader dataReader = albumInfo.Select(albumSelectArguments); - - while (dataReader.Read()) - { - Album info = dataReader.Current; - SelectArguments audioSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); - MediaDataReader albumDataReader = albumInfo.SelectMember(info.Id, audioSelectArguments); - if(albumDataReader.Read()) - albumList.Add(info.Id, info); - } - dataReader.Dispose(); - Tizen.Log.Debug(AppConstants.LogTag, "Total Albums retrived from Artist: " + albumList.Count); - return albumList; - } - - public static OrderedDictionary GetTrackListForArtist(string artistName) - { - OrderedDictionary mediaList = new OrderedDictionary(); - string expression = MEDIA_STORAGE_TYPE_QUERY + "AND " + AlbumColumns.Artist + "=\"" + artistName + "\""; - SelectArguments albumSelectArguments = CreateSelectArgument(expression, AlbumColumns.Name + MEDIA_SORT_ORDER_ASC); - MediaDataReader dataReader = albumInfo.Select(albumSelectArguments); - - while (dataReader.Read()) - { - Album info = dataReader.Current; - SelectArguments audioSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); - MediaDataReader albumDataReader = albumInfo.SelectMember(info.Id, audioSelectArguments); - - while (albumDataReader.Read()) - { - MediaInfo mediaInfo = albumDataReader.Current; - mediaList.Add(mediaInfo.Id, mediaInfo); - } - albumDataReader.Dispose(); - } - dataReader.Dispose(); - Tizen.Log.Debug(AppConstants.LogTag, "Total track retrived from Artist: " + mediaList.Count); - return mediaList; - } - - public static string GetAlbumArtPathForArtist(string artistName) - { - string expression = MEDIA_STORAGE_TYPE_QUERY + "AND " + AlbumColumns.Artist + "=\"" + artistName + "\""; - SelectArguments albumSelectArguments = CreateSelectArgument(expression, AlbumColumns.Name + MEDIA_SORT_ORDER_ASC); - MediaDataReader dataReader = albumInfo.Select(albumSelectArguments); - string albumArtPath = ""; - - while (dataReader.Read()) - { - Album info = dataReader.Current; - string path = ""; - if (!string.IsNullOrEmpty(info.AlbumArtPath)) - path = info.AlbumArtPath; - else - path = GetAlbumArtPath(info.Id); - if (!string.IsNullOrEmpty(path)) - albumArtPath = path; - } - dataReader.Dispose(); - return albumArtPath; - } - - public static int GetAlbumCountForArtist(string artistName) - { - string expression = MEDIA_STORAGE_TYPE_QUERY + "AND " + AlbumColumns.Artist + "=\"" + artistName+"\""; - int count = 0; - - SelectArguments albumSelectArguments = CreateSelectArgument(expression, AlbumColumns.Name + MEDIA_SORT_ORDER_ASC); - MediaDataReader dataReader = albumInfo.Select(albumSelectArguments); - - while (dataReader.Read()) - { - Album info = dataReader.Current; - SelectArguments audioSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); - MediaDataReader albumDataReader = albumInfo.SelectMember(info.Id, audioSelectArguments); - if (albumDataReader.Read()) - count++; - } - dataReader.Dispose(); - return count; - } - - public static int GetMediaCountForArtist(string artistName) - { - string expression = MEDIA_STORAGE_TYPE_QUERY + "AND " + MediaInfoColumns.Artist + "=\"" + artistName+"\""; - CountArguments audioCountArguments = CreateCountArgument(expression); - int count = 0; - try - { - count = mediaInfo.CountMedia(audioCountArguments); - } - catch (ObjectDisposedException ex) - { - Tizen.Log.Error(AppConstants.LogTag, "ObjectDisposedException: " + ex.Message); - } - catch (InvalidOperationException ex) - { - Tizen.Log.Error(AppConstants.LogTag, "InvalidOperationException: " + ex.Message); - } - catch (MediaDatabaseException ex) - { - Tizen.Log.Error(AppConstants.LogTag, "MediaDatabaseException: " + ex.Message); - } - catch (Exception ex) - { - Tizen.Log.Error(AppConstants.LogTag, "Unknown Exception: " + ex.Message); - } - - return count; - } - } -} diff --git a/MediaContent/MediaContents.cs b/MediaContent/MediaContents.cs deleted file mode 100755 index 6ae5a12..0000000 --- a/MediaContent/MediaContents.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using Tizen.Content.MediaContent; - -namespace MusicPlayer.Media -{ - public class MusicItemUpdateEventArgs : EventArgs - { - internal MusicItemUpdateEventArgs(int pid, - OperationType operationType, MediaType mediaType, string id, string path, string mimeType) - { - ProcessId = pid; - OperationType = operationType; - Id = id; - Path = path; - MediaType = mediaType; - MimeType = mimeType; - } - public int ProcessId { get; } - - public OperationType OperationType { get; } - - public string Id { get; } - - public string Path { get; } - - public MediaType MediaType { get; } - - public string MimeType { get; } - } - - public class MusicDBUpdateEventArgs : EventArgs - { - internal MusicDBUpdateEventArgs(OperationType operationType, string id, string path) - { - OperationType = operationType; - Id = id; - Path = path; - } - - public OperationType OperationType { get; } - - public string Id { get; } - - public string Path { get; } - } - - public static partial class Contents - { - private static Database database; - private static MediaInfoCommand mediaInfo; - private static AlbumCommand albumInfo; - private static PlaylistCommand playlistInfo; - private const string MEDIA_STORAGE_TYPE_QUERY = " (( MEDIA_STORAGE_TYPE IS NOT 101 ) AND (MEDIA_TYPE = 3)) "; - private const string MEDIA_SORT_ORDER_ASC = " COLLATE NOCASE ASC "; - - public static event EventHandler MusicItemUpdate; - public static event EventHandler MusicDBUpdate; - - static Contents() - { - database = new Database(); - mediaInfo = new MediaInfoCommand(database.MediaDatabase); - albumInfo = new AlbumCommand(database.MediaDatabase); - playlistInfo = new PlaylistCommand(database.MediaDatabase); - MediaDatabase.MediaInfoUpdated += OnMediaDatabaseItemUpdate; - MediaDatabase.FolderUpdated += OnMediaDatabaseFolderUpdate; - } - - private static void OnMediaDatabaseItemUpdate(object sender, MediaInfoUpdatedEventArgs e) - { - if(e.MediaType == MediaType.Music) - { - MusicItemUpdateEventArgs item = new MusicItemUpdateEventArgs(e.ProcessId, e.OperationType, e.MediaType, - e.Id, e.Path, e.MimeType); - MusicItemUpdate?.Invoke(null, item); - } - } - - private static void OnMediaDatabaseFolderUpdate(object sender, FolderUpdatedEventArgs e) - { - MusicDBUpdateEventArgs item = new MusicDBUpdateEventArgs(e.OperationType, e.Id, e.Path); - MusicDBUpdate?.Invoke(null, item); - } - - private static SelectArguments CreateSelectArgument(string filterExpression, string sortOrder) - { - SelectArguments arguments = new SelectArguments(); - arguments.FilterExpression = filterExpression; - arguments.SortOrder = sortOrder; - return arguments; - } - - private static CountArguments CreateCountArgument(string filterExpression) - { - CountArguments arguments = new CountArguments(); - arguments.FilterExpression = filterExpression; - return arguments; - } - - public static void Dispose() - { - database.Dispose(); - } - } - -} \ No newline at end of file diff --git a/MediaContent/MediaDatabase.cs b/MediaContent/MediaDatabase.cs deleted file mode 100755 index 5e3ec37..0000000 --- a/MediaContent/MediaDatabase.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using Tizen.Content.MediaContent; - -namespace MusicPlayer.Media -{ - class Database : IDisposable - { - private MediaDatabase mediaDatabase; - - public Database() - { - mediaDatabase = new MediaDatabase(); - mediaDatabase.Connect(); - } - - private void TerminateDatabase() - { - mediaDatabase.Disconnect(); - mediaDatabase.Dispose(); - } - - ~Database() - { - TerminateDatabase(); - } - - public void Dispose() - { - TerminateDatabase(); - // This will informed gc to not call the finalize method as resources are already released. - GC.SuppressFinalize(this); - } - - public MediaDatabase MediaDatabase - { - get { return mediaDatabase; } - } - } -} diff --git a/MediaContent/PlaylistContents.cs b/MediaContent/PlaylistContents.cs deleted file mode 100755 index d3e69ff..0000000 --- a/MediaContent/PlaylistContents.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using Tizen.Content.MediaContent; -using MusicPlayer.Common; - -namespace MusicPlayer.Media -{ - public static partial class Contents - { - public static List GetPlaylists() - { - List playlists = new List(); - SelectArguments arguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, PlaylistColumns.Name + MEDIA_SORT_ORDER_ASC); - MediaDataReader dataReader = playlistInfo.Select(arguments); - - while(dataReader.Read()) - { - Playlist playlist = dataReader.Current; - playlists.Add(playlist); - } - Tizen.Log.Debug(AppConstants.LogTag, "PlayLists Count : " + playlists.Count); - return playlists; - } - - public static Playlist GetPlaylistByName(string name) - { - string filterExpression = MEDIA_STORAGE_TYPE_QUERY + " AND " + PlaylistColumns.Name + "=\"" + name + "\""; - SelectArguments arguments = CreateSelectArgument(filterExpression, PlaylistColumns.Name + MEDIA_SORT_ORDER_ASC); - MediaDataReader dataReader = playlistInfo.Select(arguments); - - Playlist list = null; - while (dataReader.Read()) - { - list = dataReader.Current; - } - return list; - } - - public static Playlist GetPlaylistById(int playlistId) - { - Playlist list = null; - list = playlistInfo.Select(playlistId); - return list; - } - - } -} diff --git a/MediaContent/TrackContents.cs b/MediaContent/TrackContents.cs deleted file mode 100755 index 551a80c..0000000 --- a/MediaContent/TrackContents.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Specialized; -using Tizen.Content.MediaContent; -using MusicPlayer.Common; - -namespace MusicPlayer.Media -{ - public static partial class Contents - { - public static OrderedDictionary GetTrackList() - { - OrderedDictionary mediaList = new OrderedDictionary(); - - SelectArguments argument = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); - MediaDataReader dataReader = mediaInfo.SelectMedia(argument); - - while (dataReader.Read()) - { - MediaInfo info = dataReader.Current; - mediaList.Add(info.Id, info); - } - Tizen.Log.Debug(AppConstants.LogTag, "Total track retrived from database: " + mediaList.Count); - dataReader.Dispose(); - return mediaList; - } - } -} diff --git a/Models/Album.cs b/Models/Album.cs deleted file mode 100755 index 455e32d..0000000 --- a/Models/Album.cs +++ /dev/null @@ -1,69 +0,0 @@ -using MusicPlayer.Common; - -namespace MusicPlayer.Models -{ - class MusicAlbum : PropertyNotifier - { - public MusicAlbum() - { - //this is required for Activator.CreateInstance in ListViewModel - } - - public MusicAlbum(Tizen.Content.MediaContent.Album album) - { - AlbumName = album.Name; - ArtistName = album.Artist; - Id = album.Id; - string text = album.AlbumArtPath; - if (string.IsNullOrEmpty(album.AlbumArtPath)) - { - text = AlbumDataProvider.GetAlbumArtFromTracks(album.Id); - } - AlbumArtPath = text; - } - - private string albumName; - - public string AlbumName - { - get => albumName; - set - { - string text = string.IsNullOrEmpty(value) ? "Unknown" : value; - SetProperty(ref albumName, text); - } - } - - private string artistName; - - public string ArtistName - { - get => artistName; - set - { - string text = string.IsNullOrEmpty(value) ? "Unknown" : value; - SetProperty(ref artistName, text); - } - } - - private int id; - - public int Id - { - get => id; - set => id = value; - } - - private string albumArtPath; - - public string AlbumArtPath - { - get => albumArtPath; - set - { - string thumb = string.IsNullOrEmpty(value) ? Resources.GetImagePath() + "thumbnail.png" : value; - SetProperty(ref albumArtPath, thumb); - } - } - } -} diff --git a/Models/AlbumDataProvider.cs b/Models/AlbumDataProvider.cs deleted file mode 100755 index 9116246..0000000 --- a/Models/AlbumDataProvider.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Collections.Specialized; -using MusicPlayer.Media; - -namespace MusicPlayer.Models -{ - public static class AlbumDataProvider - { - private static OrderedDictionary albumsList; - - static AlbumDataProvider() - { - albumsList = Contents.GetAlbumList(); - Contents.MusicItemUpdate += OnMusicItemUpdate; - Contents.MusicDBUpdate += OnMusicDatabaseUpdate; - } - - private static void OnMusicDatabaseUpdate(object sender, MusicDBUpdateEventArgs e) - { - albumsList = Contents.GetAlbumList(); - // TODO implement database update event handler - return; - } - - private static void OnMusicItemUpdate(object sender, MusicItemUpdateEventArgs e) - { - // TODO implement database item update event handler - return; - } - - public static OrderedDictionary CurrentAlbumList() - { - return albumsList; - } - - public static OrderedDictionary GetAlbumTrackList(int albumId) - { - return Contents.GetAlbumMemberList(albumId); - } - - public static string GetAlbumArtFromTracks(int albumId) - { - return Contents.GetAlbumArtPath(albumId); - } - } -} diff --git a/Models/Artist.cs b/Models/Artist.cs deleted file mode 100755 index 20e9ff4..0000000 --- a/Models/Artist.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using MusicPlayer.Common; - -namespace MusicPlayer.Models -{ - class Artist : PropertyNotifier - { - public Artist() - { - //this is required for Activator.CreateInstance in ListViewModel - } - - public Artist(string artistName) - { - ArtistName = artistName; - AlbumCount = ArtistDataProvider.GetArtistAlbumCount(artistName).ToString(); - TrackCount = ArtistDataProvider.GetArtistTrackCount(artistName).ToString(); - TotalCount = AlbumCount + " / " + TrackCount; - AlbumArtPath = ArtistDataProvider.GetArtistAlbumArtPath(artistName); - } - - private string artistName; - - public string ArtistName - { - get => artistName; - set - { - string text = string.IsNullOrEmpty(value) ? "Unknown" : value; - SetProperty(ref artistName, text); - } - } - - private string albumCount; - - public string AlbumCount - { - get => albumCount; - set - { - string text = string.Equals(value, "1") ? " album" : " albums"; - SetProperty(ref albumCount, value + text); - } - } - - private string trackCount; - - public string TrackCount - { - get => trackCount; - set - { - string text = string.Equals(value, "1") ? " track" : " tracks"; - SetProperty(ref trackCount, value + text); - } - } - - private string totalCount; - - public string TotalCount - { - get => totalCount; - set => SetProperty(ref totalCount, value); - } - - private string albumArtPath; - - public string AlbumArtPath - { - get => albumArtPath; - set - { - string thumb = string.IsNullOrEmpty(value) ? Resources.GetImagePath() + "thumbnail.png" : value; - SetProperty(ref albumArtPath, thumb); - } - } - } -} diff --git a/Models/ArtistDataProvider.cs b/Models/ArtistDataProvider.cs deleted file mode 100755 index 3bd29d1..0000000 --- a/Models/ArtistDataProvider.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Collections.Specialized; -using System.Collections.Generic; -using MusicPlayer.Media; - -namespace MusicPlayer.Models -{ - public static class ArtistDataProvider - { - private static List artistsList; - - static ArtistDataProvider() - { - artistsList = Contents.GetArtistList(); - Contents.MusicItemUpdate += OnMusicItemUpdate; - Contents.MusicDBUpdate += OnMusicDatabaseUpdate; - } - - private static void OnMusicDatabaseUpdate(object sender, MusicDBUpdateEventArgs e) - { - artistsList = Contents.GetArtistList(); - // TODO implement database update event handler - return; - } - - private static void OnMusicItemUpdate(object sender, MusicItemUpdateEventArgs e) - { - // TODO implement database item update event handler - return; - } - - public static List CurrentArtistList() - { - return artistsList; - } - - public static int GetArtistTrackCount(string artistName) - { - return Contents.GetMediaCountForArtist(artistName); - } - - public static int GetArtistAlbumCount(string artistName) - { - return Contents.GetAlbumCountForArtist(artistName); - } - - public static string GetArtistAlbumArtPath(string artistName) - { - return Contents.GetAlbumArtPathForArtist(artistName); - } - - public static OrderedDictionary GetArtistAlbumList(string artistName) - { - return Contents.GetAlbumListForArtist(artistName); - } - - public static OrderedDictionary GetArtistTrackList(string artistName) - { - return Contents.GetTrackListForArtist(artistName); - } - } -} \ No newline at end of file diff --git a/Models/ArtistDetailAlbum.cs b/Models/ArtistDetailAlbum.cs deleted file mode 100755 index 696549b..0000000 --- a/Models/ArtistDetailAlbum.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using MusicPlayer.Common; -using System.Collections.ObjectModel; - -namespace MusicPlayer.Models -{ - class ArtistDetailAlbum: ObservableCollection - { - public ArtistDetailAlbum() - { - //this is required for Activator.CreateInstance in ListViewModel - } - - public ArtistDetailAlbum(MusicAlbum album) - { - AlbumArtPath = album.AlbumArtPath; - AlbumName = album.AlbumName; - } - - public string AlbumName { get; set; } - - public string AlbumArtPath { get; set; } - } -} diff --git a/Models/LyricsModel.cs b/Models/LyricsModel.cs deleted file mode 100644 index 6ea25e5..0000000 --- a/Models/LyricsModel.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Tizen.Multimedia; -using System.ComponentModel; -using MusicPlayer.Common; - -namespace MusicPlayer.Models -{ - class LyricsModel: PropertyNotifier - { - public LyricsModel() - { - } - - public LyricsModel(string thumbPath, string lyrics) - { - ThumbPath = thumbPath; - Lyrics = lyrics; - } - - private string thumbPath; - - public string ThumbPath - { - get => thumbPath; - set => SetProperty(ref thumbPath, value); - } - - private string lyrics; - - public string Lyrics - { - get => lyrics; - set => SetProperty(ref lyrics, value); - } - } -} diff --git a/Models/PlayerModel.cs b/Models/PlayerModel.cs deleted file mode 100755 index 1bc59db..0000000 --- a/Models/PlayerModel.cs +++ /dev/null @@ -1,76 +0,0 @@ -using MusicPlayer.Common; -using System; - -namespace MusicPlayer.Models -{ - class PlayerModel : PropertyNotifier - { - public PlayerModel() - { - } - - private Track currentTrack; - - public Track CurrentTrack - { - get => currentTrack; - set - { - currentTrack = value; - TrackName = currentTrack.TrackTitle; - TrackArtist = currentTrack.ArtistName; - TrackLength = currentTrack.Duration; - PlayingTime = TimeSpan.FromMilliseconds(0).ToString(AppConstants.TimeFormat); - ThumbnailPath = currentTrack.ThumbnailPath; - } - } - - private string trackName; - - public string TrackName - { - get => trackName; - set => SetProperty(ref trackName, value); - } - - private string trackArtist; - - public string TrackArtist - { - get => trackArtist; - set => SetProperty(ref trackArtist, value); - } - - private string trackLength; - - public string TrackLength - { - get => trackLength; - set => SetProperty(ref trackLength, value); - } - - private string thumbnailPath; - - public string ThumbnailPath - { - get => thumbnailPath; - set => SetProperty(ref thumbnailPath, value); - } - - private string playingTime; - - public string PlayingTime - { - get => playingTime; - set => SetProperty(ref playingTime, value); - } - - private float elapsedTime; - - public float ElapsedTime - { - get => elapsedTime; - set => SetProperty(ref elapsedTime, value); - } - } -} diff --git a/Models/Track.cs b/Models/Track.cs deleted file mode 100755 index 1435eb8..0000000 --- a/Models/Track.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using MusicPlayer.Common; - -namespace MusicPlayer.Models -{ - class Track : PropertyNotifier - { - public Track() - { - //this is required for Activator.CreateInstance in ListViewModel - } - - public Track(Tizen.Content.MediaContent.AudioInfo audioInfo) - { - TrackTitle = audioInfo.Title; - AlbumName = audioInfo.Album; - Id = audioInfo.Id; - ArtistName = audioInfo.Artist; - DurationInMS = audioInfo.Duration; - Duration = TimeSpan.FromMilliseconds(audioInfo.Duration).ToString(AppConstants.TimeFormat); - ThumbnailPath = audioInfo.ThumbnailPath; - FilePath = audioInfo.Path; - } - - private string trackTitle; - - public string TrackTitle - { - get => trackTitle; - set => SetProperty(ref trackTitle, value); - } - - private string albumName; - - public string AlbumName - { - get => albumName; - set - { - string name = string.IsNullOrEmpty(value) ? "Unknown" : value; - SetProperty(ref albumName, name); - } - } - - private string artistName; - - public string ArtistName - { - get => artistName; - set - { - string name = string.IsNullOrEmpty(value) ? "Unknown" : value; - SetProperty(ref artistName, name); - } - } - - private string id; - - public string Id - { - get => id; - set => id = value; - } - - private string duration; - - public string Duration - { - get => duration; - set => SetProperty(ref duration, value); - } - - private int durationInMS; - - public int DurationInMS - { - get => durationInMS; - set => SetProperty(ref durationInMS, value); - } - - private string thumbnailPath; - - public string ThumbnailPath - { - get => thumbnailPath; - set - { - string thumb = string.IsNullOrEmpty(value) ? Resources.GetImagePath() + "thumbnail.png" : value; - SetProperty(ref thumbnailPath, thumb); - } - } - - private string filePath; - - public string FilePath - { - get => filePath; - set { filePath = value; } - } - } -} diff --git a/Models/TrackDataProvider.cs b/Models/TrackDataProvider.cs deleted file mode 100755 index 1809008..0000000 --- a/Models/TrackDataProvider.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Specialized; -using MusicPlayer.Media; - -namespace MusicPlayer.Models -{ - public static class TrackDataProvider - { - private static OrderedDictionary tracksList; - - static TrackDataProvider() - { - tracksList = Contents.GetTrackList(); - Contents.MusicItemUpdate += OnMusicItemUpdate; - Contents.MusicDBUpdate += OnMusicDatabaseUpdate; - } - - private static void OnMusicDatabaseUpdate(object sender, MusicDBUpdateEventArgs e) - { - tracksList = Contents.GetTrackList(); - // TODO implement database update event handler - return; - } - - private static void OnMusicItemUpdate(object sender, MusicItemUpdateEventArgs e) - { - // TODO implement database item update event handler - return; - } - - public static OrderedDictionary CurrentTrackList() - { - return tracksList; - } - } -} diff --git a/MusicPlayer.cs b/MusicPlayer.cs deleted file mode 100755 index cb65d24..0000000 --- a/MusicPlayer.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using Tizen.NUI; -using MusicPlayer.Views; -using MusicPlayer.Common; - -namespace MusicPlayer -{ - public class Application : NUIApplication - { - public Application() : base(ThemeOptions.PlatformThemeEnabled) - { - - } - protected override void OnCreate() - { - Tizen.Log.Info(AppConstants.LogTag, "OnCreate statrted"); - base.OnCreate(); - Window window = Window.Instance; - window.BackgroundColor = Color.White; - window.KeyEvent += OnKeyEvent; - Size2D size = window.Size; - Tizen.Log.Info(AppConstants.LogTag, "Window Size: " + size.Width + "x" + size.Height); - - ViewManager manager = new ViewManager(Window.Instance); - } - - public void OnKeyEvent(object sender, Window.KeyEventArgs e) - { - if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == AppConstants.BackKeyCode || e.Key.KeyPressedName == AppConstants.EscapeKeyCode)) - { - Exit(); - } - } - - static void Main(string[] args) - { - Tizen.Log.Info(AppConstants.LogTag, "Main statrted"); - var app = new Application(); - app.Run(args); - Tizen.Log.Info(AppConstants.LogTag, "Main finished"); - } - } -} diff --git a/MusicPlayer.sln b/MusicPlayer.sln deleted file mode 100644 index 531db1c..0000000 --- a/MusicPlayer.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30804.86 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "music-player", "music-player.csproj", "{18A58E69-495D-4F9C-BA77-C969BE9D8104}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {18A58E69-495D-4F9C-BA77-C969BE9D8104}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {18A58E69-495D-4F9C-BA77-C969BE9D8104}.Debug|Any CPU.Build.0 = Debug|Any CPU - {18A58E69-495D-4F9C-BA77-C969BE9D8104}.Release|Any CPU.ActiveCfg = Release|Any CPU - {18A58E69-495D-4F9C-BA77-C969BE9D8104}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7072B878-F218-47CE-84F8-FC9AC39798C6} - EndGlobalSection -EndGlobal diff --git a/ViewModels/AlbumDetailViewModel.cs b/ViewModels/AlbumDetailViewModel.cs deleted file mode 100755 index 5117bc8..0000000 --- a/ViewModels/AlbumDetailViewModel.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System.Collections.Specialized; -using MusicPlayer.Models; -using MusicPlayer.Common; - -namespace MusicPlayer.ViewModels -{ - using AudioInfo = Tizen.Content.MediaContent.AudioInfo; - class AlbumDetailViewModel : PropertyNotifier - { - public AlbumDetailViewModel(MusicAlbum album) - { - Id = album.Id; - AlbumName = album.AlbumName; - ArtistName = album.ArtistName; - AlbumArtPath = album.AlbumArtPath; - OrderedDictionary trackList = AlbumDataProvider.GetAlbumTrackList(album.Id); - listViewModel = new ListViewModel(); - listViewModel.CreateData(trackList); - listViewModel.CollectionChanged += OnAlbumDetailListChanges; - TotalTracks = listViewModel.Count.ToString(); - } - - private void OnAlbumDetailListChanges(object sender, NotifyCollectionChangedEventArgs e) - { - //TODO - TotalTracks = listViewModel.Count.ToString(); - } - - private int id; - - public int Id - { - get => id; - set => id = value; - } - - private string albumName; - - public string AlbumName - { - get => albumName; - set - { - string text = string.Equals(value,"Unknown") ? null : value; - SetProperty(ref albumName, text); - } - } - - private string artistName; - - public string ArtistName - { - get => artistName; - set - { - string text = string.Equals(value, "Unknown") ? null : value; - SetProperty(ref artistName, text); - } - } - - private string albumArtPath; - - public string AlbumArtPath - { - get => albumArtPath; - set => SetProperty(ref albumArtPath, value); - } - - private ListViewModel listViewModel; - - public ListViewModel ListViewModel - { - get => listViewModel; - } - - private string totalTracks; - - public string TotalTracks - { - get => totalTracks; - set - { - string text = string.Equals(value, "1") ? " Track" : " Tracks"; - SetProperty(ref totalTracks, value + text); - } - } - } -} diff --git a/ViewModels/AlbumViewModel.cs b/ViewModels/AlbumViewModel.cs deleted file mode 100755 index a396076..0000000 --- a/ViewModels/AlbumViewModel.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Collections.Specialized; -using MusicPlayer.Models; -using MusicPlayer.Common; - -namespace MusicPlayer.ViewModels -{ - using Album = Tizen.Content.MediaContent.Album; - class AlbumViewModel : PropertyNotifier - { - private AlbumDetailViewModel albumDetailViewModel; - - public AlbumViewModel() - { - OrderedDictionary albumList = AlbumDataProvider.CurrentAlbumList(); - listViewModel = new ListViewModel(); - listViewModel.CreateData(albumList); - listViewModel.CollectionChanged += OnAlbumListChanges; - AlbumCount = listViewModel.Count.ToString(); - } - - private void OnAlbumListChanges(object sender, NotifyCollectionChangedEventArgs e) - { - AlbumCount = listViewModel.Count.ToString(); - } - - public AlbumDetailViewModel getDetailViewModel(MusicAlbum musicAlbum) - { - if(albumDetailViewModel == null) - albumDetailViewModel = new AlbumDetailViewModel(musicAlbum); - else if (albumDetailViewModel.Id != musicAlbum.Id) - albumDetailViewModel = new AlbumDetailViewModel(musicAlbum); - return albumDetailViewModel; - } - - private ListViewModel listViewModel; - - public ListViewModel ListViewModel - { - get => listViewModel; - } - - private string albumCount; - - public string AlbumCount - { - get => albumCount; - set - { - string text = string.Equals(value, "1") ? " album" : " albums"; - SetProperty(ref albumCount, value + text); - } - } - } -} diff --git a/ViewModels/ArtistDetailViewModel.cs b/ViewModels/ArtistDetailViewModel.cs deleted file mode 100755 index 6d09ba3..0000000 --- a/ViewModels/ArtistDetailViewModel.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Collections.Specialized; -using MusicPlayer.Models; -using MusicPlayer.Common; - -namespace MusicPlayer.ViewModels -{ - using Album = Tizen.Content.MediaContent.Album; - using AudioInfo = Tizen.Content.MediaContent.AudioInfo; - class ArtistDetailViewModel : PropertyNotifier - { - - public ArtistDetailViewModel(Artist artist) - { - ArtistName = artist.ArtistName; - TotalCount = artist.TotalCount; - string text = string.Equals(ArtistName, "Unknown") ? "" : ArtistName; - - OrderedDictionary albumList = ArtistDataProvider.GetArtistAlbumList(text); - albumListViewModel = new ListViewModel(); - albumListViewModel.CreateData(albumList); - - OrderedDictionary trackList = ArtistDataProvider.GetArtistTrackList(text); - trackListViewModel = new ListViewModel(); - trackListViewModel.CreateData(trackList); - - groupListViewModel = new ListViewModel(); - - foreach(MusicAlbum album in albumListViewModel) - { - ArtistDetailAlbum artistAlbum = new ArtistDetailAlbum(album); - OrderedDictionary albumTrackList = AlbumDataProvider.GetAlbumTrackList(album.Id); - ListViewModel albumTrackListViewModel = new ListViewModel(); - albumTrackListViewModel.CreateData(albumTrackList); - foreach (Track track in albumTrackListViewModel) - artistAlbum.Add(track); - groupListViewModel.Add(artistAlbum); - } - } - - private string artistName; - - public string ArtistName - { - get => artistName; - set => SetProperty(ref artistName, value); - } - - private string totalCount; - - public string TotalCount - { - get => totalCount; - set => SetProperty(ref totalCount, value); - } - - private readonly ListViewModel groupListViewModel; - public ListViewModel GroupListViewModel => groupListViewModel; - - private readonly ListViewModel albumListViewModel; - public ListViewModel AlbumListViewModel => albumListViewModel; - - private readonly ListViewModel trackListViewModel; - public ListViewModel TrackListViewModel => trackListViewModel; - } -} diff --git a/ViewModels/ArtistViewModel.cs b/ViewModels/ArtistViewModel.cs deleted file mode 100755 index 49d1092..0000000 --- a/ViewModels/ArtistViewModel.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Collections.Specialized; -using System.Collections.Generic; -using MusicPlayer.Models; -using MusicPlayer.Common; - -namespace MusicPlayer.ViewModels -{ - class ArtistViewModel : PropertyNotifier - { - private ArtistDetailViewModel artistDetailViewModel; - - public ArtistViewModel() - { - List artistList = ArtistDataProvider.CurrentArtistList(); - listViewModel = new ListViewModel(); - listViewModel.CreateData(artistList); - listViewModel.CollectionChanged += OnArtistListChanges; - ArtistCount = listViewModel.Count.ToString(); - } - - private void OnArtistListChanges(object sender, NotifyCollectionChangedEventArgs e) - { - artistCount = listViewModel.Count.ToString(); - } - - public ArtistDetailViewModel getDetailViewModel(Artist artist) - { - if (artistDetailViewModel == null) - artistDetailViewModel = new ArtistDetailViewModel(artist); - else if (artistDetailViewModel.ArtistName != artist.ArtistName) - artistDetailViewModel = new ArtistDetailViewModel(artist); - return artistDetailViewModel; - } - - private ListViewModel listViewModel; - - public ListViewModel ListViewModel - { - get => listViewModel; - } - - private string artistCount; - - public string ArtistCount - { - get => artistCount; - set - { - string text = string.Equals(value, "1") ? " artist" : " artists"; - SetProperty(ref artistCount, value + text); - } - } - } -} \ No newline at end of file diff --git a/ViewModels/ListViewModel.cs b/ViewModels/ListViewModel.cs deleted file mode 100755 index 24ea54e..0000000 --- a/ViewModels/ListViewModel.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Collections; -using System.Collections.Specialized; -using System.Collections.ObjectModel; -using MusicPlayer.Models; -using Tizen.Content.MediaContent; -using MusicPlayer.Common; -using System; -using System.Collections.Generic; - -namespace MusicPlayer.ViewModels -{ - class ListViewModel : ObservableCollection where T : new() - { - public ListViewModel() - { - } - - public void CreateData(OrderedDictionary dict) - { - foreach (DictionaryEntry item in dict) - { - Add((T)Activator.CreateInstance(typeof(T), new object[] { (U)item.Value })); - } - Tizen.Log.Debug(AppConstants.LogTag, "Observable list item count: " + this.Count); - } - - public void CreateData(List list) - { - foreach (var item in list) - { - Add((T)Activator.CreateInstance(typeof(T), new object[] { (U)item })); - } - Tizen.Log.Debug(AppConstants.LogTag, "Observable list item count: " + this.Count); - } - - - } -} diff --git a/ViewModels/LyricsViewModel.cs b/ViewModels/LyricsViewModel.cs deleted file mode 100644 index 6307f28..0000000 --- a/ViewModels/LyricsViewModel.cs +++ /dev/null @@ -1,64 +0,0 @@ -using Tizen.Multimedia; -using MusicPlayer.Models; -using MusicPlayer.Common; -using Tizen.NUI; - -namespace MusicPlayer.ViewModels -{ - class LyricsViewModel : PropertyNotifier - { - internal LyricsModel lyricsModel; - - public LyricsViewModel() - { - lyricsModel = new LyricsModel(); - } - - public LyricsViewModel(Track currentTrack) - { - FilePath = currentTrack.FilePath; - lyricsModel = new LyricsModel(currentTrack.ThumbnailPath, GetLyrics(FilePath)); - } - - public string FilePath { get; set; } - - private Track currentTrack; - - public Track CurrentTrack - { - get => currentTrack; - set - { - currentTrack = value; - FilePath = currentTrack.FilePath; - lyricsModel.ThumbPath = currentTrack.ThumbnailPath; - lyricsModel.Lyrics = GetLyrics(FilePath); - } - } - - private Color lyricsBackgroundColor; - - public Color LyricsBackgroundColor - { - get => lyricsBackgroundColor; - set => SetProperty(ref lyricsBackgroundColor, value); - } - - private string GetLyrics(string path) - { - var metadataExtractor = new MetadataExtractor(path); - Metadata metadata = metadataExtractor.GetMetadata(); - string lyrics = metadata.UnsyncLyrics; - if(string.IsNullOrEmpty(lyrics)) - { - LyricsBackgroundColor = Color.Transparent; - return string.Empty; - } - else - { - LyricsBackgroundColor = UIColors.LyricsBackground; - return lyrics; - } - } - } -} diff --git a/ViewModels/PlayerViewModel.cs b/ViewModels/PlayerViewModel.cs deleted file mode 100755 index 0b53d16..0000000 --- a/ViewModels/PlayerViewModel.cs +++ /dev/null @@ -1,414 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using MusicPlayer.Models; -using MusicPlayer.Common; -using MusicPlayer.Core; -using Tizen.NUI; -using Tizen.Multimedia; -using System.Threading.Tasks; - -namespace MusicPlayer.ViewModels -{ - class PlayerViewModel : PropertyNotifier - { - public const string PlayState = "Play"; - public const string PauseState = "Pause"; - private const int PlaybackTimerDuration = 1000; - private const int MinPaletteColorCount = 2; - - internal PlayerModel playerModel; - internal LyricsViewModel lyricsViewModel; - private Timer playbackTimer; - private bool isVolumeChanging; - - public PlayerViewModel() - { - lyricsViewModel = new LyricsViewModel(); - playingListViewModel = new PlayingListViewModel(); - playerModel = new PlayerModel(); - playerModel.ElapsedTime = 0.0f; - PlayingStatus = PlayingStatus.None; - PlayerController.Instance.PlayerEventOccurred += OnPlayerEventOccurred; - playbackTimer = new Timer(PlaybackTimerDuration); - playbackTimer.Tick += OnPlaybackTimerTick; - isVolumeChanging = false; - VolumeLevel = AudioManager.VolumeController.Level[AudioVolumeType.Media]; - AudioManager.VolumeController.Changed += OnVolumeLevelChanged; - HasPreviousTrack = playingListViewModel.HasPrev(); - HasNextTrack = playingListViewModel.HasNext(); - } - - internal PlayingListViewModel playingListViewModel; - - public PlayingListViewModel CurrentPlayingListViewModel - { - get => playingListViewModel; - } - - private string playButtonState; - - public string PlayButtonState - { - get => playButtonState; - set => SetProperty(ref playButtonState, value); - } - - private float volumeLevel; - - public float VolumeLevel - { - get => volumeLevel; - set => SetProperty(ref volumeLevel, value); - } - - private bool hasPreviousTrack; - - public bool HasPreviousTrack - { - get => hasPreviousTrack; - set => SetProperty(ref hasPreviousTrack, value); - } - - private bool hasNextTrack; - - public bool HasNextTrack - { - get => hasNextTrack; - set => SetProperty(ref hasNextTrack, value); - } - - private PropertyMap playerBackground; - - public PropertyMap PlayerBackground - { - get => playerBackground; - set => SetProperty(ref playerBackground, value); - } - - private PlayingStatus playingStatus; - - public PlayingStatus PlayingStatus - { - get => playingStatus; - set => UpdatePlayingStatus(value); - } - - public void SetPlayingList(ListViewModel trackListVM) - { - playingListViewModel.SetTrackListViewModel(trackListVM); - } - - public void SetCurrentTrack(Track track) - { - Tizen.Log.Info(AppConstants.LogTag, "Setting Current track"); - playerModel.CurrentTrack = track; - lyricsViewModel.CurrentTrack = track; - //TO DO need to set index properly - Track current = playingListViewModel.Current(); - if (current == null) - { - Tizen.Log.Error(AppConstants.LogTag, "Current track is null so setting new track"); - playingListViewModel.SetPlayingTrack(track); - } - // updating prev/next button state - HasPreviousTrack = playingListViewModel.HasPrev(); - HasNextTrack = playingListViewModel.HasNext(); - - // SetBackground - SetExtractedBackground(track.ThumbnailPath); - - PlayerController.Instance.Uri = track.FilePath; - StartPlayback(); - } - - public void NextButtonClicked() - { - Track nextTrack = playingListViewModel.Next(); - if (nextTrack == null) - { - Tizen.Log.Error(AppConstants.LogTag, "nextTrack is null"); - StopPlayback(); - return; - } - Tizen.Log.Debug(AppConstants.LogTag, "Next track is: " + nextTrack.TrackTitle); - SetCurrentTrack(nextTrack); - } - - public void PrevButtonClicked() - { - Track previousTrack = playingListViewModel.Prev(); - if (previousTrack == null) - { - Tizen.Log.Error(AppConstants.LogTag, "previousTrack is null"); - StopPlayback(); - return; - } - Tizen.Log.Debug(AppConstants.LogTag, "Prev track is: " + previousTrack.TrackTitle); - SetCurrentTrack(previousTrack); - } - - public void ShuffleChanged() - { - ShuffleMode currentMode = playingListViewModel.ShuffleMode; - playingListViewModel.ShuffleMode = ((currentMode == ShuffleMode.Off) ? ShuffleMode.On : ShuffleMode.Off); - } - - public void RepeatChanged() - { - var values = Enum.GetValues(typeof(RepeatMode)); - int i = 0; - foreach (RepeatMode mode in values) - { - if (playingListViewModel.RepeatMode == mode) - break; - i++; - } - - RepeatMode[] repeatArr = (RepeatMode[])values; - RepeatMode new_mode; - if (i + 1 >= values.Length) - { - new_mode = repeatArr[0]; - } - else - { - new_mode = repeatArr[i + 1]; - } - playingListViewModel.RepeatMode = new_mode; - } - - public void PlayingStatusChanged() - { - if (PlayingStatus == PlayingStatus.Playing) - { - PlayingStatus = PlayingStatus.Paused; - Pause(); - playbackTimer.Stop(); - } - else - { - PlayingStatus = PlayingStatus.Playing; - Resume(); - playbackTimer.Start(); - } - } - - public void UpdatePlayerPosition(float value) - { - int currentPosition = (int)(playerModel.CurrentTrack.DurationInMS * value); - PlayerController.Instance.SetPosition(currentPosition); - playerModel.PlayingTime = TimeSpan.FromMilliseconds(currentPosition).ToString(AppConstants.TimeFormat); - playbackTimer.Start(); - } - - public void StopPlaybackTimer() - { - playbackTimer.Stop(); - } - - public void SetElapsedTime(float value) - { - int currentPosition = (int)(playerModel.CurrentTrack.DurationInMS * value); - playerModel.PlayingTime = TimeSpan.FromMilliseconds(currentPosition).ToString(AppConstants.TimeFormat); - } - - public void VolumeChangeStarted() - { - isVolumeChanging = true; - } - - public void VolumeChangeFinished(int value) - { - VolumeLevelChanged(value); - isVolumeChanging = false; - } - public void VolumeLevelChanged(int value) - { - AudioManager.VolumeController.Level[AudioVolumeType.Media] = value; - } - - private void UpdatePlayingStatus(PlayingStatus status) - { - playingStatus = status; - switch (status) - { - case PlayingStatus.Playing: - PlayButtonState = PauseState; - break; - case PlayingStatus.Paused: // Fall Through - case PlayingStatus.Stopped: // Fall Through - case PlayingStatus.None: - PlayButtonState = PlayState; - break; - } - } - - private bool OnPlaybackTimerTick(object source, Timer.TickEventArgs e) - { - UpdatePlayingTime(); - return true; - } - - private void OnPlayerEventOccurred(object sender, PlayerEventArgs e) - { - Tizen.Log.Error(AppConstants.LogTag, "Player Event Occurred:"); - Tizen.Log.Error(AppConstants.LogTag, "\t"+e.Type.ToString()); - Tizen.Log.Error(AppConstants.LogTag, "\t:"+e.Description); - if(e.Type == EventType.PlaybackCompleted) - { - PlayNext(); - } - } - - private void PlayNext() - { - if(playingListViewModel.RepeatMode == RepeatMode.Off) - { - Tizen.Log.Debug(AppConstants.LogTag, "Repeat is off, can't play next"); - StopPlayback(); - UpdatePlayingTime(); - return; - } - NextButtonClicked(); - } - - private void UpdatePlayingTime() - { - int position = PlayerController.Instance.GetPosition(); - playerModel.ElapsedTime = position / (float)playerModel.CurrentTrack.DurationInMS; - playerModel.PlayingTime = TimeSpan.FromMilliseconds(position).ToString(AppConstants.TimeFormat); - } - - private void StartPlayback() - { - PlayingStatus = PlayingStatus.Playing; - Play(); - playbackTimer.Start(); - } - - private void StopPlayback() - { - PlayingStatus = PlayingStatus.Stopped; - Stop(); - playbackTimer.Stop(); - } - - private void Play() - { - PlayerController.Instance.Play(); - } - private void Pause() - { - PlayerController.Instance.Pause(); - } - private void Resume() - { - PlayerController.Instance.Resume(); - } - private void Stop() - { - PlayerController.Instance.Stop(); - } - - private void OnVolumeLevelChanged(object sender, VolumeChangedEventArgs e) - { - if(e.Type == AudioVolumeType.Media && isVolumeChanging == false) - { - VolumeLevel = e.Level; - } - } - - private ImageVisual CreateImageVisual() - { - ImageVisual visual = new ImageVisual() - { - URL = Resources.GetImagePath() + "gradient_music_light.png", - }; - return visual; - } - - private GradientVisual CreateGradientVisual(PropertyArray stopColor) - { - GradientVisual gradientVisual = new GradientVisual() - { - StartPosition = new Vector2(0.0f, -1.0f), - EndPosition = new Vector2(0.0f, 1.0f), - StopColor = stopColor, - SpreadMethod = GradientVisualSpreadMethodType.Pad, - }; - return gradientVisual; - } - - private PropertyArray GetGradientStopColors(Palette palette) - { - PropertyArray propertyArray = new PropertyArray(); - if(palette == null) - { - Tizen.Log.Error(AppConstants.LogTag, "Color palatte from background is null"); - return propertyArray; - } - - Palette.Swatch lightMutedSwatch = palette.GetLightMutedSwatch(); - Palette.Swatch darkMutedSwatch = palette.GetDarkMutedSwatch(); - if(lightMutedSwatch != null && darkMutedSwatch != null) - { - propertyArray.PushBack(new PropertyValue(lightMutedSwatch.GetRgb())); - propertyArray.PushBack(new PropertyValue(darkMutedSwatch.GetRgb())); - return propertyArray; - } - - Palette.Swatch lightVibrantSwatch = palette.GetLightVibrantSwatch(); - Palette.Swatch darkVibrantSwatch = palette.GetDarkVibrantSwatch(); - if(lightVibrantSwatch != null && darkVibrantSwatch != null) - { - propertyArray.PushBack(new PropertyValue(lightVibrantSwatch.GetRgb())); - propertyArray.PushBack(new PropertyValue(darkVibrantSwatch.GetRgb())); - return propertyArray; - } - - Palette.Swatch mutedSwatch = palette.GetMutedSwatch(); - Palette.Swatch vibrantSwatch = palette.GetVibrantSwatch(); - if(mutedSwatch != null && vibrantSwatch != null) - { - propertyArray.PushBack(new PropertyValue(mutedSwatch.GetRgb())); - propertyArray.PushBack(new PropertyValue(vibrantSwatch.GetRgb())); - return propertyArray; - } - - IReadOnlyCollection swatches = palette.GetSwatches(); - foreach(Palette.Swatch swatch in swatches) - { - if(propertyArray.Count() >= MinPaletteColorCount) - { - return propertyArray; - } - if(swatch != null) - { - propertyArray.PushBack(new PropertyValue(swatch.GetRgb())); - } - } - return propertyArray; - } - - private async void SetExtractedBackground(string path) - { - Tizen.Log.Debug(AppConstants.LogTag, "Path for the color image thumbnail" + path); - Palette palette = await ColorExtractor.GetPaletteAsync(path); - PropertyArray stopColor = GetGradientStopColors(palette); - if (stopColor.Count() < MinPaletteColorCount) - { - Tizen.Log.Info(AppConstants.LogTag, "Palette or palatte values not valid, adding default gradient"); - ImageVisual imageVisual = CreateImageVisual(); - PlayerBackground = imageVisual.OutputVisualMap; - return; - } - else - { - Tizen.Log.Info(AppConstants.LogTag, "setting palette color"); - GradientVisual gradientVisual = CreateGradientVisual(stopColor); - PlayerBackground = gradientVisual.OutputVisualMap; - } - } - } -} diff --git a/ViewModels/PlayingListViewModel.cs b/ViewModels/PlayingListViewModel.cs deleted file mode 100755 index d84e547..0000000 --- a/ViewModels/PlayingListViewModel.cs +++ /dev/null @@ -1,287 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using MusicPlayer.ViewModels; -using System.Threading; -using MusicPlayer.Common; -using MusicPlayer.Models; - -namespace MusicPlayer.ViewModels -{ - public static class ThreadSafeRandom - { - [ThreadStatic] private static Random Local; - - public static Random ThisThreadsRandom - { - get { return Local ??= new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId)); } - } - } - - static class ShuffleExtension - { - public static void Shuffle(this IList list) - { - int n = list.Count; - while (n > 1) - { - n--; - int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1); - T value = list[k]; - list[k] = list[n]; - list[n] = value; - } - } - } - - class PlayingListViewModel : PropertyNotifier - { - private ListViewModel tracklistViewModel; - private List shuffleList; - private int currentIndex; - private RepeatMode repeatMode; - private ShuffleMode shuffleMode; - public event EventHandler ItemsSourceChanged; - private string shuffleButtonUrl; - private string repeatButtonUrl; - - public PlayingListViewModel() - { - shuffleList = new List(); - currentIndex = -1; - tracklistViewModel = null; - RepeatMode = RepeatMode.Off; - ShuffleMode = ShuffleMode.Off; - } - - private void UpdateShuffleList(int count) - { - shuffleList.Clear(); - shuffleList.AddRange(Enumerable.Range(0, count - 1)); - } - - private void OnItemsSourceChanged(EventArgs eventArgs) - { - ItemsSourceChanged?.Invoke(this, eventArgs); - } - - public void SetTrackListViewModel(ListViewModel trackListVM) - { - // Need to check for same VM and in case same VM just update the playing track - Tizen.Log.Info(AppConstants.LogTag, "Setting Current Playing list"); - tracklistViewModel = trackListVM; - currentIndex = -1; - RepeatMode = RepeatMode.Off; - ShuffleMode = ShuffleMode.Off; - OnItemsSourceChanged(new EventArgs()); - } - - public ListViewModel TrackListVM - { - get => tracklistViewModel; - } - - public string ShuffleButtonState - { - get => shuffleButtonUrl; - set => SetProperty(ref shuffleButtonUrl, value); - } - - public ShuffleMode ShuffleMode - { - get => shuffleMode; - set - { - shuffleMode = value; - if(value == ShuffleMode.On) - { - shuffleList.Shuffle(); - } - else - { - if (tracklistViewModel != null) - { - UpdateShuffleList(tracklistViewModel.Count); - } - } - ShuffleButtonState = shuffleMode.ToString(); - } - } - - public string RepeatButtonState - { - get => repeatButtonUrl; - set => SetProperty(ref repeatButtonUrl, value); - } - - public RepeatMode RepeatMode - { - get => repeatMode; - set - { - repeatMode = value; - RepeatButtonState = repeatMode.ToString(); - } - } - - public Track Next() - { - if(currentIndex < 0 ) - { - Tizen.Log.Error(AppConstants.LogTag,"Invalid track index"); - return null; - } - if(RepeatMode == RepeatMode.RepeatOne) - { - return tracklistViewModel[shuffleList[currentIndex]]; - } - else if(RepeatMode == RepeatMode.Off) - { - if (currentIndex + 1 >= shuffleList.Count) - { - return null; - } - else - { - currentIndex += 1; - return tracklistViewModel[shuffleList[currentIndex]]; - } - } - else - { - if (currentIndex + 1 >= shuffleList.Count) - { - currentIndex = 0; - return tracklistViewModel[shuffleList[currentIndex]]; - } - else - { - currentIndex += 1; - return tracklistViewModel[shuffleList[currentIndex]]; - } - } - } - - public Track Prev() - { - if (currentIndex < 0) - { - Tizen.Log.Error(AppConstants.LogTag, "Invalid track index"); - return null; - } - if (RepeatMode == RepeatMode.RepeatOne) - { - return tracklistViewModel[shuffleList[currentIndex]]; - } - else if (RepeatMode == RepeatMode.Off) - { - if (currentIndex - 1 < 0) - { - return null; - } - else - { - currentIndex -= 1; - return tracklistViewModel[shuffleList[currentIndex]]; - } - } - else - { - if (currentIndex - 1 < 0) - { - currentIndex = shuffleList.Count-1; - return tracklistViewModel[shuffleList[currentIndex]]; - } - else - { - currentIndex -= 1; - return tracklistViewModel[shuffleList[currentIndex]]; - } - } - } - - public bool HasNext() - { - if (IsTrackIndexInvalid()) - { - return false; - } - if(RepeatMode == RepeatMode.RepeatOne || RepeatMode == RepeatMode.RepeatAll) - { - return true; - } - else - { - return currentIndex + 1 < shuffleList.Count ? true : false; - } - } - - public bool HasPrev() - { - if (IsTrackIndexInvalid()) - { - return false; - } - if (RepeatMode == RepeatMode.RepeatOne || RepeatMode == RepeatMode.RepeatAll) - { - return true; - } - else - { - return currentIndex - 1 >= 0 ? true : false; - } - } - - public Track Current() - { - if (IsTrackIndexInvalid()) - { - return null; - } - else - { - return tracklistViewModel[shuffleList[currentIndex]]; - } - } - - public void SetPlayingTrack(string mediaId) - { - int count; - for (count = 0; count< tracklistViewModel.Count; ++count) - { - if (mediaId == tracklistViewModel[count].Id) - { - currentIndex = count; - return; - } - } - currentIndex = -1; - } - - public void SetPlayingTrack(Track track) - { - int count; - for (count = 0; count < tracklistViewModel.Count; ++count) - { - if (track == tracklistViewModel[count]) - { - Tizen.Log.Debug(AppConstants.LogTag, "Current track index is " + count); - currentIndex = count; - return; - } - } - currentIndex = -1; - } - - private bool IsTrackIndexInvalid() - { - if(currentIndex < 0 || currentIndex > shuffleList.Count) - { - return true; - } - return false; - } - } -} diff --git a/ViewModels/TrackViewModel.cs b/ViewModels/TrackViewModel.cs deleted file mode 100755 index 833545f..0000000 --- a/ViewModels/TrackViewModel.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Collections.Specialized; -using MusicPlayer.Models; -using MusicPlayer.Common; - -namespace MusicPlayer.ViewModels -{ - using AudioInfo = Tizen.Content.MediaContent.AudioInfo; - class TrackViewModel : PropertyNotifier - { - public TrackViewModel() - { - OrderedDictionary trackList = TrackDataProvider.CurrentTrackList(); - listViewModel = new ListViewModel(); - listViewModel.CreateData(trackList); - listViewModel.CollectionChanged += OnTrackListChanges; - TrackCount = listViewModel.Count.ToString(); - } - - private void OnTrackListChanges(object sender, NotifyCollectionChangedEventArgs e) - { - TrackCount = listViewModel.Count.ToString(); - } - - private ListViewModel listViewModel; - - public ListViewModel ListViewModel - { - get => listViewModel; - } - - private string trackCount; - - public string TrackCount - { - get => trackCount; - set - { - string text = string.Equals(value, "1") ? " track" : " tracks"; - SetProperty(ref trackCount, value + text); - } - } - } -} diff --git a/Views/AlbumDetailLayout.cs b/Views/AlbumDetailLayout.cs deleted file mode 100755 index cb549af..0000000 --- a/Views/AlbumDetailLayout.cs +++ /dev/null @@ -1,142 +0,0 @@ -using Tizen.NUI.Components; -using Tizen.NUI.BaseComponents; -using Tizen.NUI; -using MusicPlayer.Common; - -namespace MusicPlayer.Views -{ - class AlbumDetailLayout : RecyclerViewItem - { - private View itemSeperator; - private TextLabel titleLabel; - private TextLabel subtitleLabel; - private TextLabel additionalLabel; - - private const int LayoutMargin = 16; - private const int LayoutPadding = 32; - private const int SeperatorHeight = 1; - private const int LeftPadding = 64; - private const int X = 0; - - public AlbumDetailLayout(int width = 832, int height = 108) : base() - { - base.OnInitialize(); - base.IsCreateByXaml = true; - WidthSpecification = width; - HeightSpecification = height; - - // to show the rounded rect of the bg - BackgroundColor = Color.Transparent; - - titleLabel = CreateTitleLabel(); - subtitleLabel = CreateSubTitleLabel(); - additionalLabel = CreateAdditionalLabel(width); - itemSeperator = CreateItemSeparator(width, height); - IsCreateByXaml = true; - } - - private TextLabel CreateTitleLabel() - { - TextLabel titleLabel = new TextLabel() - { - Size2D = new Size2D(596, 40), - TextColor = UIColors.HEX001447, - PixelSize = 32, - FontFamily = "BreezeSans", - VerticalAlignment = VerticalAlignment.Center, - Padding=new Extents(LayoutPadding,0,0,0), - IsCreateByXaml = true, - Position2D = new Position2D(X , LayoutMargin), - }; - base.Add(titleLabel); - return titleLabel; - } - - private TextLabel CreateSubTitleLabel() - { - TextLabel subtitleLabel = new TextLabel() - { - Size2D= new Size2D(596,36), - TextColor = UIColors.HEX001447, - PixelSize = 28, - FontFamily = "BreezeSans", - VerticalAlignment = VerticalAlignment.Center, - Padding = new Extents(LayoutPadding, 0, 0, 0), - IsCreateByXaml = true, - Position2D = new Position2D(X , LayoutMargin + 40) - }; - base.Add(subtitleLabel); - return subtitleLabel; - } - - private TextLabel CreateAdditionalLabel(int width) - { - TextLabel additionalLabel = new TextLabel() - { - Size2D= new Size2D(108,36), - TextColor = UIColors.HEX001447, - PixelSize = 28, - FontFamily = "BreezeSans", - VerticalAlignment = VerticalAlignment.Center, - HorizontalAlignment =HorizontalAlignment.End, - IsCreateByXaml = true, - Position2D = new Position2D(width-LayoutPadding-LeftPadding-108, 36) - }; - base.Add(additionalLabel); - return additionalLabel; - } - - private View CreateItemSeparator(int width, int height) - { - View itemSeperator = new View() - { - Size2D = new Size2D(width, SeperatorHeight), - ExcludeLayouting = true, - Position2D = new Position2D(X , height - SeperatorHeight), - BackgroundColor = UIColors.ItemSeperator, - }; - base.Add(itemSeperator); - return itemSeperator; - } - - public TextLabel TitleLabel - { - get => titleLabel; - } - public TextLabel SubtitleLabel - { - get => subtitleLabel; - } - public TextLabel AdditionalLabel - { - get => additionalLabel; - } - - protected override void Dispose(DisposeTypes type) - { - if (Disposed) - { - return; - } - if (type == DisposeTypes.Explicit) - { - base.Remove(itemSeperator); - itemSeperator?.Dispose(); - itemSeperator = null; - - base.Remove(titleLabel); - titleLabel?.Dispose(); - titleLabel = null; - - base.Remove(subtitleLabel); - subtitleLabel?.Dispose(); - subtitleLabel = null; - - base.Remove(additionalLabel); - additionalLabel?.Dispose(); - additionalLabel = null; - } - base.Dispose(type); - } - } -} diff --git a/Views/AlbumDetailView.cs b/Views/AlbumDetailView.cs deleted file mode 100755 index b39e11f..0000000 --- a/Views/AlbumDetailView.cs +++ /dev/null @@ -1,243 +0,0 @@ -using MusicPlayer.ViewModels; -using Tizen.NUI.Components; -using Tizen.NUI.BaseComponents; -using Tizen.NUI; -using Tizen.NUI.Binding; -using MusicPlayer.Common; - -namespace MusicPlayer.Views -{ - class AlbumDetailView : View - { - private const int LayoutPadding = 64; - private const int IconSize = 48; - private const int AlbumArtSize = 520; - private const int ControlViewWidth = 960; - private const int ControlViewHeight = 60; - private const int ControlViewMargin = 6; - - private BaseView baseView; - private View contentView; - private View leftView; - private View rightView; - private ImageView albumArtIcon; - private TextLabel albumNameLabel; - private TextLabel albumArtistLabel; - private View controlsView; - private TextLabel trackCountLabel; - private Button playAllIcon; // TODO need to implement playall feature - private Button shuffleAndPlayAllIcon; // TODO need to implement playlist manager - private CollectionView collectionView; - - private AlbumDetailViewModel viewModel; - public AlbumDetailView(AlbumDetailViewModel viewModel) : base() - { - this.viewModel = viewModel; - BindingContext = viewModel; - BackgroundColor = UIColors.HEXEEEFF1; - WidthResizePolicy = ResizePolicyType.FillToParent; - HeightResizePolicy = ResizePolicyType.FillToParent; - - //TODO need to change this part after implementation of Command Interface - baseView = new BaseView() - { - Title = viewModel.AlbumName, - BackButton = true, - MoreButton = true, - SearchButton = true, - BackgroundColor = UIColors.HEXEEEFF1, - }; - base.Add(baseView); - contentView = new View() - { - WidthSpecification = LayoutParamPolicies.MatchParent, - HeightSpecification = 876, - Layout = new FlexLayout() - { - Direction = FlexLayout.FlexDirection.Row, - ItemsAlignment = FlexLayout.AlignmentType.FlexStart, - Justification = FlexLayout.FlexJustification.FlexStart, - }, - }; - baseView.SetContent = contentView; - - leftView = CreateLeftView(); - rightView = CreateRightView(); - controlsView = AddControlView(); - AddControlElements(); - collectionView = AddCollectionView(); - AddAlbumArt(); - AddAlbumInfo(); - } - - private void OnTrackSelection(object sender, SelectionChangedEventArgs e) - { - - } - - private Button CreateButton(string url, int x, int y) - { - ButtonStyle buttonStyle = new ButtonStyle() - { - Icon = new ImageViewStyle() - { - ResourceUrl = url, - }, - IsSelectable = false, - IsEnabled = true, - }; - - Button button = new Button(buttonStyle) - { - Size2D = new Size2D(IconSize, IconSize), - Position2D = new Position2D(x, y), - }; - return button; - } - - private View CreateLeftView() - { - View leftView = new View() - { - BackgroundColor = UIColors.HEXEEEFF1, - Size2D = new Size2D(Window.Instance.WindowSize.Width / 2, 752), - Position2D = new Position2D(0, 0), - Layout = new FlexLayout - { - Direction = FlexLayout.FlexDirection.Column, - ItemsAlignment = FlexLayout.AlignmentType.Center, - Justification = FlexLayout.FlexJustification.FlexStart, - }, - Padding = new Extents(0, 0, ControlViewHeight, 42), - }; - contentView.Add(leftView); - return leftView; - } - - private View CreateRightView() - { - View rightView = new View() - { - BackgroundColor = UIColors.HEXEEEFF1, - Size2D = new Size2D(Window.Instance.WindowSize.Width / 2, 752), - Position2D = new Position2D(Window.Instance.WindowSize.Width / 2, 0), - Layout = new FlexLayout - { - Direction = FlexLayout.FlexDirection.Column, - ItemsAlignment = FlexLayout.AlignmentType.Center, - Justification = FlexLayout.FlexJustification.FlexStart, - }, - }; - contentView.Add(rightView); - return rightView; - } - - private void AddAlbumArt() - { - albumArtIcon = new ImageView() - { - BackgroundColor = UIColors.HEXEEEFF1, - Size2D = new Size2D(AlbumArtSize, AlbumArtSize), - }; - albumArtIcon.SetBinding(ImageView.ResourceUrlProperty, "AlbumArtPath"); - leftView.Add(albumArtIcon); - } - private void AddAlbumInfo() - { - albumNameLabel = new TextLabel() - { - Text = "ALBUM NAME", - Size2D = new Size2D(640, 48), - PixelSize = 36, - Margin = new Extents(0, 0, 32, 0), - FontFamily = "BreezeSans", - TextColor = UIColors.HEX001447, - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - Ellipsis = true, - }; - albumNameLabel.SetBinding(TextLabel.TextProperty, "AlbumName"); - leftView.Add(albumNameLabel); - albumArtistLabel = new TextLabel() - { - Text = "ARTIST NAME", - Size2D = new Size2D(640, 36), - PixelSize = 28, - Margin = new Extents(0, 0, 14, 0), - FontFamily = "BreezeSans", - TextColor = UIColors.HEX000209, - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - Ellipsis = true, - }; - albumArtistLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); - leftView.Add(albumArtistLabel); - - } - private View AddControlView() - { - View controlsView = new View() - { - BackgroundColor = UIColors.HEXEEEFF1, - Size2D = new Size2D(ControlViewWidth, ControlViewHeight), - Padding = new Extents(LayoutPadding, LayoutPadding, ControlViewMargin, ControlViewMargin), - }; - rightView.Add(controlsView); - return controlsView; - } - - private void AddControlElements() - { - trackCountLabel = new TextLabel() - { - Text = "TRACK COUNT", - Size2D = new Size2D(664, 36), - Position2D = new Position2D(LayoutPadding, 12), - PixelSize = 28, - Margin = new Extents(0, 0, ControlViewMargin, ControlViewMargin), - FontFamily = "BreezeSans", - TextColor = UIColors.HEX001447, - HorizontalAlignment = HorizontalAlignment.Begin, - VerticalAlignment = VerticalAlignment.Center, - }; - trackCountLabel.SetBinding(TextLabel.TextProperty, "TotalTracks"); - controlsView.Add(trackCountLabel); - - playAllIcon = CreateButton(Resources.GetImagePath() + "playlist_active.png.png", Window.Instance.WindowSize.Width / 2 - LayoutPadding - IconSize, ControlViewMargin); - playAllIcon.Margin = new Extents(40, 0, 0, 0); - controlsView.Add(playAllIcon); - - shuffleAndPlayAllIcon = CreateButton(Resources.GetImagePath() + "shuffle_on.png", Window.Instance.WindowSize.Width / 2 - LayoutPadding - 2 * IconSize - 40, ControlViewMargin); - playAllIcon.Margin = new Extents(32, 0, 0, 0); - controlsView.Add(shuffleAndPlayAllIcon); - - } - - private CollectionView AddCollectionView() - { - CollectionView collectionView = new CollectionView() - { - Size2D = new Size2D(832, 108), - BackgroundImage = Resources.GetImagePath() + "list_view_bg.png", - ItemsLayouter = new LinearLayouter(), - ItemTemplate = new DataTemplate(() => - { - AlbumDetailLayout layout = new AlbumDetailLayout(); - layout.TitleLabel.SetBinding(TextLabel.TextProperty, "TrackTitle"); - layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); - layout.AdditionalLabel.SetBinding(TextLabel.TextProperty, "Duration"); - return layout; - }), - ScrollingDirection = ScrollableBase.Direction.Vertical, - HeightSpecification = LayoutParamPolicies.WrapContent, - SelectionMode = ItemSelectionMode.Single, - }; - rightView.Add(collectionView); - FlexLayout.SetFlexGrow(collectionView, 1); - FlexLayout.SetFlexShrink(collectionView, 1); - collectionView.ItemsSource = viewModel.ListViewModel; - collectionView.SelectionChanged += OnTrackSelection; - return collectionView; - } - } -} diff --git a/Views/AlbumView.cs b/Views/AlbumView.cs deleted file mode 100755 index 16bddc9..0000000 --- a/Views/AlbumView.cs +++ /dev/null @@ -1,72 +0,0 @@ -using MusicPlayer.ViewModels; -using Tizen.NUI.Components; -using Tizen.NUI.BaseComponents; -using Tizen.NUI; -using Tizen.NUI.Binding; -using MusicPlayer.Common; -using MusicPlayer.Models; - -namespace MusicPlayer.Views -{ - class AlbumView : BaseContentView - { - private AlbumViewModel viewModel; - private TextLabel albumCountLabel; - - public AlbumView(AlbumViewModel viewModel) - { - this.viewModel = viewModel; - BindingContext = viewModel; - collectionView.ItemsSource = viewModel.ListViewModel; - collectionView.ItemTemplate = new DataTemplate(() => - { - ListItemLayout layout = new ListItemLayout(); - layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "AlbumArtPath"); - layout.TitleLabel.SetBinding(TextLabel.TextProperty, "AlbumName"); - layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); - return layout; - }); - collectionView.ScrollingDirection = ScrollableBase.Direction.Vertical; - collectionView.WidthSpecification = LayoutParamPolicies.WrapContent; - collectionView.SelectionMode = ItemSelectionMode.Single; - collectionView.SelectionChanged += OnAlbumSelection; - - albumCountLabel = new TextLabel() - { - PixelSize = 28, - Text = "ALBUM COUNT", - TextColor = UIColors.HEX001447, - VerticalAlignment = VerticalAlignment.Center, - FontFamily = "BreezeSans", - IsCreateByXaml = true, - }; - titleView.Add(albumCountLabel); - albumCountLabel.SetBinding(TextLabel.TextProperty, "AlbumCount"); - RelativeLayout.SetLeftTarget(albumCountLabel, titleView); - RelativeLayout.SetLeftRelativeOffset(albumCountLabel, 1.0f); - RelativeLayout.SetRightRelativeOffset(albumCountLabel, 0.0f); - RelativeLayout.SetFillHorizontal(albumCountLabel, true); - } - private void OnAlbumSelection(object sender, SelectionChangedEventArgs e) - { - MusicAlbum currentAlbum= (MusicAlbum)collectionView.SelectedItem; - // viewModel.getDetailViewModel(currentAlbum) => need to replace direct function call on viewModel class with command interface - AlbumDetailView view = new AlbumDetailView(viewModel.getDetailViewModel(currentAlbum)); - Window.Instance.Add(view); - } - protected override void Dispose(DisposeTypes type) - { - if (Disposed) - { - return; - } - if (type == DisposeTypes.Explicit) - { - titleView.Remove(albumCountLabel); - albumCountLabel.Dispose(); - albumCountLabel = null; - } - base.Dispose(type); - } - } -} diff --git a/Views/ArtistDetailGroupLayout.cs b/Views/ArtistDetailGroupLayout.cs deleted file mode 100755 index 4d1e63c..0000000 --- a/Views/ArtistDetailGroupLayout.cs +++ /dev/null @@ -1,118 +0,0 @@ -using Tizen.NUI.Components; -using Tizen.NUI.BaseComponents; -using Tizen.NUI; -using MusicPlayer.Common; - -namespace MusicPlayer.Views -{ - class ArtistDetailGroupLayout : RecyclerViewItem - { - private static int Width = 1792; - private static int Height = 108; - - private const int IconSize = 64; - private const int LayoutPadding = 32; - private const int SeperatorHeight = 1; - private const int LeftPadding = 64; - private const int x = 0; - - private View itemSeperator; - private TextLabel titleLabel; - private ImageView icon; - - public ArtistDetailGroupLayout(int width = 1792, int height = 108) : base() - { - base.OnInitialize(); - base.IsCreateByXaml = true; - Width = width; - Height = height; - WidthSpecification = Width; - HeightSpecification = Height; - - // to show the rounded rect of the bg - BackgroundColor = Color.Transparent; - - icon = CreateIcon(); - titleLabel = CreateTitleLabel(); - itemSeperator = CreateItemSeparator(); - IsCreateByXaml = true; - } - - private ImageView CreateIcon() - { - ImageView icon = new ImageView() - { - WidthSpecification = IconSize, - HeightSpecification = IconSize, - IsCreateByXaml = true, - Position2D = new Position2D(x, (Height / 2) - (IconSize / 2)), - }; - base.Add(icon); - return icon; - } - - private View CreateItemSeparator() - { - View itemSeperator = new View() - { - WidthSpecification = (Width - (2 * LeftPadding)), - HeightSpecification = SeperatorHeight, - ExcludeLayouting = true, - Position2D = new Position2D(x, Height - SeperatorHeight), - BackgroundColor = UIColors.ItemSeperator, - }; - base.Add(itemSeperator); - return itemSeperator; - } - - private TextLabel CreateTitleLabel() - { - TextLabel titleLabel = new TextLabel() - { - WidthSpecification = (Width - (2 * LeftPadding) - IconSize - LayoutPadding), - HeightSpecification = 40, - TextColor = UIColors.HEX001447, - PixelSize = 32, - FontFamily = "BreezeSans", - VerticalAlignment = VerticalAlignment.Center, - IsCreateByXaml = true, - Position2D = new Position2D(x + IconSize + LayoutPadding, 34), - }; - base.Add(titleLabel); - return titleLabel; - } - - public ImageView Icon - { - get => icon; - } - - public TextLabel TitleLabel - { - get => titleLabel; - } - - protected override void Dispose(DisposeTypes type) - { - if (Disposed) - { - return; - } - if (type == DisposeTypes.Explicit) - { - base.Remove(itemSeperator); - itemSeperator?.Dispose(); - itemSeperator = null; - - base.Remove(icon); - icon?.Dispose(); - icon = null; - - base.Remove(titleLabel); - titleLabel?.Dispose(); - titleLabel = null; - } - base.Dispose(type); - } - } -} diff --git a/Views/ArtistDetailItemLayout.cs b/Views/ArtistDetailItemLayout.cs deleted file mode 100755 index 95907ba..0000000 --- a/Views/ArtistDetailItemLayout.cs +++ /dev/null @@ -1,122 +0,0 @@ -using Tizen.NUI.Components; -using Tizen.NUI.BaseComponents; -using Tizen.NUI; -using MusicPlayer.Common; - -namespace MusicPlayer.Views -{ - class ArtistDetailItemLayout : RecyclerViewItem - { - private static int Width = 1792; - private static int Height = 108; - - private const int LayoutPadding = 32; - private const int SeperatorHeight = 1; - private const int LeftPadding = 64; - private const int x = 0; - - private View itemSeperator; - private TextLabel titleLabel; - private TextLabel extraLabel; - - public ArtistDetailItemLayout(int width = 1792, int height = 108) : base() - { - base.OnInitialize(); - base.IsCreateByXaml = true; - Width = width; - Height = height; - WidthSpecification = Width; - HeightSpecification = Height; - - // to show the rounded rect of the bg - BackgroundColor = Color.Transparent; - - titleLabel = CreateTitleLabel(); - extraLabel = CreateExtraLabel(); - itemSeperator = CreateItemSeparator(); - IsCreateByXaml = true; - } - - private View CreateItemSeparator() - { - View itemSeperator = new View() - { - WidthSpecification = (Width - (2 * LeftPadding)), - HeightSpecification = SeperatorHeight, - ExcludeLayouting = true, - Position2D = new Position2D(x, Height - SeperatorHeight), - BackgroundColor = UIColors.ItemSeperator, - }; - base.Add(itemSeperator); - return itemSeperator; - } - - private TextLabel CreateTitleLabel() - { - TextLabel titleLabel = new TextLabel() - { - WidthSpecification = 1272, - HeightSpecification = 40, - TextColor = UIColors.HEX001447, - PixelSize = 32, - FontFamily = "BreezeSans", - VerticalAlignment = VerticalAlignment.Center, - IsCreateByXaml = true, - Position2D = new Position2D(x, 34), - }; - base.Add(titleLabel); - return titleLabel; - } - - private TextLabel CreateExtraLabel() - { - TextLabel extraLabel = new TextLabel() - { - WidthSpecification = 360, - HeightSpecification = 36, - TextColor = UIColors.HEX001447, - PixelSize = 28, - FontFamily = "BreezeSans", - VerticalAlignment = VerticalAlignment.Center, - HorizontalAlignment = HorizontalAlignment.End, - IsCreateByXaml = true, - Position2D = new Position2D((x + 1272 + LayoutPadding), 36) - }; - base.Add(extraLabel); - return extraLabel; - } - - public TextLabel TitleLabel - { - get => titleLabel; - } - - public TextLabel ExtraLabel - { - get => extraLabel; - } - - protected override void Dispose(DisposeTypes type) - { - if (Disposed) - { - return; - } - if (type == DisposeTypes.Explicit) - { - base.Remove(itemSeperator); - itemSeperator?.Dispose(); - itemSeperator = null; - - base.Remove(titleLabel); - titleLabel?.Dispose(); - titleLabel = null; - - base.Remove(extraLabel); - extraLabel?.Dispose(); - extraLabel = null; - } - base.Dispose(type); - } - } -} diff --git a/Views/ArtistDetailView.cs b/Views/ArtistDetailView.cs deleted file mode 100755 index 91a143a..0000000 --- a/Views/ArtistDetailView.cs +++ /dev/null @@ -1,160 +0,0 @@ -using MusicPlayer.ViewModels; -using Tizen.NUI.Components; -using Tizen.NUI.BaseComponents; -using Tizen.NUI; -using Tizen.NUI.Binding; -using MusicPlayer.Common; -using MusicPlayer.Models; - -namespace MusicPlayer.Views -{ - class ArtistDetailView : View //BaseContentView - { - private const int LayoutPadding = 64; - private const int IconSize = 48; - - private BaseView baseView; - private View contentView; - private View topView; - private TextLabel totalCountLabel; - private Button playAllIcon; // TODO need to implement playall feature - private Button shuffleAndPlayAllIcon; // TODO need to implement playlist manager - private CollectionView collectionView; - - private ArtistDetailViewModel viewModel; - - public ArtistDetailView(ArtistDetailViewModel viewModel) : base() - { - this.viewModel = viewModel; - BindingContext = viewModel; - BackgroundColor = UIColors.HEXEEEFF1; - WidthResizePolicy = ResizePolicyType.FillToParent; - HeightResizePolicy = ResizePolicyType.FillToParent; - - //TODO need to change this part after implementation of Command Interface - baseView = new BaseView() - { - Title = viewModel.ArtistName, - BackButton = true, - MoreButton = true, - SearchButton = true, - BackgroundColor = UIColors.HEXEEEFF1, - }; - base.Add(baseView); - contentView = new View() - { - WidthSpecification = LayoutParamPolicies.MatchParent, - HeightSpecification = 876, - Layout = new FlexLayout() - { - Direction = FlexLayout.FlexDirection.Column, - Padding = new Extents(LayoutPadding, LayoutPadding, 0, 0), - }, - }; - baseView.SetContent = contentView; - - topView = CreateTopView(); - AddTitle(); - AddButtons(); - collectionView = AddCollectionView(); - } - - private void OnTrackSelection(object sender, SelectionChangedEventArgs e) - { - - } - - private Button CreateButton(string url, int x, int y) - { - ButtonStyle buttonStyle = new ButtonStyle() - { - Icon = new ImageViewStyle() - { - ResourceUrl = url, - }, - IsSelectable = false, - IsEnabled = true, - }; - - Button button = new Button(buttonStyle) - { - Size2D = new Size2D(IconSize, IconSize), - Position2D = new Position2D(x, y), - }; - return button; - } - - private View CreateTopView() - { - View topView = new View() - { - BackgroundColor = UIColors.HEXEEEFF1, - Size2D = new Size2D(Window.Instance.WindowSize.Width - 2 * LayoutPadding, 60), - }; - contentView.Add(topView); - return topView; - } - - private void AddTitle() - { - totalCountLabel = new TextLabel() - { - Size2D = new Size2D(1624, 36), - Position2D = new Position2D(0, 12), - PixelSize = 28, - Text = "TOTAL COUNT", - TextColor = UIColors.HEX001447, - VerticalAlignment = VerticalAlignment.Center, - FontFamily = "BreezeSans", - IsCreateByXaml = true, - }; - topView.Add(totalCountLabel); - totalCountLabel.SetBinding(TextLabel.TextProperty, "TotalCount"); - } - - private void AddButtons() - { - playAllIcon = CreateButton(Resources.GetImagePath() + "playlist_active.png", Window.Instance.WindowSize.Width - 2 * LayoutPadding - IconSize, 6); - playAllIcon.Margin = new Extents(40, 0, 0, 0); - topView.Add(playAllIcon); - - shuffleAndPlayAllIcon = CreateButton(Resources.GetImagePath() + "shuffle_on.png", Window.Instance.WindowSize.Width - 2 * LayoutPadding - 2 * IconSize - 40, 6); - playAllIcon.Margin = new Extents(32, 0, 0, 0); - topView.Add(shuffleAndPlayAllIcon); - } - - private CollectionView AddCollectionView() - { - CollectionView collectionView = new CollectionView() - { - Size2D = new Size2D(1792, 108), - BackgroundImage = Resources.GetImagePath() + "list_view_bg.png", - ItemsLayouter = new LinearLayouter(), - ItemTemplate = new DataTemplate(() => - { - ArtistDetailItemLayout layout = new ArtistDetailItemLayout(); - layout.TitleLabel.SetBinding(TextLabel.TextProperty, "TrackTitle"); - layout.ExtraLabel.SetBinding(TextLabel.TextProperty, "Duration"); - return layout; - }), - GroupHeaderTemplate = new DataTemplate(() => - { - ArtistDetailGroupLayout group = new ArtistDetailGroupLayout(); - group.Icon.SetBinding(ImageView.ResourceUrlProperty, "AlbumArtPath"); - group.TitleLabel.SetBinding(TextLabel.TextProperty, "AlbumName"); - return group; - }), - IsGrouped = true, - ScrollingDirection = ScrollableBase.Direction.Vertical, - HeightSpecification = LayoutParamPolicies.WrapContent, - SelectionMode = ItemSelectionMode.Single, - }; - contentView.Add(collectionView); - FlexLayout.SetFlexGrow(collectionView, 1); - FlexLayout.SetFlexShrink(collectionView, 1); - collectionView.ItemsSource = viewModel.GroupListViewModel; - collectionView.SelectionChanged += OnTrackSelection; - return collectionView; - } - } -} diff --git a/Views/ArtistView.cs b/Views/ArtistView.cs deleted file mode 100755 index f74e075..0000000 --- a/Views/ArtistView.cs +++ /dev/null @@ -1,71 +0,0 @@ -using MusicPlayer.ViewModels; -using Tizen.NUI.Components; -using Tizen.NUI.BaseComponents; -using Tizen.NUI; -using Tizen.NUI.Binding; -using MusicPlayer.Common; -using MusicPlayer.Models; - -namespace MusicPlayer.Views -{ - class ArtistView : BaseContentView - { - private ArtistViewModel viewModel; - private TextLabel artistCountLabel; - - public ArtistView(ArtistViewModel viewModel) - { - this.viewModel = viewModel; - BindingContext = viewModel; - collectionView.ItemsSource = viewModel.ListViewModel; - collectionView.ItemTemplate = new DataTemplate(() => - { - ListItemLayout layout = new ListItemLayout(); - layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "AlbumArtPath"); - layout.TitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); - layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "TotalCount"); - return layout; - }); - collectionView.ScrollingDirection = ScrollableBase.Direction.Vertical; - collectionView.WidthSpecification = LayoutParamPolicies.WrapContent; - collectionView.SelectionMode = ItemSelectionMode.Single; - collectionView.SelectionChanged += OnArtistSelection; - - artistCountLabel = new TextLabel() - { - PixelSize = 28, - Text = "ARTIST COUNT", - TextColor = UIColors.HEX001447, - VerticalAlignment = VerticalAlignment.Center, - FontFamily = "BreezeSans", - IsCreateByXaml = true, - }; - titleView.Add(artistCountLabel); - artistCountLabel.SetBinding(TextLabel.TextProperty, "ArtistCount"); - RelativeLayout.SetLeftTarget(artistCountLabel, titleView); - RelativeLayout.SetLeftRelativeOffset(artistCountLabel, 1.0f); - RelativeLayout.SetRightRelativeOffset(artistCountLabel, 0.0f); - RelativeLayout.SetFillHorizontal(artistCountLabel, true); - } - private void OnArtistSelection(object sender, SelectionChangedEventArgs e) - { - Artist currentArtist = (Artist)collectionView.SelectedItem; - ArtistDetailView view = new ArtistDetailView(viewModel.getDetailViewModel(currentArtist)); - Window.Instance.Add(view); - } - protected override void Dispose(DisposeTypes type) - { - if (Disposed) - { - return; - } - if (type == DisposeTypes.Explicit) - { - titleView.Remove(artistCountLabel); - artistCountLabel.Dispose(); - artistCountLabel = null; - } - base.Dispose(type); - } - } -} \ No newline at end of file diff --git a/Views/BaseContentView.cs b/Views/BaseContentView.cs deleted file mode 100755 index 5aa5c44..0000000 --- a/Views/BaseContentView.cs +++ /dev/null @@ -1,89 +0,0 @@ -using MusicPlayer.Common; -using Tizen.NUI; -using Tizen.NUI.BaseComponents; -using Tizen.NUI.Components; - -namespace MusicPlayer.Views -{ - class BaseContentView : View - { - protected View titleView; - protected CollectionView collectionView; - public BaseContentView() : base() - { - ThemeChangeSensitive = true; - WidthResizePolicy = ResizePolicyType.FillToParent; - HeightResizePolicy = ResizePolicyType.FillToParent; - Layout = new FlexLayout() - { - Direction = FlexLayout.FlexDirection.Column, - Padding = new Extents(64, 64, 0, 0), - }; - titleView = new View() - { - ThemeChangeSensitive = true, - WidthSpecification = LayoutParamPolicies.MatchParent, - HeightSpecification = 60, - Layout = new RelativeLayout() - { - Padding = new Extents(0, 0, 13, 13), - }, - }; - base.Add(titleView); - FlexLayout.SetFlexGrow(titleView, 0); - FlexLayout.SetFlexShrink(titleView, 0); - - collectionView = new CollectionView() - { - ThemeChangeSensitive = true, - Size2D = new Size2D(1792, 108), - Margin = new Extents(0, 0, 0, 2), - BackgroundImage = GetBackgroundImagePath(ThemeManager.PlatformThemeId), - ItemsLayouter = new LinearLayouter(), - ScrollingDirection = ScrollableBase.Direction.Vertical, - WidthSpecification = LayoutParamPolicies.MatchParent, - HeightSpecification = LayoutParamPolicies.WrapContent, - SelectionMode = ItemSelectionMode.Single, - }; - base.Add(collectionView); - FlexLayout.SetFlexGrow(collectionView, 1); - FlexLayout.SetFlexShrink(collectionView, 1); - } - - private string GetBackgroundImagePath(string platformThemeId) - { - if(platformThemeId.Equals(AppConstants.DarkPlatformThemeId)) - { - return Resources.GetImagePath() + "dark/list_view_bg.png"; - } - else - { - return Resources.GetImagePath() + "light/list_view_bg.png"; - } - } - - protected override void OnThemeChanged(object sender, ThemeChangedEventArgs e) - { - base.OnThemeChanged(sender, e); - if(e.IsPlatformThemeChanged) - { - collectionView.BackgroundImage = GetBackgroundImagePath(e.PlatformThemeId); - } - } - - protected override void Dispose(DisposeTypes type) - { - if (type == DisposeTypes.Explicit) - { - base.Remove(titleView); - titleView.Dispose(); - titleView = null; - - base.Remove(collectionView); - collectionView.Dispose(); - collectionView = null; - } - base.Dispose(type); - } - } -} diff --git a/Views/BaseView.cs b/Views/BaseView.cs deleted file mode 100755 index 1cddb26..0000000 --- a/Views/BaseView.cs +++ /dev/null @@ -1,268 +0,0 @@ -using System.Collections.Generic; -using Tizen.NUI; -using Tizen.NUI.BaseComponents; -using Tizen.NUI.Components; -using Tizen.NUI.Binding; -using MusicPlayer.Common; - -namespace MusicPlayer.Views -{ - class BaseView : View - { - private View topView; - private View bottomView; // TODO Used this for MiniController UI - private View contentView; - private TextLabel titleLabel; - private Button backButton; - private Button moreButton; - private Button searchButton; - private Tab tabs; - - // TODO these name strings are temporary...once the po files are added - // need to use Translatable names. - private static string[] TabNames = new string[] - { - "Playlists", - "Tracks", - "Albums", - "Artists", - }; - public BaseView() : base() - { - ThemeChangeSensitive = true; - WidthSpecification = LayoutParamPolicies.MatchParent; - HeightSpecification = LayoutParamPolicies.MatchParent; - Layout = new FlexLayout() - { - Direction = FlexLayout.FlexDirection.Column, - ItemsAlignment = FlexLayout.AlignmentType.FlexStart, - Justification = FlexLayout.FlexJustification.FlexStart, - }; - topView = new View() - { - ThemeChangeSensitive = true, - WidthSpecification = LayoutParamPolicies.MatchParent, - HeightSpecification = 120, - Layout = new RelativeLayout() - { - Padding = new Extents(64, 64, 30, 30), - }, - }; - base.Add(topView); - FlexLayout.SetFlexGrow(topView, 0); - FlexLayout.SetFlexShrink(topView, 0); - titleLabel = new TextLabel() - { - ThemeChangeSensitive = true, - Text = "Music", - PixelSize = 40, - FontFamily = "BreezeSans", - TextColor = UIColors.HEX000209, - HorizontalAlignment = HorizontalAlignment.Begin, - Margin = new Extents(0, 0, 6, 6), - Ellipsis = true, - }; - topView.Add(titleLabel); - titleLabel.SetBinding(TextLabel.TextProperty, "Title"); - RelativeLayout.SetLeftTarget(titleLabel, topView); - RelativeLayout.SetLeftRelativeOffset(titleLabel, 0.0f); - RelativeLayout.SetRightTarget(titleLabel, topView); - RelativeLayout.SetRightRelativeOffset(titleLabel, 1.0f); - RelativeLayout.SetFillHorizontal(titleLabel, true); - - contentView = new View() - { - ThemeChangeSensitive = true, - WidthSpecification = LayoutParamPolicies.MatchParent, - HeightSpecification = 876, - }; - base.Add(contentView); - FlexLayout.SetFlexGrow(contentView, 1); - FlexLayout.SetFlexShrink(contentView, 1); - - tabs = new Tab() - { - ThemeChangeSensitive = true, - Size2D = new Size2D(Window.Instance.Size.Width, 84), - WidthSpecification = LayoutParamPolicies.MatchParent, - HeightSpecification = 84, - UnderLineBackgroundColor = Color.Blue, - UnderLineSize = new Size2D(1, 3), - PointSize = 25, - BackgroundColor = Color.White, - }; - tabs.TextColorSelector = new ColorSelector - { - Normal = Color.Black, - Selected = Color.Magenta, - }; - base.Add(tabs); - for(int i = 0; i<4; ++i) - { - Tab.TabItemData item = new Tab.TabItemData(); - item.Text = TabNames[i]; - tabs.AddItem(item); - } - tabs.SelectedItemIndex = 1; - - backButton = null; - moreButton = null; - searchButton = null; - } - - public Tab Tabs - { - get => tabs; - } - - public string Title - { - get => titleLabel.Text; - set { titleLabel.Text = value;} - } - - public bool BackButton - { - set - { - if (value) - { - ButtonStyle buttonStyle = new ButtonStyle() - { - Icon = new ImageViewStyle() - { - ResourceUrl = Resources.GetImagePath() + "back_button.png", - }, - IsSelectable = false, - IsEnabled = true, - }; - - backButton = new Button(buttonStyle) - { - ThemeChangeSensitive = true, - Size2D = new Size2D(48, 48), - Margin = new Extents(0, 24, 6, 6), - }; - topView.Add(backButton); - - RelativeLayout.SetLeftRelativeOffset(backButton, 0.0f); - RelativeLayout.SetRightRelativeOffset(backButton, 0.0f); - RelativeLayout.SetHorizontalAlignment(backButton, RelativeLayout.Alignment.Start); - - RelativeLayout.SetLeftTarget(titleLabel, backButton); - RelativeLayout.SetLeftRelativeOffset(titleLabel, 1.0f); - } - } - } - - public bool MoreButton - { - set - { - if (value) - { - ButtonStyle buttonStyle = new ButtonStyle() - { - Icon = new ImageViewStyle() - { - ResourceUrl = Resources.GetImagePath() + "more.png", - }, - IsSelectable = false, - IsEnabled = true, - }; - moreButton = new Button(buttonStyle) - { - ThemeChangeSensitive = true, - Size2D = new Size2D(48, 48), - Margin = new Extents(32, 0, 6, 6), - }; - topView.Add(moreButton); - RelativeLayout.SetLeftRelativeOffset(moreButton, 1.0f); - RelativeLayout.SetRightRelativeOffset(moreButton, 1.0f); - RelativeLayout.SetHorizontalAlignment(moreButton, RelativeLayout.Alignment.End); - - RelativeLayout.SetRightTarget(titleLabel, moreButton); - RelativeLayout.SetRightRelativeOffset(titleLabel, 0.0f); - } - } - } - - public bool SearchButton - { - set - { - if (value) - { - ButtonStyle buttonStyle = new ButtonStyle() - { - Icon = new ImageViewStyle() - { - ResourceUrl = Resources.GetImagePath() + "search_icon.png", - }, - IsSelectable = false, - IsEnabled = true, - }; - searchButton = new Button(buttonStyle) - { - ThemeChangeSensitive = true, - Size2D = new Size2D(96, 60), - BackgroundImage = Resources.GetImagePath() + "search_button_bg.png", - Margin = new Extents(24, 0, 0, 0), - }; - topView.Add(searchButton); - RelativeLayout.SetRightTarget(searchButton, moreButton); - RelativeLayout.SetRightRelativeOffset(searchButton, 0.0f); - RelativeLayout.SetHorizontalAlignment(searchButton, RelativeLayout.Alignment.End); - - RelativeLayout.SetLeftTarget(titleLabel, RelativeLayout.GetLeftTarget(titleLabel)); - RelativeLayout.SetLeftRelativeOffset(titleLabel, RelativeLayout.GetLeftRelativeOffset(titleLabel)); - RelativeLayout.SetRightTarget(titleLabel, searchButton); - RelativeLayout.SetRightRelativeOffset(titleLabel, 0.0f); - } - } - } - - public View SetContent - { - set - { - contentView.Add(value); - } - } - - protected override void Dispose(DisposeTypes type) - { - if (Disposed) - { - return; - } - if (type == DisposeTypes.Explicit) - { - List children = topView?.Children; - foreach (View child in children) - { - topView.Remove(child); - child?.Dispose(); - } - base.Remove(topView); - topView?.Dispose(); - topView = null; - - // Do not delete the children of contentview as they are not owned by BaseView - base.Remove(contentView); - contentView?.Dispose(); - contentView = null; - - base.Remove(tabs); - tabs?.Dispose(); - tabs = null; - - base.Remove(bottomView); - bottomView?.Dispose(); - bottomView = null; - } - - base.Dispose(type); - } - } -} \ No newline at end of file diff --git a/Views/ListItemLayout.cs b/Views/ListItemLayout.cs deleted file mode 100755 index 071523f..0000000 --- a/Views/ListItemLayout.cs +++ /dev/null @@ -1,135 +0,0 @@ -using Tizen.NUI.Components; -using Tizen.NUI.BaseComponents; -using Tizen.NUI; -using MusicPlayer.Common; - -namespace MusicPlayer.Views -{ - class ListItemLayout : RecyclerViewItem - { - private static int Width = 1792; - private static int Height = 108; - - private const int IconSize = 64; - private const int LayoutMargin = 16; - private const int LayoutPadding = 32; - private const int SeperatorHeight = 1; - private const int LeftPadding = 64; - private const int x = 0; - - private View itemSeperator; - private TextLabel titleLabel; - private TextLabel subtitleLabel; - private ImageView icon; - - public ListItemLayout(int width = 1792, int height = 108) : base() - { - base.OnInitialize(); - base.IsCreateByXaml = true; - Width = width; - Height = height; - WidthSpecification = Width; - HeightSpecification = Height; - - // to show the rounded rect of the bg - BackgroundColor = Color.Transparent; - - icon = new ImageView() - { - WidthSpecification = IconSize, - HeightSpecification = IconSize, - IsCreateByXaml = true, - Position2D = new Position2D(x, ((Height / 2) - (IconSize / 2))), - }; - base.Add(icon); - - itemSeperator = new View() - { - WidthSpecification = (Width - (2 * LeftPadding)), - HeightSpecification = SeperatorHeight, - ExcludeLayouting = true, - Position2D = new Position2D(x, Height - SeperatorHeight), - BackgroundColor = UIColors.ItemSeperator, - }; - base.Add(itemSeperator); - - titleLabel = new TextLabel("ItemLabel") - { - ThemeChangeSensitive = true, - WidthSpecification = (Width - (2 * LeftPadding) - IconSize - LayoutPadding), - HeightSpecification = 40, - PixelSize = 32, - FontFamily = "BreezeSans", - VerticalAlignment = VerticalAlignment.Center, - IsCreateByXaml = true, - Position2D = new Position2D((x + IconSize + LayoutPadding), LayoutMargin), - }; - // ToDo need to make this a readonly const - PropertyMap titleFontStyle = new PropertyMap(); - titleFontStyle.Add("width", new PropertyValue("normal")); - titleFontStyle.Add("weight", new PropertyValue("light")); - titleLabel.FontStyle = titleFontStyle; - base.Add(titleLabel); - - subtitleLabel = new TextLabel("ItemLabel") - { - ThemeChangeSensitive = true, - WidthSpecification = (Width - (2 * LeftPadding) - IconSize - LayoutPadding), - HeightSpecification = 36, - PixelSize = 28, - FontFamily = "BreezeSans", - VerticalAlignment = VerticalAlignment.Center, - IsCreateByXaml = true, - Position2D = new Position2D((x + IconSize + LayoutPadding), LayoutMargin + 40) - }; - // ToDo need to make this a readonly const - PropertyMap subtitleFontStyle = new PropertyMap(); - subtitleFontStyle.Add("width", new PropertyValue("normal")); - subtitleFontStyle.Add("weight", new PropertyValue("normal")); - subtitleFontStyle.Add("slant", new PropertyValue("normal")); - subtitleLabel.FontStyle = subtitleFontStyle; - base.Add(subtitleLabel); - IsCreateByXaml = true; - } - public ImageView Icon - { - get => icon; - } - public TextLabel TitleLabel - { - get => titleLabel; - } - public TextLabel SubtitleLabel - { - get => subtitleLabel; - } - - protected override void Dispose(DisposeTypes type) - { - if(Disposed) - { - return; - } - if (type == DisposeTypes.Explicit) - { - base.Remove(itemSeperator); - itemSeperator?.Dispose(); - itemSeperator = null; - - base.Remove(icon); - icon?.Dispose(); - icon = null; - - base.Remove(titleLabel); - titleLabel?.Dispose(); - titleLabel = null; - - base.Remove(subtitleLabel); - subtitleLabel?.Dispose(); - subtitleLabel = null; - } - - base.Dispose(type); - } - } -} diff --git a/Views/LyricsView.cs b/Views/LyricsView.cs deleted file mode 100644 index f36473a..0000000 --- a/Views/LyricsView.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Tizen.NUI; -using Tizen.NUI.Binding; -using Tizen.NUI.BaseComponents; -using Tizen.NUI.Components; -using MusicPlayer.ViewModels; -using MusicPlayer.Common; - -namespace MusicPlayer.Views -{ - class LyricsView : View - { - private const int ViewSize = 784; - private const int LyricsViewMargin = 40; - private const int LyricsViewSize = 704; - - private readonly LyricsViewModel lyricsViewModel; - - private ImageView thumbView; - private ScrollableBase scrollView; - private TextLabel lyricsLabel; - - public LyricsView(LyricsViewModel lyricsViewModel) : base() - { - this.lyricsViewModel = lyricsViewModel; - BindingContext = lyricsViewModel.lyricsModel; - Size2D = new Size2D(ViewSize, ViewSize); - - AddThumbnail(); - AddLyricsView(); - } - - private void AddThumbnail() - { - thumbView = new ImageView() - { - HeightResizePolicy = ResizePolicyType.FillToParent, - WidthResizePolicy = ResizePolicyType.FillToParent, - }; - thumbView.SetBinding(ImageView.ResourceUrlProperty, "ThumbPath"); - base.Add(thumbView); - } - - private void AddLyricsView() - { - scrollView = new ScrollableBase() - { - Position2D = new Position2D(LyricsViewMargin, LyricsViewMargin), - Size2D = new Size2D(LyricsViewSize, LyricsViewSize), - ScrollingDirection = ScrollableBase.Direction.Vertical, - BackgroundColor = Color.Transparent, - }; - scrollView.BindingContext = lyricsViewModel; - scrollView.SetBinding(View.BackgroundColorProperty, "LyricsBackgroundColor"); - base.Add(scrollView); - - lyricsLabel = new TextLabel() - { - WidthResizePolicy = ResizePolicyType.FillToParent, - TextColor = Color.White, - MultiLine = true, - LineWrapMode = LineWrapMode.Word, - PointSize = 25.0f, - HorizontalAlignment = HorizontalAlignment.Center, - }; - lyricsLabel.BindingContext = lyricsViewModel.lyricsModel; - lyricsLabel.SetBinding(TextLabel.TextProperty, "Lyrics"); - scrollView.Add(lyricsLabel); - } - } -} diff --git a/Views/PlayerView.cs b/Views/PlayerView.cs deleted file mode 100755 index b0a5883..0000000 --- a/Views/PlayerView.cs +++ /dev/null @@ -1,781 +0,0 @@ -using Tizen.NUI; -using Tizen.Multimedia; -using Tizen.NUI.Components; -using Tizen.NUI.BaseComponents; -using Tizen.NUI.Binding; -using MusicPlayer.Common; -using MusicPlayer.ViewModels; -using MusicPlayer.Views.Utils; -using System.Collections.Generic; - -namespace MusicPlayer.Views -{ - class PlayerView : View - { - private enum PlayerViewState - { - AlbumArt, - TrackList, - } - private const int LayoutPadding = 64; - private const int IconSize = 48; - private const int TopBarSize = 120; - private const int ControlViewWidth = 640; - private const int ControlViewHeight = 384; - private const int ControlViewMargin = 315; - private const int TitleLabelHeight = 48; - private const int ArtistLabelHeight = 36; - private const int TopBarButtonsY = (TopBarSize / 2 - IconSize / 2); - - private View playerBackgroundView; - private View leftView; - private View rightView; - private View rightViewBackground; - private Button backButton; - private Button moreButton; - - private View controlsView; - private View sliderView; - private MultiStateButton playButton; - private Button prevButton; - private Button nextButton; - private MultiStateButton shuffleButton; - private MultiStateButton repeatButton; - private Slider volumeSlider; - private Slider playbackSlider; - private TextLabel titleLabel; - private TextLabel artistLabel; - private TextLabel currentTime; - private TextLabel totalTime; - - private ImageView leftVolumeIcon; - private ImageView rightVolumeIcon; - private ImageView thumb; - private Button listButton; - private Button playlistButton; - private MultiStateButton favouriteButton; - private PlayingListView currentListView; - private LyricsView lyricsView; - - private PlayerViewModel viewModel; - - private PlayerViewState viewState; - - public PlayerView(PlayerViewModel viewModel) : base() - { - this.viewModel = viewModel; - BindingContext = viewModel.playerModel; - StyleName = "AppBackground"; - WidthResizePolicy = ResizePolicyType.FillToParent; - HeightResizePolicy = ResizePolicyType.FillToParent; - - AddPlayerBackground(); - - viewState = PlayerViewState.AlbumArt; - - leftView = CreateLeftView(); - rightView = CreateRightView(); - AddRightViewBackground(); - - AddTopButtons(); - AddControlView(); - AddControlElements(); - AddPlaybackSlider(); - AddListActionButtons(); - AddThumbnail(); - AddLyricsView(); - } - - private void AddPlayerBackground() - { - playerBackgroundView = new View(); - playerBackgroundView.Size2D = new Size2D(Window.Instance.WindowSize.Width, Window.Instance.WindowSize.Height); - WidthResizePolicy = ResizePolicyType.FillToParent; - HeightResizePolicy = ResizePolicyType.FillToParent; - base.Add(playerBackgroundView); - playerBackgroundView.BackgroundColor = Color.Transparent; - playerBackgroundView.BindingContext = viewModel; - playerBackgroundView.SetBinding(BackgroundProperty, "PlayerBackground"); - } - - private View CreateLeftView() - { - View leftView = new View() - { - BackgroundColor = Color.Transparent, - HeightResizePolicy = ResizePolicyType.FillToParent, - SizeWidth = Window.Instance.WindowSize.Width / 2, - Position2D = new Position2D(0, 0), - }; - base.Add(leftView); - return leftView; - } - - private View CreateRightView() - { - View rightView = new View() - { - BackgroundColor = Color.Transparent, - HeightResizePolicy = ResizePolicyType.FillToParent, - SizeWidth = Window.Instance.WindowSize.Width / 2, - Position2D = new Position2D(Window.Instance.WindowSize.Width / 2, 0), - }; - base.Add(rightView); - return rightView; - } - - private void AddRightViewBackground() - { - rightViewBackground = new View(); - rightViewBackground.BackgroundColor = Color.Transparent; - rightViewBackground.SizeWidth = Window.Instance.WindowSize.Width / 2; - rightViewBackground.SizeHeight = Window.Instance.WindowSize.Height; - rightViewBackground.WidthResizePolicy = ResizePolicyType.FillToParent; - rightViewBackground.HeightResizePolicy = ResizePolicyType.FillToParent; - rightView.Add(rightViewBackground); - rightViewBackground.BindingContext = viewModel; - rightViewBackground.SetBinding(BackgroundProperty, "PlayerBackground"); - rightViewBackground.Hide(); - } - - private void UpdatePlayerViewBackground(PlayerViewState state) - { - if (state == PlayerViewState.AlbumArt) - { - rightViewBackground.Hide(); - playerBackgroundView.Show(); - } - else - { - playerBackgroundView.Hide(); - rightViewBackground.Show(); - } - } - - private void AddTopButtons() - { - backButton = new Button("BackButton"); - backButton.ThemeChangeSensitive = true; - backButton.Position2D = new Position2D(LayoutPadding, TopBarButtonsY); - leftView.Add(backButton); - - moreButton = new Button("MoreButton"); - moreButton.ThemeChangeSensitive = true; - moreButton.Position2D = new Position2D(Window.Instance.WindowSize.Width / 2 - LayoutPadding - IconSize, TopBarButtonsY); - rightView.Add(moreButton); - } - - private void AddControlView() - { - controlsView = new View() - { - BackgroundColor = Color.Transparent, - Size2D = new Size2D(ControlViewWidth, ControlViewHeight), - Position2D = new Position2D((Window.Instance.WindowSize.Width / 4 - ControlViewWidth / 2), TopBarSize + ControlViewMargin), - }; - rightView.Add(controlsView); - } - - private void AddTitleLabel() - { - titleLabel = new TextLabel("LabelText") - { - ThemeChangeSensitive = true, - Size2D = new Size2D(ControlViewWidth, TitleLabelHeight), - Position2D = new Position2D(0, 0), - PixelSize = 36, - FontFamily = "BreezeSans", - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - Ellipsis = true, - }; - titleLabel.SetBinding(TextLabel.TextProperty, "TrackName"); - controlsView.Add(titleLabel); - } - - private void AddArtistLabel() - { - artistLabel = new TextLabel("LabelText") - { - ThemeChangeSensitive = true, - Size2D = new Size2D(ControlViewWidth, ArtistLabelHeight), - Position2D = new Position2D(0, 62), - PixelSize = 28, - FontFamily = "BreezeSans", - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - Ellipsis = true, - }; - artistLabel.SetBinding(TextLabel.TextProperty, "TrackArtist"); - controlsView.Add(artistLabel); - } - - private void AddTextControlElements() - { - AddTitleLabel(); - AddArtistLabel(); - } - - private void AddShuffleButton() - { - shuffleButton = new MultiStateButton() - { - Size2D = new Size2D(IconSize, IconSize), - Position2D = new Position2D(0, 196), - IconResources = new Dictionary>() - { - { - ThemeType.Light, - new Dictionary() - { - { - ShuffleMode.Off.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "light/shuffle_off.png", - } - }, - { - ShuffleMode.On.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "light/shuffle_on.png", - } - }, - } - }, - { - ThemeType.Dark, - new Dictionary() - { - { - ShuffleMode.Off.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "dark/shuffle_off.png", - } - }, - { - ShuffleMode.On.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "dark/shuffle_on.png", - } - }, - } - } - }, - }; - shuffleButton.BindingContext = viewModel.playingListViewModel; - shuffleButton.SetBinding(MultiStateButton.CustomStateProperty, "ShuffleButtonState"); - // TODO need to implement command instead - shuffleButton.Clicked += (object sender, ClickedEventArgs e) => - { - viewModel.ShuffleChanged(); - }; - controlsView.Add(shuffleButton); - } - - private void AddPreviousButton() - { - prevButton = new Button("PrevButton"); - prevButton.ThemeChangeSensitive = true; - // TODO need to implement command instead - prevButton.Clicked += (object sender, ClickedEventArgs e) => - { - viewModel.PrevButtonClicked(); - }; - prevButton.BindingContext = viewModel; - prevButton.SetBinding(Button.IsEnabledProperty, "HasPreviousTrack"); - controlsView.Add(prevButton); - } - - private void AddPlayButton() - { - playButton = new MultiStateButton() - { - Size2D = new Size2D(IconSize, IconSize), - Position2D = new Position2D(296, 196), - BackgroundColor = Color.Transparent, - IconResources = new Dictionary>() - { - { - ThemeType.Light, - new Dictionary() - { - { - "Play", - new StringSelector() - { - Normal = Resources.GetImagePath() + "light/play.png", - Pressed = Resources.GetImagePath() + "play_pressed.png", - Disabled = Resources.GetImagePath() + "play_disabled.png", - } - }, - { - "Pause", - new StringSelector() - { - Normal = Resources.GetImagePath() + "light/pause.png", - Pressed = Resources.GetImagePath() + "pause_pressed.png", - Disabled = Resources.GetImagePath() + "pause_disabled.png", - } - }, - } - }, - { - ThemeType.Dark, - new Dictionary() - { - { - "Play", - new StringSelector() - { - Normal = Resources.GetImagePath() + "dark/play.png", - Pressed = Resources.GetImagePath() + "play_pressed.png", - Disabled = Resources.GetImagePath() + "play_disabled.png", - } - }, - { - "Pause", - new StringSelector() - { - Normal = Resources.GetImagePath() + "dark/pause.png", - Pressed = Resources.GetImagePath() + "pause_pressed.png", - Disabled = Resources.GetImagePath() + "pause_disabled.png", - } - }, - } - } - }, - }; - playButton.BindingContext = viewModel; - playButton.SetBinding(MultiStateButton.CustomStateProperty, "PlayButtonState"); - controlsView.Add(playButton); - // TODO need to implement command instead - playButton.Clicked += (object sender, ClickedEventArgs e) => - { - viewModel.PlayingStatusChanged(); - }; - } - - private void AddNextButton() - { - nextButton = new Button("NextButton"); - nextButton.ThemeChangeSensitive = true; - // TODO need to implement command instead - nextButton.Clicked += (object sender, ClickedEventArgs e) => - { - viewModel.NextButtonClicked(); - }; - nextButton.BindingContext = viewModel; - nextButton.SetBinding(Button.IsEnabledProperty, "HasNextTrack"); - controlsView.Add(nextButton); - } - - private void AddRepeatButton() - { - repeatButton = new MultiStateButton() - { - Size2D = new Size2D(IconSize, IconSize), - Position2D = new Position2D(592, 196), - IconResources = new Dictionary>() - { - { - ThemeType.Light, - new Dictionary() - { - { - RepeatMode.Off.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "light/repeat_off.png", - } - }, - { - RepeatMode.RepeatOne.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "light/repeat_one.png", - } - }, - { - RepeatMode.RepeatAll.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "light/repeat_all.png", - } - }, - } - }, - { - ThemeType.Dark, - new Dictionary() - { - { - RepeatMode.Off.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "dark/repeat_off.png", - } - }, - { - RepeatMode.RepeatOne.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "dark/repeat_one.png", - } - }, - { - RepeatMode.RepeatAll.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "dark/repeat_all.png", - } - }, - } - } - }, - }; - repeatButton.BindingContext = viewModel.playingListViewModel; - repeatButton.SetBinding(MultiStateButton.CustomStateProperty, "RepeatButtonState"); - controlsView.Add(repeatButton); - // TODO need to implement command instead - repeatButton.Clicked += (object sender, ClickedEventArgs e) => - { - viewModel.RepeatChanged(); - }; - } - - private void AddButtonControlElements() - { - AddShuffleButton(); - AddPreviousButton(); - AddPlayButton(); - AddNextButton(); - AddRepeatButton(); - } - - private void AddLeftVolumeIcon() - { - leftVolumeIcon = new ImageView() - { - ThemeChangeSensitive = true, - StyleName = "LeftVolume", - }; - controlsView.Add(leftVolumeIcon); - } - - private void AddRightVolumeIcon() - { - rightVolumeIcon = new ImageView() - { - ThemeChangeSensitive = true, - StyleName = "RightVolume", - }; - controlsView.Add(rightVolumeIcon); - } - - private void AddVolumeSliderEventHandlers() - { - volumeSlider.SlidingStarted += (object sender, SliderSlidingStartedEventArgs e) => - { - viewModel.VolumeChangeStarted(); - }; - volumeSlider.ValueChanged += (object sender, SliderValueChangedEventArgs e) => - { - viewModel.VolumeLevelChanged((int)e.CurrentValue); - }; - volumeSlider.SlidingFinished += (object sender, SliderSlidingFinishedEventArgs e) => - { - viewModel.VolumeChangeFinished((int)e.CurrentValue); - }; - } - - private void AddVolumeSlider() - { - volumeSlider = new Slider("Slider"); - volumeSlider.ThemeChangeSensitive = true; - volumeSlider.Size2D = new Size2D(496, 48); - volumeSlider.Position2D = new Position2D(72, 336); - volumeSlider.ThumbSize = new Tizen.NUI.Size(36, 36); - volumeSlider.Direction = Slider.DirectionType.Horizontal; - volumeSlider.MinValue = 0; - volumeSlider.MaxValue = AudioManager.VolumeController.MaxLevel[AudioVolumeType.Media]; - volumeSlider.CurrentValue = AudioManager.VolumeController.Level[AudioVolumeType.Media]; - controlsView.Add(volumeSlider); - volumeSlider.BindingContext = viewModel; - volumeSlider.SetBinding(Slider.CurrentValueProperty, "VolumeLevel"); - AddVolumeSliderEventHandlers(); - } - - private void AddVolumeSliderElements() - { - AddLeftVolumeIcon(); - AddRightVolumeIcon(); - AddVolumeSlider(); - } - - private void AddControlElements() - { - AddTextControlElements(); - AddButtonControlElements(); - AddVolumeSliderElements(); - } - - private void AddPlaybackSliderEventHandler() - { - playbackSlider.SlidingStarted += (object sender, SliderSlidingStartedEventArgs e) => - { - viewModel.StopPlaybackTimer(); - }; - playbackSlider.ValueChanged += (object sender, SliderValueChangedEventArgs e) => - { - viewModel.SetElapsedTime(e.CurrentValue); - }; - playbackSlider.SlidingFinished += (object sender, SliderSlidingFinishedEventArgs e) => - { - viewModel.UpdatePlayerPosition(e.CurrentValue); - }; - } - - private void AddPlaybackSlider(View sliderView) - { - playbackSlider = new Slider("Slider") - { - ThemeChangeSensitive = true, - MinValue = 0.0f, - MaxValue = 1.0f, - WidthResizePolicy = ResizePolicyType.FillToParent, - SizeHeight = 44, - ThumbSize = new Tizen.NUI.Size(36, 36), - Direction = Slider.DirectionType.Horizontal, - }; - playbackSlider.SetBinding(Slider.CurrentValueProperty, "ElapsedTime"); - sliderView.Add(playbackSlider); - AddPlaybackSliderEventHandler(); - } - - private void AddCurrentTimeLabel(View sliderView) - { - currentTime = new TextLabel("LabelText") - { - ThemeChangeSensitive = true, - Size2D = new Size2D(400, 32), - Position2D = new Position2D(0, 48), - PixelSize = 24, - FontFamily = "BreezeSans", - Text = "00::00:00", - HorizontalAlignment = HorizontalAlignment.Begin, - }; - currentTime.SetBinding(TextLabel.TextProperty, "PlayingTime"); - sliderView.Add(currentTime); - } - - private void AddTotalTimeLabel(View sliderView) - { - totalTime = new TextLabel("LabelText") - { - ThemeChangeSensitive = true, - Size2D = new Size2D(400, 32), - Position2D = new Position2D(1792 - 400, 48), - PixelSize = 24, - FontFamily = "BreezeSans", - HorizontalAlignment = HorizontalAlignment.End, - Text = "59:59:59", - }; - totalTime.SetBinding(TextLabel.TextProperty, "TrackLength"); - sliderView.Add(totalTime); - } - - private void AddPlaybackSlider() - { - sliderView = new View() - { - Size2D = new Size2D(1792, 80), - Position2D = new Position2D(64, 950), - BackgroundColor = Color.Transparent, - }; - Add(sliderView); - - AddPlaybackSlider(sliderView); - AddCurrentTimeLabel(sliderView); - AddTotalTimeLabel(sliderView); - UpdatePlaybackSliderPosition(viewState); - } - - private void UpdatePlaybackSliderPosition(PlayerViewState state) - { - if(state == PlayerViewState.AlbumArt) - { - sliderView.Size2D = new Size2D(1792, 80); - sliderView.Position2D = new Position2D(64, 950); - currentTime.Size2D = new Size2D(400, 32); - currentTime.Position2D = new Position2D(0, 48); - totalTime.Size2D = new Size2D(400, 32); - totalTime.Position2D = new Position2D(1392, 48); - } - else - { - sliderView.Size2D = new Size2D(640, 80); - sliderView.Position2D = new Position2D(1056, 950); - currentTime.Size2D = new Size2D(180, 32); - currentTime.Position2D = new Position2D(0, 48); - totalTime.Size2D = new Size2D(180, 32); - totalTime.Position2D = new Position2D(460, 48); - } - } - - private void AddListActionButtons() - { - View actionButtonView = new View() - { - Size2D = new Size2D(224, 48), - Position2D = new Position2D((Window.Instance.WindowSize.Width / 2 - 224 - LayoutPadding), 120), - BackgroundColor = Color.Transparent, - }; - rightView.Add(actionButtonView); - - listButton = new Button("ListButton") - { - ThemeChangeSensitive = true, - }; - listButton.Clicked += (object sender, ClickedEventArgs e) => - { - if(viewState == PlayerViewState.AlbumArt) - { - Tizen.Log.Debug(AppConstants.LogTag, "Adding Playing list view"); - viewState = PlayerViewState.TrackList; - RemoveLyricsView(); - AddPlayingListView(); - thumb.Show(); - } - else - { - Tizen.Log.Debug(AppConstants.LogTag, "Adding album art view"); - viewState = PlayerViewState.AlbumArt; - RemovePlayingListView(); - AddLyricsView(); - thumb.Hide(); - } - UpdatePlaybackSliderPosition(viewState); - UpdatePlayerViewBackground(viewState); - }; - actionButtonView.Add(listButton); - - playlistButton = new Button("PlaylistButton") - { - ThemeChangeSensitive = true, - }; - actionButtonView.Add(playlistButton); - - favouriteButton = new MultiStateButton() - { - Size2D = new Size2D(IconSize, IconSize), - Position2D = new Position2D(176, 0), - IconResources = new Dictionary>() - { - { - ThemeType.Light, - new Dictionary() - { - { - Favourite.Off.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "light/favourite_off.png", - } - }, - { - Favourite.On.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "light/favourite_on.png", - } - }, - } - }, - { - ThemeType.Dark, - new Dictionary() - { - { - Favourite.Off.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "dark/favourite_off.png", - } - }, - { - Favourite.On.ToString(), - new StringSelector() - { - All = Resources.GetImagePath() + "dark/favourite_on.png", - } - }, - } - } - }, - }; - favouriteButton.CusotmState = Favourite.Off.ToString(); - actionButtonView.Add(favouriteButton); - } - - private void AddThumbnail() - { - thumb = new ImageView() - { - BackgroundColor = Color.Cyan, - Size2D = new Size2D(200, 200), - Position2D = new Position2D(380, 120), - }; - thumb.SetBinding(ImageView.ResourceUrlProperty, "ThumbnailPath"); - rightView.Add(thumb); - thumb.Hide(); - } - - private void AddPlayingListView() - { - if (currentListView == null) - currentListView = new PlayingListView(viewModel.CurrentPlayingListViewModel); - - currentListView.Size2D = new Size2D(832, 900); - currentListView.Position2D = new Position2D(64, 108); - leftView.Add(currentListView); - currentListView.Show(); - } - - private void RemovePlayingListView() - { - if(currentListView == null) - { - Tizen.Log.Error(AppConstants.LogTag, "current listview is null, can't remove it"); - return; - } - leftView.Remove(currentListView); - currentListView.Hide(); - } - - private void AddLyricsView() - { - if (lyricsView == null) - lyricsView = new LyricsView(viewModel.lyricsViewModel); - - lyricsView.Size2D = new Size2D(784, 784); - lyricsView.Position2D = new Position2D(88, 120); - leftView.Add(lyricsView); - lyricsView.Show(); - } - - private void RemoveLyricsView() - { - if(lyricsView == null) - { - Tizen.Log.Error(AppConstants.LogTag, "lyricsview is null, can't remove it"); - return; - } - leftView.Remove(lyricsView); - lyricsView.Hide(); - } - } -} diff --git a/Views/PlayingListView.cs b/Views/PlayingListView.cs deleted file mode 100755 index cab9516..0000000 --- a/Views/PlayingListView.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Tizen.NUI.BaseComponents; -using Tizen.NUI.Components; -using Tizen.NUI; -using MusicPlayer.ViewModels; -using MusicPlayer.Common; -using Tizen.NUI.Binding; - -namespace MusicPlayer.Views -{ - class PlayingListView : View - { - private CollectionView collectionView; - private PlayingListViewModel viewModel; - - public PlayingListView(PlayingListViewModel viewModel) : base() - { - this.viewModel = viewModel; - collectionView = new CollectionView() - { - BackgroundImage = Resources.GetImagePath() + "playing_list_bg.png", - ItemsSource = this.viewModel.TrackListVM, - ItemsLayouter = new LinearLayouter(), - ItemTemplate = new DataTemplate(() => - { - ListItemLayout layout = new ListItemLayout(832, 108); - layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "ThumbnailPath"); - layout.TitleLabel.SetBinding(TextLabel.TextProperty, "TrackTitle"); - layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); - return layout; - }), - ScrollingDirection = ScrollableBase.Direction.Vertical, - SelectionMode = ItemSelectionMode.Single, - WidthResizePolicy = ResizePolicyType.FillToParent, - HeightResizePolicy = ResizePolicyType.FillToParent, - }; - base.Add(collectionView); - viewModel.ItemsSourceChanged += ItemSourceChanged; - } - - private void ItemSourceChanged(object sender, EventArgs e) - { - collectionView.ItemsSource = viewModel.TrackListVM; - } - } -} diff --git a/Views/TrackView.cs b/Views/TrackView.cs deleted file mode 100755 index daa7df1..0000000 --- a/Views/TrackView.cs +++ /dev/null @@ -1,102 +0,0 @@ -using MusicPlayer.ViewModels; -using Tizen.NUI.Components; -using Tizen.NUI.BaseComponents; -using Tizen.NUI; -using Tizen.NUI.Binding; -using MusicPlayer.Common; - -namespace MusicPlayer.Views -{ - class TrackView : BaseContentView - { - private TrackViewModel viewModel; - private TextLabel trackCountLabel; - private Button playAllIcon; // TODO need to implement playall feature - private Button addToPlaylistIcon; // TODO need to implement playlist manager - public TrackView(TrackViewModel viewModel) - { - this.viewModel = viewModel; - collectionView.ItemsSource = viewModel.ListViewModel; - collectionView.ItemTemplate = new DataTemplate(() => - { - ListItemLayout layout = new ListItemLayout(); - layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "ThumbnailPath"); - layout.TitleLabel.SetBinding(TextLabel.TextProperty, "TrackTitle"); - layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); - return layout; - }); - collectionView.ScrollingDirection = ScrollableBase.Direction.Vertical; - collectionView.WidthSpecification = LayoutParamPolicies.WrapContent; - collectionView.SelectionMode = ItemSelectionMode.Single; - collectionView.SelectionChanged += OnTrackSelection; - - trackCountLabel = new TextLabel("LabelText") - { - ThemeChangeSensitive = true, - PixelSize = 28, - Text = "TRACK COUNT", - VerticalAlignment = VerticalAlignment.Center, - FontFamily = "BreezeSans", - }; - trackCountLabel.BindingContext = viewModel; - titleView.Add(trackCountLabel); - trackCountLabel.SetBinding(TextLabel.TextProperty, "TrackCount"); - RelativeLayout.SetLeftTarget(trackCountLabel, titleView); - RelativeLayout.SetLeftRelativeOffset(trackCountLabel, 1.0f); - RelativeLayout.SetRightRelativeOffset(trackCountLabel, 0.0f); - RelativeLayout.SetFillHorizontal(trackCountLabel, true); - - playAllIcon = new Button("PlayAll") - { - ThemeChangeSensitive = true, - }; - titleView.Add(playAllIcon); - RelativeLayout.SetLeftRelativeOffset(playAllIcon, 1.0f); - RelativeLayout.SetRightRelativeOffset(playAllIcon, 1.0f); - RelativeLayout.SetHorizontalAlignment(playAllIcon, RelativeLayout.Alignment.End); - - addToPlaylistIcon = new Button("PlaylistAdd") - { - ThemeChangeSensitive = true, - Margin = new Extents(32, 40, 0, 0), - }; - titleView.Add(addToPlaylistIcon); - RelativeLayout.SetRightTarget(addToPlaylistIcon, playAllIcon); - RelativeLayout.SetRightRelativeOffset(addToPlaylistIcon, 0.0f); - RelativeLayout.SetHorizontalAlignment(addToPlaylistIcon, RelativeLayout.Alignment.End); - } - - private void OnTrackSelection(object sender, SelectionChangedEventArgs e) - { - //TODO - } - - protected override void OnThemeChanged(object sender, ThemeChangedEventArgs e) - { - base.OnThemeChanged(sender, e); - } - protected override void Dispose(DisposeTypes type) - { - if(Disposed) - { - return; - } - if(type == DisposeTypes.Explicit) - { - titleView.Remove(trackCountLabel); - trackCountLabel.Dispose(); - trackCountLabel = null; - - // TODO Uncomment after implementation is completed - titleView.Remove(playAllIcon); - playAllIcon.Dispose(); - playAllIcon = null; - - //titleView.Remove(addToPlaylistIcon); - addToPlaylistIcon.Dispose(); - addToPlaylistIcon = null; - } - base.Dispose(type); - } - } -} diff --git a/Views/Utils/MultiStateButton.cs b/Views/Utils/MultiStateButton.cs deleted file mode 100644 index e605dc0..0000000 --- a/Views/Utils/MultiStateButton.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Collections.Generic; -using Tizen.NUI; -using Tizen.NUI.Binding; -using Tizen.NUI.Components; -using MusicPlayer.Common; - -namespace MusicPlayer.Views.Utils -{ - class MultiStateButton: Button - { - public static readonly BindableProperty CustomStateProperty = BindableProperty.Create(nameof(CusotmState), typeof(string), typeof(MultiStateButton), null, propertyChanged: (bindable, oldValue, newValue) => - { - var instance = (MultiStateButton)bindable; - if (newValue != null) - { - string newCustomState = (string)newValue; - instance.UpdateCustomState(newCustomState); - } - }, - defaultValueCreator: (bindable) => - { - var instance = (MultiStateButton)bindable; - return instance.customState; - }); - - public MultiStateButton() : base() - { - ThemeChangeSensitive = true; - EnableControlState = true; - BackgroundColor = Color.Transparent; - } - - private Dictionary> iconResources; - - public Dictionary> IconResources - { - get => iconResources; - set => iconResources = value; - } - - private string customState; - public string CusotmState - { - get => (string)GetValue(CustomStateProperty); - set => SetValue(CustomStateProperty, value); - } - - private void UpdateCustomState(string customStatevalue) - { - if (IconResources == null) - { - Tizen.Log.Error(AppConstants.LogTag, "ThemesIconState needs to be set first"); - return; - } - ThemeType type = GetCurrentThemeType(); - if (iconResources.ContainsKey(type) == false) - { - Tizen.Log.Error(AppConstants.LogTag, "Theme state doesn't exists: " + type.ToString()); - return; - } - Dictionary stateResource = iconResources[type]; - if (stateResource.ContainsKey(customStatevalue) == false) - { - Tizen.Log.Error(AppConstants.LogTag, "Invalid state: " + customStatevalue); - return; - } - IconURLSelector = stateResource[customStatevalue]; - customState = customStatevalue; - } - - private ThemeType GetCurrentThemeType() - { - ThemeType type; - string id = ThemeManager.PlatformThemeId; - if (id.Equals(AppConstants.LightPlatformThemeId)) - { - type = ThemeType.Light; - } - else - { - type = ThemeType.Dark; - } - return type; - } - - protected override void OnThemeChanged(object sender, ThemeChangedEventArgs e) - { - base.OnThemeChanged(sender, e); - UpdateCustomState(CusotmState); - } - } -} - diff --git a/XamlPage.xaml.cs b/XamlPage.xaml.cs deleted file mode 100644 index 8a08eb7..0000000 --- a/XamlPage.xaml.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using Tizen.NUI; -using Tizen.NUI.BaseComponents; - -namespace MusicPlayer -{ - public partial class XamlPage : View - { - public XamlPage() - { - InitializeComponent(); - } - } -} diff --git a/music-player.csproj b/music-player.csproj deleted file mode 100755 index 782f6b6..0000000 --- a/music-player.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - Exe - netcoreapp3.1 - Tizen - MusicPlayer - - - - portable - - - None - - - - - - - - - - MSBuild:Compile - - - - - - - - - - diff --git a/music-player/Common/AppConstants.cs b/music-player/Common/AppConstants.cs new file mode 100755 index 0000000..104322b --- /dev/null +++ b/music-player/Common/AppConstants.cs @@ -0,0 +1,16 @@ +namespace MusicPlayer.Common +{ + class AppConstants + { + // LogTag + public const string LogTag = "MUSIC_PLAYER"; + // KeyCodes + public const string BackKeyCode = "XF86Back"; + public const string EscapeKeyCode = "Escape"; + + // string literals + public const string TimeFormat = @"mm\:ss"; + public const string LightPlatformThemeId = "org.tizen.default-light-theme"; + public const string DarkPlatformThemeId = "org.tizen.default-dark-theme"; + } +} diff --git a/music-player/Common/PlayerCommon.cs b/music-player/Common/PlayerCommon.cs new file mode 100755 index 0000000..04ba5a2 --- /dev/null +++ b/music-player/Common/PlayerCommon.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MusicPlayer.Common +{ + public enum ThemeType + { + Light, + Dark + }; + public enum RepeatMode + { + Off, + RepeatOne, + RepeatAll, + } + + public enum PlayingStatus + { + None, + Playing, + Paused, + Stopped, + } + + public enum ShuffleMode + { + On, + Off, + } + + public enum Favourite + { + On, + Off, + } + + public enum EventType + { + Error, + PlaybackCompleted, + } + + public class PlayerEventArgs : EventArgs + { + private readonly EventType type; + private readonly string description; + + internal PlayerEventArgs(EventType eventType, string desc) + { + type = eventType; + description = desc; + } + + public EventType Type + { + get => type; + } + public string Description + { + get => description; + } + } +} diff --git a/music-player/Common/PropertyNotifier.cs b/music-player/Common/PropertyNotifier.cs new file mode 100755 index 0000000..de87064 --- /dev/null +++ b/music-player/Common/PropertyNotifier.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace MusicPlayer.Common +{ + class PropertyNotifier : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + protected bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null) + { + if (Equals(storage, value)) + { + return false; + } + + storage = value; + OnPropertyChanged(propertyName); + return true; + } + + protected void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} diff --git a/music-player/Common/Resources.cs b/music-player/Common/Resources.cs new file mode 100644 index 0000000..361c2da --- /dev/null +++ b/music-player/Common/Resources.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MusicPlayer.Common +{ + public class Resources + { + public static string GetImagePath() + { + return Tizen.Applications.Application.Current.DirectoryInfo.Resource + "images/"; + } + + public static string GetThemePath() + { + return Tizen.Applications.Application.Current.DirectoryInfo.Resource + "themes/"; + } + } +} diff --git a/music-player/Common/UIColors.cs b/music-player/Common/UIColors.cs new file mode 100755 index 0000000..dd3026a --- /dev/null +++ b/music-player/Common/UIColors.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Tizen.NUI; + +namespace MusicPlayer.Common +{ + class UIColors + { + public static readonly Color HEX000209 = new Color(0.0f, 0.0078f, 0.0353f, 1.0f); + public static readonly Color HEX001447 = new Color(0.0f, 0.0784f, 0.2784f, 1.0f); + public static readonly Color HEXEEEFF1 = new Color(0.9333f, 0.9373f, 0.9450f, 1.0f); + + public static readonly Color LyricsBackground = new Color(0.0f, 0.0f, 0.0f, 0.85f); + public static readonly Color ItemSeperator = new Color(0.75f, 0.79f, 0.82f, 1.0f); + + } +} diff --git a/music-player/Core/ColorExtractor.cs b/music-player/Core/ColorExtractor.cs new file mode 100644 index 0000000..db4a86d --- /dev/null +++ b/music-player/Core/ColorExtractor.cs @@ -0,0 +1,39 @@ +using System.Threading; +using System.Threading.Tasks; +using Tizen.NUI; +using MusicPlayer.Common; + +namespace MusicPlayer.Core +{ + static class ColorExtractor + { + public static async Task GetPaletteAsync(string imagePath) + { + Tizen.Log.Debug(AppConstants.LogTag, "Main Thread Id: " + Thread.CurrentThread.ManagedThreadId); + return await Task.Run(() => GeneratePalette(imagePath)); + } + + private static Palette GeneratePalette(string imagePath) + { + PixelBuffer pixelBuffer = ImageLoading.LoadImageFromFile(imagePath); + if(pixelBuffer == null) + { + Tizen.Log.Error(AppConstants.LogTag, "Pixel buffer is null"); + return null; + } + + Palette palette = null; + + try + { + palette = Palette.Generate(pixelBuffer); + } + catch(System.ArgumentNullException e) + { + Tizen.Log.Error(AppConstants.LogTag, "ArgumentNullException: " + e.Message); + } + + return palette; + } + } +} diff --git a/music-player/Core/MusicPlayer.cs b/music-player/Core/MusicPlayer.cs new file mode 100644 index 0000000..30942d5 --- /dev/null +++ b/music-player/Core/MusicPlayer.cs @@ -0,0 +1,180 @@ +using System; +using System.Threading.Tasks; +using Tizen.Multimedia; +using MusicPlayer.Common; + +namespace MusicPlayer.Core +{ + public class MusicPlayer + { + private readonly Player player = new Player(); + + public MusicPlayer() + { + player.ErrorOccurred += OnErrorOccurred; + player.PlaybackCompleted += OnPlayBackCompleted; + } + + public event EventHandler PlayerEvent; + + private enum PlayerValidationState + { + Start, + Stop, + Pause, + Resume, + Position, + } + + public PlayerState State + { + get => player.State; + } + + public void SetSource(string uri) + { + if(State != PlayerState.Idle) + { + Tizen.Log.Error(AppConstants.LogTag, "Player is not in idle state, can't set source"); + return; + } + try + { + Tizen.Log.Error(AppConstants.LogTag, "setting uri: " + uri); + player.SetSource(new MediaUriSource(uri)); + } + catch (UnauthorizedAccessException ex) + { + Tizen.Log.Error(AppConstants.LogTag, "UnauthorizedAccessException: " + ex.Message); + } + catch (ObjectDisposedException ex) + { + Tizen.Log.Error(AppConstants.LogTag, "ObjectDisposed: " + ex.Message); + } + catch (InvalidOperationException ex) + { + Tizen.Log.Error(AppConstants.LogTag, "InvalidOperationException: " + ex.Message); + } + } + + public async Task PreparePlayer() + { + try + { + await player.PrepareAsync(); + } + catch (ObjectDisposedException ex) + { + Tizen.Log.Error("MusicPlayer", "ObjectDisposedException: "+ex.Message); + } + catch (InvalidOperationException ex) + { + Tizen.Log.Error("MusicPlayer", "InvalidOperationException: "+ex.Message); + } + finally // TODO do we really need this + { + //DisposePlayer(); + } + } + + public void Play() + { + if (ValidatePlayerState(PlayerValidationState.Start)) + { + player.Start(); + } + else + { + Tizen.Log.Error(AppConstants.LogTag, "Invalid player state for playing: " + player.State.ToString()); + } + } + + public void Pause() + { + if(ValidatePlayerState(PlayerValidationState.Pause)) + { + player.Pause(); + } + } + + public void Resume() + { + if (ValidatePlayerState(PlayerValidationState.Resume)) + { + player.Start(); + } + } + + public void Stop() + { + if(ValidatePlayerState(PlayerValidationState.Stop)) + { + player.Stop(); + } + } + + public int GetPosition() + { + if (ValidatePlayerState(PlayerValidationState.Position)) + { + return player.GetPlayPosition(); + } + else + { + return 0; + } + } + + public void Unprepare() + { + player.Unprepare(); + } + + public void DisposePlayer() + { + player.Dispose(); + } + + public async Task SetPosition(int pos) + { + await player.SetPlayPositionAsync(pos, false); + } + + private bool ValidatePlayerState(PlayerValidationState state) + { + if(state == PlayerValidationState.Start || state == PlayerValidationState.Position) + { + return (State == PlayerState.Ready || State == PlayerState.Playing || State == PlayerState.Paused); + } + else if(state == PlayerValidationState.Pause) + { + return (State == PlayerState.Playing); + } + else if(state == PlayerValidationState.Resume) + { + return (State == PlayerState.Paused); + } + else if(state == PlayerValidationState.Stop) + { + return (State == PlayerState.Paused || State == PlayerState.Playing); + } + else + { + return false; + } + } + + private void OnPlayBackCompleted(object sender, EventArgs e) + { + PlayerEvent?.Invoke(this, new PlayerEventArgs(EventType.PlaybackCompleted, "Playback Completed")); + Tizen.Log.Error(AppConstants.LogTag, "Playback completed"); + } + + // TODO this event is called on a differnt thread..need to handle it + private void OnErrorOccurred(object sender, PlayerErrorOccurredEventArgs e) + { + PlayerEvent.Invoke(this, new PlayerEventArgs(EventType.Error, e.Error.ToString())); + Tizen.Log.Error(AppConstants.LogTag, "Error Occurred: " + e.Error.ToString()); + } + } +} diff --git a/music-player/Core/PlayerController.cs b/music-player/Core/PlayerController.cs new file mode 100644 index 0000000..4cd4a80 --- /dev/null +++ b/music-player/Core/PlayerController.cs @@ -0,0 +1,104 @@ +using System; +using Tizen.Multimedia; +using MusicPlayer.Common; + +namespace MusicPlayer.Core +{ + class PlayerController + { + private readonly MusicPlayer musicPlayer; + private static PlayerController instance = instance ??= new PlayerController(); + + private PlayerController() + { + musicPlayer = new MusicPlayer(); + musicPlayer.PlayerEvent += OnPlayerEvent; + } + + public event EventHandler PlayerEventOccurred; + + public static PlayerController Instance + { + get => instance; + } + + private string uri; + + public string Uri + { + get => uri; + set => uri = value; + } + + public async void Play() + { + if(Uri == null) + { + Tizen.Log.Error(AppConstants.LogTag, "Please set the uri to play"); + return; + } + Tizen.Log.Error(AppConstants.LogTag, "Current player state: "+musicPlayer.State.ToString()); + if (musicPlayer.State == PlayerState.Paused || musicPlayer.State == PlayerState.Playing) + { + musicPlayer.Stop(); + } + if(musicPlayer.State == PlayerState.Ready) + { + musicPlayer.Unprepare(); + } + musicPlayer.SetSource(Uri); + if(musicPlayer.State == PlayerState.Idle) + { + await musicPlayer.PreparePlayer(); + } + musicPlayer.Play(); + } + + public void Destroy() + { + musicPlayer?.DisposePlayer(); + } + + public void SetSource() + { + musicPlayer.SetSource(Uri); + } + + public void Pause() + { + musicPlayer.Pause(); + } + + public void Resume() + { + if (musicPlayer.State == PlayerState.Paused) + { + musicPlayer.Resume(); + } + else + { + Play(); + } + } + + public void Stop() + { + musicPlayer.Stop(); + } + + public int GetPosition() + { + return musicPlayer.GetPosition(); + } + + public async void SetPosition(int pos) + { + await musicPlayer.SetPosition(pos); + } + + private void OnPlayerEvent(object sender, PlayerEventArgs e) + { + PlayerEventOccurred?.Invoke(this, e); + } + } +} diff --git a/music-player/MediaContent/AlbumContents.cs b/music-player/MediaContent/AlbumContents.cs new file mode 100755 index 0000000..2e86e50 --- /dev/null +++ b/music-player/MediaContent/AlbumContents.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Specialized; +using Tizen.Content.MediaContent; +using MusicPlayer.Common; + +namespace MusicPlayer.Media +{ + public static partial class Contents + { + public static OrderedDictionary GetAlbumList() + { + OrderedDictionary albumList = new OrderedDictionary(); + + SelectArguments albumSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, AlbumColumns.Name + MEDIA_SORT_ORDER_ASC); + MediaDataReader dataReader = albumInfo.Select(albumSelectArguments); + + while (dataReader.Read()) + { + Album info = dataReader.Current; + SelectArguments audioSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); + MediaDataReader albumDataReader = albumInfo.SelectMember(info.Id, audioSelectArguments); + if (albumDataReader.Read()) + albumList.Add(info.Id, info); + } + Tizen.Log.Debug(AppConstants.LogTag, "Total album retrived from database: " + albumList.Count); + dataReader.Dispose(); + return albumList; + } + + public static int GetAlbumMemberCount(int albumId) + { + return albumInfo.CountMember(albumId); + } + + public static OrderedDictionary GetAlbumMemberList(int albumId) + { + OrderedDictionary mediaList = new OrderedDictionary(); + SelectArguments audioSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); + MediaDataReader dataReader = albumInfo.SelectMember(albumId, audioSelectArguments); + + while (dataReader.Read()) + { + MediaInfo info = dataReader.Current; + mediaList.Add(info.Id, info); + } + Tizen.Log.Debug(AppConstants.LogTag, "Total track retrived from currentAlbum: " + mediaList.Count); + dataReader.Dispose(); + return mediaList; + } + + public static string GetAlbumArtPath(int albumId) + { + string path = ""; + SelectArguments audioSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); + MediaDataReader dataReader = albumInfo.SelectMember(albumId, audioSelectArguments); + while (dataReader.Read()) + { + MediaInfo info = dataReader.Current; + if (!string.IsNullOrEmpty(info.ThumbnailPath)) + path = info.ThumbnailPath; + } + dataReader.Dispose(); + return path; + } + } +} diff --git a/music-player/MediaContent/ArtistContents.cs b/music-player/MediaContent/ArtistContents.cs new file mode 100755 index 0000000..f6da163 --- /dev/null +++ b/music-player/MediaContent/ArtistContents.cs @@ -0,0 +1,145 @@ +using System.Collections.Specialized; +using System.Collections.Generic; +using Tizen.Content.MediaContent; +using System; +using MusicPlayer.Common; + + +namespace MusicPlayer.Media +{ + public static partial class Contents + { + public static List GetArtistList() + { + List artistList = new List(); + + SelectArguments artistSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Artist + MEDIA_SORT_ORDER_ASC); + MediaDataReader dataReader = mediaInfo.SelectGroupBy(MediaInfoColumnKey.Artist, artistSelectArguments); + + while (dataReader.Read()) + { + string info = (string)dataReader.Current; + artistList.Add(info); + } + Tizen.Log.Debug(AppConstants.LogTag, "Total artists retrived from database: " + artistList.Count); + dataReader.Dispose(); + return artistList; + } + + public static OrderedDictionary GetAlbumListForArtist(string artistName) + { + OrderedDictionary albumList = new OrderedDictionary(); + string expression = MEDIA_STORAGE_TYPE_QUERY + "AND " + AlbumColumns.Artist + "=\"" + artistName + "\""; + SelectArguments albumSelectArguments = CreateSelectArgument(expression, AlbumColumns.Name + MEDIA_SORT_ORDER_ASC); + MediaDataReader dataReader = albumInfo.Select(albumSelectArguments); + + while (dataReader.Read()) + { + Album info = dataReader.Current; + SelectArguments audioSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); + MediaDataReader albumDataReader = albumInfo.SelectMember(info.Id, audioSelectArguments); + if(albumDataReader.Read()) + albumList.Add(info.Id, info); + } + dataReader.Dispose(); + Tizen.Log.Debug(AppConstants.LogTag, "Total Albums retrived from Artist: " + albumList.Count); + return albumList; + } + + public static OrderedDictionary GetTrackListForArtist(string artistName) + { + OrderedDictionary mediaList = new OrderedDictionary(); + string expression = MEDIA_STORAGE_TYPE_QUERY + "AND " + AlbumColumns.Artist + "=\"" + artistName + "\""; + SelectArguments albumSelectArguments = CreateSelectArgument(expression, AlbumColumns.Name + MEDIA_SORT_ORDER_ASC); + MediaDataReader dataReader = albumInfo.Select(albumSelectArguments); + + while (dataReader.Read()) + { + Album info = dataReader.Current; + SelectArguments audioSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); + MediaDataReader albumDataReader = albumInfo.SelectMember(info.Id, audioSelectArguments); + + while (albumDataReader.Read()) + { + MediaInfo mediaInfo = albumDataReader.Current; + mediaList.Add(mediaInfo.Id, mediaInfo); + } + albumDataReader.Dispose(); + } + dataReader.Dispose(); + Tizen.Log.Debug(AppConstants.LogTag, "Total track retrived from Artist: " + mediaList.Count); + return mediaList; + } + + public static string GetAlbumArtPathForArtist(string artistName) + { + string expression = MEDIA_STORAGE_TYPE_QUERY + "AND " + AlbumColumns.Artist + "=\"" + artistName + "\""; + SelectArguments albumSelectArguments = CreateSelectArgument(expression, AlbumColumns.Name + MEDIA_SORT_ORDER_ASC); + MediaDataReader dataReader = albumInfo.Select(albumSelectArguments); + string albumArtPath = ""; + + while (dataReader.Read()) + { + Album info = dataReader.Current; + string path = ""; + if (!string.IsNullOrEmpty(info.AlbumArtPath)) + path = info.AlbumArtPath; + else + path = GetAlbumArtPath(info.Id); + if (!string.IsNullOrEmpty(path)) + albumArtPath = path; + } + dataReader.Dispose(); + return albumArtPath; + } + + public static int GetAlbumCountForArtist(string artistName) + { + string expression = MEDIA_STORAGE_TYPE_QUERY + "AND " + AlbumColumns.Artist + "=\"" + artistName+"\""; + int count = 0; + + SelectArguments albumSelectArguments = CreateSelectArgument(expression, AlbumColumns.Name + MEDIA_SORT_ORDER_ASC); + MediaDataReader dataReader = albumInfo.Select(albumSelectArguments); + + while (dataReader.Read()) + { + Album info = dataReader.Current; + SelectArguments audioSelectArguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); + MediaDataReader albumDataReader = albumInfo.SelectMember(info.Id, audioSelectArguments); + if (albumDataReader.Read()) + count++; + } + dataReader.Dispose(); + return count; + } + + public static int GetMediaCountForArtist(string artistName) + { + string expression = MEDIA_STORAGE_TYPE_QUERY + "AND " + MediaInfoColumns.Artist + "=\"" + artistName+"\""; + CountArguments audioCountArguments = CreateCountArgument(expression); + int count = 0; + try + { + count = mediaInfo.CountMedia(audioCountArguments); + } + catch (ObjectDisposedException ex) + { + Tizen.Log.Error(AppConstants.LogTag, "ObjectDisposedException: " + ex.Message); + } + catch (InvalidOperationException ex) + { + Tizen.Log.Error(AppConstants.LogTag, "InvalidOperationException: " + ex.Message); + } + catch (MediaDatabaseException ex) + { + Tizen.Log.Error(AppConstants.LogTag, "MediaDatabaseException: " + ex.Message); + } + catch (Exception ex) + { + Tizen.Log.Error(AppConstants.LogTag, "Unknown Exception: " + ex.Message); + } + + return count; + } + } +} diff --git a/music-player/MediaContent/MediaContents.cs b/music-player/MediaContent/MediaContents.cs new file mode 100755 index 0000000..6ae5a12 --- /dev/null +++ b/music-player/MediaContent/MediaContents.cs @@ -0,0 +1,106 @@ +using System; +using Tizen.Content.MediaContent; + +namespace MusicPlayer.Media +{ + public class MusicItemUpdateEventArgs : EventArgs + { + internal MusicItemUpdateEventArgs(int pid, + OperationType operationType, MediaType mediaType, string id, string path, string mimeType) + { + ProcessId = pid; + OperationType = operationType; + Id = id; + Path = path; + MediaType = mediaType; + MimeType = mimeType; + } + public int ProcessId { get; } + + public OperationType OperationType { get; } + + public string Id { get; } + + public string Path { get; } + + public MediaType MediaType { get; } + + public string MimeType { get; } + } + + public class MusicDBUpdateEventArgs : EventArgs + { + internal MusicDBUpdateEventArgs(OperationType operationType, string id, string path) + { + OperationType = operationType; + Id = id; + Path = path; + } + + public OperationType OperationType { get; } + + public string Id { get; } + + public string Path { get; } + } + + public static partial class Contents + { + private static Database database; + private static MediaInfoCommand mediaInfo; + private static AlbumCommand albumInfo; + private static PlaylistCommand playlistInfo; + private const string MEDIA_STORAGE_TYPE_QUERY = " (( MEDIA_STORAGE_TYPE IS NOT 101 ) AND (MEDIA_TYPE = 3)) "; + private const string MEDIA_SORT_ORDER_ASC = " COLLATE NOCASE ASC "; + + public static event EventHandler MusicItemUpdate; + public static event EventHandler MusicDBUpdate; + + static Contents() + { + database = new Database(); + mediaInfo = new MediaInfoCommand(database.MediaDatabase); + albumInfo = new AlbumCommand(database.MediaDatabase); + playlistInfo = new PlaylistCommand(database.MediaDatabase); + MediaDatabase.MediaInfoUpdated += OnMediaDatabaseItemUpdate; + MediaDatabase.FolderUpdated += OnMediaDatabaseFolderUpdate; + } + + private static void OnMediaDatabaseItemUpdate(object sender, MediaInfoUpdatedEventArgs e) + { + if(e.MediaType == MediaType.Music) + { + MusicItemUpdateEventArgs item = new MusicItemUpdateEventArgs(e.ProcessId, e.OperationType, e.MediaType, + e.Id, e.Path, e.MimeType); + MusicItemUpdate?.Invoke(null, item); + } + } + + private static void OnMediaDatabaseFolderUpdate(object sender, FolderUpdatedEventArgs e) + { + MusicDBUpdateEventArgs item = new MusicDBUpdateEventArgs(e.OperationType, e.Id, e.Path); + MusicDBUpdate?.Invoke(null, item); + } + + private static SelectArguments CreateSelectArgument(string filterExpression, string sortOrder) + { + SelectArguments arguments = new SelectArguments(); + arguments.FilterExpression = filterExpression; + arguments.SortOrder = sortOrder; + return arguments; + } + + private static CountArguments CreateCountArgument(string filterExpression) + { + CountArguments arguments = new CountArguments(); + arguments.FilterExpression = filterExpression; + return arguments; + } + + public static void Dispose() + { + database.Dispose(); + } + } + +} \ No newline at end of file diff --git a/music-player/MediaContent/MediaDatabase.cs b/music-player/MediaContent/MediaDatabase.cs new file mode 100755 index 0000000..5e3ec37 --- /dev/null +++ b/music-player/MediaContent/MediaDatabase.cs @@ -0,0 +1,39 @@ +using System; +using Tizen.Content.MediaContent; + +namespace MusicPlayer.Media +{ + class Database : IDisposable + { + private MediaDatabase mediaDatabase; + + public Database() + { + mediaDatabase = new MediaDatabase(); + mediaDatabase.Connect(); + } + + private void TerminateDatabase() + { + mediaDatabase.Disconnect(); + mediaDatabase.Dispose(); + } + + ~Database() + { + TerminateDatabase(); + } + + public void Dispose() + { + TerminateDatabase(); + // This will informed gc to not call the finalize method as resources are already released. + GC.SuppressFinalize(this); + } + + public MediaDatabase MediaDatabase + { + get { return mediaDatabase; } + } + } +} diff --git a/music-player/MediaContent/PlaylistContents.cs b/music-player/MediaContent/PlaylistContents.cs new file mode 100755 index 0000000..d3e69ff --- /dev/null +++ b/music-player/MediaContent/PlaylistContents.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using Tizen.Content.MediaContent; +using MusicPlayer.Common; + +namespace MusicPlayer.Media +{ + public static partial class Contents + { + public static List GetPlaylists() + { + List playlists = new List(); + SelectArguments arguments = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, PlaylistColumns.Name + MEDIA_SORT_ORDER_ASC); + MediaDataReader dataReader = playlistInfo.Select(arguments); + + while(dataReader.Read()) + { + Playlist playlist = dataReader.Current; + playlists.Add(playlist); + } + Tizen.Log.Debug(AppConstants.LogTag, "PlayLists Count : " + playlists.Count); + return playlists; + } + + public static Playlist GetPlaylistByName(string name) + { + string filterExpression = MEDIA_STORAGE_TYPE_QUERY + " AND " + PlaylistColumns.Name + "=\"" + name + "\""; + SelectArguments arguments = CreateSelectArgument(filterExpression, PlaylistColumns.Name + MEDIA_SORT_ORDER_ASC); + MediaDataReader dataReader = playlistInfo.Select(arguments); + + Playlist list = null; + while (dataReader.Read()) + { + list = dataReader.Current; + } + return list; + } + + public static Playlist GetPlaylistById(int playlistId) + { + Playlist list = null; + list = playlistInfo.Select(playlistId); + return list; + } + + } +} diff --git a/music-player/MediaContent/TrackContents.cs b/music-player/MediaContent/TrackContents.cs new file mode 100755 index 0000000..551a80c --- /dev/null +++ b/music-player/MediaContent/TrackContents.cs @@ -0,0 +1,26 @@ +using System.Collections.Specialized; +using Tizen.Content.MediaContent; +using MusicPlayer.Common; + +namespace MusicPlayer.Media +{ + public static partial class Contents + { + public static OrderedDictionary GetTrackList() + { + OrderedDictionary mediaList = new OrderedDictionary(); + + SelectArguments argument = CreateSelectArgument(MEDIA_STORAGE_TYPE_QUERY, MediaInfoColumns.Title + MEDIA_SORT_ORDER_ASC); + MediaDataReader dataReader = mediaInfo.SelectMedia(argument); + + while (dataReader.Read()) + { + MediaInfo info = dataReader.Current; + mediaList.Add(info.Id, info); + } + Tizen.Log.Debug(AppConstants.LogTag, "Total track retrived from database: " + mediaList.Count); + dataReader.Dispose(); + return mediaList; + } + } +} diff --git a/music-player/Models/Album.cs b/music-player/Models/Album.cs new file mode 100755 index 0000000..455e32d --- /dev/null +++ b/music-player/Models/Album.cs @@ -0,0 +1,69 @@ +using MusicPlayer.Common; + +namespace MusicPlayer.Models +{ + class MusicAlbum : PropertyNotifier + { + public MusicAlbum() + { + //this is required for Activator.CreateInstance in ListViewModel + } + + public MusicAlbum(Tizen.Content.MediaContent.Album album) + { + AlbumName = album.Name; + ArtistName = album.Artist; + Id = album.Id; + string text = album.AlbumArtPath; + if (string.IsNullOrEmpty(album.AlbumArtPath)) + { + text = AlbumDataProvider.GetAlbumArtFromTracks(album.Id); + } + AlbumArtPath = text; + } + + private string albumName; + + public string AlbumName + { + get => albumName; + set + { + string text = string.IsNullOrEmpty(value) ? "Unknown" : value; + SetProperty(ref albumName, text); + } + } + + private string artistName; + + public string ArtistName + { + get => artistName; + set + { + string text = string.IsNullOrEmpty(value) ? "Unknown" : value; + SetProperty(ref artistName, text); + } + } + + private int id; + + public int Id + { + get => id; + set => id = value; + } + + private string albumArtPath; + + public string AlbumArtPath + { + get => albumArtPath; + set + { + string thumb = string.IsNullOrEmpty(value) ? Resources.GetImagePath() + "thumbnail.png" : value; + SetProperty(ref albumArtPath, thumb); + } + } + } +} diff --git a/music-player/Models/AlbumDataProvider.cs b/music-player/Models/AlbumDataProvider.cs new file mode 100755 index 0000000..9116246 --- /dev/null +++ b/music-player/Models/AlbumDataProvider.cs @@ -0,0 +1,45 @@ +using System.Collections.Specialized; +using MusicPlayer.Media; + +namespace MusicPlayer.Models +{ + public static class AlbumDataProvider + { + private static OrderedDictionary albumsList; + + static AlbumDataProvider() + { + albumsList = Contents.GetAlbumList(); + Contents.MusicItemUpdate += OnMusicItemUpdate; + Contents.MusicDBUpdate += OnMusicDatabaseUpdate; + } + + private static void OnMusicDatabaseUpdate(object sender, MusicDBUpdateEventArgs e) + { + albumsList = Contents.GetAlbumList(); + // TODO implement database update event handler + return; + } + + private static void OnMusicItemUpdate(object sender, MusicItemUpdateEventArgs e) + { + // TODO implement database item update event handler + return; + } + + public static OrderedDictionary CurrentAlbumList() + { + return albumsList; + } + + public static OrderedDictionary GetAlbumTrackList(int albumId) + { + return Contents.GetAlbumMemberList(albumId); + } + + public static string GetAlbumArtFromTracks(int albumId) + { + return Contents.GetAlbumArtPath(albumId); + } + } +} diff --git a/music-player/Models/Artist.cs b/music-player/Models/Artist.cs new file mode 100755 index 0000000..20e9ff4 --- /dev/null +++ b/music-player/Models/Artist.cs @@ -0,0 +1,78 @@ +using System; +using MusicPlayer.Common; + +namespace MusicPlayer.Models +{ + class Artist : PropertyNotifier + { + public Artist() + { + //this is required for Activator.CreateInstance in ListViewModel + } + + public Artist(string artistName) + { + ArtistName = artistName; + AlbumCount = ArtistDataProvider.GetArtistAlbumCount(artistName).ToString(); + TrackCount = ArtistDataProvider.GetArtistTrackCount(artistName).ToString(); + TotalCount = AlbumCount + " / " + TrackCount; + AlbumArtPath = ArtistDataProvider.GetArtistAlbumArtPath(artistName); + } + + private string artistName; + + public string ArtistName + { + get => artistName; + set + { + string text = string.IsNullOrEmpty(value) ? "Unknown" : value; + SetProperty(ref artistName, text); + } + } + + private string albumCount; + + public string AlbumCount + { + get => albumCount; + set + { + string text = string.Equals(value, "1") ? " album" : " albums"; + SetProperty(ref albumCount, value + text); + } + } + + private string trackCount; + + public string TrackCount + { + get => trackCount; + set + { + string text = string.Equals(value, "1") ? " track" : " tracks"; + SetProperty(ref trackCount, value + text); + } + } + + private string totalCount; + + public string TotalCount + { + get => totalCount; + set => SetProperty(ref totalCount, value); + } + + private string albumArtPath; + + public string AlbumArtPath + { + get => albumArtPath; + set + { + string thumb = string.IsNullOrEmpty(value) ? Resources.GetImagePath() + "thumbnail.png" : value; + SetProperty(ref albumArtPath, thumb); + } + } + } +} diff --git a/music-player/Models/ArtistDataProvider.cs b/music-player/Models/ArtistDataProvider.cs new file mode 100755 index 0000000..3bd29d1 --- /dev/null +++ b/music-player/Models/ArtistDataProvider.cs @@ -0,0 +1,61 @@ +using System.Collections.Specialized; +using System.Collections.Generic; +using MusicPlayer.Media; + +namespace MusicPlayer.Models +{ + public static class ArtistDataProvider + { + private static List artistsList; + + static ArtistDataProvider() + { + artistsList = Contents.GetArtistList(); + Contents.MusicItemUpdate += OnMusicItemUpdate; + Contents.MusicDBUpdate += OnMusicDatabaseUpdate; + } + + private static void OnMusicDatabaseUpdate(object sender, MusicDBUpdateEventArgs e) + { + artistsList = Contents.GetArtistList(); + // TODO implement database update event handler + return; + } + + private static void OnMusicItemUpdate(object sender, MusicItemUpdateEventArgs e) + { + // TODO implement database item update event handler + return; + } + + public static List CurrentArtistList() + { + return artistsList; + } + + public static int GetArtistTrackCount(string artistName) + { + return Contents.GetMediaCountForArtist(artistName); + } + + public static int GetArtistAlbumCount(string artistName) + { + return Contents.GetAlbumCountForArtist(artistName); + } + + public static string GetArtistAlbumArtPath(string artistName) + { + return Contents.GetAlbumArtPathForArtist(artistName); + } + + public static OrderedDictionary GetArtistAlbumList(string artistName) + { + return Contents.GetAlbumListForArtist(artistName); + } + + public static OrderedDictionary GetArtistTrackList(string artistName) + { + return Contents.GetTrackListForArtist(artistName); + } + } +} \ No newline at end of file diff --git a/music-player/Models/ArtistDetailAlbum.cs b/music-player/Models/ArtistDetailAlbum.cs new file mode 100755 index 0000000..696549b --- /dev/null +++ b/music-player/Models/ArtistDetailAlbum.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MusicPlayer.Common; +using System.Collections.ObjectModel; + +namespace MusicPlayer.Models +{ + class ArtistDetailAlbum: ObservableCollection + { + public ArtistDetailAlbum() + { + //this is required for Activator.CreateInstance in ListViewModel + } + + public ArtistDetailAlbum(MusicAlbum album) + { + AlbumArtPath = album.AlbumArtPath; + AlbumName = album.AlbumName; + } + + public string AlbumName { get; set; } + + public string AlbumArtPath { get; set; } + } +} diff --git a/music-player/Models/LyricsModel.cs b/music-player/Models/LyricsModel.cs new file mode 100644 index 0000000..6ea25e5 --- /dev/null +++ b/music-player/Models/LyricsModel.cs @@ -0,0 +1,35 @@ +using Tizen.Multimedia; +using System.ComponentModel; +using MusicPlayer.Common; + +namespace MusicPlayer.Models +{ + class LyricsModel: PropertyNotifier + { + public LyricsModel() + { + } + + public LyricsModel(string thumbPath, string lyrics) + { + ThumbPath = thumbPath; + Lyrics = lyrics; + } + + private string thumbPath; + + public string ThumbPath + { + get => thumbPath; + set => SetProperty(ref thumbPath, value); + } + + private string lyrics; + + public string Lyrics + { + get => lyrics; + set => SetProperty(ref lyrics, value); + } + } +} diff --git a/music-player/Models/PlayerModel.cs b/music-player/Models/PlayerModel.cs new file mode 100755 index 0000000..1bc59db --- /dev/null +++ b/music-player/Models/PlayerModel.cs @@ -0,0 +1,76 @@ +using MusicPlayer.Common; +using System; + +namespace MusicPlayer.Models +{ + class PlayerModel : PropertyNotifier + { + public PlayerModel() + { + } + + private Track currentTrack; + + public Track CurrentTrack + { + get => currentTrack; + set + { + currentTrack = value; + TrackName = currentTrack.TrackTitle; + TrackArtist = currentTrack.ArtistName; + TrackLength = currentTrack.Duration; + PlayingTime = TimeSpan.FromMilliseconds(0).ToString(AppConstants.TimeFormat); + ThumbnailPath = currentTrack.ThumbnailPath; + } + } + + private string trackName; + + public string TrackName + { + get => trackName; + set => SetProperty(ref trackName, value); + } + + private string trackArtist; + + public string TrackArtist + { + get => trackArtist; + set => SetProperty(ref trackArtist, value); + } + + private string trackLength; + + public string TrackLength + { + get => trackLength; + set => SetProperty(ref trackLength, value); + } + + private string thumbnailPath; + + public string ThumbnailPath + { + get => thumbnailPath; + set => SetProperty(ref thumbnailPath, value); + } + + private string playingTime; + + public string PlayingTime + { + get => playingTime; + set => SetProperty(ref playingTime, value); + } + + private float elapsedTime; + + public float ElapsedTime + { + get => elapsedTime; + set => SetProperty(ref elapsedTime, value); + } + } +} diff --git a/music-player/Models/Track.cs b/music-player/Models/Track.cs new file mode 100755 index 0000000..1435eb8 --- /dev/null +++ b/music-player/Models/Track.cs @@ -0,0 +1,101 @@ +using System; +using MusicPlayer.Common; + +namespace MusicPlayer.Models +{ + class Track : PropertyNotifier + { + public Track() + { + //this is required for Activator.CreateInstance in ListViewModel + } + + public Track(Tizen.Content.MediaContent.AudioInfo audioInfo) + { + TrackTitle = audioInfo.Title; + AlbumName = audioInfo.Album; + Id = audioInfo.Id; + ArtistName = audioInfo.Artist; + DurationInMS = audioInfo.Duration; + Duration = TimeSpan.FromMilliseconds(audioInfo.Duration).ToString(AppConstants.TimeFormat); + ThumbnailPath = audioInfo.ThumbnailPath; + FilePath = audioInfo.Path; + } + + private string trackTitle; + + public string TrackTitle + { + get => trackTitle; + set => SetProperty(ref trackTitle, value); + } + + private string albumName; + + public string AlbumName + { + get => albumName; + set + { + string name = string.IsNullOrEmpty(value) ? "Unknown" : value; + SetProperty(ref albumName, name); + } + } + + private string artistName; + + public string ArtistName + { + get => artistName; + set + { + string name = string.IsNullOrEmpty(value) ? "Unknown" : value; + SetProperty(ref artistName, name); + } + } + + private string id; + + public string Id + { + get => id; + set => id = value; + } + + private string duration; + + public string Duration + { + get => duration; + set => SetProperty(ref duration, value); + } + + private int durationInMS; + + public int DurationInMS + { + get => durationInMS; + set => SetProperty(ref durationInMS, value); + } + + private string thumbnailPath; + + public string ThumbnailPath + { + get => thumbnailPath; + set + { + string thumb = string.IsNullOrEmpty(value) ? Resources.GetImagePath() + "thumbnail.png" : value; + SetProperty(ref thumbnailPath, thumb); + } + } + + private string filePath; + + public string FilePath + { + get => filePath; + set { filePath = value; } + } + } +} diff --git a/music-player/Models/TrackDataProvider.cs b/music-player/Models/TrackDataProvider.cs new file mode 100755 index 0000000..1809008 --- /dev/null +++ b/music-player/Models/TrackDataProvider.cs @@ -0,0 +1,35 @@ +using System.Collections.Specialized; +using MusicPlayer.Media; + +namespace MusicPlayer.Models +{ + public static class TrackDataProvider + { + private static OrderedDictionary tracksList; + + static TrackDataProvider() + { + tracksList = Contents.GetTrackList(); + Contents.MusicItemUpdate += OnMusicItemUpdate; + Contents.MusicDBUpdate += OnMusicDatabaseUpdate; + } + + private static void OnMusicDatabaseUpdate(object sender, MusicDBUpdateEventArgs e) + { + tracksList = Contents.GetTrackList(); + // TODO implement database update event handler + return; + } + + private static void OnMusicItemUpdate(object sender, MusicItemUpdateEventArgs e) + { + // TODO implement database item update event handler + return; + } + + public static OrderedDictionary CurrentTrackList() + { + return tracksList; + } + } +} diff --git a/music-player/MusicPlayer.cs b/music-player/MusicPlayer.cs new file mode 100755 index 0000000..cb65d24 --- /dev/null +++ b/music-player/MusicPlayer.cs @@ -0,0 +1,43 @@ +using System; +using Tizen.NUI; +using MusicPlayer.Views; +using MusicPlayer.Common; + +namespace MusicPlayer +{ + public class Application : NUIApplication + { + public Application() : base(ThemeOptions.PlatformThemeEnabled) + { + + } + protected override void OnCreate() + { + Tizen.Log.Info(AppConstants.LogTag, "OnCreate statrted"); + base.OnCreate(); + Window window = Window.Instance; + window.BackgroundColor = Color.White; + window.KeyEvent += OnKeyEvent; + Size2D size = window.Size; + Tizen.Log.Info(AppConstants.LogTag, "Window Size: " + size.Width + "x" + size.Height); + + ViewManager manager = new ViewManager(Window.Instance); + } + + public void OnKeyEvent(object sender, Window.KeyEventArgs e) + { + if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == AppConstants.BackKeyCode || e.Key.KeyPressedName == AppConstants.EscapeKeyCode)) + { + Exit(); + } + } + + static void Main(string[] args) + { + Tizen.Log.Info(AppConstants.LogTag, "Main statrted"); + var app = new Application(); + app.Run(args); + Tizen.Log.Info(AppConstants.LogTag, "Main finished"); + } + } +} diff --git a/music-player/MusicPlayer.sln b/music-player/MusicPlayer.sln new file mode 100644 index 0000000..531db1c --- /dev/null +++ b/music-player/MusicPlayer.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30804.86 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "music-player", "music-player.csproj", "{18A58E69-495D-4F9C-BA77-C969BE9D8104}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {18A58E69-495D-4F9C-BA77-C969BE9D8104}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {18A58E69-495D-4F9C-BA77-C969BE9D8104}.Debug|Any CPU.Build.0 = Debug|Any CPU + {18A58E69-495D-4F9C-BA77-C969BE9D8104}.Release|Any CPU.ActiveCfg = Release|Any CPU + {18A58E69-495D-4F9C-BA77-C969BE9D8104}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7072B878-F218-47CE-84F8-FC9AC39798C6} + EndGlobalSection +EndGlobal diff --git a/music-player/ViewModels/AlbumDetailViewModel.cs b/music-player/ViewModels/AlbumDetailViewModel.cs new file mode 100755 index 0000000..5117bc8 --- /dev/null +++ b/music-player/ViewModels/AlbumDetailViewModel.cs @@ -0,0 +1,88 @@ +using System.Collections.Specialized; +using MusicPlayer.Models; +using MusicPlayer.Common; + +namespace MusicPlayer.ViewModels +{ + using AudioInfo = Tizen.Content.MediaContent.AudioInfo; + class AlbumDetailViewModel : PropertyNotifier + { + public AlbumDetailViewModel(MusicAlbum album) + { + Id = album.Id; + AlbumName = album.AlbumName; + ArtistName = album.ArtistName; + AlbumArtPath = album.AlbumArtPath; + OrderedDictionary trackList = AlbumDataProvider.GetAlbumTrackList(album.Id); + listViewModel = new ListViewModel(); + listViewModel.CreateData(trackList); + listViewModel.CollectionChanged += OnAlbumDetailListChanges; + TotalTracks = listViewModel.Count.ToString(); + } + + private void OnAlbumDetailListChanges(object sender, NotifyCollectionChangedEventArgs e) + { + //TODO + TotalTracks = listViewModel.Count.ToString(); + } + + private int id; + + public int Id + { + get => id; + set => id = value; + } + + private string albumName; + + public string AlbumName + { + get => albumName; + set + { + string text = string.Equals(value,"Unknown") ? null : value; + SetProperty(ref albumName, text); + } + } + + private string artistName; + + public string ArtistName + { + get => artistName; + set + { + string text = string.Equals(value, "Unknown") ? null : value; + SetProperty(ref artistName, text); + } + } + + private string albumArtPath; + + public string AlbumArtPath + { + get => albumArtPath; + set => SetProperty(ref albumArtPath, value); + } + + private ListViewModel listViewModel; + + public ListViewModel ListViewModel + { + get => listViewModel; + } + + private string totalTracks; + + public string TotalTracks + { + get => totalTracks; + set + { + string text = string.Equals(value, "1") ? " Track" : " Tracks"; + SetProperty(ref totalTracks, value + text); + } + } + } +} diff --git a/music-player/ViewModels/AlbumViewModel.cs b/music-player/ViewModels/AlbumViewModel.cs new file mode 100755 index 0000000..a396076 --- /dev/null +++ b/music-player/ViewModels/AlbumViewModel.cs @@ -0,0 +1,54 @@ +using System.Collections.Specialized; +using MusicPlayer.Models; +using MusicPlayer.Common; + +namespace MusicPlayer.ViewModels +{ + using Album = Tizen.Content.MediaContent.Album; + class AlbumViewModel : PropertyNotifier + { + private AlbumDetailViewModel albumDetailViewModel; + + public AlbumViewModel() + { + OrderedDictionary albumList = AlbumDataProvider.CurrentAlbumList(); + listViewModel = new ListViewModel(); + listViewModel.CreateData(albumList); + listViewModel.CollectionChanged += OnAlbumListChanges; + AlbumCount = listViewModel.Count.ToString(); + } + + private void OnAlbumListChanges(object sender, NotifyCollectionChangedEventArgs e) + { + AlbumCount = listViewModel.Count.ToString(); + } + + public AlbumDetailViewModel getDetailViewModel(MusicAlbum musicAlbum) + { + if(albumDetailViewModel == null) + albumDetailViewModel = new AlbumDetailViewModel(musicAlbum); + else if (albumDetailViewModel.Id != musicAlbum.Id) + albumDetailViewModel = new AlbumDetailViewModel(musicAlbum); + return albumDetailViewModel; + } + + private ListViewModel listViewModel; + + public ListViewModel ListViewModel + { + get => listViewModel; + } + + private string albumCount; + + public string AlbumCount + { + get => albumCount; + set + { + string text = string.Equals(value, "1") ? " album" : " albums"; + SetProperty(ref albumCount, value + text); + } + } + } +} diff --git a/music-player/ViewModels/ArtistDetailViewModel.cs b/music-player/ViewModels/ArtistDetailViewModel.cs new file mode 100755 index 0000000..6d09ba3 --- /dev/null +++ b/music-player/ViewModels/ArtistDetailViewModel.cs @@ -0,0 +1,65 @@ +using System.Collections.Specialized; +using MusicPlayer.Models; +using MusicPlayer.Common; + +namespace MusicPlayer.ViewModels +{ + using Album = Tizen.Content.MediaContent.Album; + using AudioInfo = Tizen.Content.MediaContent.AudioInfo; + class ArtistDetailViewModel : PropertyNotifier + { + + public ArtistDetailViewModel(Artist artist) + { + ArtistName = artist.ArtistName; + TotalCount = artist.TotalCount; + string text = string.Equals(ArtistName, "Unknown") ? "" : ArtistName; + + OrderedDictionary albumList = ArtistDataProvider.GetArtistAlbumList(text); + albumListViewModel = new ListViewModel(); + albumListViewModel.CreateData(albumList); + + OrderedDictionary trackList = ArtistDataProvider.GetArtistTrackList(text); + trackListViewModel = new ListViewModel(); + trackListViewModel.CreateData(trackList); + + groupListViewModel = new ListViewModel(); + + foreach(MusicAlbum album in albumListViewModel) + { + ArtistDetailAlbum artistAlbum = new ArtistDetailAlbum(album); + OrderedDictionary albumTrackList = AlbumDataProvider.GetAlbumTrackList(album.Id); + ListViewModel albumTrackListViewModel = new ListViewModel(); + albumTrackListViewModel.CreateData(albumTrackList); + foreach (Track track in albumTrackListViewModel) + artistAlbum.Add(track); + groupListViewModel.Add(artistAlbum); + } + } + + private string artistName; + + public string ArtistName + { + get => artistName; + set => SetProperty(ref artistName, value); + } + + private string totalCount; + + public string TotalCount + { + get => totalCount; + set => SetProperty(ref totalCount, value); + } + + private readonly ListViewModel groupListViewModel; + public ListViewModel GroupListViewModel => groupListViewModel; + + private readonly ListViewModel albumListViewModel; + public ListViewModel AlbumListViewModel => albumListViewModel; + + private readonly ListViewModel trackListViewModel; + public ListViewModel TrackListViewModel => trackListViewModel; + } +} diff --git a/music-player/ViewModels/ArtistViewModel.cs b/music-player/ViewModels/ArtistViewModel.cs new file mode 100755 index 0000000..49d1092 --- /dev/null +++ b/music-player/ViewModels/ArtistViewModel.cs @@ -0,0 +1,54 @@ +using System.Collections.Specialized; +using System.Collections.Generic; +using MusicPlayer.Models; +using MusicPlayer.Common; + +namespace MusicPlayer.ViewModels +{ + class ArtistViewModel : PropertyNotifier + { + private ArtistDetailViewModel artistDetailViewModel; + + public ArtistViewModel() + { + List artistList = ArtistDataProvider.CurrentArtistList(); + listViewModel = new ListViewModel(); + listViewModel.CreateData(artistList); + listViewModel.CollectionChanged += OnArtistListChanges; + ArtistCount = listViewModel.Count.ToString(); + } + + private void OnArtistListChanges(object sender, NotifyCollectionChangedEventArgs e) + { + artistCount = listViewModel.Count.ToString(); + } + + public ArtistDetailViewModel getDetailViewModel(Artist artist) + { + if (artistDetailViewModel == null) + artistDetailViewModel = new ArtistDetailViewModel(artist); + else if (artistDetailViewModel.ArtistName != artist.ArtistName) + artistDetailViewModel = new ArtistDetailViewModel(artist); + return artistDetailViewModel; + } + + private ListViewModel listViewModel; + + public ListViewModel ListViewModel + { + get => listViewModel; + } + + private string artistCount; + + public string ArtistCount + { + get => artistCount; + set + { + string text = string.Equals(value, "1") ? " artist" : " artists"; + SetProperty(ref artistCount, value + text); + } + } + } +} \ No newline at end of file diff --git a/music-player/ViewModels/ListViewModel.cs b/music-player/ViewModels/ListViewModel.cs new file mode 100755 index 0000000..24ea54e --- /dev/null +++ b/music-player/ViewModels/ListViewModel.cs @@ -0,0 +1,38 @@ +using System.Collections; +using System.Collections.Specialized; +using System.Collections.ObjectModel; +using MusicPlayer.Models; +using Tizen.Content.MediaContent; +using MusicPlayer.Common; +using System; +using System.Collections.Generic; + +namespace MusicPlayer.ViewModels +{ + class ListViewModel : ObservableCollection where T : new() + { + public ListViewModel() + { + } + + public void CreateData(OrderedDictionary dict) + { + foreach (DictionaryEntry item in dict) + { + Add((T)Activator.CreateInstance(typeof(T), new object[] { (U)item.Value })); + } + Tizen.Log.Debug(AppConstants.LogTag, "Observable list item count: " + this.Count); + } + + public void CreateData(List list) + { + foreach (var item in list) + { + Add((T)Activator.CreateInstance(typeof(T), new object[] { (U)item })); + } + Tizen.Log.Debug(AppConstants.LogTag, "Observable list item count: " + this.Count); + } + + + } +} diff --git a/music-player/ViewModels/LyricsViewModel.cs b/music-player/ViewModels/LyricsViewModel.cs new file mode 100644 index 0000000..6307f28 --- /dev/null +++ b/music-player/ViewModels/LyricsViewModel.cs @@ -0,0 +1,64 @@ +using Tizen.Multimedia; +using MusicPlayer.Models; +using MusicPlayer.Common; +using Tizen.NUI; + +namespace MusicPlayer.ViewModels +{ + class LyricsViewModel : PropertyNotifier + { + internal LyricsModel lyricsModel; + + public LyricsViewModel() + { + lyricsModel = new LyricsModel(); + } + + public LyricsViewModel(Track currentTrack) + { + FilePath = currentTrack.FilePath; + lyricsModel = new LyricsModel(currentTrack.ThumbnailPath, GetLyrics(FilePath)); + } + + public string FilePath { get; set; } + + private Track currentTrack; + + public Track CurrentTrack + { + get => currentTrack; + set + { + currentTrack = value; + FilePath = currentTrack.FilePath; + lyricsModel.ThumbPath = currentTrack.ThumbnailPath; + lyricsModel.Lyrics = GetLyrics(FilePath); + } + } + + private Color lyricsBackgroundColor; + + public Color LyricsBackgroundColor + { + get => lyricsBackgroundColor; + set => SetProperty(ref lyricsBackgroundColor, value); + } + + private string GetLyrics(string path) + { + var metadataExtractor = new MetadataExtractor(path); + Metadata metadata = metadataExtractor.GetMetadata(); + string lyrics = metadata.UnsyncLyrics; + if(string.IsNullOrEmpty(lyrics)) + { + LyricsBackgroundColor = Color.Transparent; + return string.Empty; + } + else + { + LyricsBackgroundColor = UIColors.LyricsBackground; + return lyrics; + } + } + } +} diff --git a/music-player/ViewModels/PlayerViewModel.cs b/music-player/ViewModels/PlayerViewModel.cs new file mode 100755 index 0000000..0b53d16 --- /dev/null +++ b/music-player/ViewModels/PlayerViewModel.cs @@ -0,0 +1,414 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MusicPlayer.Models; +using MusicPlayer.Common; +using MusicPlayer.Core; +using Tizen.NUI; +using Tizen.Multimedia; +using System.Threading.Tasks; + +namespace MusicPlayer.ViewModels +{ + class PlayerViewModel : PropertyNotifier + { + public const string PlayState = "Play"; + public const string PauseState = "Pause"; + private const int PlaybackTimerDuration = 1000; + private const int MinPaletteColorCount = 2; + + internal PlayerModel playerModel; + internal LyricsViewModel lyricsViewModel; + private Timer playbackTimer; + private bool isVolumeChanging; + + public PlayerViewModel() + { + lyricsViewModel = new LyricsViewModel(); + playingListViewModel = new PlayingListViewModel(); + playerModel = new PlayerModel(); + playerModel.ElapsedTime = 0.0f; + PlayingStatus = PlayingStatus.None; + PlayerController.Instance.PlayerEventOccurred += OnPlayerEventOccurred; + playbackTimer = new Timer(PlaybackTimerDuration); + playbackTimer.Tick += OnPlaybackTimerTick; + isVolumeChanging = false; + VolumeLevel = AudioManager.VolumeController.Level[AudioVolumeType.Media]; + AudioManager.VolumeController.Changed += OnVolumeLevelChanged; + HasPreviousTrack = playingListViewModel.HasPrev(); + HasNextTrack = playingListViewModel.HasNext(); + } + + internal PlayingListViewModel playingListViewModel; + + public PlayingListViewModel CurrentPlayingListViewModel + { + get => playingListViewModel; + } + + private string playButtonState; + + public string PlayButtonState + { + get => playButtonState; + set => SetProperty(ref playButtonState, value); + } + + private float volumeLevel; + + public float VolumeLevel + { + get => volumeLevel; + set => SetProperty(ref volumeLevel, value); + } + + private bool hasPreviousTrack; + + public bool HasPreviousTrack + { + get => hasPreviousTrack; + set => SetProperty(ref hasPreviousTrack, value); + } + + private bool hasNextTrack; + + public bool HasNextTrack + { + get => hasNextTrack; + set => SetProperty(ref hasNextTrack, value); + } + + private PropertyMap playerBackground; + + public PropertyMap PlayerBackground + { + get => playerBackground; + set => SetProperty(ref playerBackground, value); + } + + private PlayingStatus playingStatus; + + public PlayingStatus PlayingStatus + { + get => playingStatus; + set => UpdatePlayingStatus(value); + } + + public void SetPlayingList(ListViewModel trackListVM) + { + playingListViewModel.SetTrackListViewModel(trackListVM); + } + + public void SetCurrentTrack(Track track) + { + Tizen.Log.Info(AppConstants.LogTag, "Setting Current track"); + playerModel.CurrentTrack = track; + lyricsViewModel.CurrentTrack = track; + //TO DO need to set index properly + Track current = playingListViewModel.Current(); + if (current == null) + { + Tizen.Log.Error(AppConstants.LogTag, "Current track is null so setting new track"); + playingListViewModel.SetPlayingTrack(track); + } + // updating prev/next button state + HasPreviousTrack = playingListViewModel.HasPrev(); + HasNextTrack = playingListViewModel.HasNext(); + + // SetBackground + SetExtractedBackground(track.ThumbnailPath); + + PlayerController.Instance.Uri = track.FilePath; + StartPlayback(); + } + + public void NextButtonClicked() + { + Track nextTrack = playingListViewModel.Next(); + if (nextTrack == null) + { + Tizen.Log.Error(AppConstants.LogTag, "nextTrack is null"); + StopPlayback(); + return; + } + Tizen.Log.Debug(AppConstants.LogTag, "Next track is: " + nextTrack.TrackTitle); + SetCurrentTrack(nextTrack); + } + + public void PrevButtonClicked() + { + Track previousTrack = playingListViewModel.Prev(); + if (previousTrack == null) + { + Tizen.Log.Error(AppConstants.LogTag, "previousTrack is null"); + StopPlayback(); + return; + } + Tizen.Log.Debug(AppConstants.LogTag, "Prev track is: " + previousTrack.TrackTitle); + SetCurrentTrack(previousTrack); + } + + public void ShuffleChanged() + { + ShuffleMode currentMode = playingListViewModel.ShuffleMode; + playingListViewModel.ShuffleMode = ((currentMode == ShuffleMode.Off) ? ShuffleMode.On : ShuffleMode.Off); + } + + public void RepeatChanged() + { + var values = Enum.GetValues(typeof(RepeatMode)); + int i = 0; + foreach (RepeatMode mode in values) + { + if (playingListViewModel.RepeatMode == mode) + break; + i++; + } + + RepeatMode[] repeatArr = (RepeatMode[])values; + RepeatMode new_mode; + if (i + 1 >= values.Length) + { + new_mode = repeatArr[0]; + } + else + { + new_mode = repeatArr[i + 1]; + } + playingListViewModel.RepeatMode = new_mode; + } + + public void PlayingStatusChanged() + { + if (PlayingStatus == PlayingStatus.Playing) + { + PlayingStatus = PlayingStatus.Paused; + Pause(); + playbackTimer.Stop(); + } + else + { + PlayingStatus = PlayingStatus.Playing; + Resume(); + playbackTimer.Start(); + } + } + + public void UpdatePlayerPosition(float value) + { + int currentPosition = (int)(playerModel.CurrentTrack.DurationInMS * value); + PlayerController.Instance.SetPosition(currentPosition); + playerModel.PlayingTime = TimeSpan.FromMilliseconds(currentPosition).ToString(AppConstants.TimeFormat); + playbackTimer.Start(); + } + + public void StopPlaybackTimer() + { + playbackTimer.Stop(); + } + + public void SetElapsedTime(float value) + { + int currentPosition = (int)(playerModel.CurrentTrack.DurationInMS * value); + playerModel.PlayingTime = TimeSpan.FromMilliseconds(currentPosition).ToString(AppConstants.TimeFormat); + } + + public void VolumeChangeStarted() + { + isVolumeChanging = true; + } + + public void VolumeChangeFinished(int value) + { + VolumeLevelChanged(value); + isVolumeChanging = false; + } + public void VolumeLevelChanged(int value) + { + AudioManager.VolumeController.Level[AudioVolumeType.Media] = value; + } + + private void UpdatePlayingStatus(PlayingStatus status) + { + playingStatus = status; + switch (status) + { + case PlayingStatus.Playing: + PlayButtonState = PauseState; + break; + case PlayingStatus.Paused: // Fall Through + case PlayingStatus.Stopped: // Fall Through + case PlayingStatus.None: + PlayButtonState = PlayState; + break; + } + } + + private bool OnPlaybackTimerTick(object source, Timer.TickEventArgs e) + { + UpdatePlayingTime(); + return true; + } + + private void OnPlayerEventOccurred(object sender, PlayerEventArgs e) + { + Tizen.Log.Error(AppConstants.LogTag, "Player Event Occurred:"); + Tizen.Log.Error(AppConstants.LogTag, "\t"+e.Type.ToString()); + Tizen.Log.Error(AppConstants.LogTag, "\t:"+e.Description); + if(e.Type == EventType.PlaybackCompleted) + { + PlayNext(); + } + } + + private void PlayNext() + { + if(playingListViewModel.RepeatMode == RepeatMode.Off) + { + Tizen.Log.Debug(AppConstants.LogTag, "Repeat is off, can't play next"); + StopPlayback(); + UpdatePlayingTime(); + return; + } + NextButtonClicked(); + } + + private void UpdatePlayingTime() + { + int position = PlayerController.Instance.GetPosition(); + playerModel.ElapsedTime = position / (float)playerModel.CurrentTrack.DurationInMS; + playerModel.PlayingTime = TimeSpan.FromMilliseconds(position).ToString(AppConstants.TimeFormat); + } + + private void StartPlayback() + { + PlayingStatus = PlayingStatus.Playing; + Play(); + playbackTimer.Start(); + } + + private void StopPlayback() + { + PlayingStatus = PlayingStatus.Stopped; + Stop(); + playbackTimer.Stop(); + } + + private void Play() + { + PlayerController.Instance.Play(); + } + private void Pause() + { + PlayerController.Instance.Pause(); + } + private void Resume() + { + PlayerController.Instance.Resume(); + } + private void Stop() + { + PlayerController.Instance.Stop(); + } + + private void OnVolumeLevelChanged(object sender, VolumeChangedEventArgs e) + { + if(e.Type == AudioVolumeType.Media && isVolumeChanging == false) + { + VolumeLevel = e.Level; + } + } + + private ImageVisual CreateImageVisual() + { + ImageVisual visual = new ImageVisual() + { + URL = Resources.GetImagePath() + "gradient_music_light.png", + }; + return visual; + } + + private GradientVisual CreateGradientVisual(PropertyArray stopColor) + { + GradientVisual gradientVisual = new GradientVisual() + { + StartPosition = new Vector2(0.0f, -1.0f), + EndPosition = new Vector2(0.0f, 1.0f), + StopColor = stopColor, + SpreadMethod = GradientVisualSpreadMethodType.Pad, + }; + return gradientVisual; + } + + private PropertyArray GetGradientStopColors(Palette palette) + { + PropertyArray propertyArray = new PropertyArray(); + if(palette == null) + { + Tizen.Log.Error(AppConstants.LogTag, "Color palatte from background is null"); + return propertyArray; + } + + Palette.Swatch lightMutedSwatch = palette.GetLightMutedSwatch(); + Palette.Swatch darkMutedSwatch = palette.GetDarkMutedSwatch(); + if(lightMutedSwatch != null && darkMutedSwatch != null) + { + propertyArray.PushBack(new PropertyValue(lightMutedSwatch.GetRgb())); + propertyArray.PushBack(new PropertyValue(darkMutedSwatch.GetRgb())); + return propertyArray; + } + + Palette.Swatch lightVibrantSwatch = palette.GetLightVibrantSwatch(); + Palette.Swatch darkVibrantSwatch = palette.GetDarkVibrantSwatch(); + if(lightVibrantSwatch != null && darkVibrantSwatch != null) + { + propertyArray.PushBack(new PropertyValue(lightVibrantSwatch.GetRgb())); + propertyArray.PushBack(new PropertyValue(darkVibrantSwatch.GetRgb())); + return propertyArray; + } + + Palette.Swatch mutedSwatch = palette.GetMutedSwatch(); + Palette.Swatch vibrantSwatch = palette.GetVibrantSwatch(); + if(mutedSwatch != null && vibrantSwatch != null) + { + propertyArray.PushBack(new PropertyValue(mutedSwatch.GetRgb())); + propertyArray.PushBack(new PropertyValue(vibrantSwatch.GetRgb())); + return propertyArray; + } + + IReadOnlyCollection swatches = palette.GetSwatches(); + foreach(Palette.Swatch swatch in swatches) + { + if(propertyArray.Count() >= MinPaletteColorCount) + { + return propertyArray; + } + if(swatch != null) + { + propertyArray.PushBack(new PropertyValue(swatch.GetRgb())); + } + } + return propertyArray; + } + + private async void SetExtractedBackground(string path) + { + Tizen.Log.Debug(AppConstants.LogTag, "Path for the color image thumbnail" + path); + Palette palette = await ColorExtractor.GetPaletteAsync(path); + PropertyArray stopColor = GetGradientStopColors(palette); + if (stopColor.Count() < MinPaletteColorCount) + { + Tizen.Log.Info(AppConstants.LogTag, "Palette or palatte values not valid, adding default gradient"); + ImageVisual imageVisual = CreateImageVisual(); + PlayerBackground = imageVisual.OutputVisualMap; + return; + } + else + { + Tizen.Log.Info(AppConstants.LogTag, "setting palette color"); + GradientVisual gradientVisual = CreateGradientVisual(stopColor); + PlayerBackground = gradientVisual.OutputVisualMap; + } + } + } +} diff --git a/music-player/ViewModels/PlayingListViewModel.cs b/music-player/ViewModels/PlayingListViewModel.cs new file mode 100755 index 0000000..d84e547 --- /dev/null +++ b/music-player/ViewModels/PlayingListViewModel.cs @@ -0,0 +1,287 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using MusicPlayer.ViewModels; +using System.Threading; +using MusicPlayer.Common; +using MusicPlayer.Models; + +namespace MusicPlayer.ViewModels +{ + public static class ThreadSafeRandom + { + [ThreadStatic] private static Random Local; + + public static Random ThisThreadsRandom + { + get { return Local ??= new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId)); } + } + } + + static class ShuffleExtension + { + public static void Shuffle(this IList list) + { + int n = list.Count; + while (n > 1) + { + n--; + int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1); + T value = list[k]; + list[k] = list[n]; + list[n] = value; + } + } + } + + class PlayingListViewModel : PropertyNotifier + { + private ListViewModel tracklistViewModel; + private List shuffleList; + private int currentIndex; + private RepeatMode repeatMode; + private ShuffleMode shuffleMode; + public event EventHandler ItemsSourceChanged; + private string shuffleButtonUrl; + private string repeatButtonUrl; + + public PlayingListViewModel() + { + shuffleList = new List(); + currentIndex = -1; + tracklistViewModel = null; + RepeatMode = RepeatMode.Off; + ShuffleMode = ShuffleMode.Off; + } + + private void UpdateShuffleList(int count) + { + shuffleList.Clear(); + shuffleList.AddRange(Enumerable.Range(0, count - 1)); + } + + private void OnItemsSourceChanged(EventArgs eventArgs) + { + ItemsSourceChanged?.Invoke(this, eventArgs); + } + + public void SetTrackListViewModel(ListViewModel trackListVM) + { + // Need to check for same VM and in case same VM just update the playing track + Tizen.Log.Info(AppConstants.LogTag, "Setting Current Playing list"); + tracklistViewModel = trackListVM; + currentIndex = -1; + RepeatMode = RepeatMode.Off; + ShuffleMode = ShuffleMode.Off; + OnItemsSourceChanged(new EventArgs()); + } + + public ListViewModel TrackListVM + { + get => tracklistViewModel; + } + + public string ShuffleButtonState + { + get => shuffleButtonUrl; + set => SetProperty(ref shuffleButtonUrl, value); + } + + public ShuffleMode ShuffleMode + { + get => shuffleMode; + set + { + shuffleMode = value; + if(value == ShuffleMode.On) + { + shuffleList.Shuffle(); + } + else + { + if (tracklistViewModel != null) + { + UpdateShuffleList(tracklistViewModel.Count); + } + } + ShuffleButtonState = shuffleMode.ToString(); + } + } + + public string RepeatButtonState + { + get => repeatButtonUrl; + set => SetProperty(ref repeatButtonUrl, value); + } + + public RepeatMode RepeatMode + { + get => repeatMode; + set + { + repeatMode = value; + RepeatButtonState = repeatMode.ToString(); + } + } + + public Track Next() + { + if(currentIndex < 0 ) + { + Tizen.Log.Error(AppConstants.LogTag,"Invalid track index"); + return null; + } + if(RepeatMode == RepeatMode.RepeatOne) + { + return tracklistViewModel[shuffleList[currentIndex]]; + } + else if(RepeatMode == RepeatMode.Off) + { + if (currentIndex + 1 >= shuffleList.Count) + { + return null; + } + else + { + currentIndex += 1; + return tracklistViewModel[shuffleList[currentIndex]]; + } + } + else + { + if (currentIndex + 1 >= shuffleList.Count) + { + currentIndex = 0; + return tracklistViewModel[shuffleList[currentIndex]]; + } + else + { + currentIndex += 1; + return tracklistViewModel[shuffleList[currentIndex]]; + } + } + } + + public Track Prev() + { + if (currentIndex < 0) + { + Tizen.Log.Error(AppConstants.LogTag, "Invalid track index"); + return null; + } + if (RepeatMode == RepeatMode.RepeatOne) + { + return tracklistViewModel[shuffleList[currentIndex]]; + } + else if (RepeatMode == RepeatMode.Off) + { + if (currentIndex - 1 < 0) + { + return null; + } + else + { + currentIndex -= 1; + return tracklistViewModel[shuffleList[currentIndex]]; + } + } + else + { + if (currentIndex - 1 < 0) + { + currentIndex = shuffleList.Count-1; + return tracklistViewModel[shuffleList[currentIndex]]; + } + else + { + currentIndex -= 1; + return tracklistViewModel[shuffleList[currentIndex]]; + } + } + } + + public bool HasNext() + { + if (IsTrackIndexInvalid()) + { + return false; + } + if(RepeatMode == RepeatMode.RepeatOne || RepeatMode == RepeatMode.RepeatAll) + { + return true; + } + else + { + return currentIndex + 1 < shuffleList.Count ? true : false; + } + } + + public bool HasPrev() + { + if (IsTrackIndexInvalid()) + { + return false; + } + if (RepeatMode == RepeatMode.RepeatOne || RepeatMode == RepeatMode.RepeatAll) + { + return true; + } + else + { + return currentIndex - 1 >= 0 ? true : false; + } + } + + public Track Current() + { + if (IsTrackIndexInvalid()) + { + return null; + } + else + { + return tracklistViewModel[shuffleList[currentIndex]]; + } + } + + public void SetPlayingTrack(string mediaId) + { + int count; + for (count = 0; count< tracklistViewModel.Count; ++count) + { + if (mediaId == tracklistViewModel[count].Id) + { + currentIndex = count; + return; + } + } + currentIndex = -1; + } + + public void SetPlayingTrack(Track track) + { + int count; + for (count = 0; count < tracklistViewModel.Count; ++count) + { + if (track == tracklistViewModel[count]) + { + Tizen.Log.Debug(AppConstants.LogTag, "Current track index is " + count); + currentIndex = count; + return; + } + } + currentIndex = -1; + } + + private bool IsTrackIndexInvalid() + { + if(currentIndex < 0 || currentIndex > shuffleList.Count) + { + return true; + } + return false; + } + } +} diff --git a/music-player/ViewModels/TrackViewModel.cs b/music-player/ViewModels/TrackViewModel.cs new file mode 100755 index 0000000..833545f --- /dev/null +++ b/music-player/ViewModels/TrackViewModel.cs @@ -0,0 +1,43 @@ +using System.Collections.Specialized; +using MusicPlayer.Models; +using MusicPlayer.Common; + +namespace MusicPlayer.ViewModels +{ + using AudioInfo = Tizen.Content.MediaContent.AudioInfo; + class TrackViewModel : PropertyNotifier + { + public TrackViewModel() + { + OrderedDictionary trackList = TrackDataProvider.CurrentTrackList(); + listViewModel = new ListViewModel(); + listViewModel.CreateData(trackList); + listViewModel.CollectionChanged += OnTrackListChanges; + TrackCount = listViewModel.Count.ToString(); + } + + private void OnTrackListChanges(object sender, NotifyCollectionChangedEventArgs e) + { + TrackCount = listViewModel.Count.ToString(); + } + + private ListViewModel listViewModel; + + public ListViewModel ListViewModel + { + get => listViewModel; + } + + private string trackCount; + + public string TrackCount + { + get => trackCount; + set + { + string text = string.Equals(value, "1") ? " track" : " tracks"; + SetProperty(ref trackCount, value + text); + } + } + } +} diff --git a/music-player/Views/AlbumDetailLayout.cs b/music-player/Views/AlbumDetailLayout.cs new file mode 100755 index 0000000..cb549af --- /dev/null +++ b/music-player/Views/AlbumDetailLayout.cs @@ -0,0 +1,142 @@ +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using MusicPlayer.Common; + +namespace MusicPlayer.Views +{ + class AlbumDetailLayout : RecyclerViewItem + { + private View itemSeperator; + private TextLabel titleLabel; + private TextLabel subtitleLabel; + private TextLabel additionalLabel; + + private const int LayoutMargin = 16; + private const int LayoutPadding = 32; + private const int SeperatorHeight = 1; + private const int LeftPadding = 64; + private const int X = 0; + + public AlbumDetailLayout(int width = 832, int height = 108) : base() + { + base.OnInitialize(); + base.IsCreateByXaml = true; + WidthSpecification = width; + HeightSpecification = height; + + // to show the rounded rect of the bg + BackgroundColor = Color.Transparent; + + titleLabel = CreateTitleLabel(); + subtitleLabel = CreateSubTitleLabel(); + additionalLabel = CreateAdditionalLabel(width); + itemSeperator = CreateItemSeparator(width, height); + IsCreateByXaml = true; + } + + private TextLabel CreateTitleLabel() + { + TextLabel titleLabel = new TextLabel() + { + Size2D = new Size2D(596, 40), + TextColor = UIColors.HEX001447, + PixelSize = 32, + FontFamily = "BreezeSans", + VerticalAlignment = VerticalAlignment.Center, + Padding=new Extents(LayoutPadding,0,0,0), + IsCreateByXaml = true, + Position2D = new Position2D(X , LayoutMargin), + }; + base.Add(titleLabel); + return titleLabel; + } + + private TextLabel CreateSubTitleLabel() + { + TextLabel subtitleLabel = new TextLabel() + { + Size2D= new Size2D(596,36), + TextColor = UIColors.HEX001447, + PixelSize = 28, + FontFamily = "BreezeSans", + VerticalAlignment = VerticalAlignment.Center, + Padding = new Extents(LayoutPadding, 0, 0, 0), + IsCreateByXaml = true, + Position2D = new Position2D(X , LayoutMargin + 40) + }; + base.Add(subtitleLabel); + return subtitleLabel; + } + + private TextLabel CreateAdditionalLabel(int width) + { + TextLabel additionalLabel = new TextLabel() + { + Size2D= new Size2D(108,36), + TextColor = UIColors.HEX001447, + PixelSize = 28, + FontFamily = "BreezeSans", + VerticalAlignment = VerticalAlignment.Center, + HorizontalAlignment =HorizontalAlignment.End, + IsCreateByXaml = true, + Position2D = new Position2D(width-LayoutPadding-LeftPadding-108, 36) + }; + base.Add(additionalLabel); + return additionalLabel; + } + + private View CreateItemSeparator(int width, int height) + { + View itemSeperator = new View() + { + Size2D = new Size2D(width, SeperatorHeight), + ExcludeLayouting = true, + Position2D = new Position2D(X , height - SeperatorHeight), + BackgroundColor = UIColors.ItemSeperator, + }; + base.Add(itemSeperator); + return itemSeperator; + } + + public TextLabel TitleLabel + { + get => titleLabel; + } + public TextLabel SubtitleLabel + { + get => subtitleLabel; + } + public TextLabel AdditionalLabel + { + get => additionalLabel; + } + + protected override void Dispose(DisposeTypes type) + { + if (Disposed) + { + return; + } + if (type == DisposeTypes.Explicit) + { + base.Remove(itemSeperator); + itemSeperator?.Dispose(); + itemSeperator = null; + + base.Remove(titleLabel); + titleLabel?.Dispose(); + titleLabel = null; + + base.Remove(subtitleLabel); + subtitleLabel?.Dispose(); + subtitleLabel = null; + + base.Remove(additionalLabel); + additionalLabel?.Dispose(); + additionalLabel = null; + } + base.Dispose(type); + } + } +} diff --git a/music-player/Views/AlbumDetailView.cs b/music-player/Views/AlbumDetailView.cs new file mode 100755 index 0000000..b39e11f --- /dev/null +++ b/music-player/Views/AlbumDetailView.cs @@ -0,0 +1,243 @@ +using MusicPlayer.ViewModels; +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using Tizen.NUI.Binding; +using MusicPlayer.Common; + +namespace MusicPlayer.Views +{ + class AlbumDetailView : View + { + private const int LayoutPadding = 64; + private const int IconSize = 48; + private const int AlbumArtSize = 520; + private const int ControlViewWidth = 960; + private const int ControlViewHeight = 60; + private const int ControlViewMargin = 6; + + private BaseView baseView; + private View contentView; + private View leftView; + private View rightView; + private ImageView albumArtIcon; + private TextLabel albumNameLabel; + private TextLabel albumArtistLabel; + private View controlsView; + private TextLabel trackCountLabel; + private Button playAllIcon; // TODO need to implement playall feature + private Button shuffleAndPlayAllIcon; // TODO need to implement playlist manager + private CollectionView collectionView; + + private AlbumDetailViewModel viewModel; + public AlbumDetailView(AlbumDetailViewModel viewModel) : base() + { + this.viewModel = viewModel; + BindingContext = viewModel; + BackgroundColor = UIColors.HEXEEEFF1; + WidthResizePolicy = ResizePolicyType.FillToParent; + HeightResizePolicy = ResizePolicyType.FillToParent; + + //TODO need to change this part after implementation of Command Interface + baseView = new BaseView() + { + Title = viewModel.AlbumName, + BackButton = true, + MoreButton = true, + SearchButton = true, + BackgroundColor = UIColors.HEXEEEFF1, + }; + base.Add(baseView); + contentView = new View() + { + WidthSpecification = LayoutParamPolicies.MatchParent, + HeightSpecification = 876, + Layout = new FlexLayout() + { + Direction = FlexLayout.FlexDirection.Row, + ItemsAlignment = FlexLayout.AlignmentType.FlexStart, + Justification = FlexLayout.FlexJustification.FlexStart, + }, + }; + baseView.SetContent = contentView; + + leftView = CreateLeftView(); + rightView = CreateRightView(); + controlsView = AddControlView(); + AddControlElements(); + collectionView = AddCollectionView(); + AddAlbumArt(); + AddAlbumInfo(); + } + + private void OnTrackSelection(object sender, SelectionChangedEventArgs e) + { + + } + + private Button CreateButton(string url, int x, int y) + { + ButtonStyle buttonStyle = new ButtonStyle() + { + Icon = new ImageViewStyle() + { + ResourceUrl = url, + }, + IsSelectable = false, + IsEnabled = true, + }; + + Button button = new Button(buttonStyle) + { + Size2D = new Size2D(IconSize, IconSize), + Position2D = new Position2D(x, y), + }; + return button; + } + + private View CreateLeftView() + { + View leftView = new View() + { + BackgroundColor = UIColors.HEXEEEFF1, + Size2D = new Size2D(Window.Instance.WindowSize.Width / 2, 752), + Position2D = new Position2D(0, 0), + Layout = new FlexLayout + { + Direction = FlexLayout.FlexDirection.Column, + ItemsAlignment = FlexLayout.AlignmentType.Center, + Justification = FlexLayout.FlexJustification.FlexStart, + }, + Padding = new Extents(0, 0, ControlViewHeight, 42), + }; + contentView.Add(leftView); + return leftView; + } + + private View CreateRightView() + { + View rightView = new View() + { + BackgroundColor = UIColors.HEXEEEFF1, + Size2D = new Size2D(Window.Instance.WindowSize.Width / 2, 752), + Position2D = new Position2D(Window.Instance.WindowSize.Width / 2, 0), + Layout = new FlexLayout + { + Direction = FlexLayout.FlexDirection.Column, + ItemsAlignment = FlexLayout.AlignmentType.Center, + Justification = FlexLayout.FlexJustification.FlexStart, + }, + }; + contentView.Add(rightView); + return rightView; + } + + private void AddAlbumArt() + { + albumArtIcon = new ImageView() + { + BackgroundColor = UIColors.HEXEEEFF1, + Size2D = new Size2D(AlbumArtSize, AlbumArtSize), + }; + albumArtIcon.SetBinding(ImageView.ResourceUrlProperty, "AlbumArtPath"); + leftView.Add(albumArtIcon); + } + private void AddAlbumInfo() + { + albumNameLabel = new TextLabel() + { + Text = "ALBUM NAME", + Size2D = new Size2D(640, 48), + PixelSize = 36, + Margin = new Extents(0, 0, 32, 0), + FontFamily = "BreezeSans", + TextColor = UIColors.HEX001447, + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + Ellipsis = true, + }; + albumNameLabel.SetBinding(TextLabel.TextProperty, "AlbumName"); + leftView.Add(albumNameLabel); + albumArtistLabel = new TextLabel() + { + Text = "ARTIST NAME", + Size2D = new Size2D(640, 36), + PixelSize = 28, + Margin = new Extents(0, 0, 14, 0), + FontFamily = "BreezeSans", + TextColor = UIColors.HEX000209, + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + Ellipsis = true, + }; + albumArtistLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); + leftView.Add(albumArtistLabel); + + } + private View AddControlView() + { + View controlsView = new View() + { + BackgroundColor = UIColors.HEXEEEFF1, + Size2D = new Size2D(ControlViewWidth, ControlViewHeight), + Padding = new Extents(LayoutPadding, LayoutPadding, ControlViewMargin, ControlViewMargin), + }; + rightView.Add(controlsView); + return controlsView; + } + + private void AddControlElements() + { + trackCountLabel = new TextLabel() + { + Text = "TRACK COUNT", + Size2D = new Size2D(664, 36), + Position2D = new Position2D(LayoutPadding, 12), + PixelSize = 28, + Margin = new Extents(0, 0, ControlViewMargin, ControlViewMargin), + FontFamily = "BreezeSans", + TextColor = UIColors.HEX001447, + HorizontalAlignment = HorizontalAlignment.Begin, + VerticalAlignment = VerticalAlignment.Center, + }; + trackCountLabel.SetBinding(TextLabel.TextProperty, "TotalTracks"); + controlsView.Add(trackCountLabel); + + playAllIcon = CreateButton(Resources.GetImagePath() + "playlist_active.png.png", Window.Instance.WindowSize.Width / 2 - LayoutPadding - IconSize, ControlViewMargin); + playAllIcon.Margin = new Extents(40, 0, 0, 0); + controlsView.Add(playAllIcon); + + shuffleAndPlayAllIcon = CreateButton(Resources.GetImagePath() + "shuffle_on.png", Window.Instance.WindowSize.Width / 2 - LayoutPadding - 2 * IconSize - 40, ControlViewMargin); + playAllIcon.Margin = new Extents(32, 0, 0, 0); + controlsView.Add(shuffleAndPlayAllIcon); + + } + + private CollectionView AddCollectionView() + { + CollectionView collectionView = new CollectionView() + { + Size2D = new Size2D(832, 108), + BackgroundImage = Resources.GetImagePath() + "list_view_bg.png", + ItemsLayouter = new LinearLayouter(), + ItemTemplate = new DataTemplate(() => + { + AlbumDetailLayout layout = new AlbumDetailLayout(); + layout.TitleLabel.SetBinding(TextLabel.TextProperty, "TrackTitle"); + layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); + layout.AdditionalLabel.SetBinding(TextLabel.TextProperty, "Duration"); + return layout; + }), + ScrollingDirection = ScrollableBase.Direction.Vertical, + HeightSpecification = LayoutParamPolicies.WrapContent, + SelectionMode = ItemSelectionMode.Single, + }; + rightView.Add(collectionView); + FlexLayout.SetFlexGrow(collectionView, 1); + FlexLayout.SetFlexShrink(collectionView, 1); + collectionView.ItemsSource = viewModel.ListViewModel; + collectionView.SelectionChanged += OnTrackSelection; + return collectionView; + } + } +} diff --git a/music-player/Views/AlbumView.cs b/music-player/Views/AlbumView.cs new file mode 100755 index 0000000..16bddc9 --- /dev/null +++ b/music-player/Views/AlbumView.cs @@ -0,0 +1,72 @@ +using MusicPlayer.ViewModels; +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using Tizen.NUI.Binding; +using MusicPlayer.Common; +using MusicPlayer.Models; + +namespace MusicPlayer.Views +{ + class AlbumView : BaseContentView + { + private AlbumViewModel viewModel; + private TextLabel albumCountLabel; + + public AlbumView(AlbumViewModel viewModel) + { + this.viewModel = viewModel; + BindingContext = viewModel; + collectionView.ItemsSource = viewModel.ListViewModel; + collectionView.ItemTemplate = new DataTemplate(() => + { + ListItemLayout layout = new ListItemLayout(); + layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "AlbumArtPath"); + layout.TitleLabel.SetBinding(TextLabel.TextProperty, "AlbumName"); + layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); + return layout; + }); + collectionView.ScrollingDirection = ScrollableBase.Direction.Vertical; + collectionView.WidthSpecification = LayoutParamPolicies.WrapContent; + collectionView.SelectionMode = ItemSelectionMode.Single; + collectionView.SelectionChanged += OnAlbumSelection; + + albumCountLabel = new TextLabel() + { + PixelSize = 28, + Text = "ALBUM COUNT", + TextColor = UIColors.HEX001447, + VerticalAlignment = VerticalAlignment.Center, + FontFamily = "BreezeSans", + IsCreateByXaml = true, + }; + titleView.Add(albumCountLabel); + albumCountLabel.SetBinding(TextLabel.TextProperty, "AlbumCount"); + RelativeLayout.SetLeftTarget(albumCountLabel, titleView); + RelativeLayout.SetLeftRelativeOffset(albumCountLabel, 1.0f); + RelativeLayout.SetRightRelativeOffset(albumCountLabel, 0.0f); + RelativeLayout.SetFillHorizontal(albumCountLabel, true); + } + private void OnAlbumSelection(object sender, SelectionChangedEventArgs e) + { + MusicAlbum currentAlbum= (MusicAlbum)collectionView.SelectedItem; + // viewModel.getDetailViewModel(currentAlbum) => need to replace direct function call on viewModel class with command interface + AlbumDetailView view = new AlbumDetailView(viewModel.getDetailViewModel(currentAlbum)); + Window.Instance.Add(view); + } + protected override void Dispose(DisposeTypes type) + { + if (Disposed) + { + return; + } + if (type == DisposeTypes.Explicit) + { + titleView.Remove(albumCountLabel); + albumCountLabel.Dispose(); + albumCountLabel = null; + } + base.Dispose(type); + } + } +} diff --git a/music-player/Views/ArtistDetailGroupLayout.cs b/music-player/Views/ArtistDetailGroupLayout.cs new file mode 100755 index 0000000..4d1e63c --- /dev/null +++ b/music-player/Views/ArtistDetailGroupLayout.cs @@ -0,0 +1,118 @@ +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using MusicPlayer.Common; + +namespace MusicPlayer.Views +{ + class ArtistDetailGroupLayout : RecyclerViewItem + { + private static int Width = 1792; + private static int Height = 108; + + private const int IconSize = 64; + private const int LayoutPadding = 32; + private const int SeperatorHeight = 1; + private const int LeftPadding = 64; + private const int x = 0; + + private View itemSeperator; + private TextLabel titleLabel; + private ImageView icon; + + public ArtistDetailGroupLayout(int width = 1792, int height = 108) : base() + { + base.OnInitialize(); + base.IsCreateByXaml = true; + Width = width; + Height = height; + WidthSpecification = Width; + HeightSpecification = Height; + + // to show the rounded rect of the bg + BackgroundColor = Color.Transparent; + + icon = CreateIcon(); + titleLabel = CreateTitleLabel(); + itemSeperator = CreateItemSeparator(); + IsCreateByXaml = true; + } + + private ImageView CreateIcon() + { + ImageView icon = new ImageView() + { + WidthSpecification = IconSize, + HeightSpecification = IconSize, + IsCreateByXaml = true, + Position2D = new Position2D(x, (Height / 2) - (IconSize / 2)), + }; + base.Add(icon); + return icon; + } + + private View CreateItemSeparator() + { + View itemSeperator = new View() + { + WidthSpecification = (Width - (2 * LeftPadding)), + HeightSpecification = SeperatorHeight, + ExcludeLayouting = true, + Position2D = new Position2D(x, Height - SeperatorHeight), + BackgroundColor = UIColors.ItemSeperator, + }; + base.Add(itemSeperator); + return itemSeperator; + } + + private TextLabel CreateTitleLabel() + { + TextLabel titleLabel = new TextLabel() + { + WidthSpecification = (Width - (2 * LeftPadding) - IconSize - LayoutPadding), + HeightSpecification = 40, + TextColor = UIColors.HEX001447, + PixelSize = 32, + FontFamily = "BreezeSans", + VerticalAlignment = VerticalAlignment.Center, + IsCreateByXaml = true, + Position2D = new Position2D(x + IconSize + LayoutPadding, 34), + }; + base.Add(titleLabel); + return titleLabel; + } + + public ImageView Icon + { + get => icon; + } + + public TextLabel TitleLabel + { + get => titleLabel; + } + + protected override void Dispose(DisposeTypes type) + { + if (Disposed) + { + return; + } + if (type == DisposeTypes.Explicit) + { + base.Remove(itemSeperator); + itemSeperator?.Dispose(); + itemSeperator = null; + + base.Remove(icon); + icon?.Dispose(); + icon = null; + + base.Remove(titleLabel); + titleLabel?.Dispose(); + titleLabel = null; + } + base.Dispose(type); + } + } +} diff --git a/music-player/Views/ArtistDetailItemLayout.cs b/music-player/Views/ArtistDetailItemLayout.cs new file mode 100755 index 0000000..95907ba --- /dev/null +++ b/music-player/Views/ArtistDetailItemLayout.cs @@ -0,0 +1,122 @@ +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using MusicPlayer.Common; + +namespace MusicPlayer.Views +{ + class ArtistDetailItemLayout : RecyclerViewItem + { + private static int Width = 1792; + private static int Height = 108; + + private const int LayoutPadding = 32; + private const int SeperatorHeight = 1; + private const int LeftPadding = 64; + private const int x = 0; + + private View itemSeperator; + private TextLabel titleLabel; + private TextLabel extraLabel; + + public ArtistDetailItemLayout(int width = 1792, int height = 108) : base() + { + base.OnInitialize(); + base.IsCreateByXaml = true; + Width = width; + Height = height; + WidthSpecification = Width; + HeightSpecification = Height; + + // to show the rounded rect of the bg + BackgroundColor = Color.Transparent; + + titleLabel = CreateTitleLabel(); + extraLabel = CreateExtraLabel(); + itemSeperator = CreateItemSeparator(); + IsCreateByXaml = true; + } + + private View CreateItemSeparator() + { + View itemSeperator = new View() + { + WidthSpecification = (Width - (2 * LeftPadding)), + HeightSpecification = SeperatorHeight, + ExcludeLayouting = true, + Position2D = new Position2D(x, Height - SeperatorHeight), + BackgroundColor = UIColors.ItemSeperator, + }; + base.Add(itemSeperator); + return itemSeperator; + } + + private TextLabel CreateTitleLabel() + { + TextLabel titleLabel = new TextLabel() + { + WidthSpecification = 1272, + HeightSpecification = 40, + TextColor = UIColors.HEX001447, + PixelSize = 32, + FontFamily = "BreezeSans", + VerticalAlignment = VerticalAlignment.Center, + IsCreateByXaml = true, + Position2D = new Position2D(x, 34), + }; + base.Add(titleLabel); + return titleLabel; + } + + private TextLabel CreateExtraLabel() + { + TextLabel extraLabel = new TextLabel() + { + WidthSpecification = 360, + HeightSpecification = 36, + TextColor = UIColors.HEX001447, + PixelSize = 28, + FontFamily = "BreezeSans", + VerticalAlignment = VerticalAlignment.Center, + HorizontalAlignment = HorizontalAlignment.End, + IsCreateByXaml = true, + Position2D = new Position2D((x + 1272 + LayoutPadding), 36) + }; + base.Add(extraLabel); + return extraLabel; + } + + public TextLabel TitleLabel + { + get => titleLabel; + } + + public TextLabel ExtraLabel + { + get => extraLabel; + } + + protected override void Dispose(DisposeTypes type) + { + if (Disposed) + { + return; + } + if (type == DisposeTypes.Explicit) + { + base.Remove(itemSeperator); + itemSeperator?.Dispose(); + itemSeperator = null; + + base.Remove(titleLabel); + titleLabel?.Dispose(); + titleLabel = null; + + base.Remove(extraLabel); + extraLabel?.Dispose(); + extraLabel = null; + } + base.Dispose(type); + } + } +} diff --git a/music-player/Views/ArtistDetailView.cs b/music-player/Views/ArtistDetailView.cs new file mode 100755 index 0000000..91a143a --- /dev/null +++ b/music-player/Views/ArtistDetailView.cs @@ -0,0 +1,160 @@ +using MusicPlayer.ViewModels; +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using Tizen.NUI.Binding; +using MusicPlayer.Common; +using MusicPlayer.Models; + +namespace MusicPlayer.Views +{ + class ArtistDetailView : View //BaseContentView + { + private const int LayoutPadding = 64; + private const int IconSize = 48; + + private BaseView baseView; + private View contentView; + private View topView; + private TextLabel totalCountLabel; + private Button playAllIcon; // TODO need to implement playall feature + private Button shuffleAndPlayAllIcon; // TODO need to implement playlist manager + private CollectionView collectionView; + + private ArtistDetailViewModel viewModel; + + public ArtistDetailView(ArtistDetailViewModel viewModel) : base() + { + this.viewModel = viewModel; + BindingContext = viewModel; + BackgroundColor = UIColors.HEXEEEFF1; + WidthResizePolicy = ResizePolicyType.FillToParent; + HeightResizePolicy = ResizePolicyType.FillToParent; + + //TODO need to change this part after implementation of Command Interface + baseView = new BaseView() + { + Title = viewModel.ArtistName, + BackButton = true, + MoreButton = true, + SearchButton = true, + BackgroundColor = UIColors.HEXEEEFF1, + }; + base.Add(baseView); + contentView = new View() + { + WidthSpecification = LayoutParamPolicies.MatchParent, + HeightSpecification = 876, + Layout = new FlexLayout() + { + Direction = FlexLayout.FlexDirection.Column, + Padding = new Extents(LayoutPadding, LayoutPadding, 0, 0), + }, + }; + baseView.SetContent = contentView; + + topView = CreateTopView(); + AddTitle(); + AddButtons(); + collectionView = AddCollectionView(); + } + + private void OnTrackSelection(object sender, SelectionChangedEventArgs e) + { + + } + + private Button CreateButton(string url, int x, int y) + { + ButtonStyle buttonStyle = new ButtonStyle() + { + Icon = new ImageViewStyle() + { + ResourceUrl = url, + }, + IsSelectable = false, + IsEnabled = true, + }; + + Button button = new Button(buttonStyle) + { + Size2D = new Size2D(IconSize, IconSize), + Position2D = new Position2D(x, y), + }; + return button; + } + + private View CreateTopView() + { + View topView = new View() + { + BackgroundColor = UIColors.HEXEEEFF1, + Size2D = new Size2D(Window.Instance.WindowSize.Width - 2 * LayoutPadding, 60), + }; + contentView.Add(topView); + return topView; + } + + private void AddTitle() + { + totalCountLabel = new TextLabel() + { + Size2D = new Size2D(1624, 36), + Position2D = new Position2D(0, 12), + PixelSize = 28, + Text = "TOTAL COUNT", + TextColor = UIColors.HEX001447, + VerticalAlignment = VerticalAlignment.Center, + FontFamily = "BreezeSans", + IsCreateByXaml = true, + }; + topView.Add(totalCountLabel); + totalCountLabel.SetBinding(TextLabel.TextProperty, "TotalCount"); + } + + private void AddButtons() + { + playAllIcon = CreateButton(Resources.GetImagePath() + "playlist_active.png", Window.Instance.WindowSize.Width - 2 * LayoutPadding - IconSize, 6); + playAllIcon.Margin = new Extents(40, 0, 0, 0); + topView.Add(playAllIcon); + + shuffleAndPlayAllIcon = CreateButton(Resources.GetImagePath() + "shuffle_on.png", Window.Instance.WindowSize.Width - 2 * LayoutPadding - 2 * IconSize - 40, 6); + playAllIcon.Margin = new Extents(32, 0, 0, 0); + topView.Add(shuffleAndPlayAllIcon); + } + + private CollectionView AddCollectionView() + { + CollectionView collectionView = new CollectionView() + { + Size2D = new Size2D(1792, 108), + BackgroundImage = Resources.GetImagePath() + "list_view_bg.png", + ItemsLayouter = new LinearLayouter(), + ItemTemplate = new DataTemplate(() => + { + ArtistDetailItemLayout layout = new ArtistDetailItemLayout(); + layout.TitleLabel.SetBinding(TextLabel.TextProperty, "TrackTitle"); + layout.ExtraLabel.SetBinding(TextLabel.TextProperty, "Duration"); + return layout; + }), + GroupHeaderTemplate = new DataTemplate(() => + { + ArtistDetailGroupLayout group = new ArtistDetailGroupLayout(); + group.Icon.SetBinding(ImageView.ResourceUrlProperty, "AlbumArtPath"); + group.TitleLabel.SetBinding(TextLabel.TextProperty, "AlbumName"); + return group; + }), + IsGrouped = true, + ScrollingDirection = ScrollableBase.Direction.Vertical, + HeightSpecification = LayoutParamPolicies.WrapContent, + SelectionMode = ItemSelectionMode.Single, + }; + contentView.Add(collectionView); + FlexLayout.SetFlexGrow(collectionView, 1); + FlexLayout.SetFlexShrink(collectionView, 1); + collectionView.ItemsSource = viewModel.GroupListViewModel; + collectionView.SelectionChanged += OnTrackSelection; + return collectionView; + } + } +} diff --git a/music-player/Views/ArtistView.cs b/music-player/Views/ArtistView.cs new file mode 100755 index 0000000..f74e075 --- /dev/null +++ b/music-player/Views/ArtistView.cs @@ -0,0 +1,71 @@ +using MusicPlayer.ViewModels; +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using Tizen.NUI.Binding; +using MusicPlayer.Common; +using MusicPlayer.Models; + +namespace MusicPlayer.Views +{ + class ArtistView : BaseContentView + { + private ArtistViewModel viewModel; + private TextLabel artistCountLabel; + + public ArtistView(ArtistViewModel viewModel) + { + this.viewModel = viewModel; + BindingContext = viewModel; + collectionView.ItemsSource = viewModel.ListViewModel; + collectionView.ItemTemplate = new DataTemplate(() => + { + ListItemLayout layout = new ListItemLayout(); + layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "AlbumArtPath"); + layout.TitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); + layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "TotalCount"); + return layout; + }); + collectionView.ScrollingDirection = ScrollableBase.Direction.Vertical; + collectionView.WidthSpecification = LayoutParamPolicies.WrapContent; + collectionView.SelectionMode = ItemSelectionMode.Single; + collectionView.SelectionChanged += OnArtistSelection; + + artistCountLabel = new TextLabel() + { + PixelSize = 28, + Text = "ARTIST COUNT", + TextColor = UIColors.HEX001447, + VerticalAlignment = VerticalAlignment.Center, + FontFamily = "BreezeSans", + IsCreateByXaml = true, + }; + titleView.Add(artistCountLabel); + artistCountLabel.SetBinding(TextLabel.TextProperty, "ArtistCount"); + RelativeLayout.SetLeftTarget(artistCountLabel, titleView); + RelativeLayout.SetLeftRelativeOffset(artistCountLabel, 1.0f); + RelativeLayout.SetRightRelativeOffset(artistCountLabel, 0.0f); + RelativeLayout.SetFillHorizontal(artistCountLabel, true); + } + private void OnArtistSelection(object sender, SelectionChangedEventArgs e) + { + Artist currentArtist = (Artist)collectionView.SelectedItem; + ArtistDetailView view = new ArtistDetailView(viewModel.getDetailViewModel(currentArtist)); + Window.Instance.Add(view); + } + protected override void Dispose(DisposeTypes type) + { + if (Disposed) + { + return; + } + if (type == DisposeTypes.Explicit) + { + titleView.Remove(artistCountLabel); + artistCountLabel.Dispose(); + artistCountLabel = null; + } + base.Dispose(type); + } + } +} \ No newline at end of file diff --git a/music-player/Views/BaseContentView.cs b/music-player/Views/BaseContentView.cs new file mode 100755 index 0000000..5aa5c44 --- /dev/null +++ b/music-player/Views/BaseContentView.cs @@ -0,0 +1,89 @@ +using MusicPlayer.Common; +using Tizen.NUI; +using Tizen.NUI.BaseComponents; +using Tizen.NUI.Components; + +namespace MusicPlayer.Views +{ + class BaseContentView : View + { + protected View titleView; + protected CollectionView collectionView; + public BaseContentView() : base() + { + ThemeChangeSensitive = true; + WidthResizePolicy = ResizePolicyType.FillToParent; + HeightResizePolicy = ResizePolicyType.FillToParent; + Layout = new FlexLayout() + { + Direction = FlexLayout.FlexDirection.Column, + Padding = new Extents(64, 64, 0, 0), + }; + titleView = new View() + { + ThemeChangeSensitive = true, + WidthSpecification = LayoutParamPolicies.MatchParent, + HeightSpecification = 60, + Layout = new RelativeLayout() + { + Padding = new Extents(0, 0, 13, 13), + }, + }; + base.Add(titleView); + FlexLayout.SetFlexGrow(titleView, 0); + FlexLayout.SetFlexShrink(titleView, 0); + + collectionView = new CollectionView() + { + ThemeChangeSensitive = true, + Size2D = new Size2D(1792, 108), + Margin = new Extents(0, 0, 0, 2), + BackgroundImage = GetBackgroundImagePath(ThemeManager.PlatformThemeId), + ItemsLayouter = new LinearLayouter(), + ScrollingDirection = ScrollableBase.Direction.Vertical, + WidthSpecification = LayoutParamPolicies.MatchParent, + HeightSpecification = LayoutParamPolicies.WrapContent, + SelectionMode = ItemSelectionMode.Single, + }; + base.Add(collectionView); + FlexLayout.SetFlexGrow(collectionView, 1); + FlexLayout.SetFlexShrink(collectionView, 1); + } + + private string GetBackgroundImagePath(string platformThemeId) + { + if(platformThemeId.Equals(AppConstants.DarkPlatformThemeId)) + { + return Resources.GetImagePath() + "dark/list_view_bg.png"; + } + else + { + return Resources.GetImagePath() + "light/list_view_bg.png"; + } + } + + protected override void OnThemeChanged(object sender, ThemeChangedEventArgs e) + { + base.OnThemeChanged(sender, e); + if(e.IsPlatformThemeChanged) + { + collectionView.BackgroundImage = GetBackgroundImagePath(e.PlatformThemeId); + } + } + + protected override void Dispose(DisposeTypes type) + { + if (type == DisposeTypes.Explicit) + { + base.Remove(titleView); + titleView.Dispose(); + titleView = null; + + base.Remove(collectionView); + collectionView.Dispose(); + collectionView = null; + } + base.Dispose(type); + } + } +} diff --git a/music-player/Views/BaseView.cs b/music-player/Views/BaseView.cs new file mode 100755 index 0000000..1cddb26 --- /dev/null +++ b/music-player/Views/BaseView.cs @@ -0,0 +1,268 @@ +using System.Collections.Generic; +using Tizen.NUI; +using Tizen.NUI.BaseComponents; +using Tizen.NUI.Components; +using Tizen.NUI.Binding; +using MusicPlayer.Common; + +namespace MusicPlayer.Views +{ + class BaseView : View + { + private View topView; + private View bottomView; // TODO Used this for MiniController UI + private View contentView; + private TextLabel titleLabel; + private Button backButton; + private Button moreButton; + private Button searchButton; + private Tab tabs; + + // TODO these name strings are temporary...once the po files are added + // need to use Translatable names. + private static string[] TabNames = new string[] + { + "Playlists", + "Tracks", + "Albums", + "Artists", + }; + public BaseView() : base() + { + ThemeChangeSensitive = true; + WidthSpecification = LayoutParamPolicies.MatchParent; + HeightSpecification = LayoutParamPolicies.MatchParent; + Layout = new FlexLayout() + { + Direction = FlexLayout.FlexDirection.Column, + ItemsAlignment = FlexLayout.AlignmentType.FlexStart, + Justification = FlexLayout.FlexJustification.FlexStart, + }; + topView = new View() + { + ThemeChangeSensitive = true, + WidthSpecification = LayoutParamPolicies.MatchParent, + HeightSpecification = 120, + Layout = new RelativeLayout() + { + Padding = new Extents(64, 64, 30, 30), + }, + }; + base.Add(topView); + FlexLayout.SetFlexGrow(topView, 0); + FlexLayout.SetFlexShrink(topView, 0); + titleLabel = new TextLabel() + { + ThemeChangeSensitive = true, + Text = "Music", + PixelSize = 40, + FontFamily = "BreezeSans", + TextColor = UIColors.HEX000209, + HorizontalAlignment = HorizontalAlignment.Begin, + Margin = new Extents(0, 0, 6, 6), + Ellipsis = true, + }; + topView.Add(titleLabel); + titleLabel.SetBinding(TextLabel.TextProperty, "Title"); + RelativeLayout.SetLeftTarget(titleLabel, topView); + RelativeLayout.SetLeftRelativeOffset(titleLabel, 0.0f); + RelativeLayout.SetRightTarget(titleLabel, topView); + RelativeLayout.SetRightRelativeOffset(titleLabel, 1.0f); + RelativeLayout.SetFillHorizontal(titleLabel, true); + + contentView = new View() + { + ThemeChangeSensitive = true, + WidthSpecification = LayoutParamPolicies.MatchParent, + HeightSpecification = 876, + }; + base.Add(contentView); + FlexLayout.SetFlexGrow(contentView, 1); + FlexLayout.SetFlexShrink(contentView, 1); + + tabs = new Tab() + { + ThemeChangeSensitive = true, + Size2D = new Size2D(Window.Instance.Size.Width, 84), + WidthSpecification = LayoutParamPolicies.MatchParent, + HeightSpecification = 84, + UnderLineBackgroundColor = Color.Blue, + UnderLineSize = new Size2D(1, 3), + PointSize = 25, + BackgroundColor = Color.White, + }; + tabs.TextColorSelector = new ColorSelector + { + Normal = Color.Black, + Selected = Color.Magenta, + }; + base.Add(tabs); + for(int i = 0; i<4; ++i) + { + Tab.TabItemData item = new Tab.TabItemData(); + item.Text = TabNames[i]; + tabs.AddItem(item); + } + tabs.SelectedItemIndex = 1; + + backButton = null; + moreButton = null; + searchButton = null; + } + + public Tab Tabs + { + get => tabs; + } + + public string Title + { + get => titleLabel.Text; + set { titleLabel.Text = value;} + } + + public bool BackButton + { + set + { + if (value) + { + ButtonStyle buttonStyle = new ButtonStyle() + { + Icon = new ImageViewStyle() + { + ResourceUrl = Resources.GetImagePath() + "back_button.png", + }, + IsSelectable = false, + IsEnabled = true, + }; + + backButton = new Button(buttonStyle) + { + ThemeChangeSensitive = true, + Size2D = new Size2D(48, 48), + Margin = new Extents(0, 24, 6, 6), + }; + topView.Add(backButton); + + RelativeLayout.SetLeftRelativeOffset(backButton, 0.0f); + RelativeLayout.SetRightRelativeOffset(backButton, 0.0f); + RelativeLayout.SetHorizontalAlignment(backButton, RelativeLayout.Alignment.Start); + + RelativeLayout.SetLeftTarget(titleLabel, backButton); + RelativeLayout.SetLeftRelativeOffset(titleLabel, 1.0f); + } + } + } + + public bool MoreButton + { + set + { + if (value) + { + ButtonStyle buttonStyle = new ButtonStyle() + { + Icon = new ImageViewStyle() + { + ResourceUrl = Resources.GetImagePath() + "more.png", + }, + IsSelectable = false, + IsEnabled = true, + }; + moreButton = new Button(buttonStyle) + { + ThemeChangeSensitive = true, + Size2D = new Size2D(48, 48), + Margin = new Extents(32, 0, 6, 6), + }; + topView.Add(moreButton); + RelativeLayout.SetLeftRelativeOffset(moreButton, 1.0f); + RelativeLayout.SetRightRelativeOffset(moreButton, 1.0f); + RelativeLayout.SetHorizontalAlignment(moreButton, RelativeLayout.Alignment.End); + + RelativeLayout.SetRightTarget(titleLabel, moreButton); + RelativeLayout.SetRightRelativeOffset(titleLabel, 0.0f); + } + } + } + + public bool SearchButton + { + set + { + if (value) + { + ButtonStyle buttonStyle = new ButtonStyle() + { + Icon = new ImageViewStyle() + { + ResourceUrl = Resources.GetImagePath() + "search_icon.png", + }, + IsSelectable = false, + IsEnabled = true, + }; + searchButton = new Button(buttonStyle) + { + ThemeChangeSensitive = true, + Size2D = new Size2D(96, 60), + BackgroundImage = Resources.GetImagePath() + "search_button_bg.png", + Margin = new Extents(24, 0, 0, 0), + }; + topView.Add(searchButton); + RelativeLayout.SetRightTarget(searchButton, moreButton); + RelativeLayout.SetRightRelativeOffset(searchButton, 0.0f); + RelativeLayout.SetHorizontalAlignment(searchButton, RelativeLayout.Alignment.End); + + RelativeLayout.SetLeftTarget(titleLabel, RelativeLayout.GetLeftTarget(titleLabel)); + RelativeLayout.SetLeftRelativeOffset(titleLabel, RelativeLayout.GetLeftRelativeOffset(titleLabel)); + RelativeLayout.SetRightTarget(titleLabel, searchButton); + RelativeLayout.SetRightRelativeOffset(titleLabel, 0.0f); + } + } + } + + public View SetContent + { + set + { + contentView.Add(value); + } + } + + protected override void Dispose(DisposeTypes type) + { + if (Disposed) + { + return; + } + if (type == DisposeTypes.Explicit) + { + List children = topView?.Children; + foreach (View child in children) + { + topView.Remove(child); + child?.Dispose(); + } + base.Remove(topView); + topView?.Dispose(); + topView = null; + + // Do not delete the children of contentview as they are not owned by BaseView + base.Remove(contentView); + contentView?.Dispose(); + contentView = null; + + base.Remove(tabs); + tabs?.Dispose(); + tabs = null; + + base.Remove(bottomView); + bottomView?.Dispose(); + bottomView = null; + } + + base.Dispose(type); + } + } +} \ No newline at end of file diff --git a/music-player/Views/ListItemLayout.cs b/music-player/Views/ListItemLayout.cs new file mode 100755 index 0000000..071523f --- /dev/null +++ b/music-player/Views/ListItemLayout.cs @@ -0,0 +1,135 @@ +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using MusicPlayer.Common; + +namespace MusicPlayer.Views +{ + class ListItemLayout : RecyclerViewItem + { + private static int Width = 1792; + private static int Height = 108; + + private const int IconSize = 64; + private const int LayoutMargin = 16; + private const int LayoutPadding = 32; + private const int SeperatorHeight = 1; + private const int LeftPadding = 64; + private const int x = 0; + + private View itemSeperator; + private TextLabel titleLabel; + private TextLabel subtitleLabel; + private ImageView icon; + + public ListItemLayout(int width = 1792, int height = 108) : base() + { + base.OnInitialize(); + base.IsCreateByXaml = true; + Width = width; + Height = height; + WidthSpecification = Width; + HeightSpecification = Height; + + // to show the rounded rect of the bg + BackgroundColor = Color.Transparent; + + icon = new ImageView() + { + WidthSpecification = IconSize, + HeightSpecification = IconSize, + IsCreateByXaml = true, + Position2D = new Position2D(x, ((Height / 2) - (IconSize / 2))), + }; + base.Add(icon); + + itemSeperator = new View() + { + WidthSpecification = (Width - (2 * LeftPadding)), + HeightSpecification = SeperatorHeight, + ExcludeLayouting = true, + Position2D = new Position2D(x, Height - SeperatorHeight), + BackgroundColor = UIColors.ItemSeperator, + }; + base.Add(itemSeperator); + + titleLabel = new TextLabel("ItemLabel") + { + ThemeChangeSensitive = true, + WidthSpecification = (Width - (2 * LeftPadding) - IconSize - LayoutPadding), + HeightSpecification = 40, + PixelSize = 32, + FontFamily = "BreezeSans", + VerticalAlignment = VerticalAlignment.Center, + IsCreateByXaml = true, + Position2D = new Position2D((x + IconSize + LayoutPadding), LayoutMargin), + }; + // ToDo need to make this a readonly const + PropertyMap titleFontStyle = new PropertyMap(); + titleFontStyle.Add("width", new PropertyValue("normal")); + titleFontStyle.Add("weight", new PropertyValue("light")); + titleLabel.FontStyle = titleFontStyle; + base.Add(titleLabel); + + subtitleLabel = new TextLabel("ItemLabel") + { + ThemeChangeSensitive = true, + WidthSpecification = (Width - (2 * LeftPadding) - IconSize - LayoutPadding), + HeightSpecification = 36, + PixelSize = 28, + FontFamily = "BreezeSans", + VerticalAlignment = VerticalAlignment.Center, + IsCreateByXaml = true, + Position2D = new Position2D((x + IconSize + LayoutPadding), LayoutMargin + 40) + }; + // ToDo need to make this a readonly const + PropertyMap subtitleFontStyle = new PropertyMap(); + subtitleFontStyle.Add("width", new PropertyValue("normal")); + subtitleFontStyle.Add("weight", new PropertyValue("normal")); + subtitleFontStyle.Add("slant", new PropertyValue("normal")); + subtitleLabel.FontStyle = subtitleFontStyle; + base.Add(subtitleLabel); + IsCreateByXaml = true; + } + public ImageView Icon + { + get => icon; + } + public TextLabel TitleLabel + { + get => titleLabel; + } + public TextLabel SubtitleLabel + { + get => subtitleLabel; + } + + protected override void Dispose(DisposeTypes type) + { + if(Disposed) + { + return; + } + if (type == DisposeTypes.Explicit) + { + base.Remove(itemSeperator); + itemSeperator?.Dispose(); + itemSeperator = null; + + base.Remove(icon); + icon?.Dispose(); + icon = null; + + base.Remove(titleLabel); + titleLabel?.Dispose(); + titleLabel = null; + + base.Remove(subtitleLabel); + subtitleLabel?.Dispose(); + subtitleLabel = null; + } + + base.Dispose(type); + } + } +} diff --git a/music-player/Views/LyricsView.cs b/music-player/Views/LyricsView.cs new file mode 100644 index 0000000..f36473a --- /dev/null +++ b/music-player/Views/LyricsView.cs @@ -0,0 +1,70 @@ +using Tizen.NUI; +using Tizen.NUI.Binding; +using Tizen.NUI.BaseComponents; +using Tizen.NUI.Components; +using MusicPlayer.ViewModels; +using MusicPlayer.Common; + +namespace MusicPlayer.Views +{ + class LyricsView : View + { + private const int ViewSize = 784; + private const int LyricsViewMargin = 40; + private const int LyricsViewSize = 704; + + private readonly LyricsViewModel lyricsViewModel; + + private ImageView thumbView; + private ScrollableBase scrollView; + private TextLabel lyricsLabel; + + public LyricsView(LyricsViewModel lyricsViewModel) : base() + { + this.lyricsViewModel = lyricsViewModel; + BindingContext = lyricsViewModel.lyricsModel; + Size2D = new Size2D(ViewSize, ViewSize); + + AddThumbnail(); + AddLyricsView(); + } + + private void AddThumbnail() + { + thumbView = new ImageView() + { + HeightResizePolicy = ResizePolicyType.FillToParent, + WidthResizePolicy = ResizePolicyType.FillToParent, + }; + thumbView.SetBinding(ImageView.ResourceUrlProperty, "ThumbPath"); + base.Add(thumbView); + } + + private void AddLyricsView() + { + scrollView = new ScrollableBase() + { + Position2D = new Position2D(LyricsViewMargin, LyricsViewMargin), + Size2D = new Size2D(LyricsViewSize, LyricsViewSize), + ScrollingDirection = ScrollableBase.Direction.Vertical, + BackgroundColor = Color.Transparent, + }; + scrollView.BindingContext = lyricsViewModel; + scrollView.SetBinding(View.BackgroundColorProperty, "LyricsBackgroundColor"); + base.Add(scrollView); + + lyricsLabel = new TextLabel() + { + WidthResizePolicy = ResizePolicyType.FillToParent, + TextColor = Color.White, + MultiLine = true, + LineWrapMode = LineWrapMode.Word, + PointSize = 25.0f, + HorizontalAlignment = HorizontalAlignment.Center, + }; + lyricsLabel.BindingContext = lyricsViewModel.lyricsModel; + lyricsLabel.SetBinding(TextLabel.TextProperty, "Lyrics"); + scrollView.Add(lyricsLabel); + } + } +} diff --git a/music-player/Views/PlayerView.cs b/music-player/Views/PlayerView.cs new file mode 100755 index 0000000..b0a5883 --- /dev/null +++ b/music-player/Views/PlayerView.cs @@ -0,0 +1,781 @@ +using Tizen.NUI; +using Tizen.Multimedia; +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI.Binding; +using MusicPlayer.Common; +using MusicPlayer.ViewModels; +using MusicPlayer.Views.Utils; +using System.Collections.Generic; + +namespace MusicPlayer.Views +{ + class PlayerView : View + { + private enum PlayerViewState + { + AlbumArt, + TrackList, + } + private const int LayoutPadding = 64; + private const int IconSize = 48; + private const int TopBarSize = 120; + private const int ControlViewWidth = 640; + private const int ControlViewHeight = 384; + private const int ControlViewMargin = 315; + private const int TitleLabelHeight = 48; + private const int ArtistLabelHeight = 36; + private const int TopBarButtonsY = (TopBarSize / 2 - IconSize / 2); + + private View playerBackgroundView; + private View leftView; + private View rightView; + private View rightViewBackground; + private Button backButton; + private Button moreButton; + + private View controlsView; + private View sliderView; + private MultiStateButton playButton; + private Button prevButton; + private Button nextButton; + private MultiStateButton shuffleButton; + private MultiStateButton repeatButton; + private Slider volumeSlider; + private Slider playbackSlider; + private TextLabel titleLabel; + private TextLabel artistLabel; + private TextLabel currentTime; + private TextLabel totalTime; + + private ImageView leftVolumeIcon; + private ImageView rightVolumeIcon; + private ImageView thumb; + private Button listButton; + private Button playlistButton; + private MultiStateButton favouriteButton; + private PlayingListView currentListView; + private LyricsView lyricsView; + + private PlayerViewModel viewModel; + + private PlayerViewState viewState; + + public PlayerView(PlayerViewModel viewModel) : base() + { + this.viewModel = viewModel; + BindingContext = viewModel.playerModel; + StyleName = "AppBackground"; + WidthResizePolicy = ResizePolicyType.FillToParent; + HeightResizePolicy = ResizePolicyType.FillToParent; + + AddPlayerBackground(); + + viewState = PlayerViewState.AlbumArt; + + leftView = CreateLeftView(); + rightView = CreateRightView(); + AddRightViewBackground(); + + AddTopButtons(); + AddControlView(); + AddControlElements(); + AddPlaybackSlider(); + AddListActionButtons(); + AddThumbnail(); + AddLyricsView(); + } + + private void AddPlayerBackground() + { + playerBackgroundView = new View(); + playerBackgroundView.Size2D = new Size2D(Window.Instance.WindowSize.Width, Window.Instance.WindowSize.Height); + WidthResizePolicy = ResizePolicyType.FillToParent; + HeightResizePolicy = ResizePolicyType.FillToParent; + base.Add(playerBackgroundView); + playerBackgroundView.BackgroundColor = Color.Transparent; + playerBackgroundView.BindingContext = viewModel; + playerBackgroundView.SetBinding(BackgroundProperty, "PlayerBackground"); + } + + private View CreateLeftView() + { + View leftView = new View() + { + BackgroundColor = Color.Transparent, + HeightResizePolicy = ResizePolicyType.FillToParent, + SizeWidth = Window.Instance.WindowSize.Width / 2, + Position2D = new Position2D(0, 0), + }; + base.Add(leftView); + return leftView; + } + + private View CreateRightView() + { + View rightView = new View() + { + BackgroundColor = Color.Transparent, + HeightResizePolicy = ResizePolicyType.FillToParent, + SizeWidth = Window.Instance.WindowSize.Width / 2, + Position2D = new Position2D(Window.Instance.WindowSize.Width / 2, 0), + }; + base.Add(rightView); + return rightView; + } + + private void AddRightViewBackground() + { + rightViewBackground = new View(); + rightViewBackground.BackgroundColor = Color.Transparent; + rightViewBackground.SizeWidth = Window.Instance.WindowSize.Width / 2; + rightViewBackground.SizeHeight = Window.Instance.WindowSize.Height; + rightViewBackground.WidthResizePolicy = ResizePolicyType.FillToParent; + rightViewBackground.HeightResizePolicy = ResizePolicyType.FillToParent; + rightView.Add(rightViewBackground); + rightViewBackground.BindingContext = viewModel; + rightViewBackground.SetBinding(BackgroundProperty, "PlayerBackground"); + rightViewBackground.Hide(); + } + + private void UpdatePlayerViewBackground(PlayerViewState state) + { + if (state == PlayerViewState.AlbumArt) + { + rightViewBackground.Hide(); + playerBackgroundView.Show(); + } + else + { + playerBackgroundView.Hide(); + rightViewBackground.Show(); + } + } + + private void AddTopButtons() + { + backButton = new Button("BackButton"); + backButton.ThemeChangeSensitive = true; + backButton.Position2D = new Position2D(LayoutPadding, TopBarButtonsY); + leftView.Add(backButton); + + moreButton = new Button("MoreButton"); + moreButton.ThemeChangeSensitive = true; + moreButton.Position2D = new Position2D(Window.Instance.WindowSize.Width / 2 - LayoutPadding - IconSize, TopBarButtonsY); + rightView.Add(moreButton); + } + + private void AddControlView() + { + controlsView = new View() + { + BackgroundColor = Color.Transparent, + Size2D = new Size2D(ControlViewWidth, ControlViewHeight), + Position2D = new Position2D((Window.Instance.WindowSize.Width / 4 - ControlViewWidth / 2), TopBarSize + ControlViewMargin), + }; + rightView.Add(controlsView); + } + + private void AddTitleLabel() + { + titleLabel = new TextLabel("LabelText") + { + ThemeChangeSensitive = true, + Size2D = new Size2D(ControlViewWidth, TitleLabelHeight), + Position2D = new Position2D(0, 0), + PixelSize = 36, + FontFamily = "BreezeSans", + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + Ellipsis = true, + }; + titleLabel.SetBinding(TextLabel.TextProperty, "TrackName"); + controlsView.Add(titleLabel); + } + + private void AddArtistLabel() + { + artistLabel = new TextLabel("LabelText") + { + ThemeChangeSensitive = true, + Size2D = new Size2D(ControlViewWidth, ArtistLabelHeight), + Position2D = new Position2D(0, 62), + PixelSize = 28, + FontFamily = "BreezeSans", + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + Ellipsis = true, + }; + artistLabel.SetBinding(TextLabel.TextProperty, "TrackArtist"); + controlsView.Add(artistLabel); + } + + private void AddTextControlElements() + { + AddTitleLabel(); + AddArtistLabel(); + } + + private void AddShuffleButton() + { + shuffleButton = new MultiStateButton() + { + Size2D = new Size2D(IconSize, IconSize), + Position2D = new Position2D(0, 196), + IconResources = new Dictionary>() + { + { + ThemeType.Light, + new Dictionary() + { + { + ShuffleMode.Off.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "light/shuffle_off.png", + } + }, + { + ShuffleMode.On.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "light/shuffle_on.png", + } + }, + } + }, + { + ThemeType.Dark, + new Dictionary() + { + { + ShuffleMode.Off.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "dark/shuffle_off.png", + } + }, + { + ShuffleMode.On.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "dark/shuffle_on.png", + } + }, + } + } + }, + }; + shuffleButton.BindingContext = viewModel.playingListViewModel; + shuffleButton.SetBinding(MultiStateButton.CustomStateProperty, "ShuffleButtonState"); + // TODO need to implement command instead + shuffleButton.Clicked += (object sender, ClickedEventArgs e) => + { + viewModel.ShuffleChanged(); + }; + controlsView.Add(shuffleButton); + } + + private void AddPreviousButton() + { + prevButton = new Button("PrevButton"); + prevButton.ThemeChangeSensitive = true; + // TODO need to implement command instead + prevButton.Clicked += (object sender, ClickedEventArgs e) => + { + viewModel.PrevButtonClicked(); + }; + prevButton.BindingContext = viewModel; + prevButton.SetBinding(Button.IsEnabledProperty, "HasPreviousTrack"); + controlsView.Add(prevButton); + } + + private void AddPlayButton() + { + playButton = new MultiStateButton() + { + Size2D = new Size2D(IconSize, IconSize), + Position2D = new Position2D(296, 196), + BackgroundColor = Color.Transparent, + IconResources = new Dictionary>() + { + { + ThemeType.Light, + new Dictionary() + { + { + "Play", + new StringSelector() + { + Normal = Resources.GetImagePath() + "light/play.png", + Pressed = Resources.GetImagePath() + "play_pressed.png", + Disabled = Resources.GetImagePath() + "play_disabled.png", + } + }, + { + "Pause", + new StringSelector() + { + Normal = Resources.GetImagePath() + "light/pause.png", + Pressed = Resources.GetImagePath() + "pause_pressed.png", + Disabled = Resources.GetImagePath() + "pause_disabled.png", + } + }, + } + }, + { + ThemeType.Dark, + new Dictionary() + { + { + "Play", + new StringSelector() + { + Normal = Resources.GetImagePath() + "dark/play.png", + Pressed = Resources.GetImagePath() + "play_pressed.png", + Disabled = Resources.GetImagePath() + "play_disabled.png", + } + }, + { + "Pause", + new StringSelector() + { + Normal = Resources.GetImagePath() + "dark/pause.png", + Pressed = Resources.GetImagePath() + "pause_pressed.png", + Disabled = Resources.GetImagePath() + "pause_disabled.png", + } + }, + } + } + }, + }; + playButton.BindingContext = viewModel; + playButton.SetBinding(MultiStateButton.CustomStateProperty, "PlayButtonState"); + controlsView.Add(playButton); + // TODO need to implement command instead + playButton.Clicked += (object sender, ClickedEventArgs e) => + { + viewModel.PlayingStatusChanged(); + }; + } + + private void AddNextButton() + { + nextButton = new Button("NextButton"); + nextButton.ThemeChangeSensitive = true; + // TODO need to implement command instead + nextButton.Clicked += (object sender, ClickedEventArgs e) => + { + viewModel.NextButtonClicked(); + }; + nextButton.BindingContext = viewModel; + nextButton.SetBinding(Button.IsEnabledProperty, "HasNextTrack"); + controlsView.Add(nextButton); + } + + private void AddRepeatButton() + { + repeatButton = new MultiStateButton() + { + Size2D = new Size2D(IconSize, IconSize), + Position2D = new Position2D(592, 196), + IconResources = new Dictionary>() + { + { + ThemeType.Light, + new Dictionary() + { + { + RepeatMode.Off.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "light/repeat_off.png", + } + }, + { + RepeatMode.RepeatOne.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "light/repeat_one.png", + } + }, + { + RepeatMode.RepeatAll.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "light/repeat_all.png", + } + }, + } + }, + { + ThemeType.Dark, + new Dictionary() + { + { + RepeatMode.Off.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "dark/repeat_off.png", + } + }, + { + RepeatMode.RepeatOne.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "dark/repeat_one.png", + } + }, + { + RepeatMode.RepeatAll.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "dark/repeat_all.png", + } + }, + } + } + }, + }; + repeatButton.BindingContext = viewModel.playingListViewModel; + repeatButton.SetBinding(MultiStateButton.CustomStateProperty, "RepeatButtonState"); + controlsView.Add(repeatButton); + // TODO need to implement command instead + repeatButton.Clicked += (object sender, ClickedEventArgs e) => + { + viewModel.RepeatChanged(); + }; + } + + private void AddButtonControlElements() + { + AddShuffleButton(); + AddPreviousButton(); + AddPlayButton(); + AddNextButton(); + AddRepeatButton(); + } + + private void AddLeftVolumeIcon() + { + leftVolumeIcon = new ImageView() + { + ThemeChangeSensitive = true, + StyleName = "LeftVolume", + }; + controlsView.Add(leftVolumeIcon); + } + + private void AddRightVolumeIcon() + { + rightVolumeIcon = new ImageView() + { + ThemeChangeSensitive = true, + StyleName = "RightVolume", + }; + controlsView.Add(rightVolumeIcon); + } + + private void AddVolumeSliderEventHandlers() + { + volumeSlider.SlidingStarted += (object sender, SliderSlidingStartedEventArgs e) => + { + viewModel.VolumeChangeStarted(); + }; + volumeSlider.ValueChanged += (object sender, SliderValueChangedEventArgs e) => + { + viewModel.VolumeLevelChanged((int)e.CurrentValue); + }; + volumeSlider.SlidingFinished += (object sender, SliderSlidingFinishedEventArgs e) => + { + viewModel.VolumeChangeFinished((int)e.CurrentValue); + }; + } + + private void AddVolumeSlider() + { + volumeSlider = new Slider("Slider"); + volumeSlider.ThemeChangeSensitive = true; + volumeSlider.Size2D = new Size2D(496, 48); + volumeSlider.Position2D = new Position2D(72, 336); + volumeSlider.ThumbSize = new Tizen.NUI.Size(36, 36); + volumeSlider.Direction = Slider.DirectionType.Horizontal; + volumeSlider.MinValue = 0; + volumeSlider.MaxValue = AudioManager.VolumeController.MaxLevel[AudioVolumeType.Media]; + volumeSlider.CurrentValue = AudioManager.VolumeController.Level[AudioVolumeType.Media]; + controlsView.Add(volumeSlider); + volumeSlider.BindingContext = viewModel; + volumeSlider.SetBinding(Slider.CurrentValueProperty, "VolumeLevel"); + AddVolumeSliderEventHandlers(); + } + + private void AddVolumeSliderElements() + { + AddLeftVolumeIcon(); + AddRightVolumeIcon(); + AddVolumeSlider(); + } + + private void AddControlElements() + { + AddTextControlElements(); + AddButtonControlElements(); + AddVolumeSliderElements(); + } + + private void AddPlaybackSliderEventHandler() + { + playbackSlider.SlidingStarted += (object sender, SliderSlidingStartedEventArgs e) => + { + viewModel.StopPlaybackTimer(); + }; + playbackSlider.ValueChanged += (object sender, SliderValueChangedEventArgs e) => + { + viewModel.SetElapsedTime(e.CurrentValue); + }; + playbackSlider.SlidingFinished += (object sender, SliderSlidingFinishedEventArgs e) => + { + viewModel.UpdatePlayerPosition(e.CurrentValue); + }; + } + + private void AddPlaybackSlider(View sliderView) + { + playbackSlider = new Slider("Slider") + { + ThemeChangeSensitive = true, + MinValue = 0.0f, + MaxValue = 1.0f, + WidthResizePolicy = ResizePolicyType.FillToParent, + SizeHeight = 44, + ThumbSize = new Tizen.NUI.Size(36, 36), + Direction = Slider.DirectionType.Horizontal, + }; + playbackSlider.SetBinding(Slider.CurrentValueProperty, "ElapsedTime"); + sliderView.Add(playbackSlider); + AddPlaybackSliderEventHandler(); + } + + private void AddCurrentTimeLabel(View sliderView) + { + currentTime = new TextLabel("LabelText") + { + ThemeChangeSensitive = true, + Size2D = new Size2D(400, 32), + Position2D = new Position2D(0, 48), + PixelSize = 24, + FontFamily = "BreezeSans", + Text = "00::00:00", + HorizontalAlignment = HorizontalAlignment.Begin, + }; + currentTime.SetBinding(TextLabel.TextProperty, "PlayingTime"); + sliderView.Add(currentTime); + } + + private void AddTotalTimeLabel(View sliderView) + { + totalTime = new TextLabel("LabelText") + { + ThemeChangeSensitive = true, + Size2D = new Size2D(400, 32), + Position2D = new Position2D(1792 - 400, 48), + PixelSize = 24, + FontFamily = "BreezeSans", + HorizontalAlignment = HorizontalAlignment.End, + Text = "59:59:59", + }; + totalTime.SetBinding(TextLabel.TextProperty, "TrackLength"); + sliderView.Add(totalTime); + } + + private void AddPlaybackSlider() + { + sliderView = new View() + { + Size2D = new Size2D(1792, 80), + Position2D = new Position2D(64, 950), + BackgroundColor = Color.Transparent, + }; + Add(sliderView); + + AddPlaybackSlider(sliderView); + AddCurrentTimeLabel(sliderView); + AddTotalTimeLabel(sliderView); + UpdatePlaybackSliderPosition(viewState); + } + + private void UpdatePlaybackSliderPosition(PlayerViewState state) + { + if(state == PlayerViewState.AlbumArt) + { + sliderView.Size2D = new Size2D(1792, 80); + sliderView.Position2D = new Position2D(64, 950); + currentTime.Size2D = new Size2D(400, 32); + currentTime.Position2D = new Position2D(0, 48); + totalTime.Size2D = new Size2D(400, 32); + totalTime.Position2D = new Position2D(1392, 48); + } + else + { + sliderView.Size2D = new Size2D(640, 80); + sliderView.Position2D = new Position2D(1056, 950); + currentTime.Size2D = new Size2D(180, 32); + currentTime.Position2D = new Position2D(0, 48); + totalTime.Size2D = new Size2D(180, 32); + totalTime.Position2D = new Position2D(460, 48); + } + } + + private void AddListActionButtons() + { + View actionButtonView = new View() + { + Size2D = new Size2D(224, 48), + Position2D = new Position2D((Window.Instance.WindowSize.Width / 2 - 224 - LayoutPadding), 120), + BackgroundColor = Color.Transparent, + }; + rightView.Add(actionButtonView); + + listButton = new Button("ListButton") + { + ThemeChangeSensitive = true, + }; + listButton.Clicked += (object sender, ClickedEventArgs e) => + { + if(viewState == PlayerViewState.AlbumArt) + { + Tizen.Log.Debug(AppConstants.LogTag, "Adding Playing list view"); + viewState = PlayerViewState.TrackList; + RemoveLyricsView(); + AddPlayingListView(); + thumb.Show(); + } + else + { + Tizen.Log.Debug(AppConstants.LogTag, "Adding album art view"); + viewState = PlayerViewState.AlbumArt; + RemovePlayingListView(); + AddLyricsView(); + thumb.Hide(); + } + UpdatePlaybackSliderPosition(viewState); + UpdatePlayerViewBackground(viewState); + }; + actionButtonView.Add(listButton); + + playlistButton = new Button("PlaylistButton") + { + ThemeChangeSensitive = true, + }; + actionButtonView.Add(playlistButton); + + favouriteButton = new MultiStateButton() + { + Size2D = new Size2D(IconSize, IconSize), + Position2D = new Position2D(176, 0), + IconResources = new Dictionary>() + { + { + ThemeType.Light, + new Dictionary() + { + { + Favourite.Off.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "light/favourite_off.png", + } + }, + { + Favourite.On.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "light/favourite_on.png", + } + }, + } + }, + { + ThemeType.Dark, + new Dictionary() + { + { + Favourite.Off.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "dark/favourite_off.png", + } + }, + { + Favourite.On.ToString(), + new StringSelector() + { + All = Resources.GetImagePath() + "dark/favourite_on.png", + } + }, + } + } + }, + }; + favouriteButton.CusotmState = Favourite.Off.ToString(); + actionButtonView.Add(favouriteButton); + } + + private void AddThumbnail() + { + thumb = new ImageView() + { + BackgroundColor = Color.Cyan, + Size2D = new Size2D(200, 200), + Position2D = new Position2D(380, 120), + }; + thumb.SetBinding(ImageView.ResourceUrlProperty, "ThumbnailPath"); + rightView.Add(thumb); + thumb.Hide(); + } + + private void AddPlayingListView() + { + if (currentListView == null) + currentListView = new PlayingListView(viewModel.CurrentPlayingListViewModel); + + currentListView.Size2D = new Size2D(832, 900); + currentListView.Position2D = new Position2D(64, 108); + leftView.Add(currentListView); + currentListView.Show(); + } + + private void RemovePlayingListView() + { + if(currentListView == null) + { + Tizen.Log.Error(AppConstants.LogTag, "current listview is null, can't remove it"); + return; + } + leftView.Remove(currentListView); + currentListView.Hide(); + } + + private void AddLyricsView() + { + if (lyricsView == null) + lyricsView = new LyricsView(viewModel.lyricsViewModel); + + lyricsView.Size2D = new Size2D(784, 784); + lyricsView.Position2D = new Position2D(88, 120); + leftView.Add(lyricsView); + lyricsView.Show(); + } + + private void RemoveLyricsView() + { + if(lyricsView == null) + { + Tizen.Log.Error(AppConstants.LogTag, "lyricsview is null, can't remove it"); + return; + } + leftView.Remove(lyricsView); + lyricsView.Hide(); + } + } +} diff --git a/music-player/Views/PlayingListView.cs b/music-player/Views/PlayingListView.cs new file mode 100755 index 0000000..cab9516 --- /dev/null +++ b/music-player/Views/PlayingListView.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Tizen.NUI.BaseComponents; +using Tizen.NUI.Components; +using Tizen.NUI; +using MusicPlayer.ViewModels; +using MusicPlayer.Common; +using Tizen.NUI.Binding; + +namespace MusicPlayer.Views +{ + class PlayingListView : View + { + private CollectionView collectionView; + private PlayingListViewModel viewModel; + + public PlayingListView(PlayingListViewModel viewModel) : base() + { + this.viewModel = viewModel; + collectionView = new CollectionView() + { + BackgroundImage = Resources.GetImagePath() + "playing_list_bg.png", + ItemsSource = this.viewModel.TrackListVM, + ItemsLayouter = new LinearLayouter(), + ItemTemplate = new DataTemplate(() => + { + ListItemLayout layout = new ListItemLayout(832, 108); + layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "ThumbnailPath"); + layout.TitleLabel.SetBinding(TextLabel.TextProperty, "TrackTitle"); + layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); + return layout; + }), + ScrollingDirection = ScrollableBase.Direction.Vertical, + SelectionMode = ItemSelectionMode.Single, + WidthResizePolicy = ResizePolicyType.FillToParent, + HeightResizePolicy = ResizePolicyType.FillToParent, + }; + base.Add(collectionView); + viewModel.ItemsSourceChanged += ItemSourceChanged; + } + + private void ItemSourceChanged(object sender, EventArgs e) + { + collectionView.ItemsSource = viewModel.TrackListVM; + } + } +} diff --git a/music-player/Views/TrackView.cs b/music-player/Views/TrackView.cs new file mode 100755 index 0000000..daa7df1 --- /dev/null +++ b/music-player/Views/TrackView.cs @@ -0,0 +1,102 @@ +using MusicPlayer.ViewModels; +using Tizen.NUI.Components; +using Tizen.NUI.BaseComponents; +using Tizen.NUI; +using Tizen.NUI.Binding; +using MusicPlayer.Common; + +namespace MusicPlayer.Views +{ + class TrackView : BaseContentView + { + private TrackViewModel viewModel; + private TextLabel trackCountLabel; + private Button playAllIcon; // TODO need to implement playall feature + private Button addToPlaylistIcon; // TODO need to implement playlist manager + public TrackView(TrackViewModel viewModel) + { + this.viewModel = viewModel; + collectionView.ItemsSource = viewModel.ListViewModel; + collectionView.ItemTemplate = new DataTemplate(() => + { + ListItemLayout layout = new ListItemLayout(); + layout.Icon.SetBinding(ImageView.ResourceUrlProperty, "ThumbnailPath"); + layout.TitleLabel.SetBinding(TextLabel.TextProperty, "TrackTitle"); + layout.SubtitleLabel.SetBinding(TextLabel.TextProperty, "ArtistName"); + return layout; + }); + collectionView.ScrollingDirection = ScrollableBase.Direction.Vertical; + collectionView.WidthSpecification = LayoutParamPolicies.WrapContent; + collectionView.SelectionMode = ItemSelectionMode.Single; + collectionView.SelectionChanged += OnTrackSelection; + + trackCountLabel = new TextLabel("LabelText") + { + ThemeChangeSensitive = true, + PixelSize = 28, + Text = "TRACK COUNT", + VerticalAlignment = VerticalAlignment.Center, + FontFamily = "BreezeSans", + }; + trackCountLabel.BindingContext = viewModel; + titleView.Add(trackCountLabel); + trackCountLabel.SetBinding(TextLabel.TextProperty, "TrackCount"); + RelativeLayout.SetLeftTarget(trackCountLabel, titleView); + RelativeLayout.SetLeftRelativeOffset(trackCountLabel, 1.0f); + RelativeLayout.SetRightRelativeOffset(trackCountLabel, 0.0f); + RelativeLayout.SetFillHorizontal(trackCountLabel, true); + + playAllIcon = new Button("PlayAll") + { + ThemeChangeSensitive = true, + }; + titleView.Add(playAllIcon); + RelativeLayout.SetLeftRelativeOffset(playAllIcon, 1.0f); + RelativeLayout.SetRightRelativeOffset(playAllIcon, 1.0f); + RelativeLayout.SetHorizontalAlignment(playAllIcon, RelativeLayout.Alignment.End); + + addToPlaylistIcon = new Button("PlaylistAdd") + { + ThemeChangeSensitive = true, + Margin = new Extents(32, 40, 0, 0), + }; + titleView.Add(addToPlaylistIcon); + RelativeLayout.SetRightTarget(addToPlaylistIcon, playAllIcon); + RelativeLayout.SetRightRelativeOffset(addToPlaylistIcon, 0.0f); + RelativeLayout.SetHorizontalAlignment(addToPlaylistIcon, RelativeLayout.Alignment.End); + } + + private void OnTrackSelection(object sender, SelectionChangedEventArgs e) + { + //TODO + } + + protected override void OnThemeChanged(object sender, ThemeChangedEventArgs e) + { + base.OnThemeChanged(sender, e); + } + protected override void Dispose(DisposeTypes type) + { + if(Disposed) + { + return; + } + if(type == DisposeTypes.Explicit) + { + titleView.Remove(trackCountLabel); + trackCountLabel.Dispose(); + trackCountLabel = null; + + // TODO Uncomment after implementation is completed + titleView.Remove(playAllIcon); + playAllIcon.Dispose(); + playAllIcon = null; + + //titleView.Remove(addToPlaylistIcon); + addToPlaylistIcon.Dispose(); + addToPlaylistIcon = null; + } + base.Dispose(type); + } + } +} diff --git a/music-player/Views/Utils/MultiStateButton.cs b/music-player/Views/Utils/MultiStateButton.cs new file mode 100644 index 0000000..e605dc0 --- /dev/null +++ b/music-player/Views/Utils/MultiStateButton.cs @@ -0,0 +1,93 @@ +using System.Collections.Generic; +using Tizen.NUI; +using Tizen.NUI.Binding; +using Tizen.NUI.Components; +using MusicPlayer.Common; + +namespace MusicPlayer.Views.Utils +{ + class MultiStateButton: Button + { + public static readonly BindableProperty CustomStateProperty = BindableProperty.Create(nameof(CusotmState), typeof(string), typeof(MultiStateButton), null, propertyChanged: (bindable, oldValue, newValue) => + { + var instance = (MultiStateButton)bindable; + if (newValue != null) + { + string newCustomState = (string)newValue; + instance.UpdateCustomState(newCustomState); + } + }, + defaultValueCreator: (bindable) => + { + var instance = (MultiStateButton)bindable; + return instance.customState; + }); + + public MultiStateButton() : base() + { + ThemeChangeSensitive = true; + EnableControlState = true; + BackgroundColor = Color.Transparent; + } + + private Dictionary> iconResources; + + public Dictionary> IconResources + { + get => iconResources; + set => iconResources = value; + } + + private string customState; + public string CusotmState + { + get => (string)GetValue(CustomStateProperty); + set => SetValue(CustomStateProperty, value); + } + + private void UpdateCustomState(string customStatevalue) + { + if (IconResources == null) + { + Tizen.Log.Error(AppConstants.LogTag, "ThemesIconState needs to be set first"); + return; + } + ThemeType type = GetCurrentThemeType(); + if (iconResources.ContainsKey(type) == false) + { + Tizen.Log.Error(AppConstants.LogTag, "Theme state doesn't exists: " + type.ToString()); + return; + } + Dictionary stateResource = iconResources[type]; + if (stateResource.ContainsKey(customStatevalue) == false) + { + Tizen.Log.Error(AppConstants.LogTag, "Invalid state: " + customStatevalue); + return; + } + IconURLSelector = stateResource[customStatevalue]; + customState = customStatevalue; + } + + private ThemeType GetCurrentThemeType() + { + ThemeType type; + string id = ThemeManager.PlatformThemeId; + if (id.Equals(AppConstants.LightPlatformThemeId)) + { + type = ThemeType.Light; + } + else + { + type = ThemeType.Dark; + } + return type; + } + + protected override void OnThemeChanged(object sender, ThemeChangedEventArgs e) + { + base.OnThemeChanged(sender, e); + UpdateCustomState(CusotmState); + } + } +} + diff --git a/music-player/XamlPage.xaml.cs b/music-player/XamlPage.xaml.cs new file mode 100644 index 0000000..8a08eb7 --- /dev/null +++ b/music-player/XamlPage.xaml.cs @@ -0,0 +1,14 @@ +using System; +using Tizen.NUI; +using Tizen.NUI.BaseComponents; + +namespace MusicPlayer +{ + public partial class XamlPage : View + { + public XamlPage() + { + InitializeComponent(); + } + } +} diff --git a/music-player/music-player.csproj b/music-player/music-player.csproj new file mode 100755 index 0000000..782f6b6 --- /dev/null +++ b/music-player/music-player.csproj @@ -0,0 +1,34 @@ + + + + Exe + netcoreapp3.1 + Tizen + MusicPlayer + + + + portable + + + None + + + + + + + + + + MSBuild:Compile + + + + + + + + + + diff --git a/music-player/res/layout/XamlPage.xaml b/music-player/res/layout/XamlPage.xaml new file mode 100644 index 0000000..7a54808 --- /dev/null +++ b/music-player/res/layout/XamlPage.xaml @@ -0,0 +1,9 @@ + + + + + + diff --git a/music-player/res/themes/dark.xaml b/music-player/res/themes/dark.xaml new file mode 100644 index 0000000..1ad5b52 --- /dev/null +++ b/music-player/res/themes/dark.xaml @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *Resource*/images/empty_track.png + + + + + *Resource*/images/dark/progress_track.png + + + + + *Resource*/images/dark/nomal_slider_handler.png + + + + + + + + + + + + + + + + + + + + + + + + + + *Resource*/images/dark/left_sound_icon.png + + + + *Resource*/images/dark/right_sound_icon.png + + + + + + + + + + + \ No newline at end of file diff --git a/music-player/res/themes/light.xaml b/music-player/res/themes/light.xaml new file mode 100644 index 0000000..552ec81 --- /dev/null +++ b/music-player/res/themes/light.xaml @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *Resource*/images/empty_track.png + + + + + *Resource*/images/light/progress_track.png + + + + + *Resource*/images/light/nomal_slider_handler.png + + + + + + + + + + + + + + + + + + + + + + + + + + *Resource*/images/light/left_sound_icon.png + + + + *Resource*/images/light/right_sound_icon.png + + + + + + + + + + + \ No newline at end of file diff --git a/music-player/shared/res/MusicPlayer.png b/music-player/shared/res/MusicPlayer.png new file mode 100644 index 0000000..9f3cb98 Binary files /dev/null and b/music-player/shared/res/MusicPlayer.png differ diff --git a/music-player/tizen-manifest.xml b/music-player/tizen-manifest.xml new file mode 100644 index 0000000..03c8036 --- /dev/null +++ b/music-player/tizen-manifest.xml @@ -0,0 +1,14 @@ + + + + + + MusicPlayer.png + + + + + + + + diff --git a/packaging/org.tizen.MusicPlayer-1.0.0.tpk b/packaging/org.tizen.MusicPlayer-1.0.0.tpk new file mode 100755 index 0000000..caae972 Binary files /dev/null and b/packaging/org.tizen.MusicPlayer-1.0.0.tpk differ diff --git a/packaging/org.tizen.MusicPlayer.spec b/packaging/org.tizen.MusicPlayer.spec new file mode 100755 index 0000000..aa2c7bd --- /dev/null +++ b/packaging/org.tizen.MusicPlayer.spec @@ -0,0 +1,36 @@ +Name: org.tizen.MusicPlayer +Summary: org.tizen.MusicPlayer +Version: 1.0.0 +Release: 1 +Group: N/A +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz + +ExclusiveArch: i586 x86 i486 i686 i386 armv7l arm aarch64 + + +BuildRequires: pkgconfig(libtzplatform-config) +Requires(post): /usr/bin/tpk-backend + +%define internal_name org.tizen.MusicPlayer +%define preload_tpk_path %{TZ_SYS_RO_APP}/.preload-tpk + +%description +profile/iot/apps/dotnet/music-player +This is a container package which have preload TPK/WGT files + +%prep +%setup -q + +%build + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}/%{preload_tpk_path} +install packaging/%{internal_name}-%{version}.tpk %{buildroot}/%{preload_tpk_path}/ + +%post + +%files +%defattr(-,root,root,-) +%{preload_tpk_path}/* \ No newline at end of file diff --git a/res/layout/XamlPage.xaml b/res/layout/XamlPage.xaml deleted file mode 100644 index 7a54808..0000000 --- a/res/layout/XamlPage.xaml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/res/themes/dark.xaml b/res/themes/dark.xaml deleted file mode 100644 index 1ad5b52..0000000 --- a/res/themes/dark.xaml +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *Resource*/images/empty_track.png - - - - - *Resource*/images/dark/progress_track.png - - - - - *Resource*/images/dark/nomal_slider_handler.png - - - - - - - - - - - - - - - - - - - - - - - - - - *Resource*/images/dark/left_sound_icon.png - - - - *Resource*/images/dark/right_sound_icon.png - - - - - - - - - - - \ No newline at end of file diff --git a/res/themes/light.xaml b/res/themes/light.xaml deleted file mode 100644 index 552ec81..0000000 --- a/res/themes/light.xaml +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *Resource*/images/empty_track.png - - - - - *Resource*/images/light/progress_track.png - - - - - *Resource*/images/light/nomal_slider_handler.png - - - - - - - - - - - - - - - - - - - - - - - - - - *Resource*/images/light/left_sound_icon.png - - - - *Resource*/images/light/right_sound_icon.png - - - - - - - - - - - \ No newline at end of file diff --git a/shared/res/MusicPlayer.png b/shared/res/MusicPlayer.png deleted file mode 100644 index 9f3cb98..0000000 Binary files a/shared/res/MusicPlayer.png and /dev/null differ diff --git a/tizen-manifest.xml b/tizen-manifest.xml deleted file mode 100644 index 03c8036..0000000 --- a/tizen-manifest.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - MusicPlayer.png - - - - - - - -