public async Task Search() { SearchResults.Clear(); var status = LibraryStatus; if (status == null) { //Debug.WriteLine("Searching: " + Term); // Search cancellation is not directly supported. Instead, when a search is complete, before updating the search results we ensure that the search // term has not changed. If the search term has changed meanwhile, it means we've received out-of-date data, in which case it is ignored. var searchTerm = Term; var results = await WebAwareT(async() => { return(await MusicProvider.Search(Term)); }); // WebAwareT returns default(T) if there's an exception var isResultUpToDate = searchTerm == Term; if (results != null && isResultUpToDate) { foreach (var result in results) { SearchResults.Add(result); } if (results.Count() == 0) { FeedbackMessage = "No results for: " + Term; } } } else { FeedbackMessage = status; } }
public MusicDialog() { _musicProviders.Add(new YandexMusic()); _mainMusicProvider = _musicProviders[0]; AssistantCore.Assistant.Mute += TechnicalMute; AssistantCore.Assistant.Unmute += TechnicalUnmute; }
/// <summary> /// Checks the configured library locations for new/updated/deleted files, /// and updates the database accordingly /// </summary> private async Task SynchroniseDb() { await Console.Out.WriteLineAsync("LibraryMonitor: Starting update (enumerating files)."); using (var mp = new MusicProvider()) { var lastDBUpdateTime = mp.GetLastUpdateTime(); // Set the last update time now // Otherwise, files that change between now and update completion // might not get flagged for update up in the next sync round await mp.SetLastUpdateTime(DateTime.UtcNow.ToUniversalTime()); foreach (var libraryLocation in m_libraryLocations) { await FindFilesToUpdate(libraryLocation, mp, lastDBUpdateTime); } } await Console.Out.WriteLineAsync($"LibraryMonitor: {m_filesToUpdate.Count} files need to be updated and {m_filesToAdd.Count} files need to be added."); await UpdateFiles(); m_filesToUpdate.Clear(); await AddNewFiles(); m_filesToAdd.Clear(); await DeleteStaleDbEntries(); await Console.Out.WriteLineAsync("LibraryMonitor: Database update completed successfully."); // Schedule the next sync m_syncTimer.Change(SYNC_INTERVAL_SECONDS * 1000, Timeout.Infinite); }
public static WebViewWrapper WrapperFactory(MusicProvider provider) { WKUserContentController controller = new WKUserContentController(); controller.AddUserScript( new WKUserScript(new NSString(provider.EventsJs), WKUserScriptInjectionTime.AtDocumentEnd, false) ); controller.AddScriptMessageHandler(Container.WKScriptMessageHandler, "playbackState"); WKWebViewConfiguration config = new WKWebViewConfiguration { UserContentController = controller }; config.Preferences.SetValueForKey(NSObject.FromObject(true), new NSString("developerExtrasEnabled")); var webView = new WKWebView(new CGRect(0, 0, 100, 100), config) { CustomUserAgent = "Mozilla/5.0 " + "(Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 " + "(KHTML, like Gecko) Version/12.0 Safari/605.1.15", AutoresizingMask = NSViewResizingMask.HeightSizable | NSViewResizingMask.WidthSizable, NavigationDelegate = new NavigationDelegate() }; webView.TranslatesAutoresizingMaskIntoConstraints = false; var req = new NSUrlRequest(new NSUrl(provider.Url)); webView.LoadRequest(req); return(new WebViewWrapper(webView, provider)); }
/// <summary> /// Keeps the download progress properties of the music items up-to-date /// so that the progress can be displayed under each item in the UI. /// /// The music items in the library and the playlist do not point to the /// same object even if it's the same track so we need to update both places separately. /// </summary> /// <param name="transfer"></param> protected override void OnDownloadStatusUpdate(BackgroundTransferRequest transfer) { base.OnDownloadStatusUpdate(transfer); var path = FileUtilsBase.UnixSeparators(transfer.Tag.Substring(PhoneLocalLibrary.Instance.BaseMusicPath.Length)); var musicItem = MusicProvider.SearchItem(path); var isDownloading = transfer.TransferStatus == TransferStatus.Transferring; var bytesReceived = (ulong)transfer.BytesReceived; // updates track in the library if (musicItem != null) { MusicItem.SetDownloadStatus(musicItem, bytesReceived); musicItem.IsDownloading = isDownloading; } // updates the track in the playlist var playlistTracks = PimpViewModel.Instance.MusicPlayer.Playlist.Songs .Where(item => item.Song.Path == path) .ToList(); // beautiful!!! BasePlaylist.SetDownloadStatus(playlistTracks, bytesReceived); foreach (var item in playlistTracks) { item.Song.IsDownloading = isDownloading; } }
/// <summary> /// Recursively adds all files in @param startDirectory (of the configured file types) /// that have been created or modified since @lastDBUpdateTime /// to the list of files that need to be updated in/added to the database /// </summary> /// <param name="startDirectory">Where to start looking for new/updated files</param> /// <param name="mp">Handle to the database</param> /// <param name="lastDBUpdateTime">Write time beyond which files will be condsidered new or modified</param> /// <returns></returns> private async Task FindFilesToUpdate( string startDirectory, MusicProvider mp, DateTime lastDBUpdateTime ) { foreach (var subDir in Directory.EnumerateDirectories(startDirectory)) { if (new DirectoryInfo(subDir).LastWriteTime > lastDBUpdateTime) { await FindFilesToUpdate(subDir, mp, lastDBUpdateTime); } } foreach (var filePattern in m_filePatterns) { foreach (var file in Directory.EnumerateFiles(startDirectory, filePattern, SearchOption.TopDirectoryOnly)) { if (!(await mp.AllTracks.AsNoTracking().AnyAsync(t => t.FileName == file))) { m_filesToAdd.Add(file); } else if (new FileInfo(file).LastWriteTime.ToUniversalTime() > lastDBUpdateTime) { m_filesToUpdate.Add(file); } } } }
/// <summary> /// Adds all new files marked for addition to the database /// Clears files marked for addition /// </summary> private async Task AddNewFiles() { if (m_filesToAdd.Count() < 1) { return; } foreach (var slice in m_filesToAdd.GetSlices(SAVE_TO_DISK_INTERVAL)) { var newTracks = new List <DbTrack>(); foreach (var trackFileName in slice) { var newTrack = new DbTrack { FileName = trackFileName }; newTrack.SetTrackData(TagLib.File.Create(trackFileName).Tag); newTracks.Add(newTrack); } using (MusicProvider mp = new MusicProvider()) { await mp.AllTracks.AddRangeAsync(newTracks); await mp.SaveChangesAsync(); } } }
public static WebViewWrapper BuildWebViewWrapper(MusicProvider musicProvider) { WebView webView = new WebView(); webView.Navigate(new Uri(musicProvider.Url)); return(new WebViewWrapper(webView, musicProvider)); }
public static List <MediaSessionCompat.QueueItem> GetRandomQueue(MusicProvider musicProvider) { var shuffled = musicProvider.GetShuffledMusic(); var result = shuffled.Take(RandomQueueSize).ToList(); LogHelper.Debug(Tag, "getRandomQueue: result.size=", result.Count); return(ConvertToQueue(result, "random")); }
public async Task <bool> AddTemp(OnlinePlaylist playlist) { if (playlist.Entries == null || playlist.Entries.Count == 0) { playlist.Entries = await GetOnlineTracks(playlist); } return(await MusicProvider.AddTemp(playlist)); }
public async Task DownloadFolder(MusicItem folder) { var tracks = await MusicProvider.SongsInFolder(folder); foreach (var t in tracks) { await SubmitDownload(t); } }
private async Task SubmitFolder(MusicItem folder) { var tracks = await MusicProvider.SongsInFolder(folder); foreach (var item in tracks) { await SubmitDownload(item); } }
private void HandleClick(MusicProvider provider) { if (provider == currentProvider) { return; } currentProvider = provider; RaiseProviderClicked(provider); }
public Platform(Jint.Engine engine, MusicProvider musicProvider, ISettingsService settingsService, IMvxNavigationService mvxNavigationService, IAuthenticationService authenticationService, IMvxLogProvider logProvider) { _engine = engine; _musicProvider = musicProvider; _settingsService = settingsService; _mvxNavigationService = mvxNavigationService; _authenticationService = authenticationService; _logProvider = logProvider; }
public async Task ReSync() { using (new Spinner(Strings.SyncingDatabase)) { var apis = Collection.Values.ToList(); var tasks = apis.Select(x => x.Resync()); await Task.WhenAll(tasks); await MusicProvider.SetOffline(); } }
public QueueManager(MusicProvider musicProvider, Resources resources, MetadataUpdateListener listener) { this.musicProvider = musicProvider; this.listener = listener; this.resources = resources; playingQueue = new SynchronizedList <MediaSessionCompat.QueueItem>(); currentIndex = 0; }
public WebViewWrapperBase GetWebViewWrapper(MusicProvider provider) { webViewWrappers = webViewWrappers ?? new Dictionary <string, WebViewWrapperBase>(); if (!webViewWrappers.ContainsKey(provider.Id)) { WebViewWrapperBase wrapper = wrapperFactory(provider); wrapper.PlayerStateChanged += Wrapper_PlayerStateChanged; wrapper.NowPlayingChanged += Wrapper_NowPlayingChanged; webViewWrappers[provider.Id] = wrapper; } return(webViewWrappers[provider.Id]); }
protected async void Refresh_Click(object sender, EventArgs e) { var wasUpdated = await EndpointScanner.Instance.SyncIfUnreachable(libraryManager.ActiveEndpoint); if (!wasUpdated) { // If the endpoint was updated, Reset is called anyway by PimpViewModel. // This ensures it's called exactly once. MusicProvider.Reset(); } //await OnMusicItemsNavigatedTo(); await LoadMusicItems(); }
public async Task <List <MusicItem> > GetSongsRecursively(MusicItem songOrDir) { if (!songOrDir.IsDir) { var tracks = new List <MusicItem>(); tracks.Add(songOrDir); return(tracks); } else { return(await MusicProvider.SongsInFolder(songOrDir)); } }
public async Task TrackDownloaded(string trackId) { var track = Database.Main.GetObject <Track, TempTrack> (trackId); if (track == null) { return; } var filePath = Path.Combine(Locations.MusicDir, track.FileName); var song = Database.Main.GetObject <Song, TempSong> (track.SongId); try { using (var file = TagLib.File.Create(filePath)) { file.Tag.Title = song.Name; file.Tag.Album = song.Album; file.Tag.Performers = file.Tag.AlbumArtists = new string[] { song.Artist }; file.Tag.Disc = (uint)song.Disc; file.Tag.Track = (uint)song.Track; file.Tag.TrackCount = (uint)song.TrackCount; file.Tag.Year = (uint)song.Year; file.Tag.Genres = new string[] { song.Genre }; //var artwork = await getARtwork(song); //if (!string.IsNullOrWhiteSpace(artwork)) //file.Tag.Pictures = new TagLib.IPicture[] {new TagLib.Picture(artwork) }; file.Save(); //if (File.Exists(artwork)) //File.Delete(artwork); } } catch (Exception ex) { LogManager.Shared.Report(ex); } var newTrack = new Track { Id = track.FileName, Duration = track.Duration, Genre = track.Genre, SongId = track.SongId, ServiceType = ServiceType.FileSystem, AlbumId = track.AlbumId, ArtistId = track.ArtistId, Deleted = false, ServiceId = track.ServiceId, MediaType = track.MediaType, FileExtension = track.FileExtension, }; //File.Move(filePath, Path.Combine(Locations.MusicDir, CleanFileName($"{song.Artist} - {song.Name}.mp3"))); Database.Main.InsertOrReplace(newTrack); await MusicProvider.SetOffline(newTrack); }
public async Task <string> Load() { await WebAware(async() => { MusicProvider.NewItemsLoaded += MusicProvider_NewItemsLoaded; try { await MusicProvider.LoadFolder(FolderId, MusicItems); } finally { MusicProvider.NewItemsLoaded -= MusicProvider_NewItemsLoaded; } }); FeedbackMessage = DetermineFeedbackMessage(); return(FeedbackMessage); }
public WebViewWrapper(object webView, MusicProvider musicProvider) : base(webView, musicProvider) { InitWebView(); if (musicProvider.Id == "Saavn") { return; } timer = new DispatcherTimer(); timer.Tick += Timer_Tick; timer.Interval = new TimeSpan(0, 0, 1); timer.Start(); }
async void ToggleIPod(bool on) { Settings.IncludeIpod = on; var ipod = ApiManager.Shared.GetMusicProvider <iPodProvider>(ServiceType.iPod); if (on) { ipod.SyncDatabase(); } else { MusicProvider.RemoveApi(ipod.Id); } }
public async Task LogOut(MusicProvider provider) { try { await provider.Logout(); int id; if (int.TryParse(provider.Id, out id)) { Settings.DeleteApiModel(id); } Collection.Remove(provider.Id); } catch (Exception ex) { Console.WriteLine(ex); } }
async Task StartDownload (Song song) { if(song == null) return; var track = await MusicManager.Shared.GetTrack (song.Id); if (track == null) { LogManager.Shared.Report (new Exception ("Track is null....")); return; } if (track.ServiceType == ServiceType.iPod || track.ServiceType == ServiceType.FileSystem) { await MusicProvider.SetOffline (track); return; } await BackgroundDownloadManager.Shared.Download (track); }
async Task <bool> SyncLibrary(string href = "") { try { var resp = await SyncRequestQueue.Enqueue(1, () => string.IsNullOrWhiteSpace(href)?Api.GetFavorites() : Api.Get <SApiResponse <STrack> >(href)).ConfigureAwait(false); Task <bool> nextTask = null; if (!string.IsNullOrWhiteSpace(resp?.NextUrl)) { nextTask = SyncLibrary(resp?.NextUrl); } var tracks = resp?.Items.Select(x => new FullTrackData(x.Title, x.User?.Username, "", "", x.Genre) { Id = x.Id.ToString(), Duration = x.Duration, ArtistServerId = x.UserId.ToString(), MediaType = MediaType.Audio, PlayCount = x.UserPlaybackCount ?? 0, ServiceId = Api.CurrentAccount.Identifier, ServiceType = this.ServiceType, FileExtension = "mp3", Rating = 5, Year = x.ReleaseYear ?? 0, AlbumArtwork = new List <AlbumArtwork> { new AlbumArtwork { Url = x.ArtworkUrl } }, }).ToList(); if ((tracks?.Count ?? 0) == 0) { return(true); } await MusicProvider.ProcessTracks(tracks); if (nextTask != null) { return(await nextTask); } return(true); } catch (Exception ex) { LogManager.Shared.Report(ex); } return(false); }
private void RenderProvider(MusicProvider provider) { var rightView = rightController.View; if (rightView.Subviews.Length > 0) { rightView.Subviews[0].RemoveFromSuperview(); } WKWebView webView = (WKWebView)viewModel.GetWebViewWrapper(provider).WebView; rightView.AddSubview(webView); webView.TopAnchor.ConstraintEqualToAnchor(rightView.TopAnchor).Active = true; webView.BottomAnchor.ConstraintEqualToAnchor(rightView.BottomAnchor).Active = true; webView.LeftAnchor.ConstraintEqualToAnchor(rightView.LeftAnchor).Active = true; webView.RightAnchor.ConstraintEqualToAnchor(rightView.RightAnchor).Active = true; }
/// <summary> /// Downloads the song in the background if it's not already available offline. /// </summary> /// <param name="track"></param> public async Task SubmitDownload(MusicItem track) { await BeforeDownload(track); try { var maybeLocalUri = await PhoneLocalLibrary.Instance.LocalUriIfExists(track); if (maybeLocalUri == null) { // For Subsonic, the response may be transcoded audio, in which case the // path to the track, which has the original file extension as stored on // the server, may be incorrect (example: response is transcoded to .mp3, // path is .flac). // TODO: Ensure that the file is stored locally with the correct extension, // that is, find out whether the response is transcoded. var destination = LocalLibrary.AbsolutePathTo(track); var downloadUri = MusicProvider.DownloadUriFor(track); // Only downloads tracks that are stored as MP3s, because this app does not support other local file formats. if (destination.EndsWith("mp3")) { var downloadable = new Downloadable(downloadUri, destination); if (LoadTransfersCount() < 3) { AddTransfer(downloadUri, destination); } else { // add the download to persistent storage from which it will be taken // later when there are fewer concurrent downloads DownloadDataContext.Add(downloadable); } } } } catch (PathTooLongException) { // Thrown if track.Path is about over 190 characters long, but I'm not sure what // the limit is and I don't want to be too defensive with this so I catch and // suppress the exception when it occurs. // The exception says "The specified path, file name, or both are too long. // The fully qualified file name must be less than 260 characters, and the // directory name must be less than 248 characters.", however, I don't know // the length of the fully qualified path name, so 190 chars is an estimate. AddMessage("Download of " + track.Name + " failed. The path is too long: " + track.Path); } }
protected override void OnDownloadStatusUpdate(DownloadOperation download) { base.OnDownloadStatusUpdate(download); // Updates the BytesReceived property of the possibly loaded MusicItem // so that a progress bar may be displayed under the item var musicPath = AppLocalFolderLibrary.MusicPath(download.ResultFile); var musicItem = MusicProvider.SearchItem(musicPath); var progress = download.Progress; var bytesReceived = progress.BytesReceived; if (musicItem != null) { MusicItem.SetDownloadStatus(musicItem, bytesReceived); } var playlistTracks = Playlist.Songs.Where(item => item.Song.Path == musicPath).ToList(); BasePlaylist.SetDownloadStatus(playlistTracks, bytesReceived); }
async Task <bool> GetTracks(string continuation = "") { try { var resp = await SyncRequestQueue.Enqueue(1, () => Api.GetSpecialFolderDelta("music", token: continuation)).ConfigureAwait(false); Task <bool> nextTask = null; if (!string.IsNullOrWhiteSpace(resp?.DeltaToken) && !string.IsNullOrWhiteSpace(resp?.NextLink)) { nextTask = GetTracks(resp?.DeltaToken); } var tracks = resp?.Value.Where(x => x.Audio != null).Select(x => new FullTrackData(x.Audio.Title, x.Audio.Artist, x.Audio.Artist, x.Audio.Album, x.Audio.Genre) { Id = x.Id, Duration = x.Audio.Duration, ArtistServerId = x.Audio.Artist, MediaType = MediaType.Audio, PlayCount = 0, ServiceId = Api.CurrentAccount.Identifier, ServiceType = this.ServiceType, FileExtension = System.IO.Path.GetExtension(x.Name), Rating = 5, Year = x.Audio.Year, }).ToList(); if ((tracks?.Count ?? 0) == 0) { return(true); } await MusicProvider.ProcessTracks(tracks); if (nextTask != null) { return(await nextTask); } Api.ExtraData.LastSongSync = resp.DeltaToken; return(true); } catch (Exception ex) { LogManager.Shared.Report(ex); } return(false); }