Пример #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="WaveBox.ApiHandler.Handlers.Lastfm"/> class.
        /// </summary>
        /// <param name='userId'>
        /// User identifier.
        /// </param>
        public Lastfm(User theUser)
        {
            user       = theUser;
            sessionKey = user.LastfmSession;

            // If the session key is prepended by 'token:', then the user has already generated a request token.
            // we should now try to get a session using that token.  If this fails, that simply means the user
            // has not granted us access yet.  If there is no session key at all, then we should request a token
            // and do nothing else.

            if (sessionKey == null)
            {
                this.CreateAuthUrl();
                logger.IfInfo(this.AuthUrl);
            }
            else if (sessionKey.Substring(0, 6) == "token:")
            {
                string token = sessionKey.Substring(6);
                this.GetSessionKeyAndUpdateUser(token);
            }
            else
            {
                sessionAuthenticated = true;
            }
        }
Пример #2
0
        public void startQueue()
        {
            queueThread = new Thread(delegate()
            {
                while (queueShouldLoop)
                {
                    lock (operationQueue)
                    {
                        if (operationQueue.Count > 0 && operationQueue.Peek() != null && operationQueue.Peek().IsReady)
                        {
                            try
                            {
                                currentOperation = operationQueue.Dequeue();
                            }
                            catch
                            {
                                currentOperation = null;
                            }

                            if (currentOperation != null)
                            {
                                currentOperation.Run();
                                logger.IfInfo(currentOperation.ToString() + " fired");
                            }
                        }
                    }

                    // Sleep to prevent a tight loop
                    Thread.Sleep(DEFAULT_PRECISION);
                }
            });
            queueThread.IsBackground = true;
            queueThread.Start();
        }
Пример #3
0
        /// <summary>
        /// Process performs a HLS transcode on a media item
        /// </summary>
        public void Process(UriWrapper uri, IHttpProcessor processor, User user)
        {
            // Verify ID received
            if (uri.Id == null)
            {
                processor.WriteJson(new TranscodeHlsResponse("Missing required parameter 'id'"));
                return;
            }

            try
            {
                // Get the media item associated with this id
                ItemType   itemType = Injection.Kernel.Get <IItemRepository>().ItemTypeForItemId((int)uri.Id);
                IMediaItem item     = null;
                if (itemType == ItemType.Song)
                {
                    item = Injection.Kernel.Get <ISongRepository>().SongForId((int)uri.Id);
                    logger.IfInfo("HLS transcoding for songs not currently supported");

                    // CURRENTLY DO NOT SUPPORT HLS STREAMING FOR SONGS
                    return;
                }
                else if (itemType == ItemType.Video)
                {
                    item = Injection.Kernel.Get <IVideoRepository>().VideoForId((int)uri.Id);
                    logger.IfInfo("Preparing video stream: " + item.FileName);
                }

                // Return an error if none exists
                if ((item == null) || (!File.Exists(item.FilePath())))
                {
                    processor.WriteJson(new TranscodeHlsResponse("No media item exists with ID: " + (int)uri.Id));
                    return;
                }

                // Generate the playlist file
                string   response       = null;
                string[] transQualities = uri.Parameters.ContainsKey("transQuality") ? uri.Parameters["transQuality"].Split(',') : new string[] { "Medium" };
                if (transQualities.Length == 1)
                {
                    // This is a single playlist
                    response = this.GeneratePlaylist(item, transQualities[0], uri);
                }
                else
                {
                    // This is a multi playlist
                    response = this.GenerateMultiPlaylist(item, transQualities, uri);
                }

                processor.WriteText(response, "application/x-mpegURL");
                logger.IfInfo("Successfully HLS transcoded file!");
            }
            catch (Exception e)
            {
                logger.Error(e);
            }
        }
Пример #4
0
        public void DatabaseSetup()
        {
            if (!File.Exists(DatabasePath))
            {
                try
                {
                    logger.IfInfo("Database file doesn't exist; Creating it : " + DATABASE_FILE_NAME);

                    // new filestream on the template
                    FileStream dbTemplate = new FileStream(DatabaseTemplatePath, FileMode.Open);

                    // a new byte array
                    byte[] dbData = new byte[dbTemplate.Length];

                    // read the template file into memory
                    dbTemplate.Read(dbData, 0, Convert.ToInt32(dbTemplate.Length));

                    // write it all out
                    System.IO.File.WriteAllBytes(DatabasePath, dbData);

                    // close the template file
                    dbTemplate.Close();
                }
                catch (Exception e)
                {
                    logger.Error(e);
                }
            }

            if (!File.Exists(QuerylogPath))
            {
                try
                {
                    logger.IfInfo("Query log database file doesn't exist; Creating it : " + QUERY_LOG_FILE_NAME);

                    // new filestream on the template
                    FileStream dbTemplate = new FileStream(QuerylogTemplatePath, FileMode.Open);

                    // a new byte array
                    byte[] dbData = new byte[dbTemplate.Length];

                    // read the template file into memory
                    dbTemplate.Read(dbData, 0, Convert.ToInt32(dbTemplate.Length));

                    // write it all out
                    System.IO.File.WriteAllBytes(QuerylogPath, dbData);

                    // close the template file
                    dbTemplate.Close();
                }
                catch (Exception e)
                {
                    logger.Error(e);
                }
            }
        }
Пример #5
0
        public void WriteSuccessHeader(long contentLength, string mimeType, IDictionary <string, string> customHeaders, DateTime lastModified, bool isPartial = false, string encoding = null)
        {
            StreamWriter outStream = new StreamWriter(new BufferedStream(this.Socket.GetStream()));
            string       status    = isPartial ? "HTTP/1.1 206 Partial Content" : "HTTP/1.1 200 OK";

            outStream.WriteLine(status);
            outStream.WriteLine("Date: " + DateTime.UtcNow.ToRFC1123());
            outStream.WriteLine("Server: WaveBox/" + WaveBoxService.BuildVersion);
            outStream.WriteLine("Last-Modified: " + lastModified.ToRFC1123());
            outStream.WriteLine("ETag: \"" + lastModified.ToETag() + "\"");
            outStream.WriteLine("Accept-Ranges: bytes");

            // Check request for compression
            if (encoding != null)
            {
                outStream.WriteLine("Content-Encoding: " + encoding);
            }

            if (contentLength >= 0)
            {
                outStream.WriteLine("Content-Length: " + contentLength);
            }

            outStream.WriteLine("Access-Control-Allow-Origin: *");
            outStream.WriteLine("Content-Type: " + mimeType);

            if ((object)customHeaders != null)
            {
                foreach (string key in customHeaders.Keys)
                {
                    outStream.WriteLine(key + ": " + customHeaders[key]);
                }
            }

            // Inject delayed headers
            foreach (string key in this.DelayedHeaders.Keys)
            {
                outStream.WriteLine(key + ": " + DelayedHeaders[key]);
            }

            outStream.WriteLine("Connection: close");
            outStream.WriteLine("");
            outStream.Flush();

            // Only log API responses
            if (HttpUrl.Contains("api"))
            {
                logger.IfInfo(String.Format("{0}, Length: {1}, Encoding: {2}, ETag: {3}, Last-Modified: {4}",
                                            status,
                                            contentLength,
                                            encoding ?? "none",
                                            lastModified.ToETag(),
                                            lastModified.ToRFC1123()
                                            ));
            }
        }
