Esempio n. 1
0
        public async Task Invoke(HttpContext context)
        {
            Logger.LogInformation($"{context.Request.Path}{context.Request.QueryString}\n{context.Request.Headers["Range"]}");

            if (context.Request.Path.HasValue && context.Request.Path.Value.StartsWith("/API/"))
            {
                string[] pathElements = context.Request.Path.Value.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
                int      i            = 0;
                pathElements.ToList().ForEach(dr =>
                {
                    context.Response.Headers[$"X-API-Path-{i}"] = dr;
                });
                context.Request.Query.ToList().ForEach(dr =>
                {
                    context.Response.Headers[$"X-API-QS-{dr.Key}"] = dr.Value;
                });

                if (pathElements.Length > 1 && pathElements[1].Equals("Stream") /* && context.Request.Query.ContainsKey("id")*/)
                {
                    if (context.Request.Query.ContainsKey("id"))
                    {
                        int fileID = -1;
                        if (!int.TryParse(context.Request.Query["id"], out fileID))
                        {
                            context.Response.StatusCode = 404;
                            return;
                        }
                        Models.File musicFile = MusicContext.Files
                                                .Include(dr => dr.Library)
                                                .Where(dr => dr.ID == fileID).FirstOrDefault();
                        if (musicFile != null)
                        {
                            string fullPath = Path.Combine(musicFile.Library.Path, musicFile.Path);
                            if (System.IO.File.Exists(fullPath))
                            {
                                PlaybackData dat       = null;
                                bool         newStream = false;
                                lock (Buffer)
                                {
                                    if (Buffer.ContainsKey(fileID.ToString()))
                                    {
                                        lock (dat = Buffer[fileID.ToString()])
                                        {
                                            dat.RefreshAccessTime();
                                        }
                                    }
                                    else
                                    {
                                        Buffer[fileID.ToString()] = dat = new PlaybackData();
                                        newStream = true;
                                    }
                                }

                                if (newStream)
                                {
                                    {// note how long the file is for output aproximation
                                        dat.Seconds = 600;
                                        dat.bitrate = 320;
                                    }


                                    dat.contentLengthCounter = 0;
                                    dat.writing = true;
                                    (new Thread(() =>
                                    {
                                        string argsP = $"-i \"{fullPath}\" -map 0:0 -b:a {dat.bitrate}k -v 0 -f mp3 -";
                                        Process ffmpeg;
                                        ffmpeg = new Process();
                                        ffmpeg.StartInfo.WorkingDirectory = Options.ffmpeg;
                                        ffmpeg.StartInfo.FileName = "\"" + Options.ffmpeg + "ffmpeg.exe\"";
                                        ffmpeg.StartInfo.Arguments = argsP;
                                        ffmpeg.StartInfo.RedirectStandardOutput = true;
                                        //ffmpeg.StartInfo.CreateNoWindow = true;
                                        ffmpeg.StartInfo.UseShellExecute = false;
                                        ffmpeg.Start();
                                        StreamReader reader = ffmpeg.StandardOutput;

                                        byte[] buffer = new byte[32768];
                                        int read;
                                        while ((read = reader.BaseStream.Read(buffer, 0, buffer.Length)) > 0)
                                        {
                                            dat.dataStream.Write(buffer, 0, read);
                                            dat.contentLengthCounter += read;
                                        }
                                        Logger.LogInformation("Compleated Buffering Audio File");
                                        Logger.LogInformation($"Length of data is {dat.contentLengthCounter}");
                                        dat.writing = false;
                                    })).Start();
                                }

                                int    defaultStripeSize          = 1024 * 256;
                                int    stillTranscodingStripeSize = 1024 * 16;
                                int    stripeSize      = defaultStripeSize;
                                string totalSizeString = "*";
                                //string totalSizeString = "999999999999";
                                //string totalSizeString = "";
                                int    totalSize        = -1;
                                string startIndexString = "0";
                                string endIndexString   = null;
                                if (context.Request.Headers.ContainsKey("Range"))
                                {
                                    string   range          = context.Request.Headers["Range"];
                                    string[] range_eq_split = range.Split(new char[] { '=' });
                                    string[] range_parts    = range_eq_split[1].Split(new char[] { '-' });
                                    startIndexString = range_parts[0];
                                    if (range_parts.Length > 0 && range_parts[1].Length > 0)
                                    {
                                        endIndexString = range_parts[1];
                                    }
                                }
                                int startIndex = int.Parse(startIndexString);

                                if (endIndexString != null)
                                {
                                    int requestedStripSize = int.Parse(endIndexString) - startIndex + 1;
                                    stripeSize = Math.Min(stripeSize, requestedStripSize);
                                }

                                int startingIndex = startIndex;

                                // wait until at least enough data is read
                                // this area is a little sketchy due to threading but consider that old values are OK here and we aren't writing
                                while (dat.writing && dat.contentLengthCounter < (startingIndex + stillTranscodingStripeSize))
                                {
                                    Thread.Sleep(100);
                                }

                                lock (dat)
                                {
                                    if (dat.writing)
                                    {
                                        stripeSize = Math.Min(stripeSize, stillTranscodingStripeSize);
                                    }

                                    stripeSize = Math.Min(stripeSize, dat.contentLengthCounter - startingIndex);
                                    if (!dat.writing) // we're done writing to the stream so clearly it contains the entire file
                                    {
                                        totalSize       = dat.contentLengthCounter;
                                        totalSizeString = totalSize.ToString();
                                    }
                                    //else // failed hack to get browsers to download partial
                                    //{
                                    //    totalSizeString = (startIndex + stripeSize * 2).ToString();
                                    //}
                                    else if (dat.Seconds > 0)
                                    {
                                        totalSizeString = ((int)((dat.Seconds * (dat.bitrate * 1000)) / 8)).ToString();
                                    }
                                }

                                //check stripeSize isn't negative (can only happen if fully transcoded else the system would avoid it)
                                //check startIndexString isn't greater than totalSize
                                //check startingIndex + stripeSize isn't greater than totalSize
                                if (totalSize > 0 && startIndex >= totalSize)
                                {
                                    context.Response.StatusCode  = 416;
                                    context.Response.ContentType = "audio/mpeg";
                                    context.Response.Headers["Accept-Ranges"] = "bytes";
                                    context.Response.Headers["Content-Range"] = $"bytes {startIndex}-*/{totalSizeString}";
                                    //context.Response.Headers["Content-Length"] = stripeSize.ToString();
                                }
                                else
                                {
                                    //if (totalSize >= 0 && (startIndex + stripeSize) >= totalSize)
                                    //{
                                    //    context.Response.StatusCode = 206;
                                    //}
                                    //else
                                    //{
                                    //    context.Response.StatusCode = 206;
                                    //}

                                    context.Response.StatusCode = 206;

                                    context.Response.ContentType = "audio/mpeg";
                                    context.Response.Headers["Accept-Ranges"]  = "bytes";
                                    context.Response.Headers["Content-Range"]  = $"bytes {startIndex}-{startIndex + stripeSize - 1}/{totalSizeString}";
                                    context.Response.Headers["Content-Length"] = stripeSize.ToString();

                                    //context.Response.Headers["Transfer-Encoding"] = @"chunked";
                                    //context.Response.Headers["Cache-control"] = "";
                                    //context.Response.Headers["Pragma"] = "";

                                    //X-Content-Duration: 63.23
                                    lock (dat)
                                    {
                                        byte[] outputBuffer = new byte[stripeSize];
                                        dat.dataStream.readPosition = startIndex;
                                        dat.dataStream.Read(outputBuffer, 0, stripeSize);
                                        dat.RefreshAccessTime();
                                        context.Response.Body.Write(outputBuffer, 0, stripeSize);
                                    }
                                }


                                //MemoryStream memStream = new MemoryStream();
                                //await reader.BaseStream.CopyToAsync(memStream);
                                //memStream.Position = 0;
                                //Response.ContentLength = memStream.Length;
                                //await memStream.CopyToAsync(Response.Body);

                                //await reader.BaseStream.CopyToAsync(Response.Body);

                                //(new Thread(() => {
                                //    memStream
                                //})).Start();

                                //memStream.Position = 0;

                                //ffmpeg.WaitForExit();
                                //ffmpeg.Kill(); //ffmpeg.close();

                                //Response.Headers["Content-Range"] = "bytes 0-1/*";



                                //Response.ContentLength = contentLengthCounter;
                                //Response.Headers["Content-Range"] = $"bytes 0-1/{contentLengthCounter}";

                                //{
                                //    byte[] buffer = new byte[32768];
                                //    int read;
                                //    while (((read = dat.dataStream.Read(buffer, 0, buffer.Length)) > 0) || dat.writing)
                                //    {
                                //        if (read == 0)
                                //        {
                                //            Thread.Sleep(100);
                                //            continue;
                                //        }
                                //        context.Response.Body.Write(buffer, 0, read);
                                //        lock(dat)
                                //        {
                                //            dat.RefreshAccessTime();
                                //        }
                                //    }
                                //    Logger.LogInformation("Compleated Sending Buffering Audio File");
                                //}

                                //return new FileStreamResult(memStream, HttpContext.Response.ContentType);
                                //return new FileStreamResult(reader.BaseStream, HttpContext.Response.ContentType);
                                //return new FileStreamResult(System.IO.File.OpenRead(fullPath), HttpContext.Response.ContentType);
                                //return new PhysicalFileResult(fullPath, HttpContext.Response.ContentType);
                            }
                            else
                            {
                                context.Response.StatusCode = 404;
                                return;
                            }
                        }
                        else
                        {
                            context.Response.StatusCode = 404;
                            return;
                        }
                    }
                    else
                    {
                        context.Response.StatusCode = 404;
                        return;
                    }
                }
                else
                {
                    await _next.Invoke(context);
                }
                //if (context.Response.Headers.Keys.Contains("X-API-Steam"))
                //{
                //    context.Response.Headers["X-API-SteamID"] = context.Response.Headers["X-API-Steam"];
                //    context.Response.Headers.Remove("X-API-Steam");
                //    return;
                //}

                //return;
            }
            else
            {
                await _next.Invoke(context);
            }
        }
