Initial commit
fix repeat added simple keyboard control add preloading tracks add plain view ("api") fix memory leak, add streaming responsive viewport Mobile web capable
225
.gitignore
vendored
Normal file
|
@ -0,0 +1,225 @@
|
|||
# The following command works for downloading when using Git for Windows:
|
||||
# curl -LOf http://gist.githubusercontent.com/kmorcinek/2710267/raw/.gitignore
|
||||
#
|
||||
# Download this file using PowerShell v3 under Windows with the following comand:
|
||||
# Invoke-WebRequest https://gist.githubusercontent.com/kmorcinek/2710267/raw/ -OutFile .gitignore
|
||||
#
|
||||
# or wget:
|
||||
# wget --no-check-certificate http://gist.githubusercontent.com/kmorcinek/2710267/raw/.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
# build folder is nowadays used for build scripts and should not be ignored
|
||||
#build/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.log
|
||||
*.scc
|
||||
|
||||
# OS generated files #
|
||||
.DS_Store*
|
||||
Icon?
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
*.ncrunch*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.Publish.xml
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.[Pp]ublish.xml
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
modulesbin/
|
||||
tempbin/
|
||||
|
||||
# EPiServer Site file (VPP)
|
||||
AppData/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# vim
|
||||
*.txt~
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Temp files when opening LibreOffice on ubuntu
|
||||
.~lock.*
|
||||
|
||||
# svn
|
||||
.svn
|
||||
|
||||
# CVS - Source Control
|
||||
**/CVS/
|
||||
|
||||
# Remainings from resolving conflicts in Source Control
|
||||
*.orig
|
||||
|
||||
# SQL Server files
|
||||
**/App_Data/*.mdf
|
||||
**/App_Data/*.ldf
|
||||
**/App_Data/*.sdf
|
||||
|
||||
|
||||
#LightSwitch generated files
|
||||
GeneratedArtifacts/
|
||||
_Pvt_Extensions/
|
||||
ModelManifest.xml
|
||||
|
||||
# =========================
|
||||
# Windows detritus
|
||||
# =========================
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Mac desktop service store files
|
||||
.DS_Store
|
||||
|
||||
# SASS Compiler cache
|
||||
.sass-cache
|
||||
|
||||
# Visual Studio 2014 CTP
|
||||
**/*.sln.ide
|
||||
|
||||
# Visual Studio temp something
|
||||
.vs/
|
||||
|
||||
# dotnet stuff
|
||||
project.lock.json
|
||||
|
||||
# VS 2015+
|
||||
*.vc.vc.opendb
|
||||
*.vc.db
|
||||
|
||||
# Rider
|
||||
.idea/
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/
|
||||
|
||||
# Output folder used by Webpack or other FE stuff
|
||||
**/node_modules/*
|
||||
**/wwwroot/*
|
||||
|
||||
# SpecFlow specific
|
||||
*.feature.cs
|
||||
*.feature.xlsx.*
|
||||
*.Specs_*.html
|
||||
|
||||
#####
|
||||
# End of core ignore list, below put you custom 'per project' settings (patterns or path)
|
||||
#####
|
26
Pages/Error.cshtml
Normal file
|
@ -0,0 +1,26 @@
|
|||
@page
|
||||
@model ErrorModel
|
||||
@{
|
||||
ViewData["Title"] = "Error";
|
||||
}
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (Model.ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
23
Pages/Error.cshtml.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace webmusic.Pages
|
||||
{
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public class ErrorModel : PageModel
|
||||
{
|
||||
public string RequestId { get; set; }
|
||||
|
||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
public void OnGet()
|
||||
{
|
||||
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
|
||||
}
|
||||
}
|
||||
}
|
31
Pages/Index.cshtml
Normal file
|
@ -0,0 +1,31 @@
|
|||
@page
|
||||
@using System.Web
|
||||
@model IndexModel
|
||||
@{
|
||||
ViewData["Title"] = "webmusic";
|
||||
}
|
||||
@if (Model.path.Contains(".."))
|
||||
{
|
||||
return;
|
||||
}
|
||||
<h2>@Model.displaypath <span id="state"></span> <span id="flags"></span></h2>
|
||||
<a class="action-muted">[..]</a>
|
||||
<a href="?@Model.path_oneup" class="entry-muted cfont"> Go back</a><br/>
|
||||
<a class="action-muted">[--]</a>
|
||||
<a href="#" onclick="downloadm3u()" class="entry-muted cfont"> Download m3u</a><br/><br/>
|
||||
@foreach (var dir in Model.dirs)
|
||||
{
|
||||
<a class="action" href="#">[--]</a>
|
||||
<a href="?@Model.path/@dir"> @dir</a>
|
||||
<br/>
|
||||
}
|
||||
@foreach (var file in Model.files)
|
||||
{
|
||||
var jspath = Model.Encode(Model.fullpath);
|
||||
var jsfile = jspath + "/" + Model.Encode(file);
|
||||
|
||||
<script>queue.push('@Html.Raw(jsfile)')</script>
|
||||
<a class="action" href="@Html.Raw(Model.Encode(Model.fullpath+"/"+file))" download>[DL]</a>
|
||||
<a href="#" onclick="playSong('@Html.Raw(jsfile)')"> @file</a>
|
||||
<br/>
|
||||
}
|
68
Pages/Index.cshtml.cs
Normal file
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
|
||||
namespace webmusic.Pages
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
public static string root = "music";
|
||||
public string path = "";
|
||||
public string displaypath = "";
|
||||
public string path_oneup = "";
|
||||
public string fullpath = "";
|
||||
public List<string> dirs = new List<string>();
|
||||
public List<string> files = new List<string>();
|
||||
public void OnGet()
|
||||
{
|
||||
if (Request.QueryString.HasValue)
|
||||
path = HttpUtility.UrlDecode(Request.QueryString.Value.Remove(0,1));
|
||||
if (path.Contains(".."))
|
||||
{
|
||||
Response.Redirect("/Error");
|
||||
return;
|
||||
}
|
||||
path_oneup = Regex.Match(path, @".*(?=\/)").Value;
|
||||
fullpath = root + path;
|
||||
displaypath = string.IsNullOrWhiteSpace(path) ? "/" : path;
|
||||
dirs = Directory.GetDirectories(fullpath).Select(Path.GetFileName).ToList();
|
||||
dirs.Sort();
|
||||
files = Directory.GetFiles(fullpath).Select(Path.GetFileName).ToList();
|
||||
files.RemoveAll(p => p.EndsWith(".m3u"));
|
||||
files.Sort(new NumericComparer());
|
||||
}
|
||||
|
||||
public string Encode(string str)
|
||||
{
|
||||
return str.Replace("\"", "%22").Replace("'", "%27")
|
||||
.Replace("?", "%3F").Replace("&", "%26")
|
||||
.Replace(" ", "%20");
|
||||
}
|
||||
|
||||
public class NumericComparer : IComparer<string>
|
||||
{
|
||||
public int Compare(string x, string y)
|
||||
{
|
||||
var regex = new Regex(@"^\d+");
|
||||
|
||||
// run the regex on both strings
|
||||
var xRegexResult = regex.Match(x);
|
||||
var yRegexResult = regex.Match(y);
|
||||
|
||||
// check if they are both numbers
|
||||
if (xRegexResult.Success && yRegexResult.Success)
|
||||
{
|
||||
return int.Parse(xRegexResult.Value).CompareTo(int.Parse(yRegexResult.Value));
|
||||
}
|
||||
|
||||
// otherwise return as string comparison
|
||||
return string.Compare(x, y, StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
Pages/Shared/_Layout.cshtml
Normal file
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<title>Music</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Ubuntu+Mono" rel="stylesheet">
|
||||
<script src="/howler.core.js"></script>
|
||||
<script src="/webmusic.js"></script>
|
||||
<link href="/webmusic.css" rel="stylesheet"/>
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/favicon/apple-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/favicon/apple-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/favicon/apple-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/favicon/apple-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/favicon/apple-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/favicon/apple-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/favicon/apple-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/favicon/apple-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="/favicon/android-icon-192x192.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="/favicon/favicon-96x96.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/favicon/ms-icon-144x144.png">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
@RenderBody()
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
3
Pages/_ViewImports.cshtml
Normal file
|
@ -0,0 +1,3 @@
|
|||
@using webmusic
|
||||
@namespace webmusic.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
3
Pages/_ViewStart.cshtml
Normal file
|
@ -0,0 +1,3 @@
|
|||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
18
Pages/plain.cshtml
Normal file
|
@ -0,0 +1,18 @@
|
|||
@page
|
||||
@using System.Web
|
||||
@model IndexModel
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
@if (Model.path.Contains(".."))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@foreach (var dir in Model.dirs)
|
||||
{
|
||||
@Html.Raw(dir+"\n")
|
||||
}
|
||||
@foreach (var file in Model.files)
|
||||
{
|
||||
@Html.Raw(file+"\n")
|
||||
}
|
61
Pages/plain.cshtml.cs
Normal file
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
|
||||
namespace webmusic.Pages
|
||||
{
|
||||
public class PlainModel : PageModel
|
||||
{
|
||||
public static string root = "music";
|
||||
public string path = "";
|
||||
public string displaypath = "";
|
||||
public string path_oneup = "";
|
||||
public string fullpath = "";
|
||||
public List<string> dirs = new List<string>();
|
||||
public List<string> files = new List<string>();
|
||||
public void OnGet()
|
||||
{
|
||||
if (Request.QueryString.HasValue)
|
||||
path = HttpUtility.UrlDecode(Request.QueryString.Value.Remove(0,1));
|
||||
if (path.Contains(".."))
|
||||
{
|
||||
Response.Redirect("/Error");
|
||||
return;
|
||||
}
|
||||
path_oneup = Regex.Match(path, @".*(?=\/)").Value;
|
||||
fullpath = root + path;
|
||||
displaypath = string.IsNullOrWhiteSpace(path) ? "/" : path;
|
||||
dirs = Directory.GetDirectories(fullpath).Select(Path.GetFileName).ToList();
|
||||
dirs.Sort();
|
||||
files = Directory.GetFiles(fullpath).Select(Path.GetFileName).ToList();
|
||||
files.RemoveAll(p => p.EndsWith(".m3u"));
|
||||
files.Sort(new NumericComparer());
|
||||
}
|
||||
|
||||
public class NumericComparer : IComparer<string>
|
||||
{
|
||||
public int Compare(string x, string y)
|
||||
{
|
||||
var regex = new Regex(@"^\d+");
|
||||
|
||||
// run the regex on both strings
|
||||
var xRegexResult = regex.Match(x);
|
||||
var yRegexResult = regex.Match(y);
|
||||
|
||||
// check if they are both numbers
|
||||
if (xRegexResult.Success && yRegexResult.Success)
|
||||
{
|
||||
return int.Parse(xRegexResult.Value).CompareTo(int.Parse(yRegexResult.Value));
|
||||
}
|
||||
|
||||
// otherwise return as string comparison
|
||||
return string.Compare(x, y, StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
Program.cs
Normal file
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace webmusic
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseWebRoot(".")
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
}
|
20
Properties/launchSettings.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:63053",
|
||||
"sslPort": 44395
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"webmusic": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
65
Startup.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace webmusic
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.Configure<CookiePolicyOptions>(options =>
|
||||
{
|
||||
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
|
||||
options.CheckConsentNeeded = context => true;
|
||||
options.MinimumSameSitePolicy = SameSiteMode.None;
|
||||
});
|
||||
|
||||
|
||||
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||
{
|
||||
var provider = new FileExtensionContentTypeProvider();
|
||||
provider.Mappings[".flac"] = "audio/flac";
|
||||
provider.Mappings[".m3u"] = "audio/m3u";
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseExceptionHandler("/Error");
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseStaticFiles(new StaticFileOptions()
|
||||
{
|
||||
ContentTypeProvider = provider
|
||||
});
|
||||
app.UseCookiePolicy();
|
||||
|
||||
app.UseMvc();
|
||||
}
|
||||
}
|
||||
}
|
6
app.config
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<gcServer enabled="true"/>
|
||||
</runtime>
|
||||
</configuration>
|
9
appsettings.Development.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Warning",
|
||||
"System": "Warning",
|
||||
"Microsoft": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
8
appsettings.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
BIN
favicon/android-icon-144x144.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
favicon/android-icon-192x192.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
favicon/android-icon-36x36.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
favicon/android-icon-48x48.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
favicon/android-icon-72x72.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
favicon/android-icon-96x96.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
favicon/apple-icon-114x114.png
Normal file
After Width: | Height: | Size: 7 KiB |
BIN
favicon/apple-icon-120x120.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
favicon/apple-icon-144x144.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
favicon/apple-icon-152x152.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
favicon/apple-icon-180x180.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
favicon/apple-icon-57x57.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
favicon/apple-icon-60x60.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
favicon/apple-icon-72x72.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
favicon/apple-icon-76x76.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
favicon/apple-icon-precomposed.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
favicon/apple-icon.png
Normal file
After Width: | Height: | Size: 13 KiB |
2
favicon/browserconfig.xml
Normal file
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>
|
BIN
favicon/favicon-16x16.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
favicon/favicon-32x32.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
favicon/favicon-96x96.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
favicon/favicon.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
favicon/ms-icon-144x144.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
favicon/ms-icon-150x150.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
favicon/ms-icon-310x310.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
favicon/ms-icon-70x70.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
162
howler.core.js
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*!
|
||||
* howler.js v2.1.2
|
||||
* howlerjs.com
|
||||
*
|
||||
* (c) 2013-2019, James Simpson of GoldFire Studios
|
||||
* goldfirestudios.com
|
||||
*
|
||||
* MIT License
|
||||
*/(function(){'use strict';var HowlerGlobal=function(){this.init();};HowlerGlobal.prototype={init:function(){var self=this||Howler;self._counter=1000;self._html5AudioPool=[];self.html5PoolSize=10;self._codecs={};self._howls=[];self._muted=false;self._volume=1;self._canPlayEvent='canplaythrough';self._navigator=(typeof window!=='undefined'&&window.navigator)?window.navigator:null;self.masterGain=null;self.noAudio=false;self.usingWebAudio=true;self.autoSuspend=true;self.ctx=null;self.autoUnlock=true;self._setup();return self;},volume:function(vol){var self=this||Howler;vol=parseFloat(vol);if(!self.ctx){setupAudioContext();}
|
||||
if(typeof vol!=='undefined'&&vol>=0&&vol<=1){self._volume=vol;if(self._muted){return self;}
|
||||
if(self.usingWebAudio){self.masterGain.gain.setValueAtTime(vol,Howler.ctx.currentTime);}
|
||||
for(var i=0;i<self._howls.length;i++){if(!self._howls[i]._webAudio){var ids=self._howls[i]._getSoundIds();for(var j=0;j<ids.length;j++){var sound=self._howls[i]._soundById(ids[j]);if(sound&&sound._node){sound._node.volume=sound._volume*vol;}}}}
|
||||
return self;}
|
||||
return self._volume;},mute:function(muted){var self=this||Howler;if(!self.ctx){setupAudioContext();}
|
||||
self._muted=muted;if(self.usingWebAudio){self.masterGain.gain.setValueAtTime(muted?0:self._volume,Howler.ctx.currentTime);}
|
||||
for(var i=0;i<self._howls.length;i++){if(!self._howls[i]._webAudio){var ids=self._howls[i]._getSoundIds();for(var j=0;j<ids.length;j++){var sound=self._howls[i]._soundById(ids[j]);if(sound&&sound._node){sound._node.muted=(muted)?true:sound._muted;}}}}
|
||||
return self;},unload:function(){var self=this||Howler;for(var i=self._howls.length-1;i>=0;i--){self._howls[i].unload();}
|
||||
if(self.usingWebAudio&&self.ctx&&typeof self.ctx.close!=='undefined'){self.ctx.close();self.ctx=null;setupAudioContext();}
|
||||
return self;},codecs:function(ext){return(this||Howler)._codecs[ext.replace(/^x-/,'')];},_setup:function(){var self=this||Howler;self.state=self.ctx?self.ctx.state||'suspended':'suspended';self._autoSuspend();if(!self.usingWebAudio){if(typeof Audio!=='undefined'){try{var test=new Audio();if(typeof test.oncanplaythrough==='undefined'){self._canPlayEvent='canplay';}}catch(e){self.noAudio=true;}}else{self.noAudio=true;}}
|
||||
try{var test=new Audio();if(test.muted){self.noAudio=true;}}catch(e){}
|
||||
if(!self.noAudio){self._setupCodecs();}
|
||||
return self;},_setupCodecs:function(){var self=this||Howler;var audioTest=null;try{audioTest=(typeof Audio!=='undefined')?new Audio():null;}catch(err){return self;}
|
||||
if(!audioTest||typeof audioTest.canPlayType!=='function'){return self;}
|
||||
var mpegTest=audioTest.canPlayType('audio/mpeg;').replace(/^no$/,'');var checkOpera=self._navigator&&self._navigator.userAgent.match(/OPR\/([0-6].)/g);var isOldOpera=(checkOpera&&parseInt(checkOpera[0].split('/')[1],10)<33);self._codecs={mp3:!!(!isOldOpera&&(mpegTest||audioTest.canPlayType('audio/mp3;').replace(/^no$/,''))),mpeg:!!mpegTest,opus:!!audioTest.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/,''),ogg:!!audioTest.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''),oga:!!audioTest.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''),wav:!!audioTest.canPlayType('audio/wav; codecs="1"').replace(/^no$/,''),aac:!!audioTest.canPlayType('audio/aac;').replace(/^no$/,''),caf:!!audioTest.canPlayType('audio/x-caf;').replace(/^no$/,''),m4a:!!(audioTest.canPlayType('audio/x-m4a;')||audioTest.canPlayType('audio/m4a;')||audioTest.canPlayType('audio/aac;')).replace(/^no$/,''),mp4:!!(audioTest.canPlayType('audio/x-mp4;')||audioTest.canPlayType('audio/mp4;')||audioTest.canPlayType('audio/aac;')).replace(/^no$/,''),weba:!!audioTest.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,''),webm:!!audioTest.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,''),dolby:!!audioTest.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/,''),flac:!!(audioTest.canPlayType('audio/x-flac;')||audioTest.canPlayType('audio/flac;')).replace(/^no$/,'')};return self;},_unlockAudio:function(){var self=this||Howler;if(self._audioUnlocked||!self.ctx){return;}
|
||||
self._audioUnlocked=false;self.autoUnlock=false;if(!self._mobileUnloaded&&self.ctx.sampleRate!==44100){self._mobileUnloaded=true;self.unload();}
|
||||
self._scratchBuffer=self.ctx.createBuffer(1,1,22050);var unlock=function(e){for(var i=0;i<self.html5PoolSize;i++){try{var audioNode=new Audio();audioNode._unlocked=true;self._releaseHtml5Audio(audioNode);}catch(e){self.noAudio=true;}}
|
||||
for(var i=0;i<self._howls.length;i++){if(!self._howls[i]._webAudio){var ids=self._howls[i]._getSoundIds();for(var j=0;j<ids.length;j++){var sound=self._howls[i]._soundById(ids[j]);if(sound&&sound._node&&!sound._node._unlocked){sound._node._unlocked=true;sound._node.load();}}}}
|
||||
self._autoResume();var source=self.ctx.createBufferSource();source.buffer=self._scratchBuffer;source.connect(self.ctx.destination);if(typeof source.start==='undefined'){source.noteOn(0);}else{source.start(0);}
|
||||
if(typeof self.ctx.resume==='function'){self.ctx.resume();}
|
||||
source.onended=function(){source.disconnect(0);self._audioUnlocked=true;document.removeEventListener('touchstart',unlock,true);document.removeEventListener('touchend',unlock,true);document.removeEventListener('click',unlock,true);for(var i=0;i<self._howls.length;i++){self._howls[i]._emit('unlock');}};};document.addEventListener('touchstart',unlock,true);document.addEventListener('touchend',unlock,true);document.addEventListener('click',unlock,true);return self;},_obtainHtml5Audio:function(){var self=this||Howler;if(self._html5AudioPool.length){return self._html5AudioPool.pop();}
|
||||
var testPlay=new Audio().play();if(testPlay&&typeof Promise!=='undefined'&&(testPlay instanceof Promise||typeof testPlay.then==='function')){testPlay.catch(function(){console.warn('HTML5 Audio pool exhausted, returning potentially locked audio object.');});}
|
||||
return new Audio();},_releaseHtml5Audio:function(audio){var self=this||Howler;if(audio._unlocked){self._html5AudioPool.push(audio);}
|
||||
return self;},_autoSuspend:function(){var self=this;if(!self.autoSuspend||!self.ctx||typeof self.ctx.suspend==='undefined'||!Howler.usingWebAudio){return;}
|
||||
for(var i=0;i<self._howls.length;i++){if(self._howls[i]._webAudio){for(var j=0;j<self._howls[i]._sounds.length;j++){if(!self._howls[i]._sounds[j]._paused){return self;}}}}
|
||||
if(self._suspendTimer){clearTimeout(self._suspendTimer);}
|
||||
self._suspendTimer=setTimeout(function(){if(!self.autoSuspend){return;}
|
||||
self._suspendTimer=null;self.state='suspending';self.ctx.suspend().then(function(){self.state='suspended';if(self._resumeAfterSuspend){delete self._resumeAfterSuspend;self._autoResume();}});},30000);return self;},_autoResume:function(){var self=this;if(!self.ctx||typeof self.ctx.resume==='undefined'||!Howler.usingWebAudio){return;}
|
||||
if(self.state==='running'&&self._suspendTimer){clearTimeout(self._suspendTimer);self._suspendTimer=null;}else if(self.state==='suspended'){self.ctx.resume().then(function(){self.state='running';for(var i=0;i<self._howls.length;i++){self._howls[i]._emit('resume');}});if(self._suspendTimer){clearTimeout(self._suspendTimer);self._suspendTimer=null;}}else if(self.state==='suspending'){self._resumeAfterSuspend=true;}
|
||||
return self;}};var Howler=new HowlerGlobal();var Howl=function(o){var self=this;if(!o.src||o.src.length===0){console.error('An array of source files must be passed with any new Howl.');return;}
|
||||
self.init(o);};Howl.prototype={init:function(o){var self=this;if(!Howler.ctx){setupAudioContext();}
|
||||
self._autoplay=o.autoplay||false;self._format=(typeof o.format!=='string')?o.format:[o.format];self._html5=o.html5||false;self._muted=o.mute||false;self._loop=o.loop||false;self._pool=o.pool||5;self._preload=(typeof o.preload==='boolean')?o.preload:true;self._rate=o.rate||1;self._sprite=o.sprite||{};self._src=(typeof o.src!=='string')?o.src:[o.src];self._volume=o.volume!==undefined?o.volume:1;self._xhrWithCredentials=o.xhrWithCredentials||false;self._duration=0;self._state='unloaded';self._sounds=[];self._endTimers={};self._queue=[];self._playLock=false;self._onend=o.onend?[{fn:o.onend}]:[];self._onfade=o.onfade?[{fn:o.onfade}]:[];self._onload=o.onload?[{fn:o.onload}]:[];self._onloaderror=o.onloaderror?[{fn:o.onloaderror}]:[];self._onplayerror=o.onplayerror?[{fn:o.onplayerror}]:[];self._onpause=o.onpause?[{fn:o.onpause}]:[];self._onplay=o.onplay?[{fn:o.onplay}]:[];self._onstop=o.onstop?[{fn:o.onstop}]:[];self._onmute=o.onmute?[{fn:o.onmute}]:[];self._onvolume=o.onvolume?[{fn:o.onvolume}]:[];self._onrate=o.onrate?[{fn:o.onrate}]:[];self._onseek=o.onseek?[{fn:o.onseek}]:[];self._onunlock=o.onunlock?[{fn:o.onunlock}]:[];self._onresume=[];self._webAudio=Howler.usingWebAudio&&!self._html5;if(typeof Howler.ctx!=='undefined'&&Howler.ctx&&Howler.autoUnlock){Howler._unlockAudio();}
|
||||
Howler._howls.push(self);if(self._autoplay){self._queue.push({event:'play',action:function(){self.play();}});}
|
||||
if(self._preload){self.load();}
|
||||
return self;},load:function(){var self=this;var url=null;if(Howler.noAudio){self._emit('loaderror',null,'No audio support.');return;}
|
||||
if(typeof self._src==='string'){self._src=[self._src];}
|
||||
for(var i=0;i<self._src.length;i++){var ext,str;if(self._format&&self._format[i]){ext=self._format[i];}else{str=self._src[i];if(typeof str!=='string'){self._emit('loaderror',null,'Non-string found in selected audio sources - ignoring.');continue;}
|
||||
ext=/^data:audio\/([^;,]+);/i.exec(str);if(!ext){ext=/\.([^.]+)$/.exec(str.split('?',1)[0]);}
|
||||
if(ext){ext=ext[1].toLowerCase();}}
|
||||
if(!ext){console.warn('No file extension was found. Consider using the "format" property or specify an extension.');}
|
||||
if(ext&&Howler.codecs(ext)){url=self._src[i];break;}}
|
||||
if(!url){self._emit('loaderror',null,'No codec support for selected audio sources.');return;}
|
||||
self._src=url;self._state='loading';if(window.location.protocol==='https:'&&url.slice(0,5)==='http:'){self._html5=true;self._webAudio=false;}
|
||||
new Sound(self);if(self._webAudio){loadBuffer(self);}
|
||||
return self;},play:function(sprite,internal){var self=this;var id=null;if(typeof sprite==='number'){id=sprite;sprite=null;}else if(typeof sprite==='string'&&self._state==='loaded'&&!self._sprite[sprite]){return null;}else if(typeof sprite==='undefined'){sprite='__default';if(!self._playLock){var num=0;for(var i=0;i<self._sounds.length;i++){if(self._sounds[i]._paused&&!self._sounds[i]._ended){num++;id=self._sounds[i]._id;}}
|
||||
if(num===1){sprite=null;}else{id=null;}}}
|
||||
var sound=id?self._soundById(id):self._inactiveSound();if(!sound){return null;}
|
||||
if(id&&!sprite){sprite=sound._sprite||'__default';}
|
||||
if(self._state!=='loaded'){sound._sprite=sprite;sound._ended=false;var soundId=sound._id;self._queue.push({event:'play',action:function(){self.play(soundId);}});return soundId;}
|
||||
if(id&&!sound._paused){if(!internal){self._loadQueue('play');}
|
||||
return sound._id;}
|
||||
if(self._webAudio){Howler._autoResume();}
|
||||
var seek=Math.max(0,sound._seek>0?sound._seek:self._sprite[sprite][0]/1000);var duration=Math.max(0,((self._sprite[sprite][0]+self._sprite[sprite][1])/1000)-seek);var timeout=(duration*1000)/Math.abs(sound._rate);var start=self._sprite[sprite][0]/1000;var stop=(self._sprite[sprite][0]+self._sprite[sprite][1])/1000;var loop=!!(sound._loop||self._sprite[sprite][2]);sound._sprite=sprite;sound._ended=false;var setParams=function(){sound._paused=false;sound._seek=seek;sound._start=start;sound._stop=stop;sound._loop=loop;};if(seek>=stop){self._ended(sound);return;}
|
||||
var node=sound._node;if(self._webAudio){var playWebAudio=function(){self._playLock=false;setParams();self._refreshBuffer(sound);var vol=(sound._muted||self._muted)?0:sound._volume;node.gain.setValueAtTime(vol,Howler.ctx.currentTime);sound._playStart=Howler.ctx.currentTime;if(typeof node.bufferSource.start==='undefined'){sound._loop?node.bufferSource.noteGrainOn(0,seek,86400):node.bufferSource.noteGrainOn(0,seek,duration);}else{sound._loop?node.bufferSource.start(0,seek,86400):node.bufferSource.start(0,seek,duration);}
|
||||
if(timeout!==Infinity){self._endTimers[sound._id]=setTimeout(self._ended.bind(self,sound),timeout);}
|
||||
if(!internal){setTimeout(function(){self._emit('play',sound._id);self._loadQueue();},0);}};if(Howler.state==='running'){playWebAudio();}else{self._playLock=true;self.once('resume',playWebAudio);self._clearTimer(sound._id);}}else{var playHtml5=function(){node.currentTime=seek;node.muted=sound._muted||self._muted||Howler._muted||node.muted;node.volume=sound._volume*Howler.volume();node.playbackRate=sound._rate;try{var play=node.play();if(play&&typeof Promise!=='undefined'&&(play instanceof Promise||typeof play.then==='function')){self._playLock=true;setParams();play.then(function(){self._playLock=false;node._unlocked=true;if(!internal){self._emit('play',sound._id);self._loadQueue();}}).catch(function(){self._playLock=false;self._emit('playerror',sound._id,'Playback was unable to start. This is most commonly an issue '+
|
||||
'on mobile devices and Chrome where playback was not within a user interaction.');sound._ended=true;sound._paused=true;});}else if(!internal){self._playLock=false;setParams();self._emit('play',sound._id);self._loadQueue();}
|
||||
node.playbackRate=sound._rate;if(node.paused){self._emit('playerror',sound._id,'Playback was unable to start. This is most commonly an issue '+
|
||||
'on mobile devices and Chrome where playback was not within a user interaction.');return;}
|
||||
if(sprite!=='__default'||sound._loop){self._endTimers[sound._id]=setTimeout(self._ended.bind(self,sound),timeout);}else{self._endTimers[sound._id]=function(){self._ended(sound);node.removeEventListener('ended',self._endTimers[sound._id],false);};node.addEventListener('ended',self._endTimers[sound._id],false);}}catch(err){self._emit('playerror',sound._id,err);}};if(node.src==='data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA'){node.src=self._src;node.load();}
|
||||
var loadedNoReadyState=(window&&window.ejecta)||(!node.readyState&&Howler._navigator.isCocoonJS);if(node.readyState>=3||loadedNoReadyState){playHtml5();}else{self._playLock=true;var listener=function(){playHtml5();node.removeEventListener(Howler._canPlayEvent,listener,false);};node.addEventListener(Howler._canPlayEvent,listener,false);self._clearTimer(sound._id);}}
|
||||
return sound._id;},pause:function(id){var self=this;if(self._state!=='loaded'||self._playLock){self._queue.push({event:'pause',action:function(){self.pause(id);}});return self;}
|
||||
var ids=self._getSoundIds(id);for(var i=0;i<ids.length;i++){self._clearTimer(ids[i]);var sound=self._soundById(ids[i]);if(sound&&!sound._paused){sound._seek=self.seek(ids[i]);sound._rateSeek=0;sound._paused=true;self._stopFade(ids[i]);if(sound._node){if(self._webAudio){if(!sound._node.bufferSource){continue;}
|
||||
if(typeof sound._node.bufferSource.stop==='undefined'){sound._node.bufferSource.noteOff(0);}else{sound._node.bufferSource.stop(0);}
|
||||
self._cleanBuffer(sound._node);}else if(!isNaN(sound._node.duration)||sound._node.duration===Infinity){sound._node.pause();}}}
|
||||
if(!arguments[1]){self._emit('pause',sound?sound._id:null);}}
|
||||
return self;},stop:function(id,internal){var self=this;if(self._state!=='loaded'||self._playLock){self._queue.push({event:'stop',action:function(){self.stop(id);}});return self;}
|
||||
var ids=self._getSoundIds(id);for(var i=0;i<ids.length;i++){self._clearTimer(ids[i]);var sound=self._soundById(ids[i]);if(sound){sound._seek=sound._start||0;sound._rateSeek=0;sound._paused=true;sound._ended=true;self._stopFade(ids[i]);if(sound._node){if(self._webAudio){if(sound._node.bufferSource){if(typeof sound._node.bufferSource.stop==='undefined'){sound._node.bufferSource.noteOff(0);}else{sound._node.bufferSource.stop(0);}
|
||||
self._cleanBuffer(sound._node);}}else if(!isNaN(sound._node.duration)||sound._node.duration===Infinity){sound._node.currentTime=sound._start||0;sound._node.pause();if(sound._node.duration===Infinity){self._clearSound(sound._node);}}}
|
||||
if(!internal){self._emit('stop',sound._id);}}}
|
||||
return self;},mute:function(muted,id){var self=this;if(self._state!=='loaded'||self._playLock){self._queue.push({event:'mute',action:function(){self.mute(muted,id);}});return self;}
|
||||
if(typeof id==='undefined'){if(typeof muted==='boolean'){self._muted=muted;}else{return self._muted;}}
|
||||
var ids=self._getSoundIds(id);for(var i=0;i<ids.length;i++){var sound=self._soundById(ids[i]);if(sound){sound._muted=muted;if(sound._interval){self._stopFade(sound._id);}
|
||||
if(self._webAudio&&sound._node){sound._node.gain.setValueAtTime(muted?0:sound._volume,Howler.ctx.currentTime);}else if(sound._node){sound._node.muted=Howler._muted?true:muted;}
|
||||
self._emit('mute',sound._id);}}
|
||||
return self;},volume:function(){var self=this;var args=arguments;var vol,id;if(args.length===0){return self._volume;}else if(args.length===1||args.length===2&&typeof args[1]==='undefined'){var ids=self._getSoundIds();var index=ids.indexOf(args[0]);if(index>=0){id=parseInt(args[0],10);}else{vol=parseFloat(args[0]);}}else if(args.length>=2){vol=parseFloat(args[0]);id=parseInt(args[1],10);}
|
||||
var sound;if(typeof vol!=='undefined'&&vol>=0&&vol<=1){if(self._state!=='loaded'||self._playLock){self._queue.push({event:'volume',action:function(){self.volume.apply(self,args);}});return self;}
|
||||
if(typeof id==='undefined'){self._volume=vol;}
|
||||
id=self._getSoundIds(id);for(var i=0;i<id.length;i++){sound=self._soundById(id[i]);if(sound){sound._volume=vol;if(!args[2]){self._stopFade(id[i]);}
|
||||
if(self._webAudio&&sound._node&&!sound._muted){sound._node.gain.setValueAtTime(vol,Howler.ctx.currentTime);}else if(sound._node&&!sound._muted){sound._node.volume=vol*Howler.volume();}
|
||||
self._emit('volume',sound._id);}}}else{sound=id?self._soundById(id):self._sounds[0];return sound?sound._volume:0;}
|
||||
return self;},fade:function(from,to,len,id){var self=this;if(self._state!=='loaded'||self._playLock){self._queue.push({event:'fade',action:function(){self.fade(from,to,len,id);}});return self;}
|
||||
from=parseFloat(from);to=parseFloat(to);len=parseFloat(len);self.volume(from,id);var ids=self._getSoundIds(id);for(var i=0;i<ids.length;i++){var sound=self._soundById(ids[i]);if(sound){if(!id){self._stopFade(ids[i]);}
|
||||
if(self._webAudio&&!sound._muted){var currentTime=Howler.ctx.currentTime;var end=currentTime+(len/1000);sound._volume=from;sound._node.gain.setValueAtTime(from,currentTime);sound._node.gain.linearRampToValueAtTime(to,end);}
|
||||
self._startFadeInterval(sound,from,to,len,ids[i],typeof id==='undefined');}}
|
||||
return self;},_startFadeInterval:function(sound,from,to,len,id,isGroup){var self=this;var vol=from;var diff=to-from;var steps=Math.abs(diff/0.01);var stepLen=Math.max(4,(steps>0)?len/steps:len);var lastTick=Date.now();sound._fadeTo=to;sound._interval=setInterval(function(){var tick=(Date.now()-lastTick)/len;lastTick=Date.now();vol+=diff*tick;vol=Math.max(0,vol);vol=Math.min(1,vol);vol=Math.round(vol*100)/100;if(self._webAudio){sound._volume=vol;}else{self.volume(vol,sound._id,true);}
|
||||
if(isGroup){self._volume=vol;}
|
||||
if((to<from&&vol<=to)||(to>from&&vol>=to)){clearInterval(sound._interval);sound._interval=null;sound._fadeTo=null;self.volume(to,sound._id);self._emit('fade',sound._id);}},stepLen);},_stopFade:function(id){var self=this;var sound=self._soundById(id);if(sound&&sound._interval){if(self._webAudio){sound._node.gain.cancelScheduledValues(Howler.ctx.currentTime);}
|
||||
clearInterval(sound._interval);sound._interval=null;self.volume(sound._fadeTo,id);sound._fadeTo=null;self._emit('fade',id);}
|
||||
return self;},loop:function(){var self=this;var args=arguments;var loop,id,sound;if(args.length===0){return self._loop;}else if(args.length===1){if(typeof args[0]==='boolean'){loop=args[0];self._loop=loop;}else{sound=self._soundById(parseInt(args[0],10));return sound?sound._loop:false;}}else if(args.length===2){loop=args[0];id=parseInt(args[1],10);}
|
||||
var ids=self._getSoundIds(id);for(var i=0;i<ids.length;i++){sound=self._soundById(ids[i]);if(sound){sound._loop=loop;if(self._webAudio&&sound._node&&sound._node.bufferSource){sound._node.bufferSource.loop=loop;if(loop){sound._node.bufferSource.loopStart=sound._start||0;sound._node.bufferSource.loopEnd=sound._stop;}}}}
|
||||
return self;},rate:function(){var self=this;var args=arguments;var rate,id;if(args.length===0){id=self._sounds[0]._id;}else if(args.length===1){var ids=self._getSoundIds();var index=ids.indexOf(args[0]);if(index>=0){id=parseInt(args[0],10);}else{rate=parseFloat(args[0]);}}else if(args.length===2){rate=parseFloat(args[0]);id=parseInt(args[1],10);}
|
||||
var sound;if(typeof rate==='number'){if(self._state!=='loaded'||self._playLock){self._queue.push({event:'rate',action:function(){self.rate.apply(self,args);}});return self;}
|
||||
if(typeof id==='undefined'){self._rate=rate;}
|
||||
id=self._getSoundIds(id);for(var i=0;i<id.length;i++){sound=self._soundById(id[i]);if(sound){if(self.playing(id[i])){sound._rateSeek=self.seek(id[i]);sound._playStart=self._webAudio?Howler.ctx.currentTime:sound._playStart;}
|
||||
sound._rate=rate;if(self._webAudio&&sound._node&&sound._node.bufferSource){sound._node.bufferSource.playbackRate.setValueAtTime(rate,Howler.ctx.currentTime);}else if(sound._node){sound._node.playbackRate=rate;}
|
||||
var seek=self.seek(id[i]);var duration=((self._sprite[sound._sprite][0]+self._sprite[sound._sprite][1])/1000)-seek;var timeout=(duration*1000)/Math.abs(sound._rate);if(self._endTimers[id[i]]||!sound._paused){self._clearTimer(id[i]);self._endTimers[id[i]]=setTimeout(self._ended.bind(self,sound),timeout);}
|
||||
self._emit('rate',sound._id);}}}else{sound=self._soundById(id);return sound?sound._rate:self._rate;}
|
||||
return self;},seek:function(){var self=this;var args=arguments;var seek,id;if(args.length===0){id=self._sounds[0]._id;}else if(args.length===1){var ids=self._getSoundIds();var index=ids.indexOf(args[0]);if(index>=0){id=parseInt(args[0],10);}else if(self._sounds.length){id=self._sounds[0]._id;seek=parseFloat(args[0]);}}else if(args.length===2){seek=parseFloat(args[0]);id=parseInt(args[1],10);}
|
||||
if(typeof id==='undefined'){return self;}
|
||||
if(self._state!=='loaded'||self._playLock){self._queue.push({event:'seek',action:function(){self.seek.apply(self,args);}});return self;}
|
||||
var sound=self._soundById(id);if(sound){if(typeof seek==='number'&&seek>=0){var playing=self.playing(id);if(playing){self.pause(id,true);}
|
||||
sound._seek=seek;sound._ended=false;self._clearTimer(id);if(!self._webAudio&&sound._node&&!isNaN(sound._node.duration)){sound._node.currentTime=seek;}
|
||||
var seekAndEmit=function(){self._emit('seek',id);if(playing){self.play(id,true);}};if(playing&&!self._webAudio){var emitSeek=function(){if(!self._playLock){seekAndEmit();}else{setTimeout(emitSeek,0);}};setTimeout(emitSeek,0);}else{seekAndEmit();}}else{if(self._webAudio){var realTime=self.playing(id)?Howler.ctx.currentTime-sound._playStart:0;var rateSeek=sound._rateSeek?sound._rateSeek-sound._seek:0;return sound._seek+(rateSeek+realTime*Math.abs(sound._rate));}else{return sound._node.currentTime;}}}
|
||||
return self;},playing:function(id){var self=this;if(typeof id==='number'){var sound=self._soundById(id);return sound?!sound._paused:false;}
|
||||
for(var i=0;i<self._sounds.length;i++){if(!self._sounds[i]._paused){return true;}}
|
||||
return false;},duration:function(id){var self=this;var duration=self._duration;var sound=self._soundById(id);if(sound){duration=self._sprite[sound._sprite][1]/1000;}
|
||||
return duration;},state:function(){return this._state;},unload:function(){var self=this;var sounds=self._sounds;for(var i=0;i<sounds.length;i++){if(!sounds[i]._paused){self.stop(sounds[i]._id);}
|
||||
if(!self._webAudio){self._clearSound(sounds[i]._node);sounds[i]._node.removeEventListener('error',sounds[i]._errorFn,false);sounds[i]._node.removeEventListener(Howler._canPlayEvent,sounds[i]._loadFn,false);Howler._releaseHtml5Audio(sounds[i]._node);}
|
||||
delete sounds[i]._node;self._clearTimer(sounds[i]._id);}
|
||||
var index=Howler._howls.indexOf(self);if(index>=0){Howler._howls.splice(index,1);}
|
||||
var remCache=true;for(i=0;i<Howler._howls.length;i++){if(Howler._howls[i]._src===self._src||self._src.indexOf(Howler._howls[i]._src)>=0){remCache=false;break;}}
|
||||
if(cache&&remCache){delete cache[self._src];}
|
||||
Howler.noAudio=false;self._state='unloaded';self._sounds=[];self=null;return null;},on:function(event,fn,id,once){var self=this;var events=self['_on'+event];if(typeof fn==='function'){events.push(once?{id:id,fn:fn,once:once}:{id:id,fn:fn});}
|
||||
return self;},off:function(event,fn,id){var self=this;var events=self['_on'+event];var i=0;if(typeof fn==='number'){id=fn;fn=null;}
|
||||
if(fn||id){for(i=0;i<events.length;i++){var isId=(id===events[i].id);if(fn===events[i].fn&&isId||!fn&&isId){events.splice(i,1);break;}}}else if(event){self['_on'+event]=[];}else{var keys=Object.keys(self);for(i=0;i<keys.length;i++){if((keys[i].indexOf('_on')===0)&&Array.isArray(self[keys[i]])){self[keys[i]]=[];}}}
|
||||
return self;},once:function(event,fn,id){var self=this;self.on(event,fn,id,1);return self;},_emit:function(event,id,msg){var self=this;var events=self['_on'+event];for(var i=events.length-1;i>=0;i--){if(!events[i].id||events[i].id===id||event==='load'){setTimeout(function(fn){fn.call(this,id,msg);}.bind(self,events[i].fn),0);if(events[i].once){self.off(event,events[i].fn,events[i].id);}}}
|
||||
self._loadQueue(event);return self;},_loadQueue:function(event){var self=this;if(self._queue.length>0){var task=self._queue[0];if(task.event===event){self._queue.shift();self._loadQueue();}
|
||||
if(!event){task.action();}}
|
||||
return self;},_ended:function(sound){var self=this;var sprite=sound._sprite;if(!self._webAudio&&sound._node&&!sound._node.paused&&!sound._node.ended&&sound._node.currentTime<sound._stop){setTimeout(self._ended.bind(self,sound),100);return self;}
|
||||
var loop=!!(sound._loop||self._sprite[sprite][2]);self._emit('end',sound._id);if(!self._webAudio&&loop){self.stop(sound._id,true).play(sound._id);}
|
||||
if(self._webAudio&&loop){self._emit('play',sound._id);sound._seek=sound._start||0;sound._rateSeek=0;sound._playStart=Howler.ctx.currentTime;var timeout=((sound._stop-sound._start)*1000)/Math.abs(sound._rate);self._endTimers[sound._id]=setTimeout(self._ended.bind(self,sound),timeout);}
|
||||
if(self._webAudio&&!loop){sound._paused=true;sound._ended=true;sound._seek=sound._start||0;sound._rateSeek=0;self._clearTimer(sound._id);self._cleanBuffer(sound._node);Howler._autoSuspend();}
|
||||
if(!self._webAudio&&!loop){self.stop(sound._id,true);}
|
||||
return self;},_clearTimer:function(id){var self=this;if(self._endTimers[id]){if(typeof self._endTimers[id]!=='function'){clearTimeout(self._endTimers[id]);}else{var sound=self._soundById(id);if(sound&&sound._node){sound._node.removeEventListener('ended',self._endTimers[id],false);}}
|
||||
delete self._endTimers[id];}
|
||||
return self;},_soundById:function(id){var self=this;for(var i=0;i<self._sounds.length;i++){if(id===self._sounds[i]._id){return self._sounds[i];}}
|
||||
return null;},_inactiveSound:function(){var self=this;self._drain();for(var i=0;i<self._sounds.length;i++){if(self._sounds[i]._ended){return self._sounds[i].reset();}}
|
||||
return new Sound(self);},_drain:function(){var self=this;var limit=self._pool;var cnt=0;var i=0;if(self._sounds.length<limit){return;}
|
||||
for(i=0;i<self._sounds.length;i++){if(self._sounds[i]._ended){cnt++;}}
|
||||
for(i=self._sounds.length-1;i>=0;i--){if(cnt<=limit){return;}
|
||||
if(self._sounds[i]._ended){if(self._webAudio&&self._sounds[i]._node){self._sounds[i]._node.disconnect(0);}
|
||||
self._sounds.splice(i,1);cnt--;}}},_getSoundIds:function(id){var self=this;if(typeof id==='undefined'){var ids=[];for(var i=0;i<self._sounds.length;i++){ids.push(self._sounds[i]._id);}
|
||||
return ids;}else{return[id];}},_refreshBuffer:function(sound){var self=this;sound._node.bufferSource=Howler.ctx.createBufferSource();sound._node.bufferSource.buffer=cache[self._src];if(sound._panner){sound._node.bufferSource.connect(sound._panner);}else{sound._node.bufferSource.connect(sound._node);}
|
||||
sound._node.bufferSource.loop=sound._loop;if(sound._loop){sound._node.bufferSource.loopStart=sound._start||0;sound._node.bufferSource.loopEnd=sound._stop||0;}
|
||||
sound._node.bufferSource.playbackRate.setValueAtTime(sound._rate,Howler.ctx.currentTime);return self;},_cleanBuffer:function(node){var self=this;var isIOS=Howler._navigator&&Howler._navigator.vendor.indexOf('Apple')>=0;if(Howler._scratchBuffer&&node.bufferSource){node.bufferSource.onended=null;node.bufferSource.disconnect(0);if(isIOS){try{node.bufferSource.buffer=Howler._scratchBuffer;}catch(e){}}}
|
||||
node.bufferSource=null;return self;},_clearSound:function(node){var checkIE=/MSIE |Trident\//.test(Howler._navigator&&Howler._navigator.userAgent);if(!checkIE){node.src='data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA';}}};var Sound=function(howl){this._parent=howl;this.init();};Sound.prototype={init:function(){var self=this;var parent=self._parent;self._muted=parent._muted;self._loop=parent._loop;self._volume=parent._volume;self._rate=parent._rate;self._seek=0;self._paused=true;self._ended=true;self._sprite='__default';self._id=++Howler._counter;parent._sounds.push(self);self.create();return self;},create:function(){var self=this;var parent=self._parent;var volume=(Howler._muted||self._muted||self._parent._muted)?0:self._volume;if(parent._webAudio){self._node=(typeof Howler.ctx.createGain==='undefined')?Howler.ctx.createGainNode():Howler.ctx.createGain();self._node.gain.setValueAtTime(volume,Howler.ctx.currentTime);self._node.paused=true;self._node.connect(Howler.masterGain);}else{self._node=Howler._obtainHtml5Audio();self._errorFn=self._errorListener.bind(self);self._node.addEventListener('error',self._errorFn,false);self._loadFn=self._loadListener.bind(self);self._node.addEventListener(Howler._canPlayEvent,self._loadFn,false);self._node.src=parent._src;self._node.preload='auto';self._node.volume=volume*Howler.volume();self._node.load();}
|
||||
return self;},reset:function(){var self=this;var parent=self._parent;self._muted=parent._muted;self._loop=parent._loop;self._volume=parent._volume;self._rate=parent._rate;self._seek=0;self._rateSeek=0;self._paused=true;self._ended=true;self._sprite='__default';self._id=++Howler._counter;return self;},_errorListener:function(){var self=this;self._parent._emit('loaderror',self._id,self._node.error?self._node.error.code:0);self._node.removeEventListener('error',self._errorFn,false);},_loadListener:function(){var self=this;var parent=self._parent;parent._duration=Math.ceil(self._node.duration*10)/10;if(Object.keys(parent._sprite).length===0){parent._sprite={__default:[0,parent._duration*1000]};}
|
||||
if(parent._state!=='loaded'){parent._state='loaded';parent._emit('load');parent._loadQueue();}
|
||||
self._node.removeEventListener(Howler._canPlayEvent,self._loadFn,false);}};var cache={};var loadBuffer=function(self){var url=self._src;if(cache[url]){self._duration=cache[url].duration;loadSound(self);return;}
|
||||
if(/^data:[^;]+;base64,/.test(url)){var data=atob(url.split(',')[1]);var dataView=new Uint8Array(data.length);for(var i=0;i<data.length;++i){dataView[i]=data.charCodeAt(i);}
|
||||
decodeAudioData(dataView.buffer,self);}else{var xhr=new XMLHttpRequest();xhr.open('GET',url,true);xhr.withCredentials=self._xhrWithCredentials;xhr.responseType='arraybuffer';xhr.onload=function(){var code=(xhr.status+'')[0];if(code!=='0'&&code!=='2'&&code!=='3'){self._emit('loaderror',null,'Failed loading audio file with status: '+xhr.status+'.');return;}
|
||||
decodeAudioData(xhr.response,self);};xhr.onerror=function(){if(self._webAudio){self._html5=true;self._webAudio=false;self._sounds=[];delete cache[url];self.load();}};safeXhrSend(xhr);}};var safeXhrSend=function(xhr){try{xhr.send();}catch(e){xhr.onerror();}};var decodeAudioData=function(arraybuffer,self){var error=function(){self._emit('loaderror',null,'Decoding audio data failed.');};var success=function(buffer){if(buffer&&self._sounds.length>0){cache[self._src]=buffer;loadSound(self,buffer);}else{error();}};if(typeof Promise!=='undefined'&&Howler.ctx.decodeAudioData.length===1){Howler.ctx.decodeAudioData(arraybuffer).then(success).catch(error);}else{Howler.ctx.decodeAudioData(arraybuffer,success,error);}}
|
||||
var loadSound=function(self,buffer){if(buffer&&!self._duration){self._duration=buffer.duration;}
|
||||
if(Object.keys(self._sprite).length===0){self._sprite={__default:[0,self._duration*1000]};}
|
||||
if(self._state!=='loaded'){self._state='loaded';self._emit('load');self._loadQueue();}};var setupAudioContext=function(){if(!Howler.usingWebAudio){return;}
|
||||
try{if(typeof AudioContext!=='undefined'){Howler.ctx=new AudioContext();}else if(typeof webkitAudioContext!=='undefined'){Howler.ctx=new webkitAudioContext();}else{Howler.usingWebAudio=false;}}catch(e){Howler.usingWebAudio=false;}
|
||||
if(!Howler.ctx){Howler.usingWebAudio=false;}
|
||||
var iOS=(/iP(hone|od|ad)/.test(Howler._navigator&&Howler._navigator.platform));var appVersion=Howler._navigator&&Howler._navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/);var version=appVersion?parseInt(appVersion[1],10):null;if(iOS&&version&&version<9){var safari=/safari/.test(Howler._navigator&&Howler._navigator.userAgent.toLowerCase());if(Howler._navigator&&Howler._navigator.standalone&&!safari||Howler._navigator&&!Howler._navigator.standalone&&!safari){Howler.usingWebAudio=false;}}
|
||||
if(Howler.usingWebAudio){Howler.masterGain=(typeof Howler.ctx.createGain==='undefined')?Howler.ctx.createGainNode():Howler.ctx.createGain();Howler.masterGain.gain.setValueAtTime(Howler._muted?0:1,Howler.ctx.currentTime);Howler.masterGain.connect(Howler.ctx.destination);}
|
||||
Howler._setup();};if(typeof define==='function'&&define.amd){define([],function(){return{Howler:Howler,Howl:Howl};});}
|
||||
if(typeof exports!=='undefined'){exports.Howler=Howler;exports.Howl=Howl;}
|
||||
if(typeof window!=='undefined'){window.HowlerGlobal=HowlerGlobal;window.Howler=Howler;window.Howl=Howl;window.Sound=Sound;}else if(typeof global!=='undefined'){global.HowlerGlobal=HowlerGlobal;global.Howler=Howler;global.Howl=Howl;global.Sound=Sound;}})();
|
44
manifest.json
Normal file
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"short_name": "Music",
|
||||
"name": "Music",
|
||||
"icons": [
|
||||
{
|
||||
"src": "\/android-icon-36x36.png",
|
||||
"sizes": "36x36",
|
||||
"type": "image\/png",
|
||||
"density": "0.75"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image\/png",
|
||||
"density": "1.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image\/png",
|
||||
"density": "1.5"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image\/png",
|
||||
"density": "2.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image\/png",
|
||||
"density": "3.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image\/png",
|
||||
"density": "4.0"
|
||||
}
|
||||
],
|
||||
"display": "standalone",
|
||||
"start_url": "/"
|
||||
}
|
37
webmusic.csproj
Normal file
|
@ -0,0 +1,37 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<DebugType>full</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.CookiePolicy" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.HttpsPolicy" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="music\**" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Remove="music\**" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="music\**" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="music\**" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
43
webmusic.css
Normal file
|
@ -0,0 +1,43 @@
|
|||
body {
|
||||
background-color: #161616;
|
||||
}
|
||||
|
||||
h2, h2 a {
|
||||
font-family: 'Inconsolata', 'monospace';
|
||||
font-size: 11pt;
|
||||
color: #afafaf;
|
||||
margin-top: 6px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
#container, a {
|
||||
font-family: 'Ubuntu Mono', 'monospace';
|
||||
font-size: 11pt;
|
||||
color: #d8c18c;
|
||||
text-decoration: none;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.playing {
|
||||
color: #6b9969;
|
||||
}
|
||||
|
||||
.entry-muted {
|
||||
color: #d88777;
|
||||
}
|
||||
|
||||
.action {
|
||||
font-size: 10pt;
|
||||
color: #cc7851;
|
||||
}
|
||||
|
||||
.action-muted {
|
||||
font-size: 10pt;
|
||||
color: #e5e5e5;
|
||||
}
|
||||
|
||||
#container {
|
||||
margin-left: 10%;
|
||||
margin-right: 10%;
|
||||
}
|
158
webmusic.js
Normal file
|
@ -0,0 +1,158 @@
|
|||
let gstate = "idle";
|
||||
let repeat = false;
|
||||
let continuelist = true;
|
||||
let queue = [];
|
||||
let total = 0;
|
||||
let index = 0;
|
||||
|
||||
let sound = new Howl({
|
||||
src: [''],
|
||||
format: "mp3",
|
||||
html5: true
|
||||
});
|
||||
|
||||
setInterval(function () {
|
||||
updateState();
|
||||
}, 1000);
|
||||
|
||||
window.onload = function () {
|
||||
initState();
|
||||
updateState()
|
||||
};
|
||||
|
||||
document.addEventListener("keypress", function onEvent(event) {
|
||||
if (event.key === "p") {
|
||||
togglePlayback();
|
||||
}
|
||||
else if (event.key === "r") {
|
||||
toggleRepeat();
|
||||
}
|
||||
else if (event.key === "c") {
|
||||
toggleContinue();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function togglePlayback() {
|
||||
if (sound.playing())
|
||||
sound.pause();
|
||||
else
|
||||
sound.play();
|
||||
}
|
||||
|
||||
function setState(state) {
|
||||
gstate = state;
|
||||
console.log("now in state: " + state);
|
||||
updateState();
|
||||
}
|
||||
|
||||
|
||||
function playSong(url) {
|
||||
if (document.getElementsByClassName("playing").length > 0)
|
||||
document.getElementsByClassName("playing")[0].classList.remove("playing");
|
||||
index = queue.indexOf(url);
|
||||
sound.stop();
|
||||
sound.unload();
|
||||
sound = null;
|
||||
delete sound;
|
||||
|
||||
sound = new Howl({
|
||||
src: [url],
|
||||
html5: true
|
||||
});
|
||||
setState("loading");
|
||||
sound.play();
|
||||
sound.loop(repeat);
|
||||
|
||||
document.querySelectorAll('[onclick="playSong(\''+url+'\')"]')[0].classList.add("playing");
|
||||
|
||||
sound.on("play", function () {
|
||||
setState("playing");
|
||||
});
|
||||
sound.on("loaderror", function () {
|
||||
setState("error loading track")
|
||||
});
|
||||
sound.on("playerror", function () {
|
||||
setState("error opening audio device")
|
||||
});
|
||||
sound.on("end", function () {
|
||||
setState("idle");
|
||||
nextTrack()
|
||||
});
|
||||
sound.on("pause", function () {
|
||||
setState("paused")
|
||||
});
|
||||
}
|
||||
|
||||
function toggleRepeat() {
|
||||
repeat = !repeat;
|
||||
continuelist = !repeat;
|
||||
sound.loop(repeat);
|
||||
updateState();
|
||||
}
|
||||
|
||||
function toggleContinue() {
|
||||
continuelist = !continuelist;
|
||||
updateState();
|
||||
}
|
||||
|
||||
function updateState() {
|
||||
document.getElementById("state").setAttribute('onclick', 'togglePlayback()');
|
||||
let statestr = "[";
|
||||
statestr += gstate;
|
||||
if (sound.playing())
|
||||
statestr += " " + formatTime(Math.round(sound.seek())) + "/" + formatTime(Math.round(sound.duration()));
|
||||
|
||||
statestr += "]";
|
||||
document.getElementById("state").innerHTML = statestr;
|
||||
let flags = "[";
|
||||
if (repeat)
|
||||
flags += '<a onclick="toggleRepeat()" href="#" style="color:#6b9969">R</a>';
|
||||
else
|
||||
flags += '<a onclick="toggleRepeat()" href="#">R</a>';
|
||||
if (continuelist)
|
||||
flags += '<a onclick="toggleContinue()" href="#" style="color:#6b9969">C</a>';
|
||||
else
|
||||
flags += '<a onclick="toggleContinue()" href="#">C</a>';
|
||||
|
||||
document.getElementById("flags").innerHTML = flags + "]";
|
||||
}
|
||||
|
||||
function initState() {
|
||||
total = queue.length;
|
||||
}
|
||||
|
||||
function nextTrack() {
|
||||
if (++index === total)
|
||||
index = 0;
|
||||
if (continuelist) {
|
||||
playSong(queue[index])
|
||||
}
|
||||
}
|
||||
|
||||
function formatTime(secs) {
|
||||
const minutes = Math.floor(secs / 60) || 0;
|
||||
const seconds = (secs - minutes * 60) || 0;
|
||||
return minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
|
||||
}
|
||||
|
||||
function download(filename, text) {
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:audio/m3u;charset=utf-8,' + encodeURIComponent(text));
|
||||
element.setAttribute('download', filename);
|
||||
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
|
||||
element.click();
|
||||
|
||||
document.body.removeChild(element);
|
||||
}
|
||||
|
||||
function downloadm3u() {
|
||||
let m3utext = "";
|
||||
queue.forEach(function(item, index){
|
||||
m3utext+=window.location.protocol + "//" + window.location.host + "/" + item + "\n";
|
||||
});
|
||||
download("play.m3u", m3utext)
|
||||
}
|
16
webmusic.sln
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "webmusic", "webmusic.csproj", "{C0A4B1C0-C3CE-4820-A1E6-858373C956CA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C0A4B1C0-C3CE-4820-A1E6-858373C956CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C0A4B1C0-C3CE-4820-A1E6-858373C956CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C0A4B1C0-C3CE-4820-A1E6-858373C956CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C0A4B1C0-C3CE-4820-A1E6-858373C956CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|