Пример #6
0
        public ITranscoder TranscodeSong(IMediaItem song, TranscodeType type, uint quality, bool isDirect, uint offsetSeconds, uint lengthSeconds)
        {
            if (!this.Running)
            {
                logger.Error("TranscodeService is not running!");
                return(null);
            }

            logger.IfInfo("Asked to transcode song: " + song.FileName);
            lock (transcoders) {
                ITranscoder transcoder = null;
                switch (type)
                {
                case TranscodeType.MP3:
                    transcoder = new FFMpegMP3Transcoder(song, quality, isDirect, offsetSeconds, lengthSeconds);
                    break;

                case TranscodeType.OGG:
                    transcoder = new FFMpegOGGTranscoder(song, quality, isDirect, offsetSeconds, lengthSeconds);
                    break;

                case TranscodeType.OPUS:
                    transcoder = new FFMpegOpusTranscoder(song, quality, isDirect, offsetSeconds, lengthSeconds);
                    break;

                case TranscodeType.AAC:
                    transcoder = new FFMpegAACTranscoder(song, quality, isDirect, offsetSeconds, lengthSeconds);
                    break;
                }

                transcoder = StartTranscoder(transcoder);

                return(transcoder);
            }
        }
Пример #7
0
        public bool Start()
        {
            // FOR NOW: Use the pre-existing delayed operation queues.  Once more work has been done, cron will
            // run a unified timer and spin each of these off as needed
            logger.IfInfo("Scheduling and starting all cronjobs...");

            // Start user and session purge operation
            UserPurge.Queue.queueOperation(new UserPurgeOperation(0));
            UserPurge.Queue.startQueue();

            logger.IfInfo("All cronjobs started!");

            return(true);
        }
Пример #8
0
        /// <summary>
        /// Process returns a new session key for this user upon successful login
        /// <summary>
        public void Process(UriWrapper uri, IHttpProcessor processor, User user)
        {
            logger.IfInfo(String.Format("Authenticated user, generated new session: [user: {0}, key: {1}]", user.UserName, user.SessionId));

            processor.WriteJson(new LoginResponse(null, user.SessionId));
            return;
        }
Пример #9
0
        /// <summary>
        /// The main instance of WaveBox which runs the server.  Creates necessary directories, initializes
        /// database and settings, and starts all associated services.
        /// </summary>
        public void Start()
        {
            logger.IfInfo("Initializing WaveBox " + WaveBoxService.BuildVersion + " on " + WaveBoxService.OS.ToDescription() + " platform...");

            // Initialize ImageMagick
            try {
                ImageMagickInterop.WandGenesis();
            } catch (Exception e) {
                logger.Error("Error loading ImageMagick DLL:", e);
            }

            // Create directory for WaveBox's root path, if it doesn't exist
            string rootDir = ServerUtility.RootPath();

            if (!Directory.Exists(rootDir))
            {
                Directory.CreateDirectory(rootDir);
            }

            // Create directory for WaveBox Web UI themes, if it doesn't exist
            string themeDir = ServerUtility.ExecutablePath() + "themes/";

            if (!Directory.Exists(themeDir))
            {
                Directory.CreateDirectory(themeDir);
            }

            // Perform initial setup of Settings, Database
            Injection.Kernel.Get <IDatabase>().DatabaseSetup();
            Injection.Kernel.Get <IServerSettings>().SettingsSetup();

            // Start services
            try {
                // Initialize factory, so it can register all services for deployment
                ServiceFactory.Initialize();

                // Start user defined services
                if (Injection.Kernel.Get <IServerSettings>().Services != null)
                {
                    ServiceManager.AddList(Injection.Kernel.Get <IServerSettings>().Services);
                }
                else
                {
                    logger.Warn("No services specified in configuration file!");
                }

                ServiceManager.StartAll();
            } catch (Exception e) {
                logger.Warn("Could not start one or more WaveBox services, please check services in your configuration");
                logger.Warn(e);
            }

            // Temporary: create test and admin user
            Injection.Kernel.Get <IUserRepository>().CreateUser("test", "test", Role.User, null);
            Injection.Kernel.Get <IUserRepository>().CreateUser("admin", "admin", Role.Admin, null);

            return;
        }
Пример #10
0
        private void DeviceFound(object sender, DeviceEventArgs args)
        {
            logger.IfInfo("Device Found");

            this.Status = NatStatus.DeviceFound;

            // This is the upnp enabled router
            this.Device = args.Device;

            // Create a mapping to forward external port to local port
            try {
                Device.CreatePortMap(new Mapping(Protocol.Tcp, Injection.Kernel.Get <IServerSettings>().Port, Injection.Kernel.Get <IServerSettings>().Port));
                this.Status = NatStatus.PortForwardedSuccessfully;
            } catch (Exception e) {
                this.Status = NatStatus.PortForwardingFailed;
                logger.Error("Port mapping failed", e);
            }
        }
Пример #11
0
 public void ExtendWaitOrRestart()
 {
     if (state == DelayedOperationState.Queued)
     {
         ResetWait();
         logger.IfInfo("Extending wait period.");
     }
     else if (state == DelayedOperationState.Running)
     {
         Restart();
     }
 }