Esempio n. 2
0
        void recursivePathDive(Library lib, string dirPath)
        {
            string[] Directories = Directory.GetDirectories(dirPath, @"*", SearchOption.TopDirectoryOnly);
            string[] Files       = Directory.GetFiles(dirPath, @"*", SearchOption.TopDirectoryOnly);

            foreach (string FullPath in Files)
            {
                string SubPath             = FullPath.Substring(lib.Path.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
                Alexandria.Models.File tmp = MusicContext.Files.Where(dr => dr.Library.Equals(lib) && dr.Path == SubPath).FirstOrDefault();
                if (tmp == null)
                {
                    // do we want to track this file?
                    string FileExtension = ExtensionsToMonitor.Where(dr => Path.GetFileName(FullPath).EndsWith(dr)).FirstOrDefault();
                    if (FileExtension == null)
                    {
                        ConsoleColor tmpConCol = Console.ForegroundColor;
                        Console.ForegroundColor = ConsoleColor.Gray;
                        Console.WriteLine($"Skip\t{lib.Path} | {SubPath}");
                        Console.ForegroundColor = tmpConCol;
                        continue;
                    }

                    {
                        ConsoleColor tmpConCol = Console.ForegroundColor;
                        Console.ForegroundColor = ConsoleColor.White;
                        Console.WriteLine($"New\t{lib.Path} | {SubPath}");
                        Console.ForegroundColor = tmpConCol;
                    }

                    // gather file data
                    // add to db
                    Alexandria.Models.File newFile = new Alexandria.Models.File()
                    {
                        Library      = lib,
                        Archival     = false,
                        FileModified = System.IO.File.GetLastWriteTimeUtc(FullPath),
                        RecordAdded  = DateTime.UtcNow,
                        Path         = SubPath,
                        Tags         = new List <TagAssociation>()
                    };
                    //TagAdder tagAdderRecord = new TagAdder() { Timestamp = DateTime.UtcNow, User = systemAccount };
                    //TagAssociation newTagAssoc = new TagAssociation() { Tag = unTaggedTag, Added = new List<TagAdder>() };
                    //newTagAssoc.Added.Add(tagAdderRecord);
                    //newFile.Tags.Add(newTagAssoc);

                    newFile.AddTag(unTaggedTag, systemAccount);

                    MusicContext.Files.Add(newFile);

                    MusicContext.SaveChanges();
                }
                else
                {
                    /*
                     * // skip file unless modified date has changed
                     *
                     * // do we want to track this file?
                     * string FileExtension = ExtensionsToMonitor.Where(dr => Path.GetFileName(FullPath).EndsWith(dr)).FirstOrDefault();
                     * if (FileExtension == null) continue;
                     *
                     * DateTime FileModDate = System.IO.File.GetLastWriteTimeUtc(FullPath);
                     * if(FileModDate > tmp.Modified)
                     * {
                     *  Console.WriteLine($"Changed\t{lib.Path} | {SubPath}");
                     * }
                     */
                    {
                        ConsoleColor tmpConCol = Console.ForegroundColor;
                        Console.ForegroundColor = ConsoleColor.DarkGray;
                        Console.WriteLine($"Known\t{lib.Path} | {SubPath}");
                        Console.ForegroundColor = tmpConCol;
                    }
                }
            }

            foreach (string Directory in Directories)
            {
                recursivePathDive(lib, Directory);
            }
        }