diff --git a/MPfm/MPfm.Library/Database/DatabaseFacade.cs b/MPfm/MPfm.Library/Database/DatabaseFacade.cs index 0ffad71b..56be6d5c 100644 --- a/MPfm/MPfm.Library/Database/DatabaseFacade.cs +++ b/MPfm/MPfm.Library/Database/DatabaseFacade.cs @@ -284,7 +284,7 @@ public List SelectDistinctArtistNames(AudioFileFormat audioFileFormat) { sql.AppendLine(" WHERE ArtistName = '" + FormatSQLValue(artistName) + "' "); } - sql.AppendLine(" ORDER BY ArtistName"); + sql.AppendLine(" ORDER BY ArtistName, AlbumTitle "); // Select distinct List> listTuple = _gateway.SelectTuple(sql.ToString()); diff --git a/MPfm/MPfm.MVP/Presenters/MobileLibraryBrowserPresenter.cs b/MPfm/MPfm.MVP/Presenters/MobileLibraryBrowserPresenter.cs index 5ef697da..55505caf 100644 --- a/MPfm/MPfm.MVP/Presenters/MobileLibraryBrowserPresenter.cs +++ b/MPfm/MPfm.MVP/Presenters/MobileLibraryBrowserPresenter.cs @@ -18,6 +18,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using MPfm.MVP.Messages; using MPfm.MVP.Models; using MPfm.MVP.Navigation; @@ -42,6 +44,7 @@ public class MobileLibraryBrowserPresenter : BasePresenter _items; public AudioFileFormat Filter { get; private set; } @@ -59,6 +62,7 @@ public class MobileLibraryBrowserPresenter : BasePresenter { }); } public override void BindView(IMobileLibraryBrowserView view) @@ -66,6 +70,7 @@ public override void BindView(IMobileLibraryBrowserView view) base.BindView(view); view.OnItemClick = OnItemClick; + view.OnRequestAlbumArt = RequestAlbumArt; // Subscribe to any audio file cache update so we can update this screen _messengerHub.Subscribe(AudioFileCacheUpdated); @@ -78,6 +83,23 @@ private void AudioFileCacheUpdated(AudioFileCacheUpdatedMessage audioFileCacheUp RefreshLibraryBrowser(); } + private void RequestAlbumArt(string artistName, string albumTitle) + { + // Only run one task at a time. + _currentTask = _currentTask.ContinueWith(t => { + // Get the file path of the first file in the album + var audioFiles = _libraryService.SelectAudioFiles(AudioFileFormat.All, artistName, albumTitle, string.Empty); + var audioFile = (audioFiles != null && audioFiles.Count() > 0) ? audioFiles.ElementAt(0) : null; + + if (audioFile != null) + { + // Update with with album art byte array + byte[] bytesImage = AudioFile.ExtractImageByteArrayForAudioFile(audioFile.FilePath); + View.RefreshAlbumArtCell(artistName, albumTitle, bytesImage); + } + }); + } + private void OnItemClick(int i) { // PLAYLIST TAB: Playlists --> Player diff --git a/MPfm/MPfm.MVP/Views/IMobileLibraryBrowserView.cs b/MPfm/MPfm.MVP/Views/IMobileLibraryBrowserView.cs index c64049a5..12e25471 100644 --- a/MPfm/MPfm.MVP/Views/IMobileLibraryBrowserView.cs +++ b/MPfm/MPfm.MVP/Views/IMobileLibraryBrowserView.cs @@ -27,8 +27,10 @@ namespace MPfm.MVP.Views public interface IMobileLibraryBrowserView : IBaseView { Action OnItemClick { get; set; } + Action OnRequestAlbumArt { get; set; } void RefreshLibraryBrowser(IEnumerable entities, MobileLibraryBrowserType browserType, string navigationBarTitle); + void RefreshAlbumArtCell(string artistName, string albumTitle, byte[] albumArtData); } public enum MobileLibraryBrowserType diff --git a/MPfm/MPfm.iOS/Classes/Controllers/MobileLibraryBrowserViewController.cs b/MPfm/MPfm.iOS/Classes/Controllers/MobileLibraryBrowserViewController.cs index 3c8e1e7e..b1b8a033 100644 --- a/MPfm/MPfm.iOS/Classes/Controllers/MobileLibraryBrowserViewController.cs +++ b/MPfm/MPfm.iOS/Classes/Controllers/MobileLibraryBrowserViewController.cs @@ -18,17 +18,19 @@ using System; using System.Collections.Generic; using System.Drawing; -using MonoTouch.Foundation; -using MonoTouch.UIKit; -using MPfm.iOS.Classes.Controllers.Base; -using MPfm.iOS.Classes.Delegates; -using MPfm.iOS.Classes.Controls; -using MPfm.MVP.Views; -using MPfm.MVP.Models; using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MPfm.MVP.Models; +using MPfm.MVP.Views; using MPfm.Sound.AudioFiles; using MonoTouch.CoreAnimation; using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +using MPfm.iOS.Classes.Controllers.Base; +using MPfm.iOS.Classes.Controls; +using MPfm.iOS.Classes.Delegates; namespace MPfm.iOS.Classes.Controllers { @@ -38,6 +40,7 @@ public partial class MobileLibraryBrowserViewController : BaseViewController, IM private string _cellIdentifier = "MobileLibraryBrowserCell"; private string _navigationBarTitle = string.Empty; private MobileLibraryBrowserType _browserType; + private Task _currentTask; public MobileLibraryBrowserViewController(Action onViewReady) : base (onViewReady, UserInterfaceIdiomIsPhone ? "MobileLibraryBrowserViewController_iPhone" : "MobileLibraryBrowserViewController_iPad", null) @@ -55,6 +58,7 @@ public override void ViewDidLoad() lblSubtitle1.Font = UIFont.FromName("OstrichSans-Black", 12); lblSubtitle2.Font = UIFont.FromName("OstrichSans-Black", 12); + _currentTask = Task.Factory.StartNew (() => { }); //lblArtistName.SizeToFit(); //lblAlbumTitle.SizeToFit(); @@ -103,11 +107,15 @@ public UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) cell = new UITableViewCell(cellStyle, _cellIdentifier); // Set title + cell.Tag = indexPath.Row; cell.TextLabel.Text = _items[indexPath.Row].Title; //cell.DetailTextLabel.Text = _items[indexPath.Row]. if (_browserType == MobileLibraryBrowserType.Albums) - cell.ImageView.Image = UIImage.FromBundle("Images/icon114"); + { + cell.ImageView.Image = UIImage.FromBundle("Images/emptyalbumart"); + OnRequestAlbumArt(_items[indexPath.Row].Query.ArtistName, _items[indexPath.Row].Query.AlbumTitle); + } // Set font //cell.TextLabel.Font = UIFont.FromName("Junction", 20); @@ -130,7 +138,41 @@ public void RowSelected(UITableView tableView, NSIndexPath indexPath) #region IMobileLibraryBrowserView implementation public Action OnItemClick { get; set; } + public Action OnRequestAlbumArt { get; set; } + + public void RefreshAlbumArtCell(string artistName, string albumTitle, byte[] albumArtData) + { + InvokeOnMainThread(() => { + + // Get item from list + var item = _items.FirstOrDefault(x => x.Query.ArtistName == artistName && x.Query.AlbumTitle == albumTitle); + if(item == null) + return; + // Get cell from item + int index = _items.IndexOf(item); + var cell = tableView.VisibleCells.FirstOrDefault(x => x.Tag == index); + if(cell == null) + return; + + // Load image + _currentTask = _currentTask.ContinueWith(t => { + NSData imageData = NSData.FromArray(albumArtData); + UIImage imageNotResized = UIImage.LoadFromData(imageData); + UIImage image = ScaleImage(imageNotResized, (int)cell.Bounds.Height * 2); + InvokeOnMainThread(() => { + if(cell != null) + { + if(cell.ImageView != null) + { + cell.ImageView.Image = image; + } + } + }); + }); + }); + } + public void RefreshLibraryBrowser(IEnumerable entities, MobileLibraryBrowserType browserType, string navigationBarTitle) { InvokeOnMainThread(() => { @@ -178,6 +220,77 @@ public void RefreshLibraryBrowser(IEnumerable entities, Mo #endregion + public static UIImage ScaleImage(UIImage image, int maxSize) + { + UIImage res; + + using (CGImage imageRef = image.CGImage) + { + CGImageAlphaInfo alphaInfo = imageRef.AlphaInfo; + CGColorSpace colorSpaceInfo = CGColorSpace.CreateDeviceRGB(); + if (alphaInfo == CGImageAlphaInfo.None) + { + alphaInfo = CGImageAlphaInfo.NoneSkipLast; + } + + int width, height; + + width = imageRef.Width; + height = imageRef.Height; + + + if (height >= width) + { + width = (int)Math.Floor((double)width * ((double)maxSize / (double)height)); + height = maxSize; + } + else + { + height = (int)Math.Floor((double)height * ((double)maxSize / (double)width)); + width = maxSize; + } + + + CGBitmapContext bitmap; + + if (image.Orientation == UIImageOrientation.Up || image.Orientation == UIImageOrientation.Down) + { + bitmap = new CGBitmapContext(IntPtr.Zero, width, height, imageRef.BitsPerComponent, imageRef.BytesPerRow, colorSpaceInfo, alphaInfo); + } + else + { + bitmap = new CGBitmapContext(IntPtr.Zero, height, width, imageRef.BitsPerComponent, imageRef.BytesPerRow, colorSpaceInfo, alphaInfo); + } + + switch (image.Orientation) + { + case UIImageOrientation.Left: + bitmap.RotateCTM((float)Math.PI / 2); + bitmap.TranslateCTM(0, -height); + break; + case UIImageOrientation.Right: + bitmap.RotateCTM(-((float)Math.PI / 2)); + bitmap.TranslateCTM(-width, 0); + break; + case UIImageOrientation.Up: + break; + case UIImageOrientation.Down: + bitmap.TranslateCTM(width, height); + bitmap.RotateCTM(-(float)Math.PI); + break; + } + + bitmap.DrawImage(new Rectangle(0, 0, width, height), imageRef); + + + res = UIImage.FromImage(bitmap.ToImage()); + bitmap = null; + + } + + + return res; + } } } diff --git a/MPfm/MPfm.iOS/Images/emptyalbumart.png b/MPfm/MPfm.iOS/Images/emptyalbumart.png new file mode 100644 index 00000000..fbb1c443 Binary files /dev/null and b/MPfm/MPfm.iOS/Images/emptyalbumart.png differ diff --git a/MPfm/MPfm.iOS/MPfm.iOS.csproj b/MPfm/MPfm.iOS/MPfm.iOS.csproj index db417947..79500a67 100644 --- a/MPfm/MPfm.iOS/MPfm.iOS.csproj +++ b/MPfm/MPfm.iOS/MPfm.iOS.csproj @@ -244,6 +244,7 @@ +