Пример #12
0
        /// <summary>
        /// Process returns a copy of the media database, and can be used to return SQL deltas to update
        /// the local copy of the media database
        /// </summary>
        public void Process(UriWrapper uri, IHttpProcessor processor, User user)
        {
            // If ID set, return all queries >= this id
            if (uri.Id != null)
            {
                processor.WriteJson(new DatabaseResponse(null, Injection.Kernel.Get <IDatabase>().QueryLogsSinceId((int)uri.Id)));
                return;
            }

            // No id parameter, so send down the whole backup database
            long   databaseLastQueryId = -1;
            string databaseFileName    = DatabaseBackup.Backup(out databaseLastQueryId);

            // Verify database filename present
            if ((object)databaseFileName == null)
            {
                processor.WriteErrorHeader();
                return;
            }

            try
            {
                // Read in entire database file
                Stream stream      = new FileStream(ServerUtility.RootPath() + databaseFileName, FileMode.Open, FileAccess.Read);
                long   length      = stream.Length;
                int    startOffset = 0;

                // Handle the Range header to start from later in the file if connection interrupted
                if (processor.HttpHeaders.ContainsKey("Range"))
                {
                    string range = (string)processor.HttpHeaders["Range"];
                    string start = range.Split(new char[] { '-', '=' })[1];
                    logger.IfInfo("Connection retried.  Resuming from " + start);
                    startOffset = Convert.ToInt32(start);
                }

                // We send the last query id as a custom header
                IDictionary <string, string> customHeader = new Dictionary <string, string>();
                customHeader["WaveBox-LastQueryId"] = databaseLastQueryId.ToString();

                // Send the database file
                processor.WriteFile(stream, startOffset, length, "application/octet-stream", customHeader, true, new FileInfo(ServerUtility.RootPath() + databaseFileName).LastWriteTimeUtc);
                stream.Close();
            }
            catch
            {
                // Send JSON on error
                processor.WriteJson(new DatabaseResponse("Could not open backup database " + databaseFileName, null));
            }

            return;
        }
Пример #13
0
        /// <summary>
        /// Process logs this user out and destroys their current session
        /// <summary>
        public void Process(UriWrapper uri, IHttpProcessor processor, User user)
        {
            // Destroy session
            if (user.DeleteSession(user.SessionId))
            {
                logger.IfInfo(String.Format("Logged out user, destroyed session: [user: {0}, key: {1}]", user.UserName, user.SessionId));
                processor.WriteJson(new LogoutResponse(null, user.SessionId));
                return;
            }

            processor.WriteJson(new LogoutResponse("Failed to destroy user session", user.SessionId));
            return;
        }
Пример #14
0
        /// <summary>
        /// Start user purge operation
        /// </summary>
        public static void Start()
        {
            // Delete all expired users
            foreach (User u in Injection.Kernel.Get <IUserRepository>().ExpiredUsers())
            {
                if (u.Delete())
                {
                    logger.IfInfo(String.Format("Purged expired user: [id: {0}, name: {1}]", u.UserId, u.UserName));
                }
                else
                {
                    logger.IfInfo(String.Format("Failed to purge expired user: [id: {0}, name: {1}]", u.UserId, u.UserName));
                }
            }

            // Grab a list of all sessions
            var sessions = Injection.Kernel.Get <ISessionRepository>().AllSessions();

            // Grab the current UNIX time
            long unixTime = DateTime.UtcNow.ToUnixTime();

            // Purge any sessions which have not been updated in a predefined period of time
            foreach (Session s in sessions)
            {
                // Check current time and last update, purge if the diff is higher than SessionTimeout minutes
                if ((unixTime - Convert.ToInt32(s.UpdateTime)) >= (Injection.Kernel.Get <IServerSettings>().SessionTimeout * 60))
                {
                    if (s.Delete())
                    {
                        logger.IfInfo(String.Format("Purged session: [id: {0}, user: {1}]", s.RowId, s.UserId));
                    }
                    else
                    {
                        logger.IfInfo(String.Format("Failed to purge session: [id: {0}, user: {1}]", s.RowId, s.UserId));
                    }
                }
            }
        }
        public override void Start()
        {
            logger.IfInfo("------------- ARTIST ART SCAN -------------");

            Stopwatch testTotalScanTime = new Stopwatch();

            testTotalScanTime.Start();

            // Create the cache directory if it doesn't exist yet
            if (!Directory.Exists(cachePath))
            {
                Directory.CreateDirectory(cachePath);
            }

            // Keep a set of all MusicBrainz IDs known to WaveBox
            ISet <string> musicBrainzIds = new HashSet <string>();

            // Find artists and album artists missing art
            IArtistRepository artistRepository = Injection.Kernel.Get <IArtistRepository>();
            IList <Artist>    allArtists       = artistRepository.AllArtists();

            foreach (Artist artist in allArtists)
            {
                string musicBrainzId = artist.MusicBrainzId;
                if (musicBrainzId != null)
                {
                    if (!File.Exists(this.ArtPathForMusicBrainzId(musicBrainzId)))
                    {
                        musicBrainzIds.Add(musicBrainzId);
                    }
                }
            }

            IAlbumArtistRepository albumArtistRepository = Injection.Kernel.Get <IAlbumArtistRepository>();
            IList <AlbumArtist>    allAlbumArtists       = albumArtistRepository.AllAlbumArtists();

            foreach (AlbumArtist albumArtist in allAlbumArtists)
            {
                string musicBrainzId = albumArtist.MusicBrainzId;
                if (musicBrainzId != null)
                {
                    if (!File.Exists(this.ArtPathForMusicBrainzId(musicBrainzId)))
                    {
                        musicBrainzIds.Add(musicBrainzId);
                    }
                }
            }

            // Scan all MusicBrainz IDs collected by WaveBox
            int downloadCount = this.ScanIds(musicBrainzIds);

            testTotalScanTime.Stop();

            logger.IfInfo("------------- ARTIST ART SCAN -------------");
            logger.IfInfo("items retrieved: " + downloadCount);
            logger.IfInfo("total scan time: " + testTotalScanTime.ElapsedMilliseconds + "ms");
            logger.IfInfo("-------------------------------------------");
        }
Пример #16
0
 /// <summary>
 /// Use reflection to scan for all available IService-implementing classes, register them as valid services
 /// to be created by factory
 /// <summary>
 public static void Initialize()
 {
     try {
         // Grab all available types which implement IService
         foreach (Type t in Assembly.GetExecutingAssembly().GetTypes().Where(x => x.GetInterfaces().Contains(typeof(IService))))
         {
             // Discover and instantiate all available services
             IService instance = (IService)Activator.CreateInstance(t);
             logger.IfInfo("Discovered service: " + instance.Name + " -> " + t);
             services.Add(instance);
         }
     } catch (Exception e) {
         logger.Error(e);
     }
 }
