├── SignalingServer ├── SignalingServer │ ├── Views │ │ ├── _ViewStart.cshtml │ │ ├── Home │ │ │ └── About.cshtml │ │ ├── Shared │ │ │ ├── Error.cshtml │ │ │ └── _Layout.cshtml │ │ └── Web.config │ ├── Global.asax │ ├── favicon.ico │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── App_Start │ │ ├── FilterConfig.cs │ │ ├── RouteConfig.cs │ │ └── BundleConfig.cs │ ├── Models │ │ └── MyHub1.cs │ ├── Controllers │ │ └── HomeController.cs │ ├── Content │ │ ├── Site.css │ │ ├── bootstrap-theme.min.css │ │ └── bootstrap-theme.css │ ├── Global.asax.cs │ ├── Startup.cs │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── SignalingServer.csproj.user │ ├── packages.config │ ├── Web.config │ ├── Scripts │ │ ├── jquery.validate.unobtrusive.min.js │ │ ├── jquery.validate.unobtrusive.js │ │ └── jquery.validate.min.js │ └── SignalingServer.csproj └── SignalingServer.sln ├── .gitignore ├── .vscode └── settings.json ├── index.html ├── audio ├── demo.html └── demo.js ├── video ├── demo.html └── demo.js ├── screenshare1 ├── demo.html └── demo.js ├── README.md ├── screenshare2 ├── demo.html ├── video-stream-merger.js └── demo.js ├── https ├── localhost.pem └── localhost.key └── rtcdemo ├── demo.html ├── video-stream-merger.js └── demo.js /SignalingServer/SignalingServer/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /SignalingServer/.vs 2 | /SignalingServer/packages 3 | /SignalingServer/SignalingServer/bin 4 | /SignalingServer/SignalingServer/obj 5 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="WebApplication5.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilalshahzad139/intro-to-webrtc-learn-in-urdu/HEAD/SignalingServer/SignalingServer/favicon.ico -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilalshahzad139/intro-to-webrtc-learn-in-urdu/HEAD/SignalingServer/SignalingServer/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilalshahzad139/intro-to-webrtc-learn-in-urdu/HEAD/SignalingServer/SignalingServer/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilalshahzad139/intro-to-webrtc-learn-in-urdu/HEAD/SignalingServer/SignalingServer/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilalshahzad139/intro-to-webrtc-learn-in-urdu/HEAD/SignalingServer/SignalingServer/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Error 6 | 7 | 8 |
9 |

Error.

10 |

