/// <summary>Creates the specified MDB.</summary> /// <param name="mdb">The MDB.</param> /// <param name="streamID">The stream identifier.</param> /// <param name="ownerID">The owner identifier (+user / -session / +subset).</param> /// <param name="subsetID">The subset identifier.</param> /// <param name="startTime">The start time.</param> /// <param name="audioFile">The audio file.</param> /// <returns></returns> public static MDBNowPlaying Create(MusicDataBase mdb, long streamID, long ownerID, long subsetID, DateTime startTime, MDBAudioFile audioFile) { var albumArtist = mdb.Artists.TryGetStruct(audioFile.AlbumArtistID); var artist = mdb.Artists.TryGetStruct(audioFile.SongArtistID); var album = mdb.Albums.TryGetStruct(audioFile.AlbumID); var genre = mdb.Genres.TryGetStruct(audioFile.GenreID); var tag = mdb.Tags.TryGetStruct(audioFile.TagID); return(new MDBNowPlaying() { StreamID = streamID, OwnerID = ownerID, SubsetID = subsetID, AudioFileID = audioFile.FileID, Duration = audioFile.Duration, StartDateTime = startTime, Title = audioFile.Title, ArtistName = artist.Name, AlbumArtistName = albumArtist.Name, AlbumName = album.Name, Genre = genre.Name, Genres = audioFile.Genres, Tag = tag.Name, Tags = audioFile.Tags, }); }
internal static MDBOverview Create(MusicDataBase mdb, WebServer server) { double fileSize = mdb.Files.Sum(nameof(MDBFile.Size)); double audioFilesSize = mdb.Files.Sum(nameof(MDBFile.Size), Search.FieldEquals(nameof(MDBFile.FileType), MDBFileType.mp3)); double imageFilesSize = mdb.Files.Sum(nameof(MDBFile.Size), !Search.FieldEquals(nameof(MDBFile.FileType), MDBFileType.mp3) & !Search.FieldEquals(nameof(MDBFile.FileType), MDBFileType.unknown)); TimeSpan audiofileDuration = TimeSpan.FromSeconds(Convert.ToDouble(mdb.AudioFiles.Sum(nameof(MDBAudioFile.Duration)))); return(new MDBOverview() { ID = 1 + Math.Abs(mdb.Files.SequenceNumber), LastUpdate = DateTime.Now, Version = server.ServerVersionString, AlbumCount = mdb.Albums.RowCount, ArtistCount = mdb.Artists.RowCount, AudioDataSize = (long)audioFilesSize, AudioDataSizeString = audioFilesSize.FormatSize(), AudioFileCount = mdb.AudioFiles.RowCount, Duration = audiofileDuration, DurationString = audiofileDuration.FormatTime(), FileCount = mdb.Files.RowCount, GenreCount = mdb.Genres.RowCount, ImageCount = mdb.Images.RowCount, ImageDataSize = (long)imageFilesSize, ImageDataSizeString = imageFilesSize.FormatSize(), TagCount = mdb.Tags.RowCount, }); }
void SetFtpMusicFolders(MusicDataBase mdb, FtpServer ftpServer) { lock (ftpServer.RootFolders) { ftpServer.RootFolders.Clear(); foreach (var dir in mdb.MusicFolders) { try { FileSystem.GetFileSystemEntries(dir); string name = Path.GetFileNameWithoutExtension(dir); int i = 0; string selectedName = name; while (!ftpServer.RootFolders.TryAdd(selectedName, dir)) { selectedName = name + (++i); } this.LogDebug("Added root <cyan>{0}<default> {1}", selectedName, dir); } catch (Exception ex) { this.LogWarning(ex, "Cannot access folder {0}", dir); } } ftpServer.DisconnectAllClients(); } }
MDBOverview GetOverview(MusicDataBase mdb, WebServer server) { if (cachedOverview.ID != Math.Abs(mdb.Files.SequenceNumber) + 1) { cachedOverview = MDBOverview.Create(mdb, server); } return(cachedOverview); }
/// <summary>Gets the full path.</summary> /// <param name="mdb">The MDB.</param> /// <param name="fileName">Name of the file.</param> /// <returns></returns> /// <exception cref="System.IO.DirectoryNotFoundException">Parent Folder missing!</exception> public string GetFullPath(MusicDataBase mdb, string fileName) { if (fileName == null) { throw new ArgumentNullException("fileName"); } return(FileSystem.Combine(Name, fileName)); }
/// <summary>Loads the specified <see cref="MDBPlayListItem"/>.</summary> /// <param name="mdb">The <see cref="MusicDataBase"/> instance.</param> /// <param name="item">The <see cref="MDBPlayListItem"/>.</param> /// <returns></returns> public static MDBFileSelection Load(MusicDataBase mdb, MDBPlayListItem item) { var result = new MDBFileSelection(); result.AudioFile = mdb.AudioFiles.TryGetStruct(item.AudioFileID); result.File = mdb.Files.TryGetStruct(result.AudioFile.FileID); result.NowPlaying = MDBNowPlaying.Create(mdb, item.StreamID, item.OwnerID, item.SubsetID, DateTime.MinValue, result.AudioFile); result.PlayListItem = item; return(result); }
/// <summary> /// Gets the full path of the file /// </summary> /// <param name="mdb">The mdb instance</param> /// <returns></returns> public string GetFullPath(MusicDataBase mdb) { if (FolderID == 0) { if (ReferenceEquals(Extension, null)) { return(Name); } return(Name + Extension); } return(mdb.Folders.GetStruct(FolderID).GetFullPath(mdb, Name + Extension)); }
/// <summary>Loads the specified album.</summary> /// <param name="mdb">The MDB.</param> /// <param name="album">The album.</param> /// <returns></returns> public static RPCAlbum Load(MusicDataBase mdb, MDBAlbum album) { MDBArtist artist = mdb.Artists.GetStruct(album.ArtistID); var files = mdb.AudioFiles.GetStructs(nameof(MDBAudioFile.AlbumID), album.ID); var result = new RPCAlbum() { ID = album.ID, Name = album.Name, ArtistID = artist.ID, ArtistName = artist.Name, Duration = new TimeSpan(files.Sum(f => f.Duration.Ticks)), Tags = files.SelectMany(f => f.TagNames).Distinct().Join(";"), Genres = files.SelectMany(f => f.GenreNames).Distinct().Join(";"), TrackCount = files.Count, Errors = (MDBMetaErrors)files.BinaryOr(f => (long)f.MetaErrors), }; return(result); }
/// <summary>Loads the artist from the specified MusicDataBase tables.</summary> /// <param name="mdb">The MusicDataBase.</param> /// <param name="artist">The artist.</param> /// <returns>Returns a new <see cref="RPCArtist"/> instance</returns> public static RPCArtist Load(MusicDataBase mdb, MDBArtist artist) { var files = mdb.AudioFiles.GetStructs( Search.FieldEquals(nameof(MDBAudioFile.SongArtistID), artist.ID) | Search.FieldEquals(nameof(MDBAudioFile.AlbumArtistID), artist.ID)); var result = new RPCArtist() { ID = artist.ID, Name = artist.Name, Errors = (MDBMetaErrors)files.BinaryOr(f => (long)f.MetaErrors), TitleCount = files.Count, Tags = files.SelectMany(f => f.TagNames).Distinct().Join(";"), Genres = files.SelectMany(f => f.GenreNames).Distinct().Join(";"), Duration = new TimeSpan(files.Sum(f => f.Duration.Ticks)), }; result.AlbumCount = mdb.Albums.Count(nameof(MDBAlbum.ArtistID), artist.ID); return(result); }
/// <summary>Loads the dataset using the specified MDB instance.</summary> /// <param name="mdb">The MDB.</param> /// <param name="file">The file.</param> /// <returns></returns> public static RPCAudioFile Load(MusicDataBase mdb, MDBAudioFile file) { MDBArtist albumArtist, titleArtist; MDBAlbum album; MDBCategory category; MDBGenre genre; MDBTag tag; mdb.Artists.TryGetStruct(file.AlbumArtistID, out albumArtist); mdb.Artists.TryGetStruct(file.SongArtistID, out titleArtist); mdb.Albums.TryGetStruct(file.AlbumID, out album); mdb.Categories.TryGetStruct(file.CategoryID, out category); mdb.Genres.TryGetStruct(file.GenreID, out genre); mdb.Tags.TryGetStruct(file.TagID, out tag); return(new RPCAudioFile() { AlbumID = album.ID, AlbumName = album.Name, AlbumArtistID = albumArtist.ID, AlbumArtistName = albumArtist.Name, TitleArtistID = titleArtist.ID, TitleArtistName = titleArtist.Name, AudioFileID = file.FileID, Category = category.Name, Duration = file.Duration, Errors = file.Errors, Genre = genre.Name, Genres = file.Genres, MetaErrors = file.MetaErrors, RecordingDate = file.RecordingDate, Tag = tag.Name, Tags = file.Tags, TrackCount = file.TrackCount, TrackNumber = file.TrackNumber, Title = file.Title, }); }
/// <summary>Initializes a new instance of the <see cref="WebInterface" /> class.</summary> /// <param name="mdb">The MusicDataBase instance.</param> /// <param name="authTables">The authentication tables.</param> /// <param name="player">The player.</param> /// <exception cref="System.ArgumentNullException"> /// mdb /// or /// authTables /// </exception> /// <exception cref="ArgumentNullException">mdb /// or /// player</exception> public WebInterface(MusicDataBase mdb, AuthTables authTables, IPlayer player) { FileCrawler = new FileCrawler(mdb); ArtCrawler = new ArtCrawler(mdb); this.mdb = mdb ?? throw new ArgumentNullException(nameof(mdb)); this.authTables = authTables ?? throw new ArgumentNullException(nameof(authTables)); this.player = player ?? throw new ArgumentNullException(nameof(player)); EmptyImage = WebImage.FromFile(FileSystem.Combine(mdb.WebFolder, "images", "empty.png"), mdb.CacheFolder); this.LogInfo("Loading album replacement images..."); ReplaceAlbumImages = Directory.GetFiles(FileSystem.Combine(mdb.WebFolder, "images"), "cd-??.png").Select(f => WebImage.FromFile(f, mdb.CacheFolder)).ToArray(); if (ReplaceAlbumImages.Length == 0) { ReplaceAlbumImages = new WebImage[] { WebImage.FromFile(FileSystem.Combine(mdb.WebFolder, "images", "no-image.png"), mdb.CacheFolder) }; } this.LogInfo("Loading artist replacement images..."); ReplaceArtistImages = Directory.GetFiles(FileSystem.Combine(mdb.WebFolder, "images"), "artist-??.png").Select(f => WebImage.FromFile(f, mdb.CacheFolder)).ToArray(); if (ReplaceArtistImages.Length == 0) { ReplaceArtistImages = new WebImage[] { WebImage.FromFile(FileSystem.Combine(mdb.WebFolder, "images", "no-image.png"), mdb.CacheFolder) }; } }
/// <summary> /// Initializes a new instance of the <see cref="MDBAudioFileSelector"/> class. /// </summary> /// <param name="mdb">The MDB.</param> public MDBAudioFileSelector(MusicDataBase mdb) { this.mdb = mdb; rnd = new Random(); }
public DesktopPlayer(MusicDataBase mdb, long streamID) { this.mdb = mdb; selector = new MDBAudioFileSelector(mdb); StreamID = streamID; }
public ArtCrawler(MusicDataBase mdb) { this.mdb = mdb; }
/// <summary>Loads the dataset using the specified MDB instance.</summary> /// <param name="mdb">The MDB.</param> /// <param name="audioFileID">The audio file identifier.</param> /// <returns></returns> public static RPCAudioFile Load(MusicDataBase mdb, long audioFileID) { return(Load(mdb, mdb.AudioFiles[audioFileID])); }
/// <summary>Initializes a new instance of the <see cref="MDBBroadcaster"/> class.</summary> /// <param name="mdb">The MDB.</param> public MDBBroadcaster(MusicDataBase mdb) { this.mdb = mdb; }
protected override void Worker() { if (LogConsole != null) { LogConsole.ExceptionMode = LogExceptionMode.Full; LogConsole.Flags |= LogConsoleFlags.DisplayTimeStamp; LogConsole.Mode = LogReceiverMode.Opportune; } Logger.DebugReceiver?.Close(); //init the async mysql connection class we want to use. //new MySql.Data.MySqlClient.MySqlConnection().Dispose(); WebServer webServer = null; FtpServer ftpServer = null; MusicDataBase mdb = null; MDBBroadcaster broadcaster = null; DesktopPlayer player = null; try { var rootFolder = FileSystem.ProgramDirectory; webServer = new WebServer(); mdb = new MusicDataBase(rootFolder); if (LogSystem != null) { //allow user to override loglevel by commandline if (LogSystem.Level == LogLevel.Information) { LogSystem.Level = mdb.Config.ReadEnum <LogLevel>("MusicDataBase", "LogLevel", LogLevel.Information); } } this.LogInfo("Loading Database..."); mdb.Load(); MemoryStorage.Default.LogVerboseMessages = LogSystem?.Level == LogLevel.Verbose; if (null != mdb.Database) { mdb.Database.Storage.LogVerboseMessages = MemoryStorage.Default.LogVerboseMessages; } if (mdb.Config.ReadBool("MusicDataBase", "ClearDatabase", false)) { foreach (ITable t in mdb.Tables) { t.Clear(); } } mdb.Save(); this.LogInfo("Loading auth tables..."); if (mdb.Database != null) { webServer.AuthTables.Connect(TableConnectorMode.Direct, mdb.Database); } else { try { webServer.AuthTables.Load(mdb.DataBasePath); } catch (Exception ex) { this.LogWarning(ex, "Load auth tables failed. Recreating..."); } } authTables = webServer.AuthTables; var authInterface = new AuthInterface <MDBUserLevel>(webServer); { //auth interface User admin = webServer.AuthTables.CheckAdminPresent(); if (mdb.Config.ReadBool("MusicDataBase", "LocalhostIsAdmin", false)) { authInterface.DefaultLocalhostUser = admin; } } this.LogInfo("Initializing FtpServer..."); ftpServer = new FtpServer(); ftpServer.CheckLogin += this.FtpServerCheckLogin; //add music dirs to ftp server SetFtpMusicFolders(mdb, ftpServer); int ftpPort = mdb.Config.ReadInt32("FtpServer", "Port", 8021); ftpServer.Listen(ftpPort); player = new DesktopPlayer(mdb, (long)MDBStreamType.JukeBob); player.Start(); this.LogInfo("Initializing WebServer..."); webServer.SessionMode = WebServerSessionMode.Cookie; webServer.SessionTimeout = TimeSpan.FromDays(1); webServer.PerformanceChecks = mdb.Config.ReadBool("WebServer", "PerformanceChecks", false); webServer.EnableExplain = mdb.Config.ReadBool("WebServer", "Explain", false); webServer.TransmitLayout = false; webServer.EnableTemplates = true; webServer.CheckAccess += WebServerCheckAccess; webServer.StaticFilesPath = mdb.WebFolder; //prepare rpc var avatarFolder = mdb.GetFolderConfig("MusicDataBase", "AvatarFolder", "avatar"); webServer.Register(new AvatarInterface(avatarFolder)); webServer.Register(authInterface); var webInterface = new WebInterface(mdb, webServer.AuthTables, player); webInterface.LogCollector.Level = LogLevel.Debug; webInterface.LogCollector.MaximumItemCount = 1000; webInterface.LogCollector.ExceptionMode = LogExceptionMode.Full; webServer.Register(webInterface); webServer.Register(new HostInterface(this)); //start server int webPort = mdb.Config.ReadInt32("WebServer", "Port", 8080); webServer.Listen(webPort); mdb.SetHostConfiguration(Environment.UserName + "." + Environment.MachineName, webPort, ftpPort, mdb.GetLocalAddresses()); //using (Streamer streamer = new Streamer(mdb, MDBStreamType.JukeBox)) broadcaster = new MDBBroadcaster(mdb); broadcaster.Start(); if (mdb.Config.ReadBool("Crawler", "RunAtStartup", false)) { webInterface.FileCrawler.Start(); } //main loop this.LogNotice("Entering main loop..."); while (!ServiceParameters.Shutdown) { ServiceParameters.WaitForShutdown(1000); //SetConsoleTitle(); } } finally { //cleanup broadcaster?.Dispose(); ftpServer?.Close(); player?.Stop(); player?.Dispose(); authTables?.Save(); authTables = null; mdb?.Save(); webServer?.Close(); } this.LogInfo("Shutdown completed."); Logger.Flush(); }