Пример #17
0
        public void CancelTranscode()
        {
            if (TranscodeProcess != null)
            {
                logger.IfInfo("Cancelling transcode for " + Item.FileName);

                // Kill the process
                TranscodeProcess.Kill();
                TranscodeProcess = null;

                // Wait for the thread to die
                TranscodeThread.Join();
                TranscodeThread = null;

                // Set the state
                State = TranscodeState.Canceled;

                // Inform the delegate
                if ((object)TranscoderDelegate != null)
                {
                    TranscoderDelegate.TranscodeFailed(this);
                }
            }
        }
Пример #18
0
        /// <summary>
        /// Use reflection to scan for all available IApiHandler-implementing classes, register them as valid API
        /// handlers to be created by factory
        /// <summary>
        public void Initialize()
        {
            try {
                // Initialize list
                apiHandlers = new List <IApiHandler>();

                // Grab all available types which implement IApiHandler
                foreach (Type t in Assembly.GetExecutingAssembly().GetTypes().Where(x => x.GetInterfaces().Contains(typeof(IApiHandler))))
                {
                    // Discover and instantiate all available apiHandlers
                    IApiHandler instance = (IApiHandler)Activator.CreateInstance(t);
                    logger.IfInfo("Discovered API: " + instance.Name + " -> " + t);
                    this.apiHandlers.Add(instance);
                }
            } catch (Exception e) {
                logger.Error(e);
            }
        }
Пример #19
0
        public void RemoveMediaItemAtIndexes(IList <int> indices)
        {
            ISQLiteConnection conn = null;

            try
            {
                conn = Injection.Kernel.Get <IDatabase>().GetSqliteConnection();
                conn.BeginTransaction();

                // delete the items at the indicated indices
                foreach (int index in indices)
                {
                    logger.IfInfo("Deleting row at ItemPosition: " + index);
                    conn.ExecuteLogged("DELETE FROM PlaylistItem WHERE PlaylistId = ? AND ItemPosition = ?", PlaylistId, index);
                }

                // select the id of all members of the playlist
                var result = conn.Query <PlaylistItem>("SELECT * FROM PlaylistItem WHERE PlaylistId = ? ORDER BY ItemPosition", PlaylistId);

                // update the values of each index in the array to be the new index
                for (int i = 0; i < result.Count; i++)
                {
                    var item = result[i];

                    conn.ExecuteLogged("UPDATE PlaylistItem SET ItemPosition = ? WHERE PlaylistItemId = ? AND PlaylistId = ?", i, item.PlaylistItemId, PlaylistId);
                }

                conn.Commit();
            }
            catch (Exception e)
            {
                if (!ReferenceEquals(conn, null))
                {
                    conn.Rollback();
                }
                logger.Error(e);
            }
            finally
            {
                Injection.Kernel.Get <IDatabase>().CloseSqliteConnection(conn);
            }
        }
Пример #20
0
        public int?GetParentFolderId(string path)
        {
            string parentFolderPath = Directory.GetParent(path).FullName;

            int?pFolderId = null;

            int id = this.database.GetScalar <int>("SELECT FolderId FROM Folder WHERE FolderPath = ?", parentFolderPath);

            if (id == 0)
            {
                logger.IfInfo("No db result for parent folder.	Constructing parent folder object.");
                Folder f = FolderForPath(parentFolderPath);
                f.InsertFolder(false);
                pFolderId = f.FolderId;
            }
            else
            {
                pFolderId = id;
            }

            return(pFolderId);
        }
Пример #21
0
        /// <summary>
        /// Process produces a direct file stream of the requested media file
        /// </summary>
        public void Process(UriWrapper uri, IHttpProcessor processor, User user)
        {
            // Verify ID received
            if (uri.Id == null)
            {
                processor.WriteJson(new StreamResponse("Missing required parameter 'id'"));
                return;
            }

            logger.IfInfo("Starting file streaming sequence");

            // Try to get seconds
            float seconds = 0f;

            if (uri.Parameters.ContainsKey("seconds"))
            {
                float.TryParse(uri.Parameters["seconds"], out seconds);
            }

            try {
                // Get the media item associated with this id
                ItemType   itemType = Injection.Kernel.Get <IItemRepository>().ItemTypeForItemId((int)uri.Id);
                IMediaItem item     = null;
                if (itemType == ItemType.Song)
                {
                    item = Injection.Kernel.Get <ISongRepository>().SongForId((int)uri.Id);
                    logger.IfInfo("Preparing audio stream: " + item.FileName);
                }
                else if (itemType == ItemType.Video)
                {
                    item = Injection.Kernel.Get <IVideoRepository>().VideoForId((int)uri.Id);
                    logger.IfInfo("Preparing video stream: " + item.FileName);
                }

                // Return an error if none exists
                if ((item == null) || (!File.Exists(item.FilePath())))
                {
                    processor.WriteJson(new StreamResponse("No media item exists with ID: " + (int)uri.Id));
                    return;
                }

                // Prepare file stream
                Stream stream      = item.File();
                long   length      = stream.Length;
                int    startOffset = 0;
                long?  limitToSize = null;

                if (seconds > 0)
                {
                    // Guess the file position based on the seconds requested
                    // this is just rough now, but will be improved to take into account the header size
                    float percent = seconds / (float)item.Duration;
                    if (percent < 1f)
                    {
                        startOffset = (int)(item.FileSize * percent);
                        logger.IfInfo("seconds: " + seconds + "  Resuming from " + startOffset);
                    }
                }
                else if (processor.HttpHeaders.ContainsKey("Range"))
                {
                    // Handle the Range header to start from later in the file
                    string range = (string)processor.HttpHeaders["Range"];
                    var    split = range.Split(new char[] { '-', '=' });
                    string start = split[1];
                    string end   = split.Length > 2 ? split[2] : null;

                    logger.IfInfo("Range header: " + range + "  Resuming from " + start);
                    startOffset = Convert.ToInt32(start);
                    if (!ReferenceEquals(end, null) && end != String.Empty)
                    {
                        limitToSize = (Convert.ToInt64(end) + 1) - startOffset;
                    }
                }

                // Send the file
                processor.WriteFile(stream, startOffset, length, item.FileType.MimeType(), null, true, new FileInfo(item.FilePath()).LastWriteTimeUtc, limitToSize);
                stream.Close();

                logger.IfInfo("Successfully streamed file!");
            } catch (Exception e) {
                logger.Error(e);
            }
        }