An error occurred while processing your request.

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace WebApplication5 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5501, 3 | "liveServer.settings.root": "/", 4 | "liveServer.settings.CustomBrowser": "chrome", 5 | "liveServer.settings.https": { 6 | "enable": true, 7 | "cert": "E:/webrtcdemo/https/localhost.pem", 8 | "key": "E:/webrtcdemo/https/localhost.key", 9 | "passphrase": "12345" 10 | } 11 | } -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Models/MyHub1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using Microsoft.AspNet.SignalR; 6 | 7 | namespace WebApplication5.Models 8 | { 9 | public class WebRtcHub : Hub 10 | { 11 | public void Send(string message) 12 | { 13 | Clients.Others.newMessage(message); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | Audio Demo 11 | 12 | Video Demo 13 | 14 | Screen Share 1 15 | 16 | Screen Share + Cam 17 | 18 | WebRTC Demo 19 | 20 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | 7 | namespace WebApplication5.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | public ActionResult Index() 12 | { 13 | return View("about"); 14 | } 15 | 16 | public ActionResult About() 17 | { 18 | ViewBag.Message = "Your application description page."; 19 | 20 | return View(); 21 | } 22 | 23 | 24 | } 25 | } -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Set padding to keep content from hitting the edges */ 7 | .body-content { 8 | padding-left: 15px; 9 | padding-right: 15px; 10 | } 11 | 12 | /* Override the default bootstrap behavior where horizontal description lists 13 | will truncate terms that are too long to fit in the left column 14 | */ 15 | .dl-horizontal dt { 16 | white-space: normal; 17 | } 18 | 19 | /* Set width on the form input elements since they're 100% wide by default */ 20 | input, 21 | select, 22 | textarea { 23 | max-width: 280px; 24 | } 25 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Optimization; 7 | using System.Web.Routing; 8 | 9 | namespace WebApplication5 10 | { 11 | public class MvcApplication : System.Web.HttpApplication 12 | { 13 | protected void Application_Start() 14 | { 15 | AreaRegistration.RegisterAllAreas(); 16 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 17 | RouteConfig.RegisterRoutes(RouteTable.Routes); 18 | BundleConfig.RegisterBundles(BundleTable.Bundles); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNet.SignalR; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Web; 6 | using System.Web.Mvc; 7 | using System.Web.Routing; 8 | 9 | namespace WebApplication5 10 | { 11 | public class RouteConfig 12 | { 13 | public static void RegisterRoutes(RouteCollection routes) 14 | { 15 | 16 | 17 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 18 | 19 | routes.MapRoute( 20 | name: "Default", 21 | url: "{controller}/{action}/{id}", 22 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 23 | ); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /audio/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebRTC Demo 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 | Home 29 | 30 | -------------------------------------------------------------------------------- /video/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebRTC Demo 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 | Home 33 | 34 | -------------------------------------------------------------------------------- /screenshare1/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebRTC Demo 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 |
35 | Home 36 | 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # intro-to-webrtc-learn-in-urdu 2 | 3 | # How to run? 4 | 5 | Open index.html through any web server (e.g. Live Server in Visual Studio Code) 6 | 7 | # audio 8 | 9 | This folder contains demo of how to capture microphone audio, record it and allow user to download it. 10 | 11 | # video 12 | 13 | This folder contains demo of how to capture microphone audio + camera video, record it and allow user to download it. 14 | 15 | # screenshare1 16 | 17 | This folder contains demo of how to capture screen sharing with microphone audio, record it and allow user to download it. 18 | 19 | # screenshare2 20 | 21 | This folder contains demo of how to capture screen sharing + camera with microphone audio, record it and allow user to download it. 22 | 23 | # rtcdemo 24 | 25 | This folder contains demo of how to create RTCConnection and share metadata with peer through a 'signaling server'. It shows how we can send audio/video/screen share with peer. 26 | 27 | # signalingServer 28 | 29 | This folder contains ASP.NET SignalR project which is being used as 'signaling server' for RTC Demo. You may use any websocket implementation instead. 30 | 31 | # https 32 | 33 | This folder contains self signed certificate for localhost 34 | 35 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29613.14 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SignalingServer", "SignalingServer\SignalingServer.csproj", "{A01DE8A2-49D7-454B-8E7B-1143CB5D82FA}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {A01DE8A2-49D7-454B-8E7B-1143CB5D82FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {A01DE8A2-49D7-454B-8E7B-1143CB5D82FA}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {A01DE8A2-49D7-454B-8E7B-1143CB5D82FA}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {A01DE8A2-49D7-454B-8E7B-1143CB5D82FA}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {66F4F429-E40C-4A2A-9CC0-FE16063D0403} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Startup.cs: -------------------------------------------------------------------------------- 1 | using Owin; 2 | using Microsoft.Owin; 3 | using Microsoft.AspNet.SignalR; 4 | using System.Web.Routing; 5 | using Microsoft.Owin.Cors; 6 | 7 | [assembly: OwinStartup(typeof(SignalRChat.Startup))] 8 | namespace SignalRChat 9 | { 10 | public class Startup 11 | { 12 | public void Configuration(IAppBuilder app) 13 | { 14 | 15 | // Any connection or hub wire up and configuration should go here 16 | 17 | app.Map("/signalr", map => 18 | { 19 | map.UseCors(CorsOptions.AllowAll); 20 | 21 | var hubConfiguration = new HubConfiguration 22 | { 23 | // You can enable JSONP by uncommenting line below. 24 | // JSONP requests are insecure but some older browsers (and some 25 | // versions of IE) require JSONP to work cross domain 26 | //EnableJSONP = true 27 | }; 28 | // Run the SignalR pipeline. We're not using MapSignalR 29 | // since this branch already runs under the "/signalr" 30 | // path. 31 | map.RunSignalR(hubConfiguration); 32 | }); 33 | 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace WebApplication5 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 15 | "~/Scripts/jquery.validate*")); 16 | 17 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 18 | // ready for production, use the build tool at https://modernizr.com to pick only the tests you need. 19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 20 | "~/Scripts/modernizr-*")); 21 | 22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 23 | "~/Scripts/bootstrap.js")); 24 | 25 | bundles.Add(new StyleBundle("~/Content/css").Include( 26 | "~/Content/bootstrap.css", 27 | "~/Content/site.css")); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /screenshare2/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebRTC Demo 7 | 8 | 9 | 10 | 11 | 12 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 |
39 | Home 40 | 41 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /https/localhost.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID4zCCAsugAwIBAgIUKsYsNVqmFlpbxOyO21KlCYzfRP8wDQYJKoZIhvcNAQEL 3 | BQAwgYAxCzAJBgNVBAYTAlBLMQswCQYDVQQIDAJQVTEMMAoGA1UEBwwDTEhSMQsw 4 | CQYDVQQKDAJJQjENMAsGA1UECwwEVGVjaDESMBAGA1UEAwwJbG9jYWxob3N0MSYw 5 | JAYJKoZIhvcNAQkBFhdiaWxhbC5zaGFoemFkQHlhaG9vLmNvbTAeFw0yMDA0MjUx 6 | NjIxMjBaFw0zMDA0MjMxNjIxMjBaMIGAMQswCQYDVQQGEwJQSzELMAkGA1UECAwC 7 | UFUxDDAKBgNVBAcMA0xIUjELMAkGA1UECgwCSUIxDTALBgNVBAsMBFRlY2gxEjAQ 8 | BgNVBAMMCWxvY2FsaG9zdDEmMCQGCSqGSIb3DQEJARYXYmlsYWwuc2hhaHphZEB5 9 | YWhvby5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLbf8AzDqE 10 | iIyAMVlEqOGpMs4lrIn89t5NQ6756odcaRXj+uYRawYdJjNsXW4ur89U32XzOHn3 11 | vtu/cU1SA4Ixc94xuTpgxz2e2GMJWJtXU87LF8VxNkgio34Z8/kPq31fr4wgzYSF 12 | eiruzpCZvcTkFLvzUoFNznOV8tC4L98O+Oa8DUPpZgLqx7B1I3fsybll9yLJia7e 13 | sKfHZYqoDsXmiEjsSUj7ui4canDKKl2HWpQbEcRSJw7/GJtmhmuzDY4ZOX2vKo76 14 | +jcfEjrfmdm0tACJQlJY5czriJGDCFGv1U1/gzkaz3EClp0M89Hd+PW1QB6rlam/ 15 | 3x+AA56snh9VAgMBAAGjUzBRMB0GA1UdDgQWBBSg8jA4gqO1avcFdPvZjOWueh+O 16 | IzAfBgNVHSMEGDAWgBSg8jA4gqO1avcFdPvZjOWueh+OIzAPBgNVHRMBAf8EBTAD 17 | AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBU3Oij9znednBTkXrMonYxqticBZZXuVXS 18 | h/NMhEKM6da7qdMQesRbKc/Jnl8sSaE98WcduAfb7uxeculNSBJhL6kNOXdOSEJ0 19 | R0SZG/C5184FlPOzH8fzotsFYNtFcksXnbzLEuhFxa1rHnzrX9gqf7FG9rBFWnGL 20 | sCjcgPuavcvj4l+zjJurh6XAK3dnEDvAHxXRh7VfTlH7YbTyr13o4OfF93z4bY+I 21 | XlC+KqU2spX0YJskWV2Vj1eZKHd1giRDOaPnDDfnVEFcOF0PK9KvTGhY9APeOfxc 22 | 1PqnBU5i5StsHw620RJoM1DsGuFqG8keMSNN+eihE14x5LPJXKxb 23 | -----END CERTIFICATE----- 24 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WebApplication5")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WebApplication5")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("694ac1a1-1754-40ff-8c31-4e94bfc3dd32")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /rtcdemo/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | RTC Demo 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 |
43 | Home 44 | 45 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/SignalingServer.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug|Any CPU 5 | true 6 | 7 | 44338 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | CurrentPage 20 | True 21 | False 22 | False 23 | False 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | True 33 | False 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @ViewBag.Title - My ASP.NET Application 7 | @Styles.Render("~/Content/css") 8 | @Scripts.Render("~/bundles/modernizr") 9 | 10 | 11 | 30 |
31 | @RenderBody() 32 |
33 | 36 |
37 | 38 | @Scripts.Render("~/bundles/jquery") 39 | @Scripts.Render("~/bundles/bootstrap") 40 | @RenderSection("scripts", required: false) 41 | 42 | 43 | -------------------------------------------------------------------------------- /https/localhost.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: AES-256-CBC,0F59ABC3B3E7F7A634BE7493F68A81D2 4 | 5 | YP9ZFGhqrl3AX9iq+dlvlKeMD/PZIftS9L7gbPpHxa6T3FJpuno24AL69ucc3XDA 6 | 9bt+yuFDzI5lsGyIp5B2EG2stWzkvdAMTu+lzICGCD+kw/i5gXHB4/p8Ka3eRQ5D 7 | NHf8x+QWPA0ttSclCswifuW1x7nJPg/wPu1YdgYtv28Pm1YEEccalLdTVYm7x1ln 8 | 6w7vf++ghHA4nkVws+XsO7v61SSD63Dt4Ungn5WPomkgOQU1eZ1ir5qrvjx1QO8j 9 | RwbvpOZX968evo8KwbSHOoHc1RPtTfK83f+cyUUldnRK4xj8DOsogtDyQ6jTlkuu 10 | Jx9kwhMSU23rROTVxJEmE/iq/A1+zU0brIBKvto/Mu5+bV9WTLh8DngYbiV5Mhxm 11 | gXxU3W3rfvc2KDFpmSbCFa8fegKM7JWtCrzh0QhoodA6lXPu+6ycRzkfupnmYRK/ 12 | ovlZcZ/0fjaATAhcL9BoKl2LSwmaikmVc28IL8+ky9qQHM1abm0eUM7QQw4aTtXQ 13 | hLQ6+7aJREyQFegUg7yyjj4j1UZIymlAZptNell3EjUcOQyZPsnBuQDIJ1rynLT3 14 | w/sfQ/dmruV3BXSdiM8D5Iheb1LOQCFPIvU0fwsYTU5qSEYbat5UKbLUL1OVu1hG 15 | ULIEWHJl8O4sCIbSU9dqq/I9dDAE4ZpfO3E2RkGRdLzXXEHNh0r5xZKTw11/4ZgL 16 | BzvAX9PtKa8u5+kRoZutykCTAlJo9ZoZAtjhqk76TTjGWqSfFTKSKgjIG6LSU5MX 17 | /dd39/ox5728GKTw3VC159MbG8WKTcQvCqeOVfAzdS+GAgbZZwVnR/eQOmkQH1Jg 18 | 0KGYK614xdqHbGlnNXZx63HlYF0M/FIDtDsx8a7snX3tAeBSVJHuhsINobMfll3A 19 | YH7Vdjn+iTXtYHsbqRoMpJlsylhJ0kXywgAV3bZDLIntFpsPtQk7CmECjFXVUaDb 20 | nTAnVBcwYMtpNCxyfOe1Ew2EFOBzc4YYFf7R/klhw+z1GExs8FDluZdKQ5VGF+Ac 21 | 8rf+K3WhK866RArIbCpZBE5UwPq3/jyZL9mwb/bsVF7yVaqdyHGJgxEkEG1o7kWM 22 | ZmFsT5WXbvgtbproa/203NYkJLEgx0ZdvO7oyExbX1SNcuokvZgeH7p35SFQou7V 23 | wTGm/IVeU9KMb+tMaFopVRQEE7LDQQt/7cNNJsmdMcFD7KhTL99ipG8BDOro7Bry 24 | aNMr4G54/8Wi+O432OdpzC0gzNJi7quub5kiU8X9isApUBwP1HXw8SfWEYFQ425B 25 | 8O04mwet/THTuXed8mCImWHAKE8rrYZbKOi1hI13TR5rsOJm8qUihETGl/CDaTNG 26 | w7M4Y7GKy4+sPbAxK41WkCbM8T5cAi9gUABCPD6vhg2MYgyU55lWCMPVZblw5DMA 27 | oecbTaZxo6Hq9yr3cDQlL/XYaJLydmr+Z0kLr+xvkv4bk4QxGmJFL5X014FveZop 28 | VNnW47S7HwqI0+5brwk0/pW5777ojhHKWgpNOQJ34V4C5hNQyZp0Az9FlPS3PuoR 29 | 5o7/nMD67b5bbNVFgNI03um3VvdvMCpabVZw52xCyfLNvrCKoT3IXuSzRHrOrcCx 30 | -----END RSA PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Views/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /audio/demo.js: -------------------------------------------------------------------------------- 1 | var Demo = (function () { 2 | var _myMediaStream; // My MediaStream instance 3 | var _audioTrack; 4 | var _mediaRecorder; 5 | var _recordedChunks = []; 6 | 7 | async function _init() { 8 | eventBindingForAudio(); 9 | await startCall(); 10 | 11 | } 12 | 13 | function eventBindingForAudio() { 14 | $("#btnMuteUnmute").on('click', function () { 15 | if (!_audioTrack) return; 16 | 17 | if (_audioTrack.enabled == false) { 18 | _audioTrack.enabled = true; 19 | $(this).text("Mute"); 20 | } 21 | else { 22 | _audioTrack.enabled = false; 23 | $(this).text("UnMute"); 24 | } 25 | console.log(_audioTrack); 26 | }); 27 | 28 | $("#btnStartReco").on('click', function () { 29 | setupMediaRecorder(_myMediaStream); 30 | _mediaRecorder.start(1000); 31 | }); 32 | $("#btnPauseReco").on('click', function () { 33 | _mediaRecorder.pause(); 34 | }); 35 | $("#btnResumeReco").on('click', function () { 36 | _mediaRecorder.resume(); 37 | }); 38 | $("#btnStopReco").on('click', function () { 39 | _mediaRecorder.stop(); 40 | }); 41 | } 42 | 43 | function setupMediaRecorder(stream) { 44 | _recordedChunks = []; 45 | _mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' }); 46 | 47 | _mediaRecorder.ondataavailable = (e) => { 48 | console.log(e.data.size); 49 | if(e.data.size > 0) 50 | _recordedChunks.push(e.data); 51 | }; 52 | 53 | 54 | _mediaRecorder.onstart = async () => { 55 | $("#btnStartReco").hide(); 56 | $("#btnPauseReco").show(); 57 | $("#btnStopReco").show(); 58 | $("#downloadRecording").hide(); 59 | }; 60 | _mediaRecorder.onpause = async () => { 61 | $("#btnPauseReco").hide(); 62 | $("#btnResumeReco").show(); 63 | }; 64 | _mediaRecorder.onresume = async () => { 65 | $("#btnResumeReco").hide(); 66 | $("#btnPauseReco").show(); 67 | $("#btnStopReco").show(); 68 | }; 69 | 70 | _mediaRecorder.onstop = async () => { 71 | 72 | var blob = new Blob(_recordedChunks, { type: 'video/webm' }); 73 | 74 | let url = window.URL.createObjectURL(blob); 75 | //document.getElementById('videoCtr').src = url; 76 | 77 | $("#downloadRecording").attr({ href: url, download: 'test.weba' }).show(); 78 | 79 | $("#btnStartReco").show(); 80 | $("#btnPauseReco").hide(); 81 | $("#btnStopReco").hide(); 82 | //var download = document.getElementById('downloadRecording'); 83 | //download.href = url; 84 | //download.download = 'test.weba'; 85 | //download.style.display = 'block'; 86 | 87 | 88 | }; 89 | } 90 | 91 | async function startCall() { 92 | 93 | try { 94 | _myMediaStream = await navigator.mediaDevices.getUserMedia( 95 | { video: false, audio: true }); 96 | 97 | } catch (e) { 98 | console.log(e); 99 | } 100 | 101 | document.getElementById('audioCtr').srcObject = _myMediaStream; 102 | 103 | _audioTrack = _myMediaStream.getAudioTracks()[0]; 104 | 105 | _audioTrack.onmute = function (e) { 106 | console.log(e); 107 | } 108 | _audioTrack.onunmute = function (e) { 109 | console.log(e); 110 | } 111 | 112 | _myMediaStream.getAudioTracks().forEach(track => { 113 | console.log(track); 114 | }) 115 | 116 | } 117 | 118 | return { 119 | init: async function () { 120 | await _init(); 121 | } 122 | } 123 | }()); -------------------------------------------------------------------------------- /video/demo.js: -------------------------------------------------------------------------------- 1 | var Demo = (function () { 2 | var _audioTrack; 3 | var _videoTrack = null; 4 | 5 | var _mediaRecorder; 6 | var _recordedChunks = []; 7 | 8 | async function _init() { 9 | await startwithAudio(); 10 | eventBinding(); 11 | } 12 | 13 | function eventBinding() { 14 | 15 | $("#btnMuteUnmute").on('click', function () { 16 | if (!_audioTrack) return; 17 | 18 | if (_audioTrack.enabled == false) { 19 | _audioTrack.enabled = true; 20 | $(this).text("Mute"); 21 | } 22 | else { 23 | _audioTrack.enabled = false; 24 | $(this).text("Unmute"); 25 | } 26 | console.log(_audioTrack); 27 | }); 28 | $("#btnStartReco").on('click', function () { 29 | setupMediaRecorder(); 30 | _mediaRecorder.start(1000); 31 | }); 32 | $("#btnPauseReco").on('click', function () { 33 | _mediaRecorder.pause(); 34 | }); 35 | $("#btnResumeReco").on('click', function () { 36 | _mediaRecorder.resume(); 37 | }); 38 | $("#btnStopReco").on('click', function () { 39 | _mediaRecorder.stop(); 40 | }); 41 | 42 | $("#btnStartStopCam").on('click', async function () { 43 | 44 | if (_videoTrack) { 45 | _videoTrack.stop(); 46 | _videoTrack = null; 47 | document.getElementById('videoCtr').srcObject = null; 48 | $("#btnStartStopCam").text("Start Camera"); 49 | return; 50 | } 51 | try { 52 | var vstream = await navigator.mediaDevices.getUserMedia({ video: true }); 53 | console.log(vstream); 54 | if (vstream && vstream.getVideoTracks().length > 0) { 55 | _videoTrack = vstream.getVideoTracks()[0]; 56 | console.log(_videoTrack); 57 | document.getElementById('videoCtr').srcObject = new MediaStream([_videoTrack]); 58 | $("#btnStartStopCam").text("Stop Camera"); 59 | } 60 | } catch (e) { 61 | console.log(e); 62 | return; 63 | } 64 | }); 65 | 66 | } 67 | 68 | function setupMediaRecorder() { 69 | 70 | var stream = new MediaStream([_audioTrack]); 71 | 72 | if (_videoTrack && _videoTrack.readyState === "live") { 73 | stream.addTrack(_videoTrack); 74 | } 75 | 76 | stream.getTracks().forEach(track => { 77 | console.log(track); 78 | }) 79 | 80 | _recordedChunks = []; 81 | _mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm; codecs=vp8,opus' }); 82 | _mediaRecorder.ondataavailable = (e) => { 83 | console.log(e.data.size); 84 | if(e.data.size > 0) 85 | _recordedChunks.push(e.data); 86 | }; 87 | _mediaRecorder.onstart = async () => { 88 | console.log('onstart'); 89 | $("#btnStartReco").hide(); 90 | $("#btnPauseReco").show(); 91 | $("#btnStopReco").show(); 92 | $("#downloadRecording").hide(); 93 | }; 94 | _mediaRecorder.onpause = async () => { 95 | $("#btnPauseReco").hide(); 96 | $("#btnResumeReco").show(); 97 | }; 98 | _mediaRecorder.onresume = async () => { 99 | $("#btnResumeReco").hide(); 100 | $("#btnPauseReco").show(); 101 | $("#btnStopReco").show(); 102 | }; 103 | 104 | _mediaRecorder.onstop = async () => { 105 | console.log('onstop'); 106 | var blob = new Blob(_recordedChunks, { type: 'video/webm' }); 107 | let url = window.URL.createObjectURL(blob); 108 | 109 | var videoRecPlayer = document.getElementById('videoCtrRec'); 110 | videoRecPlayer.srcObject = null; 111 | videoRecPlayer.load(); 112 | videoRecPlayer.src = url; 113 | videoRecPlayer.play(); 114 | $(videoRecPlayer).show(); 115 | 116 | $("#downloadRecording").attr({ href: url, download: 'video.webm' }).show(); 117 | 118 | $("#btnStartReco").show(); 119 | $("#btnPauseReco").hide(); 120 | $("#btnStopReco").hide(); 121 | //var download = document.getElementById('downloadRecording'); 122 | //download.href = url; 123 | //download.download = 'test.weba'; 124 | //download.style.display = 'block'; 125 | 126 | 127 | }; 128 | } 129 | 130 | async function startwithAudio() { 131 | 132 | try { 133 | var astream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true }); 134 | 135 | _audioTrack = astream.getAudioTracks()[0]; 136 | 137 | _audioTrack.onmute = function (e) { 138 | console.log(e); 139 | } 140 | _audioTrack.onunmute = function (e) { 141 | console.log(e); 142 | } 143 | 144 | _audioTrack.enabled = false; 145 | 146 | } catch (e) { 147 | console.log(e); 148 | return; 149 | } 150 | } 151 | 152 | return { 153 | init: async function () { 154 | await _init(); 155 | } 156 | } 157 | }()); -------------------------------------------------------------------------------- /screenshare1/demo.js: -------------------------------------------------------------------------------- 1 | var Demo = (function () { 2 | var _audioTrack; 3 | var _screenTrack = null; 4 | 5 | var _mediaRecorder; 6 | var _recordedChunks = []; 7 | 8 | async function _init() { 9 | 10 | await startwithAudio(); 11 | eventBinding(); 12 | } 13 | 14 | function eventBinding() { 15 | 16 | $("#btnMuteUnmute").on('click', function () { 17 | if (!_audioTrack) return; 18 | 19 | if (_audioTrack.enabled == false) { 20 | _audioTrack.enabled = true; 21 | $(this).text("Mute"); 22 | } 23 | else { 24 | _audioTrack.enabled = false; 25 | $(this).text("Unmute"); 26 | } 27 | console.log(_audioTrack); 28 | }); 29 | $("#btnStartReco").on('click', function () { 30 | setupMediaRecorder(); 31 | _mediaRecorder.start(1000); 32 | }); 33 | $("#btnPauseReco").on('click', function () { 34 | _mediaRecorder.pause(); 35 | }); 36 | $("#btnResumeReco").on('click', function () { 37 | _mediaRecorder.resume(); 38 | }); 39 | $("#btnStopReco").on('click', function () { 40 | _mediaRecorder.stop(); 41 | }); 42 | 43 | 44 | $("#btnStartStopScreenshare").on('click', async function () { 45 | 46 | if (_screenTrack) { 47 | _screenTrack.stop(); 48 | _screenTrack = null; 49 | document.getElementById('screenShare').srcObject = null; 50 | $(this).text("Screen Share"); 51 | return; 52 | } 53 | try { 54 | var sc_stream = await navigator.mediaDevices.getDisplayMedia({ 55 | audio: false, 56 | video: { 57 | frameRate: 1, 58 | }, 59 | }); 60 | if (sc_stream && sc_stream.getVideoTracks().length > 0) { 61 | _screenTrack = sc_stream.getVideoTracks()[0]; 62 | document.getElementById('screenShare').srcObject = new MediaStream([_screenTrack]); 63 | $(this).text("Stop Share"); 64 | } 65 | _screenStream = sc_stream; 66 | } catch (e) { 67 | console.log(e); 68 | return; 69 | } 70 | }); 71 | } 72 | 73 | function setupMediaRecorder() { 74 | debugger; 75 | 76 | var stream = new MediaStream([_audioTrack]); 77 | 78 | if (_screenTrack && _screenTrack.readyState === "live") { 79 | stream.addTrack(_screenTrack); 80 | } 81 | 82 | stream.getTracks().forEach(track => { 83 | console.log(track); 84 | }) 85 | 86 | _recordedChunks = []; 87 | _mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm; codecs=vp8,opus' }); 88 | _mediaRecorder.ondataavailable = (e) => { 89 | console.log(e.data.size); 90 | if(e.data.size > 0) 91 | _recordedChunks.push(e.data); 92 | }; 93 | _mediaRecorder.onstart = async () => { 94 | console.log('onstart'); 95 | $("#btnStartReco").hide(); 96 | $("#btnPauseReco").show(); 97 | $("#btnStopReco").show(); 98 | $("#downloadRecording").hide(); 99 | }; 100 | _mediaRecorder.onpause = async () => { 101 | $("#btnPauseReco").hide(); 102 | $("#btnResumeReco").show(); 103 | }; 104 | _mediaRecorder.onresume = async () => { 105 | $("#btnResumeReco").hide(); 106 | $("#btnPauseReco").show(); 107 | $("#btnStopReco").show(); 108 | }; 109 | 110 | _mediaRecorder.onstop = async () => { 111 | console.log('onstop'); 112 | var blob = new Blob(_recordedChunks, { type: 'video/webm' }); 113 | let url = window.URL.createObjectURL(blob); 114 | 115 | var videoRecPlayer = document.getElementById('videoCtrRec'); 116 | videoRecPlayer.src = url; 117 | videoRecPlayer.play(); 118 | $(videoRecPlayer).show(); 119 | 120 | $("#downloadRecording").attr({ href: url, download: 'video.webm' }).show(); 121 | $("#btnStartReco").show(); 122 | $("#btnPauseReco").hide(); 123 | $("#btnStopReco").hide(); 124 | //var download = document.getElementById('downloadRecording'); 125 | //download.href = url; 126 | //download.download = 'test.weba'; 127 | //download.style.display = 'block'; 128 | }; 129 | } 130 | 131 | async function startwithAudio() { 132 | 133 | try { 134 | var astream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true }); 135 | 136 | _audioTrack = astream.getAudioTracks()[0]; 137 | 138 | _audioTrack.onmute = function (e) { 139 | console.log(e); 140 | } 141 | _audioTrack.onunmute = function (e) { 142 | console.log(e); 143 | } 144 | 145 | _audioTrack.enabled = false; 146 | 147 | } catch (e) { 148 | console.log(e); 149 | return; 150 | } 151 | } 152 | 153 | return { 154 | init: async function () { 155 | await _init(); 156 | } 157 | } 158 | }()); -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Scripts/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | // Unobtrusive validation support library for jQuery and jQuery Validate 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 4 | // @version v3.2.11 5 | !function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function u(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=f.unobtrusive.options||{},u=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),u("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),u("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),u("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var m,f=a.validator,v="unobtrusiveValidation";return f.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=u(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){f.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=u(this);a&&a.attachValidation()})}},m=f.unobtrusive.adapters,m.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},m.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},m.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},m.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},f.addMethod("__dummy__",function(a,e,n){return!0}),f.addMethod("regex",function(a,e,n){var t;return!!this.optional(e)||(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),f.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),f.methods.extension?(m.addSingleVal("accept","mimtype"),m.addSingleVal("extension","extension")):m.addSingleVal("extension","extension","accept"),m.addSingleVal("regex","pattern"),m.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),m.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),m.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),m.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),m.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||e(a,"required",!0)}),m.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),m.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),m.add("fileextensions",["extensions"],function(a){e(a,"extension",a.params.extensions)}),a(function(){f.unobtrusive.parse(document)}),f.unobtrusive}); -------------------------------------------------------------------------------- /rtcdemo/video-stream-merger.js: -------------------------------------------------------------------------------- 1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.VideoStreamMerger = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i=c&&b._requestAnimationFrame(b._draw.bind(b))}var b=this;if(b.started){var c=b._streams.length;b.clearRect&&b._ctx.clearRect(0,0,b.width,b.height),b._streams.forEach(function(c){c.draw?c.draw(b._ctx,c.element,a):!c.isData&&c.hasVideo?(b._ctx.drawImage(c.element,c.x,c.y,c.width,c.height),a()):a()}),0===b._streams.length&&a()}},VideoStreamMerger.prototype.destroy=function(){var a=this;a.started=!1,a._canvas=null,a._ctx=null,a._streams=[],a._audioCtx.close(),a._audioCtx=null,a._audioDestination=null,a.result.getTracks().forEach(function(a){a.stop()}),a.result=null}; 3 | 4 | },{}]},{},[1])(1) 5 | }); 6 | -------------------------------------------------------------------------------- /screenshare2/video-stream-merger.js: -------------------------------------------------------------------------------- 1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.VideoStreamMerger = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i=c&&b._requestAnimationFrame(b._draw.bind(b))}var b=this;if(b.started){var c=b._streams.length;b.clearRect&&b._ctx.clearRect(0,0,b.width,b.height),b._streams.forEach(function(c){c.draw?c.draw(b._ctx,c.element,a):!c.isData&&c.hasVideo?(b._ctx.drawImage(c.element,c.x,c.y,c.width,c.height),a()):a()}),0===b._streams.length&&a()}},VideoStreamMerger.prototype.destroy=function(){var a=this;a.started=!1,a._canvas=null,a._ctx=null,a._streams=[],a._audioCtx.close(),a._audioCtx=null,a._audioDestination=null,a.result.getTracks().forEach(function(a){a.stop()}),a.result=null}; 3 | 4 | },{}]},{},[1])(1) 5 | }); 6 | -------------------------------------------------------------------------------- /screenshare2/demo.js: -------------------------------------------------------------------------------- 1 | var Demo = (function () { 2 | var _audioTrack; 3 | var _videoTrack = null; 4 | var _screenTrack = null; 5 | 6 | var _mediaRecorder; 7 | var _recordedChunks = []; 8 | 9 | async function _init() { 10 | 11 | await startwithAudio(); 12 | eventBinding(); 13 | 14 | } 15 | 16 | function eventBinding() { 17 | 18 | $("#btnMuteUnmute").on('click', function () { 19 | if (!_audioTrack) return; 20 | 21 | if (_audioTrack.enabled == false) { 22 | _audioTrack.enabled = true; 23 | $(this).text("Mute"); 24 | } 25 | else { 26 | _audioTrack.enabled = false; 27 | $(this).text("Unmute"); 28 | } 29 | console.log(_audioTrack); 30 | }); 31 | $("#btnStartReco").on('click', function () { 32 | setupMediaRecorder(); 33 | _mediaRecorder.start(1000); 34 | }); 35 | $("#btnPauseReco").on('click', function () { 36 | _mediaRecorder.pause(); 37 | }); 38 | $("#btnResumeReco").on('click', function () { 39 | _mediaRecorder.resume(); 40 | }); 41 | $("#btnStopReco").on('click', function () { 42 | _mediaRecorder.stop(); 43 | }); 44 | 45 | 46 | $("#btnStartStopCam").on('click', async function () { 47 | 48 | if (_videoTrack) { 49 | _videoTrack.stop(); 50 | _videoTrack = null; 51 | document.getElementById('videoCtr').srcObject = null; 52 | $("#btnStartStopCam").text("Start Camera"); 53 | return; 54 | } 55 | try { 56 | var vstream = await navigator.mediaDevices.getUserMedia({ 57 | video: { 58 | width: 200, 59 | height: 200 60 | }, 61 | audio:false 62 | }); 63 | 64 | if (vstream && vstream.getVideoTracks().length > 0) { 65 | _videoTrack = vstream.getVideoTracks()[0]; 66 | document.getElementById('videoCtr').srcObject = new MediaStream([_videoTrack]); 67 | $("#btnStartStopCam").text("Stop Camera"); 68 | } 69 | 70 | } catch (e) { 71 | console.log(e); 72 | return; 73 | } 74 | }); 75 | 76 | $("#btnStartStopScreenshare").on('click', async function () { 77 | 78 | if (_screenTrack) { 79 | _screenTrack.stop(); 80 | _screenTrack = null; 81 | document.getElementById('screenShare').srcObject = null; 82 | $(this).text("Screen Share"); 83 | return; 84 | } 85 | try { 86 | var sc_stream = await navigator.mediaDevices.getDisplayMedia({ 87 | audio: false, 88 | video: { 89 | frameRate: 1, 90 | }, 91 | }); 92 | if (sc_stream && sc_stream.getVideoTracks().length > 0) { 93 | _screenTrack = sc_stream.getVideoTracks()[0]; 94 | document.getElementById('screenShare').srcObject = new MediaStream([_screenTrack]); 95 | $(this).text("Stop Share"); 96 | } 97 | _screenStream = sc_stream; 98 | } catch (e) { 99 | console.log(e); 100 | return; 101 | } 102 | }); 103 | } 104 | 105 | function setupMediaRecorder() { 106 | debugger; 107 | 108 | var _width = 0; 109 | var _height = 0; 110 | 111 | if (_screenTrack) { 112 | _width = _screenTrack.getSettings().width; 113 | _height = _screenTrack.getSettings().height; 114 | } 115 | else if (_videoTrack) { 116 | _width = _videoTrack.getSettings().width; 117 | _height = _videoTrack.getSettings().height; 118 | } 119 | 120 | var merger = new VideoStreamMerger({ 121 | width: _width, // Width of the output video 122 | height: _height, // Height of the output video 123 | //fps: 1, // Video capture frames per second 124 | audioContext: null, 125 | }) 126 | 127 | if (_screenTrack && _screenTrack.readyState === "live") { 128 | // Add the screen capture.Position it to fill the whole stream (the default) 129 | merger.addStream(new MediaStream([_screenTrack]), { 130 | x: 0, // position of the topleft corner 131 | y: 0, 132 | //width: _screenTrack.getSettings().width, 133 | //height: _screenTrack.getSettings().height, 134 | mute: true // we don't want sound from the screen (if there is any) 135 | }); 136 | 137 | if (_videoTrack && _videoTrack.readyState === "live") { 138 | // Add the webcam stream. Position it on the bottom left and resize it to 100x100. 139 | merger.addStream(new MediaStream([_videoTrack]), { 140 | x: 0, 141 | y: merger.height - 100, 142 | width: 100, 143 | height: 100, 144 | mute: true 145 | }); 146 | } 147 | } 148 | else { 149 | if (_videoTrack && _videoTrack.readyState === "live") { 150 | // Add the webcam stream. 151 | merger.addStream(new MediaStream([_videoTrack]), { 152 | x: 0, 153 | y: 0, 154 | width: _width, 155 | height: _height, 156 | mute: true 157 | }); 158 | } 159 | } 160 | 161 | 162 | if (_audioTrack && _audioTrack.readyState === "live") { 163 | // Add the webcam stream. Position it on the bottom left and resize it to 100x100. 164 | merger.addStream(new MediaStream([_audioTrack]), { 165 | mute: false 166 | }); 167 | } 168 | 169 | // Start the merging. Calling this makes the result available to us 170 | merger.start() 171 | 172 | // We now have a merged MediaStream! 173 | var stream = merger.result; 174 | var videoRecPlayer = document.getElementById('videoCtrRec'); 175 | videoRecPlayer.srcObject = stream; 176 | videoRecPlayer.load(); 177 | $(videoRecPlayer).show(); 178 | 179 | //stream.addTrack(_audioTrack); 180 | //var stream = new MediaStream([_audioTrack]); 181 | 182 | //if (_videoTrack && _videoTrack.readyState === "live") { 183 | // stream.addTrack(_videoTrack); 184 | //} 185 | 186 | //if (_screenTrack && _screenTrack.readyState === "live") { 187 | // stream.addTrack(_screenTrack); 188 | //} 189 | 190 | stream.getTracks().forEach(track => { 191 | console.log(track); 192 | }) 193 | 194 | _recordedChunks = []; 195 | _mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm; codecs=vp8,opus' }); 196 | _mediaRecorder.ondataavailable = (e) => { 197 | console.log(e.data.size); 198 | if(e.data.size > 0) 199 | _recordedChunks.push(e.data); 200 | }; 201 | _mediaRecorder.onstart = async () => { 202 | console.log('onstart'); 203 | $("#btnStartReco").hide(); 204 | $("#btnPauseReco").show(); 205 | $("#btnStopReco").show(); 206 | $("#downloadRecording").hide(); 207 | }; 208 | _mediaRecorder.onpause = async () => { 209 | $("#btnPauseReco").hide(); 210 | $("#btnResumeReco").show(); 211 | }; 212 | _mediaRecorder.onresume = async () => { 213 | $("#btnResumeReco").hide(); 214 | $("#btnPauseReco").show(); 215 | $("#btnStopReco").show(); 216 | }; 217 | 218 | _mediaRecorder.onstop = async () => { 219 | console.log('onstop'); 220 | var blob = new Blob(_recordedChunks, { type: 'video/webm' }); 221 | let url = window.URL.createObjectURL(blob); 222 | 223 | 224 | videoRecPlayer.srcObject = null; 225 | videoRecPlayer.load(); 226 | videoRecPlayer.src = url; 227 | videoRecPlayer.play(); 228 | $(videoRecPlayer).show(); 229 | 230 | $("#downloadRecording").attr({ href: url, download: 'video.webm' }).show(); 231 | 232 | $("#btnStartReco").show(); 233 | $("#btnPauseReco").hide(); 234 | $("#btnStopReco").hide(); 235 | //var download = document.getElementById('downloadRecording'); 236 | //download.href = url; 237 | //download.download = 'test.weba'; 238 | //download.style.display = 'block'; 239 | 240 | 241 | }; 242 | } 243 | 244 | async function startwithAudio() { 245 | 246 | try { 247 | var astream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true }); 248 | 249 | _audioTrack = astream.getAudioTracks()[0]; 250 | 251 | _audioTrack.onmute = function (e) { 252 | console.log(e); 253 | } 254 | _audioTrack.onunmute = function (e) { 255 | console.log(e); 256 | } 257 | 258 | _audioTrack.enabled = false; 259 | 260 | } catch (e) { 261 | console.log(e); 262 | return; 263 | } 264 | } 265 | 266 | return { 267 | init: async function () { 268 | await _init(); 269 | } 270 | } 271 | }()); -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/SignalingServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | 9 | 10 | 2.0 11 | {A01DE8A2-49D7-454B-8E7B-1143CB5D82FA} 12 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 13 | Library 14 | Properties 15 | WebApplication5 16 | WebApplication5 17 | v4.8 18 | false 19 | true 20 | 21 | 44338 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | true 31 | full 32 | false 33 | bin\ 34 | DEBUG;TRACE 35 | prompt 36 | 4 37 | 38 | 39 | true 40 | pdbonly 41 | true 42 | bin\ 43 | TRACE 44 | prompt 45 | 4 46 | 47 | 48 | 49 | ..\packages\Microsoft.AspNet.SignalR.Core.2.2.2\lib\net45\Microsoft.AspNet.SignalR.Core.dll 50 | 51 | 52 | ..\packages\Microsoft.AspNet.SignalR.SystemWeb.2.2.2\lib\net45\Microsoft.AspNet.SignalR.SystemWeb.dll 53 | 54 | 55 | ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll 56 | 57 | 58 | 59 | ..\packages\Microsoft.Owin.4.1.0\lib\net45\Microsoft.Owin.dll 60 | 61 | 62 | ..\packages\Microsoft.Owin.Cors.4.1.0\lib\net45\Microsoft.Owin.Cors.dll 63 | 64 | 65 | ..\packages\Microsoft.Owin.Host.SystemWeb.4.0.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll 66 | 67 | 68 | ..\packages\Microsoft.Owin.Security.4.0.1\lib\net45\Microsoft.Owin.Security.dll 69 | 70 | 71 | ..\packages\Owin.1.0\lib\net40\Owin.dll 72 | 73 | 74 | 75 | 76 | 77 | ..\packages\Microsoft.AspNet.Cors.5.0.0\lib\net45\System.Web.Cors.dll 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | True 96 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll 97 | 98 | 99 | 100 | 101 | 102 | 103 | True 104 | ..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.Helpers.dll 105 | 106 | 107 | True 108 | ..\packages\Microsoft.AspNet.Mvc.5.2.7\lib\net45\System.Web.Mvc.dll 109 | 110 | 111 | ..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll 112 | 113 | 114 | True 115 | ..\packages\Microsoft.AspNet.Razor.3.2.7\lib\net45\System.Web.Razor.dll 116 | 117 | 118 | True 119 | ..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.dll 120 | 121 | 122 | True 123 | ..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Deployment.dll 124 | 125 | 126 | True 127 | ..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Razor.dll 128 | 129 | 130 | ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll 131 | 132 | 133 | True 134 | ..\packages\WebGrease.1.6.0\lib\WebGrease.dll 135 | 136 | 137 | True 138 | ..\packages\Antlr.3.5.0.2\lib\Antlr3.Runtime.dll 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | Global.asax 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | Web.config 180 | 181 | 182 | Web.config 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 10.0 208 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | True 221 | True 222 | 50537 223 | / 224 | https://localhost:44338/ 225 | False 226 | False 227 | 228 | 229 | False 230 | 231 | 232 | 233 | 234 | 235 | 236 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 237 | 238 | 239 | 240 | 246 | -------------------------------------------------------------------------------- /rtcdemo/demo.js: -------------------------------------------------------------------------------- 1 | var Demo = (function () { 2 | var _audioTrack; 3 | var _videoTrack = null; 4 | var _screenTrack = null; 5 | 6 | var _mediaRecorder; 7 | var _recordedChunks = []; 8 | 9 | var connection = null; 10 | var _remoteStream = new MediaStream(); 11 | 12 | var _localVideo; 13 | 14 | var _rtpSender; 15 | 16 | // Set up the SignalR connection 17 | var hub = $.connection.webRtcHub; 18 | $.connection.hub.url = 'https://localhost:44338/signalr/hubs'; 19 | $.connection.hub.start(function () { 20 | console.log('connected to signal server.'); 21 | }); 22 | 23 | async function _init() { 24 | 25 | _localVideo = document.getElementById('videoCtr'); 26 | 27 | eventBinding(); 28 | } 29 | 30 | function eventBinding() { 31 | 32 | $("#btnMuteUnmute").on('click', function () { 33 | if (!_audioTrack) return; 34 | 35 | if (_audioTrack.enabled == false) { 36 | _audioTrack.enabled = true; 37 | $(this).text("Mute"); 38 | } 39 | else { 40 | _audioTrack.enabled = false; 41 | $(this).text("Unmute"); 42 | } 43 | console.log(_audioTrack); 44 | }); 45 | $("#btnStartReco").on('click', function () { 46 | setupMediaRecorder(); 47 | _mediaRecorder.start(1000); 48 | }); 49 | $("#btnPauseReco").on('click', function () { 50 | _mediaRecorder.pause(); 51 | }); 52 | $("#btnResumeReco").on('click', function () { 53 | _mediaRecorder.resume(); 54 | }); 55 | $("#btnStopReco").on('click', function () { 56 | _mediaRecorder.stop(); 57 | }); 58 | 59 | $("#btnStartStopCam").on('click', async function () { 60 | 61 | if (_videoTrack) { 62 | _videoTrack.stop(); 63 | _videoTrack = null; 64 | _localVideo.srcObject = null; 65 | $("#btnStartStopCam").text("Start Camera"); 66 | 67 | if (_rtpSender && connection) { 68 | connection.removeTrack(_rtpSender); 69 | _rtpSender = null; 70 | } 71 | 72 | return; 73 | } 74 | try { 75 | var vstream = await navigator.mediaDevices.getUserMedia({ 76 | video: { 77 | width: 200, 78 | height: 200 79 | }, 80 | audio: false 81 | }); 82 | if (vstream && vstream.getVideoTracks().length > 0) { 83 | _videoTrack = vstream.getVideoTracks()[0]; 84 | setLocalVideo(true); 85 | //_localVideo.srcObject = new MediaStream([_videoTrack]); 86 | $("#btnStartStopCam").text("Stop Camera"); 87 | } 88 | //debugger; 89 | //if (_rtpSender && _rtpSender.track && _videoTrack && connection) { 90 | // _rtpSender.replaceTrack(_videoTrack); 91 | //} 92 | //else { 93 | // if (_videoTrack && connection) 94 | // _rtpSender = connection.addTrack(_videoTrack); 95 | //} 96 | 97 | 98 | } catch (e) { 99 | console.log(e); 100 | return; 101 | } 102 | }); 103 | 104 | $("#btnStartStopScreenshare").on('click', async function () { 105 | 106 | if (_screenTrack) { 107 | _screenTrack.stop(); 108 | _screenTrack = null; 109 | _localVideo.srcObject = null; 110 | $(this).text("Screen Share"); 111 | 112 | if (_rtpSender && connection) { 113 | connection.removeTrack(_rtpSender); 114 | _rtpSender = null; 115 | } 116 | return; 117 | } 118 | try { 119 | var sc_stream = await navigator.mediaDevices.getDisplayMedia({ 120 | audio: false, 121 | video: { 122 | frameRate: 1, 123 | }, 124 | }); 125 | if (sc_stream && sc_stream.getVideoTracks().length > 0) { 126 | _screenTrack = sc_stream.getVideoTracks()[0]; 127 | setLocalVideo(false); 128 | //_localVideo.srcObject = new MediaStream([_screenTrack]); 129 | $(this).text("Stop Share"); 130 | } 131 | 132 | //if (_videoTrack) { 133 | // connection.removeTrack(_videoTrack); 134 | //} 135 | 136 | //if (_screenTrack && connection) 137 | // connection.addTrack(_screenTrack); 138 | 139 | //if (_rtpSender && _rtpSender.track && _screenTrack && connection) { 140 | // _rtpSender.replaceTrack(_screenTrack); 141 | //} 142 | //else { 143 | // if (_screenTrack && connection) 144 | // _rtpSender = connection.addTrack(_screenTrack); 145 | //} 146 | 147 | } catch (e) { 148 | console.log(e); 149 | return; 150 | } 151 | }); 152 | 153 | $("#startConnection").on('click', async function () { 154 | await startwithAudio(); 155 | await _createConnection(); 156 | //await _createOffer(); 157 | }); 158 | } 159 | 160 | function setLocalVideo(isVideo) { 161 | var currtrack; 162 | 163 | if (isVideo) { 164 | if (_screenTrack) 165 | $("#btnStartStopScreenshare").trigger('click'); 166 | 167 | if (_videoTrack) { 168 | _localVideo.srcObject = new MediaStream([_videoTrack]); 169 | currtrack = _videoTrack; 170 | } 171 | 172 | } 173 | else { 174 | if (_videoTrack) 175 | $("#btnStartStopCam").trigger('click'); 176 | 177 | if (_screenTrack) { 178 | _localVideo.srcObject = new MediaStream([_screenTrack]); 179 | currtrack = _screenTrack; 180 | } 181 | } 182 | 183 | if (_rtpSender && _rtpSender.track && currtrack && connection) { 184 | _rtpSender.replaceTrack(currtrack); 185 | } 186 | else { 187 | if (currtrack && connection) 188 | _rtpSender = connection.addTrack(currtrack); 189 | } 190 | } 191 | 192 | function setupMediaRecorder() { 193 | 194 | var _width = 0; 195 | var _height = 0; 196 | 197 | if (_screenTrack) { 198 | _width = _screenTrack.getSettings().width; 199 | _height = _screenTrack.getSettings().height; 200 | } 201 | else if (_videoTrack) { 202 | _width = _videoTrack.getSettings().width; 203 | _height = _videoTrack.getSettings().height; 204 | } 205 | 206 | var merger = new VideoStreamMerger({ 207 | width: _width, // Width of the output video 208 | height: _height, // Height of the output video 209 | //fps: 1, // Video capture frames per second 210 | audioContext: null, 211 | }) 212 | 213 | if (_screenTrack && _screenTrack.readyState === "live") { 214 | // Add the screen capture.Position it to fill the whole stream (the default) 215 | merger.addStream(new MediaStream([_screenTrack]), { 216 | x: 0, // position of the topleft corner 217 | y: 0, 218 | //width: _screenTrack.getSettings().width, 219 | //height: _screenTrack.getSettings().height, 220 | mute: true // we don't want sound from the screen (if there is any) 221 | }); 222 | 223 | if (_videoTrack && _videoTrack.readyState === "live") { 224 | // Add the webcam stream. Position it on the bottom left and resize it to 100x100. 225 | merger.addStream(new MediaStream([_videoTrack]), { 226 | x: 0, 227 | y: merger.height - 100, 228 | width: 100, 229 | height: 100, 230 | mute: true 231 | }); 232 | } 233 | } 234 | else { 235 | if (_videoTrack && _videoTrack.readyState === "live") { 236 | // Add the webcam stream. 237 | merger.addStream(new MediaStream([_videoTrack]), { 238 | x: 0, 239 | y: 0, 240 | width: _width, 241 | height: _height, 242 | mute: true 243 | }); 244 | } 245 | } 246 | 247 | 248 | if (_audioTrack && _audioTrack.readyState === "live") { 249 | // Add the webcam stream. Position it on the bottom left and resize it to 100x100. 250 | merger.addStream(new MediaStream([_audioTrack]), { 251 | mute: false 252 | }); 253 | } 254 | 255 | // Start the merging. Calling this makes the result available to us 256 | merger.start() 257 | 258 | // We now have a merged MediaStream! 259 | var stream = merger.result; 260 | var videoRecPlayer = document.getElementById('videoCtrRec'); 261 | videoRecPlayer.srcObject = stream; 262 | videoRecPlayer.load(); 263 | $(videoRecPlayer).show(); 264 | 265 | stream.getTracks().forEach(track => { 266 | console.log(track); 267 | }) 268 | 269 | _recordedChunks = []; 270 | _mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm; codecs=vp8,opus' }); 271 | _mediaRecorder.ondataavailable = (e) => { 272 | console.log(e.data.size); 273 | if (e.data.size > 0) 274 | _recordedChunks.push(e.data); 275 | }; 276 | _mediaRecorder.onstart = async () => { 277 | console.log('onstart'); 278 | $("#btnStartReco").hide(); 279 | $("#btnPauseReco").show(); 280 | $("#btnStopReco").show(); 281 | $("#downloadRecording").hide(); 282 | }; 283 | _mediaRecorder.onpause = async () => { 284 | $("#btnPauseReco").hide(); 285 | $("#btnResumeReco").show(); 286 | }; 287 | _mediaRecorder.onresume = async () => { 288 | $("#btnResumeReco").hide(); 289 | $("#btnPauseReco").show(); 290 | $("#btnStopReco").show(); 291 | }; 292 | 293 | _mediaRecorder.onstop = async () => { 294 | console.log('onstop'); 295 | var blob = new Blob(_recordedChunks, { type: 'video/webm' }); 296 | let url = window.URL.createObjectURL(blob); 297 | 298 | 299 | videoRecPlayer.srcObject = null; 300 | videoRecPlayer.load(); 301 | videoRecPlayer.src = url; 302 | videoRecPlayer.play(); 303 | $(videoRecPlayer).show(); 304 | 305 | $("#downloadRecording").attr({ href: url, download: 'video.webm' }).show(); 306 | 307 | $("#btnStartReco").show(); 308 | $("#btnPauseReco").hide(); 309 | $("#btnStopReco").hide(); 310 | //var download = document.getElementById('downloadRecording'); 311 | //download.href = url; 312 | //download.download = 'test.weba'; 313 | //download.style.display = 'block'; 314 | 315 | 316 | }; 317 | } 318 | 319 | async function startwithAudio() { 320 | 321 | try { 322 | var astream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true }); 323 | 324 | _audioTrack = astream.getAudioTracks()[0]; 325 | 326 | _audioTrack.onmute = function (e) { 327 | console.log(e); 328 | } 329 | _audioTrack.onunmute = function (e) { 330 | console.log(e); 331 | } 332 | 333 | _audioTrack.enabled = false; 334 | 335 | } catch (e) { 336 | console.log(e); 337 | return; 338 | } 339 | } 340 | 341 | hub.client.newMessage = async function (message) { 342 | console.log('messag', message); 343 | message = JSON.parse(message); 344 | 345 | if (message.rejected) { 346 | alert('other user rejected'); 347 | } 348 | else if (message.answer) { 349 | console.log('answer', message.answer); 350 | await connection.setRemoteDescription(new RTCSessionDescription(message.answer)); 351 | } 352 | else if (message.offer) { 353 | console.log('offer', message.offer); 354 | var r = true; 355 | 356 | if (!_audioTrack) { 357 | r = confirm('want to continue?'); 358 | if (r) { 359 | await startwithAudio(); 360 | if (_audioTrack) { 361 | connection.addTrack(_audioTrack); 362 | } 363 | } 364 | else { 365 | hub.server.send(JSON.stringify({ 'rejected': 'true' })); 366 | } 367 | } 368 | if (_audioTrack) { 369 | 370 | if (!connection) { 371 | await _createConnection(); 372 | } 373 | 374 | await connection.setRemoteDescription(new RTCSessionDescription(message.offer)); 375 | var answer = await connection.createAnswer(); 376 | await connection.setLocalDescription(answer); 377 | hub.server.send(JSON.stringify({ 'answer': answer })); 378 | } 379 | } 380 | else if (message.iceCandidate) { 381 | console.log('iceCandidate', message.iceCandidate); 382 | if (!connection) { 383 | await _createConnection(); 384 | } 385 | try { 386 | await connection.addIceCandidate(message.iceCandidate); 387 | } catch (e) { 388 | console.log(e); 389 | } 390 | } 391 | } 392 | 393 | async function _createConnection() { 394 | 395 | console.log('_createConnection'); 396 | 397 | connection = new RTCPeerConnection(null); 398 | connection.onicecandidate = function (event) { 399 | console.log('onicecandidate', event.candidate); 400 | if (event.candidate) { 401 | hub.server.send(JSON.stringify({ 'iceCandidate': event.candidate })); 402 | } 403 | } 404 | connection.onicecandidateerror = function (event) { 405 | console.log('onicecandidateerror', event); 406 | 407 | } 408 | connection.onicegatheringstatechange = function (event) { 409 | console.log('onicegatheringstatechange', event); 410 | }; 411 | connection.onnegotiationneeded = async function (event) { 412 | await _createOffer(); 413 | } 414 | connection.onconnectionstatechange = function (event) { 415 | console.log('onconnectionstatechange', connection.connectionState) 416 | //if (connection.connectionState === "connected") { 417 | // console.log('connected') 418 | //} 419 | } 420 | // New remote media stream was added 421 | connection.ontrack = function (event) { 422 | 423 | 424 | if (!_remoteStream) 425 | _remoteStream = new MediaStream(); 426 | 427 | if (event.streams.length > 0) { 428 | 429 | //_remoteStream = event.streams[0]; 430 | } 431 | 432 | if (event.track.kind == 'video') { 433 | _remoteStream.getVideoTracks().forEach(t => _remoteStream.removeTrack(t)); 434 | } 435 | 436 | _remoteStream.addTrack(event.track); 437 | 438 | _remoteStream.getTracks().forEach(t => console.log(t)); 439 | 440 | var newVideoElement = document.getElementById('remoteVideoCtr'); 441 | 442 | 443 | newVideoElement.srcObject = null; 444 | newVideoElement.srcObject = _remoteStream; 445 | newVideoElement.load(); 446 | //newVideoElement.play(); 447 | }; 448 | 449 | 450 | if (_videoTrack) { 451 | _rtpSender = connection.addTrack(_videoTrack); 452 | } 453 | 454 | if (_screenTrack) { 455 | _rtpSender = connection.addTrack(_screenTrack); 456 | } 457 | 458 | if (_audioTrack) { 459 | connection.addTrack(_audioTrack, _remoteStream); 460 | } 461 | 462 | } 463 | 464 | async function _createOffer() { 465 | debugger; 466 | var offer = await connection.createOffer(); 467 | await connection.setLocalDescription(offer); 468 | console.log('offer', offer); 469 | console.log('localDescription', connection.localDescription); 470 | //Send offer to Server 471 | hub.server.send(JSON.stringify({ 'offer': connection.localDescription })); 472 | } 473 | 474 | return { 475 | init: async function () { 476 | await _init(); 477 | } 478 | } 479 | }()); -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Scripts/jquery.validate.unobtrusive.js: -------------------------------------------------------------------------------- 1 | // Unobtrusive validation support library for jQuery and jQuery Validate 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 4 | // @version v3.2.11 5 | 6 | /*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ 7 | /*global document: false, jQuery: false */ 8 | 9 | (function (factory) { 10 | if (typeof define === 'function' && define.amd) { 11 | // AMD. Register as an anonymous module. 12 | define("jquery.validate.unobtrusive", ['jquery-validation'], factory); 13 | } else if (typeof module === 'object' && module.exports) { 14 | // CommonJS-like environments that support module.exports 15 | module.exports = factory(require('jquery-validation')); 16 | } else { 17 | // Browser global 18 | jQuery.validator.unobtrusive = factory(jQuery); 19 | } 20 | }(function ($) { 21 | var $jQval = $.validator, 22 | adapters, 23 | data_validation = "unobtrusiveValidation"; 24 | 25 | function setValidationValues(options, ruleName, value) { 26 | options.rules[ruleName] = value; 27 | if (options.message) { 28 | options.messages[ruleName] = options.message; 29 | } 30 | } 31 | 32 | function splitAndTrim(value) { 33 | return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g); 34 | } 35 | 36 | function escapeAttributeValue(value) { 37 | // As mentioned on http://api.jquery.com/category/selectors/ 38 | return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1"); 39 | } 40 | 41 | function getModelPrefix(fieldName) { 42 | return fieldName.substr(0, fieldName.lastIndexOf(".") + 1); 43 | } 44 | 45 | function appendModelPrefix(value, prefix) { 46 | if (value.indexOf("*.") === 0) { 47 | value = value.replace("*.", prefix); 48 | } 49 | return value; 50 | } 51 | 52 | function onError(error, inputElement) { // 'this' is the form element 53 | var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"), 54 | replaceAttrValue = container.attr("data-valmsg-replace"), 55 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null; 56 | 57 | container.removeClass("field-validation-valid").addClass("field-validation-error"); 58 | error.data("unobtrusiveContainer", container); 59 | 60 | if (replace) { 61 | container.empty(); 62 | error.removeClass("input-validation-error").appendTo(container); 63 | } 64 | else { 65 | error.hide(); 66 | } 67 | } 68 | 69 | function onErrors(event, validator) { // 'this' is the form element 70 | var container = $(this).find("[data-valmsg-summary=true]"), 71 | list = container.find("ul"); 72 | 73 | if (list && list.length && validator.errorList.length) { 74 | list.empty(); 75 | container.addClass("validation-summary-errors").removeClass("validation-summary-valid"); 76 | 77 | $.each(validator.errorList, function () { 78 | $("
  • ").html(this.message).appendTo(list); 79 | }); 80 | } 81 | } 82 | 83 | function onSuccess(error) { // 'this' is the form element 84 | var container = error.data("unobtrusiveContainer"); 85 | 86 | if (container) { 87 | var replaceAttrValue = container.attr("data-valmsg-replace"), 88 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null; 89 | 90 | container.addClass("field-validation-valid").removeClass("field-validation-error"); 91 | error.removeData("unobtrusiveContainer"); 92 | 93 | if (replace) { 94 | container.empty(); 95 | } 96 | } 97 | } 98 | 99 | function onReset(event) { // 'this' is the form element 100 | var $form = $(this), 101 | key = '__jquery_unobtrusive_validation_form_reset'; 102 | if ($form.data(key)) { 103 | return; 104 | } 105 | // Set a flag that indicates we're currently resetting the form. 106 | $form.data(key, true); 107 | try { 108 | $form.data("validator").resetForm(); 109 | } finally { 110 | $form.removeData(key); 111 | } 112 | 113 | $form.find(".validation-summary-errors") 114 | .addClass("validation-summary-valid") 115 | .removeClass("validation-summary-errors"); 116 | $form.find(".field-validation-error") 117 | .addClass("field-validation-valid") 118 | .removeClass("field-validation-error") 119 | .removeData("unobtrusiveContainer") 120 | .find(">*") // If we were using valmsg-replace, get the underlying error 121 | .removeData("unobtrusiveContainer"); 122 | } 123 | 124 | function validationInfo(form) { 125 | var $form = $(form), 126 | result = $form.data(data_validation), 127 | onResetProxy = $.proxy(onReset, form), 128 | defaultOptions = $jQval.unobtrusive.options || {}, 129 | execInContext = function (name, args) { 130 | var func = defaultOptions[name]; 131 | func && $.isFunction(func) && func.apply(form, args); 132 | }; 133 | 134 | if (!result) { 135 | result = { 136 | options: { // options structure passed to jQuery Validate's validate() method 137 | errorClass: defaultOptions.errorClass || "input-validation-error", 138 | errorElement: defaultOptions.errorElement || "span", 139 | errorPlacement: function () { 140 | onError.apply(form, arguments); 141 | execInContext("errorPlacement", arguments); 142 | }, 143 | invalidHandler: function () { 144 | onErrors.apply(form, arguments); 145 | execInContext("invalidHandler", arguments); 146 | }, 147 | messages: {}, 148 | rules: {}, 149 | success: function () { 150 | onSuccess.apply(form, arguments); 151 | execInContext("success", arguments); 152 | } 153 | }, 154 | attachValidation: function () { 155 | $form 156 | .off("reset." + data_validation, onResetProxy) 157 | .on("reset." + data_validation, onResetProxy) 158 | .validate(this.options); 159 | }, 160 | validate: function () { // a validation function that is called by unobtrusive Ajax 161 | $form.validate(); 162 | return $form.valid(); 163 | } 164 | }; 165 | $form.data(data_validation, result); 166 | } 167 | 168 | return result; 169 | } 170 | 171 | $jQval.unobtrusive = { 172 | adapters: [], 173 | 174 | parseElement: function (element, skipAttach) { 175 | /// 176 | /// Parses a single HTML element for unobtrusive validation attributes. 177 | /// 178 | /// The HTML element to be parsed. 179 | /// [Optional] true to skip attaching the 180 | /// validation to the form. If parsing just this single element, you should specify true. 181 | /// If parsing several elements, you should specify false, and manually attach the validation 182 | /// to the form when you are finished. The default is false. 183 | var $element = $(element), 184 | form = $element.parents("form")[0], 185 | valInfo, rules, messages; 186 | 187 | if (!form) { // Cannot do client-side validation without a form 188 | return; 189 | } 190 | 191 | valInfo = validationInfo(form); 192 | valInfo.options.rules[element.name] = rules = {}; 193 | valInfo.options.messages[element.name] = messages = {}; 194 | 195 | $.each(this.adapters, function () { 196 | var prefix = "data-val-" + this.name, 197 | message = $element.attr(prefix), 198 | paramValues = {}; 199 | 200 | if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy) 201 | prefix += "-"; 202 | 203 | $.each(this.params, function () { 204 | paramValues[this] = $element.attr(prefix + this); 205 | }); 206 | 207 | this.adapt({ 208 | element: element, 209 | form: form, 210 | message: message, 211 | params: paramValues, 212 | rules: rules, 213 | messages: messages 214 | }); 215 | } 216 | }); 217 | 218 | $.extend(rules, { "__dummy__": true }); 219 | 220 | if (!skipAttach) { 221 | valInfo.attachValidation(); 222 | } 223 | }, 224 | 225 | parse: function (selector) { 226 | /// 227 | /// Parses all the HTML elements in the specified selector. It looks for input elements decorated 228 | /// with the [data-val=true] attribute value and enables validation according to the data-val-* 229 | /// attribute values. 230 | /// 231 | /// Any valid jQuery selector. 232 | 233 | // $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one 234 | // element with data-val=true 235 | var $selector = $(selector), 236 | $forms = $selector.parents() 237 | .addBack() 238 | .filter("form") 239 | .add($selector.find("form")) 240 | .has("[data-val=true]"); 241 | 242 | $selector.find("[data-val=true]").each(function () { 243 | $jQval.unobtrusive.parseElement(this, true); 244 | }); 245 | 246 | $forms.each(function () { 247 | var info = validationInfo(this); 248 | if (info) { 249 | info.attachValidation(); 250 | } 251 | }); 252 | } 253 | }; 254 | 255 | adapters = $jQval.unobtrusive.adapters; 256 | 257 | adapters.add = function (adapterName, params, fn) { 258 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation. 259 | /// The name of the adapter to be added. This matches the name used 260 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 261 | /// [Optional] An array of parameter names (strings) that will 262 | /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and 263 | /// mmmm is the parameter name). 264 | /// The function to call, which adapts the values from the HTML 265 | /// attributes into jQuery Validate rules and/or messages. 266 | /// 267 | if (!fn) { // Called with no params, just a function 268 | fn = params; 269 | params = []; 270 | } 271 | this.push({ name: adapterName, params: params, adapt: fn }); 272 | return this; 273 | }; 274 | 275 | adapters.addBool = function (adapterName, ruleName) { 276 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 277 | /// the jQuery Validate validation rule has no parameter values. 278 | /// The name of the adapter to be added. This matches the name used 279 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 280 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 281 | /// of adapterName will be used instead. 282 | /// 283 | return this.add(adapterName, function (options) { 284 | setValidationValues(options, ruleName || adapterName, true); 285 | }); 286 | }; 287 | 288 | adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) { 289 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 290 | /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and 291 | /// one for min-and-max). The HTML parameters are expected to be named -min and -max. 292 | /// The name of the adapter to be added. This matches the name used 293 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 294 | /// The name of the jQuery Validate rule to be used when you only 295 | /// have a minimum value. 296 | /// The name of the jQuery Validate rule to be used when you only 297 | /// have a maximum value. 298 | /// The name of the jQuery Validate rule to be used when you 299 | /// have both a minimum and maximum value. 300 | /// [Optional] The name of the HTML attribute that 301 | /// contains the minimum value. The default is "min". 302 | /// [Optional] The name of the HTML attribute that 303 | /// contains the maximum value. The default is "max". 304 | /// 305 | return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) { 306 | var min = options.params.min, 307 | max = options.params.max; 308 | 309 | if (min && max) { 310 | setValidationValues(options, minMaxRuleName, [min, max]); 311 | } 312 | else if (min) { 313 | setValidationValues(options, minRuleName, min); 314 | } 315 | else if (max) { 316 | setValidationValues(options, maxRuleName, max); 317 | } 318 | }); 319 | }; 320 | 321 | adapters.addSingleVal = function (adapterName, attribute, ruleName) { 322 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 323 | /// the jQuery Validate validation rule has a single value. 324 | /// The name of the adapter to be added. This matches the name used 325 | /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name). 326 | /// [Optional] The name of the HTML attribute that contains the value. 327 | /// The default is "val". 328 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 329 | /// of adapterName will be used instead. 330 | /// 331 | return this.add(adapterName, [attribute || "val"], function (options) { 332 | setValidationValues(options, ruleName || adapterName, options.params[attribute]); 333 | }); 334 | }; 335 | 336 | $jQval.addMethod("__dummy__", function (value, element, params) { 337 | return true; 338 | }); 339 | 340 | $jQval.addMethod("regex", function (value, element, params) { 341 | var match; 342 | if (this.optional(element)) { 343 | return true; 344 | } 345 | 346 | match = new RegExp(params).exec(value); 347 | return (match && (match.index === 0) && (match[0].length === value.length)); 348 | }); 349 | 350 | $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) { 351 | var match; 352 | if (nonalphamin) { 353 | match = value.match(/\W/g); 354 | match = match && match.length >= nonalphamin; 355 | } 356 | return match; 357 | }); 358 | 359 | if ($jQval.methods.extension) { 360 | adapters.addSingleVal("accept", "mimtype"); 361 | adapters.addSingleVal("extension", "extension"); 362 | } else { 363 | // for backward compatibility, when the 'extension' validation method does not exist, such as with versions 364 | // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for 365 | // validating the extension, and ignore mime-type validations as they are not supported. 366 | adapters.addSingleVal("extension", "extension", "accept"); 367 | } 368 | 369 | adapters.addSingleVal("regex", "pattern"); 370 | adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"); 371 | adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range"); 372 | adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength"); 373 | adapters.add("equalto", ["other"], function (options) { 374 | var prefix = getModelPrefix(options.element.name), 375 | other = options.params.other, 376 | fullOtherName = appendModelPrefix(other, prefix), 377 | element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0]; 378 | 379 | setValidationValues(options, "equalTo", element); 380 | }); 381 | adapters.add("required", function (options) { 382 | // jQuery Validate equates "required" with "mandatory" for checkbox elements 383 | if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") { 384 | setValidationValues(options, "required", true); 385 | } 386 | }); 387 | adapters.add("remote", ["url", "type", "additionalfields"], function (options) { 388 | var value = { 389 | url: options.params.url, 390 | type: options.params.type || "GET", 391 | data: {} 392 | }, 393 | prefix = getModelPrefix(options.element.name); 394 | 395 | $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) { 396 | var paramName = appendModelPrefix(fieldName, prefix); 397 | value.data[paramName] = function () { 398 | var field = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']"); 399 | // For checkboxes and radio buttons, only pick up values from checked fields. 400 | if (field.is(":checkbox")) { 401 | return field.filter(":checked").val() || field.filter(":hidden").val() || ''; 402 | } 403 | else if (field.is(":radio")) { 404 | return field.filter(":checked").val() || ''; 405 | } 406 | return field.val(); 407 | }; 408 | }); 409 | 410 | setValidationValues(options, "remote", value); 411 | }); 412 | adapters.add("password", ["min", "nonalphamin", "regex"], function (options) { 413 | if (options.params.min) { 414 | setValidationValues(options, "minlength", options.params.min); 415 | } 416 | if (options.params.nonalphamin) { 417 | setValidationValues(options, "nonalphamin", options.params.nonalphamin); 418 | } 419 | if (options.params.regex) { 420 | setValidationValues(options, "regex", options.params.regex); 421 | } 422 | }); 423 | adapters.add("fileextensions", ["extensions"], function (options) { 424 | setValidationValues(options, "extension", options.params.extensions); 425 | }); 426 | 427 | $(function () { 428 | $jQval.unobtrusive.parse(document); 429 | }); 430 | 431 | return $jQval.unobtrusive; 432 | })); 433 | -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Scripts/jquery.validate.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Validation Plugin - v1.17.0 - 7/29/2017 2 | * https://jqueryvalidation.org/ 3 | * Copyright (c) 2017 Jörn Zaefferer; Licensed MIT */ 4 | !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){a.extend(a.fn,{validate:function(b){if(!this.length)return void(b&&b.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."));var c=a.data(this[0],"validator");return c?c:(this.attr("novalidate","novalidate"),c=new a.validator(b,this[0]),a.data(this[0],"validator",c),c.settings.onsubmit&&(this.on("click.validate",":submit",function(b){c.submitButton=b.currentTarget,a(this).hasClass("cancel")&&(c.cancelSubmit=!0),void 0!==a(this).attr("formnovalidate")&&(c.cancelSubmit=!0)}),this.on("submit.validate",function(b){function d(){var d,e;return c.submitButton&&(c.settings.submitHandler||c.formSubmitted)&&(d=a("").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),!c.settings.submitHandler||(e=c.settings.submitHandler.call(c,c.currentForm,b),d&&d.remove(),void 0!==e&&e)}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,b||(d=d.concat(c.errorList))}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0];if(null!=j&&(!j.form&&j.hasAttribute("contenteditable")&&(j.form=this.closest("form")[0],j.name=this.attr("name")),null!=j.form)){if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(a,b){i[b]=f[b],delete f[b]}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g)),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}}),a.extend(a.expr.pseudos||a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){var c=a(b).val();return null!==c&&!!a.trim(""+c)},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:void 0===c?b:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",pendingClass:"pending",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||a.inArray(c.keyCode,d)!==-1||(b.name in this.submitted||b.name in this.invalid)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}."),step:a.validator.format("Please enter a multiple of {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){!this.form&&this.hasAttribute("contenteditable")&&(this.form=a(this).closest("form")[0],this.name=a(this).attr("name"));var c=a.data(this.form,"validator"),d="on"+b.type.replace(/^validate/,""),e=c.settings;e[d]&&!a(this).is(e.ignore)&&e[d].call(c,this,b)}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){d[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox'], [contenteditable], [type='button']",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c,d,e=this.clean(b),f=this.validationTargetFor(e),g=this,h=!0;return void 0===f?delete this.invalid[e.name]:(this.prepareElement(f),this.currentElements=a(f),d=this.groups[f.name],d&&a.each(this.groups,function(a,b){b===d&&a!==f.name&&(e=g.validationTargetFor(g.clean(g.findByName(a))),e&&e.name in g.invalid&&(g.currentElements.push(e),h=g.check(e)&&h))}),c=this.check(f)!==!1,h=h&&c,c?this.invalid[f.name]=!1:this.invalid[f.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),a(b).attr("aria-invalid",!c)),h},showErrors:function(b){if(b){var c=this;a.extend(this.errorMap,b),this.errorList=a.map(this.errorMap,function(a,b){return{message:a,element:c.findByName(b)[0]}}),this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.invalid={},this.submitted={},this.prepareForm(),this.hideErrors();var b=this.elements().removeData("previousValue").removeAttr("aria-invalid");this.resetElements(b)},resetElements:function(a){var b;if(this.settings.unhighlight)for(b=0;a[b];b++)this.settings.unhighlight.call(this,a[b],this.settings.errorClass,""),this.findByName(a[b].name).removeClass(this.settings.validClass);else a.removeClass(this.settings.errorClass).removeClass(this.settings.validClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)void 0!==a[b]&&null!==a[b]&&a[b]!==!1&&c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea, [contenteditable]").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){var d=this.name||a(this).attr("name");return!d&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.hasAttribute("contenteditable")&&(this.form=a(this).closest("form")[0],this.name=d),!(d in c||!b.objectLength(a(this).rules()))&&(c[d]=!0,!0)})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},resetInternals:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([])},reset:function(){this.resetInternals(),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d,e=a(b),f=b.type;return"radio"===f||"checkbox"===f?this.findByName(b.name).filter(":checked").val():"number"===f&&"undefined"!=typeof b.validity?b.validity.badInput?"NaN":e.val():(c=b.hasAttribute("contenteditable")?e.text():e.val(),"file"===f?"C:\\fakepath\\"===c.substr(0,12)?c.substr(12):(d=c.lastIndexOf("/"),d>=0?c.substr(d+1):(d=c.lastIndexOf("\\"),d>=0?c.substr(d+1):c)):"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f,g=a(b).rules(),h=a.map(g,function(a,b){return b}).length,i=!1,j=this.elementValue(b);if("function"==typeof g.normalizer?f=g.normalizer:"function"==typeof this.settings.normalizer&&(f=this.settings.normalizer),f){if(j=f.call(b,j),"string"!=typeof j)throw new TypeError("The normalizer should return a string value.");delete g.normalizer}for(d in g){e={method:d,parameters:g[d]};try{if(c=a.validator.methods[d].call(this,j,b,e.parameters),"dependency-mismatch"===c&&1===h){i=!0;continue}if(i=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(k){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",k),k instanceof TypeError&&(k.message+=". Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),k}}if(!i)return this.objectLength(g)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;aWarning: No message defined for "+b.name+""),e=/\$?\{(\d+)\}/g;return"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),d},formatAndAdd:function(a,b){var c=this.defaultMessage(a,b);this.errorList.push({message:c,element:a,method:b.method}),this.errorMap[a.name]=c,this.submitted[a.name]=c},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g,h=this.errorsFor(b),i=this.idOrName(b),j=a(b).attr("aria-describedby");h.length?(h.removeClass(this.settings.validClass).addClass(this.settings.errorClass),h.html(c)):(h=a("<"+this.settings.errorElement+">").attr("id",i+"-error").addClass(this.settings.errorClass).html(c||""),d=h,this.settings.wrapper&&(d=h.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement.call(this,d,a(b)):d.insertAfter(b),h.is("label")?h.attr("for",i):0===h.parents("label[for='"+this.escapeCssMeta(i)+"']").length&&(f=h.attr("id"),j?j.match(new RegExp("\\b"+this.escapeCssMeta(f)+"\\b"))||(j+=" "+f):j=f,a(b).attr("aria-describedby",j),e=this.groups[b.name],e&&(g=this,a.each(g.groups,function(b,c){c===e&&a("[name='"+g.escapeCssMeta(b)+"']",g.currentForm).attr("aria-describedby",h.attr("id"))})))),!c&&this.settings.success&&(h.text(""),"string"==typeof this.settings.success?h.addClass(this.settings.success):this.settings.success(h,b)),this.toShow=this.toShow.add(h)},errorsFor:function(b){var c=this.escapeCssMeta(this.idOrName(b)),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+this.escapeCssMeta(d).replace(/\s+/g,", #")),this.errors().filter(e)},escapeCssMeta:function(a){return a.replace(/([\\!"#$%&'()*+,.\/:;<=>?@\[\]^`{|}~])/g,"\\$1")},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+this.escapeCssMeta(b)+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return!this.dependTypes[typeof a]||this.dependTypes[typeof a](a,b)},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(b){this.pending[b.name]||(this.pendingRequest++,a(b).addClass(this.settings.pendingClass),this.pending[b.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],a(b).removeClass(this.settings.pendingClass),c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.submitButton&&a("input:hidden[name='"+this.submitButton.name+"']",this.currentForm).remove(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b,c){return c="string"==typeof c&&c||"remote",a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,{method:c})})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator").find(".validate-equalTo-blur").off(".validate-equalTo").removeClass("validate-equalTo-blur")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max|step/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a[c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0===e.param||e.param:(a.data(c.form,"validator").resetElements(a(c)),delete b[d])}}),a.each(b,function(d,e){b[d]=a.isFunction(e)&&"normalizer"!==d?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[\/?#]\S*)?$/i.test(a)},date:function(a,b){return this.optional(b)||!/Invalid|NaN/.test(new Date(a).toString())},dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e<=d},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||a<=c},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},step:function(b,c,d){var e,f=a(c).attr("type"),g="Step attribute on input type "+f+" is not supported.",h=["text","number","range"],i=new RegExp("\\b"+f+"\\b"),j=f&&!i.test(h.join()),k=function(a){var b=(""+a).match(/(?:\.(\d+))?$/);return b&&b[1]?b[1].length:0},l=function(a){return Math.round(a*Math.pow(10,e))},m=!0;if(j)throw new Error(g);return e=k(d),(k(b)>e||l(b)%l(d)!==0)&&(m=!1),this.optional(c)||m},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-equalTo-blur").length&&e.addClass("validate-equalTo-blur").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d,e){if(this.optional(c))return"dependency-mismatch";e="string"==typeof e&&e||"remote";var f,g,h,i=this.previousValue(c,e);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),i.originalMessage=i.originalMessage||this.settings.messages[c.name][e],this.settings.messages[c.name][e]=i.message,d="string"==typeof d&&{url:d}||d,h=a.param(a.extend({data:b},d.data)),i.old===h?i.valid:(i.old=h,f=this,this.startRequest(c),g={},g[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:g,context:f.currentForm,success:function(a){var d,g,h,j=a===!0||"true"===a;f.settings.messages[c.name][e]=i.originalMessage,j?(h=f.formSubmitted,f.resetInternals(),f.toHide=f.errorsFor(c),f.formSubmitted=h,f.successList.push(c),f.invalid[c.name]=!1,f.showErrors()):(d={},g=a||f.defaultMessage(c,{method:e,parameters:b}),d[c.name]=i.message=g,f.invalid[c.name]=!0,f.showErrors(d)),i.valid=j,f.stopRequest(c,j)}},d)),"pending")}}});var b,c={};return a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)}),a}); -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Content/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.4.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x;background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x;background-color:#2e6da4}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} 6 | /*# sourceMappingURL=bootstrap-theme.min.css.map */ -------------------------------------------------------------------------------- /SignalingServer/SignalingServer/Content/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.4.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | .btn-default, 7 | .btn-primary, 8 | .btn-success, 9 | .btn-info, 10 | .btn-warning, 11 | .btn-danger { 12 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); 13 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); 14 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); 15 | } 16 | .btn-default:active, 17 | .btn-primary:active, 18 | .btn-success:active, 19 | .btn-info:active, 20 | .btn-warning:active, 21 | .btn-danger:active, 22 | .btn-default.active, 23 | .btn-primary.active, 24 | .btn-success.active, 25 | .btn-info.active, 26 | .btn-warning.active, 27 | .btn-danger.active { 28 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 29 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 30 | } 31 | .btn-default.disabled, 32 | .btn-primary.disabled, 33 | .btn-success.disabled, 34 | .btn-info.disabled, 35 | .btn-warning.disabled, 36 | .btn-danger.disabled, 37 | .btn-default[disabled], 38 | .btn-primary[disabled], 39 | .btn-success[disabled], 40 | .btn-info[disabled], 41 | .btn-warning[disabled], 42 | .btn-danger[disabled], 43 | fieldset[disabled] .btn-default, 44 | fieldset[disabled] .btn-primary, 45 | fieldset[disabled] .btn-success, 46 | fieldset[disabled] .btn-info, 47 | fieldset[disabled] .btn-warning, 48 | fieldset[disabled] .btn-danger { 49 | -webkit-box-shadow: none; 50 | box-shadow: none; 51 | } 52 | .btn-default .badge, 53 | .btn-primary .badge, 54 | .btn-success .badge, 55 | .btn-info .badge, 56 | .btn-warning .badge, 57 | .btn-danger .badge { 58 | text-shadow: none; 59 | } 60 | .btn:active, 61 | .btn.active { 62 | background-image: none; 63 | } 64 | .btn-default { 65 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); 66 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); 67 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); 68 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); 69 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); 70 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 71 | background-repeat: repeat-x; 72 | border-color: #dbdbdb; 73 | text-shadow: 0 1px 0 #fff; 74 | border-color: #ccc; 75 | } 76 | .btn-default:hover, 77 | .btn-default:focus { 78 | background-color: #e0e0e0; 79 | background-position: 0 -15px; 80 | } 81 | .btn-default:active, 82 | .btn-default.active { 83 | background-color: #e0e0e0; 84 | border-color: #dbdbdb; 85 | } 86 | .btn-default.disabled, 87 | .btn-default[disabled], 88 | fieldset[disabled] .btn-default, 89 | .btn-default.disabled:hover, 90 | .btn-default[disabled]:hover, 91 | fieldset[disabled] .btn-default:hover, 92 | .btn-default.disabled:focus, 93 | .btn-default[disabled]:focus, 94 | fieldset[disabled] .btn-default:focus, 95 | .btn-default.disabled.focus, 96 | .btn-default[disabled].focus, 97 | fieldset[disabled] .btn-default.focus, 98 | .btn-default.disabled:active, 99 | .btn-default[disabled]:active, 100 | fieldset[disabled] .btn-default:active, 101 | .btn-default.disabled.active, 102 | .btn-default[disabled].active, 103 | fieldset[disabled] .btn-default.active { 104 | background-color: #e0e0e0; 105 | background-image: none; 106 | } 107 | .btn-primary { 108 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); 109 | background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); 110 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); 111 | background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); 112 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); 113 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 114 | background-repeat: repeat-x; 115 | border-color: #245580; 116 | } 117 | .btn-primary:hover, 118 | .btn-primary:focus { 119 | background-color: #265a88; 120 | background-position: 0 -15px; 121 | } 122 | .btn-primary:active, 123 | .btn-primary.active { 124 | background-color: #265a88; 125 | border-color: #245580; 126 | } 127 | .btn-primary.disabled, 128 | .btn-primary[disabled], 129 | fieldset[disabled] .btn-primary, 130 | .btn-primary.disabled:hover, 131 | .btn-primary[disabled]:hover, 132 | fieldset[disabled] .btn-primary:hover, 133 | .btn-primary.disabled:focus, 134 | .btn-primary[disabled]:focus, 135 | fieldset[disabled] .btn-primary:focus, 136 | .btn-primary.disabled.focus, 137 | .btn-primary[disabled].focus, 138 | fieldset[disabled] .btn-primary.focus, 139 | .btn-primary.disabled:active, 140 | .btn-primary[disabled]:active, 141 | fieldset[disabled] .btn-primary:active, 142 | .btn-primary.disabled.active, 143 | .btn-primary[disabled].active, 144 | fieldset[disabled] .btn-primary.active { 145 | background-color: #265a88; 146 | background-image: none; 147 | } 148 | .btn-success { 149 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); 150 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); 151 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); 152 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); 153 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); 154 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 155 | background-repeat: repeat-x; 156 | border-color: #3e8f3e; 157 | } 158 | .btn-success:hover, 159 | .btn-success:focus { 160 | background-color: #419641; 161 | background-position: 0 -15px; 162 | } 163 | .btn-success:active, 164 | .btn-success.active { 165 | background-color: #419641; 166 | border-color: #3e8f3e; 167 | } 168 | .btn-success.disabled, 169 | .btn-success[disabled], 170 | fieldset[disabled] .btn-success, 171 | .btn-success.disabled:hover, 172 | .btn-success[disabled]:hover, 173 | fieldset[disabled] .btn-success:hover, 174 | .btn-success.disabled:focus, 175 | .btn-success[disabled]:focus, 176 | fieldset[disabled] .btn-success:focus, 177 | .btn-success.disabled.focus, 178 | .btn-success[disabled].focus, 179 | fieldset[disabled] .btn-success.focus, 180 | .btn-success.disabled:active, 181 | .btn-success[disabled]:active, 182 | fieldset[disabled] .btn-success:active, 183 | .btn-success.disabled.active, 184 | .btn-success[disabled].active, 185 | fieldset[disabled] .btn-success.active { 186 | background-color: #419641; 187 | background-image: none; 188 | } 189 | .btn-info { 190 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 191 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 192 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); 193 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); 194 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); 195 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 196 | background-repeat: repeat-x; 197 | border-color: #28a4c9; 198 | } 199 | .btn-info:hover, 200 | .btn-info:focus { 201 | background-color: #2aabd2; 202 | background-position: 0 -15px; 203 | } 204 | .btn-info:active, 205 | .btn-info.active { 206 | background-color: #2aabd2; 207 | border-color: #28a4c9; 208 | } 209 | .btn-info.disabled, 210 | .btn-info[disabled], 211 | fieldset[disabled] .btn-info, 212 | .btn-info.disabled:hover, 213 | .btn-info[disabled]:hover, 214 | fieldset[disabled] .btn-info:hover, 215 | .btn-info.disabled:focus, 216 | .btn-info[disabled]:focus, 217 | fieldset[disabled] .btn-info:focus, 218 | .btn-info.disabled.focus, 219 | .btn-info[disabled].focus, 220 | fieldset[disabled] .btn-info.focus, 221 | .btn-info.disabled:active, 222 | .btn-info[disabled]:active, 223 | fieldset[disabled] .btn-info:active, 224 | .btn-info.disabled.active, 225 | .btn-info[disabled].active, 226 | fieldset[disabled] .btn-info.active { 227 | background-color: #2aabd2; 228 | background-image: none; 229 | } 230 | .btn-warning { 231 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 232 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 233 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); 234 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); 235 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); 236 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 237 | background-repeat: repeat-x; 238 | border-color: #e38d13; 239 | } 240 | .btn-warning:hover, 241 | .btn-warning:focus { 242 | background-color: #eb9316; 243 | background-position: 0 -15px; 244 | } 245 | .btn-warning:active, 246 | .btn-warning.active { 247 | background-color: #eb9316; 248 | border-color: #e38d13; 249 | } 250 | .btn-warning.disabled, 251 | .btn-warning[disabled], 252 | fieldset[disabled] .btn-warning, 253 | .btn-warning.disabled:hover, 254 | .btn-warning[disabled]:hover, 255 | fieldset[disabled] .btn-warning:hover, 256 | .btn-warning.disabled:focus, 257 | .btn-warning[disabled]:focus, 258 | fieldset[disabled] .btn-warning:focus, 259 | .btn-warning.disabled.focus, 260 | .btn-warning[disabled].focus, 261 | fieldset[disabled] .btn-warning.focus, 262 | .btn-warning.disabled:active, 263 | .btn-warning[disabled]:active, 264 | fieldset[disabled] .btn-warning:active, 265 | .btn-warning.disabled.active, 266 | .btn-warning[disabled].active, 267 | fieldset[disabled] .btn-warning.active { 268 | background-color: #eb9316; 269 | background-image: none; 270 | } 271 | .btn-danger { 272 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 273 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 274 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); 275 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); 276 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); 277 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 278 | background-repeat: repeat-x; 279 | border-color: #b92c28; 280 | } 281 | .btn-danger:hover, 282 | .btn-danger:focus { 283 | background-color: #c12e2a; 284 | background-position: 0 -15px; 285 | } 286 | .btn-danger:active, 287 | .btn-danger.active { 288 | background-color: #c12e2a; 289 | border-color: #b92c28; 290 | } 291 | .btn-danger.disabled, 292 | .btn-danger[disabled], 293 | fieldset[disabled] .btn-danger, 294 | .btn-danger.disabled:hover, 295 | .btn-danger[disabled]:hover, 296 | fieldset[disabled] .btn-danger:hover, 297 | .btn-danger.disabled:focus, 298 | .btn-danger[disabled]:focus, 299 | fieldset[disabled] .btn-danger:focus, 300 | .btn-danger.disabled.focus, 301 | .btn-danger[disabled].focus, 302 | fieldset[disabled] .btn-danger.focus, 303 | .btn-danger.disabled:active, 304 | .btn-danger[disabled]:active, 305 | fieldset[disabled] .btn-danger:active, 306 | .btn-danger.disabled.active, 307 | .btn-danger[disabled].active, 308 | fieldset[disabled] .btn-danger.active { 309 | background-color: #c12e2a; 310 | background-image: none; 311 | } 312 | .thumbnail, 313 | .img-thumbnail { 314 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 315 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 316 | } 317 | .dropdown-menu > li > a:hover, 318 | .dropdown-menu > li > a:focus { 319 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 320 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 321 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 322 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 323 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 324 | background-repeat: repeat-x; 325 | background-color: #e8e8e8; 326 | } 327 | .dropdown-menu > .active > a, 328 | .dropdown-menu > .active > a:hover, 329 | .dropdown-menu > .active > a:focus { 330 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 331 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 332 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 333 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 334 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 335 | background-repeat: repeat-x; 336 | background-color: #2e6da4; 337 | } 338 | .navbar-default { 339 | background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); 340 | background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); 341 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8)); 342 | background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); 343 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 344 | background-repeat: repeat-x; 345 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 346 | border-radius: 4px; 347 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); 348 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); 349 | } 350 | .navbar-default .navbar-nav > .open > a, 351 | .navbar-default .navbar-nav > .active > a { 352 | background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 353 | background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 354 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); 355 | background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); 356 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); 357 | background-repeat: repeat-x; 358 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075); 359 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075); 360 | } 361 | .navbar-brand, 362 | .navbar-nav > li > a { 363 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); 364 | } 365 | .navbar-inverse { 366 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); 367 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); 368 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); 369 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); 370 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 371 | background-repeat: repeat-x; 372 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 373 | border-radius: 4px; 374 | } 375 | .navbar-inverse .navbar-nav > .open > a, 376 | .navbar-inverse .navbar-nav > .active > a { 377 | background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); 378 | background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); 379 | background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); 380 | background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); 381 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); 382 | background-repeat: repeat-x; 383 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25); 384 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25); 385 | } 386 | .navbar-inverse .navbar-brand, 387 | .navbar-inverse .navbar-nav > li > a { 388 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 389 | } 390 | .navbar-static-top, 391 | .navbar-fixed-top, 392 | .navbar-fixed-bottom { 393 | border-radius: 0; 394 | } 395 | @media (max-width: 767px) { 396 | .navbar .navbar-nav .open .dropdown-menu > .active > a, 397 | .navbar .navbar-nav .open .dropdown-menu > .active > a:hover, 398 | .navbar .navbar-nav .open .dropdown-menu > .active > a:focus { 399 | color: #fff; 400 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 401 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 402 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 403 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 404 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 405 | background-repeat: repeat-x; 406 | } 407 | } 408 | .alert { 409 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2); 410 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); 411 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); 412 | } 413 | .alert-success { 414 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 415 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 416 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); 417 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 418 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 419 | background-repeat: repeat-x; 420 | border-color: #b2dba1; 421 | } 422 | .alert-info { 423 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 424 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 425 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); 426 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 427 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 428 | background-repeat: repeat-x; 429 | border-color: #9acfea; 430 | } 431 | .alert-warning { 432 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 433 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 434 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); 435 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 436 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 437 | background-repeat: repeat-x; 438 | border-color: #f5e79e; 439 | } 440 | .alert-danger { 441 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 442 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 443 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); 444 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 445 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 446 | background-repeat: repeat-x; 447 | border-color: #dca7a7; 448 | } 449 | .progress { 450 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 451 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 452 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); 453 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 454 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 455 | background-repeat: repeat-x; 456 | } 457 | .progress-bar { 458 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); 459 | background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); 460 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); 461 | background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); 462 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); 463 | background-repeat: repeat-x; 464 | } 465 | .progress-bar-success { 466 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); 467 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); 468 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); 469 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 470 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 471 | background-repeat: repeat-x; 472 | } 473 | .progress-bar-info { 474 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 475 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 476 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); 477 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 478 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 479 | background-repeat: repeat-x; 480 | } 481 | .progress-bar-warning { 482 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 483 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 484 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); 485 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 486 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 487 | background-repeat: repeat-x; 488 | } 489 | .progress-bar-danger { 490 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); 491 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); 492 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); 493 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 494 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 495 | background-repeat: repeat-x; 496 | } 497 | .progress-bar-striped { 498 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 499 | background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 500 | background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); 501 | } 502 | .list-group { 503 | border-radius: 4px; 504 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 505 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 506 | } 507 | .list-group-item.active, 508 | .list-group-item.active:hover, 509 | .list-group-item.active:focus { 510 | text-shadow: 0 -1px 0 #286090; 511 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); 512 | background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); 513 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); 514 | background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); 515 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); 516 | background-repeat: repeat-x; 517 | border-color: #2b669a; 518 | } 519 | .list-group-item.active .badge, 520 | .list-group-item.active:hover .badge, 521 | .list-group-item.active:focus .badge { 522 | text-shadow: none; 523 | } 524 | .panel { 525 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 526 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 527 | } 528 | .panel-default > .panel-heading { 529 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 530 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 531 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 532 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 533 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 534 | background-repeat: repeat-x; 535 | } 536 | .panel-primary > .panel-heading { 537 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 538 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 539 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 540 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 541 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 542 | background-repeat: repeat-x; 543 | } 544 | .panel-success > .panel-heading { 545 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 546 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 547 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); 548 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 549 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 550 | background-repeat: repeat-x; 551 | } 552 | .panel-info > .panel-heading { 553 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 554 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 555 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); 556 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 557 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 558 | background-repeat: repeat-x; 559 | } 560 | .panel-warning > .panel-heading { 561 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 562 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 563 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); 564 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 565 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 566 | background-repeat: repeat-x; 567 | } 568 | .panel-danger > .panel-heading { 569 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 570 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 571 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); 572 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 573 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 574 | background-repeat: repeat-x; 575 | } 576 | .well { 577 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 578 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 579 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); 580 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 581 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 582 | background-repeat: repeat-x; 583 | border-color: #dcdcdc; 584 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); 585 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); 586 | } 587 | /*# sourceMappingURL=bootstrap-theme.css.map */ --------------------------------------------------------------------------------