Пример #22
0
        private byte[] ResizeImageMagick(Stream stream, int width, double blurSigma)
        {
            // new wand
            IntPtr wand = ImageMagickInterop.NewWand();

            // get original image
            byte[] b = new byte[stream.Length];
            stream.Read(b, 0, (int)stream.Length);
            bool success = ImageMagickInterop.ReadImageBlob(wand, b);

            if (success)
            {
                int sourceWidth  = (int)ImageMagickInterop.GetWidth(wand);
                int sourceHeight = (int)ImageMagickInterop.GetHeight(wand);

                float nPercent  = 0;
                float nPercentW = 0;
                float nPercentH = 0;

                nPercentW = ((float)width / (float)sourceWidth);
                nPercentH = ((float)width / (float)sourceHeight);

                if (nPercentH < nPercentW)
                {
                    nPercent = nPercentH;
                }
                else
                {
                    nPercent = nPercentW;
                }

                int destWidth  = (int)(sourceWidth * nPercent);
                int destHeight = (int)(sourceHeight * nPercent);

                Stopwatch s = new Stopwatch();
                s.Start();
                ImageMagickInterop.ResizeImage(wand, (IntPtr)destWidth, (IntPtr)destHeight, ImageMagickInterop.Filter.Lanczos, 1.0);
                s.Stop();
                logger.IfInfo("resize image time: " + s.ElapsedMilliseconds + "ms");

                Stopwatch s1 = new Stopwatch();
                if (blurSigma > 0.0)
                {
                    s1.Start();
                    ImageMagickInterop.BlurImage(wand, 0.0, blurSigma);
                    s1.Stop();
                    logger.IfInfo("blur image time: " + s1.ElapsedMilliseconds + "ms");
                }

                logger.IfInfo("total image time: " + (s.ElapsedMilliseconds + s1.ElapsedMilliseconds) + "ms");

                byte[] newData = ImageMagickInterop.GetImageBlob(wand);

                // cleanup
                ImageMagickInterop.DestroyWand(wand);
                return(newData);
            }
            else
            {
                return(b);
            }
        }
Пример #23
0
        public override void Start()
        {
            Stopwatch sw = new Stopwatch();

            logger.IfInfo("---------------- ORPHAN SCAN ----------------");
            logger.IfInfo("Folders:");
            sw.Start();
            this.CheckFolders();
            sw.Stop();
            logger.IfInfo("Done, elapsed: " + sw.ElapsedMilliseconds + "ms");

            logger.IfInfo("Songs:");
            sw.Restart();
            this.CheckSongs();
            sw.Stop();
            logger.IfInfo("Done, elapsed: " + sw.ElapsedMilliseconds + "ms");

            logger.IfInfo("Artists:");
            sw.Restart();
            this.CheckArtists();
            sw.Stop();
            logger.IfInfo("Done, elapsed: " + sw.ElapsedMilliseconds + "ms");

            logger.IfInfo("AlbumArtists:");
            sw.Restart();
            this.CheckAlbumArtists();
            sw.Stop();
            logger.IfInfo("Done, elapsed: " + sw.ElapsedMilliseconds + "ms");

            logger.IfInfo("Albums:");
            sw.Restart();
            this.CheckAlbums();
            sw.Stop();
            logger.IfInfo("Done, elapsed: " + sw.ElapsedMilliseconds + "ms");

            logger.IfInfo("Genres:");
            sw.Restart();
            this.CheckGenres();
            sw.Stop();
            logger.IfInfo("Done, elapsed: " + sw.ElapsedMilliseconds + "ms");

            logger.IfInfo("Videos:");
            sw.Restart();
            this.CheckVideos();
            sw.Stop();
            logger.IfInfo("Done, elapsed: " + sw.ElapsedMilliseconds + "ms");

            logger.IfInfo("DONE, TOTAL ELAPSED: " + (totalExistsTime / 10000) + "ms");
            logger.IfInfo("---------------------------------------------");
        }
Пример #24
0
        /// <summary>
        /// Process a Last.fm API request
        /// </summary>
        public void Process(UriWrapper uri, IHttpProcessor processor, User user)
        {
            // Create Last.fm object for this user
            Lastfm lfm = new Lastfm(user);

            // Pull URL parameters for Last.fm integration
            string eve = null;

            uri.Parameters.TryGetValue("event", out eve);

            if (uri.Action == null || uri.Action == "auth")
            {
                // If not authenticated, pass back authorization URL
                if (!lfm.SessionAuthenticated)
                {
                    processor.WriteJson(new ScrobbleResponse(null, lfm.AuthUrl));
                }
                else
                {
                    // Else, already authenticated
                    processor.WriteJson(new ScrobbleResponse("LFMAlreadyAuthenticated"));
                }
                return;
            }

            // If Last.fm is not authenticated, provide an authorization URL
            if (!lfm.SessionAuthenticated)
            {
                logger.IfInfo("You must authenticate before you can scrobble.");

                processor.WriteJson(new ScrobbleResponse("LFMNotAuthenticated", lfm.AuthUrl));
                return;
            }

            // Create list of scrobble data
            IList <LfmScrobbleData> scrobbles = new List <LfmScrobbleData>();

            // Get Last.fm API enumerations
            LfmScrobbleType scrobbleType = Lastfm.ScrobbleTypeForString(uri.Action);

            // On invalid scrobble type, return error JSON
            if (scrobbleType == LfmScrobbleType.INVALID)
            {
                processor.WriteJson(new ScrobbleResponse("LFMInvalidScrobbleType"));
                return;
            }

            // On now playing scrobble type
            if (scrobbleType == LfmScrobbleType.NOWPLAYING)
            {
                // Ensure ID specified for scrobble
                if (uri.Id == null)
                {
                    processor.WriteJson(new ScrobbleResponse("LFMNoIdSpecifiedForNowPlaying"));
                    return;
                }

                // Add successful scrobble to list, submit
                scrobbles.Add(new LfmScrobbleData((int)uri.Id, null));
                lfm.Scrobble(scrobbles, scrobbleType);
            }
            // Else, unknown scrobble event
            else
            {
                // On null event, return error JSON
                if (eve == null)
                {
                    processor.WriteJson(new ScrobbleResponse("LFMNoEventSpecifiedForScrobble"));
                    return;
                }

                // Ensure input is a comma-separated pair
                string[] input = eve.Split(',');
                if ((input.Length % 2) != 0)
                {
                    processor.WriteJson(new ScrobbleResponse("LFMInvalidInput"));
                    return;
                }

                // Add scrobbles from input data pairs
                int i = 0;
                while (i < input.Length)
                {
                    scrobbles.Add(new LfmScrobbleData(int.Parse(input[i]), long.Parse(input[i + 1])));
                    i = i + 2;
                }
            }

            // Scrobble all plays
            string  result = lfm.Scrobble(scrobbles, scrobbleType);
            dynamic resp   = null;

            // No response, service must be offline
            if (result == null)
            {
                processor.WriteJson(new ScrobbleResponse("LFMServiceOffline"));
                return;
            }

            // If result is not null, store deserialize and store it
            try
            {
                resp = JsonConvert.DeserializeObject(result);
            }
            catch (Exception e)
            {
                logger.Error(e);
            }

            // Check for nowplaying or scrobbles fields
            if ((resp.nowplaying != null) || (resp.scrobbles != null))
            {
                // Write blank scrobble response
                processor.WriteJson(new ScrobbleResponse());
                return;
            }
            // Write error JSON if it exists
            else if (resp.error != null)
            {
                processor.WriteJson(new ScrobbleResponse(string.Format("LFM{0}: {1}", resp.error, resp.message)));
                return;
            }
        }
Пример #25
0
        public override void Run()
        {
            try {
                string ffmpegArguments = "-loglevel quiet -i \"" + Item.FilePath() + "\" -f wav -";
                logger.IfInfo("Forking the process");
                logger.IfInfo("ffmpeg " + ffmpegArguments);

                // Create the ffmpeg process
                FfmpegProcess = new Process();
                FfmpegProcess.StartInfo.FileName               = "ffmpeg";
                FfmpegProcess.StartInfo.Arguments              = ffmpegArguments;
                FfmpegProcess.StartInfo.UseShellExecute        = false;
                FfmpegProcess.StartInfo.RedirectStandardOutput = true;
                FfmpegProcess.StartInfo.RedirectStandardError  = true;

                // Create the opusenc object
                logger.IfInfo("opusenc " + Arguments);
                TranscodeProcess = new Process();
                TranscodeProcess.StartInfo.FileName               = "opusenc";
                TranscodeProcess.StartInfo.Arguments              = Arguments;
                TranscodeProcess.StartInfo.UseShellExecute        = false;
                TranscodeProcess.StartInfo.RedirectStandardInput  = true;
                TranscodeProcess.StartInfo.RedirectStandardOutput = true;
                TranscodeProcess.StartInfo.RedirectStandardError  = false;

                var buffer = new byte[8192];
                FfmpegProcess.Start();
                TranscodeProcess.Start();

                var input        = new BinaryWriter(TranscodeProcess.StandardInput.BaseStream);
                int totalWritten = 0;

                while (true)
                {
                    int bytesRead = FfmpegProcess.StandardOutput.BaseStream.Read(buffer, 0, 8192);
                    totalWritten += bytesRead;
                    if (bytesRead > 0)
                    {
                        input.Write(buffer, 0, bytesRead);
                    }

                    if (bytesRead == 0 && FfmpegProcess.HasExited)
                    {
                        input.Close();
                        FfmpegProcess.Close();
                        break;
                    }
                }

                logger.IfInfo("Waiting for processes to finish");

                // Block until done
                TranscodeProcess.WaitForExit();

                logger.IfInfo("Process finished");
            } catch (Exception e) {
                logger.IfInfo("\t" + "Failed to start transcode process " + e);

                try {
                    TranscodeProcess.Kill();
                    TranscodeProcess.Close();
                } catch { /* do nothing if killing the process fails */ }

                try {
                    FfmpegProcess.Kill();
                    FfmpegProcess.Close();
                } catch { /* do nothing if killing the process fails */ }

                // Set the state
                State = TranscodeState.Failed;

                // Inform the delegate
                if ((object)TranscoderDelegate != null)
                {
                    TranscoderDelegate.TranscodeFailed(this);
                }

                return;
            }

            if (TranscodeProcess != null)
            {
                int exitValue = TranscodeProcess.ExitCode;
                logger.IfInfo("Exit value " + exitValue);

                if (exitValue == 0)
                {
                    State = TranscodeState.Finished;

                    if ((object)TranscoderDelegate != null)
                    {
                        TranscoderDelegate.TranscodeFinished(this);
                    }
                }
                else
                {
                    State = TranscodeState.Failed;

                    if ((object)TranscoderDelegate != null)
                    {
                        TranscoderDelegate.TranscodeFailed(this);
                    }
                }
            }
        }
Пример #26
0
        public override void Start()
        {
            // Stopwatches to track scanning times
            Stopwatch testTotalScanTime       = new Stopwatch();
            Stopwatch testArtistScanTime      = new Stopwatch();
            Stopwatch testAlbumArtistScanTime = new Stopwatch();

            // Dictionary of artists and existing IDs
            IDictionary <string, string> existingIds = new Dictionary <string, string>();

            // List of artists who don't have IDs
            IList <Artist> artistsMissingId = new List <Artist>();

            logger.IfInfo("------------- MUSICBRAINZ SCAN -------------");

            testTotalScanTime.Start();

            // Find artists and album artists missing ids, and all existing musicbrainz ids, to avoid extra lookups
            IArtistRepository artistRepository = Injection.Kernel.Get <IArtistRepository>();
            IList <Artist>    allArtists       = artistRepository.AllArtists();

            foreach (Artist artist in allArtists)
            {
                if (artist.MusicBrainzId == null)
                {
                    artistsMissingId.Add(artist);
                }
                else
                {
                    existingIds[artist.ArtistName] = artist.MusicBrainzId;
                }
            }

            IList <AlbumArtist> albumArtistsMissingId = new List <AlbumArtist>();

            IAlbumArtistRepository albumArtistRepository = Injection.Kernel.Get <IAlbumArtistRepository>();
            IList <AlbumArtist>    allAlbumArtists       = albumArtistRepository.AllAlbumArtists();

            foreach (AlbumArtist albumArtist in allAlbumArtists)
            {
                if (albumArtist.MusicBrainzId == null)
                {
                    albumArtistsMissingId.Add(albumArtist);
                }
                else
                {
                    existingIds[albumArtist.AlbumArtistName] = albumArtist.MusicBrainzId;
                }
            }

            testArtistScanTime.Start();
            int artistCount = this.ScanArtists(existingIds, artistsMissingId);

            testArtistScanTime.Stop();

            testAlbumArtistScanTime.Start();
            int albumArtistCount = this.ScanAlbumArtists(existingIds, albumArtistsMissingId);

            testAlbumArtistScanTime.Stop();

            testTotalScanTime.Stop();

            logger.IfInfo("------------- MUSICBRAINZ SCAN -------------");
            logger.IfInfo("total scan time: " + testTotalScanTime.ElapsedMilliseconds + "ms");
            logger.IfInfo("---------------------------------------------");
            logger.IfInfo("artist IDs retrieved: " + artistCount);
            logger.IfInfo("artist scan time: " + testArtistScanTime.ElapsedMilliseconds + "ms");
            logger.IfInfo("albumArtist IDs retrieved: " + albumArtistCount);
            logger.IfInfo("albumArtist scan time: " + testAlbumArtistScanTime.ElapsedMilliseconds + "ms");
            logger.IfInfo("---------------------------------------------");
        }
Пример #27
0
        /// <summary>
        /// Add a new service, by name, to the manager, optionally starting it automatically
        /// </summary>
        public static bool Add(string name, bool autostart = false)
        {
            // Ensure lowercase names
            name = name.ToLower();

            // Check if service is disabled
            if (name[0] == '!')
            {
                logger.IfInfo("Skipping disabled service: " + name);
                return(true);
            }

            // Check if service is already present in list
            if (Services.Any(x => x.Name == name))
            {
                logger.IfInfo("Skipping duplicate service: " + name);
                return(false);
            }

            // Generate service from name
            IService service = ServiceFactory.CreateService(name);

            // Ensure service was valid
            if ((object)service == null)
            {
                logger.Error("Unknown service: " + name);
                return(false);
            }

            // Add service to list
            Services.Add(service);

            // Autostart if requested
            if (autostart)
            {
                if (!Start(service))
                {
                    logger.Error("Failed to autostart service: " + service.Name);
                    return(false);
                }
            }

            return(true);
        }
Пример #28
0
        /// <summary>
        /// Process returns a page from the WaveBox web interface
        /// </summary>
        public void Process(UriWrapper uri, IHttpProcessor processor, User user)
        {
            // Store root path, return index by default
            string path = webRoot;

            // Check for and apply theme path
            if (Injection.Kernel.Get <IServerSettings>().Theme == null)
            {
                logger.Error("No theme set in WaveBox configuration, cannot serve Web UI");

                // File not found
                processor.WriteErrorHeader();
                return;
            }

            // Append theme path to web root
            path += Injection.Kernel.Get <IServerSettings>().Theme;

            // Validate theme path
            if (!Directory.Exists(path))
            {
                logger.Error("Invalid theme '" + Injection.Kernel.Get <IServerSettings>().Theme + "' set in WaveBox configuration, cannot serve Web UI");

                // File not found
                processor.WriteErrorHeader();
                return;
            }

            if (uri.UriParts.Count == 0)
            {
                // No path, so return the home page
                path += Path.DirectorySeparatorChar + "index.html";

                // Ensure theme contains an index
                if (!File.Exists(path))
                {
                    logger.Error("Theme '" + Injection.Kernel.Get <IServerSettings>().Theme + "' missing required file index.html");

                    // File not found
                    processor.WriteErrorHeader();
                    return;
                }
            }
            else
            {
                // Iterate UriParts to send web pages
                for (int i = 0; i < uri.UriParts.Count; i++)
                {
                    string pathPart = uri.UriParts[i];
                    if (pathPart.Length > 0 && pathPart[0] == '.')
                    {
                        // Do not return hidden files/folders
                        processor.WriteErrorHeader();
                        return;
                    }
                    else
                    {
                        path += Path.DirectorySeparatorChar + uri.UriParts[i];
                    }
                }
            }

            // Make sure the file exists
            if (!File.Exists(path))
            {
                logger.IfInfo("File does not exist: " + path);

                // File not found
                processor.WriteErrorHeader();
                return;
            }

            // Serve up files inside html directory
            FileStream file        = new FileStream(path, FileMode.Open, FileAccess.Read);
            int        startOffset = 0;

            // Handle the Range header to start from later in the file
            if (processor.HttpHeaders.ContainsKey("Range"))
            {
                string range = (string)processor.HttpHeaders["Range"];
                string start = range.Split(new char[] { '-', '=' })[1];
                logger.IfInfo("Connection retried.  Resuming from " + start);
                startOffset = Convert.ToInt32(start);
            }

            long length = file.Length - startOffset;

            processor.WriteFile(file, startOffset, length, HttpHeader.MimeTypeForExtension(Path.GetExtension(path)), null, true, new FileInfo(path).LastWriteTimeUtc);
            file.Close();
        }
Пример #29
0
        /// <summary>
        /// Process returns an AlbumArtistsResponse containing a list of artists, albums, and songs
        /// </summary>
        public void Process(UriWrapper uri, IHttpProcessor processor, User user)
        {
            // Lists of artists, albums, songs to be returned via handler
            IList <AlbumArtist>      albumArtists     = new List <AlbumArtist>();
            IList <Album>            albums           = new List <Album>();
            IList <Song>             songs            = new List <Song>();
            Dictionary <string, int> counts           = new Dictionary <string, int>();
            PairList <string, int>   sectionPositions = new PairList <string, int>();

            // Optional Last.fm info
            string lastfmInfo = null;

            // Check if an ID was passed
            if (uri.Id != null)
            {
                // Add artist by ID to the list
                AlbumArtist a = Injection.Kernel.Get <IAlbumArtistRepository>().AlbumArtistForId((int)uri.Id);
                albumArtists.Add(a);

                // Add artist's albums to response
                albums = a.ListOfAlbums();
                counts.Add("albums", albums.Count);

                // If requested, add artist's songs to response
                if (uri.Parameters.ContainsKey("includeSongs") && uri.Parameters["includeSongs"].IsTrue())
                {
                    songs = a.ListOfSongs();
                    counts.Add("songs", songs.Count);
                }
                else
                {
                    counts.Add("songs", a.ListOfSongs().Count);
                }

                // If requested, add artist's Last.fm info to response
                if (uri.Parameters.ContainsKey("lastfmInfo") && uri.Parameters["lastfmInfo"].IsTrue())
                {
                    logger.IfInfo("Querying Last.fm for artist: " + a.AlbumArtistName);
                    try
                    {
                        lastfmInfo = Lastfm.GetAlbumArtistInfo(a);
                        logger.IfInfo("Last.fm query complete!");
                    }
                    catch (Exception e)
                    {
                        logger.Error("Last.fm query failed!");
                        logger.Error(e);
                    }
                }

                // Get favorites count if available
                if (a.AlbumArtistId != null)
                {
                    int favoriteCount = Injection.Kernel.Get <IFavoriteRepository>().FavoritesForAlbumArtistId(a.AlbumArtistId, user.UserId).Count;
                    counts.Add("favorites", favoriteCount);
                }
                else
                {
                    counts.Add("favorites", 0);
                }
            }
            // Check for a request for range of artists
            else if (uri.Parameters.ContainsKey("range"))
            {
                string[] range = uri.Parameters["range"].Split(',');

                // Ensure valid range was parsed
                if (range.Length != 2)
                {
                    processor.WriteJson(new AlbumArtistsResponse("Parameter 'range' requires a valid, comma-separated character tuple", null, null, null, null, null, null));
                    return;
                }

                // Validate as characters
                char start, end;
                if (!Char.TryParse(range[0], out start) || !Char.TryParse(range[1], out end))
                {
                    processor.WriteJson(new AlbumArtistsResponse("Parameter 'range' requires characters which are single alphanumeric values", null, null, null, null, null, null));
                    return;
                }

                // Grab range of artists
                albumArtists = Injection.Kernel.Get <IAlbumArtistRepository>().RangeAlbumArtists(start, end);
            }

            // Check for a request to limit/paginate artists, like SQL
            // Note: can be combined with range or all artists
            if (uri.Parameters.ContainsKey("limit") && uri.Id == null)
            {
                string[] limit = uri.Parameters["limit"].Split(',');

                // Ensure valid limit was parsed
                if (limit.Length < 1 || limit.Length > 2)
                {
                    processor.WriteJson(new AlbumArtistsResponse("Parameter 'limit' requires a single integer, or a valid, comma-separated integer tuple", null, null, null, null, null, null));
                    return;
                }

                // Validate as integers
                int index    = 0;
                int duration = Int32.MinValue;
                if (!Int32.TryParse(limit[0], out index))
                {
                    processor.WriteJson(new AlbumArtistsResponse("Parameter 'limit' requires a valid integer start index", null, null, null, null, null, null));
                    return;
                }

                // Ensure positive index
                if (index < 0)
                {
                    processor.WriteJson(new AlbumArtistsResponse("Parameter 'limit' requires a non-negative integer start index", null, null, null, null, null, null));
                    return;
                }

                // Check for duration
                if (limit.Length == 2)
                {
                    if (!Int32.TryParse(limit[1], out duration))
                    {
                        processor.WriteJson(new AlbumArtistsResponse("Parameter 'limit' requires a valid integer duration", null, null, null, null, null, null));
                        return;
                    }

                    // Ensure positive duration
                    if (duration < 0)
                    {
                        processor.WriteJson(new AlbumArtistsResponse("Parameter 'limit' requires a non-negative integer duration", null, null, null, null, null, null));
                        return;
                    }
                }

                // Check if results list already populated by range
                if (albumArtists.Count > 0)
                {
                    // No duration?  Return just specified number of artists
                    if (duration == Int32.MinValue)
                    {
                        albumArtists = albumArtists.Skip(0).Take(index).ToList();
                    }
                    else
                    {
                        // Else, return artists starting at index, up to count duration
                        albumArtists = albumArtists.Skip(index).Take(duration).ToList();
                    }
                }
                else
                {
                    // If no artists in list, grab directly using model method
                    albumArtists = Injection.Kernel.Get <IAlbumArtistRepository>().LimitAlbumArtists(index, duration);
                }
            }

            // Finally, if no artists already in list, send the whole list
            if (albumArtists.Count == 0)
            {
                albumArtists     = Injection.Kernel.Get <IAlbumArtistRepository>().AllAlbumArtists();
                sectionPositions = Utility.SectionPositionsFromSortedList(new List <IGroupingItem>(albumArtists.Select(c => (IGroupingItem)c)));
            }

            // Send it!
            processor.WriteJson(new AlbumArtistsResponse(null, albumArtists, albums, songs, counts, lastfmInfo, sectionPositions));
            return;
        }
Пример #30
0
        public bool Register(User user, IMediaItem m, long?timestamp = null)
        {
            // Begin building object
            NowPlaying nowPlaying = new NowPlaying();

            // Store user object
            nowPlaying.User = user;

            // Check if client sent a timestamp (if not, use current time)
            if (timestamp == null)
            {
                timestamp = DateTime.UtcNow.ToUnixTime();
            }

            // Capture play time to set up automatic unregister on playback end
            nowPlaying.StartTime = timestamp;
            nowPlaying.EndTime   = timestamp + Convert.ToInt32(m.Duration);

            // Start a timer, set to elapse and unregister this song exactly when it should finish playback
            nowPlaying.Timer          = new Timer(Convert.ToInt32(m.Duration) * 1000);
            nowPlaying.Timer.Elapsed += delegate { this.Unregister(user.UserName, user.CurrentSession.ClientName); };
            nowPlaying.Timer.Start();

            // Capture media item's type
            Type mediaType = m.GetType();

            // Unregister any items with matching user and client
            this.Unregister(user.UserName, user.CurrentSession.ClientName);

            // Handling for Song items
            if (mediaType.IsAssignableFrom(typeof(Song)))
            {
                // Box IMediaItem to Song
                Song s = (Song)m;
                nowPlaying.MediaItem = s;

                // Report now playing
                playing.Add(nowPlaying);
                logger.IfInfo(String.Format("{0}@{1} Now Playing: {2} - {3} - {4} [{5}]",
                                            user.UserName,
                                            user.CurrentSession.ClientName,
                                            s.ArtistName,
                                            s.AlbumName,
                                            s.SongName,
                                            Convert.ToInt32(s.Duration).ToTimeString()
                                            ));
            }
            // Handling for Video items
            else if (mediaType.IsAssignableFrom(typeof(Video)))
            {
                // Box IMediaItem to Video
                Video v = (Video)m;
                nowPlaying.MediaItem = v;

                // Report now playing
                playing.Add(nowPlaying);
                logger.IfInfo(String.Format("{0}@{1} Now Watching: {2} [{3}]",
                                            user.UserName,
                                            user.CurrentSession.ClientName,
                                            v.FileName,
                                            Convert.ToInt32(v.Duration).ToTimeString()
                                            ));
            }
            else
            {
                // Report unsupported media types
                logger.IfInfo("Media type not supported, skipping now playing registration...");
            }

            return(true);
        }