diff --git a/.gitignore b/.gitignore index 6b71cb4..c58b51e 100644 --- a/.gitignore +++ b/.gitignore @@ -185,3 +185,10 @@ $RECYCLE.BIN/ /VCR.NET/packages *.sln *.openAsAdmin +/VCR.NET/node_modules +/VCR.NET/WebClient41/content/styles.css +/VCR.NET/WebClient41/scripts/vcrnet.js* + +.vs + +package-lock.json \ No newline at end of file diff --git a/DVB.NET Viewer/Application/Dialogs/ProgramSettings.Designer.cs b/DVB.NET Viewer/Application/Dialogs/ProgramSettings.Designer.cs index 4a19231..1b3d8f0 100644 --- a/DVB.NET Viewer/Application/Dialogs/ProgramSettings.Designer.cs +++ b/DVB.NET Viewer/Application/Dialogs/ProgramSettings.Designer.cs @@ -61,6 +61,8 @@ private void InitializeComponent() this.ckOverwrite = new System.Windows.Forms.CheckBox(); this.label8 = new System.Windows.Forms.Label(); this.tabFilter = new System.Windows.Forms.TabPage(); + this.udAVDelay = new System.Windows.Forms.NumericUpDown(); + this.label16 = new System.Windows.Forms.Label(); this.selH264 = new System.Windows.Forms.ComboBox(); this.label15 = new System.Windows.Forms.Label(); this.selAC3 = new System.Windows.Forms.ComboBox(); @@ -79,6 +81,7 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.selSaturation)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.selContrast)).BeginInit(); this.tabFilter.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.udAVDelay)).BeginInit(); this.SuspendLayout(); // // label1 @@ -103,7 +106,6 @@ private void InitializeComponent() // // selPrio // - resources.ApplyResources(this.selPrio, "selPrio"); this.selPrio.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.selPrio.FormattingEnabled = true; this.selPrio.Items.AddRange(new object[] { @@ -113,28 +115,29 @@ private void InitializeComponent() resources.GetString("selPrio.Items3"), resources.GetString("selPrio.Items4"), resources.GetString("selPrio.Items5")}); + resources.ApplyResources(this.selPrio, "selPrio"); this.selPrio.Name = "selPrio"; // // selType // - resources.ApplyResources(this.selType, "selType"); this.selType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.selType.FormattingEnabled = true; this.selType.Items.AddRange(new object[] { resources.GetString("selType.Items"), resources.GetString("selType.Items1"), resources.GetString("selType.Items2")}); + resources.ApplyResources(this.selType, "selType"); this.selType.Name = "selType"; // // selEnc // - resources.ApplyResources(this.selEnc, "selEnc"); this.selEnc.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.selEnc.FormattingEnabled = true; this.selEnc.Items.AddRange(new object[] { resources.GetString("selEnc.Items"), resources.GetString("selEnc.Items1"), resources.GetString("selEnc.Items2")}); + resources.ApplyResources(this.selEnc, "selEnc"); this.selEnc.Name = "selEnc"; // // selOSD @@ -234,7 +237,6 @@ private void InitializeComponent() // // tabGeneral // - resources.ApplyResources(this.tabGeneral, "tabGeneral"); this.tabGeneral.BackColor = System.Drawing.SystemColors.Control; this.tabGeneral.Controls.Add(this.ckRemote); this.tabGeneral.Controls.Add(this.ckHideCursor); @@ -253,6 +255,7 @@ private void InitializeComponent() this.tabGeneral.Controls.Add(this.label3); this.tabGeneral.Controls.Add(this.txMCast); this.tabGeneral.Controls.Add(this.selType); + resources.ApplyResources(this.tabGeneral, "tabGeneral"); this.tabGeneral.Name = "tabGeneral"; // // ckRemote @@ -269,7 +272,6 @@ private void InitializeComponent() // // tabVideo // - resources.ApplyResources(this.tabVideo, "tabVideo"); this.tabVideo.BackColor = System.Drawing.SystemColors.Control; this.tabVideo.Controls.Add(this.selHue); this.tabVideo.Controls.Add(this.selBrightness); @@ -280,6 +282,7 @@ private void InitializeComponent() this.tabVideo.Controls.Add(this.label9); this.tabVideo.Controls.Add(this.ckOverwrite); this.tabVideo.Controls.Add(this.label8); + resources.ApplyResources(this.tabVideo, "tabVideo"); this.tabVideo.Name = "tabVideo"; // // selHue @@ -351,8 +354,9 @@ private void InitializeComponent() // // tabFilter // - resources.ApplyResources(this.tabFilter, "tabFilter"); this.tabFilter.BackColor = System.Drawing.SystemColors.Control; + this.tabFilter.Controls.Add(this.udAVDelay); + this.tabFilter.Controls.Add(this.label16); this.tabFilter.Controls.Add(this.selH264); this.tabFilter.Controls.Add(this.label15); this.tabFilter.Controls.Add(this.selAC3); @@ -361,8 +365,34 @@ private void InitializeComponent() this.tabFilter.Controls.Add(this.label13); this.tabFilter.Controls.Add(this.selMPEG2); this.tabFilter.Controls.Add(this.label12); + resources.ApplyResources(this.tabFilter, "tabFilter"); this.tabFilter.Name = "tabFilter"; // + // udAVDelay + // + this.udAVDelay.Increment = new decimal(new int[] { + 50, + 0, + 0, + 0}); + resources.ApplyResources(this.udAVDelay, "udAVDelay"); + this.udAVDelay.Maximum = new decimal(new int[] { + 2000, + 0, + 0, + 0}); + this.udAVDelay.Minimum = new decimal(new int[] { + 2000, + 0, + 0, + -2147483648}); + this.udAVDelay.Name = "udAVDelay"; + // + // label16 + // + resources.ApplyResources(this.label16, "label16"); + this.label16.Name = "label16"; + // // selH264 // resources.ApplyResources(this.selH264, "selH264"); @@ -441,6 +471,7 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.selContrast)).EndInit(); this.tabFilter.ResumeLayout(false); this.tabFilter.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.udAVDelay)).EndInit(); this.ResumeLayout(false); } @@ -487,5 +518,7 @@ private void InitializeComponent() private System.Windows.Forms.Label label12; private System.Windows.Forms.CheckBox ckHideCursor; private System.Windows.Forms.CheckBox ckRemote; + private System.Windows.Forms.NumericUpDown udAVDelay; + private System.Windows.Forms.Label label16; } } \ No newline at end of file diff --git a/DVB.NET Viewer/Application/Dialogs/ProgramSettings.cs b/DVB.NET Viewer/Application/Dialogs/ProgramSettings.cs index 9b70dff..bd580e2 100644 --- a/DVB.NET Viewer/Application/Dialogs/ProgramSettings.cs +++ b/DVB.NET Viewer/Application/Dialogs/ProgramSettings.cs @@ -108,6 +108,7 @@ private void ProgramSettings_Load( object sender, EventArgs e ) ckCyberlink.Checked = settings.UseCyberlinkCodec; ckHideCursor.Checked = settings.HideCursor; ckRemote.Checked = settings.UseRemote; + udAVDelay.Value = settings.AVDelay; // All lists LoadList( selMPEG2, DisplayGraph.VideoDecoderFilters, settings.MPEG2Decoder ); @@ -277,6 +278,7 @@ private void cmdSave_Click( object sender, EventArgs e ) settings.PayTV = (selEnc.SelectedIndex < 2); settings.HideCursor = ckHideCursor.Checked; settings.OSDLifeTime = (int) selOSD.Value; + settings.AVDelay = (int) udAVDelay.Value; settings.UseRemote = ckRemote.Checked; settings.Priority = CurrentPriority; settings.BroadcastIP = txMCast.Text; @@ -357,6 +359,7 @@ private void SettingChanging( object sender, SettingChangingEventArgs e ) case "H264Decoder": m_Rebuid = true; break; case "MP2Decoder": m_Rebuid = true; break; case "AC3Decoder": m_Rebuid = true; break; + case "AVDelay": m_Rebuid = true; break; } } diff --git a/DVB.NET Viewer/Application/Dialogs/ProgramSettings.de.resx b/DVB.NET Viewer/Application/Dialogs/ProgramSettings.de.resx index f6996b6..f8ee351 100644 --- a/DVB.NET Viewer/Application/Dialogs/ProgramSettings.de.resx +++ b/DVB.NET Viewer/Application/Dialogs/ProgramSettings.de.resx @@ -190,9 +190,6 @@ &CyberLink / PowerDVD H.264 Format aktivieren - - Allgemein - 150, 17 @@ -205,11 +202,8 @@ Maus&zeiger ausblenden - - 638, 317 - - - Bild + + Allgemein 43, 13 @@ -238,8 +232,14 @@ &Kontrast - - 638, 317 + + Bild + + + 107, 13 + + + Ton&verzögerung (ms) 56, 13 diff --git a/DVB.NET Viewer/Application/Dialogs/ProgramSettings.resx b/DVB.NET Viewer/Application/Dialogs/ProgramSettings.resx index 1cccd12..93210a2 100644 --- a/DVB.NET Viewer/Application/Dialogs/ProgramSettings.resx +++ b/DVB.NET Viewer/Application/Dialogs/ProgramSettings.resx @@ -118,1110 +118,1158 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 2 - - - 2 - - - - CenterParent - - - 11 + + True - - 21, 42 + + 6, 14 - - selHue + + 79, 13 - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0 - - 5 + + Process &Priority - - 513, 45 + + label1 - - VCR.NET + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 8 + + tabGeneral - - 558, 358 + + 2 - - 372, 21 + + True - - Encrypted and Free + + + NoControl - - $this + + 6, 40 - - label15 + + 144, 13 - - NoControl + + 2 - - 6 + + OSD &Display Time (Seconds) - - Radio only + + label2 - - tabGeneral + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tabs + + tabGeneral - - 137, 39 + + 7 - - txURL + + True - - tabVideo + + NoControl - - 5 + + 6, 67 - - 156, 91 + + 67, 13 - + 4 - - 225, 21 + + Station &Type - - True + + label3 - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabGeneral - + + 14 + + + True + + NoControl - - 246, 17 + + 6, 94 - - 7 + + 57, 13 - - 7 + + 6 - - 0 + + &Encryption - + + label4 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabGeneral - - True - - - NoControl - - - 9, 267 + + 11 - - 6, 67 + + Idle - - 56, 13 + + Below Normal - - tabFilter + + Normal - - 50, 20 + + Above Normal - - tabVideo + + High - - 77, 13 + + Real Time - - ckOverwrite + + 156, 11 - - 513, 45 + + 225, 21 - - &Saturation + + 1 - - 156, 38 + + selPrio - - tabs + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabGeneral - - 4, 22 - - - 13 - - - 2 - - - &Hue + + 12 - - label10 + + Radio and TV - - tabGeneral + + Radio only - - 3 + + TV only - - 40, 55 + + 156, 64 - - General Settings + + 225, 21 5 - - 15 + + selType - - tabs + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - label11 + + tabGeneral - - 3 + + 16 - - NoControl - - - NoControl + + Encrypted and Free - - 0 + + Encrypted only - - tabGeneral + + Free only - - selMPEG2 + + 156, 91 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 225, 21 - - NoControl + + 7 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + selEnc - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabGeneral - - 2 + + 13 - - 156, 204 + + 156, 38 - - True + + 50, 20 - - selPrio + + 3 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + selOSD - - True + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 20 + + tabGeneral - - NoControl + + 9 - - 144, 13 + + Bottom, Left - - 1 + + 16, 358 - - 7 + + 100, 23 - - System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 1 - - 2 + + &Update - - tabFilter + + cmdSave - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 3 + + $this - - 60, 20 + + 2 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Bottom, Right - - 7 + + 558, 358 - - 57, 13 + + 100, 23 - - 3 + + 2 - - 225, 21 + + &Cancel - - 9 + + cmdCancel - - 6, 40 + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - &Overwrite Default Settings + + $this - - 57, 13 + + 1 - - Above Normal + + True - - System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - 0 + + 6, 138 - - tabFilter + + 90, 13 - - Top, Left, Right + + 8 - - Bottom, Left + + &Multicast Address - - 27, 13 + + label5 - - 3, 3, 3, 3 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 40, 106 + + tabGeneral - - tabFilter + + 8 - - $this + + True - - 6 + + NoControl - - selContrast + + 6, 163 - - tabGeneral + + 91, 13 - - 3, 3, 3, 3 + + 10 - - tabFilter + + TCP&/IP UDP Port - - tabFilter + + label6 - - label12 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Use &Remote Control + + tabGeneral - - &Encryption + + 5 - - 119, 17 + + 156, 161 - - 21, 14 + + 60, 20 - - High + + 11 - - selType + + selPort - - Radio and TV + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabGeneral - - True + + 3 - - System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 156, 135 - - MPEG-2 &Video + + 225, 20 - - 372, 21 + + 9 - - System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + txMCast + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 tabGeneral - + + 15 + + + True + + NoControl - - 79, 13 + + 6, 207 - - label8 + + 54, 13 - - label13 + + 12 - - 9 + + VCR.NET - - 3 + + label7 - - 12, 9 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 1 + + tabGeneral - - &Hide Mouse Pointer + + 6 - - 20, 17 + + 156, 204 - - 3 + + 459, 20 - - True + + 13 - - 21, 69 + + txURL - - label9 + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 225, 21 + + tabGeneral - - 5 + + 10 - + True - - 20 - - - 1 + + 9, 244 - - label1 + + 246, 17 - - 12 + + 14 - - 40, 208 + + Activate &CyberLink / PowerDVD H.264 Format - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ckCyberlink - - 638, 291 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - label3 + + tabGeneral - - 4, 22 + + 4 - - tabVideo + + Top, Bottom, Left, Right - + True - - Process &Priority + + 9, 290 - - 1 + + 121, 17 - - 91, 13 + + 16 - - tabGeneral + + Use &Remote Control - + + ckRemote + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabGeneral - - 4 + + 0 - - 16 + + True - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 9, 267 - - 16, 358 + + 119, 17 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 15 - - True + + &Hide Mouse Pointer + + + ckHideCursor + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabGeneral - - tabVideo + + 1 - - selOSD + + 4, 22 - + 3, 3, 3, 3 638, 317 - - 15 + + 0 - - 156, 135 + + General - - 5 + + tabGeneral - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 67, 13 + + tabs - - 6, 138 + + 0 - - 20 + + NoControl - - 4 + + 107, 193 - - label2 + + 513, 45 - - Normal + + 8 - - 46, 13 + + selHue - - 107, 40 + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - General + + tabVideo - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - 8 + + 107, 142 - - 2 + + 513, 45 - - tabVideo + + 6 - - OSD &Display Time (Seconds) + + selBrightness - - 100, 23 + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - True + + tabVideo - - 149, 17 + + 1 - - 4 + + True - - 1 + + NoControl - - tabGeneral + + 40, 208 - - &Contrast + + 27, 13 - - Top, Left, Right + + 7 - - ProgramSettings + + &Hue - - 0 + + label11 - - tabFilter + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 16 + + tabVideo - - 4, 22 + + 2 - - 100, 23 + + NoControl - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 107, 91 - - 4 + + 513, 45 - - 6, 163 + + 4 - - ckRemote + + selSaturation - - Idle + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 1 + + tabVideo - - 59, 13 + + 3 - - tabs + + True - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 40, 157 - - 20 + + 56, 13 - - 137, 66 + + 5 - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + &Brightness - - 107, 142 + + label10 - - True + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 0 + + tabVideo - - 9, 244 + + 4 - - Top, Left, Right + + 107, 40 - - 6, 14 + + 513, 45 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 2 - - 6 + + selContrast - - txMCast + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabVideo - - 225, 20 + + 5 - - selBrightness + + True - + NoControl - - tabFilter + + 40, 106 - - NoControl + + 55, 13 + + + 3 - - &Cancel + + &Saturation - - selEnc + + label9 - - Real Time + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - &Multicast Address + + tabVideo - - 121, 17 + + 6 - - 513, 45 + + True - - 372, 21 + + 20, 17 - - 372, 21 + + 149, 17 - + 0 - - tabFilter + + &Overwrite Default Settings - - True + + ckOverwrite - - 2 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 8 + + tabVideo - - 6, 13 + + 7 - + True - - True + + 40, 55 - - 156, 161 + + 46, 13 - - System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 1 - - True + + &Contrast - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + label8 - - 13 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 54, 13 + + tabVideo - - selPort + + 8 - - MP2 &Audio + + 4, 22 - - True + + 3, 3, 3, 3 - - 14 + + 638, 317 - - System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 1 - - tabGeneral + + Video - - 5 + + tabVideo - - True + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - selAC3 + + tabs - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 1 - - 14 + + 137, 152 - - tabGeneral + + 52, 20 - - 1 + + 9 - - 638, 291 + + udAVDelay - - NoControl + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - TCP&/IP UDP Port + + tabFilter - - tabGeneral + + 0 - - 7 + + True - - 6 + + 21, 154 - - tabGeneral + + 86, 13 - - Video + + 8 - - 2 + + Audio &Delay (ms) - - cmdSave + + label16 - - ckHideCursor + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 0 + + tabFilter - - &H.264 Video + + 1 - - NoControl + + Top, Left, Right 137, 93 - - 6, 207 + + 20 - - 8 + + 372, 21 - - Station &Type + + 7 - - Top, Bottom, Left, Right + + selH264 - - 6 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tabVideo + + tabFilter - - Bottom, Right + + 2 - - &Brightness + + True - - 0 + + 21, 96 - - 55, 13 + + 66, 13 - - tabGeneral + + 6 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + &H.264 Video - - ckCyberlink + + label15 - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 0 + + tabFilter - - tabVideo + + 3 - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Top, Left, Right - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 137, 66 - - tabGeneral + + 20 + + + 372, 21 + + + 5 + + + selAC3 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabFilter - - 7 + + 4 - - 107, 91 + + True - - 11 + + 21, 69 - - 40, 157 + + 57, 13 - - 12 + + 4 - - 90, 13 + + AC&3 Audio - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + label14 - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 2 - - - 10 + + tabFilter - - selH264 + + 5 - - &Update + + Top, Left, Right - - 666, 393 + + 137, 39 - - 2 + + 20 - - 156, 64 + + 372, 21 - - 21, 96 + + 3 - - 1 + + selMP2 - - label7 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabFilter - + 6 - - label5 + + True - - 0 + + 21, 42 - - Below Normal + + 59, 13 - - $this + + 2 - - 1 + + MP2 &Audio - - tabVideo + + label13 - - tabVideo + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 646, 343 + + tabFilter + + + 7 + + + Top, Left, Right 137, 11 - - 459, 20 + + 20 - - tabVideo + + 372, 21 - - Activate &CyberLink / PowerDVD H.264 Format + + 1 - - 6, 94 + + selMPEG2 - - 156, 11 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - label4 + + tabFilter - - selMP2 + + 8 - - Free only + + True - - Encrypted only + + 21, 14 - - 1 + + 77, 13 - - Top, Left, Right + + 0 - + + MPEG-2 &Video + + + label12 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 107, 193 + + tabFilter - - True + + 9 - - 513, 45 + + 4, 22 - - AC&3 Audio + + 3, 3, 3, 3 - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 638, 317 - - TV only + + 2 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Decoder - - 4 + + tabFilter - - 9, 290 + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - selSaturation + + tabs - - 66, 13 + + 2 - - True + + 12, 9 - - label6 + + 646, 343 - - 10 + + 0 - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabs - - Decoder + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - cmdCancel + + $this - - label14 + + 0 True + + 6, 13 + + + 666, 393 + + + CenterParent + + + General Settings + + + ProgramSettings + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file diff --git a/DVB.NET Viewer/Application/Properties/Settings.Designer.cs b/DVB.NET Viewer/Application/Properties/Settings.Designer.cs index b8fc092..0ecb607 100644 --- a/DVB.NET Viewer/Application/Properties/Settings.Designer.cs +++ b/DVB.NET Viewer/Application/Properties/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18444 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -430,5 +430,17 @@ public string Version { this["Version"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("500")] + public int AVDelay { + get { + return ((int)(this["AVDelay"])); + } + set { + this["AVDelay"] = value; + } + } } } diff --git a/DVB.NET Viewer/Application/Properties/Settings.settings b/DVB.NET Viewer/Application/Properties/Settings.settings index 96f58b5..39ef96b 100644 --- a/DVB.NET Viewer/Application/Properties/Settings.settings +++ b/DVB.NET Viewer/Application/Properties/Settings.settings @@ -104,5 +104,8 @@ 0.0 + + 500 + \ No newline at end of file diff --git a/DVB.NET Viewer/Application/ViewerMain.cs b/DVB.NET Viewer/Application/ViewerMain.cs index b9c6be7..67dabed 100644 --- a/DVB.NET Viewer/Application/ViewerMain.cs +++ b/DVB.NET Viewer/Application/ViewerMain.cs @@ -734,59 +734,19 @@ private void LeaveFullScreen() /// /// Meldet, ob der Cyberlink / PowerDVD Codec fr H.264 aktiviert werden soll. /// - bool IGeneralInfo.UseCyberlinkCodec - { - get - { - // Report - return Properties.Settings.Default.UseCyberlinkCodec; - } - } + bool IGeneralInfo.UseCyberlinkCodec { get { return Properties.Settings.Default.UseCyberlinkCodec; } } - bool IGeneralInfo.UseRemoteControl - { - get - { - // Report - return Properties.Settings.Default.UseRemote; - } - } + bool IGeneralInfo.UseRemoteControl { get { return Properties.Settings.Default.UseRemote; } } - string IGeneralInfo.H264Decoder - { - get - { - // Report - return Properties.Settings.Default.H264Decoder; - } - } + string IGeneralInfo.H264Decoder { get { return Properties.Settings.Default.H264Decoder; } } - string IGeneralInfo.MPEG2Decoder - { - get - { - // Report - return Properties.Settings.Default.MPEG2Decoder; - } - } + string IGeneralInfo.MPEG2Decoder { get { return Properties.Settings.Default.MPEG2Decoder; } } - string IGeneralInfo.AC3Decoder - { - get - { - // Report - return Properties.Settings.Default.AC3Decoder; - } - } + string IGeneralInfo.AC3Decoder { get { return Properties.Settings.Default.AC3Decoder; } } - string IGeneralInfo.MP2Decoder - { - get - { - // Report - return Properties.Settings.Default.MP2Decoder; - } - } + string IGeneralInfo.MP2Decoder { get { return Properties.Settings.Default.MP2Decoder; } } + + int IGeneralInfo.AVDelay { get { return Properties.Settings.Default.AVDelay; } } void IGeneralInfo.SetPictureParameters( PictureParameters parameters ) { diff --git a/DVB.NET Viewer/Application/app.config b/DVB.NET Viewer/Application/app.config index f2e5a39..d096fce 100644 --- a/DVB.NET Viewer/Application/app.config +++ b/DVB.NET Viewer/Application/app.config @@ -110,6 +110,9 @@ 0.0 + + 500 + diff --git a/DVB.NET Viewer/Setups/Viewer/Viewer.wixproj b/DVB.NET Viewer/Setups/Viewer/Viewer.wixproj index 6680565..88a6dc0 100644 --- a/DVB.NET Viewer/Setups/Viewer/Viewer.wixproj +++ b/DVB.NET Viewer/Setups/Viewer/Viewer.wixproj @@ -17,7 +17,7 @@ ..\..\..\msi\ obj\$(Configuration)\ Debug - SETUPVERSION=4.3.11 + SETUPVERSION=4.3.13 de-de True ICE57 @@ -25,7 +25,7 @@ ..\..\..\msi\ obj\$(Configuration)\ - SETUPVERSION=4.3.11 + SETUPVERSION=4.3.13 de-de True ICE57 @@ -88,7 +88,7 @@ set "$(WixVariables)" -"%25ProgramFiles%25\Windows Kits\8.0\bin\x86\msiinfo.exe" "$(TargetDir)\de-de\$(TargetFileName)" /T "DVB.NET Viewer %25SETUPVERSION%25" +"%25ProgramFiles%25\Windows Kits\10\bin\x86\msiinfo.exe" "$(TargetDir)\de-de\$(TargetFileName)" /T "DVB.NET Viewer %25SETUPVERSION%25" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + &Speichern + + + &Verwerfen + + + Wert eingeben + + \ No newline at end of file diff --git a/DVB.NET/BDA4/Editors/FreeText.resx b/DVB.NET/BDA4/Editors/FreeText.resx new file mode 100644 index 0000000..bef0ff9 --- /dev/null +++ b/DVB.NET/BDA4/Editors/FreeText.resx @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + False + + + + 304, 10 + + + 75, 23 + + + 1 + + + &Update + + + cmdSave + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + 385, 10 + + + 75, 23 + + + 2 + + + &Discard + + + cmdCancel + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 12, 12 + + + 286, 20 + + + 0 + + + txtValue + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 6, 13 + + + 472, 45 + + + + CenterParent + + + Enter Value + + + FreeText + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/DVB.NET/BDA4/Enumerators/Device.cs b/DVB.NET/BDA4/Enumerators/Device.cs index c6be294..0f0fd7d 100644 --- a/DVB.NET/BDA4/Enumerators/Device.cs +++ b/DVB.NET/BDA4/Enumerators/Device.cs @@ -286,7 +286,7 @@ private void ChangeState( int stateCode ) pData.cbSize = Marshal.SizeOf( pData ); // Find them all - for (uint ix = 0; SetupDiEnumDeviceInfo( hInfoList, ix++, ref pData ); ) + for (uint ix = 0; SetupDiEnumDeviceInfo( hInfoList, ix++, ref pData );) { // Load the name string name; @@ -360,7 +360,7 @@ public static List GetDeviceInformations( string deviceClass // Open enumerator var @class = new Guid( deviceClass ); var hInfoList = SetupDiGetClassDevs( ref @class, IntPtr.Zero, IntPtr.Zero, 2 ); - if ((int) hInfoList == -1) + if (hInfoList.ToInt64() == -1) throw new DeviceException( "Could not create Device Set" ); // With cleanup @@ -370,7 +370,7 @@ public static List GetDeviceInformations( string deviceClass var pData = new DeviceInfoData { cbSize = Marshal.SizeOf( typeof( DeviceInfoData ) ) }; // Find them all - for (uint ix = 0; SetupDiEnumDeviceInfo( hInfoList, ix++, ref pData ); ) + for (uint ix = 0; SetupDiEnumDeviceInfo( hInfoList, ix++, ref pData );) { // Friendly name var friendly = ReadStringProperty( hInfoList, ref pData, 0 ); @@ -449,7 +449,7 @@ public static string[] GetDevicePaths( Guid deviceClassIdentifier ) var pathPtr = new IntPtr( sysmem.ToInt64() + 4 ); // Find them all - for (uint ix = 0; SetupDiEnumDeviceInterfaces( hInfoList, IntPtr.Zero, ref deviceClassIdentifier, ix++, ref interfaceData ); ) + for (uint ix = 0; SetupDiEnumDeviceInterfaces( hInfoList, IntPtr.Zero, ref deviceClassIdentifier, ix++, ref interfaceData );) { // Helper UInt32 needed; diff --git a/DVB.NET/BDA4/JMS.DVB.DeviceAccess.csproj b/DVB.NET/BDA4/JMS.DVB.DeviceAccess.csproj index 4de115d..0780e8c 100644 --- a/DVB.NET/BDA4/JMS.DVB.DeviceAccess.csproj +++ b/DVB.NET/BDA4/JMS.DVB.DeviceAccess.csproj @@ -79,6 +79,12 @@ + + Form + + + FreeText.cs + Form @@ -210,11 +216,14 @@ - - dvbnet4.snk - - - + + FreeText.cs + Designer + + + FreeText.cs + Designer + DeviceIndex.cs Designer diff --git a/DVB.NET/Card Server/CardServerCore/ActiveStream.cs b/DVB.NET/Card Server/CardServerCore/ActiveStream.cs index 00c8886..0e4325c 100644 --- a/DVB.NET/Card Server/CardServerCore/ActiveStream.cs +++ b/DVB.NET/Card Server/CardServerCore/ActiveStream.cs @@ -200,7 +200,7 @@ public void Refresh( TimeSpan interval ) return; // Get the source information - var info = manager.GetCurrentInformation(); + var info = manager.GetCurrentInformationAsync().CancelAfter( 15000 ).Result; // Must start if (!FirstActivationDone) diff --git a/DVB.NET/Card Server/CardServerCore/Implementation/InMemoryCardServer_EPG.cs b/DVB.NET/Card Server/CardServerCore/Implementation/InMemoryCardServer_EPG.cs index bc0acd0..63c42fd 100644 --- a/DVB.NET/Card Server/CardServerCore/Implementation/InMemoryCardServer_EPG.cs +++ b/DVB.NET/Card Server/CardServerCore/Implementation/InMemoryCardServer_EPG.cs @@ -469,7 +469,7 @@ private void CollectProgramGuide( Hardware device ) device.SelectGroup( next.Location, next.Group ); // See if there is something on this group - if (null == device.GetGroupInformation( 5000 )) + if (null == device.GetGroupInformation( 15000 )) { // Push back m_EPGPending.Add( next ); diff --git a/DVB.NET/Card Server/CardServerCore/InMemoryCardServer.cs b/DVB.NET/Card Server/CardServerCore/InMemoryCardServer.cs index fb6c684..39a6208 100644 --- a/DVB.NET/Card Server/CardServerCore/InMemoryCardServer.cs +++ b/DVB.NET/Card Server/CardServerCore/InMemoryCardServer.cs @@ -248,7 +248,7 @@ private void TestForRestart( Hardware device ) return; // Get the group information - var info = device.GetGroupInformation( 5000 ); + var info = device.GetGroupInformation( 15000 ); if (info == null) { // See if we are already out of retries @@ -510,7 +510,7 @@ private ServerInformation CreateState( Hardware device ) var info = new ServerInformation { - HasGroupInformation = (device.GetGroupInformation( 5000 ) != null), + HasGroupInformation = (device.GetGroupInformation( 15000 ) != null), ProgramGuideProgress = EPGProgress, Selection = selection.SelectionKey }; diff --git a/DVB.NET/Common/RunTimeLoader.cs b/DVB.NET/Common/RunTimeLoader.cs index 00ae1b6..8bd91cb 100644 --- a/DVB.NET/Common/RunTimeLoader.cs +++ b/DVB.NET/Common/RunTimeLoader.cs @@ -136,7 +136,8 @@ private static DirectoryInfo GetInstallationDirectory( string scope ) var path = @"SOFTWARE\JMS\DVB.NET\" + name.ToString(); // Attach to the registry - using (var key = Registry.LocalMachine.OpenSubKey( path )) + using (var reg32 = RegistryKey.OpenBaseKey( RegistryHive.LocalMachine, RegistryView.Registry32 )) + using (var key = reg32.OpenSubKey( path, false )) { // Not found if (key == null) diff --git a/DVB.NET/EPG/Descriptor.cs b/DVB.NET/EPG/Descriptor.cs index 2e15cfc..3ea1af6 100644 --- a/DVB.NET/EPG/Descriptor.cs +++ b/DVB.NET/EPG/Descriptor.cs @@ -38,33 +38,38 @@ public abstract class Descriptor /// of type with a single parameter. This method /// has to report true for any descriptor tag it is responsible for. /// - private static readonly Type[] m_Handlers = - { - typeof(Descriptors.ShortEvent), - typeof(Descriptors.Content), - typeof(Descriptors.Component), - typeof(Descriptors.ExtendedEvent), - typeof(Descriptors.PrivateData), - typeof(Descriptors.PDCDescriptor), - typeof(Descriptors.ParentalRating), - typeof(Descriptors.Linkage), + private static readonly Type[] m_Handlers = + { + typeof(Descriptors.ShortEvent), + typeof(Descriptors.Content), + typeof(Descriptors.Component), + typeof(Descriptors.ExtendedEvent), + typeof(Descriptors.PrivateData), + typeof(Descriptors.PDCDescriptor), + typeof(Descriptors.ParentalRating), + typeof(Descriptors.Linkage), typeof(Descriptors.StreamIdentifier), typeof(Descriptors.Service), typeof(Descriptors.ISOLanguage), typeof(Descriptors.DataBroadcast), typeof(Descriptors.Teletext), typeof(Descriptors.AC3), - typeof(Descriptors.NetworkName), - typeof(Descriptors.CableDelivery), - typeof(Descriptors.SatelliteDelivery), + typeof(Descriptors.AAC), + typeof(Descriptors.NetworkName), + typeof(Descriptors.CableDelivery), + typeof(Descriptors.SatelliteDelivery), typeof(Descriptors.TerrestrialDelivery), - typeof(Descriptors.ServiceList), + typeof(Descriptors.ServiceList), typeof(Descriptors.Subtitle), typeof(Descriptors.ContentTransmissionPremiere), typeof(Descriptors.CellList), typeof(Descriptors.FrequencyList), - typeof(Descriptors.CellFrequencyLink) - }; + typeof(Descriptors.CellFrequencyLink), + typeof(Descriptors.AncillaryData), + typeof(Descriptors.ApplicationSignalling), + typeof(Descriptors.DataBroadastId), + typeof(Descriptors.CarouselIdentifier) + }; /// /// Populate the descriptor tag lookup map. @@ -72,7 +77,7 @@ public abstract class Descriptor static Descriptor() { // Use helper - Tools.InitializeDynamicCreate( m_Handlers, m_HandlerForTag, typeof( Descriptors.Generic ) ); + Tools.InitializeDynamicCreate(m_Handlers, m_HandlerForTag, typeof(Descriptors.Generic)); } /// @@ -114,10 +119,10 @@ static Descriptor() /// The number of bytes for this instance. Since this /// does not include the tag and the length /// will be two greater than the value of this parameter. - protected Descriptor( IDescriptorContainer container, int offset, int length ) + protected Descriptor(IDescriptorContainer container, int offset, int length) { // Set - Tag = (DescriptorTags) container.Section[offset - 2]; + Tag = (DescriptorTags)container.Section[offset - 2]; // Remember Container = container; @@ -128,7 +133,7 @@ protected Descriptor( IDescriptorContainer container, int offset, int length ) /// /// /// - protected Descriptor( DescriptorTags tag ) + protected Descriptor(DescriptorTags tag) { // Remember Tag = tag; @@ -149,13 +154,13 @@ protected Descriptor( DescriptorTags tag ) /// does not include the tag and the length /// will be two greater than the value of this parameter. /// A newly created instance. - static public Descriptor Create( IDescriptorContainer container, int offset, int length ) + static public Descriptor Create(IDescriptorContainer container, int offset, int length) { // Attach to the type - Type pHandler = (Type) m_HandlerForTag[container.Section[offset - 2]]; + Type pHandler = (Type)m_HandlerForTag[container.Section[offset - 2]]; // Create - return (Descriptor) Activator.CreateInstance( pHandler, new object[] { container, offset, length } ); + return (Descriptor)Activator.CreateInstance(pHandler, new object[] { container, offset, length }); } /// @@ -175,7 +180,7 @@ static public Descriptor Create( IDescriptorContainer container, int offset, int /// event. New instances are created until /// there is no space left. /// All instances for an event. - static public Descriptor[] Load( IDescriptorContainer container, int offset, int length ) + static public Descriptor[] Load(IDescriptorContainer container, int offset, int length) { // Attach to data Section section = container.Section; @@ -196,10 +201,10 @@ static public Descriptor[] Load( IDescriptorContainer container, int offset, int if ((2 + bytes) > length) break; // Create instance - Descriptor pNew = Create( container, offset + 2, bytes ); + Descriptor pNew = Create(container, offset + 2, bytes); // Remember - all.Add( pNew ); + all.Add(pNew); // Adjust offset += pNew.Length; @@ -207,20 +212,13 @@ static public Descriptor[] Load( IDescriptorContainer container, int offset, int } // Create - return (Descriptor[]) all.ToArray( typeof( Descriptor ) ); + return (Descriptor[])all.ToArray(typeof(Descriptor)); } /// /// Report if this instance is valid. /// - public bool IsValid - { - get - { - // Report - return m_Valid; - } - } + public bool IsValid => m_Valid; /// /// The related . @@ -228,14 +226,7 @@ public bool IsValid /// /// This is the of our . /// - public Table Table - { - get - { - // Forward - return Container.Container; - } - } + public Table Table => Container.Container; /// /// The related . @@ -243,39 +234,32 @@ public Table Table /// /// This is the of our . /// - public Section Section - { - get - { - // Forward - return Table.Section; - } - } + public Section Section => Table.Section; /// /// Append the binary formatted descriptor to the buffer provided. /// /// Some buffer. - internal void CreateDescriptor( TableConstructor buffer ) + internal void CreateDescriptor(TableConstructor buffer) { // Write the tag - buffer.Add( (byte) Tag ); + buffer.Add((byte)Tag); // Position of length int lengthPos = buffer.CreateDynamicLength(); // Add payload - CreatePayload( buffer ); + CreatePayload(buffer); // Update the length - buffer.SetDynamicLength( lengthPos ); + buffer.SetDynamicLength(lengthPos); } /// /// /// /// - protected virtual void CreatePayload( TableConstructor buffer ) + protected virtual void CreatePayload(TableConstructor buffer) { // Must be implemented by derived classes throw new NotImplementedException(); @@ -294,14 +278,14 @@ public static class DescriptorExtensions /// Die Liste der zu durchsuchenden Beschreibungen. /// Die gewnschte Beschreibung oder null, wenn keine Beschreibung /// der gesuchten Art in der Liste vorhanden ist. - public static T Find( this Descriptor[] descriptors ) where T : Descriptor + public static T Find(this Descriptor[] descriptors) where T : Descriptor { // Not possible if (null == descriptors) return null; // Lookup - return (T) Array.Find( descriptors, d => typeof( T ) == d.GetType() ); + return (T)Array.Find(descriptors, d => typeof(T) == d.GetType()); } } diff --git a/DVB.NET/EPG/DescriptorTags.cs b/DVB.NET/EPG/DescriptorTags.cs index fea186f..bcc87b7 100644 --- a/DVB.NET/EPG/DescriptorTags.cs +++ b/DVB.NET/EPG/DescriptorTags.cs @@ -2,17 +2,17 @@ namespace JMS.DVB.EPG { - /// - /// The various descriptor types as defined in the original documentation, - /// e.g. ETSI EN 300 468 V1.6.1 (2004-06) or alternate versions. - /// - /// - /// - /// 0x80 to 0xfe are user defined and 0xff - /// is forbidden. - /// - public enum DescriptorTags - { + /// + /// The various descriptor types as defined in the original documentation, + /// e.g. ETSI EN 300 468 V1.6.1 (2004-06) or alternate versions. + /// + /// + /// + /// 0x80 to 0xfe are user defined and 0xff + /// is forbidden. + /// + public enum DescriptorTags + { /// /// 0x00 /// @@ -52,7 +52,7 @@ public enum DescriptorTags /// 0x07 /// TargetBackgroundGrid, - + /// /// 0x08 /// @@ -111,302 +111,312 @@ public enum DescriptorTags /// /// 0x13 /// - ISOReservedLow = 0x13, + CarouselIdentifier, + + /// + /// 0x14 + /// + ISOReservedLow = 0x14, /// /// 0x3f /// ISOReservedHigh = 0x3f, - /// - /// 0x40 - /// - NetworkName, + /// + /// 0x40 + /// + NetworkName, - /// - /// 0x41 - /// - SeviceList, + /// + /// 0x41 + /// + SeviceList, - /// - /// 0x42 - /// - Stuffing, + /// + /// 0x42 + /// + Stuffing, - /// - /// 0x43 - /// - SatelliteDeliverySystem, + /// + /// 0x43 + /// + SatelliteDeliverySystem, - /// - /// 0x44 - /// - CableDeliverySystem, + /// + /// 0x44 + /// + CableDeliverySystem, - /// - /// 0x45 - /// - VBIData, - - /// - /// 0x46 - /// - VBITeletext, - - /// - /// 0x47 - /// - BouquetName, - - /// - /// 0x48 - /// - Service, - - /// - /// 0x49 - /// - CountryAvailability, - - /// - /// 0x4a - /// - Linkage, - - /// - /// 0x4b - /// - NVODReference, - - /// - /// 0x4c - /// - TimeShiftedService, - - /// - /// 0x4d - /// - ShortEvent, - - /// - /// 0x4e - /// - ExtendedEvent, - - /// - /// 0x4f - /// - TimeShiftedEvent, - - /// - /// 0x50 - /// - Component, - - /// - /// 0x51 - /// - Mosaic, - - /// - /// 0x52 - /// - StreamIdentifier, - - /// - /// 0x53 - /// - CAIdentifier, - - /// - /// 0x54 - /// - Content, - - /// - /// 0x55 - /// - ParentalRating, - - /// - /// 0x56 - /// - Teletext, - - /// - /// 0x57 - /// - Telephone, - - /// - /// 0x58 - /// - LocalTimeOffset, - - /// - /// 0x59 - /// - Subtitling, - - /// - /// 0x5a - /// - TerrestrialDeliverySystem, - - /// - /// 0x5b - /// - MultilingualNetworkName, - - /// - /// 0x5c - /// - MultilingualBouquetName, - - /// - /// 0x5d - /// - MultilingualServiceName, - - /// - /// 0x5e - /// - MultilingualComponent, - - /// - /// 0x5f - /// - PrivateDataSpecifier, - - /// - /// 0x60 - /// - ServiceMove, - - /// - /// 0x61 - /// - ShortSmoothingBuffer, - - /// - /// 0x62 - /// - FrequencyList, - - /// - /// 0x63 - /// - PartialTransportStream, - - /// - /// 0x64 - /// - DataBroadcast, - - /// - /// 0x65 - /// - CASystem, - - /// - /// 0x66 - /// - DataBroadcastId, - - /// - /// 0x67 - /// - TransportStream, - - /// - /// 0x68 - /// - DSNG, - - /// - /// 0x69 - /// - PDC, - - /// - /// 0x6a - /// - AC3, - - /// - /// 0x6b - /// - AncillaryData, - - /// - /// 0x6c - /// - CellList, - - /// - /// 0x6d - /// - CellFrequencyLink, - - /// - /// 0x6e - /// - AnnouncementSupport, - - /// - /// 0x6f - /// - ApplicationSignalling, - - /// - /// 0x70 - /// - AdaptationFieldData, - - /// - /// 0x71 - /// - ServiceIdentifier, - - /// - /// 0x72 - /// - ServiceAvailability, - - /// - /// 0x73 - /// - DefaultAuthority, + /// + /// 0x45 + /// + VBIData, - /// - /// 0x74 - /// - RelatedContent, - - /// - /// 0x75 - /// - TVAId, - - /// - /// 0x76 - /// - ContentIdentifier, - - /// - /// 0x77 - /// - TimeSliceFecIdentifier, - - /// - /// 0x78 + /// + /// 0x46 + /// + VBITeletext, + + /// + /// 0x47 + /// + BouquetName, + + /// + /// 0x48 + /// + Service, + + /// + /// 0x49 + /// + CountryAvailability, + + /// + /// 0x4a + /// + Linkage, + + /// + /// 0x4b + /// + NVODReference, + + /// + /// 0x4c + /// + TimeShiftedService, + + /// + /// 0x4d + /// + ShortEvent, + + /// + /// 0x4e + /// + ExtendedEvent, + + /// + /// 0x4f + /// + TimeShiftedEvent, + + /// + /// 0x50 + /// + Component, + + /// + /// 0x51 + /// + Mosaic, + + /// + /// 0x52 + /// + StreamIdentifier, + + /// + /// 0x53 + /// + CAIdentifier, + + /// + /// 0x54 + /// + Content, + + /// + /// 0x55 + /// + ParentalRating, + + /// + /// 0x56 + /// + Teletext, + + /// + /// 0x57 + /// + Telephone, + + /// + /// 0x58 + /// + LocalTimeOffset, + + /// + /// 0x59 + /// + Subtitling, + + /// + /// 0x5a + /// + TerrestrialDeliverySystem, + + /// + /// 0x5b + /// + MultilingualNetworkName, + + /// + /// 0x5c + /// + MultilingualBouquetName, + + /// + /// 0x5d + /// + MultilingualServiceName, + + /// + /// 0x5e + /// + MultilingualComponent, + + /// + /// 0x5f + /// + PrivateDataSpecifier, + + /// + /// 0x60 + /// + ServiceMove, + + /// + /// 0x61 + /// + ShortSmoothingBuffer, + + /// + /// 0x62 + /// + FrequencyList, + + /// + /// 0x63 + /// + PartialTransportStream, + + /// + /// 0x64 + /// + DataBroadcast, + + /// + /// 0x65 + /// + CASystem, + + /// + /// 0x66 + /// + DataBroadcastId, + + /// + /// 0x67 + /// + TransportStream, + + /// + /// 0x68 + /// + DSNG, + + /// + /// 0x69 + /// + PDC, + + /// + /// 0x6a + /// + AC3, + + /// + /// 0x6b + /// + AncillaryData, + + /// + /// 0x6c + /// + CellList, + + /// + /// 0x6d + /// + CellFrequencyLink, + + /// + /// 0x6e + /// + AnnouncementSupport, + + /// + /// 0x6f + /// + ApplicationSignalling, + + /// + /// 0x70 + /// + AdaptationFieldData, + + /// + /// 0x71 + /// + ServiceIdentifier, + + /// + /// 0x72 + /// + ServiceAvailability, + + /// + /// 0x73 + /// + DefaultAuthority, + + /// + /// 0x74 + /// + RelatedContent, + + /// + /// 0x75 + /// + TVAId, + + /// + /// 0x76 + /// + ContentIdentifier, + + /// + /// 0x77 + /// + TimeSliceFecIdentifier, + + /// + /// 0x78 + /// + ECMRepetitionRate, + + /// + /// 0x7c /// - ECMRepetitionRate, + AAC = 0x7c, /// /// Enthlt die Ausstrahlungsdaten einer Sendung des deutschen PayTV /// Anbieters PREMIERE. /// ContentTransmissionPremiere = 0xf2 - } + } } diff --git a/DVB.NET/EPG/Descriptors/AAC.cs b/DVB.NET/EPG/Descriptors/AAC.cs new file mode 100644 index 0000000..0abc26a --- /dev/null +++ b/DVB.NET/EPG/Descriptors/AAC.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; + +namespace JMS.DVB.EPG.Descriptors +{ + /// + /// AAC descriptor. + /// + public class AAC : Descriptor + { + /// + /// Profile and level of the content. + /// + public byte ProfileAndLevel { get; set; } + + /// + /// AAC Type of the content. + /// + public byte? Type { get; set; } + + /// + /// Additional information. + /// + private byte[] m_AdditionalInformation = { }; + + /// + /// + /// + public byte[] AdditionalInformation + { + get + { + // Report + return m_AdditionalInformation; + } + set + { + // Never null it + m_AdditionalInformation = value ?? new byte[0]; + } + } + + /// + /// + /// + public AAC(byte profileAndLevel, byte? type) + : base(DescriptorTags.AAC) + { + ProfileAndLevel = profileAndLevel; + Type = type; + } + + /// + /// Create a new descriptor instance. + /// + /// + /// will only be set if the payload is + /// consistent. + /// + /// The related container instance. + /// First byte of the descriptor data - the first byte after the tag. + /// Number of payload bytes for this descriptor. + public AAC(IDescriptorContainer container, int offset, int length) + : base(container, offset, length) + { + // Attach to the section + Section section = container.Section; + + // Check minimum length + if (length-- < 1) return; + + // Read profile and level. + ProfileAndLevel = section[offset++]; + + // Check minimum length + if (length-- < 1) return; + + // Read flags + byte flags = section[offset++]; + + // Load type. + if (0x80 == (0x80 & flags)) + { + // Check minimum length + if (length-- < 1) return; + + Type = section[offset++]; + } + + // Load the additional information + m_AdditionalInformation = section.ReadBytes(offset, length); + + // Done + m_Valid = true; + } + + /// + /// Check if this class is responsible for a given descriptor tag. + /// + /// The tag to test for. + /// Set if this class can handle the payload for the given tag. + public static bool IsHandlerFor(byte tag) => (DescriptorTags.AAC == (DescriptorTags)tag); + + /// + /// + /// + /// + protected override void CreatePayload(TableConstructor buffer) + { + // Profile and level. + buffer.Add(ProfileAndLevel); + + // Collected flags + byte flags = 0; + + // Load flags + if (Type.HasValue) flags |= 0x80; + + // Write flags + buffer.Add(flags); + + // Write all + if (Type.HasValue) buffer.Add(Type.Value); + + // Load the additional information + buffer.Add(m_AdditionalInformation); + } + } +} diff --git a/DVB.NET/EPG/Descriptors/AncillaryData.cs b/DVB.NET/EPG/Descriptors/AncillaryData.cs new file mode 100644 index 0000000..9cc0f9b --- /dev/null +++ b/DVB.NET/EPG/Descriptors/AncillaryData.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; + +namespace JMS.DVB.EPG.Descriptors +{ + /// + /// Ancillary data . + /// + /// + /// For details please refer to the original documentation, + /// e.g. ETSI EN 300 468 V1.6.1 (2004-06) or alternate versions. + /// + public class AncillaryData : Descriptor + { + /// + /// The Data Identifier. + /// + public readonly byte Identifier; + + /// + /// + /// + public AncillaryData(byte identifier) + : base(DescriptorTags.AncillaryData) + { + // Remember + Identifier = identifier; + } + + /// + /// Create a new descriptor instance. + /// + /// + /// will only be set if the payload is + /// consistent. + /// + /// The related container instance. + /// First byte of the descriptor data - the first byte after the tag. + /// Number of payload bytes for this descriptor. + public AncillaryData(IDescriptorContainer container, int offset, int length) + : base(container, offset, length) + { + // Validate size + if (1 != length) return; + + // Attach to data + Section section = container.Section; + + // Load + Identifier = section[offset]; + + // We are valid + m_Valid = true; + } + + /// + /// Check if this class is responsible for a given descriptor tag. + /// + /// The tag to test for. + /// Set if this class can handle the payload for the given tag. + public static bool IsHandlerFor(byte tag) => DescriptorTags.AncillaryData == (DescriptorTags)tag; + + /// + /// + /// + /// + protected override void CreatePayload(TableConstructor buffer) + { + // Add + buffer.Add(Identifier); + } + } +} diff --git a/DVB.NET/EPG/Descriptors/ApplicationSignalling.cs b/DVB.NET/EPG/Descriptors/ApplicationSignalling.cs new file mode 100644 index 0000000..12ef505 --- /dev/null +++ b/DVB.NET/EPG/Descriptors/ApplicationSignalling.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; + +namespace JMS.DVB.EPG.Descriptors +{ + /// + /// Application Signalling . + /// + /// + /// For details please refer to the original documentation, + /// e.g. ETSI TS 102 809 V1.3.1 (2017-06) or alternate versions. + /// + public class ApplicationSignalling : Descriptor + { + /// + /// Informationen zu einer einzelnen Anwendung. + /// + public struct Application + { + /// + /// Die Art der Anwendung. + /// + readonly ushort Type; + + /// + /// Die Version der Anwendung. + /// + readonly byte Version; + + /// + /// Erstellt eine neue Information zu einer Anwendung. + /// + /// Die Art der Anwendung. + /// Die Version der Anwendung. + public Application(ushort type, byte version) + { + Type = type; + Version = version; + } + + /// + /// Rekonstruiert die Anewnedungsinformation. + /// + /// Sammelt rekonstruierte Daten. + public void createPayload(TableConstructor buffer) + { + buffer.Add((byte)(Type >> 8)); + buffer.Add((byte)Type); + buffer.Add((byte)(Version | 0xe0)); + } + }; + + /// + /// Alle Anwendungen. + /// + public readonly List Applications = new List(); + + /// + /// + /// + public ApplicationSignalling(params Application[] applications) + : base(DescriptorTags.ApplicationSignalling) + { + Applications.AddRange(applications); + } + + /// + /// Create a new descriptor instance. + /// + /// + /// will only be set if the payload is + /// consistent. + /// + /// The related container instance. + /// First byte of the descriptor data - the first byte after the tag. + /// Number of payload bytes for this descriptor. + public ApplicationSignalling(IDescriptorContainer container, int offset, int length) + : base(container, offset, length) + { + // Attach to data + Section section = container.Section; + + // Readhte list + for (; length >= 3; length -= 3) + { + // Type and version. + var typeH = section[offset++] & 0x7f; + var typeL = section[offset++]; + var version = section[offset++] & 0x1f; + + Applications.Add(new Application((ushort)((typeH << 8) + typeL), (byte)version)); + } + + // Validate size + if (0 != length) return; + + // We are valid + m_Valid = true; + } + + /// + /// Check if this class is responsible for a given descriptor tag. + /// + /// The tag to test for. + /// Set if this class can handle the payload for the given tag. + public static bool IsHandlerFor(byte tag) => DescriptorTags.ApplicationSignalling == (DescriptorTags)tag; + + /// + /// + /// + /// + protected override void CreatePayload(TableConstructor buffer) + { + // Das machen die Anwendungen selbst. + Applications.ForEach(a => a.createPayload(buffer)); + } + } +} diff --git a/DVB.NET/EPG/Descriptors/CarouselIdentifier.cs b/DVB.NET/EPG/Descriptors/CarouselIdentifier.cs new file mode 100644 index 0000000..0e53d37 --- /dev/null +++ b/DVB.NET/EPG/Descriptors/CarouselIdentifier.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; + +namespace JMS.DVB.EPG.Descriptors +{ + /// + /// Carousel Identifier . + /// + /// + /// For details please refer to the original documentation, + /// e.g. ETSI TS 102 809 V1.3.1 (2017-06) or alternate versions. + /// + public class CarouselIdentifier : Descriptor + { + /// + /// Identification of the carousel. + /// + public uint Identifier; + + /// + /// Format of the Carousel. + /// + public byte Format; + + /// + /// Nicht weiter ausgewertet Informationen zum Format. + /// + public readonly List RawFormat = new List(); + + /// + /// + /// + public CarouselIdentifier(uint identifier, byte format, params byte[] rawFormat) + : base(DescriptorTags.CarouselIdentifier) + { + Identifier = identifier; + Format = format; + + RawFormat.AddRange(rawFormat); + } + + /// + /// Create a new descriptor instance. + /// + /// + /// will only be set if the payload is + /// consistent. + /// + /// The related container instance. + /// First byte of the descriptor data - the first byte after the tag. + /// Number of payload bytes for this descriptor. + public CarouselIdentifier(IDescriptorContainer container, int offset, int length) + : base(container, offset, length) + { + // Validate size + if (length < 5) return; + + // Attach to data + Section section = container.Section; + + // Load + var id3 = section[offset++]; + var id2 = section[offset++]; + var id1 = section[offset++]; + var id0 = section[offset++]; + + Identifier = (uint)(id0 + 256 * (id1 + 256 * (id2 + 256 * id3))); + Format = section[offset++]; + + // Load the selector bytes. + for (length -= 5; length > 0; length--) + { + RawFormat.Add(section[offset++]); + } + + // We are valid + m_Valid = true; + } + + /// + /// Check if this class is responsible for a given descriptor tag. + /// + /// The tag to test for. + /// Set if this class can handle the payload for the given tag. + public static bool IsHandlerFor(byte tag) => DescriptorTags.CarouselIdentifier == (DescriptorTags)tag; + + /// + /// + /// + /// + protected override void CreatePayload(TableConstructor buffer) + { + buffer.Add((byte)(Identifier >> 24)); + buffer.Add((byte)(Identifier >> 16)); + buffer.Add((byte)(Identifier >> 8)); + buffer.Add((byte)Identifier); + + buffer.Add(Format); + + buffer.Add(RawFormat.ToArray()); + } + } +} diff --git a/DVB.NET/EPG/Descriptors/DataBroadastId.cs b/DVB.NET/EPG/Descriptors/DataBroadastId.cs new file mode 100644 index 0000000..5976fd8 --- /dev/null +++ b/DVB.NET/EPG/Descriptors/DataBroadastId.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; + +namespace JMS.DVB.EPG.Descriptors +{ + /// + /// Data Broadcast Identifier . + /// + /// + /// For details please refer to the original documentation, + /// e.g. ETSI EN 300 468 V1.6.1 (2004-06) or alternate versions. + /// + public class DataBroadastId : Descriptor + { + /// + /// Identification of the broadcast. + /// + public ushort Identifier; + + /// + /// Selector Bytes. + /// + public readonly List Selectors = new List(); + + /// + /// + /// + public DataBroadastId(ushort identifier, params byte[] selectors) + : base(DescriptorTags.DataBroadcastId) + { + Identifier = identifier; + + Selectors.AddRange(selectors); + } + + /// + /// Create a new descriptor instance. + /// + /// + /// will only be set if the payload is + /// consistent. + /// + /// The related container instance. + /// First byte of the descriptor data - the first byte after the tag. + /// Number of payload bytes for this descriptor. + public DataBroadastId(IDescriptorContainer container, int offset, int length) + : base(container, offset, length) + { + // Validate size + if (length < 2) return; + + // Attach to data + Section section = container.Section; + + // Load + var idH = section[offset++]; + var idL = section[offset++]; + + Identifier = (ushort)((idH << 8) + idL); + + // Load the selector bytes. + for (length -= 2; length > 0; length--) + { + Selectors.Add(section[offset++]); + } + + // We are valid + m_Valid = true; + } + + /// + /// Check if this class is responsible for a given descriptor tag. + /// + /// The tag to test for. + /// Set if this class can handle the payload for the given tag. + public static bool IsHandlerFor(byte tag) => DescriptorTags.DataBroadcastId == (DescriptorTags)tag; + + /// + /// + /// + /// + protected override void CreatePayload(TableConstructor buffer) + { + buffer.Add(Identifier); + buffer.Add(Selectors.ToArray()); + } + } +} diff --git a/DVB.NET/EPG/Descriptors/Generic.cs b/DVB.NET/EPG/Descriptors/Generic.cs index e0543f5..4ce6f38 100644 --- a/DVB.NET/EPG/Descriptors/Generic.cs +++ b/DVB.NET/EPG/Descriptors/Generic.cs @@ -1,16 +1,22 @@ using System; +using System.Collections.Generic; namespace JMS.DVB.EPG.Descriptors { - /// - /// A generic class used for all unsupported - /// descriptor tags. - /// - /// - /// will always be unset. - /// - public class Generic: Descriptor - { + /// + /// A generic class used for all unsupported + /// descriptor tags. + /// + /// + /// will always be unset. + /// + public class Generic : Descriptor + { + /// + /// Die nicht ausgewerteten Rohdaten - vor allem zu Testzwecken. + /// + public readonly List RawData = new List(); + /// /// Create a new descriptor instance. /// @@ -23,7 +29,11 @@ public class Generic: Descriptor /// Number of payload bytes for this descriptor. public Generic(IDescriptorContainer container, int offset, int length) : base(container, offset, length) - { + { + while (length-- > 0) + { + RawData.Add(container.Section[offset++]); + } } - } + } } diff --git a/DVB.NET/EPG/JMS.DVB.EPG.csproj b/DVB.NET/EPG/JMS.DVB.EPG.csproj index 263abfc..1b2073b 100644 --- a/DVB.NET/EPG/JMS.DVB.EPG.csproj +++ b/DVB.NET/EPG/JMS.DVB.EPG.csproj @@ -127,6 +127,11 @@ + + + + + diff --git a/DVB.NET/EPG/ProgramEntry.cs b/DVB.NET/EPG/ProgramEntry.cs index 0a43d30..be3e839 100644 --- a/DVB.NET/EPG/ProgramEntry.cs +++ b/DVB.NET/EPG/ProgramEntry.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Collections.Generic; +using System.Linq; namespace JMS.DVB.EPG { @@ -12,7 +13,7 @@ public class ProgramEntry : EntryBase /// /// Maps ISO language names to their native representation. /// - private static Dictionary m_CultureMap = new Dictionary( StringComparer.InvariantCultureIgnoreCase ); + private static Dictionary m_CultureMap = new Dictionary(StringComparer.InvariantCultureIgnoreCase); /// /// The constructor is private to make this class static. @@ -20,35 +21,35 @@ public class ProgramEntry : EntryBase static ProgramEntry() { // Load all - foreach (CultureInfo info in CultureInfo.GetCultures( CultureTypes.NeutralCultures )) + foreach (CultureInfo info in CultureInfo.GetCultures(CultureTypes.NeutralCultures)) { // Remember m_CultureMap[info.ThreeLetterISOLanguageName] = info; } // Add special entries (bibliographic - see ISO639-2) - AddBibliographicShortcut( "bod", "tib" ); - AddBibliographicShortcut( "ces", "cze" ); - AddBibliographicShortcut( "cym", "wel" ); - AddBibliographicShortcut( "deu", "ger" ); - AddBibliographicShortcut( "ell", "gre" ); - AddBibliographicShortcut( "eus", "baq" ); - AddBibliographicShortcut( "fas", "per" ); - AddBibliographicShortcut( "fra", "fre" ); - AddBibliographicShortcut( "hrv", "scr" ); - AddBibliographicShortcut( "hye", "arm" ); - AddBibliographicShortcut( "isl", "ice" ); - AddBibliographicShortcut( "kat", "geo" ); - AddBibliographicShortcut( "mkd", "mac" ); - AddBibliographicShortcut( "mri", "mao" ); - AddBibliographicShortcut( "msa", "may" ); - AddBibliographicShortcut( "mya", "bur" ); - AddBibliographicShortcut( "nld", "dut" ); - AddBibliographicShortcut( "ron", "rum" ); - AddBibliographicShortcut( "slk", "slo" ); - AddBibliographicShortcut( "sqi", "alb" ); - AddBibliographicShortcut( "srp", "scc" ); - AddBibliographicShortcut( "zho", "chi" ); + AddBibliographicShortcut("bod", "tib"); + AddBibliographicShortcut("ces", "cze"); + AddBibliographicShortcut("cym", "wel"); + AddBibliographicShortcut("deu", "ger"); + AddBibliographicShortcut("ell", "gre"); + AddBibliographicShortcut("eus", "baq"); + AddBibliographicShortcut("fas", "per"); + AddBibliographicShortcut("fra", "fre"); + AddBibliographicShortcut("hrv", "scr"); + AddBibliographicShortcut("hye", "arm"); + AddBibliographicShortcut("isl", "ice"); + AddBibliographicShortcut("kat", "geo"); + AddBibliographicShortcut("mkd", "mac"); + AddBibliographicShortcut("mri", "mao"); + AddBibliographicShortcut("msa", "may"); + AddBibliographicShortcut("mya", "bur"); + AddBibliographicShortcut("nld", "dut"); + AddBibliographicShortcut("ron", "rum"); + AddBibliographicShortcut("slk", "slo"); + AddBibliographicShortcut("sqi", "alb"); + AddBibliographicShortcut("srp", "scc"); + AddBibliographicShortcut("zho", "chi"); } /// @@ -56,15 +57,15 @@ static ProgramEntry() /// /// Official three letter code. /// Alternat (bibliographic) three letter code. - private static void AddBibliographicShortcut( string terminologyCode, string bibliographicCode ) + private static void AddBibliographicShortcut(string terminologyCode, string bibliographicCode) { // See if code already exists - if (m_CultureMap.ContainsKey( bibliographicCode )) + if (m_CultureMap.ContainsKey(bibliographicCode)) return; // Load entry CultureInfo terminologic; - if (!m_CultureMap.TryGetValue( terminologyCode, out terminologic )) + if (!m_CultureMap.TryGetValue(terminologyCode, out terminologic)) return; // Connect @@ -109,20 +110,20 @@ private static void AddBibliographicShortcut( string terminologyCode, string bib /// The maximum number of bytes available. If this number /// is greater than the of this program another event will /// follow in the same table. - internal ProgramEntry( Table table, int offset, int length ) - : base( table ) + internal ProgramEntry(Table table, int offset, int length) + : base(table) { // Access section Section section = Section; // Load - ElementaryPID = (ushort) (0x1fff & Tools.MergeBytesToWord( section[offset + 2], section[offset + 1] )); - StreamType = (StreamTypes) section[offset + 0]; + ElementaryPID = (ushort)(0x1fff & Tools.MergeBytesToWord(section[offset + 2], section[offset + 1])); + StreamType = (StreamTypes)section[offset + 0]; // Read the length - int descrLength = 0xfff & Tools.MergeBytesToWord( section[offset + 4], section[offset + 3] ); + int descrLength = 0xfff & Tools.MergeBytesToWord(section[offset + 4], section[offset + 3]); - // Caluclate the total length + // Calculate the total length Length = 5 + descrLength; // Verify @@ -130,7 +131,7 @@ internal ProgramEntry( Table table, int offset, int length ) return; // Try to load descriptors - Descriptors = Descriptor.Load( this, offset + 5, descrLength ); + Descriptors = Descriptor.Load(this, offset + 5, descrLength); // Can use it IsValid = true; @@ -147,14 +148,14 @@ internal ProgramEntry( Table table, int offset, int length ) /// follow in the same table. /// A new service instance or null if there are less than /// 5 bytes available. - static internal ProgramEntry Create( Table table, int offset, int length ) + static internal ProgramEntry Create(Table table, int offset, int length) { // Validate if (length < 5) return null; // Create - return new ProgramEntry( table, offset, length ); + return new ProgramEntry(table, offset, length); } /// @@ -176,15 +177,15 @@ public string ProgrammeName // Remember the first one set string name = language.Languages[0].ISOLanguage; - if (string.IsNullOrEmpty( name )) + if (string.IsNullOrEmpty(name)) continue; // Convert - return GetLanguageFromISOLanguage( name ); + return GetLanguageFromISOLanguage(name); } // Use default - return string.Format( "#{0}", ElementaryPID ); + return string.Format("#{0}", ElementaryPID); } } @@ -194,11 +195,11 @@ public string ProgrammeName /// /// Eine ISO Kurzbezeichnung. /// Der Name der Sprache, ausgerckt in der Sprache selbst. - public static string GetLanguageFromISOLanguage( string language ) + public static string GetLanguageFromISOLanguage(string language) { // Find CultureInfo cult; - if (m_CultureMap.TryGetValue( language, out cult )) + if (m_CultureMap.TryGetValue(language, out cult)) return cult.NativeName; // Report as is diff --git a/DVB.NET/EPG/StreamTypes.cs b/DVB.NET/EPG/StreamTypes.cs index 54c3d13..709f44b 100644 --- a/DVB.NET/EPG/StreamTypes.cs +++ b/DVB.NET/EPG/StreamTypes.cs @@ -8,7 +8,7 @@ namespace JMS.DVB.EPG /// The type of a transport stream. /// public enum StreamTypes - { + { /// /// ITU-T | ISO/IEC Reserved /// @@ -67,7 +67,7 @@ public enum StreamTypes /// /// ISO/IEC 13818-6 type B /// - TypeB, + Carousel, /// /// ISO/IEC 13818-6 type C @@ -77,17 +77,22 @@ public enum StreamTypes /// /// ISO/IEC 13818-6 type D /// - TypeD, + MultiProtocolDataStream, /// /// ISO/IEC 13818-1 auxiliary /// Auxiliary, - /// - /// Intermediate entry for H.264 video. + /// + /// Intermediate entry for AAC Audio. /// - H264 = 0x1b, + AAC = 0x11, + + /// + /// Intermediate entry for H.264 video. + /// + H264 = 0x1b, /// /// ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved, lowest value @@ -108,5 +113,5 @@ public enum StreamTypes /// User Private, highest value /// UserPrivateHigh = 0xff - } + } } diff --git a/DVB.NET/HardwareAbstraction/SourceStreamsManager.cs b/DVB.NET/HardwareAbstraction/SourceStreamsManager.cs index 0d7a015..70c6770 100644 --- a/DVB.NET/HardwareAbstraction/SourceStreamsManager.cs +++ b/DVB.NET/HardwareAbstraction/SourceStreamsManager.cs @@ -1,8 +1,9 @@ -using System; +using JMS.DVB.SI; +using JMS.DVB.TS; +using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; -using JMS.DVB.SI; -using JMS.DVB.TS; namespace JMS.DVB @@ -24,22 +25,11 @@ public class FileStreamInformation /// public VideoTypes VideoType { get; set; } - /// - /// Erzeugt eine neue Beschreibung. - /// - public FileStreamInformation() - { - } - /// /// Meldet einen Anzeigetest zu Testzwecken. /// /// Der Anzeigetext. - public override string ToString() - { - // Construct - return string.Format( "{0} ({1})", FilePath, VideoType ); - } + public override string ToString() => $"{FilePath} ({VideoType})"; } /// @@ -164,15 +154,15 @@ public class SourceStreamsManager : IDisposable /// Die Quelle, die zu betrachten ist. /// Die zu betrachtenden Datenströme. /// Ein Parameter wurde nicht angegeben. - public SourceStreamsManager( Hardware hardware, Profile profile, SourceIdentifier source, StreamSelection selection ) + public SourceStreamsManager(Hardware hardware, Profile profile, SourceIdentifier source, StreamSelection selection) { // Validate if (null == hardware) - throw new ArgumentNullException( "hardware" ); + throw new ArgumentNullException("hardware"); if (null == source) - throw new ArgumentNullException( "source" ); + throw new ArgumentNullException("source"); if (null == selection) - throw new ArgumentNullException( "selection" ); + throw new ArgumentNullException("selection"); // Remember all StreamSelection = selection; @@ -185,26 +175,18 @@ public SourceStreamsManager( Hardware hardware, Profile profile, SourceIdentifie /// Startet das Auslesen der aktuellen Daten zur aktiven Quelle im Hintergrund. /// /// Eine Steuerinstanz zum asynchronen Zugriff auf die aktuellen Daten. - public CancellableTask GetCurrentInformationAsync() - { - // Just forward - return Hardware.GetSourceInformationAsync( Source, Profile ); - } + public CancellableTask GetCurrentInformationAsync() => Hardware.GetSourceInformationAsync(Source, Profile); /// /// Ermittelt die aktuellen Daten zur aktiven Quelle. /// /// Die neu ermittelten aktuellen Daten. - public SourceInformation GetCurrentInformation() - { - // Just forward - return GetCurrentInformationAsync().CancelAfter( 5000 ).Result; - } + public SourceInformation GetCurrentInformation() => GetCurrentInformationAsync().CancelAfter(5000).Result; /// /// Meldet die aktuell verwendeten Daten der Quelle. /// - public SourceInformation ActiveInformation { get { return m_OriginalSettings; } } + public SourceInformation ActiveInformation => m_OriginalSettings; /// /// Meldet oder legt fest, ob Berichte über das Schreiben der Systemuhr @@ -231,11 +213,7 @@ public Action OnWritingPCR /// Optional die Angabe eines Dateinames. /// Gesetzt, wenn die Quelle bekannt ist und der Empfang aktiviert wurde. /// Es ist bereits eine Aufzeichnung aktiv. - public bool CreateStream( string filePath ) - { - // Forward - return CreateStream( filePath, null ); - } + public bool CreateStream(string filePath) => CreateStream(filePath, null); /// /// Beginnt die Aufzeichnung in einen Transport Stream - optional als @@ -245,7 +223,7 @@ public bool CreateStream( string filePath ) /// Die aktuelle Konfiguration der Quelle oder null, wenn keine bekannt ist. /// Gesetzt, wenn die Quelle bekannt ist und der Empfang aktiviert wurde. /// Es ist bereits eine Aufzeichnung aktiv. - public bool CreateStream( string filePath, SourceInformation info ) + public bool CreateStream(string filePath, SourceInformation info) { // Validate if (m_TransportStream != null) @@ -265,13 +243,13 @@ public bool CreateStream( string filePath, SourceInformation info ) return false; // Forward - CreateStream( NextStreamIdentifier, false ); + CreateStream(NextStreamIdentifier, false); // Update signature - m_CurrentSignature = CreateRecordingSignature( m_OriginalSettings ); + m_CurrentSignature = CreateRecordingSignature(m_OriginalSettings); // Activate streaming - if (!string.IsNullOrEmpty( m_LastStreamTarget )) + if (!string.IsNullOrEmpty(m_LastStreamTarget)) StreamingTarget = m_LastStreamTarget; // Did it @@ -311,32 +289,32 @@ public string StreamingTarget return null; // Combine - return string.Format( "{0}:{1}", m_TransportStream.TCPClient, m_TransportStream.TCPPort ); + return $"{m_TransportStream.TCPClient}:{m_TransportStream.TCPPort}"; } set { // Check mode - if (string.IsNullOrEmpty( value )) + if (string.IsNullOrEmpty(value)) { // Clear if (null != m_TransportStream) - m_TransportStream.SetStreamTarget( string.Empty, 0 ); + m_TransportStream.SetStreamTarget(string.Empty, 0); } else { // Split - var parts = value.Split( ':' ); + var parts = value.Split(':'); if (2 != parts.Length) - throw new ArgumentException( value, "value" ); + throw new ArgumentException(value, "value"); // Get port ushort port; - if (!ushort.TryParse( parts[1], out port )) - throw new ArgumentException( value, "value" ); + if (!ushort.TryParse(parts[1], out port)) + throw new ArgumentException(value, "value"); // Update if (null != m_TransportStream) - m_TransportStream.SetStreamTarget( parts[0], port ); + m_TransportStream.SetStreamTarget(parts[0], port); } // Remember @@ -397,7 +375,7 @@ public int ConsumerCount /// /// Die aktuellen Daten zur zugehörigen Quelle. /// Ein Schlüssel passend zur aktuellen Aufzeichnung. - private string CreateRecordingSignature( SourceInformation information ) + private string CreateRecordingSignature(SourceInformation information) { // All keys - will be sorted to make sure that lists are ordered var flags = new List(); @@ -417,8 +395,8 @@ private string CreateRecordingSignature( SourceInformation information ) var videoType = (information.VideoType == VideoTypes.H264) ? EPG.StreamTypes.H264 : EPG.StreamTypes.Video13818; // Register - flags.Add( Offset_VideoType + (int) videoType ); - flags.Add( Offset_VideoPID + (int) information.VideoStream ); + flags.Add(Offset_VideoType + (int)videoType); + flags.Add(Offset_VideoPID + (int)information.VideoStream); } // All MP2 audio @@ -427,15 +405,15 @@ private string CreateRecordingSignature( SourceInformation information ) if (StreamSelection.MP2Tracks.LanguageMode == LanguageModes.Primary) { // Add as is - flags.Add( Offset_MP2PID + (int) audio.AudioStream ); + flags.Add(Offset_MP2PID + (int)audio.AudioStream); // Finish break; } - else if (StreamSelection.MP2Tracks.Contains( audio.Language )) + else if (StreamSelection.MP2Tracks.Contains(audio.Language)) { // Add as is - flags.Add( Offset_MP2PID + (int) audio.AudioStream ); + flags.Add(Offset_MP2PID + (int)audio.AudioStream); } // All AC3 audio @@ -444,21 +422,21 @@ private string CreateRecordingSignature( SourceInformation information ) if (StreamSelection.AC3Tracks.LanguageMode == LanguageModes.Primary) { // Add as is - flags.Add( Offset_AC3PID + (int) audio.AudioStream ); + flags.Add(Offset_AC3PID + (int)audio.AudioStream); // Finish break; } - else if (StreamSelection.AC3Tracks.Contains( audio.Language )) + else if (StreamSelection.AC3Tracks.Contains(audio.Language)) { // Add as is - flags.Add( Offset_AC3PID + (int) audio.AudioStream ); + flags.Add(Offset_AC3PID + (int)audio.AudioStream); } // Videotext if (StreamSelection.Videotext) if (0 != information.TextStream) - flags.Add( Offset_TTXPID + (int) information.TextStream ); + flags.Add(Offset_TTXPID + (int)information.TextStream); // Subtitle streams var subtitles = new Dictionary(); @@ -473,7 +451,7 @@ private string CreateRecordingSignature( SourceInformation information ) // Finish break; } - else if (StreamSelection.SubTitles.Contains( subtitle.Language )) + else if (StreamSelection.SubTitles.Contains(subtitle.Language)) { // Add as is subtitles[subtitle.SubtitleStream] = true; @@ -481,33 +459,22 @@ private string CreateRecordingSignature( SourceInformation information ) // Process all subtitles foreach (var subtitleStream in subtitles.Keys) - flags.Add( Offset_SUBPID + (int) subtitleStream ); + flags.Add(Offset_SUBPID + (int)subtitleStream); // Create the key - return (information.IsEncrypted ? "+" : "-") + string.Join( ".", flags.ConvertAll( f => f.ToString( "x5" ) ).ToArray() ); + return (information.IsEncrypted ? "+" : "-") + string.Join(".", flags.ConvertAll(f => f.ToString("x5")).ToArray()); } /// /// Meldet, ob der Datenempfang aktiviert wurde. /// - public bool IsActive - { - get - { - // Check stream - return (null != m_TransportStream); - } - } + public bool IsActive => (m_TransportStream != null); /// /// Prüft, ob sich an der Konfiguration der Quelle etwas verändert hat. /// /// Gesetzt, wenn nun der Empfang aktiv ist. - public bool RetestSourceInformation() - { - // Forward - return RetestSourceInformation( GetCurrentInformation() ); - } + public bool RetestSourceInformation() => RetestSourceInformation(GetCurrentInformation()); /// /// Prüft, ob sich an der Konfiguration der Quelle etwas verändert hat. @@ -516,7 +483,7 @@ public bool RetestSourceInformation() /// Gesetzt, wenn nun der Empfang aktiv ist. /// Der angegebenen Konfiguration ist keine Quelle zugeordnet. /// Die Konfiguration gehört zu einer anderen Quelle als der aktuellen. - public bool RetestSourceInformation( SourceInformation information ) + public bool RetestSourceInformation(SourceInformation information) { // Must get the current source information if (information == null) @@ -530,16 +497,30 @@ public bool RetestSourceInformation( SourceInformation information ) // Validate if (information.Source == null) - throw new ArgumentNullException( "information.Source" ); - if (!information.Source.Equals( Source )) - throw new ArgumentException( information.Source.ToString(), "information.Source" ); + throw new ArgumentNullException("information.Source"); + if (!information.Source.Equals(Source)) + throw new ArgumentException(information.Source.ToString(), "information.Source"); // Nothing changed - var signature = CreateRecordingSignature( information ); + var signature = CreateRecordingSignature(information); if (m_TransportStream != null) - if (signature.Equals( m_CurrentSignature )) + { + // No need to switch + if (signature.Equals(m_CurrentSignature)) return true; + // Report to see what happened + if (!string.IsNullOrEmpty(m_CurrentSignature)) + try + { + // Report and ignore + EventLog.WriteEntry("DVB.NET", $"Detected PSI Change: {m_CurrentSignature} => {signature}", EventLogEntryType.Information); + } + catch + { + } + } + // Get the streaming data var streamTarget = StreamingTarget; @@ -554,7 +535,7 @@ public bool RetestSourceInformation( SourceInformation information ) if (BeforeRecreateStream != null) { // Request new stream configuration - var newSelection = BeforeRecreateStream( this ); + var newSelection = BeforeRecreateStream(this); if (newSelection == null) return false; @@ -563,7 +544,7 @@ public bool RetestSourceInformation( SourceInformation information ) } // Forward - CreateStream( NextStreamIdentifier, true ); + CreateStream(NextStreamIdentifier, true); // Reactivate streaming if (streamTarget != null) @@ -580,7 +561,7 @@ public bool RetestSourceInformation( SourceInformation information ) /// Die erste Datenstromkennung (PID), die in der Aufzeichnungsdatei verwendet werden darf. /// Gesetzt, wenn ein Neustart aufgrund veränderter Nutzdatenströme erforderlich wurde. /// Eine Aufzeichnung der angegebenen Quelle ist nicht möglich. - private void CreateStream( short nextPID, bool recreate ) + private void CreateStream(short nextPID, bool recreate) { // Try to get the full name var filePath = m_OriginalPath; @@ -588,12 +569,12 @@ private void CreateStream( short nextPID, bool recreate ) if (m_FileCount > 0) { // Split off the parts - var name = Path.GetFileNameWithoutExtension( filePath ); - var dir = Path.GetDirectoryName( filePath ); - var ext = Path.GetExtension( filePath ); + var name = Path.GetFileNameWithoutExtension(filePath); + var dir = Path.GetDirectoryName(filePath); + var ext = Path.GetExtension(filePath); // Construct new name - filePath = Path.Combine( dir, string.Format( "{0} - {1}{2}", name, m_FileCount, ext ) ); + filePath = Path.Combine(dir, $"{name} - {m_FileCount}{ext}"); } // Try to decrypt @@ -601,7 +582,7 @@ private void CreateStream( short nextPID, bool recreate ) try { // Process - Hardware.Decrypt( Source ); + Hardware.Decrypt(Source); } catch { @@ -619,10 +600,10 @@ private void CreateStream( short nextPID, bool recreate ) videoType = (m_OriginalSettings.VideoType == VideoTypes.H264) ? EPG.StreamTypes.H264 : EPG.StreamTypes.Video13818; // Get the buffer size - var bufferSize = (FileBufferSizeChooser == null) ? null : FileBufferSizeChooser( videoType ); + var bufferSize = (FileBufferSizeChooser == null) ? null : FileBufferSizeChooser(videoType); // Create the new stream - m_TransportStream = new Manager( filePath, nextPID, bufferSize.GetValueOrDefault( Manager.DefaultBufferSize ) ); + m_TransportStream = new Manager(filePath, nextPID, bufferSize.GetValueOrDefault(Manager.DefaultBufferSize)); // Attach PCR sink m_TransportStream.OnWritingPCR = m_WritePCRSink; @@ -635,18 +616,18 @@ private void CreateStream( short nextPID, bool recreate ) { // Video first if (videoType.HasValue) - AddConsumer( m_OriginalSettings.VideoStream, StreamTypes.Video, m_TransportStream.AddVideo( (byte) videoType.Value ) ); + AddConsumer(m_OriginalSettings.VideoStream, StreamTypes.Video, m_TransportStream.AddVideo((byte)videoType.Value)); // Select audio - ProcessAudioSelection( AudioTypes.MP2, result.MP2Tracks, StreamSelection.MP2Tracks ); - ProcessAudioSelection( AudioTypes.AC3, result.AC3Tracks, StreamSelection.AC3Tracks ); + ProcessAudioSelection(AudioTypes.MP2, result.MP2Tracks, StreamSelection.MP2Tracks); + ProcessAudioSelection(AudioTypes.AC3, result.AC3Tracks, StreamSelection.AC3Tracks); // Videotext if (StreamSelection.Videotext) if (0 != m_OriginalSettings.TextStream) { // Register - AddConsumer( m_OriginalSettings.TextStream, StreamTypes.VideoText, m_TransportStream.AddTeleText() ); + AddConsumer(m_OriginalSettings.TextStream, StreamTypes.VideoText, m_TransportStream.AddTeleText()); // Remember result.Videotext = true; @@ -666,26 +647,26 @@ private void CreateStream( short nextPID, bool recreate ) if (StreamSelection.SubTitles.LanguageMode == LanguageModes.Primary) { // Attach to the list - AddSubtitleInformation( subtitle, subtitles ); + AddSubtitleInformation(subtitle, subtitles); // Copy over result.SubTitles.LanguageMode = LanguageModes.Primary; // Remember - result.SubTitles.Languages.Add( subtitle.Language ); + result.SubTitles.Languages.Add(subtitle.Language); // Done break; } // Standard selection - if (StreamSelection.SubTitles.Contains( subtitle.Language )) + if (StreamSelection.SubTitles.Contains(subtitle.Language)) { // Attach to the list - AddSubtitleInformation( subtitle, subtitles ); + AddSubtitleInformation(subtitle, subtitles); // Remember - result.SubTitles.Languages.Add( subtitle.Language ); + result.SubTitles.Languages.Add(subtitle.Language); } else { @@ -701,7 +682,7 @@ private void CreateStream( short nextPID, bool recreate ) // Process all subtitles foreach (var current in subtitles) - AddConsumer( current.Key, StreamTypes.SubTitle, m_TransportStream.AddSubtitles( current.Value.ToArray() ) ); + AddConsumer(current.Key, StreamTypes.SubTitle, m_TransportStream.AddSubtitles(current.Value.ToArray())); // See if program guide is requested bool epg = StreamSelection.ProgramGuide; @@ -711,17 +692,17 @@ private void CreateStream( short nextPID, bool recreate ) if ((Hardware.Profile != null) && Hardware.Profile.DisableProgramGuide) epg = false; else if (Profile != null) - if (Profile.GetFilter( Source ).DisableProgramGuide) + if (Profile.GetFilter(Source).DisableProgramGuide) epg = false; // EPG if (epg) { // Activate dispatch - m_TransportStream.SetEPGMapping( Source.Network, Source.TransportStream, Source.Service ); + m_TransportStream.SetEPGMapping(Source.Network, Source.TransportStream, Source.Service); // Start it - Hardware.AddProgramGuideConsumer( DispatchEPG ); + Hardware.AddProgramGuideConsumer(DispatchEPG); // Remember result.ProgramGuide = true; @@ -736,7 +717,7 @@ private void CreateStream( short nextPID, bool recreate ) try { // Forward - Hardware.SetConsumerState( consumer, true ); + Hardware.SetConsumerState(consumer, true); // Count it ++started; @@ -744,20 +725,20 @@ private void CreateStream( short nextPID, bool recreate ) catch (OutOfConsumersException) { // Translate - throw new OutOfConsumersException( m_Consumers.Count, started ) { RequestedSelection = result }; + throw new OutOfConsumersException(m_Consumers.Count, started) { RequestedSelection = result }; } } catch { // Detach EPG - Hardware.RemoveProgramGuideConsumer( DispatchEPG ); + Hardware.RemoveProgramGuideConsumer(DispatchEPG); // Cleanup on all errors foreach (var consumer in m_Consumers) try { // Remove - Hardware.SetConsumerState( consumer, null ); + Hardware.SetConsumerState(consumer, null); } catch { @@ -770,7 +751,7 @@ private void CreateStream( short nextPID, bool recreate ) // Remember path if (filePath != null) - m_AllFiles.Add( new FileStreamInformation { FilePath = filePath, VideoType = m_OriginalSettings.VideoType } ); + m_AllFiles.Add(new FileStreamInformation { FilePath = filePath, VideoType = m_OriginalSettings.VideoType }); // Remember the time LastActivationTime = DateTime.UtcNow; @@ -796,7 +777,7 @@ private void CreateStream( short nextPID, bool recreate ) // Report if (createNotify != null) - createNotify( this ); + createNotify(this); } /// @@ -804,7 +785,7 @@ private void CreateStream( short nextPID, bool recreate ) /// /// Die neue Aufzeichnungsdatei. /// Gesetzt, wenn die Trennung erfolgreich angenommen wurde. - public bool SplitFile( string newPath ) + public bool SplitFile(string newPath) { // No stream active if (m_TransportStream == null) @@ -825,17 +806,17 @@ public bool SplitFile( string newPath ) try { // Do the split - m_TransportStream.SplitFile( newPath ); + m_TransportStream.SplitFile(newPath); // Create new entry - m_AllFiles.Add( new FileStreamInformation { FilePath = newPath, VideoType = last.VideoType } ); + m_AllFiles.Add(new FileStreamInformation { FilePath = newPath, VideoType = last.VideoType }); // Attach to clients var createNotify = OnCreatedStream; // Report if (createNotify != null) - createNotify( this ); + createNotify(this); // Did it return true; @@ -852,11 +833,11 @@ public bool SplitFile( string newPath ) /// /// Die Untertitelspur. /// Alle bisher aufgenommenen Spuren. - private void AddSubtitleInformation( SubtitleInformation subtitle, Dictionary> subtitles ) + private void AddSubtitleInformation(SubtitleInformation subtitle, Dictionary> subtitles) { // Attach to the list List list; - if (!subtitles.TryGetValue( subtitle.SubtitleStream, out list )) + if (!subtitles.TryGetValue(subtitle.SubtitleStream, out list)) { // Create new list = new List(); @@ -870,10 +851,10 @@ private void AddSubtitleInformation( SubtitleInformation subtitle, Dictionary @@ -882,15 +863,8 @@ private void AddSubtitleInformation( SubtitleInformation subtitle, DictionaryDie gewünschte Art der Tonspur. /// Die aktive Auswahl der Tonspuren. /// Die gewünschten Sprachen. - private void ProcessAudioSelection( AudioTypes type, LanguageSelection selected, LanguageSelection requested ) + private void ProcessAudioSelection(AudioTypes type, LanguageSelection selected, LanguageSelection requested) { - // Get method for adding streams - Func addConsumer; - if (type == AudioTypes.MP2) - addConsumer = m_TransportStream.AddAudio; - else - addConsumer = m_TransportStream.AddDolby; - // Preset mode selected.LanguageMode = LanguageModes.All; @@ -902,26 +876,40 @@ private void ProcessAudioSelection( AudioTypes type, LanguageSelection selected, if (requested.LanguageMode == LanguageModes.Primary) { // Register - AddConsumer( audio.AudioStream, StreamTypes.Audio, addConsumer( audio.Language.ToISOLanguage() ) ); + if (type == AudioTypes.MP2) + { + AddConsumer(audio.AudioStream, StreamTypes.Audio, m_TransportStream.AddAudio(audio.Language.ToISOLanguage(), audio.AAC)); + } + else + { + AddConsumer(audio.AudioStream, StreamTypes.Audio, m_TransportStream.AddDolby(audio.Language.ToISOLanguage())); + } // Copy over selected.LanguageMode = LanguageModes.Primary; // Remember - selected.Languages.Add( audio.Language ); + selected.Languages.Add(audio.Language); // Done return; } // Regular test - if (requested.Contains( audio.Language )) + if (requested.Contains(audio.Language)) { // Register - AddConsumer( audio.AudioStream, StreamTypes.Audio, addConsumer( audio.Language.ToISOLanguage() ) ); + if (type == AudioTypes.MP2) + { + AddConsumer(audio.AudioStream, StreamTypes.Audio, m_TransportStream.AddAudio(audio.Language.ToISOLanguage(), audio.AAC)); + } + else + { + AddConsumer(audio.AudioStream, StreamTypes.Audio, m_TransportStream.AddDolby(audio.Language.ToISOLanguage())); + } // Remember - selected.Languages.Add( audio.Language ); + selected.Languages.Add(audio.Language); } else { @@ -931,7 +919,7 @@ private void ProcessAudioSelection( AudioTypes type, LanguageSelection selected, } // Clear flag if no audio is used - if (LanguageModes.All == selected.LanguageMode) + if (selected.LanguageMode == LanguageModes.All) if (selected.Languages.Count < 1) selected.LanguageMode = LanguageModes.Selection; } @@ -939,27 +927,20 @@ private void ProcessAudioSelection( AudioTypes type, LanguageSelection selected, /// /// Meldet alle Dateien, die geöffnet wurden. /// - public FileStreamInformation[] AllFiles - { - get - { - // Report - return m_AllFiles.ToArray(); - } - } + public FileStreamInformation[] AllFiles => m_AllFiles.ToArray(); /// /// Übermittelt die Daten zur Programmzeitschrift. /// /// Eine Tabelle der Programmzeitschrift. - private void DispatchEPG( EIT table ) + private void DispatchEPG(EIT table) { // Be safe try { // Forward if (null != m_TransportStream) - m_TransportStream.AddEventTable( table.Table ); + m_TransportStream.AddEventTable(table.Table); } catch { @@ -973,11 +954,7 @@ private void DispatchEPG( EIT table ) /// Die gewünschte Datestromkennung (PID). /// Die Art der Nutzdaten im Datenstrom. /// Der Empfänger der Daten. - private void AddConsumer( ushort pid, StreamTypes type, StreamBase stream ) - { - // Register - m_Consumers.Add( Hardware.AddConsumer( pid, type, stream.AddPayload ) ); - } + private void AddConsumer(ushort pid, StreamTypes type, StreamBase stream) => m_Consumers.Add(Hardware.AddConsumer(pid, type, stream.AddPayload)); /// /// Beendet die Aufzeichnung in eine Datei. @@ -1004,14 +981,14 @@ public void CloseStream() ++m_FileCount; // Stop EPG receiver - Hardware.RemoveProgramGuideConsumer( DispatchEPG ); + Hardware.RemoveProgramGuideConsumer(DispatchEPG); // Stop all consumers foreach (var consumer in m_Consumers) try { // Try to stop the individual stream - Hardware.SetConsumerState( consumer, null ); + Hardware.SetConsumerState(consumer, null); } catch { diff --git a/DVB.NET/HardwareAbstraction/TableExtensions.cs b/DVB.NET/HardwareAbstraction/TableExtensions.cs index f2b3f67..f1c6afc 100644 --- a/DVB.NET/HardwareAbstraction/TableExtensions.cs +++ b/DVB.NET/HardwareAbstraction/TableExtensions.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using JMS.DVB.SI; - +using JMS.DVB.EPG.Descriptors; namespace JMS.DVB { @@ -21,16 +21,16 @@ public static class TableExtensions /// Die Methode, an die alle erkannten SI Tabellen der gewünschten Art gemeldet werden. /// Die eindeutige Kennung des neu angemeldeten Verbrauchers. /// Die Hardware Abstraktion und / oder der Verbraucher sind nicht gesetzt. - public static Guid AddConsumer( this Hardware provider, ushort stream, Action consumer ) where T : Table + public static Guid AddConsumer(this Hardware provider, ushort stream, Action consumer) where T : Table { // Validate if (null == provider) - throw new ArgumentNullException( "provider" ); + throw new ArgumentNullException("provider"); if (null == consumer) - throw new ArgumentNullException( "consumer" ); + throw new ArgumentNullException("consumer"); // Forward - return provider.AddConsumer( stream, TableParser.Create( consumer ), Table.GetIsExtendedTable() ? StreamTypes.ExtendedTable : StreamTypes.StandardTable ); + return provider.AddConsumer(stream, TableParser.Create(consumer), Table.GetIsExtendedTable() ? StreamTypes.ExtendedTable : StreamTypes.StandardTable); } /// @@ -42,19 +42,19 @@ public static Guid AddConsumer( this Hardware provider, ushort stream, Action /// Die Methode, an die alle erkannten SI Tabellen der gewünschten Art gemeldet werden. /// Die eindeutige Kennung des neu angemeldeten Verbrauchers. /// Die Hardware Abstraktion und / oder der Verbraucher sind nicht gesetzt. - public static Guid AddConsumer( this Hardware provider, Action consumer ) where T : WellKnownTable + public static Guid AddConsumer(this Hardware provider, Action consumer) where T : WellKnownTable { // Validate if (null == provider) - throw new ArgumentNullException( "provider" ); + throw new ArgumentNullException("provider"); if (null == consumer) - throw new ArgumentNullException( "consumer" ); + throw new ArgumentNullException("consumer"); // Read the stream ushort stream = WellKnownTable.GetWellKnownStream(); // Forward - return provider.AddConsumer( stream, TableParser.Create( consumer ), Table.GetIsExtendedTable() ? StreamTypes.ExtendedTable : StreamTypes.StandardTable ); + return provider.AddConsumer(stream, TableParser.Create(consumer), Table.GetIsExtendedTable() ? StreamTypes.ExtendedTable : StreamTypes.StandardTable); } /// @@ -66,10 +66,10 @@ public static Guid AddConsumer( this Hardware provider, Action consumer ) /// Die eindeutige Kennung des neu angemeldeten Verbrauchers. /// Die Hardware Abstraktion und / oder die Analyseinstanz /// sind nicht gesetzt. - public static Guid AddConsumer( this Hardware provider, ushort stream, TableParser parser ) + public static Guid AddConsumer(this Hardware provider, ushort stream, TableParser parser) { // Forward - return provider.AddConsumer( stream, parser, StreamTypes.StandardTable ); + return provider.AddConsumer(stream, parser, StreamTypes.StandardTable); } /// @@ -82,16 +82,16 @@ public static Guid AddConsumer( this Hardware provider, ushort stream, TablePars /// Die eindeutige Kennung der neu angemeldeten Analyseeinheit. /// Die Hardware Abstraktion und / oder die Analyseinstanz /// sind nicht gesetzt. - public static Guid AddConsumer( this Hardware provider, ushort stream, TableParser parser, StreamTypes streamType ) + public static Guid AddConsumer(this Hardware provider, ushort stream, TableParser parser, StreamTypes streamType) { // Validate if (null == provider) - throw new ArgumentNullException( "provider" ); + throw new ArgumentNullException("provider"); if (null == parser) - throw new ArgumentNullException( "parser" ); + throw new ArgumentNullException("parser"); // Register - return provider.AddConsumer( stream, streamType, parser.AddPayload ); + return provider.AddConsumer(stream, streamType, parser.AddPayload); } /// @@ -101,10 +101,10 @@ public static Guid AddConsumer( this Hardware provider, ushort stream, TablePars /// Die maximale Wartezeit auf die Informationen in Millisekunden. /// Die gewünschten Informationen oder null, wenn diese in der angegebenen /// Zeit nicht bereit gestellt werden konnten. - public static SatelliteLocationInformation GetLocationInformation( this SatelliteHardware provider, int milliSeconds ) + public static SatelliteLocationInformation GetLocationInformation(this SatelliteHardware provider, int milliSeconds) { // Forward - return (SatelliteLocationInformation) ((Hardware) provider).GetLocationInformation( milliSeconds ); + return (SatelliteLocationInformation)((Hardware)provider).GetLocationInformation(milliSeconds); } /// @@ -114,10 +114,10 @@ public static SatelliteLocationInformation GetLocationInformation( this Satellit /// Die maximale Wartezeit auf die Informationen in Millisekunden. /// Die gewünschten Informationen oder null, wenn diese in der angegebenen /// Zeit nicht bereit gestellt werden konnten. - public static CableLocationInformation GetLocationInformation( this CableHardware provider, int milliSeconds ) + public static CableLocationInformation GetLocationInformation(this CableHardware provider, int milliSeconds) { // Forward - return (CableLocationInformation) ((Hardware) provider).GetLocationInformation( milliSeconds ); + return (CableLocationInformation)((Hardware)provider).GetLocationInformation(milliSeconds); } /// @@ -127,10 +127,10 @@ public static CableLocationInformation GetLocationInformation( this CableHardwar /// Die maximale Wartezeit auf die Informationen in Millisekunden. /// Die gewünschten Informationen oder null, wenn diese in der angegebenen /// Zeit nicht bereit gestellt werden konnten. - public static TerrestrialLocationInformation GetLocationInformation( this TerrestrialHardware provider, int milliSeconds ) + public static TerrestrialLocationInformation GetLocationInformation(this TerrestrialHardware provider, int milliSeconds) { // Forward - return (TerrestrialLocationInformation) ((Hardware) provider).GetLocationInformation( milliSeconds ); + return (TerrestrialLocationInformation)((Hardware)provider).GetLocationInformation(milliSeconds); } /// @@ -140,11 +140,11 @@ public static TerrestrialLocationInformation GetLocationInformation( this Terres /// Die Rohinformationen als SI NIT Tabellen. /// Das zugehörige DVB.NET Gerät, das noch auf den Ursprung eingestellt ist. /// Die gewünschten Informationen. - public static LocationInformation ToLocationInformation( this NIT[] tables, Hardware provider ) + public static LocationInformation ToLocationInformation(this NIT[] tables, Hardware provider) { // Validate if (null == provider) - throw new ArgumentNullException( "provider" ); + throw new ArgumentNullException("provider"); // None if (null == tables) @@ -153,20 +153,20 @@ public static LocationInformation ToLocationInformation( this NIT[] tables, Hard // Check DVB-S(2) Hardware sat = provider as Hardware; if (null != sat) - return tables.ToLocationInformation( sat ); + return tables.ToLocationInformation(sat); // Check DVB-C Hardware cab = provider as Hardware; if (null != cab) - return tables.ToLocationInformation( cab ); + return tables.ToLocationInformation(cab); // Check DVB-T Hardware ter = provider as Hardware; if (null != ter) - return tables.ToLocationInformation( ter ); + return tables.ToLocationInformation(ter); // Not supported - throw new ArgumentException( provider.GetType().FullName, "provider" ); + throw new ArgumentException(provider.GetType().FullName, "provider"); } /// @@ -176,13 +176,13 @@ public static LocationInformation ToLocationInformation( this NIT[] tables, Hard /// Die Rohinformationen als SI NIT Tabellen. /// Das zugehörige DVB.NET Gerät, das noch auf den Ursprung eingestellt ist. /// Die gewünschten Informationen. - public static SatelliteLocationInformation ToLocationInformation( this NIT[] tables, Hardware provider ) + public static SatelliteLocationInformation ToLocationInformation(this NIT[] tables, Hardware provider) { // Forward if (null == provider) - return CreateLocationInformation( new SatelliteLocation(), tables ); + return CreateLocationInformation(new SatelliteLocation(), tables); else - return CreateLocationInformation( SatelliteLocation.Parse( provider.CurrentLocation.ToString() ), tables ); + return CreateLocationInformation(SatelliteLocation.Parse(provider.CurrentLocation.ToString()), tables); } /// @@ -194,7 +194,7 @@ public static SatelliteLocationInformation ToLocationInformation( this NIT[] tab /// Der Usprung, zu dem die Tabellen ermittelt wurden. /// Die SI NIT Tabellengruppe zum noch angewählten Ursprung. /// Eine Informationsisntanz passend zur SI NIT Tabellengruppe oder null. - private static L CreateLocationInformation( GroupLocation location, NIT[] tables ) + private static L CreateLocationInformation(GroupLocation location, NIT[] tables) where G : SourceGroup, new() where L : LocationInformation, new() { @@ -219,7 +219,7 @@ private static L CreateLocationInformation( GroupLocation location, NIT // Add if possible if (null != group) - info.SourceGroups.Add( group ); + info.SourceGroups.Add(group); // Process next group break; @@ -234,7 +234,7 @@ private static L CreateLocationInformation( GroupLocation location, NIT // Add if possible if (null != group) - info.SourceGroups.Add( group ); + info.SourceGroups.Add(group); // Process next group break; @@ -249,7 +249,7 @@ private static L CreateLocationInformation( GroupLocation location, NIT // Add if possible if (null != group) - info.SourceGroups.Add( group ); + info.SourceGroups.Add(group); // Process next group break; @@ -266,16 +266,16 @@ private static L CreateLocationInformation( GroupLocation location, NIT /// /// Die Daten zur Quellgruppe. /// Die Quellgruppe. - private static CableGroup ToGroup( this EPG.Descriptors.CableDelivery descriptor ) + private static CableGroup ToGroup(this EPG.Descriptors.CableDelivery descriptor) { // Create core CableGroup group = new CableGroup - { - Frequency = descriptor.Frequency, - SpectrumInversion = SpectrumInversions.Auto, - SymbolRate = descriptor.SymbolRate * 1000, - Bandwidth = Bandwidths.NotDefined - }; + { + Frequency = descriptor.Frequency, + SpectrumInversion = SpectrumInversions.Auto, + SymbolRate = descriptor.SymbolRate * 1000, + Bandwidth = Bandwidths.NotDefined + }; // Modulation switch (descriptor.Modulation) @@ -297,14 +297,14 @@ private static CableGroup ToGroup( this EPG.Descriptors.CableDelivery descriptor /// /// Die Daten zur Quellgruppe. /// Die Quellgruppe. - private static TerrestrialGroup ToGroup( this EPG.Descriptors.TerrestrialDelivery descriptor ) + private static TerrestrialGroup ToGroup(this EPG.Descriptors.TerrestrialDelivery descriptor) { // Create core TerrestrialGroup group = new TerrestrialGroup - { - Frequency = descriptor.Frequency - }; + { + Frequency = descriptor.Frequency + }; // Bandwidth switch (descriptor.Bandwidth) @@ -329,16 +329,16 @@ private static TerrestrialGroup ToGroup( this EPG.Descriptors.TerrestrialDeliver /// /// Die Daten zur Quellgruppe. /// Die Quellgruppe. - private static SatelliteGroup ToGroup( this EPG.Descriptors.SatelliteDelivery descriptor ) + private static SatelliteGroup ToGroup(this EPG.Descriptors.SatelliteDelivery descriptor) { // Create core var group = new SatelliteGroup - { - Frequency = descriptor.Frequency, - IsWestPosition = descriptor.West, - OrbitalPosition = descriptor.OrbitalPosition.ToString( "0000" ), - SymbolRate = descriptor.SymbolRate * 1000 - }; + { + Frequency = descriptor.Frequency, + IsWestPosition = descriptor.West, + OrbitalPosition = descriptor.OrbitalPosition.ToString("0000"), + SymbolRate = descriptor.SymbolRate * 1000 + }; // DVB-S2 modulation group.UsesS2Modulation = (0 != (0x04 & descriptor.Modulation)); @@ -403,10 +403,10 @@ private static SatelliteGroup ToGroup( this EPG.Descriptors.SatelliteDelivery de /// Die Rohinformationen als SI NIT Tabellen. /// Das zugehörige DVB.NET Gerät, das noch auf den Ursprung eingestellt ist. /// Die gewünschten Informationen. - public static CableLocationInformation ToLocationInformation( this NIT[] tables, Hardware provider ) + public static CableLocationInformation ToLocationInformation(this NIT[] tables, Hardware provider) { // Forward - return CreateLocationInformation( new CableLocation(), tables ); + return CreateLocationInformation(new CableLocation(), tables); } /// @@ -416,10 +416,10 @@ public static CableLocationInformation ToLocationInformation( this NIT[] tables, /// Die Rohinformationen als SI NIT Tabellen. /// Das zugehörige DVB.NET Gerät, das noch auf den Ursprung eingestellt ist. /// Die gewünschten Informationen. - public static TerrestrialLocationInformation ToLocationInformation( this NIT[] tables, Hardware provider ) + public static TerrestrialLocationInformation ToLocationInformation(this NIT[] tables, Hardware provider) { // Forward - return CreateLocationInformation( new TerrestrialLocation(), tables ); + return CreateLocationInformation(new TerrestrialLocation(), tables); } /// @@ -430,7 +430,7 @@ public static TerrestrialLocationInformation ToLocationInformation( this NIT[] t /// Die SI Informationen mit der Zuordnung der Dienste /// zu den Program Mapping Table (PMT) Tabellen. /// Die gewünschte Informationsinstanz. - public static GroupInformation ToGroupInformation( this SDT[] services, PAT[] associations ) + public static GroupInformation ToGroupInformation(this SDT[] services, PAT[] associations) { // Create new var info = new GroupInformation(); @@ -458,7 +458,7 @@ public static GroupInformation ToGroupInformation( this SDT[] services, PAT[] as if (associations[0][entry.ServiceIdentifier].HasValue) { // Find the description - var descr = EPG.DescriptorExtensions.Find( entry.Descriptors ); + var descr = EPG.DescriptorExtensions.Find(entry.Descriptors); if (descr == null) continue; @@ -470,6 +470,8 @@ public static GroupInformation ToGroupInformation( this SDT[] services, PAT[] as type = SourceTypes.TV; else if (descr.ServiceType == EPG.ServiceTypes.DigitalRadio) type = SourceTypes.Radio; + else if (descr.ServiceType == EPG.ServiceTypes.FMRadio) + type = SourceTypes.Radio; else if (descr.ServiceType == EPG.ServiceTypes.SDTVDigitalTelevision) type = SourceTypes.TV; else if (descr.ServiceType == EPG.ServiceTypes.HDTVDigitalTelevision) @@ -484,18 +486,18 @@ public static GroupInformation ToGroupInformation( this SDT[] services, PAT[] as // Add the station info.Sources.Add( new Station - { - TransportStream = service.TransportStream, - Service = entry.ServiceIdentifier, - Provider = descr.ProviderName, - IsEncrypted = entry.Scrambled, - Network = service.Network, - Name = descr.ServiceName, - SourceType = type, - } ); + { + TransportStream = service.TransportStream, + Service = entry.ServiceIdentifier, + Provider = descr.ProviderName, + IsEncrypted = entry.Scrambled, + Network = service.Network, + Name = descr.ServiceName, + SourceType = type, + }); // Mark as done - processed.Add( entry.ServiceIdentifier ); + processed.Add(entry.ServiceIdentifier); } // Get the first SDT as a reference @@ -503,18 +505,18 @@ public static GroupInformation ToGroupInformation( this SDT[] services, PAT[] as // No check all services foreach (var serviceIdentifier in associations[0].Services) - if (!processed.Contains( serviceIdentifier )) + if (!processed.Contains(serviceIdentifier)) info.Sources.Add( new Station { - Name = string.Format( "Service {0}", serviceIdentifier ), + Name = string.Format("Service {0}", serviceIdentifier), TransportStream = sdt.TransportStream, SourceType = SourceTypes.Unknown, Service = serviceIdentifier, Network = sdt.Network, Provider = "Service", IsService = true, - } ); + }); // Report return info; @@ -526,12 +528,12 @@ public static GroupInformation ToGroupInformation( this SDT[] services, PAT[] as /// Die Liste der Assoziationen. /// Die eindeutige Kennung des gewünschten Dienstes. /// Die Datenstromkennung der SI Tabelle PMT des gewünschten Dienstes. - public static ushort? FindService( this PAT[] associations, ushort serviceIdentifier ) + public static ushort? FindService(this PAT[] associations, ushort serviceIdentifier) { return (associations ?? Enumerable.Empty()) - .Select( association => association[serviceIdentifier] ) - .FirstOrDefault( pmt => pmt.HasValue ); + .Select(association => association[serviceIdentifier]) + .FirstOrDefault(pmt => pmt.HasValue); } /// @@ -540,7 +542,7 @@ public static GroupInformation ToGroupInformation( this SDT[] services, PAT[] as /// /// Die Daten zu einer Quelle, die vervollständigt werden sollen. /// Die SI Programmbeschreibung. - public static void Update( this SourceInformation source, EPG.ProgramEntry program ) + public static void Update(this SourceInformation source, EPG.ProgramEntry program) { // MPEG-2 Video if (EPG.StreamTypes.Video13818 == program.StreamType) @@ -568,10 +570,44 @@ public static void Update( this SourceInformation source, EPG.ProgramEntry progr if ((EPG.StreamTypes.Audio11172 == program.StreamType) || (EPG.StreamTypes.Audio13818 == program.StreamType)) { // Create new entry - AudioInformation audio = new AudioInformation { AudioType = AudioTypes.MP2, AudioStream = program.ElementaryPID, Language = program.ProgrammeName.Trim() }; + var audio = new AudioInformation { AudioType = AudioTypes.MP2, AudioStream = program.ElementaryPID, Language = program.ProgrammeName.Trim() }; // Remember it - source.AudioTracks.Add( audio ); + source.AudioTracks.Add(audio); + + // Done + return; + } + + // AAC Audio + if (EPG.StreamTypes.AAC == program.StreamType) + { + // The AAC information. + int? aac = null; + + // Find corresponding AAC descriptor. + var aacDescriptor = program.Descriptors.OfType().FirstOrDefault(); + + if (aacDescriptor != null) + { + // Optional type. + aac = aacDescriptor.Type ?? 255; + + // Profile and level. + aac = (aac << 8) + aacDescriptor.ProfileAndLevel; + } + + // Create new entry + var audio = new AudioInformation + { + AAC = aac.HasValue ? (ushort)aac : (ushort?)null, + Language = program.ProgrammeName.Trim(), + AudioType = AudioTypes.MP2, + AudioStream = program.ElementaryPID, + }; + + // Remember it + source.AudioTracks.Add(audio); // Done return; @@ -592,7 +628,7 @@ public static void Update( this SourceInformation source, EPG.ProgramEntry progr AudioInformation audio = new AudioInformation { AudioType = AudioTypes.AC3, AudioStream = program.ElementaryPID, Language = program.ProgrammeName.Trim() }; // Remember it - source.AudioTracks.Add( audio ); + source.AudioTracks.Add(audio); // Done return; @@ -618,16 +654,16 @@ public static void Update( this SourceInformation source, EPG.ProgramEntry progr { // Create the information var info = new SubtitleInformation - { - SubtitleStream = program.ElementaryPID, - Language = subTitle.Language, - SubtitleType = (SubtitleTypes) subTitle.Type, - CompositionPage = subTitle.CompositionPage, - AncillaryPage = subTitle.AncillaryPage - }; + { + SubtitleStream = program.ElementaryPID, + Language = subTitle.Language, + SubtitleType = (SubtitleTypes)subTitle.Type, + CompositionPage = subTitle.CompositionPage, + AncillaryPage = subTitle.AncillaryPage + }; // Remember - source.Subtitles.Add( info ); + source.Subtitles.Add(info); } // Done @@ -641,14 +677,14 @@ public static void Update( this SourceInformation source, EPG.ProgramEntry progr /// /// Die gewünschte Sprache. /// Die ISO Kurznotation. - public static string ToISOLanguage( this string language ) + public static string ToISOLanguage(this string language) { // Not possible if (null == language) return null; // Use helper - return EPG.LanguageItemExtensions.ToISOLanguage( language ); + return EPG.LanguageItemExtensions.ToISOLanguage(language); } /// @@ -656,14 +692,14 @@ public static string ToISOLanguage( this string language ) /// /// Eine ISO Kurznotation. /// Die zugehörige Sprache, wie sie in DVB.NET verwendet wird. - public static string FromISOLanguage( this string language ) + public static string FromISOLanguage(this string language) { // Not possible if (null == language) return null; // Use helper - return EPG.ProgramEntry.GetLanguageFromISOLanguage( language ); + return EPG.ProgramEntry.GetLanguageFromISOLanguage(language); } } } diff --git a/DVB.NET/Provider/DVBNETLegacy/DVBNETProviders.xml b/DVB.NET/Provider/DVBNETLegacy/DVBNETProviders.xml index 963cbfc..3d7f670 100644 --- a/DVB.NET/Provider/DVBNETLegacy/DVBNETProviders.xml +++ b/DVB.NET/Provider/DVBNETLegacy/DVBNETProviders.xml @@ -191,4 +191,21 @@ 50 + + + Ubuntu DVB-S2 + + JMS.DVB.Provider.Ubuntu.DeviceProvider, JMS.DVB.Provider.Ubuntu + 200 + + true + + + + + 29713 + + + + diff --git a/DVB.NET/Provider/DVBNETLegacy/JMS.DVB.Provider.Legacy.csproj b/DVB.NET/Provider/DVBNETLegacy/JMS.DVB.Provider.Legacy.csproj index edeadef..9088ca7 100644 --- a/DVB.NET/Provider/DVBNETLegacy/JMS.DVB.Provider.Legacy.csproj +++ b/DVB.NET/Provider/DVBNETLegacy/JMS.DVB.Provider.Legacy.csproj @@ -64,6 +64,10 @@ ..\..\Assemblies\Adapter\JMS.DVB.Provider.TTPremium.dll False + + ..\..\Assemblies\Adapter\JMS.DVB.Provider.Ubuntu.dll + False + False diff --git a/DVB.NET/Provider/DVBNETLegacy/LegacyHardware.cs b/DVB.NET/Provider/DVBNETLegacy/LegacyHardware.cs index 070d659..050014b 100644 --- a/DVB.NET/Provider/DVBNETLegacy/LegacyHardware.cs +++ b/DVB.NET/Provider/DVBNETLegacy/LegacyHardware.cs @@ -5,7 +5,6 @@ using JMS.DVB.Editors; using JMS.TechnoTrend; - namespace JMS.DVB.Provider.Legacy { /// @@ -106,6 +105,10 @@ public static HardwareRestriction GetRestriction( Profile profile ) // But is able to provide signal information restr.ProvidesSignalInformation = true; } + else if (typeof(Ubuntu.DeviceProvider).IsAssignableFrom(driver)) + { + restr.ProvidesSignalInformation = true; + } else if (typeof( TTBudget.BudgetProvider ).IsAssignableFrom( driver )) { // Maximum number of streams is restricted diff --git a/DVB.NET/Provider/TechnoTrend/TTPremium/JMS.DVB.Provider.TTPremium.csproj b/DVB.NET/Provider/TechnoTrend/TTPremium/JMS.DVB.Provider.TTPremium.csproj index 1bd2abf..125bd70 100644 --- a/DVB.NET/Provider/TechnoTrend/TTPremium/JMS.DVB.Provider.TTPremium.csproj +++ b/DVB.NET/Provider/TechnoTrend/TTPremium/JMS.DVB.Provider.TTPremium.csproj @@ -102,7 +102,6 @@ ..\..\..\Assemblies\RunTime\JMS.DVB.SourceManagement.dll - False False diff --git a/DVB.NET/Provider/Ubuntu/DeviceProvider.cs b/DVB.NET/Provider/Ubuntu/DeviceProvider.cs new file mode 100644 index 0000000..3b6d14b --- /dev/null +++ b/DVB.NET/Provider/Ubuntu/DeviceProvider.cs @@ -0,0 +1,364 @@ +using JMS.DVB.DeviceAccess.Interfaces; +using JMS.DVB.TS; +using JMS.TechnoTrend; +using System; +using System.Collections; +using System.Diagnostics; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.Threading; + +namespace JMS.DVB.Provider.Ubuntu +{ + public class DeviceProvider : ILegacyDevice + { + private readonly string m_server; + + private readonly int m_port; + + private TcpClient m_connection; + + private readonly object m_lock = new object(); + + private TSParser m_parser = new TSParser(true); + + public DeviceProvider(Hashtable args) + { + m_server = (string)args["Adapter.Server"]; + m_port = ArgumentToNumber(args["Adapter.Port"], 29713); + } + + private static int ArgumentToNumber(object arg, int fallback = 0) + { + if (int.TryParse((string)arg, out int number)) + return number; + + return fallback; + } + + private void SendRequest(FrontendRequestType type, TData data) + { + Open(); + + var size = 4 + Marshal.SizeOf(data); + var buf = new byte[size]; + var bufptr = GCHandle.Alloc(buf, GCHandleType.Pinned); + + try + { + Marshal.WriteInt32(bufptr.AddrOfPinnedObject() + 0, (Int32)type); + Marshal.StructureToPtr(data, bufptr.AddrOfPinnedObject() + 4, true); + } + finally + { + bufptr.Free(); + } + + SafeWrite(buf); + } + + private void SafeWrite(byte[] buf) + { + try + { + m_connection.GetStream().Write(buf, 0, buf.Length); + } + catch (Exception e) + { + Debug.WriteLine("Failed to send request: {0}", e); + } + } + + private void SendRequest(FrontendRequestType type, UInt16 data) + { + Open(); + + var buf = new byte[6]; + var bufptr = GCHandle.Alloc(buf, GCHandleType.Pinned); + + try + { + Marshal.WriteInt32(bufptr.AddrOfPinnedObject() + 0, (Int32)type); + Marshal.WriteInt16(bufptr.AddrOfPinnedObject() + 4, (Int16)data); + } + finally + { + bufptr.Free(); + } + + SafeWrite(buf); + } + + private void SendRequest(FrontendRequestType type) + { + Open(); + + var buf = new byte[4]; + var bufptr = GCHandle.Alloc(buf, GCHandleType.Pinned); + + try + { + Marshal.WriteInt32(bufptr.AddrOfPinnedObject() + 0, (Int32)type); + } + finally + { + bufptr.Free(); + } + + SafeWrite(buf); + } + + + + private void StartReader(object state) + { + var buffer = new byte[180000]; + + try + { + var stream = m_connection.GetStream(); + + for (; ; ) + { + var read = stream.Read(buffer, 0, buffer.Length); + + if (read <= 0) + { + return; + } + + m_parser.AddPayload(buffer, 0, read); + } + } + catch (Exception) + { + return; + } + } + + private void Open() + { + if (m_connection != null) + return; + + m_connection = new TcpClient { ReceiveBufferSize = 10 * 1024 * 1024 }; + + try + { + m_connection.Connect(m_server, m_port); + + ThreadPool.QueueUserWorkItem(StartReader); + + SendRequest(FrontendRequestType.connect_adapter); + } + catch (Exception) + { + Close(); + + throw; + } + } + + private void Close() + { + using (m_parser) + { + m_parser = new TSParser(true); + } + + + if (m_connection == null) + return; + + using (m_connection) + { + try + { + m_connection.Close(); + } + finally + { + m_connection = null; + } + } + } + + public void StopFilters() + { + using (m_parser) + { + m_parser = new TSParser(true); + } + + if (m_connection != null) + SendRequest(FrontendRequestType.del_all_filters); + } + + private static DiSEqCModes ConvertDiSEqC(DiSEqCLocations location) + { + switch (location) + { + case DiSEqCLocations.BurstOff: + return DiSEqCModes.burst_off; + case DiSEqCLocations.BurstOn: + return DiSEqCModes.burst_on; + case DiSEqCLocations.DiSEqC1: + return DiSEqCModes.diseqc1; + case DiSEqCLocations.DiSEqC2: + return DiSEqCModes.diseqc2; + case DiSEqCLocations.DiSEqC3: + return DiSEqCModes.diseqc3; + case DiSEqCLocations.DiSEqC4: + return DiSEqCModes.diseqc4; + default: + return DiSEqCModes.none; + } + } + + private static FeModulation ConvertModulation(SatelliteModulations modulation) + { + switch (modulation) + { + case SatelliteModulations.Auto: + return FeModulation.QAM_AUTO; + case SatelliteModulations.PSK8: + return FeModulation.PSK_8; + case SatelliteModulations.QAM16: + return FeModulation.QAM_16; + default: + return FeModulation.QPSK; + } + } + + private static FeCodeRate ConvertCodeRate(InnerForwardErrorCorrectionModes modulation) + { + switch (modulation) + { + case InnerForwardErrorCorrectionModes.Conv1_2: + return FeCodeRate.FEC_1_2; + case InnerForwardErrorCorrectionModes.Conv2_3: + return FeCodeRate.FEC_2_3; + case InnerForwardErrorCorrectionModes.Conv3_4: + return FeCodeRate.FEC_3_4; + case InnerForwardErrorCorrectionModes.Conv3_5: + return FeCodeRate.FEC_3_5; + case InnerForwardErrorCorrectionModes.Conv4_5: + return FeCodeRate.FEC_4_5; + case InnerForwardErrorCorrectionModes.Conv5_6: + return FeCodeRate.FEC_5_6; + case InnerForwardErrorCorrectionModes.Conv7_8: + return FeCodeRate.FEC_7_8; + case InnerForwardErrorCorrectionModes.Conv8_9: + return FeCodeRate.FEC_8_9; + case InnerForwardErrorCorrectionModes.Conv9_10: + return FeCodeRate.FEC_9_10; + case InnerForwardErrorCorrectionModes.NoConv: + return FeCodeRate.FEC_NONE; + default: + return FeCodeRate.FEC_AUTO; + } + } + + private static FeRolloff ConvertRolloff(S2RollOffs modulation) + { + switch (modulation) + { + case S2RollOffs.Alpha20: + return FeRolloff.ROLLOFF_20; + case S2RollOffs.Alpha25: + return FeRolloff.ROLLOFF_25; + case S2RollOffs.Alpha35: + return FeRolloff.ROLLOFF_35; + default: + return FeRolloff.ROLLOFF_AUTO; + } + } + + public void Tune(SourceGroup group, GroupLocation location) + { + StopFilters(); + + var satGroup = group as SatelliteGroup; + + if (satGroup == null) + return; + + var satLocation = location as SatelliteLocation; + + if (satLocation == null) + return; + + var tune = new SatelliteTune + { + frequency = satGroup.Frequency, + horizontal = satGroup.Polarization == Polarizations.Horizontal, + innerFEC = ConvertCodeRate(satGroup.InnerFEC), + lnb1 = satLocation.Frequency1, + lnb2 = satLocation.Frequency2, + lnbMode = ConvertDiSEqC(satLocation.LNB), + lnbPower = satLocation.UsePower, + lnbSwitch = satLocation.SwitchFrequency, + modulation = ConvertModulation(satGroup.Modulation), + rolloff = ConvertRolloff(satGroup.RollOff), + s2 = satGroup.UsesS2Modulation, + symbolrate = satGroup.SymbolRate, + }; + + SendRequest(FrontendRequestType.tune, tune); + } + + public void SetVideoAudio(ushort videoPID, ushort audioPID) + { + Open(); + } + + public void StartSectionFilter(ushort pid, Action callback, byte[] filterData, byte[] filterMask) + { + m_parser.SetFilter(pid, true, callback); + + SendRequest(FrontendRequestType.add_filter, pid); + } + + public void RegisterPipingFilter(ushort pid, bool video, bool smallBuffer, Action callback) + { + m_parser.SetFilter(pid, false, callback); + + SendRequest(FrontendRequestType.add_filter, pid); + } + + public void StartFilter(ushort pid) + { + } + + public void StopFilter(ushort pid) + { + m_parser.RemoveFilter(pid); + + if (m_connection != null) + SendRequest(FrontendRequestType.del_filter, pid); + } + + public void Decrypt(ushort? station) + { + } + + public override string ToString() + { + return string.Format("Ubuntu DVB Proxy to {0}:{1}", m_server, m_port); + } + + public void WakeUp() + { + } + + public SignalStatus SignalStatus { get; private set; } = new SignalStatus(true, 0, 0); + + public virtual void Dispose() + { + StopFilters(); + + Close(); + } + } + +} diff --git a/DVB.NET/Provider/Ubuntu/DiSEqCModes.cs b/DVB.NET/Provider/Ubuntu/DiSEqCModes.cs new file mode 100644 index 0000000..9ad4b87 --- /dev/null +++ b/DVB.NET/Provider/Ubuntu/DiSEqCModes.cs @@ -0,0 +1,13 @@ +namespace JMS.DVB.Provider.Ubuntu +{ + public enum DiSEqCModes + { + none = 0, + burst_off = 5, + burst_on = 6, + diseqc1 = 1, + diseqc2 = 2, + diseqc3 = 3, + diseqc4 = 4, + } +} \ No newline at end of file diff --git a/DVB.NET/Provider/Ubuntu/FeCodeRate.cs b/DVB.NET/Provider/Ubuntu/FeCodeRate.cs new file mode 100644 index 0000000..34dc4b1 --- /dev/null +++ b/DVB.NET/Provider/Ubuntu/FeCodeRate.cs @@ -0,0 +1,19 @@ +namespace JMS.DVB.Provider.Ubuntu +{ + public enum FeCodeRate + { + FEC_NONE = 0, + FEC_1_2 = 1, + FEC_2_3 = 2, + FEC_3_4 = 3, + FEC_4_5 = 4, + FEC_5_6 = 5, + FEC_6_7 = 6, + FEC_7_8 = 7, + FEC_8_9 = 8, + FEC_AUTO = 9, + FEC_3_5 = 10, + FEC_9_10 = 11, + FEC_2_5 = 12, + } +} \ No newline at end of file diff --git a/DVB.NET/Provider/Ubuntu/FeModulation.cs b/DVB.NET/Provider/Ubuntu/FeModulation.cs new file mode 100644 index 0000000..16ae9be --- /dev/null +++ b/DVB.NET/Provider/Ubuntu/FeModulation.cs @@ -0,0 +1,20 @@ +namespace JMS.DVB.Provider.Ubuntu +{ + public enum FeModulation + { + QPSK = 0, + QAM_16 = 1, + QAM_32 = 2, + QAM_64 = 3, + QAM_128 = 4, + QAM_256 = 5, + QAM_AUTO = 6, + VSB_8 = 7, + VSB_16 = 8, + PSK_8 = 9, + APSK_16 = 10, + APSK_32 = 11, + DQPSK = 12, + QAM_4_NR = 13, + } +} \ No newline at end of file diff --git a/DVB.NET/Provider/Ubuntu/FeRolloff.cs b/DVB.NET/Provider/Ubuntu/FeRolloff.cs new file mode 100644 index 0000000..1f3355b --- /dev/null +++ b/DVB.NET/Provider/Ubuntu/FeRolloff.cs @@ -0,0 +1,10 @@ +namespace JMS.DVB.Provider.Ubuntu +{ + public enum FeRolloff + { + ROLLOFF_35 = 0, + ROLLOFF_20 = 1, + ROLLOFF_25 = 2, + ROLLOFF_AUTO = 3, + } +} \ No newline at end of file diff --git a/DVB.NET/Provider/Ubuntu/FeStatus.cs b/DVB.NET/Provider/Ubuntu/FeStatus.cs new file mode 100644 index 0000000..255c634 --- /dev/null +++ b/DVB.NET/Provider/Ubuntu/FeStatus.cs @@ -0,0 +1,17 @@ +using System; + +namespace JMS.DVB.Provider.Ubuntu +{ + [Flags] + public enum FeStatus + { + FE_NONE = 0x00, + FE_HAS_SIGNAL = 0x01, + FE_HAS_CARRIER = 0x02, + FE_HAS_VITERBI = 0x04, + FE_HAS_SYNC = 0x08, + FE_HAS_LOCK = 0x10, + FE_TIMEDOUT = 0x20, + FE_REINIT = 0x40, + } +} \ No newline at end of file diff --git a/DVB.NET/Provider/Ubuntu/FrontendRequestType.cs b/DVB.NET/Provider/Ubuntu/FrontendRequestType.cs new file mode 100644 index 0000000..1e0c6d0 --- /dev/null +++ b/DVB.NET/Provider/Ubuntu/FrontendRequestType.cs @@ -0,0 +1,11 @@ +namespace JMS.DVB.Provider.Ubuntu +{ + public enum FrontendRequestType + { + add_filter = 0, + connect_adapter = 1, + del_all_filters = 2, + del_filter = 3, + tune = 4, + } +} \ No newline at end of file diff --git a/DVB.NET/Provider/Ubuntu/JMS.DVB.Provider.Ubuntu.csproj b/DVB.NET/Provider/Ubuntu/JMS.DVB.Provider.Ubuntu.csproj new file mode 100644 index 0000000..a9228b3 --- /dev/null +++ b/DVB.NET/Provider/Ubuntu/JMS.DVB.Provider.Ubuntu.csproj @@ -0,0 +1,86 @@ + + + + + Debug + AnyCPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956} + Library + Properties + JMS.DVB.Provider.Ubuntu + JMS.DVB.Provider.Ubuntu + v4.5.1 + 512 + true + + + + true + full + false + ..\..\Assemblies\Adapter\ + DEBUG;TRACE + prompt + 4 + ..\..\Assemblies\Adapter\JMS.DVB.Provider.Ubuntu.xml + true + CS1591 + + + pdbonly + true + ..\..\Assemblies\Adapter\ + TRACE + prompt + 4 + ..\..\Assemblies\Adapter\JMS.DVB.Provider.Ubuntu.xml + true + CS1591 + + + true + + + ..\..\..\..\dvbnet4.snk + + + + ..\..\Assemblies\RunTime\JMS.DVB.SourceManagement.dll + False + + + ..\..\Assemblies\RunTime\JMS.DVB.TS.dll + False + + + ..\..\Assemblies\Adapter\JMS.TechnoTrend.MFCWrapper.dll + False + + + + + + + + + + + + + + + + + + + + + + + + ..\..\Assemblies\RunTime\JMS.DVB.DeviceAccess.dll + False + + + + \ No newline at end of file diff --git a/DVB.NET/Provider/Ubuntu/Properties/AssemblyInfo.cs b/DVB.NET/Provider/Ubuntu/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f52cd93 --- /dev/null +++ b/DVB.NET/Provider/Ubuntu/Properties/AssemblyInfo.cs @@ -0,0 +1,56 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("DVB.NET Provider for Ubuntu DVB Proxy")] +[assembly: AssemblyDescription("TCP/IP Connector to Ubuntu DVB.NET DVB-S Proxy Server")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("JMS")] +[assembly: AssemblyProduct("DVB.NET")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("4.3.0.0")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] \ No newline at end of file diff --git a/DVB.NET/Provider/Ubuntu/SatelliteTune.cs b/DVB.NET/Provider/Ubuntu/SatelliteTune.cs new file mode 100644 index 0000000..13140ca --- /dev/null +++ b/DVB.NET/Provider/Ubuntu/SatelliteTune.cs @@ -0,0 +1,22 @@ +using System; +using System.Runtime.InteropServices; + +namespace JMS.DVB.Provider.Ubuntu +{ + [StructLayout(LayoutKind.Sequential)] + public struct SatelliteTune + { + public DiSEqCModes lnbMode; + public UInt32 lnb1; + public UInt32 lnb2; + public UInt32 lnbSwitch; + public bool lnbPower; + public FeModulation modulation; + public UInt32 frequency; + public UInt32 symbolrate; + public bool horizontal; + public FeCodeRate innerFEC; + public bool s2; + public FeRolloff rolloff; + } +} \ No newline at end of file diff --git a/DVB.NET/Setups/Core/Core.sln b/DVB.NET/Setups/Core/Core.sln index bf47007..fb6de2f 100644 --- a/DVB.NET/Setups/Core/Core.sln +++ b/DVB.NET/Setups/Core/Core.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Common", "..\..\Common\JMS.DVB.Common.csproj", "{A224B2D5-7987-4C86-8FF7-CDD09ED76BA0}" EndProject @@ -29,11 +29,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.TS", "..\..\TS\JMS. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.HardwareAbstraction", "..\..\HardwareAbstraction\JMS.DVB.HardwareAbstraction.csproj", "{76D4B1A1-14FF-4265-8351-06DFD98F2DC3}" ProjectSection(ProjectDependencies) = postProject + {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {B2325F13-C217-4D96-846C-3FF857DA6128} = {B2325F13-C217-4D96-846C-3FF857DA6128} {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} = {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} {90D05FCC-70F9-4423-A79F-B8D31BFBC228} = {90D05FCC-70F9-4423-A79F-B8D31BFBC228} - {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {A224B2D5-7987-4C86-8FF7-CDD09ED76BA0} = {A224B2D5-7987-4C86-8FF7-CDD09ED76BA0} EndProjectSection EndProject @@ -41,29 +41,30 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.FavoriteManager", "..\. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.TechnoTrend.MFCWrapper", "..\..\Provider\TechnoTrend\TTAPI\JMS.TechnoTrend.MFCWrapper.csproj", "{CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F}" ProjectSection(ProjectDependencies) = postProject + {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {B2325F13-C217-4D96-846C-3FF857DA6128} = {B2325F13-C217-4D96-846C-3FF857DA6128} {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} {90D05FCC-70F9-4423-A79F-B8D31BFBC228} = {90D05FCC-70F9-4423-A79F-B8D31BFBC228} - {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Provider.Legacy", "..\..\Provider\DVBNETLegacy\JMS.DVB.Provider.Legacy.csproj", "{D528B63E-EE1A-4297-BE78-90D38F6CE0C2}" ProjectSection(ProjectDependencies) = postProject - {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} = {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} + {0FF2B905-EBFC-47D8-BEDA-6961C9438114} = {0FF2B905-EBFC-47D8-BEDA-6961C9438114} + {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} = {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} - {744054D8-2B4A-42D1-A84B-781561F575EB} = {744054D8-2B4A-42D1-A84B-781561F575EB} - {0FF2B905-EBFC-47D8-BEDA-6961C9438114} = {0FF2B905-EBFC-47D8-BEDA-6961C9438114} + {7FC369A1-D9B5-441A-873E-CB6AC92B9956} = {7FC369A1-D9B5-441A-873E-CB6AC92B9956} {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} = {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} - {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {A224B2D5-7987-4C86-8FF7-CDD09ED76BA0} = {A224B2D5-7987-4C86-8FF7-CDD09ED76BA0} + {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} = {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} + {744054D8-2B4A-42D1-A84B-781561F575EB} = {744054D8-2B4A-42D1-A84B-781561F575EB} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.DirectShow", "..\..\BDA\JMS.DVB.DirectShow.csproj", "{18E9D0C8-8AC6-4F86-AD43-DBDCFBFB2F26}" ProjectSection(ProjectDependencies) = postProject + {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {B2325F13-C217-4D96-846C-3FF857DA6128} = {B2325F13-C217-4D96-846C-3FF857DA6128} {90D05FCC-70F9-4423-A79F-B8D31BFBC228} = {90D05FCC-70F9-4423-A79F-B8D31BFBC228} - {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {A224B2D5-7987-4C86-8FF7-CDD09ED76BA0} = {A224B2D5-7987-4C86-8FF7-CDD09ED76BA0} EndProjectSection EndProject @@ -77,45 +78,45 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Algorithms", "..\.. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Provider.TTPremium", "..\..\Provider\TechnoTrend\TTPremium\JMS.DVB.Provider.TTPremium.csproj", "{744054D8-2B4A-42D1-A84B-781561F575EB}" ProjectSection(ProjectDependencies) = postProject - {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} = {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} - {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} + {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} + {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} = {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Provider.TTBudget", "..\..\Provider\TechnoTrend\TTBudget\JMS.DVB.Provider.TTBudget.csproj", "{0FF2B905-EBFC-47D8-BEDA-6961C9438114}" ProjectSection(ProjectDependencies) = postProject - {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} = {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} + {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} = {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} = {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} {90D05FCC-70F9-4423-A79F-B8D31BFBC228} = {90D05FCC-70F9-4423-A79F-B8D31BFBC228} - {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} + {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} = {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Provider.FireDTV", "..\..\Provider\FireDTV\JMS.DVB.Provider.FireDTV.csproj", "{D02922AD-4064-4B13-8B81-073079788FEA}" ProjectSection(ProjectDependencies) = postProject + {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} = {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} = {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} {90D05FCC-70F9-4423-A79F-B8D31BFBC228} = {90D05FCC-70F9-4423-A79F-B8D31BFBC228} - {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Provider.KNC", "..\..\Provider\KNC\JMS.DVB.Provider.KNC.csproj", "{7294F8A2-5ABF-40A5-BE22-4E6ACCEE9394}" ProjectSection(ProjectDependencies) = postProject + {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} = {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} = {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} {90D05FCC-70F9-4423-A79F-B8D31BFBC228} = {90D05FCC-70F9-4423-A79F-B8D31BFBC228} - {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Provider.NovaS2", "..\..\Provider\Hauppauge\NovaS2\JMS.DVB.Provider.NovaS2.csproj", "{08D0AD01-4137-49E2-8B28-3B466A142C8A}" ProjectSection(ProjectDependencies) = postProject + {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} = {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} = {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} - {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Administration.Framework", "..\..\Administration\PlugIns\AdminFramework\JMS.DVB.Administration.Framework.csproj", "{A5C02DC8-7FBD-4653-AD40-D540F2B05220}" @@ -127,20 +128,20 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Administration.Profiles", "..\..\Administration\PlugIns\Profile Manager\JMS.DVB.Administration.Profiles.csproj", "{E20D7FF6-2358-4B25-8D45-F523E0C6B816}" ProjectSection(ProjectDependencies) = postProject {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} - {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} = {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} {D528B63E-EE1A-4297-BE78-90D38F6CE0C2} = {D528B63E-EE1A-4297-BE78-90D38F6CE0C2} - {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} = {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} - {E1ED756B-6A4D-4CF3-9E8F-B191E2029C54} = {E1ED756B-6A4D-4CF3-9E8F-B191E2029C54} {9B137745-492B-46DF-A525-3CA83D64AA96} = {9B137745-492B-46DF-A525-3CA83D64AA96} + {E1ED756B-6A4D-4CF3-9E8F-B191E2029C54} = {E1ED756B-6A4D-4CF3-9E8F-B191E2029C54} + {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} = {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} + {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} = {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} {A5C02DC8-7FBD-4653-AD40-D540F2B05220} = {A5C02DC8-7FBD-4653-AD40-D540F2B05220} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Administration.TransponderScan", "..\..\Administration\PlugIns\Transponder Scanner\JMS.DVB.Administration.TransponderScan.csproj", "{9B137745-492B-46DF-A525-3CA83D64AA96}" ProjectSection(ProjectDependencies) = postProject {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} + {E1ED756B-6A4D-4CF3-9E8F-B191E2029C54} = {E1ED756B-6A4D-4CF3-9E8F-B191E2029C54} {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} = {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} = {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} - {E1ED756B-6A4D-4CF3-9E8F-B191E2029C54} = {E1ED756B-6A4D-4CF3-9E8F-B191E2029C54} {A5C02DC8-7FBD-4653-AD40-D540F2B05220} = {A5C02DC8-7FBD-4653-AD40-D540F2B05220} EndProjectSection EndProject @@ -149,8 +150,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DVBNETAdmin", "..\..\Admini {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} = {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} = {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} - {A224B2D5-7987-4C86-8FF7-CDD09ED76BA0} = {A224B2D5-7987-4C86-8FF7-CDD09ED76BA0} {A5C02DC8-7FBD-4653-AD40-D540F2B05220} = {A5C02DC8-7FBD-4653-AD40-D540F2B05220} + {A224B2D5-7987-4C86-8FF7-CDD09ED76BA0} = {A224B2D5-7987-4C86-8FF7-CDD09ED76BA0} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserProfileManager", "..\..\Tools\UserProfileManager\UserProfileManager.csproj", "{E6A0DED8-7C22-4FB0-BDC9-AD93E24EE76C}" @@ -168,11 +169,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.DeviceAccess", "..\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Provider.Duoflex", "..\..\Provider\Duoflex\JMS.DVB.Provider.Duoflex.csproj", "{7D7FD386-E5C4-4264-853E-3C484BEFCDA6}" ProjectSection(ProjectDependencies) = postProject + {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} = {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} = {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} {90D05FCC-70F9-4423-A79F-B8D31BFBC228} = {90D05FCC-70F9-4423-A79F-B8D31BFBC228} - {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RCLearner", "..\..\Tools\RC Learner\RCLearner.csproj", "{822E86FA-1BB4-4860-A97C-413DB4773A8B}" @@ -191,10 +192,18 @@ Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "CoreSetup", "CoreSetup.wixp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Provider.TeViiS2", "..\..\Provider\TeViiS2\JMS.DVB.Provider.TeViiS2.csproj", "{B26CE348-CB62-4DA1-949D-EDA4526F892D}" ProjectSection(ProjectDependencies) = postProject + {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} = {620B2A8D-ACCC-401A-A67B-70F3AAE47F55} {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} = {76D4B1A1-14FF-4265-8351-06DFD98F2DC3} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JMS.DVB.Provider.Ubuntu", "..\..\Provider\Ubuntu\JMS.DVB.Provider.Ubuntu.csproj", "{7FC369A1-D9B5-441A-873E-CB6AC92B9956}" + ProjectSection(ProjectDependencies) = postProject {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} = {046BA60E-E22F-48AA-AB52-5D8AA7F0A6C4} + {B2325F13-C217-4D96-846C-3FF857DA6128} = {B2325F13-C217-4D96-846C-3FF857DA6128} + {6662DE38-74C1-4432-9512-C7E94C2EFDFA} = {6662DE38-74C1-4432-9512-C7E94C2EFDFA} + {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} = {CC42C4D5-3158-4E1C-9FC8-8138DBE52D8F} EndProjectSection EndProject Global @@ -477,8 +486,23 @@ Global {B26CE348-CB62-4DA1-949D-EDA4526F892D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {B26CE348-CB62-4DA1-949D-EDA4526F892D}.Release|Mixed Platforms.Build.0 = Release|Any CPU {B26CE348-CB62-4DA1-949D-EDA4526F892D}.Release|x86.ActiveCfg = Release|Any CPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956}.Debug|x86.ActiveCfg = Debug|Any CPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956}.Debug|x86.Build.0 = Debug|Any CPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956}.Release|Any CPU.Build.0 = Release|Any CPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956}.Release|x86.ActiveCfg = Release|Any CPU + {7FC369A1-D9B5-441A-873E-CB6AC92B9956}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0F83CADA-641F-4A22-B3E8-35A2FCDF6952} + EndGlobalSection EndGlobal diff --git a/DVB.NET/Setups/Core/CoreSetup.wixproj b/DVB.NET/Setups/Core/CoreSetup.wixproj index 76553b8..dfeeb22 100644 --- a/DVB.NET/Setups/Core/CoreSetup.wixproj +++ b/DVB.NET/Setups/Core/CoreSetup.wixproj @@ -17,7 +17,7 @@ obj\$(Configuration)\ Debug True - SETUPVERSION=4.3.11 + SETUPVERSION=4.3.19 de-de ICE57 @@ -25,7 +25,7 @@ ..\..\..\msi\ obj\$(Configuration)\ True - SETUPVERSION=4.3.11 + SETUPVERSION=4.3.19 de-de ICE57 @@ -264,6 +264,16 @@ + + JMS.DVB.Provider.Ubuntu + {7fc369a1-d9b5-441a-873e-cb6ac92b9956} + True + + + Binaries;Sources;Content;Documents + + + JMS.DVB.SITables {620b2a8d-accc-401a-a67b-70f3aae47f55} @@ -319,7 +329,7 @@ set "$(WixVariables)" -"%25ProgramFiles%25\Windows Kits\8.0\bin\x86\msiinfo.exe" "$(TargetDir)\de-de\$(TargetFileName)" /T "DVB.NET Library %25SETUPVERSION%25" +"%25ProgramFiles%25\Windows Kits\10\bin\x86\msiinfo.exe" "$(TargetDir)\de-de\$(TargetFileName)" /T "DVB.NET Library %25SETUPVERSION%25" - + @@ -23,8 +29,8 @@ - - + + diff --git a/VCR.NET/Service/App.config.release b/VCR.NET/Service/App.config.release index 0cca64e..6619e97 100644 --- a/VCR.NET/Service/App.config.release +++ b/VCR.NET/Service/App.config.release @@ -8,6 +8,12 @@ + + + + + + diff --git a/VCR.NET/Service/Properties/AssemblyInfo.cs b/VCR.NET/Service/Properties/AssemblyInfo.cs index fbfcd93..20a6344 100644 --- a/VCR.NET/Service/Properties/AssemblyInfo.cs +++ b/VCR.NET/Service/Properties/AssemblyInfo.cs @@ -26,4 +26,6 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion( "4.3.0.0" )] +[assembly: AssemblyVersion( "4.5.0.0" )] +[assembly: AssemblyFileVersion("4.5.0.0")] + diff --git a/VCR.NET/Service/Service.csproj b/VCR.NET/Service/Service.csproj index 39d1490..383d975 100644 --- a/VCR.NET/Service/Service.csproj +++ b/VCR.NET/Service/Service.csproj @@ -85,7 +85,7 @@ - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\GAC\JMS.DVB.Common.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\GAC\JMS.DVB.Common.dll False diff --git a/VCR.NET/ServiceCore/JobManager.cs b/VCR.NET/ServiceCore/JobManager.cs index 666e072..865d165 100644 --- a/VCR.NET/ServiceCore/JobManager.cs +++ b/VCR.NET/ServiceCore/JobManager.cs @@ -1,8 +1,8 @@ +using JMS.DVBVCR.RecordingService.Persistence; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using JMS.DVBVCR.RecordingService.Persistence; namespace JMS.DVBVCR.RecordingService @@ -25,17 +25,17 @@ public partial class JobManager /// /// Ermittelt das Protokollverzeichnis vom VCR.NET. /// - public DirectoryInfo LogDirectory { get { return new DirectoryInfo( Path.Combine( RootDirectory.FullName, "Logs" ) ); } } + public DirectoryInfo LogDirectory => new DirectoryInfo( Path.Combine( RootDirectory.FullName, "Logs" ) ); /// /// Ermittelt das EPG und Sendersuchlaufverzeichnis vom VCR.NET. /// - public DirectoryInfo CollectorDirectory { get { return new DirectoryInfo( Path.Combine( RootDirectory.FullName, "EPG" ) ); } } + public DirectoryInfo CollectorDirectory => new DirectoryInfo( Path.Combine( RootDirectory.FullName, "EPG" ) ); /// /// Ermittelt das Verzeichnis aller aktiven Auftrge vom VCR.NET. /// - public DirectoryInfo JobDirectory { get { return new DirectoryInfo( Path.Combine( RootDirectory.FullName, "Active" ) ); } } + public DirectoryInfo JobDirectory => new DirectoryInfo( Path.Combine( RootDirectory.FullName, "Active" ) ); /// /// Meldet das Wurzelverzeichnis, unter dem Auftrge und Protokolle abgelegt werden. @@ -114,10 +114,10 @@ public void Delete( VCRJob job ) lock (m_Jobs) { // Load from the map - VCRJob internalJob = this[job.UniqueID.Value]; + var internalJob = this[job.UniqueID.Value]; // See if this is active - if (null != internalJob) + if (internalJob != null) { // Delete it internalJob.Delete( JobDirectory ); @@ -148,12 +148,9 @@ public VCRJob this[Guid jobIdentifier] { get { - // The result - VCRJob result; - // Cut off lock (m_Jobs) - if (m_Jobs.TryGetValue( jobIdentifier, out result )) + if (m_Jobs.TryGetValue( jobIdentifier, out VCRJob result)) return result; // Report @@ -211,13 +208,13 @@ public VCRJob FindJob( Guid jobIdentifier ) return result; // Create file name - FileInfo jobFile = new FileInfo( Path.Combine( ArchiveDirectory.FullName, jobIdentifier.ToString( "N" ).ToUpper() + VCRJob.FileSuffix ) ); + var jobFile = new FileInfo( Path.Combine( ArchiveDirectory.FullName, jobIdentifier.ToString( "N" ).ToUpper() + VCRJob.FileSuffix ) ); if (!jobFile.Exists) return null; // Load result = SerializationTools.Load( jobFile ); - if (null == result) + if (result == null) return null; } @@ -242,7 +239,7 @@ public VCRJob FindJob( Guid jobIdentifier ) public void SetRestartThreshold( VCRRecordingInfo recording ) { // Forward - if (null != recording) + if (recording != null) SetRestartThreshold( recording, recording.EndsAt ); } @@ -297,7 +294,7 @@ private void SetRestartThreshold( Guid jobIdentifier, Guid scheduleIdentifier, D /// /// Ermittelt das Archivverzeichnis vom VCR.NET. /// - public DirectoryInfo ArchiveDirectory { get { return new DirectoryInfo( Path.Combine( RootDirectory.FullName, "Archive" ) ); } } + public DirectoryInfo ArchiveDirectory => new DirectoryInfo( Path.Combine( RootDirectory.FullName, "Archive" ) ); /// /// Ermittelt alle archivierten Auftrge zu allen DVB.NET Gerteprofilen. diff --git a/VCR.NET/ServiceCore/Persistence/FileInformation.cs b/VCR.NET/ServiceCore/Persistence/FileInformation.cs index 884a0ef..fd362b5 100644 --- a/VCR.NET/ServiceCore/Persistence/FileInformation.cs +++ b/VCR.NET/ServiceCore/Persistence/FileInformation.cs @@ -1,7 +1,7 @@ +using JMS.DVB; using System; using System.IO; using System.Xml.Serialization; -using JMS.DVB; namespace JMS.DVBVCR.RecordingService.Persistence diff --git a/VCR.NET/ServiceCore/Persistence/VCRJob.cs b/VCR.NET/ServiceCore/Persistence/VCRJob.cs index c387f13..28fed55 100644 --- a/VCR.NET/ServiceCore/Persistence/VCRJob.cs +++ b/VCR.NET/ServiceCore/Persistence/VCRJob.cs @@ -1,9 +1,9 @@ +using JMS.DVB; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml.Serialization; -using JMS.DVB; namespace JMS.DVBVCR.RecordingService.Persistence @@ -145,14 +145,7 @@ public class VCRJob /// /// Der Pfad zu einem Zielverzeichnis. /// Die zugehrige Datei. - private FileInfo GetFileName( DirectoryInfo target ) - { - // Create - if (UniqueID.HasValue) - return new FileInfo( Path.Combine( target.FullName, UniqueID.Value.ToString( "N" ).ToUpper() + FileSuffix ) ); - else - return null; - } + private FileInfo GetFileName( DirectoryInfo target ) => UniqueID.HasValue ? new FileInfo( Path.Combine( target.FullName, UniqueID.Value.ToString( "N" ).ToUpper() + FileSuffix ) ) : null; /// /// Ermittelt alle Auftrge in einem Verzeichnis. @@ -174,7 +167,7 @@ public static IEnumerable Load( DirectoryInfo directory ) /// eine Aufzeichnung noch vorhanden ist. /// [XmlIgnore] - public bool IsActive { get { return Schedules.Any( schedule => schedule.IsActive ); } } + public bool IsActive => Schedules.Any( schedule => schedule.IsActive ); /// /// Prft, ob ein Auftrag zulssig ist. @@ -220,23 +213,19 @@ public void Validate( Guid? scheduleIdentifier ) /// Meldet, ob diesem Auftrag eine Quelle zugeordnet ist. /// [XmlIgnore] - public bool HasSource { get { return (Source != null) && (Source.Source != null); } } + public bool HasSource => (Source != null) && (Source.Source != null); /// /// Ermittelt eine Aufzeichnung dieses Auftrags. /// /// Die eindeutige Kennung der Aufzeichnung. /// Die Aufzeichnung oder null. - public VCRSchedule this[Guid uniqueIdentifier] { get { return Schedules.Find( s => s.UniqueID.HasValue && (s.UniqueID.Value == uniqueIdentifier) ); } } + public VCRSchedule this[Guid uniqueIdentifier] => Schedules.Find( s => s.UniqueID.HasValue && (s.UniqueID.Value == uniqueIdentifier) ); /// /// Entfernt alle Ausnahmeregelungen, die bereits verstrichen sind. /// - public void CleanupExceptions() - { - // Forward - Schedules.ForEach( schedule => schedule.CleanupExceptions() ); - } + public void CleanupExceptions() => Schedules.ForEach( schedule => schedule.CleanupExceptions() ); /// /// Stellt sicher, dass fr diesen Auftrag ein Gerteprprofil ausgewhlt ist. @@ -244,9 +233,8 @@ public void CleanupExceptions() internal void SetProfile() { // No need - if (Source != null) - if (!string.IsNullOrEmpty( Source.ProfileName )) - return; + if (!string.IsNullOrEmpty( Source?.ProfileName )) + return; // Attach to the default profile var defaultProfile = VCRProfiles.DefaultProfile; @@ -289,11 +277,7 @@ public static class ValidationExtension /// /// Die Auswahl der Quelle oder null. /// Gesetzt, wenn die Auswahl gltig ist. - public static bool Validate( this SourceSelection source ) - { - // Forward - return (VCRProfiles.FindSource( source ) != null); - } + public static bool Validate( this SourceSelection source ) => (VCRProfiles.FindSource( source ) != null); /// /// Prft, ob eine Datenstromauswahl zulssig ist. @@ -328,14 +312,7 @@ public static bool Validate( this StreamSelection streams ) /// /// Der zu prfenden Name. /// Gesetzt, wenn der Name verwendet werden darf. - public static bool IsValidName( this string name ) - { - // Always - if (string.IsNullOrEmpty( name )) - return true; - else - return (name.IndexOfAny( m_BadCharacters ) < 0); - } + public static bool IsValidName( this string name ) => string.IsNullOrEmpty( name ) || (name.IndexOfAny( m_BadCharacters ) < 0); /// /// Ersetzt alle Zeichen, die nicht in Dateinamen erlaubt sind, durch einen @@ -351,7 +328,7 @@ public static string MakeValid( this string s ) // Correct all if (s.IndexOfAny( m_BadCharacters ) >= 0) - foreach (char ch in m_BadCharacters) + foreach (var ch in m_BadCharacters) s = s.Replace( ch, '_' ); // Report diff --git a/VCR.NET/ServiceCore/Persistence/VCRRecordingInfo.cs b/VCR.NET/ServiceCore/Persistence/VCRRecordingInfo.cs index b1d863e..4a663a6 100644 --- a/VCR.NET/ServiceCore/Persistence/VCRRecordingInfo.cs +++ b/VCR.NET/ServiceCore/Persistence/VCRRecordingInfo.cs @@ -1,13 +1,13 @@ +using JMS.DVB; +using JMS.DVB.Algorithms.Scheduler; +using JMS.DVB.CardServer; +using JMS.DVBVCR.RecordingService.Planning; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Xml.Serialization; -using JMS.DVB; -using JMS.DVB.Algorithms.Scheduler; -using JMS.DVB.CardServer; -using JMS.DVBVCR.RecordingService.Planning; namespace JMS.DVBVCR.RecordingService.Persistence @@ -207,7 +207,7 @@ public DateTime EndsAt /// Meldet die zugehrige Quelle, so wie sie im aktuellen Gerteprofil bekannt ist. /// [XmlIgnore] - public SourceSelection CurrentSource { get { return VCRProfiles.FindSource( Source ); } } + public SourceSelection CurrentSource => VCRProfiles.FindSource( Source ); /// /// Erstellt eine exakte Kopie dieser Aufzeichnungsinformation. @@ -218,21 +218,21 @@ public VCRRecordingInfo Clone() // Create clone var clone = new VCRRecordingInfo - { - Source = (Source == null) ? null : new SourceSelection { DisplayName = Source.DisplayName, SelectionKey = Source.SelectionKey }, - Streams = (Streams == null) ? null : Streams.Clone(), - DisableHibernation = DisableHibernation, - ScheduleUniqueID = ScheduleUniqueID, - m_physicalStart = m_physicalStart, - JobUniqueID = JobUniqueID, - StartsLate = StartsLate, - TotalSize = TotalSize, - StartsAt = StartsAt, - FileName = FileName, - IsHidden = IsHidden, - m_endsAt = m_endsAt, - Name = Name, - }; + { + Source = (Source == null) ? null : new SourceSelection { DisplayName = Source.DisplayName, SelectionKey = Source.SelectionKey }, + Streams = (Streams == null) ? null : Streams.Clone(), + DisableHibernation = DisableHibernation, + ScheduleUniqueID = ScheduleUniqueID, + m_physicalStart = m_physicalStart, + JobUniqueID = JobUniqueID, + StartsLate = StartsLate, + TotalSize = TotalSize, + StartsAt = StartsAt, + FileName = FileName, + IsHidden = IsHidden, + m_endsAt = m_endsAt, + Name = Name, + }; // File data clone.RecordingFiles.AddRange( RecordingFiles.Select( info => new FileInformation { Path = info.Path, VideoType = info.VideoType, ScheduleIdentifier = info.ScheduleIdentifier } ) ); @@ -391,7 +391,7 @@ internal void LoadDefaults() else { // Set dummy name - pattern = string.Format( "Test {0:dd-MM-yyyy HH-mm-ss}", DateTime.Now ); + pattern = $"Test {DateTime.Now:dd-MM-yyyy HH-mm-ss}"; } // Default directory @@ -411,11 +411,7 @@ internal void LoadDefaults() /// /// Der ursprngliche Dateiname mit Platzhaltern. /// Der Dateiname mit den ausgetauschten Platzhaltern. - private string UpdatePlaceHolders( string withPatterns ) - { - // Replace all - return GetReplacementPatterns().Aggregate( withPatterns, ( current, rule ) => current.Replace( rule.Key, rule.Value.MakeValid() ) ); - } + private string UpdatePlaceHolders( string withPatterns ) => GetReplacementPatterns().Aggregate( withPatterns, ( current, rule ) => current.Replace( rule.Key, rule.Value.MakeValid() ) ); /// /// Prft, ob diese Aufzeichnung zu einem gerade aufgezeichneten Datenstrom gehrt. @@ -466,9 +462,9 @@ public static VCRRecordingInfo Create( IScheduleInformation planItem, PlanContex { // Validate if (planItem == null) - throw new ArgumentNullException( "planItem" ); + throw new ArgumentNullException( nameof( planItem ) ); if (context == null) - throw new ArgumentNullException( "jobMap" ); + throw new ArgumentNullException( nameof( context ) ); // Check type var definition = planItem.Definition as IScheduleDefinition; @@ -479,16 +475,16 @@ public static VCRRecordingInfo Create( IScheduleInformation planItem, PlanContex if (guideCollection != null) return new VCRRecordingInfo - { - Source = new SourceSelection { ProfileName = planItem.Resource.Name, DisplayName = VCRJob.ProgramGuideName }, - FileName = Path.Combine( guideCollection.CollectorDirectory.FullName, Guid.NewGuid().ToString( "N" ) + ".epg" ), - ScheduleUniqueID = guideCollection.UniqueIdentifier, - IsHidden = planItem.Resource == null, - StartsLate = planItem.StartsLate, - StartsAt = planItem.Time.Start, - Name = guideCollection.Name, - EndsAt = planItem.Time.End, - }; + { + Source = new SourceSelection { ProfileName = planItem.Resource.Name, DisplayName = VCRJob.ProgramGuideName }, + FileName = Path.Combine( guideCollection.CollectorDirectory.FullName, Guid.NewGuid().ToString( "N" ) + ".epg" ), + ScheduleUniqueID = guideCollection.UniqueIdentifier, + IsHidden = planItem.Resource == null, + StartsLate = planItem.StartsLate, + StartsAt = planItem.Time.Start, + Name = guideCollection.Name, + EndsAt = planItem.Time.End, + }; // Check for source list update var sourceUpdater = planItem.Definition as SourceListTask; diff --git a/VCR.NET/ServiceCore/Persistence/VCRSchedule.cs b/VCR.NET/ServiceCore/Persistence/VCRSchedule.cs index 4f910f0..8efd582 100644 --- a/VCR.NET/ServiceCore/Persistence/VCRSchedule.cs +++ b/VCR.NET/ServiceCore/Persistence/VCRSchedule.cs @@ -1,10 +1,10 @@ +using JMS.DVB; +using JMS.DVB.Algorithms.Scheduler; +using JMS.DVBVCR.RecordingService.Planning; using System; using System.Collections.Generic; using System.Linq; using System.Xml.Serialization; -using JMS.DVB; -using JMS.DVB.Algorithms.Scheduler; -using JMS.DVBVCR.RecordingService.Planning; namespace JMS.DVBVCR.RecordingService.Persistence @@ -24,8 +24,8 @@ public class VCRSchedule /// Abbildung der .NET Wochentage auf die interne Darstellung in . /// static private Dictionary m_DayMapper = - new Dictionary - { + new Dictionary + { { DayOfWeek.Monday, VCRDay.Monday }, { DayOfWeek.Tuesday, VCRDay.Tuesday }, { DayOfWeek.Wednesday, VCRDay.Wednesday }, @@ -206,7 +206,7 @@ public bool IsActive var startDate = new DateTime( startLocal.Date.Ticks, DateTimeKind.Local ); // Find some allowed date - no need to test more than a week - for (var day = 7; day-- > 0; ) + for (var day = 7; day-- > 0;) { // Yeah, can to it if (MayRecordOn( lastDate )) @@ -242,42 +242,21 @@ public bool IsActive /// Meldet, ob fr diese Aufzeichnung eine Wiederholung definiert ist. /// [XmlIgnore] - private bool IsRepeatable - { - get - { - // See if repeat mask is set - if (Days.HasValue) - return ((int) Days.Value != 0); - - // Once only - return false; - } - } + private bool IsRepeatable => Days.HasValue && ((int) Days.Value != 0); /// /// Prft, ob eine Aufzeichnung an dem angegebenen Wochentag erlaubt ist. /// /// Der genaue Aufzeichnungszeitpunkt in der lokalen Zeitzone. /// Gesetzt, wenn eine Aufzeichnung erlaubt ist. - private bool MayRecordOn( DateTime day ) - { - // Not repeated - if (!Days.HasValue) - return false; - else - return ((Days.Value & GetDay( day.DayOfWeek )) != 0); - } + private bool MayRecordOn( DateTime day ) => Days.HasValue && ((Days.Value & GetDay( day.DayOfWeek )) != 0); /// /// Wandelt einen Wochentag in eine VCR.NET Kennzeichnung des Wochentags. /// /// Ein beliebiger Wochentag. /// Die zugehrige Kennzeichnung. - public static VCRDay GetDay( DayOfWeek day ) - { - return m_DayMapper[day]; - } + public static VCRDay GetDay( DayOfWeek day ) => m_DayMapper[day]; /// /// Ermittelt, ob fr einen bestimmten Tag eine Ausnahme definiert ist. @@ -310,7 +289,7 @@ public VCRScheduleException FindException( DateTime recordingEnd ) var date = recordingEnd.ToLocalTime().Date; // Process day around check day - for (int i = 5; i-- > 0; ) + for (int i = 5; i-- > 0;) { // Get the current date to test var referenceDay = date.AddDays( 2 - i ); @@ -400,11 +379,11 @@ public void AddToScheduler( RecordingScheduler scheduler, VCRJob job, IScheduleR { // Validate if (scheduler == null) - throw new ArgumentNullException( "scheduler" ); + throw new ArgumentNullException( nameof( scheduler ) ); if (job == null) - throw new ArgumentNullException( "job" ); + throw new ArgumentNullException( nameof( job ) ); if (findSource == null) - throw new ArgumentNullException( "findSource" ); + throw new ArgumentNullException( nameof( findSource ) ); // Let VCR.NET choose a profile to do the work if (job.AutomaticResourceSelection) @@ -427,9 +406,9 @@ public void AddToScheduler( RecordingScheduler scheduler, VCRJob job, IScheduleR Source = new Station { - TransportStream = persistedSource.Source.TransportStream, - Network = persistedSource.Source.Network, - Service = persistedSource.Source.Service, + TransportStream = persistedSource.Source?.TransportStream ?? 0, + Network = persistedSource.Source?.Network ?? 0, + Service = persistedSource.Source?.Service ?? 0, Name = persistedSource.DisplayName, }, }; @@ -441,7 +420,7 @@ public void AddToScheduler( RecordingScheduler scheduler, VCRJob job, IScheduleR return; // Load all - var name = string.IsNullOrEmpty( Name ) ? job.Name : string.Format( "{0} ({1})", job.Name, Name ); + var name = string.IsNullOrEmpty( Name ) ? job.Name : $"{job.Name} ({Name})"; var source = ProfileScheduleResource.CreateSource( selection ); var duration = TimeSpan.FromMinutes( Duration ); var noStartBefore = NoStartBefore; diff --git a/VCR.NET/ServiceCore/Persistence/VCRScheduleException.cs b/VCR.NET/ServiceCore/Persistence/VCRScheduleException.cs index 4ff375a..aff13ee 100644 --- a/VCR.NET/ServiceCore/Persistence/VCRScheduleException.cs +++ b/VCR.NET/ServiceCore/Persistence/VCRScheduleException.cs @@ -1,5 +1,5 @@ -using System; using JMS.DVB.Algorithms.Scheduler; +using System; namespace JMS.DVBVCR.RecordingService.Persistence @@ -30,7 +30,7 @@ public class VCRScheduleException /// /// Meldet, ob Ausnahmewerte gesetzt sind. /// - public bool IsEmpty { get { return !Duration.HasValue && !ShiftTime.HasValue; } } + public bool IsEmpty => !Duration.HasValue && !ShiftTime.HasValue; /// /// Wandelt diese Ausnahmebeschreibung in ein entsprechendes auivalent fr die Planung. diff --git a/VCR.NET/ServiceCore/Planning/IRecordingPlannerSite.cs b/VCR.NET/ServiceCore/Planning/IRecordingPlannerSite.cs index d09555d..9df7c7d 100644 --- a/VCR.NET/ServiceCore/Planning/IRecordingPlannerSite.cs +++ b/VCR.NET/ServiceCore/Planning/IRecordingPlannerSite.cs @@ -1,7 +1,7 @@ -using System; -using System.Collections.Generic; -using JMS.DVB; +using JMS.DVB; using JMS.DVB.Algorithms.Scheduler; +using System; +using System.Collections.Generic; namespace JMS.DVBVCR.RecordingService.Planning diff --git a/VCR.NET/ServiceCore/Planning/PlanContext.cs b/VCR.NET/ServiceCore/Planning/PlanContext.cs index 7fa2fd4..ae8c423 100644 --- a/VCR.NET/ServiceCore/Planning/PlanContext.cs +++ b/VCR.NET/ServiceCore/Planning/PlanContext.cs @@ -1,9 +1,9 @@ -using System; +using JMS.DVB.Algorithms.Scheduler; +using JMS.DVBVCR.RecordingService.Persistence; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; -using JMS.DVB.Algorithms.Scheduler; -using JMS.DVBVCR.RecordingService.Persistence; namespace JMS.DVBVCR.RecordingService.Planning @@ -29,7 +29,7 @@ private class ScheduleInformationComparer : IComparer /// Die erste Planung. /// Die zweite Planung. /// Die Anordnung der beiden Planungen. - public int Compare( IScheduleInformation left, IScheduleInformation right ) + public int Compare(IScheduleInformation left, IScheduleInformation right) { // Check mode if (left == null) @@ -40,7 +40,7 @@ public int Compare( IScheduleInformation left, IScheduleInformation right ) else if (right == null) return +1; else - return left.Time.Start.CompareTo( right.Time.Start ); + return left.Time.Start.CompareTo(right.Time.Start); } } @@ -63,10 +63,10 @@ public int Compare( IScheduleInformation left, IScheduleInformation right ) /// Erstellt eine neue Detailinformation. /// /// Alle laufenden Aufzeichnungen. - internal PlanContext( IEnumerable running ) + internal PlanContext(IEnumerable running) { // Remember - m_running = (running ?? Enumerable.Empty()).ToDictionary( info => info.Schedule.Definition.UniqueIdentifier ); + m_running = (running ?? Enumerable.Empty()).ToDictionary(info => info.Schedule.Definition.UniqueIdentifier); } /// @@ -74,30 +74,26 @@ internal PlanContext( IEnumerable running ) /// /// Die eindeutige Kennung der Aufzeichnung. /// Die Informationen, mit denen die Aufzeichnung gestartet wurde. - public ScheduleInformation GetRunState( Guid uniqueIdentifier ) - { - // Report - ScheduleInformation info; - return m_running.TryGetValue( uniqueIdentifier, out info ) ? info : null; - } + public ScheduleInformation GetRunState(Guid uniqueIdentifier) => + m_running.TryGetValue(uniqueIdentifier, out ScheduleInformation info) ? info : null; /// /// Ergänz die Abbildung von einer Aufzeichnung auf einen Auftrag. /// /// Eine Aufzeichnung. /// Der zugehörige Auftrag. - public void RegisterSchedule( VCRSchedule schedule, VCRJob job ) + public void RegisterSchedule(VCRSchedule schedule, VCRJob job) { // Validate if (schedule == null) - throw new ArgumentNullException( "schedule" ); + throw new ArgumentNullException(nameof(schedule)); if (job == null) - throw new ArgumentNullException( "job" ); + throw new ArgumentNullException(nameof(job)); // Skip on missing identifier var scheduleIdentifier = schedule.UniqueID; if (scheduleIdentifier.HasValue) - m_jobsBySchedule.Add( scheduleIdentifier.Value, job ); + m_jobsBySchedule.Add(scheduleIdentifier.Value, job); } /// @@ -105,23 +101,19 @@ public void RegisterSchedule( VCRSchedule schedule, VCRJob job ) /// /// Die Kennung einer Aufzeichnung. /// Der zugehörige Auftrag oder null. - public VCRJob TryFindJob( Guid scheduleIdentifier ) - { - // Test - VCRJob job; - return m_jobsBySchedule.TryGetValue( scheduleIdentifier, out job ) ? job : null; - } + public VCRJob TryFindJob(Guid scheduleIdentifier) => + m_jobsBySchedule.TryGetValue(scheduleIdentifier, out VCRJob job) ? job : null; /// /// Versucht zu einer Aufzeichnung den zugehörigen Auftrag zu finden. /// /// Eine Aufzeichnung. /// Der zugehörige Auftrag oder null. - public VCRJob TryFindJob( VCRSchedule schedule ) + public VCRJob TryFindJob(VCRSchedule schedule) { // Validate if (schedule == null) - throw new ArgumentNullException( "schedule" ); + throw new ArgumentNullException(nameof(schedule)); // Skip on missing identifier var scheduleIdentifier = schedule.UniqueID; @@ -129,40 +121,32 @@ public VCRJob TryFindJob( VCRSchedule schedule ) return null; // Forward - return TryFindJob( scheduleIdentifier.Value ); + return TryFindJob(scheduleIdentifier.Value); } /// /// Vermerkt den Aufzeichnungsplan. /// /// Alle einzelnen Aufzeichnungen. - public void LoadPlan( IEnumerable planItems ) + public void LoadPlan(IEnumerable planItems) { // Load m_schedules = (planItems ?? Enumerable.Empty()).ToList(); // Finish - m_schedules.Sort( ByStartComparer ); + m_schedules.Sort(ByStartComparer); } /// /// Meldet alle Aufzeichnungen. /// /// Die Liste aller Aufzeichnungen. - public IEnumerator GetEnumerator() - { - // Forward - return m_schedules.GetEnumerator(); - } + public IEnumerator GetEnumerator() => m_schedules.GetEnumerator(); /// /// Meldet alle Aufzeichnungen. /// /// Die Liste aller Aufzeichnungen. - IEnumerator IEnumerable.GetEnumerator() - { - // Forward - return GetEnumerator(); - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } } diff --git a/VCR.NET/ServiceCore/Planning/ProgramGuideTask.cs b/VCR.NET/ServiceCore/Planning/ProgramGuideTask.cs index 7803d34..c0e48f7 100644 --- a/VCR.NET/ServiceCore/Planning/ProgramGuideTask.cs +++ b/VCR.NET/ServiceCore/Planning/ProgramGuideTask.cs @@ -1,6 +1,6 @@ -using System; +using JMS.DVB.Algorithms.Scheduler; +using System; using System.IO; -using JMS.DVB.Algorithms.Scheduler; namespace JMS.DVBVCR.RecordingService.Planning @@ -52,9 +52,9 @@ private ProgramGuideTask( IScheduleResource forResource, ProfileState profile, F { // Validate if (forResource == null) - throw new ArgumentNullException( "forResource" ); + throw new ArgumentNullException( nameof( forResource ) ); if (lastUpdate == null) - throw new ArgumentNullException( "lastUpdate" ); + throw new ArgumentNullException( nameof( lastUpdate ) ); // Remember m_Resources = new[] { forResource }; @@ -73,49 +73,39 @@ private ProgramGuideTask( IScheduleResource forResource, ProfileState profile, F /// /// Meldet das Gerät, für das diese Sammlung erfolgt. /// - public override IScheduleResource[] Resources { get { return m_Resources; } } + public override IScheduleResource[] Resources => m_Resources; /// /// Meldet, ob die Ausführung grundsätzlich aktiviert ist. /// - public override bool IsEnabled { get { return VCRConfiguration.Current.ProgramGuideUpdateEnabled; } } + public override bool IsEnabled => VCRConfiguration.Current.ProgramGuideUpdateEnabled; /// /// Meldet wenn möglich den Zeitpunkt, an dem letztmalig ein Durchlauf /// stattgefunden hat. /// - public override DateTime? LastRun { get { return m_LastUpdate(); } } + public override DateTime? LastRun => m_LastUpdate(); /// /// Meldet die maximale Dauer einer Ausführung. /// - public override TimeSpan Duration { get { return TimeSpan.FromMinutes( VCRConfiguration.Current.ProgramGuideUpdateDuration ); } } + public override TimeSpan Duration => TimeSpan.FromMinutes( VCRConfiguration.Current.ProgramGuideUpdateDuration ); /// /// Meldet die Zeitspanne nach der ein neuer Durchlauf gestartet werden darf, /// wenn der Computer sowieso gerade aktiv ist. /// - public override TimeSpan? JoinThreshold - { - get - { - // Ask configuration - if (VCRConfiguration.Current.HasRecordedSomething) - return VCRConfiguration.Current.ProgramGuideJoinThreshold; - else - return null; - } - } + public override TimeSpan? JoinThreshold => VCRConfiguration.Current.HasRecordedSomething ? VCRConfiguration.Current.ProgramGuideJoinThreshold : null; /// /// Meldet die Zeitspanne, die mindestens zwischen zwei Durchläufen liegen soll. /// - public override TimeSpan DefaultInterval { get { return VCRConfiguration.Current.ProgramGuideUpdateInterval ?? new TimeSpan( 1 ); } } + public override TimeSpan DefaultInterval => VCRConfiguration.Current.ProgramGuideUpdateInterval ?? new TimeSpan( 1 ); /// /// Meldet die bevorzugten Uhrzeiten für eine Ausführung. Die verwendeten Zeiten /// bezeichnen dabei Stunden in der lokalen Zeitzone. /// - public override uint[] PreferredHours { get { return VCRConfiguration.Current.ProgramGuideUpdateHours; } } + public override uint[] PreferredHours => VCRConfiguration.Current.ProgramGuideUpdateHours; } } diff --git a/VCR.NET/ServiceCore/Planning/RecordingPlanner.cs b/VCR.NET/ServiceCore/Planning/RecordingPlanner.cs index 63aeef3..7a2c008 100644 --- a/VCR.NET/ServiceCore/Planning/RecordingPlanner.cs +++ b/VCR.NET/ServiceCore/Planning/RecordingPlanner.cs @@ -1,9 +1,9 @@ -using System; +using JMS.DVB; +using JMS.DVB.Algorithms.Scheduler; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; -using JMS.DVB; -using JMS.DVB.Algorithms.Scheduler; namespace JMS.DVBVCR.RecordingService.Planning @@ -116,10 +116,7 @@ private RecordingPlanner( IRecordingPlannerSite site ) /// public void Dispose() { - // Cleanup - var manager = Interlocked.Exchange( ref m_manager, null ); - if (manager != null) - manager.Dispose(); + (Interlocked.Exchange( ref m_manager, null ))?.Dispose(); } /// @@ -134,8 +131,7 @@ public IScheduleResource GetResourceForProfile( string profileName ) return null; // Ask map - IScheduleResource resource; - if (m_resources.TryGetValue( profileName, out resource )) + if (m_resources.TryGetValue(profileName, out IScheduleResource resource)) return resource; // Not found @@ -151,7 +147,7 @@ public static RecordingPlanner Create( IRecordingPlannerSite site ) { // Validate if (site == null) - throw new ArgumentNullException( "site" ); + throw new ArgumentNullException( nameof( site ) ); // Forward return new RecordingPlanner( site ); @@ -164,7 +160,7 @@ public static RecordingPlanner Create( IRecordingPlannerSite site ) public void DispatchNextActivity( DateTime referenceTime ) { // As long as necessary - for (var skipped = new HashSet(); ; ) + for (var skipped = new HashSet(); ;) { // The plan context we created PlanContext context = null; @@ -216,8 +212,7 @@ public void DispatchNextActivity( DateTime referenceTime ) if (stop != null) { // Lookup the item and report to site - ScheduleInformation schedule; - if (!m_started.TryGetValue( stop.UniqueIdentifier, out schedule )) + if (!m_started.TryGetValue(stop.UniqueIdentifier, out ScheduleInformation schedule)) return; // Report to site @@ -291,8 +286,7 @@ public bool SetEndTime( Guid itemIdentifier, DateTime newEndTime ) return false; // See if we know it - ScheduleInformation started; - if (!m_started.TryGetValue( itemIdentifier, out started )) + if (!m_started.TryGetValue(itemIdentifier, out ScheduleInformation started)) return true; // Try to get the new schedule data @@ -338,11 +332,7 @@ private PlanContext GetPlan( RecordingScheduler scheduler, DateTime referenceTim /// /// Der Bezugspunkt für die Planung. /// Die Liste der nächsten Aufzeichnungen. - public PlanContext GetPlan( DateTime referenceTime ) - { - // Forward - return GetPlan( m_manager.CreateScheduler( false ), referenceTime, null, 1000 ); - } + public PlanContext GetPlan( DateTime referenceTime ) => GetPlan( m_manager.CreateScheduler( false ), referenceTime, null, 1000 ); /// /// Entfernt alle aktiven Aufzeichnungen. diff --git a/VCR.NET/ServiceCore/Planning/ScheduleInformation.cs b/VCR.NET/ServiceCore/Planning/ScheduleInformation.cs index 188a89a..8d885d3 100644 --- a/VCR.NET/ServiceCore/Planning/ScheduleInformation.cs +++ b/VCR.NET/ServiceCore/Planning/ScheduleInformation.cs @@ -1,5 +1,5 @@ -using System; -using JMS.DVB.Algorithms.Scheduler; +using JMS.DVB.Algorithms.Scheduler; +using System; namespace JMS.DVBVCR.RecordingService.Planning @@ -22,7 +22,7 @@ public ScheduleInformation( IScheduleInformation original ) { // Validate if (original == null) - throw new ArgumentNullException( "original" ); + throw new ArgumentNullException( nameof( original ) ); // Remember RealTime = original.Time; diff --git a/VCR.NET/ServiceCore/Planning/SourceListTask.cs b/VCR.NET/ServiceCore/Planning/SourceListTask.cs index d31625c..d43d69f 100644 --- a/VCR.NET/ServiceCore/Planning/SourceListTask.cs +++ b/VCR.NET/ServiceCore/Planning/SourceListTask.cs @@ -1,6 +1,6 @@ -using System; +using JMS.DVB.Algorithms.Scheduler; +using System; using System.IO; -using JMS.DVB.Algorithms.Scheduler; namespace JMS.DVBVCR.RecordingService.Planning @@ -52,9 +52,9 @@ private SourceListTask( IScheduleResource forResource, ProfileState profile, Fun { // Validate if (forResource == null) - throw new ArgumentNullException( "forResource" ); + throw new ArgumentNullException( nameof( forResource ) ); if (lastUpdate == null) - throw new ArgumentNullException( "lastUpdate" ); + throw new ArgumentNullException( nameof( lastUpdate ) ); // Remember m_Resources = new[] { forResource }; @@ -73,7 +73,7 @@ private SourceListTask( IScheduleResource forResource, ProfileState profile, Fun /// /// Meldet das Gerät, für das diese Sammlung erfolgt. /// - public override IScheduleResource[] Resources { get { return m_Resources; } } + public override IScheduleResource[] Resources => m_Resources; /// /// Meldet, ob die Ausführung grundsätzlich aktiviert ist. @@ -95,29 +95,19 @@ public override bool IsEnabled /// /// Meldet die maximale Dauer einer Ausführung. /// - public override TimeSpan Duration { get { return TimeSpan.FromMinutes( VCRConfiguration.Current.SourceListUpdateDuration ); } } + public override TimeSpan Duration => TimeSpan.FromMinutes( VCRConfiguration.Current.SourceListUpdateDuration ); /// /// Meldet wenn möglich den Zeitpunkt, an dem letztmalig ein Durchlauf /// stattgefunden hat. /// - public override DateTime? LastRun { get { return m_LastUpdate(); } } + public override DateTime? LastRun => m_LastUpdate(); /// /// Meldet die Zeitspanne nach der ein neuer Durchlauf gestartet werden darf, /// wenn der Computer sowieso gerade aktiv ist. /// - public override TimeSpan? JoinThreshold - { - get - { - // Ask configuration - if (VCRConfiguration.Current.HasRecordedSomething) - return VCRConfiguration.Current.SourceListJoinThreshold; - else - return null; - } - } + public override TimeSpan? JoinThreshold => VCRConfiguration.Current.HasRecordedSomething ? VCRConfiguration.Current.SourceListJoinThreshold : null; /// /// Meldet die Zeitspanne, die mindestens zwischen zwei Durchläufen liegen soll. @@ -144,6 +134,6 @@ public override TimeSpan DefaultInterval /// Meldet die bevorzugten Uhrzeiten für eine Ausführung. Die verwendeten Zeiten /// bezeichnen dabei Stunden in der lokalen Zeitzone. /// - public override uint[] PreferredHours { get { return VCRConfiguration.Current.SourceListUpdateHours; } } + public override uint[] PreferredHours => VCRConfiguration.Current.SourceListUpdateHours; } } diff --git a/VCR.NET/ServiceCore/ProfileState.cs b/VCR.NET/ServiceCore/ProfileState.cs index 96a362c..5dcabdd 100644 --- a/VCR.NET/ServiceCore/ProfileState.cs +++ b/VCR.NET/ServiceCore/ProfileState.cs @@ -200,7 +200,7 @@ public bool BeginRequest( CardServerProxy request, bool throwOnBusy = true ) lock (m_RequestLock) { // Wait for current request to end - for (; ; ) + for (;;) { // Load var current = m_CurrentRequest; @@ -300,7 +300,7 @@ public void StartRecording( VCRRecordingInfo recording ) { // Protect current request against transistions lock (m_RequestLock) - for (; ; ) + for (;;) { // Attach to the current request var current = m_CurrentRequest; @@ -393,6 +393,11 @@ public CardServerProxy ChangeStreamEnd( Guid streamIdentifier, DateTime newEndTi } } + /// + /// Meldet die Anzahl der gerade aktiven Aufzeichnungen. + /// + public int NumberOfActiveRecordings => m_CurrentRequest?.NumberOfActiveRecordings ?? 0; + /// /// Aktiviert oder deaktiviert den Netzwerkversand einer aktiven Quelle. /// @@ -422,7 +427,7 @@ public bool SetStreamTarget( SourceIdentifier source, Guid uniqueIdentifier, str /// Meldet den Namen des Wertes in der Registrierung von Windows, wo der Zeitpunkt /// der letzten Aktualisierung der Liste der Quellen gespeichert wird. /// - private string SourceUpdateRegistryName { get { return string.Format( "LastPSIRun {0}", ProfileName ); } } + private string SourceUpdateRegistryName => $"LastPSIRun {ProfileName}"; /// /// Liest oder setzt den Zeitpunkt der letzen Aktualisierung der Liste der Quellen diff --git a/VCR.NET/ServiceCore/ProfileStateCollection.cs b/VCR.NET/ServiceCore/ProfileStateCollection.cs index c3c511c..fcc19d7 100644 --- a/VCR.NET/ServiceCore/ProfileStateCollection.cs +++ b/VCR.NET/ServiceCore/ProfileStateCollection.cs @@ -67,11 +67,12 @@ internal ProfileStateCollection( VCRServer server ) /// Die Art der gemeldeten Informationen. /// Methode zum Erstellen der Information zu einem einzelnen Geräteprofil. /// Die Informationen zu den Profilen. - public IEnumerable InspectProfiles( Func factory ) - { - // Forward - return m_profiles.Values.Select( factory ); - } + public IEnumerable InspectProfiles( Func factory ) => m_profiles.Values.Select( factory ); + + /// + /// Meldet die Anzahl der aktiven Aufzeichnungen. + /// + public int NumberOfActiveRecordings => (m_profiles.Count < 1) ? 0 : m_profiles.Values.Sum( profile => profile.NumberOfActiveRecordings ); /// /// Ermittelt den Zustand eines einzelnen Geräteprofils. @@ -95,8 +96,7 @@ public ProfileState this[string profileName] } // Load - ProfileState profile; - if (m_profiles.TryGetValue( profileName, out profile )) + if (m_profiles.TryGetValue(profileName, out ProfileState profile)) return profile; else return null; @@ -453,7 +453,7 @@ public void EnsureNewPlan() { // Make sure that we use an up do date plan lock (m_planAvailableSync) - for (int i = 2; i-- > 0; ) + for (int i = 2; i-- > 0;) { // Enforce calculation BeginNewPlan(); @@ -584,9 +584,8 @@ internal void ConfirmOperation( Guid scheduleIdentifier, bool isStart ) PeriodicScheduler IRecordingPlannerSite.CreateProgramGuideTask( IScheduleResource resource, Profile profile ) { // Protect against misuse - ProfileState state; - if (m_profiles.TryGetValue( profile.Name, out state )) - return new ProgramGuideTask( resource, state ); + if (m_profiles.TryGetValue(profile.Name, out ProfileState state)) + return new ProgramGuideTask(resource, state); else return null; } @@ -600,9 +599,8 @@ PeriodicScheduler IRecordingPlannerSite.CreateProgramGuideTask( IScheduleResourc PeriodicScheduler IRecordingPlannerSite.CreateSourceScanTask( IScheduleResource resource, Profile profile ) { // Protect against misuse - ProfileState state; - if (m_profiles.TryGetValue( profile.Name, out state )) - return new SourceListTask( resource, state ); + if (m_profiles.TryGetValue(profile.Name, out ProfileState state)) + return new SourceListTask(resource, state); else return null; } @@ -703,8 +701,7 @@ void IRecordingPlannerSite.Stop( IScheduleInformation item, RecordingPlanner pla VCRServer.Log( LoggingLevel.Schedules, "Done recording '{0}'", item.Definition.Name ); // Locate the profile - if we don't find it we are in big trouble! - ProfileState profile; - if (!m_profiles.TryGetValue( item.Resource.Name, out profile )) + if (!m_profiles.TryGetValue(item.Resource.Name, out ProfileState profile)) return; // Mark as pending @@ -743,8 +740,7 @@ void IRecordingPlannerSite.Start( IScheduleInformation item, RecordingPlanner pl VCRServer.Log( LoggingLevel.Schedules, "Start recording '{0}'", item.Definition.Name ); // Locate the profile - if we don't find it we are in big trouble! - ProfileState profile; - if (!m_profiles.TryGetValue( item.Resource.Name, out profile )) + if (!m_profiles.TryGetValue(item.Resource.Name, out ProfileState profile)) return; // Mark as pending diff --git a/VCR.NET/ServiceCore/ProgramGuide/GuideEntryFilter.cs b/VCR.NET/ServiceCore/ProgramGuide/GuideEntryFilter.cs index ad8f51f..ea88918 100644 --- a/VCR.NET/ServiceCore/ProgramGuide/GuideEntryFilter.cs +++ b/VCR.NET/ServiceCore/ProgramGuide/GuideEntryFilter.cs @@ -1,7 +1,7 @@ +using JMS.DVB; using System; using System.Collections.Generic; using System.Linq; -using JMS.DVB; namespace JMS.DVBVCR.RecordingService.ProgramGuide diff --git a/VCR.NET/ServiceCore/ProgramGuide/OrderedEntries.cs b/VCR.NET/ServiceCore/ProgramGuide/OrderedEntries.cs index c801714..1d2302c 100644 --- a/VCR.NET/ServiceCore/ProgramGuide/OrderedEntries.cs +++ b/VCR.NET/ServiceCore/ProgramGuide/OrderedEntries.cs @@ -178,7 +178,7 @@ public void Add( ProgramGuideEntry entry ) var tNext = entry.EndTime; // May need to cleanup - for (++ix; ix < m_Events.Count; ) + for (++ix; ix < m_Events.Count;) { // Load the entry var cur = m_Events[ix]; @@ -209,28 +209,14 @@ public void DiscardOld() /// /// Meldet die Anzahl der verwalteten Eintrge. /// - public int Count - { - get - { - // Report - return m_Events.Count; - } - } + public int Count => m_Events.Count; /// /// Ermittelt einen bestimmten Eintrag. /// /// Die 0-basierte laufende Nummer des Eintrags. /// Der gewnschte Eintrag. - public ProgramGuideEntry this[int index] - { - get - { - // Report - return m_Events[index]; - } - } + public ProgramGuideEntry this[int index] => m_Events[index]; #region IEnumerable Members @@ -238,11 +224,7 @@ public ProgramGuideEntry this[int index] /// Erzeugt eine Auflistung ber alle enthaltenen Eintrge. /// /// Die gewnschte Auflistung. - public IEnumerator GetEnumerator() - { - // Forward - return m_Events.GetEnumerator(); - } + public IEnumerator GetEnumerator() => m_Events.GetEnumerator(); #endregion @@ -252,11 +234,7 @@ public IEnumerator GetEnumerator() /// Erzeugt eine Auflistung ber alle enthaltenen Eintrge. /// /// Die gewnschte Auflistung. - IEnumerator IEnumerable.GetEnumerator() - { - // Forward - return GetEnumerator(); - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); #endregion @@ -282,11 +260,7 @@ public OrderedEntries Clone() /// Erzeugt eine exakte Kopie dieser Liste. /// /// Die gewnschte Kopie. - object ICloneable.Clone() - { - // Forward - return Clone(); - } + object ICloneable.Clone() => Clone(); #endregion } diff --git a/VCR.NET/ServiceCore/ProgramGuide/ProgramGuideEntries.cs b/VCR.NET/ServiceCore/ProgramGuide/ProgramGuideEntries.cs index 48ca4d3..d79707e 100644 --- a/VCR.NET/ServiceCore/ProgramGuide/ProgramGuideEntries.cs +++ b/VCR.NET/ServiceCore/ProgramGuide/ProgramGuideEntries.cs @@ -1,8 +1,8 @@ +using JMS.DVB; using System; using System.Collections.Generic; using System.Linq; using System.Xml.Serialization; -using JMS.DVB; namespace JMS.DVBVCR.RecordingService.ProgramGuide @@ -40,7 +40,7 @@ public ProgramGuideEntries() public void AddRange( IEnumerable entries ) { // Add in order - if (null != entries) + if (entries != null) foreach (var entry in entries) Add( entry ); } @@ -55,9 +55,8 @@ public void Add( ProgramGuideEntry newEvent ) var key = newEvent.Source; // Attach to holder - OrderedEntries events; - if (!m_Events.TryGetValue( key, out events )) - m_Events.Add( key, events = new OrderedEntries() ); + if (!m_Events.TryGetValue(key, out OrderedEntries events)) + m_Events.Add(key, events = new OrderedEntries()); // Forward events.Add( newEvent ); @@ -73,9 +72,8 @@ public void Add( ProgramGuideEntry newEvent ) public bool HasEntry( SourceIdentifier source, DateTime start, DateTime end ) { // Attach to holder - OrderedEntries events; - if (m_Events.TryGetValue( source, out events )) - return events.HasEntry( start, end ); + if (m_Events.TryGetValue(source, out OrderedEntries events)) + return events.HasEntry(start, end); else return false; } @@ -92,11 +90,10 @@ public bool HasEntry( SourceIdentifier source, DateTime start, DateTime end ) public TTarget FindBestEntry( SourceIdentifier source, DateTime start, DateTime end, Func factory ) { // Attach to holder - OrderedEntries events; - if (m_Events.TryGetValue( source, out events )) - return events.FindBestEntry( start, end, factory ); + if (m_Events.TryGetValue(source, out OrderedEntries events)) + return events.FindBestEntry(start, end, factory); else - return default( TTarget ); + return default(TTarget); } /// @@ -108,9 +105,8 @@ public TTarget FindBestEntry( SourceIdentifier source, DateTime start, public ProgramGuideEntry FindEntry( SourceIdentifier source, DateTime start ) { // Attach to holder - OrderedEntries events; - if (m_Events.TryGetValue( source, out events )) - return events.FindEntry( start ); + if (m_Events.TryGetValue(source, out OrderedEntries events)) + return events.FindEntry(start); else return null; } @@ -179,8 +175,7 @@ public void DiscardOld() public IEnumerable GetEntries( SourceIdentifier source ) { // Load list - OrderedEntries entries; - if (!m_Events.TryGetValue( source, out entries )) + if (!m_Events.TryGetValue(source, out OrderedEntries entries)) yield break; // Process all as long as caller needs it diff --git a/VCR.NET/ServiceCore/ProgramGuide/ProgramGuideEntry.cs b/VCR.NET/ServiceCore/ProgramGuide/ProgramGuideEntry.cs index 012519a..c6fa7da 100644 --- a/VCR.NET/ServiceCore/ProgramGuide/ProgramGuideEntry.cs +++ b/VCR.NET/ServiceCore/ProgramGuide/ProgramGuideEntry.cs @@ -1,8 +1,8 @@ +using JMS.DVB; using System; using System.Collections.Generic; using System.Text; using System.Xml.Serialization; -using JMS.DVB; namespace JMS.DVBVCR.RecordingService.ProgramGuide @@ -137,10 +137,10 @@ public DateTime StartTime static ProgramGuideEntry() { // Helper - List disallow = new List(); + var disallow = new List(); // Fill - for (char ch = '\x0020'; ch-- > '\x0000'; ) + for (char ch = '\x0020'; ch-- > '\x0000';) if (('\x0009' != ch) && ('\x000a' != ch) && ('\x000d' != ch)) disallow.Add( ch ); @@ -175,7 +175,7 @@ private static string CleanString( string input ) StringBuilder clean = new StringBuilder(); // Process - for (int cur = 0; cur < input.Length; ) + for (int cur = 0; cur < input.Length;) { // Find next int next = input.IndexOfAny( m_Disallowed, cur ); @@ -221,14 +221,7 @@ public DateTime EndTime /// Meldet die Quelle zu diesem Eintrag. /// [XmlIgnore] - public SourceIdentifier Source - { - get - { - // Report - return new SourceIdentifier( NetworkIdentifier, TransportIdentifier, ServiceIdentifier ); - } - } + public SourceIdentifier Source => new SourceIdentifier( NetworkIdentifier, TransportIdentifier, ServiceIdentifier ); #region IComparable Members @@ -244,7 +237,7 @@ public int CompareTo( object obj ) ProgramGuideEntry other = obj as ProgramGuideEntry; // Not comparable - we are left of these - if (null == other) + if (other == null) return -1; // Forward diff --git a/VCR.NET/ServiceCore/ProgramGuide/ProgramGuideManager.cs b/VCR.NET/ServiceCore/ProgramGuide/ProgramGuideManager.cs index e3f9664..a624cdd 100644 --- a/VCR.NET/ServiceCore/ProgramGuide/ProgramGuideManager.cs +++ b/VCR.NET/ServiceCore/ProgramGuide/ProgramGuideManager.cs @@ -1,9 +1,9 @@ -using System; +using JMS.DVB; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; -using JMS.DVB; namespace JMS.DVBVCR.RecordingService.ProgramGuide @@ -16,17 +16,17 @@ public class ProgramGuideManager /// /// Die zugehörige Auftragsverwaltung. /// - public JobManager JobManager { get; private set; } + public JobManager JobManager { get; } /// /// Der Name des zugehörigen Geräteprofils. /// - public string ProfileName { get; private set; } + public string ProfileName { get; } /// /// Meldet die zugehörige Datei mit den Daten der Programmzeitschrift. /// - public FileInfo ProgramGuideFile { get; private set; } + public FileInfo ProgramGuideFile { get; } /// /// Die Daten der Programmzeitschrift. @@ -45,7 +45,7 @@ public ProgramGuideManager( JobManager jobs, string profileName ) JobManager = jobs; // Calculate file - ProgramGuideFile = new FileInfo( Path.Combine( JobManager.CollectorDirectory.FullName, string.Format( "EPGData for {0}.xml", ProfileName ) ) ); + ProgramGuideFile = new FileInfo( Path.Combine( JobManager.CollectorDirectory.FullName, $"EPGData for {ProfileName}.xml" ) ); // See if profile has it's own program guide if (!HasProgramGuide) @@ -143,13 +143,13 @@ public bool HasProgramGuide /// /// Meldet das zugehörige Geräteprofil. /// - public Profile Profile { get { return VCRProfiles.FindProfile( ProfileName ); } } + public Profile Profile => VCRProfiles.FindProfile( ProfileName ); /// /// Meldet den Namen des Wertes in der Registrierung von Windows, wo der Zeitpunkt /// der letzten Ausführung gespeichert wird. /// - private string UpdateRegistryName { get { return string.Format( "LastEPGRun {0}", ProfileName ); } } + private string UpdateRegistryName => $"LastEPGRun {ProfileName}"; /// /// Liest oder setzt den Zeitpunkt der letzen Aktualisierung der Programmzeitschrift. @@ -242,15 +242,7 @@ public TTarget FindBestEntry( SourceIdentifier source, DateTime start, /// Die Quelle, deren Eintrag ermittelt werden soll. /// Der exakte Startzeitpunkt. /// Der gewünschte Eintrag. - public ProgramGuideEntry FindEntry( SourceIdentifier source, DateTime start ) - { - // Forward - var entries = LeafEntries; - if (entries == null) - return null; - else - return entries.FindEntry( source, start ); - } + public ProgramGuideEntry FindEntry( SourceIdentifier source, DateTime start ) => LeafEntries?.FindEntry( source, start ); /// /// Ermittelt einen Auszug aus der Programmzeitschrift. diff --git a/VCR.NET/ServiceCore/Properties/AssemblyInfo.cs b/VCR.NET/ServiceCore/Properties/AssemblyInfo.cs index 8f55247..ee26964 100644 --- a/VCR.NET/ServiceCore/Properties/AssemblyInfo.cs +++ b/VCR.NET/ServiceCore/Properties/AssemblyInfo.cs @@ -34,7 +34,8 @@ // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion( "4.3.0.0" )] +[assembly: AssemblyVersion( "4.5.0.0" )] +[assembly: AssemblyFileVersion("4.5.0.0")] // Startcode für die Web Anwendung [assembly: PreApplicationStartMethod( typeof( ServerRuntime ), "WebStartup" )] diff --git a/VCR.NET/ServiceCore/Requests/CardServerProxy.cs b/VCR.NET/ServiceCore/Requests/CardServerProxy.cs index 8c3a9d2..ca7447c 100644 --- a/VCR.NET/ServiceCore/Requests/CardServerProxy.cs +++ b/VCR.NET/ServiceCore/Requests/CardServerProxy.cs @@ -1,11 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using JMS.DVB; +using JMS.DVB; using JMS.DVB.CardServer; using JMS.DVBVCR.RecordingService.Persistence; using JMS.DVBVCR.RecordingService.Status; using JMS.DVBVCR.RecordingService.Win32Tools; +using System; +using System.Collections.Generic; +using System.Threading; namespace JMS.DVBVCR.RecordingService.Requests @@ -67,8 +67,13 @@ protected CardServerProxy( ProfileState state, VCRRecordingInfo primary ) /// /// Meldet den Namen des aktuellen Geräteprofils. /// - public string ProfileName { get { return ProfileState.ProfileName; } } + public string ProfileName => ProfileState.ProfileName; + /// + /// Meldet die anzahl der gerade aktiven Aufzeichnungen. + /// + public virtual int NumberOfActiveRecordings => 1; + /// /// Wird aufgerufen, wenn eine Bindung an ein Geräteprofil vorgenommen wird. /// @@ -93,11 +98,7 @@ public void Deactivate() /// Erzeugt eine Beschreibung der mit diesem Zugriff verbundenen Aufzeichnungen. /// /// Die gewünschte Beschreibung. - public FullInfo CreateFullInformation() - { - // Forward - return CreateFullInformation( false ); - } + public FullInfo CreateFullInformation() => CreateFullInformation( false ); /// /// Erzeugt eine Beschreibung der mit diesem Zugriff verbundenen Aufzeichnungen. @@ -187,12 +188,12 @@ public virtual void SetRestartThreshold( Guid? scheduleIdentifier ) /// /// Wird gesetzt, sobald der Aufzeichnungsthread beendet ist. /// - public ManualResetEvent RequestFinished { get; private set; } + public ManualResetEvent RequestFinished { get; } /// /// Gesetzt, während dieser Zugriff beendet wird. /// - public bool IsShuttingDown { get { return !m_running; } } + public bool IsShuttingDown => !m_running; /// /// Erzeugt einen passenden Aufzeichnungsprozess. @@ -231,7 +232,7 @@ public void Start() else { // Create thread and start it - if this works we are no longer responsible for the plan request - m_worker = new Thread( Run ) { Name = string.Format( "Card Server Proxy Thread for {0}", ProfileName ) }; + m_worker = new Thread( Run ) { Name = $"Card Server Proxy Thread for {ProfileName}" }; m_worker.Start(); } } @@ -303,7 +304,7 @@ public void Stop( Guid scheduleIdentifier ) /// /// Prüft, ob es sich um eine reguläre Aufzeichnung handelt. /// - protected virtual bool IsRealRecording { get { return true; } } + protected virtual bool IsRealRecording => true; /// /// Die Art dieser Aufzeichnung. @@ -711,11 +712,7 @@ protected bool WaitForEnd( ref TAsync request, string traceFormat = null /// Führt eine Aktion auf dem Aufzeichnungsthread aus. /// /// Die gewünschte Aktion. - protected void EnqueueActionAndWait( Action action ) - { - // Forward - EnqueueActionAndWait( () => { action(); return null; } ); - } + protected void EnqueueActionAndWait( Action action ) => EnqueueActionAndWait( () => { action(); return null; } ); /// /// Führt eine Aktion auf dem Aufzeichnungsthread aus. @@ -801,10 +798,10 @@ protected void AddFilesToEnvironment( Dictionary environment, st foreach (var file in files) { // Report - environment[string.Format( "%{0}File{1}%", prefix, ++i )] = file.Path; + environment[$"%{prefix}File{++i}%"] = file.Path; // Create the name - string formatName = string.Format( "%{0}Format{1}%", prefix, i ); + string formatName = $"%{prefix}Format{i}%"; // Check mode switch (file.VideoType) @@ -817,28 +814,20 @@ protected void AddFilesToEnvironment( Dictionary environment, st } // Set count - environment[string.Format( "%{0}Files%", prefix )] = i.ToString(); + environment[$"%{prefix}Files%"] = i.ToString(); } /// /// Aktiviert eine VCR.NET Erweiterung. /// /// Die Umgebungsvariablen für die Erweiterung. - protected void FireRecordingStartedExtensions( Dictionary environment ) - { - // Process extensions - ProfileState.Server.ExtensionProcessManager.AddWithCleanup( "RecordingStarted", environment ); - } + protected void FireRecordingStartedExtensions( Dictionary environment ) => ProfileState.Server.ExtensionProcessManager.AddWithCleanup( "RecordingStarted", environment ); /// /// Aktiviert eine VCR.NET Erweiterung. /// /// Die Umgebungsvariablen für die Erweiterung. - protected void FireRecordingFinishedExtensions( Dictionary environment ) - { - // Process extensions - ProfileState.Server.ExtensionProcessManager.AddWithCleanup( "RecordingFinished", environment ); - } + protected void FireRecordingFinishedExtensions( Dictionary environment ) => ProfileState.Server.ExtensionProcessManager.AddWithCleanup( "RecordingFinished", environment ); #endregion } diff --git a/VCR.NET/ServiceCore/Requests/ProgramGuideProxy.cs b/VCR.NET/ServiceCore/Requests/ProgramGuideProxy.cs index 680f750..195c899 100644 --- a/VCR.NET/ServiceCore/Requests/ProgramGuideProxy.cs +++ b/VCR.NET/ServiceCore/Requests/ProgramGuideProxy.cs @@ -1,11 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using JMS.DVB; +using JMS.DVB; using JMS.DVB.CardServer; using JMS.DVBVCR.RecordingService.Persistence; using JMS.DVBVCR.RecordingService.ProgramGuide; using JMS.DVBVCR.RecordingService.Status; +using System; +using System.Collections.Generic; +using System.Linq; namespace JMS.DVBVCR.RecordingService.Requests @@ -65,12 +65,10 @@ private ProgramGuideProxy( ProfileState state, VCRRecordingInfo recording ) continue; // Locate - SourceSelection realSource; - if (allSources.TryGetValue( legacyName, out realSource )) - m_selected.Add( realSource.Source ); + if (allSources.TryGetValue(legacyName, out SourceSelection realSource)) + m_selected.Add(realSource.Source); else - VCRServer.Log( LoggingLevel.Full, Properties.Resources.BadEPGStation, legacyName ); - + VCRServer.Log(LoggingLevel.Full, Properties.Resources.BadEPGStation, legacyName); } } @@ -85,9 +83,9 @@ public static ProgramGuideProxy Create( ProfileState state, VCRRecordingInfo rec { // Validate if (state == null) - throw new ArgumentNullException( "state" ); + throw new ArgumentNullException( nameof( state ) ); if (recording == null) - throw new ArgumentNullException( "recording" ); + throw new ArgumentNullException( nameof( recording ) ); // Forward return new ProgramGuideProxy( state, recording ); @@ -96,7 +94,7 @@ public static ProgramGuideProxy Create( ProfileState state, VCRRecordingInfo rec /// /// Die Art dieser Aufzeichnung. /// - protected override string TypeName { get { return "Update Program Guide"; } } + protected override string TypeName => "Update Program Guide"; /// /// Beginnt mit der Sammlung. @@ -116,18 +114,7 @@ protected override void OnStart() /// /// Prüft, ob noch Zugriffe ausstehen. /// - protected override bool HasPendingServerRequest - { - get - { - // See if we are still waiting - if (!WaitForEnd( ref m_startPending, "Program Guide Collection now active" )) - return true; - - // Nope, we are idle - return false; - } - } + protected override bool HasPendingServerRequest => !WaitForEnd( ref m_startPending, "Program Guide Collection now active" ); /// /// Wird aufgerufen, wenn ein neuer Zustand verfügbar ist. diff --git a/VCR.NET/ServiceCore/Requests/RecordingProxy.cs b/VCR.NET/ServiceCore/Requests/RecordingProxy.cs index 6ba9369..4f43d09 100644 --- a/VCR.NET/ServiceCore/Requests/RecordingProxy.cs +++ b/VCR.NET/ServiceCore/Requests/RecordingProxy.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using JMS.DVB; +using JMS.DVB; using JMS.DVB.CardServer; using JMS.DVBVCR.RecordingService.Persistence; using JMS.DVBVCR.RecordingService.ProgramGuide; using JMS.DVBVCR.RecordingService.Status; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; namespace JMS.DVBVCR.RecordingService.Requests @@ -72,7 +72,7 @@ public RecordingProxy( ProfileState state, VCRRecordingInfo firstRecording ) /// /// Die Art dieser Aufzeichnung. /// - protected override string TypeName { get { return "Regular Recording"; } } + protected override string TypeName => "Regular Recording"; /// /// Prüft, ob asynchrone Aufrufe ausstehen. Es werden niemals neue Anfragen @@ -99,11 +99,7 @@ protected override bool HasPendingServerRequest /// Wird einmalig nach dem Starten des Aufzeichnungsprozesses aufgerufen. Dieser /// ist zu diesem Zeitpunkt im Leerlauf. /// - protected override void OnStart() - { - // Select the source group - m_groupPending = Server.BeginSelect( Representative.Source.SelectionKey ); - } + protected override void OnStart() => m_groupPending = Server.BeginSelect( Representative.Source.SelectionKey ); /// /// Bearbeitet neue Daten vom Aufzeichnungsprozess. Dieser Aufruf erfolgt immer, @@ -136,7 +132,7 @@ protected override void OnNewStateAvailable( ServerInformation state ) } // Total file size - Representative.TotalSize = (uint) (totalSize / 1024); + Representative.TotalSize = (uint)(totalSize / 1024); // No new files if (newFiles.Count < 1) @@ -192,7 +188,7 @@ protected override void OnEndRecording( Guid scheduleIdentifier ) { // Cleanup from list lock (m_recordings) - for (int i = m_recordings.Count; i-- > 0; ) + for (int i = m_recordings.Count; i-- > 0;) { // Load recording var recording = m_recordings[i]; @@ -302,6 +298,19 @@ public override void SetRestartThreshold( Guid? scheduleIdentifier ) } ); } + /// + /// Meldet die anzahl der gerade aktiven Aufzeichnungen. + /// + public override int NumberOfActiveRecordings + { + get + { + // In case there are no recordings (during startup or shutdown) make sure we block out caller + lock (m_recordings) + return Math.Max( 1, m_recordings.Count ); + } + } + /// /// Verändert den Endzeitpunkt einer Aufzeichnung. /// @@ -313,7 +322,7 @@ public override void ChangeEndTime( Guid streamIdentifier, DateTime newEndTime, // Report Tools.ExtendedLogging( "Setting End for {0} to {1}", ProfileName, newEndTime ); - // Disable hibernation + // Disable hibernation if this is the last recording in our list if (disableHibernation) Representative.DisableHibernation = true; @@ -378,15 +387,14 @@ private void EnforceUniqueFileNames() foreach (var recording in m_recordings) { // Load list - List recordings; - if (!names.TryGetValue( recording.FileName, out recordings )) + if (!names.TryGetValue(recording.FileName, out List recordings)) { // Create new recordings = new List(); // To map and ordered list - names.Add( recording.FileName, recordings ); - orderedNames.Add( recordings ); + names.Add(recording.FileName, recordings); + orderedNames.Add(recordings); } // Remember @@ -412,7 +420,7 @@ private void EnforceUniqueFileNames() do { // Create the new name - recording.FileName = Path.Combine( dir, string.Format( "{0} ({1}){2}", name, nextIndex++, ext ) ); + recording.FileName = Path.Combine( dir, $"{name} ({nextIndex++}){ext}" ); } while (names.ContainsKey( recording.FileName )); } @@ -468,11 +476,7 @@ private void RecordingPostProcessing( params VCRRecordingInfo[] recordings ) /// /// Die eindeutige Kennung der Aufzeichnung. /// Die Aufzeichnung, sofern bekannt. - private VCRRecordingInfo FindRecording( Guid scheduleIdentifier ) - { - // Easy - return m_recordings.FirstOrDefault( recording => scheduleIdentifier.Equals( recording.ScheduleUniqueID.Value ) ); - } + private VCRRecordingInfo FindRecording( Guid scheduleIdentifier ) => m_recordings.FirstOrDefault( recording => scheduleIdentifier.Equals( recording.ScheduleUniqueID.Value ) ); /// /// Berechnet das aktuelle Ende der Aufzeichnung. diff --git a/VCR.NET/ServiceCore/Requests/SourceScanProxy.cs b/VCR.NET/ServiceCore/Requests/SourceScanProxy.cs index a8f844a..1872595 100644 --- a/VCR.NET/ServiceCore/Requests/SourceScanProxy.cs +++ b/VCR.NET/ServiceCore/Requests/SourceScanProxy.cs @@ -1,7 +1,7 @@ -using System; -using JMS.DVB.CardServer; +using JMS.DVB.CardServer; using JMS.DVBVCR.RecordingService.Persistence; using JMS.DVBVCR.RecordingService.Status; +using System; namespace JMS.DVBVCR.RecordingService.Requests @@ -43,9 +43,9 @@ public static SourceScanProxy Create( ProfileState state, VCRRecordingInfo recor { // Validate if (state == null) - throw new ArgumentNullException( "state" ); + throw new ArgumentNullException( nameof( state ) ); if (recording == null) - throw new ArgumentNullException( "recording" ); + throw new ArgumentNullException( nameof( recording ) ); // Forward return new SourceScanProxy( state, recording ); @@ -54,7 +54,7 @@ public static SourceScanProxy Create( ProfileState state, VCRRecordingInfo recor /// /// Die Art dieser Aufzeichnung. /// - protected override string TypeName { get { return "Update Source List"; } } + protected override string TypeName => "Update Source List"; /// /// Aktiviert die Aktualisierung der Quellen. @@ -134,17 +134,6 @@ protected override void OnFillInformation( FullInfo info, bool finalCall, Server /// /// Prüft, ob noch Zugriffe ausstehen. /// - protected override bool HasPendingServerRequest - { - get - { - // See if we are still waiting - if (!WaitForEnd( ref m_startPending, "Source Scan now active" )) - return true; - - // Nope, we are idle - return false; - } - } + protected override bool HasPendingServerRequest => !WaitForEnd( ref m_startPending, "Source Scan now active" ); } } diff --git a/VCR.NET/ServiceCore/Requests/ZappingProxy.cs b/VCR.NET/ServiceCore/Requests/ZappingProxy.cs index 1fb0aee..3e5ac24 100644 --- a/VCR.NET/ServiceCore/Requests/ZappingProxy.cs +++ b/VCR.NET/ServiceCore/Requests/ZappingProxy.cs @@ -1,9 +1,9 @@ -using System; -using System.IO; -using JMS.DVB; +using JMS.DVB; using JMS.DVB.CardServer; using JMS.DVBVCR.RecordingService.Persistence; using JMS.DVBVCR.RecordingService.Status; +using System; +using System.IO; namespace JMS.DVBVCR.RecordingService.Requests @@ -47,9 +47,9 @@ public static ZappingProxy Create( ProfileState profile, string target ) { // Validate if (profile == null) - throw new ArgumentNullException( "profile" ); + throw new ArgumentNullException( nameof( profile ) ); if (string.IsNullOrEmpty( target )) - throw new ArgumentNullException( "target" ); + throw new ArgumentNullException( nameof( target ) ); // Create controlling information var now = DateTime.UtcNow; @@ -95,12 +95,12 @@ public override void ChangeEndTime( Guid streamIdentifier, DateTime newEndTime, /// /// Meldet, ob noch asynchrone Aufrufe ausstehen. /// - protected override bool HasPendingServerRequest { get { return false; } } + protected override bool HasPendingServerRequest => false; /// /// Prüft, ob es sich um eine reguläre Aufzeichnungs handelt. /// - protected override bool IsRealRecording { get { return false; } } + protected override bool IsRealRecording => false; /// /// Ermittelt eine Beschreibung der aktuellen Nutzung. @@ -153,7 +153,7 @@ protected override void OnStop() /// /// Meldet einen Anzeigenamen für den LIVE Zugang. /// - protected override string TypeName { get { return "LIVE"; } } + protected override string TypeName => "LIVE"; /// /// Aktiviert eine neue Quelle. diff --git a/VCR.NET/ServiceCore/RestWebApi/ConfigurationController.cs b/VCR.NET/ServiceCore/RestWebApi/ConfigurationController.cs index 86bc423..52b1885 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ConfigurationController.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ConfigurationController.cs @@ -1,12 +1,12 @@ -using System; +using JMS.DVB; +using JMS.DVBVCR.RecordingService.WebServer; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System; using System.IO; using System.Linq; using System.Runtime.Serialization; using System.Web.Http; -using JMS.DVB; -using JMS.DVBVCR.RecordingService.WebServer; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -25,13 +25,13 @@ public class SecuritySettings /// /// Die Gruppe der normalen Benutzer. /// - [DataMember( Name = "users" )] + [DataMember(Name = "users")] public string UserRole { get; set; } /// /// Die Gruppe der Administratoren. /// - [DataMember( Name = "admins" )] + [DataMember(Name = "admins")] public string AdminRole { get; set; } } @@ -44,13 +44,13 @@ public class DirectorySettings /// /// Die aktuelle Liste der erlaubten Verzeichnisse. /// - [DataMember( Name = "directories" )] + [DataMember(Name = "directories")] public string[] TargetDirectories { get; set; } /// /// Das Muster für die Erstellung der Dateinamen. /// - [DataMember( Name = "pattern" )] + [DataMember(Name = "pattern")] public string RecordingPattern { get; set; } } @@ -63,37 +63,37 @@ public class GuideSettings /// /// Der Schwellwert für vorgezogene Aktualisierungen (in Stunden). /// - [DataMember( Name = "joinHours" )] + [DataMember(Name = "joinHours")] public int? Threshold { get; set; } /// /// Der minimale Abstand zwischen Aktualisierungen (in Stunden). /// - [DataMember( Name = "minDelay" )] + [DataMember(Name = "minDelay")] public int? Interval { get; set; } /// /// Die maximale Dauer einer Aktualisierung (in Minuten). /// - [DataMember( Name = "duration" )] + [DataMember(Name = "duration")] public uint Duration { get; set; } /// /// Die Stunden, zu denen eine Aktualisierung stattfinden soll. /// - [DataMember( Name = "hours" )] + [DataMember(Name = "hours")] public uint[] Hours { get; set; } /// /// Die Quellen, die bei der Aktualisierung zu berücksichtigen sind. /// - [DataMember( Name = "sources" )] + [DataMember(Name = "sources")] public string[] Sources { get; set; } /// /// Gesetzt, wenn auch die britischen Sendungen zu berücksichtigen sind. /// - [DataMember( Name = "includeUK" )] + [DataMember(Name = "includeUK")] public bool WithUKGuide { get; set; } } @@ -106,31 +106,31 @@ public class SourceScanSettings /// /// Der Schwellwert für vorgezogene Aktualisierungen (in Tagen). /// - [DataMember( Name = "joinDays" )] + [DataMember(Name = "joinDays")] public int? Threshold { get; set; } /// /// Der minimale Abstand zwischen Aktualisierungen (in Tagen). /// - [DataMember( Name = "interval" )] + [DataMember(Name = "interval")] public int? Interval { get; set; } /// /// Die maximale Dauer einer Aktualisierung (in Minuten). /// - [DataMember( Name = "duration" )] + [DataMember(Name = "duration")] public uint Duration { get; set; } /// /// Die Stunden, zu denen eine Aktualisierung stattfinden soll. /// - [DataMember( Name = "hours" )] + [DataMember(Name = "hours")] public uint[] Hours { get; set; } /// /// Gesetzt, wenn die neue Liste mit der alten zusammengeführt werden soll. /// - [DataMember( Name = "merge" )] + [DataMember(Name = "merge")] public bool MergeLists { get; set; } } @@ -143,13 +143,13 @@ public class ProfileSettings /// /// Die Liste aller bekannten Geräteprofile. /// - [DataMember( Name = "profiles" )] + [DataMember(Name = "profiles")] public ConfigurationProfile[] SystemProfiles { get; set; } /// /// Der Name des bevorzugten Geräteprofils. /// - [DataMember( Name = "defaultProfile" )] + [DataMember(Name = "defaultProfile")] public string DefaultProfile { get; set; } } @@ -162,85 +162,85 @@ public class OtherSettings /// /// Gesetzt, wenn der VCR.NET Recording Service den Rechner in den Schlafzustand versetzen darf- /// - [DataMember( Name = "mayHibernate" )] + [DataMember(Name = "mayHibernate")] public bool AllowHibernate { get; set; } /// /// Gesetzt, wenn beim Übergang in den Schlafzustand StandBy verwendet werden soll. /// - [DataMember( Name = "useStandBy" )] + [DataMember(Name = "useStandBy")] public bool UseStandBy { get; set; } /// /// Verweildauer (in Wochen) von Aufträgen im Archiv. /// - [DataMember( Name = "archive" )] + [DataMember(Name = "archive")] public uint ArchiveTime { get; set; } /// /// Verweildauer (in Wochen) von Protokolleinträgen. /// - [DataMember( Name = "protocol" )] + [DataMember(Name = "protocol")] public uint ProtocolTime { get; set; } /// /// Vorlaufzeit (in Sekunden) beim Aufwecken aus dem Schlafzustand. /// - [DataMember( Name = "hibernationDelay" )] + [DataMember(Name = "hibernationDelay")] public uint HibernationDelay { get; set; } /// /// Gesetzt, wenn für H.264 Aufzeichnungen kein PCR generiert werden soll. /// - [DataMember( Name = "noH264PCR" )] + [DataMember(Name = "noH264PCR")] public bool DisablePCRFromH264 { get; set; } /// /// Gesetzt, wenn für MPEG-2 Aufzeichnungen kein PCR generiert werden soll. /// - [DataMember( Name = "noMPEG2PCR" )] + [DataMember(Name = "noMPEG2PCR")] public bool DisablePCRFromMPEG2 { get; set; } /// /// Minimale Verweildauer (in Minuten) im Schlafzustand bei einem erzwungenen Übergang. /// - [DataMember( Name = "forcedHibernationDelay" )] + [DataMember(Name = "forcedHibernationDelay")] public uint DelayAfterForcedHibernation { get; set; } /// /// Gesetzt um die minimale Verweildauer im Schlafzustand zu ignorieren. /// - [DataMember( Name = "suppressHibernationDelay" )] + [DataMember(Name = "suppressHibernationDelay")] public bool SuppressDelayAfterForcedHibernation { get; set; } /// /// Gesetzt, wenn auch das Basic Protokoll zur Autorisierung verwendet werden darf. /// - [DataMember( Name = "basicAuth" )] + [DataMember(Name = "basicAuth")] public bool AllowBasic { get; set; } /// /// Gesetzt, wenn auch eine verschlüsselter SSL Verbindung unterstützt werden soll. /// - [DataMember( Name = "ssl" )] + [DataMember(Name = "ssl")] public bool UseSSL { get; set; } /// /// Der TCP/IP Port für verschlüsselte Verbindungen. /// - [DataMember( Name = "sslPort" )] + [DataMember(Name = "sslPort")] public ushort SSLPort { get; set; } /// /// Der TCP/IP Port des Web Servers. /// - [DataMember( Name = "webPort" )] + [DataMember(Name = "webPort")] public ushort WebPort { get; set; } /// /// Die Art der Protokollierung. /// - [DataMember( Name = "logging" ), JsonConverter( typeof( StringEnumConverter ) )] + [DataMember(Name = "logging"), JsonConverter(typeof(StringEnumConverter))] public LoggingLevel Logging { get; set; } } @@ -253,7 +253,7 @@ public class SchedulerRules /// /// Der Inhalt der Regeldatei. /// - [DataMember( Name = "rules" )] + [DataMember(Name = "rules")] public string RuleFileContents { get; set; } } @@ -265,31 +265,31 @@ public class SchedulerRules /// Das Bezugsverzeichnis. /// Die Verzeichnisse innerhalb ober oberhalb des Bezugsverzeichnisses. [HttpGet] - public string[] Browse( string browse, bool toParent = false, string root = null ) + public string[] Browse(string browse, bool toParent = false, string root = null) { // Validate ServerRuntime.TestAdminAccess(); // See if we can move up - if (!string.IsNullOrEmpty( root )) + if (!string.IsNullOrEmpty(root)) if (toParent) - if (StringComparer.InvariantCultureIgnoreCase.Equals( root, Path.GetPathRoot( root ) )) + if (StringComparer.InvariantCultureIgnoreCase.Equals(root, Path.GetPathRoot(root))) root = null; else - root = Path.GetDirectoryName( root ); + root = Path.GetDirectoryName(root); // Devices - var names = string.IsNullOrEmpty( root ) + var names = string.IsNullOrEmpty(root) ? DriveInfo - .GetDrives() - .Where( drive => drive.DriveType == DriveType.Fixed ) - .Where( drive => drive.IsReady ) - .Select( drive => drive.RootDirectory.FullName ) + .GetDrives() + .Where(drive => drive.DriveType == DriveType.Fixed) + .Where(drive => drive.IsReady) + .Select(drive => drive.RootDirectory.FullName) : Directory - .GetDirectories( root ); + .GetDirectories(root); // Report - return new[] { root }.Concat( names.OrderBy( name => name, StringComparer.InvariantCultureIgnoreCase ) ).ToArray(); + return new[] { root }.Concat(names.OrderBy(name => name, StringComparer.InvariantCultureIgnoreCase)).ToArray(); } /// @@ -299,7 +299,7 @@ public string[] Browse( string browse, bool toParent = false, string root = null /// Das zu prüfende Verzeichnis. /// Gesetzt, wenn das Verzeichnis verwendet werden kann. [HttpGet] - public bool Validate( string validate, string directory ) + public bool Validate(string validate, string directory) { // Validate ServerRuntime.TestAdminAccess(); @@ -308,7 +308,7 @@ public bool Validate( string validate, string directory ) try { // Test - return Directory.Exists( directory ); + return Directory.Exists(directory); } catch (Exception) { @@ -323,11 +323,7 @@ public bool Validate( string validate, string directory ) /// Wird zur Unterscheidung der Methoden verwendet. /// Die aktuellen Regeln. [HttpGet] - public SchedulerRules ReadSchedulerRules( string rules ) - { - // Blind forward - we allow regular users to read the current rule set as well - return new SchedulerRules { RuleFileContents = ServerRuntime.VCRServer.SchedulerRules }; - } + public SchedulerRules ReadSchedulerRules(string rules) => new SchedulerRules { RuleFileContents = ServerRuntime.VCRServer.SchedulerRules }; /// /// Aktualisiert das Regelwerk für die Aufzeichnungsplanung. @@ -336,11 +332,7 @@ public SchedulerRules ReadSchedulerRules( string rules ) /// Die ab sofort zu verwendenden Regeln. /// Meldet, ob ein Neustart erforderlich ist. [HttpPut] - public bool? WriteSchedulerRules( string rules, [FromBody] SchedulerRules settings ) - { - // Process - return ServerRuntime.UpdateSchedulerRules( settings.RuleFileContents ); - } + public bool? WriteSchedulerRules(string rules, [FromBody] SchedulerRules settings) => ServerRuntime.UpdateSchedulerRules(settings.RuleFileContents); /// /// Meldet die Konfigurationsdaten der Geräte. @@ -348,13 +340,12 @@ public SchedulerRules ReadSchedulerRules( string rules ) /// Wird zur Unterscheidung der Methoden verwendet. /// Die aktuelle Konfiguration. [HttpGet] - public ProfileSettings ReadProfiles( string devices ) + public ProfileSettings ReadProfiles(string devices) { // Validate ServerRuntime.TestAdminAccess(); // Helper - string defaultName; // Create response var settings = @@ -363,8 +354,8 @@ public ProfileSettings ReadProfiles( string devices ) SystemProfiles = ServerRuntime .VCRServer - .GetProfiles( ConfigurationProfile.Create, out defaultName ) - .OrderBy( profile => profile.Name, ProfileManager.ProfileNameComparer ) + .GetProfiles(ConfigurationProfile.Create, out string defaultName) + .OrderBy(profile => profile.Name, ProfileManager.ProfileNameComparer) .ToArray() }; @@ -382,31 +373,31 @@ public ProfileSettings ReadProfiles( string devices ) /// Die gewünschten neuen Einstellungen. /// Das Ergebnis der Änderung. [HttpPut] - public bool? WriteProfiles( string devices, [FromBody] ProfileSettings settings ) + public bool? WriteProfiles(string devices, [FromBody] ProfileSettings settings) { // Validate ServerRuntime.TestAdminAccess(); // List of profiles to use - var profiles = settings.SystemProfiles.Where( profile => profile.UsedForRecording ).Select( profile => profile.Name ).ToList(); + var profiles = settings.SystemProfiles.Where(profile => profile.UsedForRecording).Select(profile => profile.Name).ToList(); // Move default to the front - var defaultIndex = profiles.IndexOf( settings.DefaultProfile ); + var defaultIndex = profiles.IndexOf(settings.DefaultProfile); if (defaultIndex >= 0) { // Insert at the very beginning - profiles.Insert( 0, profiles[defaultIndex] ); - profiles.RemoveAt( defaultIndex + 1 ); + profiles.Insert(0, profiles[defaultIndex]); + profiles.RemoveAt(defaultIndex + 1); } // Prepare - var update = VCRConfiguration.Current.BeginUpdate( SettingNames.Profiles ); + var update = VCRConfiguration.Current.BeginUpdate(SettingNames.Profiles); // Fill - update[SettingNames.Profiles].NewValue = string.Join( "|", profiles ); + update[SettingNames.Profiles].NewValue = string.Join("|", profiles); // Process - return ServerRuntime.Update( update.Values, ServerRuntime.VCRServer.UpdateProfiles( settings.SystemProfiles, profile => profile.Name, ( profile, device ) => profile.WriteBack( device ) ) ); + return ServerRuntime.Update(update.Values, ServerRuntime.VCRServer.UpdateProfiles(settings.SystemProfiles, profile => profile.Name, (profile, device) => profile.WriteBack(device))); } /// @@ -415,7 +406,7 @@ public ProfileSettings ReadProfiles( string devices ) /// Wird zur Unterscheidung der Methoden verwendet. /// Die gewünschten Einstellungen. [HttpGet] - public DirectorySettings ReadDirectory( string directory ) + public DirectorySettings ReadDirectory(string directory) { // Validate ServerRuntime.TestAdminAccess(); @@ -436,18 +427,18 @@ public DirectorySettings ReadDirectory( string directory ) /// Die neuen Daten. /// Das Ergebnis der Operation. [HttpPut] - public bool? WriteDirectory( string directory, [FromBody] DirectorySettings settings ) + public bool? WriteDirectory(string directory, [FromBody] DirectorySettings settings) { // Prepare to update - var update = VCRConfiguration.Current.BeginUpdate( SettingNames.VideoRecorderDirectory, SettingNames.AdditionalRecorderPaths, SettingNames.FileNamePattern ); + var update = VCRConfiguration.Current.BeginUpdate(SettingNames.VideoRecorderDirectory, SettingNames.AdditionalRecorderPaths, SettingNames.FileNamePattern); // Change settings - update[SettingNames.AdditionalRecorderPaths].NewValue = string.Join( ", ", settings.TargetDirectories.Skip( 1 ) ); + update[SettingNames.AdditionalRecorderPaths].NewValue = string.Join(", ", settings.TargetDirectories.Skip(1)); update[SettingNames.VideoRecorderDirectory].NewValue = settings.TargetDirectories.FirstOrDefault(); update[SettingNames.FileNamePattern].NewValue = settings.RecordingPattern; // Process - return ServerRuntime.Update( update.Values ); + return ServerRuntime.Update(update.Values); } /// @@ -456,7 +447,7 @@ public DirectorySettings ReadDirectory( string directory ) /// Unterscheidet zwischen den einzelnen Methoden. /// Die aktuellen Einstellungen. [HttpGet] - public SourceScanSettings ReadSoureScan( string scan ) + public SourceScanSettings ReadSoureScan(string scan) { // Validate ServerRuntime.TestAdminAccess(); @@ -469,11 +460,11 @@ public SourceScanSettings ReadSoureScan( string scan ) return new SourceScanSettings { - Hours = VCRConfiguration.Current.SourceListUpdateHoursAsArray.OrderBy( hour => hour ).ToArray(), - Threshold = join.HasValue ? (int) join.Value.TotalDays : default( int? ), + Hours = VCRConfiguration.Current.SourceListUpdateHoursAsArray.OrderBy(hour => hour).ToArray(), + Threshold = join.HasValue ? (int)join.Value.TotalDays : default(int?), MergeLists = VCRConfiguration.Current.MergeSourceListUpdateResult, Duration = VCRConfiguration.Current.SourceListUpdateDuration, - Interval = (interval != 0) ? interval : default( int? ), + Interval = (interval != 0) ? interval : default(int?), }; } @@ -484,26 +475,26 @@ public SourceScanSettings ReadSoureScan( string scan ) /// Die neuen Einstellungen. /// Das Ergebnis der Änderung. [HttpPut] - public bool? WriteSourceScan( string scan, [FromBody] SourceScanSettings settings ) + public bool? WriteSourceScan(string scan, [FromBody] SourceScanSettings settings) { // Check mode - if (settings.Interval == 0) + if (settings.Interval.GetValueOrDefault(0) == 0) { // Create settings - var disable = VCRConfiguration.Current.BeginUpdate( SettingNames.ScanInterval ); + var disable = VCRConfiguration.Current.BeginUpdate(SettingNames.ScanInterval); // Store disable[SettingNames.ScanInterval].NewValue = "0"; // Process - return ServerRuntime.Update( disable.Values ); + return ServerRuntime.Update(disable.Values); } // Check mode if (settings.Interval < 0) { // Create settings - var manual = VCRConfiguration.Current.BeginUpdate( SettingNames.ScanDuration, SettingNames.MergeScanResult, SettingNames.ScanInterval ); + var manual = VCRConfiguration.Current.BeginUpdate(SettingNames.ScanDuration, SettingNames.MergeScanResult, SettingNames.ScanInterval); // Store manual[SettingNames.MergeScanResult].NewValue = settings.MergeLists.ToString(); @@ -511,21 +502,21 @@ public SourceScanSettings ReadSoureScan( string scan ) manual[SettingNames.ScanInterval].NewValue = "-1"; // Process - return ServerRuntime.Update( manual.Values ); + return ServerRuntime.Update(manual.Values); } // Prepare to update - var update = VCRConfiguration.Current.BeginUpdate( SettingNames.ScanDuration, SettingNames.MergeScanResult, SettingNames.ScanInterval, SettingNames.ScanHours, SettingNames.ScanJoinThreshold ); + var update = VCRConfiguration.Current.BeginUpdate(SettingNames.ScanDuration, SettingNames.MergeScanResult, SettingNames.ScanInterval, SettingNames.ScanHours, SettingNames.ScanJoinThreshold); // Fill it - update[SettingNames.ScanHours].NewValue = string.Join( ", ", settings.Hours.Select( hour => hour.ToString() ) ); + update[SettingNames.ScanHours].NewValue = string.Join(", ", settings.Hours.Select(hour => hour.ToString())); update[SettingNames.ScanJoinThreshold].NewValue = settings.Threshold.ToString(); update[SettingNames.MergeScanResult].NewValue = settings.MergeLists.ToString(); update[SettingNames.ScanInterval].NewValue = settings.Interval.ToString(); update[SettingNames.ScanDuration].NewValue = settings.Duration.ToString(); // Process - return ServerRuntime.Update( update.Values ); + return ServerRuntime.Update(update.Values); } /// @@ -534,7 +525,7 @@ public SourceScanSettings ReadSoureScan( string scan ) /// Unterscheidet zwischen den einzelnen Methoden. /// Die aktuellen Einstellungen. [HttpGet] - public GuideSettings ReadGuide( string guide ) + public GuideSettings ReadGuide(string guide) { // Validate ServerRuntime.TestAdminAccess(); @@ -547,10 +538,10 @@ public GuideSettings ReadGuide( string guide ) return new GuideSettings { - Sources = VCRConfiguration.Current.ProgramGuideSourcesAsArray.OrderBy( name => name, StringComparer.InvariantCultureIgnoreCase ).ToArray(), - Hours = VCRConfiguration.Current.ProgramGuideUpdateHoursAsArray.OrderBy( hour => hour ).ToArray(), - Interval = interval.HasValue ? (int) interval.Value.TotalHours : default( int? ), - Threshold = join.HasValue ? (int) join.Value.TotalHours : default( int? ), + Sources = VCRConfiguration.Current.ProgramGuideSourcesAsArray.OrderBy(name => name, StringComparer.InvariantCultureIgnoreCase).ToArray(), + Hours = VCRConfiguration.Current.ProgramGuideUpdateHoursAsArray.OrderBy(hour => hour).ToArray(), + Interval = interval.HasValue ? (int)interval.Value.TotalHours : default(int?), + Threshold = join.HasValue ? (int)join.Value.TotalHours : default(int?), Duration = VCRConfiguration.Current.ProgramGuideUpdateDuration, WithUKGuide = VCRConfiguration.Current.EnableFreeSat, }; @@ -563,34 +554,34 @@ public GuideSettings ReadGuide( string guide ) /// Die neuen Einstellungen. /// Das Ergebnis der Änderung. [HttpPut] - public bool? WriteGuide( string guide, [FromBody] GuideSettings settings ) + public bool? WriteGuide(string guide, [FromBody] GuideSettings settings) { // Check mode if (settings.Duration < 1) { // Create settings - var disable = VCRConfiguration.Current.BeginUpdate( SettingNames.EPGDuration ); + var disable = VCRConfiguration.Current.BeginUpdate(SettingNames.EPGDuration); // Store disable[SettingNames.EPGDuration].NewValue = "0"; // Process - return ServerRuntime.Update( disable.Values ); + return ServerRuntime.Update(disable.Values); } // Prepare to update - var update = VCRConfiguration.Current.BeginUpdate( SettingNames.EPGDuration, SettingNames.EPGStations, SettingNames.EPGHours, SettingNames.EPGIncludeFreeSat, SettingNames.EPGInterval, SettingNames.EPGJoinThreshold ); + var update = VCRConfiguration.Current.BeginUpdate(SettingNames.EPGDuration, SettingNames.EPGStations, SettingNames.EPGHours, SettingNames.EPGIncludeFreeSat, SettingNames.EPGInterval, SettingNames.EPGJoinThreshold); // Fill it - update[SettingNames.EPGHours].NewValue = string.Join( ", ", settings.Hours.Select( hour => hour.ToString() ) ); + update[SettingNames.EPGHours].NewValue = string.Join(", ", settings.Hours.Select(hour => hour.ToString())); update[SettingNames.EPGIncludeFreeSat].NewValue = settings.WithUKGuide.ToString(); - update[SettingNames.EPGStations].NewValue = string.Join( ", ", settings.Sources ); + update[SettingNames.EPGStations].NewValue = string.Join(", ", settings.Sources); update[SettingNames.EPGJoinThreshold].NewValue = settings.Threshold.ToString(); update[SettingNames.EPGInterval].NewValue = settings.Interval.ToString(); update[SettingNames.EPGDuration].NewValue = settings.Duration.ToString(); // Process - return ServerRuntime.Update( update.Values ); + return ServerRuntime.Update(update.Values); } /// @@ -599,7 +590,7 @@ public GuideSettings ReadGuide( string guide ) /// Unterscheidet zwischen den einzelnen Methoden. /// Die aktuellen Einstellungen. [HttpGet] - public SecuritySettings ReadSecurity( string security ) + public SecuritySettings ReadSecurity(string security) { // Validate ServerRuntime.TestAdminAccess(); @@ -620,17 +611,17 @@ public SecuritySettings ReadSecurity( string security ) /// Die neuen Einstellungen. /// null bei Fehlern und ansonsten gesetzt, wenn ein Neustart des Dienstes ausgeführt wird. [HttpPut] - public bool? WriteSecurity( string security, [FromBody] SecuritySettings settings ) + public bool? WriteSecurity(string security, [FromBody] SecuritySettings settings) { // Prepare to update - var update = VCRConfiguration.Current.BeginUpdate( SettingNames.RequiredUserRole, SettingNames.RequiredAdminRole ); + var update = VCRConfiguration.Current.BeginUpdate(SettingNames.RequiredUserRole, SettingNames.RequiredAdminRole); // Change settings update[SettingNames.RequiredAdminRole].NewValue = settings.AdminRole; update[SettingNames.RequiredUserRole].NewValue = settings.UserRole; // Process - return ServerRuntime.Update( update.Values ); + return ServerRuntime.Update(update.Values); } /// @@ -639,7 +630,7 @@ public SecuritySettings ReadSecurity( string security ) /// Wird zur Unterscheidung der Methoden verwendet. /// Die aktuellen Einstellungen. [HttpGet] - public OtherSettings ReadOtherSettings( string other ) + public OtherSettings ReadOtherSettings(string other) { // Validate ServerRuntime.TestAdminAccess(); @@ -648,7 +639,7 @@ public OtherSettings ReadOtherSettings( string other ) return new OtherSettings { - DelayAfterForcedHibernation = (uint) VCRConfiguration.Current.DelayAfterForcedHibernation.TotalMinutes, + DelayAfterForcedHibernation = (uint)VCRConfiguration.Current.DelayAfterForcedHibernation.TotalMinutes, SuppressDelayAfterForcedHibernation = VCRConfiguration.Current.SuppressDelayAfterForcedHibernation, DisablePCRFromMPEG2 = VCRConfiguration.Current.DisablePCRFromMPEG2Generation, DisablePCRFromH264 = VCRConfiguration.Current.DisablePCRFromH264Generation, @@ -672,7 +663,7 @@ public OtherSettings ReadOtherSettings( string other ) /// Die neuen Einstellungen. /// Das Ergebnis der Änderung. [HttpPut] - public bool? WriteOther( string other, [FromBody] OtherSettings settings ) + public bool? WriteOther(string other, [FromBody] OtherSettings settings) { // Prepare to update var update = @@ -711,7 +702,7 @@ public OtherSettings ReadOtherSettings( string other ) update[SettingNames.UseSSL].NewValue = settings.UseSSL.ToString(); // Process - return ServerRuntime.Update( update.Values ); + return ServerRuntime.Update(update.Values); } } } diff --git a/VCR.NET/ServiceCore/RestWebApi/ConfigurationProfile.cs b/VCR.NET/ServiceCore/RestWebApi/ConfigurationProfile.cs index 6bc9b5b..fba37b4 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ConfigurationProfile.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ConfigurationProfile.cs @@ -58,8 +58,7 @@ private static uint ReadSetting( Profile profile, string settingName, uint setti return settingDefault; // Check value - uint value; - if (uint.TryParse( settings, out value )) + if (uint.TryParse(settings, out uint value)) return value; else return settingDefault; diff --git a/VCR.NET/ServiceCore/RestWebApi/EditController.cs b/VCR.NET/ServiceCore/RestWebApi/EditController.cs index 13a9623..29383f0 100644 --- a/VCR.NET/ServiceCore/RestWebApi/EditController.cs +++ b/VCR.NET/ServiceCore/RestWebApi/EditController.cs @@ -63,8 +63,7 @@ public JobScheduleInfo FindJob( string detail, string epg = null ) detail = detail.Substring( 1, 32 ) + Guid.NewGuid().ToString( "N" ); // Parameter analysieren - VCRJob job; - var schedule = ServerRuntime.ParseUniqueWebId( detail, out job ); + var schedule = ServerRuntime.ParseUniqueWebId(detail, out VCRJob job); // See if we have to initialize from program guide ProgramGuideEntry epgEntry = null; @@ -91,8 +90,7 @@ public JobScheduleInfo FindJob( string detail, string epg = null ) public void UpdateRecording( string detail, [FromBody] JobScheduleData data ) { // Parameter analysieren - VCRJob job; - var schedule = ServerRuntime.ParseUniqueWebId( detail, out job ); + var schedule = ServerRuntime.ParseUniqueWebId(detail, out VCRJob job); // Validate if (schedule == null) @@ -135,8 +133,7 @@ public void UpdateRecording( string detail, [FromBody] JobScheduleData data ) public void DeleteRecording( string detail ) { // Parameter analysieren - VCRJob job; - var schedule = ServerRuntime.ParseUniqueWebId( detail, out job ); + var schedule = ServerRuntime.ParseUniqueWebId(detail, out VCRJob job); // Validate if (schedule == null) @@ -162,8 +159,7 @@ public void DeleteRecording( string detail ) public string CreateNewRecording( string detail, [FromBody] JobScheduleData data ) { // Parameter analysieren - VCRJob job; - ServerRuntime.ParseUniqueWebId( detail + Guid.NewGuid().ToString( "N" ), out job ); + ServerRuntime.ParseUniqueWebId(detail + Guid.NewGuid().ToString("N"), out VCRJob job); // Validate if (job == null) diff --git a/VCR.NET/ServiceCore/RestWebApi/ExceptionController.cs b/VCR.NET/ServiceCore/RestWebApi/ExceptionController.cs index fb60456..7728729 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ExceptionController.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ExceptionController.cs @@ -22,10 +22,7 @@ public void ChangeException( string detail, string when, int startDelta, int dur { // Parse the date var date = new DateTime( long.Parse( when ), DateTimeKind.Utc ); - - // Split - Guid jobIdentifier, scheduleIdentifier; - ServerRuntime.ParseUniqueWebId( detail, out jobIdentifier, out scheduleIdentifier ); + ServerRuntime.ParseUniqueWebId( detail, out Guid jobIdentifier, out Guid scheduleIdentifier ); // Forward ServerRuntime.VCRServer.ChangeException( jobIdentifier, scheduleIdentifier, date, startDelta, durationDelta ); diff --git a/VCR.NET/ServiceCore/RestWebApi/GuideController.cs b/VCR.NET/ServiceCore/RestWebApi/GuideController.cs index ccba1d0..5511c66 100644 --- a/VCR.NET/ServiceCore/RestWebApi/GuideController.cs +++ b/VCR.NET/ServiceCore/RestWebApi/GuideController.cs @@ -1,10 +1,7 @@ -using System; -using System.Linq; -using System.Web.Http; -using JMS.DVB; -using JMS.DVBVCR.RecordingService.ProgramGuide; +using JMS.DVB; using JMS.DVBVCR.RecordingService.WebServer; - +using System; +using System.Web.Http; namespace JMS.DVBVCR.RecordingService.RestWebApi { @@ -21,19 +18,19 @@ public class GuideController : ApiController /// Informationen zum Abruf des Eintrags. /// Der gewünschte Eintrag. [HttpGet] - public GuideItem Find( string profile, string source, string pattern ) + public GuideItem Find(string profile, string source, string pattern) { // Check mode - var split = pattern.IndexOf( '-' ); + var split = pattern.IndexOf('-'); if (split < 0) return null; // Split pattern - var start = new DateTime( long.Parse( pattern.Substring( 0, split ) ) * Tools.UnixTimeFactor + Tools.UnixTimeBias, DateTimeKind.Utc ); - var end = new DateTime( long.Parse( pattern.Substring( split + 1 ) ) * Tools.UnixTimeFactor + Tools.UnixTimeBias, DateTimeKind.Utc ); + var start = new DateTime(long.Parse(pattern.Substring(0, split)) * Tools.UnixTimeFactor + Tools.UnixTimeBias, DateTimeKind.Utc); + var end = new DateTime(long.Parse(pattern.Substring(split + 1)) * Tools.UnixTimeFactor + Tools.UnixTimeBias, DateTimeKind.Utc); // Forward - return ServerRuntime.VCRServer.FindProgramGuideEntry( profile, SourceIdentifier.Parse( source ), start, end, GuideItem.Create ); + return ServerRuntime.VCRServer.FindProgramGuideEntry(profile, SourceIdentifier.Parse(source), start, end, GuideItem.Create); } /// @@ -42,11 +39,7 @@ public GuideItem Find( string profile, string source, string pattern ) /// Die Beschreibung des Filters. /// Die Liste aller passenden Einträge. [HttpPost] - public GuideItem[] Find( [FromBody] GuideFilter filter ) - { - // Forward - return ServerRuntime.VCRServer.GetProgramGuideEntries( filter, GuideFilter.Translate, GuideItem.Create ); - } + public GuideItem[] Find([FromBody] GuideFilter filter) => ServerRuntime.VCRServer.GetProgramGuideEntries(filter, GuideFilter.Translate, GuideItem.Create); /// /// Meldet alle Einträge der Programmzeitschrift zu einem Geräteprofil. @@ -55,11 +48,7 @@ public GuideItem[] Find( [FromBody] GuideFilter filter ) /// Die Beschreibung des Filters. /// Die Anzahl aller passenden Einträge. [HttpPost] - public int Count( string countOnly, [FromBody] GuideFilter filter ) - { - // Forward - return ServerRuntime.VCRServer.GetProgramGuideEntries( filter, GuideFilter.Translate ); - } + public int Count(string countOnly, [FromBody] GuideFilter filter) => ServerRuntime.VCRServer.GetProgramGuideEntries(filter, GuideFilter.Translate); /// @@ -68,10 +57,6 @@ public int Count( string countOnly, [FromBody] GuideFilter filter ) /// Der Name des Profils. /// Die gewünschten Informationen. [HttpGet] - public GuideInfo GetInfo( string detail ) - { - // Forward - return ServerRuntime.VCRServer.GetProgramGuideInformation( detail, GuideInfo.Create ); - } + public GuideInfo GetInfo(string detail) => ServerRuntime.VCRServer.GetProgramGuideInformation(detail, GuideInfo.Create); } } diff --git a/VCR.NET/ServiceCore/RestWebApi/GuideItem.cs b/VCR.NET/ServiceCore/RestWebApi/GuideItem.cs index fbcb843..8110640 100644 --- a/VCR.NET/ServiceCore/RestWebApi/GuideItem.cs +++ b/VCR.NET/ServiceCore/RestWebApi/GuideItem.cs @@ -30,7 +30,7 @@ public string StartTimeISO [DataMember( Name = "duration" )] public int DurationInSeconds { - get { return (int) Math.Round( Duration.TotalSeconds ); } + get { return (int)Math.Round( Duration.TotalSeconds ); } set { Duration = TimeSpan.FromSeconds( value ); } } @@ -117,7 +117,7 @@ public static GuideItem Create( ProgramGuideEntry entry, string profileName ) return new GuideItem { - Identifier = string.Format( "{0}:{1}:{2}", entry.StartTime.Ticks, profileName, SourceIdentifier.ToString( entry.Source ).Replace( " ", "" ) ), + Identifier = $"{entry.StartTime.Ticks}:{profileName}:{SourceIdentifier.ToString( entry.Source ).Replace( " ", "" )}", Station = (source == null) ? entry.StationName : source.GetUniqueName(), Duration = TimeSpan.FromSeconds( entry.Duration ), Categories = entry.Categories.ToArray(), diff --git a/VCR.NET/ServiceCore/RestWebApi/HibernateController.cs b/VCR.NET/ServiceCore/RestWebApi/HibernateController.cs index 7562c75..04981d7 100644 --- a/VCR.NET/ServiceCore/RestWebApi/HibernateController.cs +++ b/VCR.NET/ServiceCore/RestWebApi/HibernateController.cs @@ -1,5 +1,5 @@ -using System.Web.Http; -using JMS.DVBVCR.RecordingService.WebServer; +using JMS.DVBVCR.RecordingService.WebServer; +using System.Web.Http; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -14,21 +14,13 @@ public class HibernateController : ApiController /// /// Dient zur Unterscheidung der Methoden. [HttpPost] - public void ResetPendingHibernation( string reset ) - { - // Forward - ServerRuntime.VCRServer.ResetPendingHibernation(); - } + public void ResetPendingHibernation( string reset ) => ServerRuntime.VCRServer.ResetPendingHibernation(); /// /// Versucht, den Schlafzustand auszulösen. /// /// Dient zur Unterscheidung der Methoden [HttpPost] - public void TryHibernate( string hibernate ) - { - // Forward - ServerRuntime.VCRServer.TryHibernateIgnoringInteractiveUsers(); - } + public void TryHibernate( string hibernate ) => ServerRuntime.VCRServer.TryHibernateIgnoringInteractiveUsers(); } } diff --git a/VCR.NET/ServiceCore/RestWebApi/InfoController.cs b/VCR.NET/ServiceCore/RestWebApi/InfoController.cs index 6275f1d..ddcf509 100644 --- a/VCR.NET/ServiceCore/RestWebApi/InfoController.cs +++ b/VCR.NET/ServiceCore/RestWebApi/InfoController.cs @@ -1,4 +1,5 @@ -using System; +using JMS.DVBVCR.RecordingService.WebServer; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -6,7 +7,6 @@ using System.Runtime.InteropServices; using System.Text; using System.Web.Http; -using JMS.DVBVCR.RecordingService.WebServer; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -73,7 +73,7 @@ private static string InstalledVersion // Retrieve if (MsiGetProductInfo( productCode.ToString(), "VersionString", buffer, ref bufferSize ) == 0) - _InstalledVersion = new string( buffer, 0, checked( (int) bufferSize ) ); + _InstalledVersion = new string( buffer, 0, checked((int) bufferSize) ); } } catch (Exception e) @@ -124,12 +124,8 @@ public InfoService VersionInformation() /// Wird zur Unterscheidung der Methoden verwendet. /// Die gewünschte Liste. [HttpGet] - public string[] GetRecordingDirectories( string directories ) - { - // First is default - return VCRConfiguration.Current.TargetDirectoriesNames.SelectMany( ScanDirectory ).ToArray(); - } - + public string[] GetRecordingDirectories( string directories ) => VCRConfiguration.Current.TargetDirectoriesNames.SelectMany( ScanDirectory ).ToArray(); + /// /// Meldet alle Aufträge. /// diff --git a/VCR.NET/ServiceCore/RestWebApi/InfoJob.cs b/VCR.NET/ServiceCore/RestWebApi/InfoJob.cs index 470f677..5be9855 100644 --- a/VCR.NET/ServiceCore/RestWebApi/InfoJob.cs +++ b/VCR.NET/ServiceCore/RestWebApi/InfoJob.cs @@ -1,8 +1,8 @@ -using System; +using JMS.DVBVCR.RecordingService.Persistence; +using JMS.DVBVCR.RecordingService.WebServer; +using System; using System.Linq; using System.Runtime.Serialization; -using JMS.DVBVCR.RecordingService.Persistence; -using JMS.DVBVCR.RecordingService.WebServer; namespace JMS.DVBVCR.RecordingService.RestWebApi diff --git a/VCR.NET/ServiceCore/RestWebApi/InfoSchedule.cs b/VCR.NET/ServiceCore/RestWebApi/InfoSchedule.cs index 21acfdd..0d74173 100644 --- a/VCR.NET/ServiceCore/RestWebApi/InfoSchedule.cs +++ b/VCR.NET/ServiceCore/RestWebApi/InfoSchedule.cs @@ -1,8 +1,8 @@ -using System; +using JMS.DVBVCR.RecordingService.Persistence; +using JMS.DVBVCR.RecordingService.WebServer; +using System; using System.Globalization; using System.Runtime.Serialization; -using JMS.DVBVCR.RecordingService.Persistence; -using JMS.DVBVCR.RecordingService.WebServer; namespace JMS.DVBVCR.RecordingService.RestWebApi diff --git a/VCR.NET/ServiceCore/RestWebApi/JobScheduleData.cs b/VCR.NET/ServiceCore/RestWebApi/JobScheduleData.cs index fe39925..2f28ceb 100644 --- a/VCR.NET/ServiceCore/RestWebApi/JobScheduleData.cs +++ b/VCR.NET/ServiceCore/RestWebApi/JobScheduleData.cs @@ -1,7 +1,7 @@ -using System; -using System.Runtime.Serialization; -using JMS.DVBVCR.RecordingService.Persistence; +using JMS.DVBVCR.RecordingService.Persistence; using JMS.DVBVCR.RecordingService.ProgramGuide; +using System; +using System.Runtime.Serialization; namespace JMS.DVBVCR.RecordingService.RestWebApi diff --git a/VCR.NET/ServiceCore/RestWebApi/PlanActivity.cs b/VCR.NET/ServiceCore/RestWebApi/PlanActivity.cs index 7b461eb..e45bd92 100644 --- a/VCR.NET/ServiceCore/RestWebApi/PlanActivity.cs +++ b/VCR.NET/ServiceCore/RestWebApi/PlanActivity.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Runtime.Serialization; -using JMS.DVB; +using JMS.DVB; using JMS.DVB.Algorithms.Scheduler; using JMS.DVBVCR.RecordingService.Persistence; using JMS.DVBVCR.RecordingService.Planning; using JMS.DVBVCR.RecordingService.WebServer; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Runtime.Serialization; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -258,10 +258,10 @@ public static PlanActivity Create( IScheduleInformation schedule, PlanContext co var end = time.End; var activity = new PlanActivity - { - IsHidden = (schedule.Resource == null), - IsLate = schedule.StartsLate, - }; + { + IsHidden = (schedule.Resource == null), + IsLate = schedule.StartsLate, + }; // May need some correction if (runningInfo != null) @@ -333,7 +333,7 @@ public static PlanActivity Create( IScheduleInformation schedule, PlanContext co } // Copy station name - if (source != null) + if (source?.Source != null) { // Remember activity.Source = SourceIdentifier.ToString( source.Source ).Replace( " ", "" ); diff --git a/VCR.NET/ServiceCore/RestWebApi/PlanController.cs b/VCR.NET/ServiceCore/RestWebApi/PlanController.cs index 961631c..ae9835c 100644 --- a/VCR.NET/ServiceCore/RestWebApi/PlanController.cs +++ b/VCR.NET/ServiceCore/RestWebApi/PlanController.cs @@ -1,9 +1,9 @@ -using System; +using JMS.DVB; +using JMS.DVBVCR.RecordingService.WebServer; +using System; using System.Globalization; using System.Linq; using System.Web.Http; -using JMS.DVB; -using JMS.DVBVCR.RecordingService.WebServer; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -23,13 +23,11 @@ public class PlanController : ApiController public PlanActivity[] GetPlan( string limit, string end ) { // Get the limit - int maximum; - if (!int.TryParse( limit, out maximum ) || (maximum <= 0)) + if (!int.TryParse(limit, out int maximum) || (maximum <= 0)) maximum = 1000; // Get the date - DateTime endTime; - if (!DateTime.TryParse( end, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out endTime )) + if (!DateTime.TryParse(end, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out DateTime endTime)) endTime = DateTime.MaxValue; // Route from Web AppDomain into service AppDomain @@ -52,8 +50,7 @@ public PlanActivity[] GetPlan( string limit, string end ) public PlanActivityMobile[] GetPlanMobile( string limit, string mobile ) { // Get the limit - int maximum; - if (!int.TryParse( limit, out maximum ) || (maximum <= 0)) + if (!int.TryParse(limit, out int maximum) || (maximum <= 0)) maximum = 1000; // Use helper @@ -107,22 +104,14 @@ public PlanCurrentMobile[] GetCurrent( string mobile ) /// /// Wird zur Unterscheidung der Methoden verwendet. [HttpPost] - public void StartSourceScan( string sourceScan ) - { - // Forward - ServerRuntime.VCRServer.ForceSoureListUpdate(); - } + public void StartSourceScan( string sourceScan ) => ServerRuntime.VCRServer.ForceSoureListUpdate(); /// /// Fordert die Aktualisierung der Programmzeitschrift an. /// /// Wird zur Unterscheidung der Methoden verwendet. [HttpPost] - public void StartGuideUpdate( string guideUpdate ) - { - // Forward - ServerRuntime.VCRServer.ForceProgramGuideUpdate(); - } + public void StartGuideUpdate( string guideUpdate ) => ServerRuntime.VCRServer.ForceProgramGuideUpdate(); /// /// Ändert den Netzwerkversand. diff --git a/VCR.NET/ServiceCore/RestWebApi/PlanCurrent.cs b/VCR.NET/ServiceCore/RestWebApi/PlanCurrent.cs index 3dd00a4..78a8d3b 100644 --- a/VCR.NET/ServiceCore/RestWebApi/PlanCurrent.cs +++ b/VCR.NET/ServiceCore/RestWebApi/PlanCurrent.cs @@ -1,14 +1,14 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Runtime.Serialization; -using JMS.DVB; +using JMS.DVB; using JMS.DVB.Algorithms.Scheduler; using JMS.DVBVCR.RecordingService.Persistence; using JMS.DVBVCR.RecordingService.Planning; using JMS.DVBVCR.RecordingService.Status; using JMS.DVBVCR.RecordingService.WebServer; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Runtime.Serialization; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -170,7 +170,7 @@ public class PlanCurrent : PlanCurrentMobile [DataMember( Name = "remainingMinutes" )] public uint RemainingTimeInMinutes { - get { return (PlanIdentifier == null) ? 0 : checked( (uint) Math.Max( 0, Math.Round( (StartTime + Duration - DateTime.UtcNow).TotalMinutes ) ) ); } + get { return (PlanIdentifier == null) ? 0 : checked((uint) Math.Max( 0, Math.Round( (StartTime + Duration - DateTime.UtcNow).TotalMinutes ) )); } set { } } @@ -218,7 +218,7 @@ public static PlanCurrent[] Create( FullInfo active, VCRServer server ) { // Validate if (active == null) - throw new ArgumentNullException( "active" ); + throw new ArgumentNullException( nameof( active ) ); // Validate var recording = active.Recording; @@ -254,9 +254,9 @@ public static PlanCurrent[] Create( FullInfo active, VCRServer server ) // Finish if (VCRJob.ProgramGuideName.Equals( sourceName )) - current.SizeHint = string.Format( "{0:N0} Einträge", recording.TotalSize ); + current.SizeHint = $"{recording.TotalSize:N0} Einträge"; else if (VCRJob.SourceScanName.Equals( sourceName )) - current.SizeHint = string.Format( "{0:N0} Quellen", recording.TotalSize ); + current.SizeHint = $"{recording.TotalSize:N0} Quellen"; else if (VCRJob.ZappingName.Equals( sourceName )) current.SizeHint = GetSizeHint( recording.TotalSize ); else @@ -298,9 +298,9 @@ public static string GetSizeHint( decimal totalSize ) { // Check mode if (totalSize < 10000m) - return string.Format( "{0:N0} kBytes", totalSize ); + return $"{totalSize:N0} kBytes"; else - return string.Format( "{0:N0} MBytes", Math.Round( totalSize / 1024m ) ); + return $"{Math.Round( totalSize / 1024m ):N0} MBytes"; } /// @@ -395,10 +395,6 @@ public static PlanCurrent Create( IScheduleInformation plan, PlanContext context /// /// Der Name des Geräteprofils. /// Die zugehörige Beschreibung. - public static PlanCurrent Create( string profileName ) - { - // Create - return new PlanCurrent { ProfileName = profileName, IsIdle = true }; - } + public static PlanCurrent Create( string profileName ) => new PlanCurrent { ProfileName = profileName, IsIdle = true }; } } diff --git a/VCR.NET/ServiceCore/RestWebApi/PlanException.cs b/VCR.NET/ServiceCore/RestWebApi/PlanException.cs index a17d5af..dd2d6fc 100644 --- a/VCR.NET/ServiceCore/RestWebApi/PlanException.cs +++ b/VCR.NET/ServiceCore/RestWebApi/PlanException.cs @@ -1,7 +1,7 @@ -using System; +using JMS.DVBVCR.RecordingService.Persistence; +using System; using System.Globalization; using System.Runtime.Serialization; -using JMS.DVBVCR.RecordingService.Persistence; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -106,9 +106,9 @@ public static PlanException Create( VCRScheduleException exception, VCRSchedule { // Validate if (exception == null) - throw new ArgumentNullException( "exception" ); + throw new ArgumentNullException( nameof( exception ) ); if (schedule == null) - throw new ArgumentNullException( "schedule" ); + throw new ArgumentNullException( nameof( schedule ) ); // Forward return new PlanException( exception, schedule ); diff --git a/VCR.NET/ServiceCore/RestWebApi/ProfileController.cs b/VCR.NET/ServiceCore/RestWebApi/ProfileController.cs index 6909045..dfe5a2a 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ProfileController.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ProfileController.cs @@ -1,9 +1,9 @@ -using System; +using JMS.DVB; +using JMS.DVBVCR.RecordingService.WebServer; +using System; using System.Globalization; using System.Linq; using System.Web.Http; -using JMS.DVB; -using JMS.DVBVCR.RecordingService.WebServer; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -36,11 +36,7 @@ public ProfileInfo[] ListProfiles() /// Der Name des zu verwendenden Geräteprofils. /// Die gewünschte Liste von Sendern. [HttpGet] - public ProfileSource[] FindSources( string detail ) - { - // Forward to other application domain - return ServerRuntime.VCRServer.GetSources( detail, true, true, ProfileSource.Create ); - } + public ProfileSource[] FindSources( string detail ) => ServerRuntime.VCRServer.GetSources( detail, true, true, ProfileSource.Create ); /// /// Verändert den Endzeitpunkt. @@ -57,7 +53,7 @@ public void SetNewEndTime( string detail, bool disableHibernate, string schedule var end = DateTime.Parse( endTime, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind ); // Forward - ServerRuntime.VCRServer.ChangeRecordingStreamEndTime( detail, scheduleIdentifier, end, disableHibernate ); + ServerRuntime.VCRServer.ChangeRecordingStreamEndTime( detail, scheduleIdentifier, end, disableHibernate ); } /// diff --git a/VCR.NET/ServiceCore/RestWebApi/ProfileInfo.cs b/VCR.NET/ServiceCore/RestWebApi/ProfileInfo.cs index bd94734..bfff7b7 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ProfileInfo.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ProfileInfo.cs @@ -26,7 +26,7 @@ public static ProfileInfo Create( ProfileState profile ) { // Validate if (profile == null) - throw new ArgumentNullException( "profile" ); + throw new ArgumentNullException( nameof( profile ) ); // Create return new ProfileInfo { Name = profile.ProfileName }; diff --git a/VCR.NET/ServiceCore/RestWebApi/ProfileJobInfo.cs b/VCR.NET/ServiceCore/RestWebApi/ProfileJobInfo.cs index 12d56e9..e12c401 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ProfileJobInfo.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ProfileJobInfo.cs @@ -1,6 +1,6 @@ -using System; +using JMS.DVBVCR.RecordingService.Persistence; +using System; using System.Runtime.Serialization; -using JMS.DVBVCR.RecordingService.Persistence; namespace JMS.DVBVCR.RecordingService.RestWebApi diff --git a/VCR.NET/ServiceCore/RestWebApi/ProfileSource.cs b/VCR.NET/ServiceCore/RestWebApi/ProfileSource.cs index 2840508..40e0994 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ProfileSource.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ProfileSource.cs @@ -1,6 +1,6 @@ -using System; +using JMS.DVB; +using System; using System.Runtime.Serialization; -using JMS.DVB; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -22,10 +22,6 @@ public class ProfileSource : SourceInformation /// Führt individuelle Initialisierungen aus. /// /// Die Informationen zur Quelle. - protected override void OnCreate( Station station ) - { - // If it's not definitly a radio station we guess it's television - IsTVStation = (station.SourceType != SourceTypes.Radio); - } + protected override void OnCreate( Station station ) => IsTVStation = (station.SourceType != SourceTypes.Radio); } } diff --git a/VCR.NET/ServiceCore/RestWebApi/ProtocolController.cs b/VCR.NET/ServiceCore/RestWebApi/ProtocolController.cs index 34647c9..0ea1942 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ProtocolController.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ProtocolController.cs @@ -1,7 +1,7 @@ -using System; +using JMS.DVBVCR.RecordingService.WebServer; +using System; using System.Globalization; using System.Web.Http; -using JMS.DVBVCR.RecordingService.WebServer; namespace JMS.DVBVCR.RecordingService.RestWebApi diff --git a/VCR.NET/ServiceCore/RestWebApi/ProtocolEntry.cs b/VCR.NET/ServiceCore/RestWebApi/ProtocolEntry.cs index 24065d0..cab536a 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ProtocolEntry.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ProtocolEntry.cs @@ -1,9 +1,9 @@ -using System; +using JMS.DVBVCR.RecordingService.Persistence; +using System; using System.Globalization; using System.IO; using System.Linq; using System.Runtime.Serialization; -using JMS.DVBVCR.RecordingService.Persistence; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -93,9 +93,9 @@ public static ProtocolEntry Create( VCRRecordingInfo entry ) // Finish if (VCRJob.ProgramGuideName.Equals( sourceName )) - protocol.SizeHint = string.Format( "{0:N0} Einträge", entry.TotalSize ); + protocol.SizeHint = $"{entry.TotalSize:N0} Einträge"; else if (VCRJob.SourceScanName.Equals( sourceName )) - protocol.SizeHint = string.Format( "{0:N0} Quellen", entry.TotalSize ); + protocol.SizeHint = $"{entry.TotalSize:N0} Quellen"; else protocol.SizeHint = PlanCurrent.GetSizeHint( entry.TotalSize ); diff --git a/VCR.NET/ServiceCore/RestWebApi/SourceInformation.cs b/VCR.NET/ServiceCore/RestWebApi/SourceInformation.cs index 5c0693b..81d7643 100644 --- a/VCR.NET/ServiceCore/RestWebApi/SourceInformation.cs +++ b/VCR.NET/ServiceCore/RestWebApi/SourceInformation.cs @@ -1,6 +1,6 @@ -using System; +using JMS.DVB; +using System; using System.Runtime.Serialization; -using JMS.DVB; namespace JMS.DVBVCR.RecordingService.RestWebApi diff --git a/VCR.NET/ServiceCore/RestWebApi/UserProfile.cs b/VCR.NET/ServiceCore/RestWebApi/UserProfile.cs index 1fc86cb..543a111 100644 --- a/VCR.NET/ServiceCore/RestWebApi/UserProfile.cs +++ b/VCR.NET/ServiceCore/RestWebApi/UserProfile.cs @@ -1,7 +1,6 @@ -using System.Linq; +using JMS.DVBVCR.RecordingService.WebServer; +using System.Linq; using System.Runtime.Serialization; -using System.Web; -using JMS.DVBVCR.RecordingService.WebServer; namespace JMS.DVBVCR.RecordingService.RestWebApi diff --git a/VCR.NET/ServiceCore/RestWebApi/UserProfileController.cs b/VCR.NET/ServiceCore/RestWebApi/UserProfileController.cs index f919122..9cafc1b 100644 --- a/VCR.NET/ServiceCore/RestWebApi/UserProfileController.cs +++ b/VCR.NET/ServiceCore/RestWebApi/UserProfileController.cs @@ -1,5 +1,5 @@ -using System.Web.Http; -using JMS.DVBVCR.RecordingService.WebServer; +using JMS.DVBVCR.RecordingService.WebServer; +using System.Web.Http; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -14,11 +14,7 @@ public class UserProfileController : ApiController /// /// Die Einstellungen des Anwenders. [HttpGet] - public UserProfile GetCurrentProfile() - { - // Report - return UserProfile.Create(); - } + public UserProfile GetCurrentProfile() => UserProfile.Create(); /// /// Aktualisiert die Daten des Geräteprofils. diff --git a/VCR.NET/ServiceCore/RestWebApi/ZappingController.cs b/VCR.NET/ServiceCore/RestWebApi/ZappingController.cs index b7a97da..5404bce 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ZappingController.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ZappingController.cs @@ -1,6 +1,6 @@ -using System.Web.Http; -using JMS.DVB; +using JMS.DVB; using JMS.DVBVCR.RecordingService.WebServer; +using System.Web.Http; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -17,11 +17,7 @@ public class ZappingController : ApiController /// Der Name des zu verwendenden Geräteprofils. /// Der Zustand auf dem gewählten Geräteprofil. [HttpGet] - public ZappingStatus GetCurrentStatus( string detail ) - { - // Process - return ServerRuntime.VCRServer.LiveModeOperation( detail, true, null, null, ZappingStatus.Create ); - } + public ZappingStatus GetCurrentStatus( string detail ) => ServerRuntime.VCRServer.LiveModeOperation( detail, true, null, null, ZappingStatus.Create ); /// /// Ermittelt alle verfügbaren Sender. @@ -31,11 +27,7 @@ public ZappingStatus GetCurrentStatus( string detail ) /// Gesetzt, wenn Radiosender berücksichtigt werden sollen. /// Die gewünschte Liste von Sendern. [HttpGet] - public ZappingSource[] FindSources( string detail, bool tv, bool radio ) - { - // Forward to other application domain - return ServerRuntime.VCRServer.GetSources( detail, tv, radio, ZappingSource.Create ); - } + public ZappingSource[] FindSources( string detail, bool tv, bool radio ) => ServerRuntime.VCRServer.GetSources( detail, tv, radio, ZappingSource.Create ); /// /// Aktiviert eine neue Sitzung. @@ -44,11 +36,7 @@ public ZappingSource[] FindSources( string detail, bool tv, bool radio ) /// Legt fest, wohin die Nutzdaten zu senden sind. /// Der Zustand auf dem gewählten Geräteprofil. [HttpPost] - public ZappingStatus Connect( string detail, string target ) - { - // Process - return ServerRuntime.VCRServer.LiveModeOperation( detail, true, target, null, ZappingStatus.Create ); - } + public ZappingStatus Connect( string detail, string target ) => ServerRuntime.VCRServer.LiveModeOperation( detail, true, target, null, ZappingStatus.Create ); /// /// Deaktiviert eine Sitzung. @@ -56,11 +44,7 @@ public ZappingStatus Connect( string detail, string target ) /// Der Name des zu verwendenden Geräteprofils. /// Der Zustand auf dem gewählten Geräteprofil. [HttpDelete] - public ZappingStatus Disconnect( string detail ) - { - // Process - return ServerRuntime.VCRServer.LiveModeOperation( detail, false, null, null, ZappingStatus.Create ); - } + public ZappingStatus Disconnect( string detail ) => ServerRuntime.VCRServer.LiveModeOperation( detail, false, null, null, ZappingStatus.Create ); /// /// Wählt einen Quelle aus. @@ -69,10 +53,6 @@ public ZappingStatus Disconnect( string detail ) /// Die gewünschte Quelle als Tripel analog zur Textdarstellung von . /// Der Zustand auf dem gewählten Geräteprofil. [HttpPut] - public ZappingStatus Tune( string detail, string source ) - { - // Process - return ServerRuntime.VCRServer.LiveModeOperation( detail, true, null, SourceIdentifier.Parse( source ), ZappingStatus.Create ); - } + public ZappingStatus Tune( string detail, string source ) => ServerRuntime.VCRServer.LiveModeOperation( detail, true, null, SourceIdentifier.Parse( source ), ZappingStatus.Create ); } } diff --git a/VCR.NET/ServiceCore/RestWebApi/ZappingService.cs b/VCR.NET/ServiceCore/RestWebApi/ZappingService.cs index 8fa0ea5..baa6ec4 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ZappingService.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ZappingService.cs @@ -1,7 +1,7 @@ -using System; -using System.Runtime.Serialization; -using JMS.DVB; +using JMS.DVB; using JMS.DVB.CardServer; +using System; +using System.Runtime.Serialization; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -47,10 +47,9 @@ private static int GetServiceIndex( string uniqueName ) return -1; // Get the part - uint result; - if (uint.TryParse( uniqueName.Substring( 0, i ), out result )) + if (uint.TryParse(uniqueName.Substring(0, i), out uint result)) if (result < int.MaxValue) - return (int) result; + return (int)result; else return -1; else @@ -66,7 +65,7 @@ public static ZappingService Create( ServiceInformation service ) { // Validate if (service == null) - throw new ArgumentNullException( "service" ); + throw new ArgumentNullException( nameof( service ) ); // Create new return diff --git a/VCR.NET/ServiceCore/RestWebApi/ZappingSource.cs b/VCR.NET/ServiceCore/RestWebApi/ZappingSource.cs index 5bd0e2c..df24280 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ZappingSource.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ZappingSource.cs @@ -1,6 +1,6 @@ -using System; +using JMS.DVB; +using System; using System.Runtime.Serialization; -using JMS.DVB; namespace JMS.DVBVCR.RecordingService.RestWebApi @@ -22,10 +22,6 @@ public class ZappingSource : SourceInformation /// Führt individuelle Initialisierungen aus. /// /// Die Informationen zur Quelle. - protected override void OnCreate( Station station ) - { - // Finish - Source = SourceIdentifier.ToString( station ).Replace( " ", "" ); - } + protected override void OnCreate( Station station ) => Source = SourceIdentifier.ToString( station ).Replace( " ", "" ); } } diff --git a/VCR.NET/ServiceCore/RestWebApi/ZappingStatus.cs b/VCR.NET/ServiceCore/RestWebApi/ZappingStatus.cs index 591b4c9..508317b 100644 --- a/VCR.NET/ServiceCore/RestWebApi/ZappingStatus.cs +++ b/VCR.NET/ServiceCore/RestWebApi/ZappingStatus.cs @@ -1,8 +1,8 @@ -using System; +using JMS.DVB; +using JMS.DVB.CardServer; +using System; using System.Linq; using System.Runtime.Serialization; -using JMS.DVB; -using JMS.DVB.CardServer; namespace JMS.DVBVCR.RecordingService.RestWebApi diff --git a/VCR.NET/ServiceCore/ServiceCore.csproj b/VCR.NET/ServiceCore/ServiceCore.csproj index da5bd7f..4fed2e9 100644 --- a/VCR.NET/ServiceCore/ServiceCore.csproj +++ b/VCR.NET/ServiceCore/ServiceCore.csproj @@ -70,41 +70,41 @@ - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\Administration PlugIns\JMS.DVB.Administration.Profiles.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\Administration PlugIns\JMS.DVB.Administration.Profiles.dll False False - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\RunTime\JMS.DVB.Algorithms.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\RunTime\JMS.DVB.Algorithms.dll False False - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\RunTime\JMS.DVB.CardServerCore.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\RunTime\JMS.DVB.CardServerCore.dll False False - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\GAC\JMS.DVB.Common.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\GAC\JMS.DVB.Common.dll False - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\RunTime\JMS.DVB.HardwareAbstraction.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\RunTime\JMS.DVB.HardwareAbstraction.dll False False - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\RunTime\JMS.DVB.SITables.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\RunTime\JMS.DVB.SITables.dll False False - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\RunTime\JMS.DVB.SourceManagement.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\RunTime\JMS.DVB.SourceManagement.dll False False - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\RunTime\JMS.DVB.TS.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\RunTime\JMS.DVB.TS.dll False False @@ -112,9 +112,9 @@ True ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - False - ..\packages\Newtonsoft.Json.6.0.7\lib\net45\Newtonsoft.Json.dll + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + True @@ -127,45 +127,54 @@ True - + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll False - ..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll + True + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll False - ..\packages\Microsoft.AspNet.WebPages.3.2.2\lib\net45\System.Web.Helpers.dll + True - + + ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll False - ..\packages\Microsoft.AspNet.WebApi.Core.5.2.2\lib\net45\System.Web.Http.dll + True - + + ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll False - ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.2\lib\net45\System.Web.Http.WebHost.dll + True - + + ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll False - ..\packages\Microsoft.AspNet.Mvc.5.2.2\lib\net45\System.Web.Mvc.dll + True + ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll False - ..\packages\Microsoft.AspNet.Razor.3.2.2\lib\net45\System.Web.Razor.dll + True + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll False - ..\packages\Microsoft.AspNet.WebPages.3.2.2\lib\net45\System.Web.WebPages.dll + True + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll False - ..\packages\Microsoft.AspNet.WebPages.3.2.2\lib\net45\System.Web.WebPages.Deployment.dll + True + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll False - ..\packages\Microsoft.AspNet.WebPages.3.2.2\lib\net45\System.Web.WebPages.Razor.dll + True diff --git a/VCR.NET/ServiceCore/Status/FullInfo.cs b/VCR.NET/ServiceCore/Status/FullInfo.cs index 22b9743..23a9015 100644 --- a/VCR.NET/ServiceCore/Status/FullInfo.cs +++ b/VCR.NET/ServiceCore/Status/FullInfo.cs @@ -1,7 +1,7 @@ +using JMS.DVBVCR.RecordingService.Persistence; using System; using System.Collections.Generic; using System.Xml.Serialization; -using JMS.DVBVCR.RecordingService.Persistence; namespace JMS.DVBVCR.RecordingService.Status diff --git a/VCR.NET/ServiceCore/Status/ScheduleInfo.cs b/VCR.NET/ServiceCore/Status/ScheduleInfo.cs index 3a3d989..7aefbcb 100644 --- a/VCR.NET/ServiceCore/Status/ScheduleInfo.cs +++ b/VCR.NET/ServiceCore/Status/ScheduleInfo.cs @@ -1,8 +1,8 @@ +using JMS.DVB; +using JMS.DVBVCR.RecordingService.Persistence; using System; using System.Collections.Generic; using System.Xml.Serialization; -using JMS.DVB; -using JMS.DVBVCR.RecordingService.Persistence; namespace JMS.DVBVCR.RecordingService.Status @@ -74,9 +74,8 @@ public static ScheduleInfo Create( VCRRecordingInfo recording, Dictionary GetHourList( string hours ) yield break; // Process all - uint hour; - foreach (var hourAsString in hours.Split( ',' )) - if (uint.TryParse( hourAsString.Trim(), out hour )) + foreach (var hourAsString in hours.Split(',')) + if (uint.TryParse(hourAsString.Trim(), out uint hour)) if ((hour >= 0) && (hour <= 23)) yield return hour; } diff --git a/VCR.NET/ServiceCore/VCRConfiguration.cs b/VCR.NET/ServiceCore/VCRConfiguration.cs index 250755b..53e4b1a 100644 --- a/VCR.NET/ServiceCore/VCRConfiguration.cs +++ b/VCR.NET/ServiceCore/VCRConfiguration.cs @@ -26,7 +26,7 @@ public abstract class SettingDescription : MarshalByRefObject, ICloneable /// /// Meldet den Namen der Einstellung. /// - public SettingNames Name { get; private set; } + public SettingNames Name { get; } /// /// Ein eventuell veränderter Wert. @@ -37,7 +37,7 @@ public abstract class SettingDescription : MarshalByRefObject, ICloneable /// Erzeugt eine neue Beschreibung. /// /// Der Name der Beschreibung. - internal SettingDescription( SettingNames name ) + internal SettingDescription(SettingNames name) { // Remember Name = name; @@ -47,61 +47,41 @@ internal SettingDescription( SettingNames name ) /// Liest den Namen der Einstellung. /// /// Der Wert der Einstellung als Zeichenkette. - public virtual object ReadValue() - { - // Forward - return GetCurrentValue(); - } + public virtual object ReadValue() => GetCurrentValue(); /// /// Liest den Namen der Einstellung. /// /// Der Wert der Einstellung als Zeichenkette. - public string GetCurrentValue() - { - // Report - return (string) ReadRawValue( Tools.ApplicationConfiguration ); - } + public string GetCurrentValue() => (string)ReadRawValue(Tools.ApplicationConfiguration); /// /// Liest den Namen der Einstellung. /// /// Die zu verwendende Konfiguration. /// Der Wert der Einstellung als Zeichenkette. - private object ReadRawValue( Configuration configuration ) - { - // Load the setting - KeyValueConfigurationElement setting = configuration.AppSettings.Settings[Name.ToString()]; - - // Not found - if (null == setting) - return null; - else if (null == setting.Value) - return null; - else - return setting.Value.Trim(); - } + private object ReadRawValue(Configuration configuration) => configuration.AppSettings.Settings[Name.ToString()]?.Value?.Trim(); /// /// Aktualisiert einen Konfigurationswert. /// /// /// - internal bool Update( Configuration newConfiguration ) + internal bool Update(Configuration newConfiguration) { // Corret - string newValue = string.IsNullOrEmpty( NewValue ) ? string.Empty : NewValue.Trim(); + var newValue = string.IsNullOrEmpty(NewValue) ? string.Empty : NewValue.Trim(); // Not changed - if (Equals( newValue, ReadRawValue( newConfiguration ) )) + if (Equals(newValue, ReadRawValue(newConfiguration))) return false; // Load the setting - KeyValueConfigurationElement setting = newConfiguration.AppSettings.Settings[Name.ToString()]; + var setting = newConfiguration.AppSettings.Settings[Name.ToString()]; // Ups, missing - if (null == setting) - newConfiguration.AppSettings.Settings.Add( Name.ToString(), newValue ); + if (setting == null) + newConfiguration.AppSettings.Settings.Add(Name.ToString(), newValue); else setting.Value = newValue; @@ -121,21 +101,13 @@ internal bool Update( Configuration newConfiguration ) /// Erzeugt eine Kopie des Eintrags. /// /// Die gewünschte Kopie. - public SettingDescription Clone() - { - // Forward - return CreateClone(); - } + public SettingDescription Clone() => CreateClone(); /// /// Erzeugt eine Kopie des Eintrags. /// /// Die gewünschte Kopie. - object ICloneable.Clone() - { - // Forward - return Clone(); - } + object ICloneable.Clone() => Clone(); #endregion } @@ -143,18 +115,18 @@ object ICloneable.Clone() /// /// Beschreibt eine Einstellung und deren Wert. /// - /// Der Datentyp des Wertes. - public class SettingDescription : SettingDescription + /// Der Datentyp des Wertes. + public class SettingDescription : SettingDescription { /// /// Liest oder setzt den Wert. /// - public T Value { get; set; } + public TValueType Value { get; set; } /// /// Der zu verwendende Wert, wenn die Einstellung nicht gefunden wurde. /// - private T m_Default; + private TValueType m_Default; /// /// Erzeugt eine neue Beschreibung. @@ -162,8 +134,8 @@ public class SettingDescription : SettingDescription /// Der Name der Beschreibung. /// Ein Wert für den Fall, dass der gewünschte Konfigurationswert /// nicht belegt ist. - internal SettingDescription( SettingNames name, T defaultValue ) - : base( name ) + internal SettingDescription(SettingNames name, TValueType defaultValue) + : base(name) { // Remember m_Default = defaultValue; @@ -173,21 +145,13 @@ internal SettingDescription( SettingNames name, T defaultValue ) /// Erzeugt eine Kopie des Eintrags. /// /// Die gewünschte Kopie. - protected override SettingDescription CreateClone() - { - // Process - return new SettingDescription( Name, m_Default ); - } + protected override SettingDescription CreateClone() => new SettingDescription(Name, m_Default); /// /// Erzeugt eine Kopie des Eintrags. /// /// Die gewünschte Kopie. - public new SettingDescription Clone() - { - // Forward - return (SettingDescription) CreateClone(); - } + public new SettingDescription Clone() => (SettingDescription)CreateClone(); /// /// Liest den Namen der Einstellung. @@ -196,30 +160,30 @@ protected override SettingDescription CreateClone() public override object ReadValue() { // Load as string - string setting = (string) base.ReadValue(); + var setting = (string)base.ReadValue(); // None - if (string.IsNullOrEmpty( setting )) + if (string.IsNullOrEmpty(setting)) return m_Default; // Try to convert try { // Type to use for parsing - var resultType = typeof( T ); + var resultType = typeof(TValueType); // Check mode - if (resultType == typeof( string )) - return (T) (object) setting; + if (resultType == typeof(string)) + return (TValueType)(object)setting; // See if type is nullable - resultType = Nullable.GetUnderlyingType( resultType ) ?? resultType; + resultType = Nullable.GetUnderlyingType(resultType) ?? resultType; // Forward if (resultType.IsEnum) - return (T) Enum.Parse( resultType, setting ); + return (TValueType)Enum.Parse(resultType, setting); else - return (T) resultType.InvokeMember( "Parse", BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[] { setting } ); + return (TValueType)resultType.InvokeMember("Parse", BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[] { setting }); } catch { @@ -245,41 +209,41 @@ public override object ReadValue() static VCRConfiguration() { // Remember all - Add( SettingNames.FileNamePattern, "%Job% - %Schedule% - %Start%" ); - Add( SettingNames.SuppressDelayAfterForcedHibernation, false ); - Add( SettingNames.DelayAfterForcedHibernation, (uint) 5 ); - Add( SettingNames.VideoRecorderDirectory, "Recordings" ); - Add( SettingNames.DisablePCRFromMPEG2Generation, false ); - Add( SettingNames.DisablePCRFromH264Generation, false ); - Add( SettingNames.UseStandByForHibernation, false ); - Add( SettingNames.LoggingLevel, LoggingLevel.Full ); - Add( SettingNames.ScanJoinThreshold, (uint?) null ); - Add( SettingNames.EPGJoinThreshold, (uint?) null ); - Add( SettingNames.UseExternalCardServer, true ); - Add( SettingNames.HibernationDelay, (uint) 60 ); - Add( SettingNames.EPGInterval, (uint?) null ); - Add( SettingNames.MayHibernateSystem, false ); - Add( SettingNames.ArchiveLifeTime, (uint) 5 ); - Add( SettingNames.EPGIncludeFreeSat, false ); - Add( SettingNames.AdditionalRecorderPaths ); - Add( SettingNames.ScanDuration, (uint) 60 ); - Add( SettingNames.EPGDuration, (uint) 15 ); - Add( SettingNames.TCPPort, (ushort) 2909 ); - Add( SettingNames.SSLPort, (ushort) 3909 ); - Add( SettingNames.LogLifeTime, (uint) 5 ); - Add( SettingNames.MergeScanResult, true ); - Add( SettingNames.TSAudioBufferSize, 0 ); - Add( SettingNames.TSSDTVBufferSize, 0 ); - Add( SettingNames.TSHDTVBufferSize, 0 ); - Add( SettingNames.AllowBasic, false ); - Add( SettingNames.RequiredAdminRole ); - Add( SettingNames.RequiredUserRole ); - Add( SettingNames.ScanInterval, 0 ); - Add( SettingNames.UseSSL, false ); - Add( SettingNames.EPGStations ); - Add( SettingNames.ScanHours ); - Add( SettingNames.Profiles ); - Add( SettingNames.EPGHours ); + Add(SettingNames.FileNamePattern, "%Job% - %Schedule% - %Start%"); + Add(SettingNames.SuppressDelayAfterForcedHibernation, false); + Add(SettingNames.DelayAfterForcedHibernation, (uint)5); + Add(SettingNames.VideoRecorderDirectory, "Recordings"); + Add(SettingNames.DisablePCRFromMPEG2Generation, false); + Add(SettingNames.DisablePCRFromH264Generation, false); + Add(SettingNames.UseStandByForHibernation, false); + Add(SettingNames.LoggingLevel, LoggingLevel.Full); + Add(SettingNames.ScanJoinThreshold, (uint?)null); + Add(SettingNames.EPGJoinThreshold, (uint?)null); + Add(SettingNames.UseExternalCardServer, true); + Add(SettingNames.HibernationDelay, (uint)60); + Add(SettingNames.EPGInterval, (uint?)null); + Add(SettingNames.MayHibernateSystem, false); + Add(SettingNames.ArchiveLifeTime, (uint)5); + Add(SettingNames.EPGIncludeFreeSat, false); + Add(SettingNames.AdditionalRecorderPaths); + Add(SettingNames.ScanDuration, (uint)60); + Add(SettingNames.EPGDuration, (uint)15); + Add(SettingNames.TCPPort, (ushort)2909); + Add(SettingNames.SSLPort, (ushort)3909); + Add(SettingNames.LogLifeTime, (uint)5); + Add(SettingNames.MergeScanResult, true); + Add(SettingNames.TSAudioBufferSize, 0); + Add(SettingNames.TSSDTVBufferSize, 0); + Add(SettingNames.TSHDTVBufferSize, 0); + Add(SettingNames.AllowBasic, false); + Add(SettingNames.RequiredAdminRole); + Add(SettingNames.RequiredUserRole); + Add(SettingNames.ScanInterval, 0); + Add(SettingNames.UseSSL, false); + Add(SettingNames.EPGStations); + Add(SettingNames.ScanHours); + Add(SettingNames.Profiles); + Add(SettingNames.EPGHours); // Set restart items m_Restart[SettingNames.AllowBasic] = true; @@ -292,34 +256,26 @@ static VCRConfiguration() /// /// Aktiviert eine Konfiguration in der aktuellen . /// - public static void Startup() - { - // Process - Register( new VCRConfiguration() ); - } + public static void Startup() => Register(new VCRConfiguration()); /// /// Instanzen dieser Klasse sind nicht zeitgebunden. /// /// Die Antwort muss immer null sein. - public override object InitializeLifetimeService() - { - // No lease at all - return null; - } + public override object InitializeLifetimeService() => null; /// /// Bereitet eine Aktualisierung vor. /// /// Die zu aktualisierenden Einträge. /// Alle gewünschten Einträge. - public Dictionary BeginUpdate( params SettingNames[] names ) + public Dictionary BeginUpdate(params SettingNames[] names) { // Create empty - if (null == names) + if (names == null) return new Dictionary(); else - return names.ToDictionary( n => n, n => m_Settings[n].Clone() ); + return names.ToDictionary(n => n, n => m_Settings[n].Clone()); } /// @@ -327,27 +283,27 @@ public Dictionary BeginUpdate( params SettingN /// /// Die eventuell veränderten Einstellungen. /// Gesetzt, wenn ein Neustart erforderlich war. - internal bool CommitUpdate( IEnumerable settings ) + internal bool CommitUpdate(IEnumerable settings) { // Validate - if (null == settings) + if (settings == null) return false; // Clone the current configuration - var newConfiguration = ConfigurationManager.OpenExeConfiguration( Tools.ExecutablePath ); + var newConfiguration = ConfigurationManager.OpenExeConfiguration(Tools.ExecutablePath); // See if we changed at all bool changed = false, restart = false; // Process all foreach (var setting in settings) - if (setting.Update( newConfiguration )) + if (setting.Update(newConfiguration)) { // Remember changed = true; // See if this requires a restart - if (m_Restart.ContainsKey( setting.Name )) + if (m_Restart.ContainsKey(setting.Name)) restart = true; } @@ -359,16 +315,16 @@ internal bool CommitUpdate( IEnumerable settings ) string origName = Tools.ExecutablePath + ".config", tempName = origName + ".new"; // Write back to primary - newConfiguration.SaveAs( tempName ); + newConfiguration.SaveAs(tempName); // Be safe try { // Try to overwrite - File.Copy( tempName, origName, true ); + File.Copy(tempName, origName, true); // Write back to backup for upgrade installation - File.Copy( tempName, origName + ".cpy", true ); + File.Copy(tempName, origName + ".cpy", true); // Force reload if (!restart) @@ -380,7 +336,7 @@ internal bool CommitUpdate( IEnumerable settings ) finally { // Cleanup - File.Delete( tempName ); + File.Delete(tempName); } } @@ -388,12 +344,12 @@ internal bool CommitUpdate( IEnumerable settings ) /// Aktiviert eine bestimmte Konfiguration in der aktuellen . /// /// Die gewünschte Konfiguration. - internal static void Register( VCRConfiguration configuration ) + internal static void Register(VCRConfiguration configuration) { // Validate - if (null == configuration) - throw new ArgumentNullException( "configuration" ); - if (null != Current) + if (configuration == null) + throw new ArgumentNullException("configuration"); + if (Current != null) throw new InvalidOperationException(); // Remember @@ -406,51 +362,39 @@ internal static void Register( VCRConfiguration configuration ) private VCRConfiguration() { // Report - Tools.ExtendedLogging( "New Configuration Instance Created" ); + Tools.ExtendedLogging("New Configuration Instance Created"); } /// /// Vermerkt eine Einstellung. /// /// Der Name der Einstellung. - private static void Add( SettingNames name ) - { - // Forward - Add( name, (string) null ); - } + private static void Add(SettingNames name) => Add(name, (string)null); /// /// Vermerkt eine Einstellung. /// - /// Der Datentyp des zugehörigen Wertes. + /// Der Datentyp des zugehörigen Wertes. /// Der Name der Einstellung. /// Der voreingestellt Wert. - private static void Add( SettingNames name, T defaultValue ) - { - // Create new - m_Settings[name] = new SettingDescription( name, defaultValue ); - } + private static void Add(SettingNames name, TValueType defaultValue) => m_Settings[name] = new SettingDescription(name, defaultValue); /// /// Ermittelt eine einzelne Einstellung. /// /// Name der Einstellung. /// Wert der Einstellung. - private static object ReadSetting( SettingNames name ) + private static object ReadSetting(SettingNames name) { // Find and forward - SettingDescription settings; - if (m_Settings.TryGetValue( name, out settings )) - return settings.ReadValue(); - else - return null; + return m_Settings.TryGetValue(name, out SettingDescription settings) ? settings.ReadValue() : null; } /// /// Meldet den Namen der Kontogruppe der Anwender, die Zugriff auf den /// VCR.NET Recording Service haben. /// - public string UserRole { get { return (string) ReadSetting( SettingNames.RequiredUserRole ); } } + public string UserRole => (string)ReadSetting(SettingNames.RequiredUserRole); /// /// Meldet oder legt fest, ob bereits einmal eine Aufzeichnung ausgeführt wurde. @@ -466,13 +410,13 @@ private static object ReadSetting( SettingNames name ) /// Meldet den Namen der Kontogruppe der Anwender, die administrativen Zugriff auf den /// VCR.NET Recording Service haben. /// - public string AdminRole { get { return (string) ReadSetting( SettingNames.RequiredAdminRole ); } } + public string AdminRole => (string)ReadSetting(SettingNames.RequiredAdminRole); /// /// Meldet, ob der Schlafzustand S3 (Standby) anstelle von S4 (Hibernate) /// verwenden soll. /// - public bool UseS3ForHibernate { get { return (bool) ReadSetting( SettingNames.UseStandByForHibernation ); } } + public bool UseS3ForHibernate => (bool)ReadSetting(SettingNames.UseStandByForHibernation); /// /// Meldet die Größe für die Zwischenspeicherung bei Radioaufnahmen. @@ -482,11 +426,11 @@ public int? AudioBufferSize get { // Process - var buffer = (int) ReadSetting( SettingNames.TSAudioBufferSize ); + var buffer = (int)ReadSetting(SettingNames.TSAudioBufferSize); if (buffer < 1) return null; else - return Math.Max( 1000, buffer ); + return Math.Max(1000, buffer); } } @@ -498,11 +442,11 @@ public int? StandardVideoBufferSize get { // Process - var buffer = (int) ReadSetting( SettingNames.TSSDTVBufferSize ); + var buffer = (int)ReadSetting(SettingNames.TSSDTVBufferSize); if (buffer < 1) return null; else - return Math.Max( 1000, buffer ); + return Math.Max(1000, buffer); } } @@ -514,11 +458,11 @@ public int? HighDefinitionVideoBufferSize get { // Process - var buffer = (int) ReadSetting( SettingNames.TSHDTVBufferSize ); + var buffer = (int)ReadSetting(SettingNames.TSHDTVBufferSize); if (buffer < 1) return null; else - return Math.Max( 1000, buffer ); + return Math.Max(1000, buffer); } } @@ -526,46 +470,46 @@ public int? HighDefinitionVideoBufferSize /// Meldet, ob der VCR.NET Recording Service den Rechner in einen Schlafzustand /// versetzten darf. /// - public bool MayHibernateSystem { get { return (bool) ReadSetting( SettingNames.MayHibernateSystem ); } } + public bool MayHibernateSystem => (bool)ReadSetting(SettingNames.MayHibernateSystem); /// /// Meldet die geschätzte Zeit, die dieses System maximal braucht, um aus dem /// Schlafzustand zu erwachen. /// - public uint HibernationDelay { get { return (uint) ReadSetting( SettingNames.HibernationDelay ); } } + public uint HibernationDelay => (uint)ReadSetting(SettingNames.HibernationDelay); /// /// Meldet, ob der Card Server als eigenständiger Prozess gestartet werden soll. /// - public bool UseExternalCardServer { get { return (bool) ReadSetting( SettingNames.UseExternalCardServer ); } } + public bool UseExternalCardServer => (bool)ReadSetting(SettingNames.UseExternalCardServer); /// /// Gesetzt wenn es nicht gestattet ist, aus einem H.264 Bildsignal die Zeitbasis (PCR) /// abzuleiten. /// - public bool DisablePCRFromH264Generation { get { return (bool) ReadSetting( SettingNames.DisablePCRFromH264Generation ); } } + public bool DisablePCRFromH264Generation => (bool)ReadSetting(SettingNames.DisablePCRFromH264Generation); /// /// Gesetzt wenn es nicht gestattet ist, aus einem MPEG2 Bildsignal die Zeitbasis (PCR) /// abzuleiten. /// - public bool DisablePCRFromMPEG2Generation { get { return (bool) ReadSetting( SettingNames.DisablePCRFromMPEG2Generation ); } } + public bool DisablePCRFromMPEG2Generation => (bool)ReadSetting(SettingNames.DisablePCRFromMPEG2Generation); /// /// Meldet, ob die Programmzeitschrift der englischen FreeSat Sender eingeschlossen /// werden soll. /// - public bool EnableFreeSat { get { return (bool) ReadSetting( SettingNames.EPGIncludeFreeSat ); } } + public bool EnableFreeSat => (bool)ReadSetting(SettingNames.EPGIncludeFreeSat); /// /// Die Liste der Quellen, die in der Programmzeitschrift berücksichtigt werden sollen. /// - public string ProgramGuideSourcesRaw { get { return (string) ReadSetting( SettingNames.EPGStations ); } } + public string ProgramGuideSourcesRaw => (string)ReadSetting(SettingNames.EPGStations); /// /// Meldet alle Quellen, für die Daten gesammelt werden sollen. /// - public string[] ProgramGuideSourcesAsArray { get { return ProgramGuideSources.ToArray(); } } + public string[] ProgramGuideSourcesAsArray => ProgramGuideSources.ToArray(); /// /// Meldet alle Quellen, für die Daten gesammelt werden sollen. @@ -576,15 +520,15 @@ public IEnumerable ProgramGuideSources { // Load from settings var sources = ProgramGuideSourcesRaw; - if (string.IsNullOrEmpty( sources )) + if (string.IsNullOrEmpty(sources)) yield break; // Process all - foreach (var source in sources.Split( ',' )) + foreach (var source in sources.Split(',')) { // Cleanup var trimmed = source.Trim(); - if (!string.IsNullOrEmpty( trimmed )) + if (!string.IsNullOrEmpty(trimmed)) yield return trimmed; } } @@ -604,7 +548,7 @@ public bool ProgramGuideUpdateEnabled return false; else if (ProgramGuideUpdateHours.Any()) return true; - else if (ProgramGuideUpdateInterval.GetValueOrDefault( TimeSpan.Zero ).TotalDays > 0) + else if (ProgramGuideUpdateInterval.GetValueOrDefault(TimeSpan.Zero).TotalDays > 0) return true; else return false; @@ -614,17 +558,17 @@ public bool ProgramGuideUpdateEnabled /// /// Meldet alle vollen Stunden, zu denen eine Sammlung stattfinden soll. /// - public uint[] ProgramGuideUpdateHours { get { return Tools.GetHourList( ProgramGuideUpdateHoursRaw ).ToArray(); } } + public uint[] ProgramGuideUpdateHours => Tools.GetHourList(ProgramGuideUpdateHoursRaw).ToArray(); /// /// Meldet alle vollen Stunden, zu denen eine Sammlung stattfinden soll. /// - public uint[] ProgramGuideUpdateHoursAsArray { get { return ProgramGuideUpdateHours.ToArray(); } } + public uint[] ProgramGuideUpdateHoursAsArray => ProgramGuideUpdateHours.ToArray(); /// /// Meldet die maximale Laufzeit einer Aktualisierung gemäß der Konfiguration. /// - public uint ProgramGuideUpdateDuration { get { return (uint) ReadSetting( SettingNames.EPGDuration ); } } + public uint ProgramGuideUpdateDuration => (uint)ReadSetting(SettingNames.EPGDuration); /// /// Meldet die minimale Zeitspanne zwischen zwei Aktualisierungen der Programmzeitschrift. @@ -634,9 +578,9 @@ public TimeSpan? ProgramGuideUpdateInterval get { // Load - var interval = (uint?) ReadSetting( SettingNames.EPGInterval ); + var interval = (uint?)ReadSetting(SettingNames.EPGInterval); if (interval.HasValue) - return TimeSpan.FromHours( interval.Value ); + return TimeSpan.FromHours(interval.Value); else return null; } @@ -651,9 +595,9 @@ public TimeSpan? ProgramGuideJoinThreshold get { // Load - var interval = (uint?) ReadSetting( SettingNames.EPGJoinThreshold ); + var interval = (uint?)ReadSetting(SettingNames.EPGJoinThreshold); if (interval.HasValue) - return TimeSpan.FromHours( interval.Value ); + return TimeSpan.FromHours(interval.Value); else return null; } @@ -668,9 +612,9 @@ public TimeSpan? SourceListJoinThreshold get { // Load - var interval = (uint?) ReadSetting( SettingNames.ScanJoinThreshold ); + var interval = (uint?)ReadSetting(SettingNames.ScanJoinThreshold); if (interval.HasValue) - return TimeSpan.FromDays( interval.Value ); + return TimeSpan.FromDays(interval.Value); else return null; } @@ -679,116 +623,116 @@ public TimeSpan? SourceListJoinThreshold /// /// Meldet die maximale Laufzeit für die Aktualisierung der Quellen eines Geräteprofils. /// - public uint SourceListUpdateDuration { get { return (uint) ReadSetting( SettingNames.ScanDuration ); } } + public uint SourceListUpdateDuration => (uint)ReadSetting(SettingNames.ScanDuration); /// /// Meldet, wieviele Tage mindestens zwischen zwei Aktualisierungen der Liste /// der Quellen eines Geräteprofils liegen müssen. /// - public int SourceListUpdateInterval { get { return (int) ReadSetting( SettingNames.ScanInterval ); } } + public int SourceListUpdateInterval => (int)ReadSetting(SettingNames.ScanInterval); /// /// Meldet, ob nach Abschluss der Aktualisierung die Listen der Quellen zusammengeführt /// werden sollen. /// - public bool MergeSourceListUpdateResult { get { return (bool) ReadSetting( SettingNames.MergeScanResult ); } } + public bool MergeSourceListUpdateResult => (bool)ReadSetting(SettingNames.MergeScanResult); /// /// Meldet die Liste der Stunden, an denen eine Aktualisierung einer /// Liste von Quellen stattfinden darf. /// - public string SourceListUpdateHoursRaw { get { return (string) ReadSetting( SettingNames.ScanHours ); } } + public string SourceListUpdateHoursRaw => (string)ReadSetting(SettingNames.ScanHours); /// /// Meldet alle vollen Stunden, zu denen eine Sammlung stattfinden soll. /// - public uint[] SourceListUpdateHours { get { return Tools.GetHourList( SourceListUpdateHoursRaw ).ToArray(); } } + public uint[] SourceListUpdateHours => Tools.GetHourList(SourceListUpdateHoursRaw).ToArray(); /// /// Meldet alle vollen Stunden, zu denen eine Sammlung stattfinden soll. /// - public uint[] SourceListUpdateHoursAsArray { get { return SourceListUpdateHours.ToArray(); } } + public uint[] SourceListUpdateHoursAsArray => SourceListUpdateHours.ToArray(); /// /// Meldet die Liste der Stunden, an denen eine Aktualisierung einer /// Programmzeitschrift stattfinden darf. /// - public string ProgramGuideUpdateHoursRaw { get { return (string) ReadSetting( SettingNames.EPGHours ); } } + public string ProgramGuideUpdateHoursRaw => (string)ReadSetting(SettingNames.EPGHours); /// /// Meldet die Zeit in Wochen, die ein Protokolleintrag vorgehalten wird. /// - public uint LogLifeTime { get { return (uint) ReadSetting( SettingNames.LogLifeTime ); } } + public uint LogLifeTime { get { return (uint)ReadSetting(SettingNames.LogLifeTime); } } /// /// Meldet die maximale Verweildauer eines archivierten Auftrags im Archiv, bevor /// er gelöscht wird. /// - public uint ArchiveLifeTime { get { return (uint) ReadSetting( SettingNames.ArchiveLifeTime ); } } + public uint ArchiveLifeTime => (uint)ReadSetting(SettingNames.ArchiveLifeTime); /// /// Meldet die Zeit die nach einem erzwungenen Schlafzustand verstreichen muss, bevor der /// Rechner für eine Aufzeichnung aufgweckt wird. /// - public uint RawDelayAfterForcedHibernation { get { return (uint) ReadSetting( SettingNames.DelayAfterForcedHibernation ); } } + public uint RawDelayAfterForcedHibernation => (uint)ReadSetting(SettingNames.DelayAfterForcedHibernation); /// /// Meldet die Zeit die nach einem erzwungenen Schlafzustand verstreichen muss, bevor der /// Rechner für eine Aufzeichnung aufgweckt wird. /// - public TimeSpan DelayAfterForcedHibernation { get { return TimeSpan.FromMinutes( Math.Max( 1, RawDelayAfterForcedHibernation ) ); } } + public TimeSpan DelayAfterForcedHibernation => TimeSpan.FromMinutes(Math.Max(1, RawDelayAfterForcedHibernation)); /// /// Gesetzt, wenn beim Schlafzustand keine Sonderbehandlung erwünscht ist. /// - public bool SuppressDelayAfterForcedHibernation { get { return (bool) ReadSetting( SettingNames.SuppressDelayAfterForcedHibernation ); } } + public bool SuppressDelayAfterForcedHibernation => (bool)ReadSetting(SettingNames.SuppressDelayAfterForcedHibernation); /// /// Meldet den aktuellen Umfang der Protokollierung. /// - public LoggingLevel LoggingLevel { get { return (LoggingLevel) ReadSetting( SettingNames.LoggingLevel ); } } + public LoggingLevel LoggingLevel => (LoggingLevel)ReadSetting(SettingNames.LoggingLevel); /// /// Meldet den TCP/IP Port, an den der Web Server gebunden werden soll. /// - public ushort WebServerTcpPort { get { return (ushort) ReadSetting( SettingNames.TCPPort ); } } + public ushort WebServerTcpPort => (ushort)ReadSetting(SettingNames.TCPPort); /// /// Meldet den TCP/IP Port, an den der Web Server bei einer sichen Verbindung gebunden werden soll. /// - public ushort WebServerSecureTcpPort { get { return (ushort) ReadSetting( SettingNames.SSLPort ); } } + public ushort WebServerSecureTcpPort => (ushort)ReadSetting(SettingNames.SSLPort); /// /// Gesetzt, wenn die Verbindung zu den Web Diensten verschlüsselt werden soll. /// - public bool EncryptWebCommunication { get { return (bool) ReadSetting( SettingNames.UseSSL ); } } + public bool EncryptWebCommunication => (bool)ReadSetting(SettingNames.UseSSL); /// /// Gesetzt, wenn die Anwender sich auch über das Basic Prototokoll /// autorisieren dürfen. /// - public bool EnableBasicAuthentication { get { return (bool) ReadSetting( SettingNames.AllowBasic ); } } + public bool EnableBasicAuthentication => (bool)ReadSetting(SettingNames.AllowBasic); /// /// Ermittelt das Ersetzungsmuster für Dateinamen. /// - public string FileNamePattern { get { return (string) ReadSetting( SettingNames.FileNamePattern ); } } + public string FileNamePattern => (string)ReadSetting(SettingNames.FileNamePattern); /// /// Ermittelt den Namen des primären Aufzeichnungsverzeichnisses /// - public string PrimaryRecordingDirectory { get { return (string) ReadSetting( SettingNames.VideoRecorderDirectory ); } } + public string PrimaryRecordingDirectory => (string)ReadSetting(SettingNames.VideoRecorderDirectory); /// /// Meldet die zusätzlichen Aufzeichnungsverzeichnisse. /// - public string AlternateRecordingDirectories { get { return (string) ReadSetting( SettingNames.AdditionalRecorderPaths ); } } + public string AlternateRecordingDirectories => (string)ReadSetting(SettingNames.AdditionalRecorderPaths); /// /// Meldet die Namen der DVB.NET Geräteprofile, die der VCR.NET Recording Service /// verwenden darf. /// - public string ProfileNames { get { return (string) ReadSetting( SettingNames.Profiles ); } } + public string ProfileNames => (string)ReadSetting(SettingNames.Profiles); /// /// Meldet das primäre Aufzeichnungsverzeichnis. @@ -798,22 +742,22 @@ public DirectoryInfo PrimaryTargetDirectory get { // Get the path - var path = Path.Combine( Tools.ApplicationDirectory.Parent.FullName, PrimaryRecordingDirectory ); + var path = Path.Combine(Tools.ApplicationDirectory.Parent.FullName, PrimaryRecordingDirectory); // Extend it - if (!string.IsNullOrEmpty( path )) + if (!string.IsNullOrEmpty(path)) if (path[path.Length - 1] != Path.DirectorySeparatorChar) path += Path.DirectorySeparatorChar; // Create - return new DirectoryInfo( path ); + return new DirectoryInfo(path); } } /// /// Meldet alle erlaubten Aufzeichnungsverzeichnisse. /// - public string[] TargetDirectoriesNames { get { return TargetDirectories.Select( d => d.FullName ).ToArray(); } } + public string[] TargetDirectoriesNames => TargetDirectories.Select(d => d.FullName).ToArray(); /// /// Meldet alle erlaubten Aufzeichnungsverzeichnisse. @@ -829,14 +773,14 @@ public IEnumerable TargetDirectories var dirs = AlternateRecordingDirectories; // Process - if (!string.IsNullOrEmpty( dirs )) - foreach (var dir in dirs.Split( ',' )) + if (!string.IsNullOrEmpty(dirs)) + foreach (var dir in dirs.Split(',')) { // Load the path string path = dir.Trim(); // Skip - if (string.IsNullOrEmpty( path )) + if (string.IsNullOrEmpty(path)) continue; // Extend it @@ -850,12 +794,12 @@ public IEnumerable TargetDirectories try { // Load - info = new DirectoryInfo( path ); + info = new DirectoryInfo(path); } catch (Exception e) { // Report as error - VCRServer.Log( e ); + VCRServer.Log(e); // Just ignore continue; @@ -872,21 +816,21 @@ public IEnumerable TargetDirectories /// /// Der zu prüfende Dateipfad. /// Gesetzt, wenn der Pfad gültig ist. - public bool IsValidTarget( string path ) + public bool IsValidTarget(string path) { // Must habe a path - if (string.IsNullOrEmpty( path )) + if (string.IsNullOrEmpty(path)) return false; // Test it foreach (var allowed in TargetDirectories) - if (path.StartsWith( allowed.FullName, StringComparison.InvariantCultureIgnoreCase )) + if (path.StartsWith(allowed.FullName, StringComparison.InvariantCultureIgnoreCase)) { // Silent create the directory try { // Create the directory - Directory.CreateDirectory( Path.GetDirectoryName( path ) ); + Directory.CreateDirectory(Path.GetDirectoryName(path)); // Yeah return true; @@ -894,7 +838,7 @@ public bool IsValidTarget( string path ) catch (Exception e) { // Report - VCRServer.Log( e ); + VCRServer.Log(e); // Done return false; diff --git a/VCR.NET/ServiceCore/VCRProfiles.cs b/VCR.NET/ServiceCore/VCRProfiles.cs index 9b118d9..7591b12 100644 --- a/VCR.NET/ServiceCore/VCRProfiles.cs +++ b/VCR.NET/ServiceCore/VCRProfiles.cs @@ -114,7 +114,7 @@ internal static void Reset() sourcesByIdentifier[source.Source] = source; // Correct back the name - source.DisplayName = ((Station) source.Source).FullName; + source.DisplayName = ((Station)source.Source).FullName; } } @@ -129,10 +129,10 @@ internal static void Reset() if (!source.Key.Equals( source.Value.DisplayName )) { // Unmap the station - var station = (Station) source.Value.Source; + var station = (Station)source.Value.Source; // Enter special notation - profileMap[string.Format( "{0} {1} [{2}]", station.Name, station.ToStringKey(), station.Provider )] = source.Value; + profileMap[$"{station.Name} {station.ToStringKey()} [{station.Provider}]"] = source.Value; } // Use all @@ -183,13 +183,11 @@ public static SourceSelection FindSource( string profileName, string name ) profileName = state.Profiles[0].Name; // Map to use - Dictionary sources; - if (!state.SourceBySelectionMap.TryGetValue( profileName, out sources )) + if (!state.SourceBySelectionMap.TryGetValue(profileName, out Dictionary sources)) return null; // Ask map - SourceSelection source; - if (!sources.TryGetValue( name, out source )) + if (!sources.TryGetValue(name, out SourceSelection source)) return null; // Report @@ -217,13 +215,11 @@ public static SourceSelection FindSource( string profileName, SourceIdentifier s profileName = state.Profiles[0].Name; // Find the map - Dictionary map; - if (!state.SourceByIdentifierMap.TryGetValue( profileName, out map )) + if (!state.SourceByIdentifierMap.TryGetValue(profileName, out Dictionary map)) return null; // Find the source - SourceSelection found; - if (!map.TryGetValue( source, out found )) + if (!map.TryGetValue(source, out SourceSelection found)) return null; else return found; @@ -251,22 +247,14 @@ public static SourceSelection FindSource( SourceSelection source ) /// /// Der Name des Geräteprofils. /// Alle Quellen zum Profil. - public static IEnumerable GetSources( string profileName ) - { - // Forward - return GetSources( profileName, (Func) null ); - } + public static IEnumerable GetSources( string profileName ) => GetSources( profileName, (Func)null ); /// /// Ermittelt alle Quellen zu einem DVB.NET Geräteprofil. /// /// Der Name des Geräteprofils. /// Alle Quellen zum Profil. - public static IEnumerable GetSources( Profile profile ) - { - // Forward - return GetSources( profile, (Func) null ); - } + public static IEnumerable GetSources( Profile profile ) => GetSources( profile, (Func)null ); /// /// Ermittelt alle Quellen zu einem DVB.NET Geräteprofil. @@ -274,11 +262,7 @@ public static IEnumerable GetSources( Profile profile ) /// Der Name des Geräteprofils. /// Methode, die prüft, ob eine Quelle gemeldet werden soll. /// Alle Quellen zum Profil. - public static IEnumerable GetSources( string profileName, Func predicate ) - { - // Forward - return GetSources( FindProfile( profileName ), predicate ); - } + public static IEnumerable GetSources( string profileName, Func predicate ) => GetSources( FindProfile( profileName ), predicate ); /// /// Ermittelt alle Quellen zu einem DVB.NET Geräteprofil. @@ -289,10 +273,10 @@ public static IEnumerable GetSources( string profileName, Func< public static IEnumerable GetSources( string profileName, Func predicate ) { // Forward - if (null == predicate) + if (predicate == null) return GetSources( FindProfile( profileName ) ); else - return GetSources( FindProfile( profileName ), s => predicate( (Station) s.Source ) ); + return GetSources( FindProfile( profileName ), s => predicate( (Station)s.Source ) ); } /// @@ -304,12 +288,11 @@ public static IEnumerable GetSources( string profileName, Func< public static IEnumerable GetSources( Profile profile, Func predicate ) { // Resolve - if (null == profile) + if (profile == null) yield break; // Load the map - Dictionary map; - if (!CurrentState.SourceByIdentifierMap.TryGetValue( profile.Name, out map )) + if (!CurrentState.SourceByIdentifierMap.TryGetValue(profile.Name, out Dictionary map)) yield break; // Use state @@ -331,8 +314,7 @@ public static Profile FindProfile( string name ) return DefaultProfile; // Read out - Profile profile; - return CurrentState.ProfileMap.TryGetValue( name, out profile ) ? profile : null; + return CurrentState.ProfileMap.TryGetValue(name, out Profile profile) ? profile : null; } /// @@ -354,8 +336,7 @@ public static string GetUniqueName( SourceSelection source ) return null; // Find the name - string name; - if (!CurrentState.UniqueNameBySelectionMap.TryGetValue( active.SelectionKey, out name )) + if (!CurrentState.UniqueNameBySelectionMap.TryGetValue(active.SelectionKey, out string name)) return null; // Report it diff --git a/VCR.NET/ServiceCore/VCRServer/VCRServer.cs b/VCR.NET/ServiceCore/VCRServer/VCRServer.cs index 4fa326e..42f3881 100644 --- a/VCR.NET/ServiceCore/VCRServer/VCRServer.cs +++ b/VCR.NET/ServiceCore/VCRServer/VCRServer.cs @@ -20,12 +20,12 @@ public partial class VCRServer : MarshalByRefObject, IDisposable /// /// Wird beim Bauen automatisch eingemischt. /// - private const string CURRENTDATE = "2015/02/08"; + private const string CURRENTDATE = "2019/11/17"; /// /// Aktuelle Version des VCR.NET Recording Service. /// - public const string CurrentVersion = "4.3 [" + CURRENTDATE + "]"; + public const string CurrentVersion = "4.5 [" + CURRENTDATE + "]"; /// /// Konfigurationseintrag in der Registrierung von Windows. diff --git a/VCR.NET/ServiceCore/VCRServer/VCRServer_Hibernate.cs b/VCR.NET/ServiceCore/VCRServer/VCRServer_Hibernate.cs index 452b952..f6dde56 100644 --- a/VCR.NET/ServiceCore/VCRServer/VCRServer_Hibernate.cs +++ b/VCR.NET/ServiceCore/VCRServer/VCRServer_Hibernate.cs @@ -1,9 +1,9 @@ +using JMS.DVBVCR.RecordingService.Win32Tools; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; -using JMS.DVBVCR.RecordingService.Win32Tools; namespace JMS.DVBVCR.RecordingService @@ -18,7 +18,7 @@ partial class VCRServer /// /// Allgemeine Sperre zum Zugriff auf vernderliche globale Eigenschaften. /// - private object m_HibernateSync = new object(); + private readonly object m_HibernateSync = new object(); /// /// Gesetzt, wenn beim bergang in den Schlafzustand auf interaktive Anwender geprft werden soll. @@ -78,11 +78,7 @@ public void PrepareSuspend() /// /// Setzt diese Instanz in den Anfangszustand bezglich der berwachung des Schlafzustands zurck. /// - public void ResetPendingHibernation() - { - // Clear flag - m_PendingHibernation = false; - } + public void ResetPendingHibernation() => m_PendingHibernation = false; /// /// Teilt der Laufzeitumgebung mit, dass ein Gerteprofil eine Aufzeichnung abgeschlossen hat. diff --git a/VCR.NET/ServiceCore/VCRServer/VCRServer_Jobs.cs b/VCR.NET/ServiceCore/VCRServer/VCRServer_Jobs.cs index 542c2d8..4d77ff7 100644 --- a/VCR.NET/ServiceCore/VCRServer/VCRServer_Jobs.cs +++ b/VCR.NET/ServiceCore/VCRServer/VCRServer_Jobs.cs @@ -1,5 +1,5 @@ -using System; using JMS.DVBVCR.RecordingService.Persistence; +using System; namespace JMS.DVBVCR.RecordingService @@ -16,11 +16,7 @@ partial class VCRServer /// /// Die eindeutige Kennung des Auftrags. /// Der gewnschte Auftrag oder null. - public VCRJob FindJob( Guid uniqueIdentifier ) - { - // Ask job manager - return JobManager.FindJob( uniqueIdentifier ); - } + public VCRJob FindJob( Guid uniqueIdentifier ) => JobManager.FindJob( uniqueIdentifier ); /// /// Aktualisiert einen Auftrag oder legt einen neue an. diff --git a/VCR.NET/ServiceCore/VCRServer/VCRServer_Logging.cs b/VCR.NET/ServiceCore/VCRServer/VCRServer_Logging.cs index c04c509..1b5da9a 100644 --- a/VCR.NET/ServiceCore/VCRServer/VCRServer_Logging.cs +++ b/VCR.NET/ServiceCore/VCRServer/VCRServer_Logging.cs @@ -17,11 +17,7 @@ partial class VCRServer /// /// Abgefangener Fehler, eingetragen wird /// . - public static void Log( Exception e ) - { - // Forwatd - LogError( "{0}", e ); - } + public static void Log( Exception e ) => LogError( "{0}", e ); /// /// Trgt eine Fehlermeldung ins Ereignisprotokoll ein, wenn die Konfiguration @@ -29,11 +25,7 @@ public static void Log( Exception e ) /// /// Format fr den Aufbau der Fehlermeldung. /// Parameter fr den Aufbau der Fehlermeldung. - public static void LogError( string format, params object[] args ) - { - // Forward - Log( LoggingLevel.Errors, EventLogEntryType.Error, format, args ); - } + public static void LogError( string format, params object[] args ) => Log( LoggingLevel.Errors, EventLogEntryType.Error, format, args ); /// /// Trgt eine Meldung ins Ereignisprotokoll ein, wenn die Schwere der Meldung @@ -43,11 +35,7 @@ public static void LogError( string format, params object[] args ) /// Schwere der Meldung. /// Format fr den Aufbau der Meldung. /// Parameter fr den Aufbau der Meldung. - public static void Log( LoggingLevel level, string format, params object[] args ) - { - // Forward - Log( level, EventLogEntryType.Information, format, args ); - } + public static void Log( LoggingLevel level, string format, params object[] args ) => Log( level, EventLogEntryType.Information, format, args ); /// /// Check if an event of the indicated level should be reported to @@ -56,11 +44,7 @@ public static void Log( LoggingLevel level, string format, params object[] args /// Some logging level. /// Set, if the logging level configured requires /// the event to be logged. - public static bool ShouldLog( LoggingLevel reportLevel ) - { - // Respect the implied ordering - return (reportLevel >= VCRConfiguration.Current.LoggingLevel); - } + public static bool ShouldLog( LoggingLevel reportLevel ) => (reportLevel >= VCRConfiguration.Current.LoggingLevel); /// /// Trgt eine Meldung ins Ereignisprotokoll ein, wenn die Schwere der Meldung diff --git a/VCR.NET/ServiceCore/VCRServer/VCRServer_Recording.cs b/VCR.NET/ServiceCore/VCRServer/VCRServer_Recording.cs index dbe322c..8b33fae 100644 --- a/VCR.NET/ServiceCore/VCRServer/VCRServer_Recording.cs +++ b/VCR.NET/ServiceCore/VCRServer/VCRServer_Recording.cs @@ -1,6 +1,6 @@ -using System; using JMS.DVB; using JMS.DVB.CardServer; +using System; namespace JMS.DVBVCR.RecordingService @@ -10,13 +10,7 @@ partial class VCRServer /// /// Wird zur Prfung auf neue Bearbeitungen aufgerufen. /// - public void BeginNewPlan() - { - // Forward - var profiles = Profiles; - if (profiles != null) - profiles.BeginNewPlan(); - } + public void BeginNewPlan() => Profiles?.BeginNewPlan(); /// /// Fordert eine baldmgliche Aktualisierung der Programmzeitschrift an. @@ -46,7 +40,7 @@ public void ForceSoureListUpdate() /// /// Meldet, ob auf irgendeinem Gerteprofil ein Zugriff aktiv ist. /// - public bool IsActive { get { return Profiles.IsActive; } } + public bool IsActive => Profiles.IsActive; /// /// Verndert die Endzeit der aktuellen Aufzeichnung auf einem Gerteprofil. @@ -55,13 +49,12 @@ public void ForceSoureListUpdate() /// Die eindeutige Kennung des zu verwendenden Datenstroms. /// Der neue Endzeitpunkt. /// Gesetzt, wenn der bergang in den Schlafzustand deaktiviert werden soll. - public void ChangeRecordingStreamEndTime( string profile, Guid streamIdentifier, DateTime newEndTime, bool disableHibernation ) - { - // Forward - var state = FindProfile( profile ); - if (state != null) - state.ChangeStreamEnd( streamIdentifier, newEndTime, disableHibernation ); - } + public void ChangeRecordingStreamEndTime( string profile, Guid streamIdentifier, DateTime newEndTime, bool disableHibernation ) => FindProfile( profile )?.ChangeStreamEnd( streamIdentifier, newEndTime, disableHibernation && (NumberOfActiveRecordings == 1) ); + + /// + /// Meldet die Anzahl der aktiven Aufzeichnungen. + /// + public int NumberOfActiveRecordings => Profiles.NumberOfActiveRecordings; /// /// Aktiviert oder deaktiviert den Netzwerkversand fr eine Quelle. @@ -70,13 +63,7 @@ public void ChangeRecordingStreamEndTime( string profile, Guid streamIdentifier, /// Die betroffene Quelle. /// Die eindeutige Kennung der Teilaufzeichnung. /// Das neue Ziel des Netzwerkversands. - public void SetStreamTarget( string profile, SourceIdentifier source, Guid uniqueIdentifier, string target ) - { - // Attach to the profile and process - var state = FindProfile( profile ); - if (state != null) - state.SetStreamTarget( source, uniqueIdentifier, target ); - } + public void SetStreamTarget( string profile, SourceIdentifier source, Guid uniqueIdentifier, string target ) => FindProfile( profile )?.SetStreamTarget( source, uniqueIdentifier, target ); /// /// Steuert den Zapping Modus. diff --git a/VCR.NET/ServiceCore/VCRServer/VCRServer_Rest.cs b/VCR.NET/ServiceCore/VCRServer/VCRServer_Rest.cs index 2c418ef..0d1997a 100644 --- a/VCR.NET/ServiceCore/VCRServer/VCRServer_Rest.cs +++ b/VCR.NET/ServiceCore/VCRServer/VCRServer_Rest.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; using JMS.DVB; using JMS.DVB.Algorithms.Scheduler; using JMS.DVBVCR.RecordingService.Persistence; using JMS.DVBVCR.RecordingService.Planning; using JMS.DVBVCR.RecordingService.ProgramGuide; using JMS.DVBVCR.RecordingService.Status; +using System; +using System.Collections.Generic; +using System.Linq; namespace JMS.DVBVCR.RecordingService @@ -80,15 +80,7 @@ public TTarget FindProgramGuideEntry( string profileName, SourceIdentif /// Die Quelle, deren Eintrag ermittelt werden soll. /// Der exakte Startzeitpunkt. /// Der gewnschte Eintrag. - public ProgramGuideEntry FindProgramGuideEntry( string profileName, SourceIdentifier source, DateTime start ) - { - // See if profile exists - var profile = Profiles[profileName]; - if (profile == null) - return null; - else - return profile.ProgramGuide.FindEntry( source, start ); - } + public ProgramGuideEntry FindProgramGuideEntry( string profileName, SourceIdentifier source, DateTime start ) => Profiles[profileName]?.ProgramGuide.FindEntry( source, start ); /// /// Verndert eine Ausnahme. @@ -137,11 +129,7 @@ public void ChangeException( Guid jobIdentifier, Guid scheduleIdentifier, DateTi /// Die Art der gemeldeten Information. /// Methode zum Erzeugen der Informationen zu einem einzelnen Gerteprofil. /// Die Informationen zu den Profilen. - public TInfo[] GetProfiles( Func factory ) - { - // Forward - return Profiles.InspectProfiles( factory ).ToArray(); - } + public TInfo[] GetProfiles( Func factory ) => Profiles.InspectProfiles( factory ).ToArray(); /// /// Meldet alle Auftrge. diff --git a/VCR.NET/ServiceCore/WebServer/ApplicationEndPoint.cs b/VCR.NET/ServiceCore/WebServer/ApplicationEndPoint.cs index 025d3a4..4ace114 100644 --- a/VCR.NET/ServiceCore/WebServer/ApplicationEndPoint.cs +++ b/VCR.NET/ServiceCore/WebServer/ApplicationEndPoint.cs @@ -27,12 +27,12 @@ public abstract class ApplicationEndPoint : IDisposable where TRun /// /// Die Anzahl der gestarteten aber noch nicht zu Ende durchgeführten Operationen. /// - private int m_Threads = 0; + private int m_Threads; /// /// Die ASP.NET Laufzeitumgebung. /// - private TRuntimeType m_runtime = null; + private TRuntimeType m_runtime; /// /// Synchronisiert den Zugriff auf die Laufzeitumgebung. @@ -64,11 +64,11 @@ public ApplicationEndPoint( string name, string path ) m_listener.AuthenticationSchemes |= AuthenticationSchemes.Basic; // Regular HTTP sink - m_listener.Prefixes.Add( string.Format( "http://*:{0}/{1}/", configuration.WebServerTcpPort, name ) ); + m_listener.Prefixes.Add( $"http://*:{configuration.WebServerTcpPort}/{name}/" ); // Secure HTTP sink if (configuration.EncryptWebCommunication) - m_listener.Prefixes.Add( string.Format( "https://*:{0}/{1}/", configuration.WebServerSecureTcpPort, name ) ); + m_listener.Prefixes.Add( $"https://*:{configuration.WebServerSecureTcpPort}/{name}/" ); // Finish configuration m_listener.AuthenticationSchemeSelectorDelegate = SelectAuthentication; @@ -114,8 +114,7 @@ private TRuntimeType RunTime try { // See if the domain is still up and running - if (m_runtime != null) - m_runtime.Test(); + m_runtime?.Test(); } catch { @@ -146,7 +145,7 @@ private TRuntimeType RunTime } // Create - m_runtime = (TRuntimeType) ApplicationHost.CreateApplicationHost( typeof( ServerRuntime ), string.Format( "/{0}", m_name ), rootDir ); + m_runtime = (TRuntimeType) ApplicationHost.CreateApplicationHost( typeof( ServerRuntime ), $"/{m_name}", rootDir ); // Report RuntimeStarted( m_runtime ); diff --git a/VCR.NET/ServiceCore/WebServer/ContextAccessor.cs b/VCR.NET/ServiceCore/WebServer/ContextAccessor.cs index 0272c79..6bfd681 100644 --- a/VCR.NET/ServiceCore/WebServer/ContextAccessor.cs +++ b/VCR.NET/ServiceCore/WebServer/ContextAccessor.cs @@ -235,8 +235,7 @@ public IntPtr UserToken var domain = (parts.Length == 2) ? parts[0] : "."; // Try to logon - IntPtr handle; - if (!LogonUser( name, domain, basicIdentity.Password, 3, 0, out handle )) + if (!LogonUser(name, domain, basicIdentity.Password, 3, 0, out IntPtr handle)) { // Set result var response = Context.Response; diff --git a/VCR.NET/ServiceCore/WebServer/Request.cs b/VCR.NET/ServiceCore/WebServer/Request.cs index f673f8f..661d24d 100644 --- a/VCR.NET/ServiceCore/WebServer/Request.cs +++ b/VCR.NET/ServiceCore/WebServer/Request.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Collections.Specialized; using System.IO; using System.Net; using System.Web; @@ -34,11 +33,7 @@ public Request( ContextAccessor context ) /// /// Der HTTP Zugriff ist beendet. /// - public override void EndOfRequest() - { - // Forward - m_Context.End(); - } + public override void EndOfRequest() => m_Context.End(); /// /// Alle zwischengespeicherten Daten zum Aufrufer senden. @@ -63,21 +58,13 @@ public override void FlushResponse( bool finalFlush ) /// Meldet, ob noch eine Netzwerkverbindung zum Client besteht. /// /// Gesetzt, wenn noch eine Verbindung aktiv ist. - public override bool IsClientConnected() - { - // Forward - return m_ClientRunning; - } + public override bool IsClientConnected() => m_ClientRunning; /// /// Ermittelt die HTTP Aufrufmethode. /// /// Die HTTP Methode, die vom Client zum Aufruf verwendet wird. - public override string GetHttpVerbName() - { - // Forward to context - return m_Context.HttpMethod; - } + public override string GetHttpVerbName() => m_Context.HttpMethod; /// /// Ermittelt die HTTP Version. @@ -86,31 +73,23 @@ public override string GetHttpVerbName() public override string GetHttpVersion() { // Load the version - Version version = m_Context.ProtocolVersion; + var version = m_Context.ProtocolVersion; // Ask Context - return string.Format( "HTTP/{0}.{1}", version.Major, version.Minor ); + return $"HTTP/{version.Major}.{version.Minor}"; } /// /// Liefert die IP Adresse des Servers. /// /// Die IP Adresse des Servers. - public override string GetLocalAddress() - { - // Forward - return m_Context.LocalEndPoint.Address.ToString(); - } + public override string GetLocalAddress() => m_Context.LocalEndPoint.Address.ToString(); /// /// Liefert den TCP/IP Port unter dem der Server HHTP Aufrufe annimmt. /// /// Der TCP/IP Port des Servers. - public override int GetLocalPort() - { - // Forward - return m_Context.LocalEndPoint.Port; - } + public override int GetLocalPort() => m_Context.LocalEndPoint.Port; /// /// Ermittelt die Suchzeichenkette zum Aufruf. @@ -119,13 +98,14 @@ public override int GetLocalPort() public override string GetQueryString() { // Get the full URL - string fullUrl = m_Context.RawUrl; + var fullUrl = m_Context.RawUrl; // Check for query stringt - int index = fullUrl.IndexOf( '?' ); + var index = fullUrl.IndexOf( '?' ); // None - if (index++ < 0) return string.Empty; + if (index++ < 0) + return string.Empty; // Split off return fullUrl.Substring( index ); @@ -135,52 +115,32 @@ public override string GetQueryString() /// Liefert die ursprngliche URL des Zugriffs. /// /// Die URL des HTTP Zugrifss. - public override string GetRawUrl() - { - // Forward - return m_Context.RawUrl; - } + public override string GetRawUrl() => m_Context.RawUrl; /// /// Ermittelt die IP Adresse des Aufrufers. /// /// Die IP Adresse des Aufrufers. - public override string GetRemoteAddress() - { - // Forward to context - return m_Context.RemoteEndPoint.Address.ToString(); - } + public override string GetRemoteAddress() => m_Context.RemoteEndPoint.Address.ToString(); /// /// Liefert den TCP/IP Port, an den die HHTP Antwort gesendet wird. /// /// Der TCP/IP Port fr die Rckgabedaten. - public override int GetRemotePort() - { - // Forward - return m_Context.RemoteEndPoint.Port; - } + public override int GetRemotePort() => m_Context.RemoteEndPoint.Port; /// /// Ermittelt die lokale URI zum Aufruf. /// /// URI relativ zum Server. - public override string GetUriPath() - { - // Forward to context - return m_Context.Url.LocalPath; - } + public override string GetUriPath() => m_Context.Url.LocalPath; /// /// Ubertrgt einen vordefinierten HTTP Header Wert. /// /// Index des vorderfinierten Wertes. /// In den Header zu bernehmende Daten. - public override void SendKnownResponseHeader( int index, string value ) - { - // Forward to context - m_Context.SetHeader( HttpWorkerRequest.GetKnownResponseHeaderName( index ), value ); - } + public override void SendKnownResponseHeader( int index, string value ) => m_Context.SetHeader( HttpWorkerRequest.GetKnownResponseHeaderName( index ), value ); /// /// bertrgt den Inhalt einer Datei zum Aufrufer. @@ -247,42 +207,26 @@ public override void SendResponseFromMemory( byte[] data, int length ) /// /// HTTP Statuscode. /// Ergnzende Bexschreibung zum Status. - public override void SendStatus( int statusCode, string statusDescription ) - { - // Forward to context - m_Context.SetStatus( statusCode, statusDescription ); - } + public override void SendStatus( int statusCode, string statusDescription ) => m_Context.SetStatus( statusCode, statusDescription ); /// /// bertrgt einen HTTP Header Wert. /// /// Name des Header Wertes. /// In den Header zu bernehmende Daten. - public override void SendUnknownResponseHeader( string name, string value ) - { - // Blind forward as is - m_Context.SetHeader( name, value ); - } + public override void SendUnknownResponseHeader( string name, string value ) => m_Context.SetHeader( name, value ); /// /// Liefert den Namen des virtuellen Verzeichnisses. /// /// Das virtuelle Verzeichnis. - public override string GetAppPath() - { - // Report - return HttpRuntime.AppDomainAppVirtualPath; - } + public override string GetAppPath() => HttpRuntime.AppDomainAppVirtualPath; /// /// Liefert den physikalischen Pfad zum virtuellen Verzeichnis. /// /// Voller Pfad zum physikalischen Verzeichnis. - public override string GetAppPathTranslated() - { - // Report - return HttpRuntime.AppDomainAppPath; - } + public override string GetAppPathTranslated() => HttpRuntime.AppDomainAppPath; /// /// Ermittelt den virtuellen Pfad zum HTTP Zugriff. @@ -291,16 +235,18 @@ public override string GetAppPathTranslated() public override string GetFilePath() { // Load - string path = base.GetFilePath(); + var path = base.GetFilePath(); // Split - string[] parts = path.Split( '/' ); + var parts = path.Split( '/' ); // Not allowed - if (parts.Length < 3) return path; + if (parts.Length < 3) + return path; // Check for Web Service call - if (!parts[parts.Length - 2].ToLower().EndsWith( ".asmx" )) return path; + if (!parts[parts.Length - 2].ToLower().EndsWith( ".asmx" )) + return path; // Cut off the method name return path.Substring( 0, path.LastIndexOf( '/' ) ); @@ -313,10 +259,10 @@ public override string GetFilePath() public override string GetFilePathTranslated() { // The the path - string path = GetFilePath(); + var path = GetFilePath(); // Cut length - int cut = HttpRuntime.AppDomainAppVirtualPath.Length + 1; + var cut = HttpRuntime.AppDomainAppVirtualPath.Length + 1; // Test if (path.Length > cut) @@ -363,13 +309,14 @@ public override string GetKnownRequestHeader( int index ) public override string GetPathInfo() { // Retrieve full path - string basePath = GetFilePath(); + var basePath = GetFilePath(); // Retrieve local path - string local = m_Context.Url.LocalPath; + var local = m_Context.Url.LocalPath; // Absolute - if (basePath.Length >= local.Length) return string.Empty; + if (basePath.Length >= local.Length) + return string.Empty; // Get suffix return local.Substring( basePath.Length ); @@ -412,22 +359,23 @@ public override string GetServerVariable( string name ) public override string[][] GetUnknownRequestHeaders() { // Result - List pairs = new List(); + var pairs = new List(); // Create as list - NameValueCollection headers = m_Context.RequestHeaders; + var headers = m_Context.RequestHeaders; // All of it - for (int i = 0; i < headers.Count; ++i) + for (var i = 0; i < headers.Count; ++i) { // Load the name - string name = headers.GetKey( i ); + var name = headers.GetKey( i ); // Do not use - if (GetKnownRequestHeaderIndex( name ) >= 0) continue; + if (GetKnownRequestHeaderIndex( name ) >= 0) + continue; // Remember - pairs.Add( new string[] { name, headers.Get( i ) } ); + pairs.Add( new[] { name, headers.Get( i ) } ); } // Done @@ -438,11 +386,7 @@ public override string[][] GetUnknownRequestHeaders() /// Ermittelt den aktuellen Anwender. /// /// Windows interne Referenz (Token) zum aktuellen Anwender. - public override IntPtr GetUserToken() - { - // Forward - return m_Context.UserToken; - } + public override IntPtr GetUserToken() => m_Context.UserToken; /// /// List die bertragenen Nutzdaten. @@ -450,21 +394,13 @@ public override IntPtr GetUserToken() /// Speicherbereich fr den Emfpang der Daten. /// Anzahl der zu lesenden Bytes. /// Anzahl der gelesenen Bytes. - public override int ReadEntityBody( byte[] buffer, int size ) - { - // Forward - return m_Context.InputStream.Read( buffer, 0, size ); - } + public override int ReadEntityBody( byte[] buffer, int size ) => m_Context.InputStream.Read( buffer, 0, size ); /// /// Prfe, ob der aktuelle HTTP Zugriff SSL verwendet. /// /// Gesetzt, wenn die Verbindung zum Aufrufer ber SSL erfolgt. - public override bool IsSecure() - { - // Forward - return m_Context.IsSecureConnection; - } + public override bool IsSecure() => m_Context.IsSecureConnection; /// /// Ermittelt den Namen dieses Rechners. @@ -473,16 +409,17 @@ public override bool IsSecure() public override string GetServerName() { // Load - string name = GetKnownRequestHeader( HeaderHost ); + var name = GetKnownRequestHeader( HeaderHost ); // Use it if (!string.IsNullOrEmpty( name )) { // Check for port - string[] splitName = name.Split( ':' ); + var splitName = name.Split( ':' ); // Can use it - if ((1 == splitName.Length) || (2 == splitName.Length)) return splitName[0]; + if ((1 == splitName.Length) || (2 == splitName.Length)) + return splitName[0]; } // Default diff --git a/VCR.NET/ServiceCore/WebServer/ServerHost.cs b/VCR.NET/ServiceCore/WebServer/ServerHost.cs index 99baf30..5d53ea2 100644 --- a/VCR.NET/ServiceCore/WebServer/ServerHost.cs +++ b/VCR.NET/ServiceCore/WebServer/ServerHost.cs @@ -44,10 +44,7 @@ public PrimaryEndPoint( VCRServer server ) /// Wird aufgerufen, sobald die Laufzeitumgebung gestartet wurde. /// /// Die neu angelegte Laufzeitumgebung. - protected override void RuntimeStarted( ServerRuntime runtime ) - { - runtime.SetServer( m_server ); - } + protected override void RuntimeStarted( ServerRuntime runtime ) => runtime.SetServer( m_server ); } /// @@ -159,11 +156,7 @@ public void Stop() /// Dient zur Freigabe aller verwendeten Ressourcen. /// /// - public void Dispose() - { - // Finish - Stop(); - } + public void Dispose() => Stop(); #endregion } diff --git a/VCR.NET/ServiceCore/WebServer/ServerRuntime.cs b/VCR.NET/ServiceCore/WebServer/ServerRuntime.cs index e993500..6507d21 100644 --- a/VCR.NET/ServiceCore/WebServer/ServerRuntime.cs +++ b/VCR.NET/ServiceCore/WebServer/ServerRuntime.cs @@ -1,11 +1,10 @@ +using JMS.DVB; +using JMS.DVBVCR.RecordingService.Persistence; +using Microsoft.Web.Infrastructure.DynamicModuleHelper; using System; using System.Collections.Generic; using System.Diagnostics; -using System.Security.Principal; using System.Web; -using JMS.DVB; -using JMS.DVBVCR.RecordingService.Persistence; -using Microsoft.Web.Infrastructure.DynamicModuleHelper; namespace JMS.DVBVCR.RecordingService.WebServer @@ -18,17 +17,13 @@ public class ApplicationRuntime : MarshalByRefObject /// /// Meldet die , in der ASP.NET luft. /// - public AppDomain AppDomain { get { return AppDomain.CurrentDomain; } } + public AppDomain AppDomain => AppDomain.CurrentDomain; /// /// Instanzen dieser Klasse sind nicht zeitgebunden. /// /// Die Antwort muss immer null sein. - public override object InitializeLifetimeService() - { - // No lease at all - return null; - } + public override object InitializeLifetimeService() => null; /// /// Wird periodisch aufgerufen um zu sehen, ob die Anwendung noch verfgbar ist. @@ -41,11 +36,7 @@ public void Test() /// Beginnt mit der Ausfhrung einer Anfrage. /// /// Die Anfrage. - public void ProcessRequest( ContextAccessor context ) - { - // Execute - HttpRuntime.ProcessRequest( new Request( context ) ); - } + public void ProcessRequest( ContextAccessor context ) => HttpRuntime.ProcessRequest( new Request( context ) ); /// /// Beendet die ASP.NET Laufzeitumgebung. @@ -54,11 +45,7 @@ public void ProcessRequest( ContextAccessor context ) /// Der Aufruf kehrt erst wieder zurck, wenn alle ausstehenden Anfragen bearbeitet /// wurden. Neue Anfragen werden nicht angenommen. /// - public virtual void Stop() - { - // Shutdown ASP.NET properly - HttpRuntime.Close(); - } + public virtual void Stop() => HttpRuntime.Close(); } /// @@ -154,11 +141,7 @@ public static VCRServer VCRServer /// Prft, ob ein Anwender Zugriff auf die Webanwendung hat. /// /// Gesetzt, wenn es sich sogar um einen Administrator handelt. - public static bool TestWebAccess() - { - // Forward - return TestWebAccess( true ); - } + public static bool TestWebAccess() => TestWebAccess( true ); /// /// Prft, ob ein Anwender Zugriff auf den VCR.NET Recording Service hat. @@ -173,18 +156,16 @@ public static bool TestWebAccess( bool endOnFail ) return true; // Attach to the current context - HttpContext request = HttpContext.Current; + var request = HttpContext.Current; // Attach to user - IPrincipal user = request.User; + var user = request.User; // See if user is provided - if (null != user) + if (user != null) { // Get the user role - string userRole = VCRConfiguration.Current.UserRole; - - // No restriction + var userRole = VCRConfiguration.Current.UserRole; if (string.IsNullOrEmpty( userRole )) return true; @@ -216,7 +197,7 @@ public static void TestAdminAccess() return; // Attach to the current context - HttpContext request = HttpContext.Current; + var request = HttpContext.Current; // Reject request.Response.StatusCode = 401; @@ -265,7 +246,7 @@ public static string GetUniqueWebId( VCRJob job, VCRSchedule schedule ) if (job == null) return "*"; else if (schedule == null) - return string.Format( "*{0:N}", job.UniqueID.Value ); + return $"*{job.UniqueID.Value:N}"; else return GetUniqueWebId( job.UniqueID.Value, schedule.UniqueID.Value ); } @@ -286,7 +267,7 @@ public static string GetUniqueWebId( string job, string schedule ) schedule = Guid.Empty.ToString( "N" ); // Create - return string.Format( "{0}{1}", job, schedule ); + return $"{job}{schedule}"; } /// @@ -296,11 +277,7 @@ public static string GetUniqueWebId( string job, string schedule ) /// Die eindeutige Kennung eines Auftrags. /// Die eindeutige Kennung einer Aufzeichnung des Auftrags. /// Die eindeutige Referenz. - public static string GetUniqueWebId( Guid job, Guid schedule ) - { - // Forward - return GetUniqueWebId( job.ToString( "N" ), schedule.ToString( "N" ) ); - } + public static string GetUniqueWebId( Guid job, Guid schedule ) => GetUniqueWebId( job.ToString( "N" ), schedule.ToString( "N" ) ); /// /// Rekonstruiert einen Auftrag und eine Aufzeichnung aus einer Textdarstellung. @@ -323,9 +300,7 @@ public static void ParseUniqueWebId( string id, out Guid job, out Guid schedule /// Die zugehrige Aufzeichnung im Auftrag. public static VCRSchedule ParseUniqueWebId( string id, out VCRJob job ) { - // Read all - Guid jobID, scheduleID; - ParseUniqueWebId( id, out jobID, out scheduleID ); + ParseUniqueWebId( id, out Guid jobID, out Guid scheduleID ); // Find the job job = VCRServer.FindJob( jobID ); @@ -418,7 +393,7 @@ public static class ServerRuntimeExtensions public static bool GetUsesDolbyAudio( this StreamSelection streams ) { // Check mode - if (null == streams) + if (streams == null) return false; else if (streams.AC3Tracks.LanguageMode != LanguageModes.Selection) return true; @@ -431,14 +406,7 @@ public static bool GetUsesDolbyAudio( this StreamSelection streams ) /// /// Die Datenstromkonfiguration. /// Gesetzt, wenn alle Tonspuren aufgezeichnet werden sollen. - public static bool GetUsesAllAudio( this StreamSelection streams ) - { - // Check mode - if (null == streams) - return false; - else - return (streams.MP2Tracks.LanguageMode == LanguageModes.All); - } + public static bool GetUsesAllAudio( this StreamSelection streams ) => (streams != null) && (streams.MP2Tracks.LanguageMode == LanguageModes.All); /// /// Prft, ob eine Datenstromkonfiguration DVB Untertitel nicht @@ -449,7 +417,7 @@ public static bool GetUsesAllAudio( this StreamSelection streams ) public static bool GetUsesSubtitles( this StreamSelection streams ) { // Check mode - if (null == streams) + if (streams == null) return false; else if (streams.SubTitles.LanguageMode != LanguageModes.Selection) return true; @@ -462,28 +430,14 @@ public static bool GetUsesSubtitles( this StreamSelection streams ) /// /// Die Datenstromkonfiguration. /// Gesetzt, wenn der Videotext aufgezeichnet werden soll. - public static bool GetUsesVideotext( this StreamSelection streams ) - { - // Check mode - if (null == streams) - return false; - else - return streams.Videotext; - } + public static bool GetUsesVideotext( this StreamSelection streams ) => (streams != null) && streams.Videotext; /// /// Prft, ob eine Datenstromkonfiguration auch einen Extrakt der Programmzeitschrift umfasst. /// /// Die Datenstromkonfiguration. /// Gesetzt, wenn die Programmzeitschrift bercksichtigt werden soll. - public static bool GetUsesProgramGuide( this StreamSelection streams ) - { - // Check mode - if (null == streams) - return false; - else - return streams.ProgramGuide; - } + public static bool GetUsesProgramGuide( this StreamSelection streams ) => (streams != null) && streams.ProgramGuide; /// /// Legt fest, ob die Dolby Digital Tonspur aufgezeichnet werden soll. @@ -518,15 +472,9 @@ public static void SetUsesAllAudio( this StreamSelection streams, bool set ) // Check mode if (set) - { - // All streams.MP2Tracks.LanguageMode = LanguageModes.All; - } else - { - // Remember streams.MP2Tracks.LanguageMode = LanguageModes.Primary; - } // Forward if (streams.AC3Tracks.LanguageMode != LanguageModes.Selection) @@ -555,10 +503,6 @@ public static void SetUsesSubtitles( this StreamSelection streams, bool set ) /// /// Die Konfiguration der zu verwendenden Datenstrme. /// Gesetzt, wenn die Datenspur aktiviert werden soll. - public static void SetUsesVideotext( this StreamSelection streams, bool set ) - { - // Direct - streams.Videotext = set; - } + public static void SetUsesVideotext( this StreamSelection streams, bool set ) => streams.Videotext = set; } } diff --git a/VCR.NET/ServiceCore/WebServer/StarterModule.cs b/VCR.NET/ServiceCore/WebServer/StarterModule.cs index 651d2d5..c04f839 100644 --- a/VCR.NET/ServiceCore/WebServer/StarterModule.cs +++ b/VCR.NET/ServiceCore/WebServer/StarterModule.cs @@ -22,8 +22,8 @@ public class StarterModule : IHttpModule /// Alle Dateiendungen, für die wir ETags erzeugen. /// private static readonly HashSet _ETagExtensions = - new HashSet( StringComparer.InvariantCultureIgnoreCase ) - { + new HashSet( StringComparer.InvariantCultureIgnoreCase ) + { ".html", ".css", ".js", @@ -93,7 +93,7 @@ private static void OnBeginRequest( object sender, EventArgs e ) // Check out context var context = HttpContext.Current; - var worker = ((IServiceProvider) context).GetService( typeof( HttpWorkerRequest ) ) as Request; + var worker = ((IServiceProvider)context).GetService( typeof( HttpWorkerRequest ) ) as Request; if (worker == null) return; @@ -138,7 +138,7 @@ private static void OnEndRequest( object sender, EventArgs e ) return; // Check our context - var worker = ((IServiceProvider) context).GetService( typeof( HttpWorkerRequest ) ) as Request; + var worker = ((IServiceProvider)context).GetService( typeof( HttpWorkerRequest ) ) as Request; if (worker == null) return; @@ -178,7 +178,7 @@ private static string GetETag() // Convert var modifiedAsFileTime = lastModified.ToFileTime(); var nowAsFileTime = utcNow.ToFileTime(); - var etag = string.Format( "\"{0:X8}\"", modifiedAsFileTime ); + var etag = $"\"{modifiedAsFileTime:X8}\""; // Check mode if ((nowAsFileTime - modifiedAsFileTime) <= 30000000L) diff --git a/VCR.NET/ServiceCore/WebServer/UserProfileManager.cs b/VCR.NET/ServiceCore/WebServer/UserProfileManager.cs index 47f285e..3e78ea2 100644 --- a/VCR.NET/ServiceCore/WebServer/UserProfileManager.cs +++ b/VCR.NET/ServiceCore/WebServer/UserProfileManager.cs @@ -3,7 +3,6 @@ using System.Collections.Specialized; using System.Configuration; using System.IO; -using System.Reflection; using System.Web; using System.Web.Profile; using System.Xml; @@ -47,10 +46,7 @@ public UserProfileManager() /// /// Die Namen der Anwender, deren Profile entfernt werden sollen. /// Die Anzahl der entfernten Profile. - public override int DeleteProfiles( string[] usernames ) - { - return 0; - } + public override int DeleteProfiles( string[] usernames ) => 0; /// /// Wird zum Lschen von Benutzerprofilen aufgerufen und macht in dieser Implementierung @@ -58,10 +54,7 @@ public override int DeleteProfiles( string[] usernames ) /// /// Eine Sammlung der zu lschenden Profile.. /// Die Anzahl der entfernten Profile. - public override int DeleteProfiles( ProfileInfoCollection profiles ) - { - return 0; - } + public override int DeleteProfiles( ProfileInfoCollection profiles ) => 0; /// /// Jscht nicht mehr verwendete Benutzerprofile. @@ -69,10 +62,7 @@ public override int DeleteProfiles( ProfileInfoCollection profiles ) /// Die Art der Benutzerauthentisierung. /// Das Bezugsdatum fr die Prfung auf Inaktivitt. /// Die Anzahl der entfernten Profile. - public override int DeleteInactiveProfiles( ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate ) - { - return 0; - } + public override int DeleteInactiveProfiles( ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate ) => 0; /// /// Ermittelt die Anzahl nicht mehr verwendeter Benutzerprofile. @@ -80,10 +70,7 @@ public override int DeleteInactiveProfiles( ProfileAuthenticationOption authenti /// Die Art der Benutzerauthentisierung. /// Das Bezugsdatum fr die Prfung auf Inaktivitt. /// Die Anzahl der nicht mehr verwendeten Benutzerprofile. - public override int GetNumberOfInactiveProfiles( ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate ) - { - return 0; - } + public override int GetNumberOfInactiveProfiles( ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate ) => 0; /// /// Erzeugt eine leere Auflistung fr Benutzerprofile. @@ -110,11 +97,7 @@ private ProfileInfoCollection CreateEmptyCollection( out int totalRecords ) /// Die Anzahl der Profile pro Seite. /// Meldet die gesamte Anzahl von Profilen. /// Eine auflistung mit den gewnschten Profilen. - public override ProfileInfoCollection GetAllProfiles( ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords ) - { - // Forward - return CreateEmptyCollection( out totalRecords ); - } + public override ProfileInfoCollection GetAllProfiles( ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords ) => CreateEmptyCollection( out totalRecords ); /// /// Meldet alle Benutzerprofile, die nicht mehr verwendet werden. @@ -125,11 +108,7 @@ public override ProfileInfoCollection GetAllProfiles( ProfileAuthenticationOptio /// Die Anzahl der Profile pro Seite. /// Meldet die gesamte Anzahl von Profilen. /// Eine auflistung mit den gewnschten Profilen. - public override ProfileInfoCollection GetAllInactiveProfiles( ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords ) - { - // Forward - return CreateEmptyCollection( out totalRecords ); - } + public override ProfileInfoCollection GetAllInactiveProfiles( ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords ) => CreateEmptyCollection( out totalRecords ); /// /// Meldet alle Benutzerprofile zu einem Benutzernamen. @@ -140,11 +119,7 @@ public override ProfileInfoCollection GetAllInactiveProfiles( ProfileAuthenticat /// Die Anzahl der Profile pro Seite. /// Meldet die gesamte Anzahl von Profilen. /// Eine auflistung mit den gewnschten Profilen. - public override ProfileInfoCollection FindProfilesByUserName( ProfileAuthenticationOption authenticationOption, string usernameToMatch, int pageIndex, int pageSize, out int totalRecords ) - { - // Forward - return CreateEmptyCollection( out totalRecords ); - } + public override ProfileInfoCollection FindProfilesByUserName( ProfileAuthenticationOption authenticationOption, string usernameToMatch, int pageIndex, int pageSize, out int totalRecords ) => CreateEmptyCollection( out totalRecords ); /// /// Meldet alle nicht mehr verwendeten Benutzerprofile zu einem Benutzernamen. @@ -156,11 +131,7 @@ public override ProfileInfoCollection FindProfilesByUserName( ProfileAuthenticat /// Die Anzahl der Profile pro Seite. /// Meldet die gesamte Anzahl von Profilen. /// Eine auflistung mit den gewnschten Profilen. - public override ProfileInfoCollection FindInactiveProfilesByUserName( ProfileAuthenticationOption authenticationOption, string usernameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords ) - { - // Forward - return CreateEmptyCollection( out totalRecords ); - } + public override ProfileInfoCollection FindInactiveProfilesByUserName( ProfileAuthenticationOption authenticationOption, string usernameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords ) => CreateEmptyCollection( out totalRecords ); /// /// Ermittelt alle Eintrge aus einem Benutzerprofil. @@ -171,7 +142,7 @@ public override ProfileInfoCollection FindInactiveProfilesByUserName( ProfileAut public override SettingsPropertyValueCollection GetPropertyValues( SettingsContext context, SettingsPropertyCollection collection ) { // Profile data - XmlDocument xml = new XmlDocument(); + var xml = new XmlDocument(); // Must be autenticated if ((bool) context["IsAuthenticated"]) @@ -231,7 +202,7 @@ public override SettingsPropertyValueCollection GetPropertyValues( SettingsConte var parse = property.PropertyType.GetMethod( "Parse", ParseSignature ); // Set current value - if (null == parse) + if (parse == null) value.PropertyValue = defaultValue; else value.PropertyValue = parse.Invoke( null, new object[] { defaultValue } ); @@ -305,21 +276,11 @@ private string GetUserProfile( SettingsContext context ) /// /// Meldet eine Beschreibung. /// - public override string Description { get { return "User Profile Manager for VCR.NET"; } } + public override string Description => "User Profile Manager for VCR.NET"; /// /// Meldet unseren Namen. /// - public override string Name { get { return "VCRNETProvider"; } } - - /// - /// - /// - /// - /// - public override void Initialize( string name, NameValueCollection config ) - { - base.Initialize( name, config ); - } + public override string Name => "VCRNETProvider"; } } diff --git a/VCR.NET/ServiceCore/WebServer/UserProfileSettings.cs b/VCR.NET/ServiceCore/WebServer/UserProfileSettings.cs index fd10869..747c325 100644 --- a/VCR.NET/ServiceCore/WebServer/UserProfileSettings.cs +++ b/VCR.NET/ServiceCore/WebServer/UserProfileSettings.cs @@ -13,7 +13,7 @@ public static class UserProfileSettings /// /// Meldet die Liste der zuletzt verwendenden Sendern. /// - public static StringCollection RecentChannels { get { return (StringCollection) Profile["RecentChannels"]; } } + public static StringCollection RecentChannels => (StringCollection) Profile["RecentChannels"]; /// /// Meldet die maximal erlaubte Anzahl von Sendern in der Liste zuletzt verwendeter Sender. @@ -27,7 +27,7 @@ public static int MaxRecentChannels /// /// Meldet das aktuelle Benutzerprofil. /// - private static ProfileBase Profile { get { return HttpContext.Current.Profile; } } + private static ProfileBase Profile => HttpContext.Current.Profile; /// /// Begrenzt die Anzahl der zuletzt verwendeten Quellen auf die Hchstgrenze. diff --git a/VCR.NET/ServiceCore/Win32Tools/LogonManager.cs b/VCR.NET/ServiceCore/Win32Tools/LogonManager.cs index 1863a2a..2dece9e 100644 --- a/VCR.NET/ServiceCore/Win32Tools/LogonManager.cs +++ b/VCR.NET/ServiceCore/Win32Tools/LogonManager.cs @@ -69,21 +69,18 @@ private static string ShellName get { // Try to open - 64 Bit first on 64 Bit OS - IntPtr key; - if (RegOpenKeyEx( LocalMachineKey, KeyName, 0, 0x20119, out key ) == 0) + if (RegOpenKeyEx(LocalMachineKey, KeyName, 0, 0x20119, out IntPtr key) == 0) try { - // Try to read the value - Int32 size, type; - if (RegQueryValueEx( key, ValueName, IntPtr.Zero, out type, null, out size ) == 0) + if (RegQueryValueEx(key, ValueName, IntPtr.Zero, out int type, null, out int size) == 0) if ((type == 1) || (type == 2)) if (size > 1) { // Allocate enough space - var buffer = new StringBuilder( size + 1 ); + var buffer = new StringBuilder(size + 1); // Read - if (RegQueryValueEx( key, ValueName, IntPtr.Zero, out type, buffer, out size ) == 0) + if (RegQueryValueEx(key, ValueName, IntPtr.Zero, out type, buffer, out size) == 0) { // Finish buffer buffer.Length = size - 1; @@ -96,7 +93,7 @@ private static string ShellName finally { // Free resources - RegCloseKey( key ); + RegCloseKey(key); } // Find the name of the shell diff --git a/VCR.NET/ServiceCore/packages.config b/VCR.NET/ServiceCore/packages.config index 2d0a340..6d69429 100644 --- a/VCR.NET/ServiceCore/packages.config +++ b/VCR.NET/ServiceCore/packages.config @@ -1,11 +1,11 @@  - - - - - - + + + + + + - + \ No newline at end of file diff --git a/VCR.NET/StandByTool/Program.cs b/VCR.NET/StandByTool/Program.cs new file mode 100644 index 0000000..8eae91f --- /dev/null +++ b/VCR.NET/StandByTool/Program.cs @@ -0,0 +1,28 @@ +using System; +using System.Windows.Forms; + +namespace StandByTool +{ + static class Program + { + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault( false ); + + if (MessageBox.Show( new Form(), "Soll dieser Rechner in den Schlafzustand versetzt werden?", "VCR.NET Schlafzustand", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1 ) == DialogResult.Yes) + VCRControlCenter.VCRNETRestProxy.TryHibernate( "http://localhost/vcr.net" ); + } + } +} + +namespace VCRControlCenter +{ + static class VCRNETControl + { + public static void Log( string format, params string[] args ) + { + } + } +} diff --git a/VCR.NET/StandByTool/Properties/AssemblyInfo.cs b/VCR.NET/StandByTool/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..87c2b9e --- /dev/null +++ b/VCR.NET/StandByTool/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "StandByTool" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "" )] +[assembly: AssemblyProduct( "StandByTool" )] +[assembly: AssemblyCopyright( "Copyright © 2014" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "a97deb2b-e326-44c5-91e5-5da0d6f008c2" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/VCR.NET/StandByTool/Properties/Resources.Designer.cs b/VCR.NET/StandByTool/Properties/Resources.Designer.cs new file mode 100644 index 0000000..36d0dc2 --- /dev/null +++ b/VCR.NET/StandByTool/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace StandByTool.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("StandByTool.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/VCR.NET/StandByTool/Properties/Resources.resx b/VCR.NET/StandByTool/Properties/Resources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/VCR.NET/StandByTool/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/VCR.NET/StandByTool/Properties/Settings.Designer.cs b/VCR.NET/StandByTool/Properties/Settings.Designer.cs new file mode 100644 index 0000000..2d59d5b --- /dev/null +++ b/VCR.NET/StandByTool/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34209 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace StandByTool.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/VCR.NET/StandByTool/Properties/Settings.settings b/VCR.NET/StandByTool/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/VCR.NET/StandByTool/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/VCR.NET/StandByTool/StandByTool.csproj b/VCR.NET/StandByTool/StandByTool.csproj new file mode 100644 index 0000000..455d35b --- /dev/null +++ b/VCR.NET/StandByTool/StandByTool.csproj @@ -0,0 +1,93 @@ + + + + + Debug + AnyCPU + {F1FAA708-96C3-44F9-BE64-3FBB44488C9C} + WinExe + Properties + StandByTool + StandByTool + v4.5.1 + 512 + + + + AnyCPU + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\ + TRACE + prompt + 4 + false + + + app.ico + + + + False + ..\packages\Newtonsoft.Json.6.0.7\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + + + + VCRNETRestProxy.cs + + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + \ No newline at end of file diff --git a/VCR.NET/StandByTool/app.ico b/VCR.NET/StandByTool/app.ico new file mode 100644 index 0000000..65bc69f Binary files /dev/null and b/VCR.NET/StandByTool/app.ico differ diff --git a/VCR.NET/TVBrowserPlugIn/Properties/AssemblyInfo.cs b/VCR.NET/TVBrowserPlugIn/Properties/AssemblyInfo.cs index 2455163..5aea79a 100644 --- a/VCR.NET/TVBrowserPlugIn/Properties/AssemblyInfo.cs +++ b/VCR.NET/TVBrowserPlugIn/Properties/AssemblyInfo.cs @@ -29,4 +29,5 @@ // Build Number // Revision // -[assembly: AssemblyVersion( "4.3.0.0" )] +[assembly: AssemblyVersion( "4.5.0.0" )] +[assembly: AssemblyFileVersion("4.5.0.0")] diff --git a/VCR.NET/TVBrowserPlugIn/TVBrowserPlugIn.csproj b/VCR.NET/TVBrowserPlugIn/TVBrowserPlugIn.csproj index 364cf37..9e922d7 100644 --- a/VCR.NET/TVBrowserPlugIn/TVBrowserPlugIn.csproj +++ b/VCR.NET/TVBrowserPlugIn/TVBrowserPlugIn.csproj @@ -54,9 +54,9 @@ false - - False - ..\packages\Newtonsoft.Json.6.0.7\lib\net45\Newtonsoft.Json.dll + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + True @@ -151,8 +151,8 @@ --> - rem xcopy /y /q "$(TargetPath)" "C:\Program Files\JMS\VCR.NET" -rem xcopy /y /q "$(TargetPath).config" "C:\Program Files\JMS\VCR.NET" -rem xcopy /y /q "$(TargetDir)de\TVBrowserPlugIn.resources.dll" "C:\Program Files\JMS\VCR.NET\de" + rem xcopy /y /q "$(TargetPath)" "C:\Program Files (x86)\JMS\VCR.NET" +rem xcopy /y /q "$(TargetPath).config" "C:\Program Files (x86)\JMS\VCR.NET" +rem xcopy /y /q "$(TargetDir)de\TVBrowserPlugIn.resources.dll" "C:\Program Files (x86)\JMS\VCR.NET\de" \ No newline at end of file diff --git a/VCR.NET/TVBrowserPlugIn/packages.config b/VCR.NET/TVBrowserPlugIn/packages.config index ba2b301..3e14be6 100644 --- a/VCR.NET/TVBrowserPlugIn/packages.config +++ b/VCR.NET/TVBrowserPlugIn/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/VCR.NET/Tests/Upgrade Test/Upgrade Test.csproj b/VCR.NET/Tests/Upgrade Test/Upgrade Test.csproj index e4631e8..0adcba0 100644 --- a/VCR.NET/Tests/Upgrade Test/Upgrade Test.csproj +++ b/VCR.NET/Tests/Upgrade Test/Upgrade Test.csproj @@ -32,18 +32,18 @@ - ..\..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.0\GAC\JMS.DVB.Common.dll + ..\..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.0\GAC\JMS.DVB.Common.dll - ..\..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.0\RunTime\JMS.DVB.HardwareAbstraction.dll + ..\..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.0\RunTime\JMS.DVB.HardwareAbstraction.dll False - ..\..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.0\RunTime\JMS.DVB.SITables.dll + ..\..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.0\RunTime\JMS.DVB.SITables.dll False - ..\..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.0\RunTime\JMS.DVB.SourceManagement.dll + ..\..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.0\RunTime\JMS.DVB.SourceManagement.dll False diff --git a/VCR.NET/Unit Test Collection/CombinedSchedulerTests.cs b/VCR.NET/Unit Test Collection/CombinedSchedulerTests.cs index ef86b7f..df8d484 100644 --- a/VCR.NET/Unit Test Collection/CombinedSchedulerTests.cs +++ b/VCR.NET/Unit Test Collection/CombinedSchedulerTests.cs @@ -68,17 +68,13 @@ public CombinedSchedulerTests() // Create directory m_jobDirectory.Create(); - // Path of the scratch file - var zipPath = Path.Combine( m_jobDirectory.FullName, "temp.zip" ); - - // Copy our archive to the directory - File.WriteAllBytes( zipPath, Properties.Resources.TestJobs ); - // Extract [.NET 4.5] - //ZipFile.ExtractToDirectory( zipPath, m_jobDirectory.FullName ); - - // Forget it - File.Delete( zipPath ); + using (var zipStream = new MemoryStream( Properties.Resources.TestJobs )) + using (var zip = new ZipArchive( zipStream )) + foreach (var entry in zip.Entries) + using (var source = entry.Open()) + using (var target = new FileStream( Path.Combine( m_jobDirectory.FullName, entry.Name ), FileMode.CreateNew, FileAccess.Write, FileShare.None )) + source.CopyTo( target ); // Process all files m_jobs = @@ -174,7 +170,7 @@ public void FullValidation() // Create component under Test using (var cfg = TestConfigurationProvider.Create( Properties.Resources.AllSchedulers )) using (var cut = RecordingPlanner.Create( this )) - for (int i = 250; i-- > 0; ) + for (int i = 250; i-- > 0;) cut.DispatchNextActivity( m_planTime ); } diff --git a/VCR.NET/Unit Test Collection/Unit Test Collection.csproj b/VCR.NET/Unit Test Collection/Unit Test Collection.csproj index 67683db..c24a408 100644 --- a/VCR.NET/Unit Test Collection/Unit Test Collection.csproj +++ b/VCR.NET/Unit Test Collection/Unit Test Collection.csproj @@ -41,28 +41,31 @@ - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\RunTime\JMS.DVB.Algorithms.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\RunTime\JMS.DVB.Algorithms.dll False - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\RunTime\JMS.DVB.HardwareAbstraction.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\RunTime\JMS.DVB.HardwareAbstraction.dll False - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\RunTime\JMS.DVB.SITables.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\RunTime\JMS.DVB.SITables.dll False - ..\..\..\..\..\..\..\Program Files\JMS\DVB.NET 4.3\RunTime\JMS.DVB.SourceManagement.dll + ..\..\..\..\..\..\..\Program Files (x86)\JMS\DVB.NET 4.3\RunTime\JMS.DVB.SourceManagement.dll False - + + False + 3.5 + diff --git a/VCR.NET/Unit Test Collection/app.config b/VCR.NET/Unit Test Collection/app.config index 4429813..8460dd4 100644 --- a/VCR.NET/Unit Test Collection/app.config +++ b/VCR.NET/Unit Test Collection/app.config @@ -4,7 +4,7 @@ - + diff --git a/VCR.NET/VCR.NET.sln b/VCR.NET/VCR.NET.sln index 959a0e5..35cbfae 100644 --- a/VCR.NET/VCR.NET.sln +++ b/VCR.NET/VCR.NET.sln @@ -1,11 +1,12 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EFF4945E-6C0C-4179-97C8-6FF592789C19}" ProjectSection(SolutionItems) = preProject Local.testsettings = Local.testsettings + package.json = package.json TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings VCR.NET.vsmdi = VCR.NET.vsmdi EndProjectSection @@ -145,6 +146,9 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6487A231-0153-4E1F-9080-DD46EC6452D0} + EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = VCR.NET.vsmdi EndGlobalSection diff --git a/VCR.NET/VCRNETSetup/Deutsch.wxl b/VCR.NET/VCRNETSetup/Deutsch.wxl index 226f831..d473933 100644 --- a/VCR.NET/VCRNETSetup/Deutsch.wxl +++ b/VCR.NET/VCRNETSetup/Deutsch.wxl @@ -2,7 +2,6 @@ VCR.NET Recording Service - Quellcode Der VCR.NET Recording Service setzt eine Installation des Microsoft .NET Frameworks in der Version 4.5.1 voraus. Vor der Installation muss die existierende Version des VCR.NET Recording Service deinstalliert werden. Zur Installation des VCR.NET Recording Service muss DVB.NET inklusive des Card Servers bereits installiert sein. Die aktuelle Version kann hier heruntergeladen werden: diff --git a/VCR.NET/VCRNETSetup/DirectoryTree.wxs b/VCR.NET/VCRNETSetup/DirectoryTree.wxs index ff7d44a..064d5fe 100644 --- a/VCR.NET/VCRNETSetup/DirectoryTree.wxs +++ b/VCR.NET/VCRNETSetup/DirectoryTree.wxs @@ -43,70 +43,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -119,17 +55,5 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/VCR.NET/VCRNETSetup/Product.wxs b/VCR.NET/VCRNETSetup/Product.wxs index 5e3577f..cc2e0ed 100644 --- a/VCR.NET/VCRNETSetup/Product.wxs +++ b/VCR.NET/VCRNETSetup/Product.wxs @@ -93,28 +93,6 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/VCR.NET/VCRNETSetup/Service.wxs b/VCR.NET/VCRNETSetup/Service.wxs index f539e6d..238c29a 100644 --- a/VCR.NET/VCRNETSetup/Service.wxs +++ b/VCR.NET/VCRNETSetup/Service.wxs @@ -70,7 +70,7 @@ - + diff --git a/VCR.NET/VCRNETSetup/VCRNETSetup.wixproj b/VCR.NET/VCRNETSetup/VCRNETSetup.wixproj index 1a4e724..d419f1a 100644 --- a/VCR.NET/VCRNETSetup/VCRNETSetup.wixproj +++ b/VCR.NET/VCRNETSetup/VCRNETSetup.wixproj @@ -22,7 +22,7 @@ _Extensions.wxs obj\$(Configuration)\_Extensions.wixobj ICE57;ICE43 - SETUPVERSION=4.3.38 + SETUPVERSION=4.5.14 ..\..\msi\ @@ -33,7 +33,7 @@ ICE57;ICE43 _Extensions.wxs obj\$(Configuration)\_Extensions.wixobj - SETUPVERSION=4.3.38 + SETUPVERSION=4.5.14 @@ -153,13 +153,13 @@ - - “%25WIX%25\bin\heat.exe” dir "$(SolutionDir)FTPWrap/VCR.NET Extension" -ag -sfrag -dr Extensions -var var.ExtensionsPath -cg Extensions -srd -out "$(ProjectDir)_Extensions.wxs" - set "$(WixVariables)" -"%25ProgramFiles%25\Windows Kits\8.0\bin\x86\msiinfo.exe" "$(TargetDir)\de-de\$(TargetFileName)" /T "VCR.NET Recording Service %25SETUPVERSION%25" +"%25ProgramFiles%25\Windows Kits\10\bin\x86\msiinfo.exe" "$(TargetDir)\de-de\$(TargetFileName)" /T "VCR.NET Recording Service %25SETUPVERSION%25" + + + "%25WIX%25bin\heat.exe" dir "$(SolutionDir)FTPWrap/VCR.NET Extension" -ag -sfrag -dr Extensions -var var.ExtensionsPath -cg Extensions -srd -out "$(ProjectDir)_Extensions.wxs" |EventPluginHub| | Event | + * | | . | | +-----------+ | Propagators| + * | ReactEvent | . | | |TapEvent | |------------| + * | Emitter | . | |<---+|Plugin | |other plugin| + * | | . | | +-----------+ | utilities | + * | +-----------.--->| | +------------+ + * | | | . +--------------+ + * +-----|------+ . ^ +-----------+ + * | . | |Enter/Leave| + * + . +-------+|Plugin | + * +-------------+ . +-----------+ + * | application | . + * |-------------| . + * | | . + * | | . + * +-------------+ . + * . + * React Core . General Purpose Event Plugin System + */ + +var alreadyListeningTo = {}; +var isMonitoringScrollValue = false; +var reactTopListenersCounter = 0; + +// For events like 'submit' which don't consistently bubble (which we trap at a +// lower node than `document`), binding at `document` would cause duplicate +// events so we don't include them here +var topEventMapping = { + topAbort: 'abort', + topBlur: 'blur', + topCanPlay: 'canplay', + topCanPlayThrough: 'canplaythrough', + topChange: 'change', + topClick: 'click', + topCompositionEnd: 'compositionend', + topCompositionStart: 'compositionstart', + topCompositionUpdate: 'compositionupdate', + topContextMenu: 'contextmenu', + topCopy: 'copy', + topCut: 'cut', + topDoubleClick: 'dblclick', + topDrag: 'drag', + topDragEnd: 'dragend', + topDragEnter: 'dragenter', + topDragExit: 'dragexit', + topDragLeave: 'dragleave', + topDragOver: 'dragover', + topDragStart: 'dragstart', + topDrop: 'drop', + topDurationChange: 'durationchange', + topEmptied: 'emptied', + topEncrypted: 'encrypted', + topEnded: 'ended', + topError: 'error', + topFocus: 'focus', + topInput: 'input', + topKeyDown: 'keydown', + topKeyPress: 'keypress', + topKeyUp: 'keyup', + topLoadedData: 'loadeddata', + topLoadedMetadata: 'loadedmetadata', + topLoadStart: 'loadstart', + topMouseDown: 'mousedown', + topMouseMove: 'mousemove', + topMouseOut: 'mouseout', + topMouseOver: 'mouseover', + topMouseUp: 'mouseup', + topPaste: 'paste', + topPause: 'pause', + topPlay: 'play', + topPlaying: 'playing', + topProgress: 'progress', + topRateChange: 'ratechange', + topScroll: 'scroll', + topSeeked: 'seeked', + topSeeking: 'seeking', + topSelectionChange: 'selectionchange', + topStalled: 'stalled', + topSuspend: 'suspend', + topTextInput: 'textInput', + topTimeUpdate: 'timeupdate', + topTouchCancel: 'touchcancel', + topTouchEnd: 'touchend', + topTouchMove: 'touchmove', + topTouchStart: 'touchstart', + topVolumeChange: 'volumechange', + topWaiting: 'waiting', + topWheel: 'wheel' +}; + +/** + * To ensure no conflicts with other potential React instances on the page + */ +var topListenersIDKey = '_reactListenersID' + String(Math.random()).slice(2); + +function getListeningForDocument(mountAt) { + // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty` + // directly. + if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) { + mountAt[topListenersIDKey] = reactTopListenersCounter++; + alreadyListeningTo[mountAt[topListenersIDKey]] = {}; + } + return alreadyListeningTo[mountAt[topListenersIDKey]]; +} + +/** + * `ReactBrowserEventEmitter` is used to attach top-level event listeners. For + * example: + * + * ReactBrowserEventEmitter.putListener('myID', 'onClick', myFunction); + * + * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'. + * + * @internal + */ +var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, { + + /** + * Injectable event backend + */ + ReactEventListener: null, + + injection: { + /** + * @param {object} ReactEventListener + */ + injectReactEventListener: function (ReactEventListener) { + ReactEventListener.setHandleTopLevel(ReactBrowserEventEmitter.handleTopLevel); + ReactBrowserEventEmitter.ReactEventListener = ReactEventListener; + } + }, + + /** + * Sets whether or not any created callbacks should be enabled. + * + * @param {boolean} enabled True if callbacks should be enabled. + */ + setEnabled: function (enabled) { + if (ReactBrowserEventEmitter.ReactEventListener) { + ReactBrowserEventEmitter.ReactEventListener.setEnabled(enabled); + } + }, + + /** + * @return {boolean} True if callbacks are enabled. + */ + isEnabled: function () { + return !!(ReactBrowserEventEmitter.ReactEventListener && ReactBrowserEventEmitter.ReactEventListener.isEnabled()); + }, + + /** + * We listen for bubbled touch events on the document object. + * + * Firefox v8.01 (and possibly others) exhibited strange behavior when + * mounting `onmousemove` events at some node that was not the document + * element. The symptoms were that if your mouse is not moving over something + * contained within that mount point (for example on the background) the + * top-level listeners for `onmousemove` won't be called. However, if you + * register the `mousemove` on the document object, then it will of course + * catch all `mousemove`s. This along with iOS quirks, justifies restricting + * top-level listeners to the document object only, at least for these + * movement types of events and possibly all events. + * + * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html + * + * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but + * they bubble to document. + * + * @param {string} registrationName Name of listener (e.g. `onClick`). + * @param {object} contentDocumentHandle Document which owns the container + */ + listenTo: function (registrationName, contentDocumentHandle) { + var mountAt = contentDocumentHandle; + var isListening = getListeningForDocument(mountAt); + var dependencies = EventPluginRegistry.registrationNameDependencies[registrationName]; + + var topLevelTypes = EventConstants.topLevelTypes; + for (var i = 0; i < dependencies.length; i++) { + var dependency = dependencies[i]; + if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) { + if (dependency === topLevelTypes.topWheel) { + if (isEventSupported('wheel')) { + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt); + } else if (isEventSupported('mousewheel')) { + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt); + } else { + // Firefox needs to capture a different mouse scroll event. + // @see http://www.quirksmode.org/dom/events/tests/scroll.html + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'DOMMouseScroll', mountAt); + } + } else if (dependency === topLevelTypes.topScroll) { + + if (isEventSupported('scroll', true)) { + ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt); + } else { + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topScroll, 'scroll', ReactBrowserEventEmitter.ReactEventListener.WINDOW_HANDLE); + } + } else if (dependency === topLevelTypes.topFocus || dependency === topLevelTypes.topBlur) { + + if (isEventSupported('focus', true)) { + ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt); + ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt); + } else if (isEventSupported('focusin')) { + // IE has `focusin` and `focusout` events which bubble. + // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt); + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt); + } + + // to make sure blur and focus event listeners are only attached once + isListening[topLevelTypes.topBlur] = true; + isListening[topLevelTypes.topFocus] = true; + } else if (topEventMapping.hasOwnProperty(dependency)) { + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(dependency, topEventMapping[dependency], mountAt); + } + + isListening[dependency] = true; + } + } + }, + + trapBubbledEvent: function (topLevelType, handlerBaseName, handle) { + return ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelType, handlerBaseName, handle); + }, + + trapCapturedEvent: function (topLevelType, handlerBaseName, handle) { + return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelType, handlerBaseName, handle); + }, + + /** + * Listens to window scroll and resize events. We cache scroll values so that + * application code can access them without triggering reflows. + * + * NOTE: Scroll events do not bubble. + * + * @see http://www.quirksmode.org/dom/events/scroll.html + */ + ensureScrollValueMonitoring: function () { + if (!isMonitoringScrollValue) { + var refresh = ViewportMetrics.refreshScrollValues; + ReactBrowserEventEmitter.ReactEventListener.monitorScrollValue(refresh); + isMonitoringScrollValue = true; + } + }, + + eventNameDispatchConfigs: EventPluginHub.eventNameDispatchConfigs, + + registrationNameModules: EventPluginHub.registrationNameModules, + + putListener: EventPluginHub.putListener, + + getListener: EventPluginHub.getListener, + + deleteListener: EventPluginHub.deleteListener, + + deleteAllListeners: EventPluginHub.deleteAllListeners + +}); + +ReactPerf.measureMethods(ReactBrowserEventEmitter, 'ReactBrowserEventEmitter', { + putListener: 'putListener', + deleteListener: 'deleteListener' +}); + +module.exports = ReactBrowserEventEmitter; +},{"114":114,"133":133,"15":15,"16":16,"17":17,"24":24,"62":62,"78":78}],29:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @typechecks + * @providesModule ReactCSSTransitionGroup + */ + +'use strict'; + +var React = _dereq_(26); + +var assign = _dereq_(24); + +var ReactTransitionGroup = _dereq_(94); +var ReactCSSTransitionGroupChild = _dereq_(30); + +function createTransitionTimeoutPropValidator(transitionType) { + var timeoutPropName = 'transition' + transitionType + 'Timeout'; + var enabledPropName = 'transition' + transitionType; + + return function (props) { + // If the transition is enabled + if (props[enabledPropName]) { + // If no timeout duration is provided + if (props[timeoutPropName] == null) { + return new Error(timeoutPropName + ' wasn\'t supplied to ReactCSSTransitionGroup: ' + 'this can cause unreliable animations and won\'t be supported in ' + 'a future version of React. See ' + 'https://fb.me/react-animation-transition-group-timeout for more ' + 'information.'); + + // If the duration isn't a number + } else if (typeof props[timeoutPropName] !== 'number') { + return new Error(timeoutPropName + ' must be a number (in milliseconds)'); + } + } + }; +} + +var ReactCSSTransitionGroup = React.createClass({ + displayName: 'ReactCSSTransitionGroup', + + propTypes: { + transitionName: ReactCSSTransitionGroupChild.propTypes.name, + + transitionAppear: React.PropTypes.bool, + transitionEnter: React.PropTypes.bool, + transitionLeave: React.PropTypes.bool, + transitionAppearTimeout: createTransitionTimeoutPropValidator('Appear'), + transitionEnterTimeout: createTransitionTimeoutPropValidator('Enter'), + transitionLeaveTimeout: createTransitionTimeoutPropValidator('Leave') + }, + + getDefaultProps: function () { + return { + transitionAppear: false, + transitionEnter: true, + transitionLeave: true + }; + }, + + _wrapChild: function (child) { + // We need to provide this childFactory so that + // ReactCSSTransitionGroupChild can receive updates to name, enter, and + // leave while it is leaving. + return React.createElement(ReactCSSTransitionGroupChild, { + name: this.props.transitionName, + appear: this.props.transitionAppear, + enter: this.props.transitionEnter, + leave: this.props.transitionLeave, + appearTimeout: this.props.transitionAppearTimeout, + enterTimeout: this.props.transitionEnterTimeout, + leaveTimeout: this.props.transitionLeaveTimeout + }, child); + }, + + render: function () { + return React.createElement(ReactTransitionGroup, assign({}, this.props, { childFactory: this._wrapChild })); + } +}); + +module.exports = ReactCSSTransitionGroup; +},{"24":24,"26":26,"30":30,"94":94}],30:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @typechecks + * @providesModule ReactCSSTransitionGroupChild + */ + +'use strict'; + +var React = _dereq_(26); +var ReactDOM = _dereq_(40); + +var CSSCore = _dereq_(145); +var ReactTransitionEvents = _dereq_(93); + +var onlyChild = _dereq_(135); + +// We don't remove the element from the DOM until we receive an animationend or +// transitionend event. If the user screws up and forgets to add an animation +// their node will be stuck in the DOM forever, so we detect if an animation +// does not start and if it doesn't, we just call the end listener immediately. +var TICK = 17; + +var ReactCSSTransitionGroupChild = React.createClass({ + displayName: 'ReactCSSTransitionGroupChild', + + propTypes: { + name: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.shape({ + enter: React.PropTypes.string, + leave: React.PropTypes.string, + active: React.PropTypes.string + }), React.PropTypes.shape({ + enter: React.PropTypes.string, + enterActive: React.PropTypes.string, + leave: React.PropTypes.string, + leaveActive: React.PropTypes.string, + appear: React.PropTypes.string, + appearActive: React.PropTypes.string + })]).isRequired, + + // Once we require timeouts to be specified, we can remove the + // boolean flags (appear etc.) and just accept a number + // or a bool for the timeout flags (appearTimeout etc.) + appear: React.PropTypes.bool, + enter: React.PropTypes.bool, + leave: React.PropTypes.bool, + appearTimeout: React.PropTypes.number, + enterTimeout: React.PropTypes.number, + leaveTimeout: React.PropTypes.number + }, + + transition: function (animationType, finishCallback, userSpecifiedDelay) { + var node = ReactDOM.findDOMNode(this); + + if (!node) { + if (finishCallback) { + finishCallback(); + } + return; + } + + var className = this.props.name[animationType] || this.props.name + '-' + animationType; + var activeClassName = this.props.name[animationType + 'Active'] || className + '-active'; + var timeout = null; + + var endListener = function (e) { + if (e && e.target !== node) { + return; + } + + clearTimeout(timeout); + + CSSCore.removeClass(node, className); + CSSCore.removeClass(node, activeClassName); + + ReactTransitionEvents.removeEndEventListener(node, endListener); + + // Usually this optional callback is used for informing an owner of + // a leave animation and telling it to remove the child. + if (finishCallback) { + finishCallback(); + } + }; + + CSSCore.addClass(node, className); + + // Need to do this to actually trigger a transition. + this.queueClass(activeClassName); + + // If the user specified a timeout delay. + if (userSpecifiedDelay) { + // Clean-up the animation after the specified delay + timeout = setTimeout(endListener, userSpecifiedDelay); + this.transitionTimeouts.push(timeout); + } else { + // DEPRECATED: this listener will be removed in a future version of react + ReactTransitionEvents.addEndEventListener(node, endListener); + } + }, + + queueClass: function (className) { + this.classNameQueue.push(className); + + if (!this.timeout) { + this.timeout = setTimeout(this.flushClassNameQueue, TICK); + } + }, + + flushClassNameQueue: function () { + if (this.isMounted()) { + this.classNameQueue.forEach(CSSCore.addClass.bind(CSSCore, ReactDOM.findDOMNode(this))); + } + this.classNameQueue.length = 0; + this.timeout = null; + }, + + componentWillMount: function () { + this.classNameQueue = []; + this.transitionTimeouts = []; + }, + + componentWillUnmount: function () { + if (this.timeout) { + clearTimeout(this.timeout); + } + this.transitionTimeouts.forEach(function (timeout) { + clearTimeout(timeout); + }); + }, + + componentWillAppear: function (done) { + if (this.props.appear) { + this.transition('appear', done, this.props.appearTimeout); + } else { + done(); + } + }, + + componentWillEnter: function (done) { + if (this.props.enter) { + this.transition('enter', done, this.props.enterTimeout); + } else { + done(); + } + }, + + componentWillLeave: function (done) { + if (this.props.leave) { + this.transition('leave', done, this.props.leaveTimeout); + } else { + done(); + } + }, + + render: function () { + return onlyChild(this.props.children); + } +}); + +module.exports = ReactCSSTransitionGroupChild; +},{"135":135,"145":145,"26":26,"40":40,"93":93}],31:[function(_dereq_,module,exports){ +/** + * Copyright 2014-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactChildReconciler + * @typechecks static-only + */ + +'use strict'; + +var ReactReconciler = _dereq_(84); + +var instantiateReactComponent = _dereq_(132); +var shouldUpdateReactComponent = _dereq_(141); +var traverseAllChildren = _dereq_(142); +var warning = _dereq_(173); + +function instantiateChild(childInstances, child, name) { + // We found a component instance. + var keyUnique = childInstances[name] === undefined; + if ("development" !== 'production') { + "development" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.', name) : undefined; + } + if (child != null && keyUnique) { + childInstances[name] = instantiateReactComponent(child, null); + } +} + +/** + * ReactChildReconciler provides helpers for initializing or updating a set of + * children. Its output is suitable for passing it onto ReactMultiChild which + * does diffed reordering and insertion. + */ +var ReactChildReconciler = { + /** + * Generates a "mount image" for each of the supplied children. In the case + * of `ReactDOMComponent`, a mount image is a string of markup. + * + * @param {?object} nestedChildNodes Nested child maps. + * @return {?object} A set of child instances. + * @internal + */ + instantiateChildren: function (nestedChildNodes, transaction, context) { + if (nestedChildNodes == null) { + return null; + } + var childInstances = {}; + traverseAllChildren(nestedChildNodes, instantiateChild, childInstances); + return childInstances; + }, + + /** + * Updates the rendered children and returns a new set of children. + * + * @param {?object} prevChildren Previously initialized set of children. + * @param {?object} nextChildren Flat child element maps. + * @param {ReactReconcileTransaction} transaction + * @param {object} context + * @return {?object} A new set of child instances. + * @internal + */ + updateChildren: function (prevChildren, nextChildren, transaction, context) { + // We currently don't have a way to track moves here but if we use iterators + // instead of for..in we can zip the iterators and check if an item has + // moved. + // TODO: If nothing has changed, return the prevChildren object so that we + // can quickly bailout if nothing has changed. + if (!nextChildren && !prevChildren) { + return null; + } + var name; + for (name in nextChildren) { + if (!nextChildren.hasOwnProperty(name)) { + continue; + } + var prevChild = prevChildren && prevChildren[name]; + var prevElement = prevChild && prevChild._currentElement; + var nextElement = nextChildren[name]; + if (prevChild != null && shouldUpdateReactComponent(prevElement, nextElement)) { + ReactReconciler.receiveComponent(prevChild, nextElement, transaction, context); + nextChildren[name] = prevChild; + } else { + if (prevChild) { + ReactReconciler.unmountComponent(prevChild, name); + } + // The child must be instantiated before it's mounted. + var nextChildInstance = instantiateReactComponent(nextElement, null); + nextChildren[name] = nextChildInstance; + } + } + // Unmount children that are no longer present. + for (name in prevChildren) { + if (prevChildren.hasOwnProperty(name) && !(nextChildren && nextChildren.hasOwnProperty(name))) { + ReactReconciler.unmountComponent(prevChildren[name]); + } + } + return nextChildren; + }, + + /** + * Unmounts all rendered children. This should be used to clean up children + * when this component is unmounted. + * + * @param {?object} renderedChildren Previously initialized set of children. + * @internal + */ + unmountChildren: function (renderedChildren) { + for (var name in renderedChildren) { + if (renderedChildren.hasOwnProperty(name)) { + var renderedChild = renderedChildren[name]; + ReactReconciler.unmountComponent(renderedChild); + } + } + } + +}; + +module.exports = ReactChildReconciler; +},{"132":132,"141":141,"142":142,"173":173,"84":84}],32:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactChildren + */ + +'use strict'; + +var PooledClass = _dereq_(25); +var ReactElement = _dereq_(57); + +var emptyFunction = _dereq_(153); +var traverseAllChildren = _dereq_(142); + +var twoArgumentPooler = PooledClass.twoArgumentPooler; +var fourArgumentPooler = PooledClass.fourArgumentPooler; + +var userProvidedKeyEscapeRegex = /\/(?!\/)/g; +function escapeUserProvidedKey(text) { + return ('' + text).replace(userProvidedKeyEscapeRegex, '//'); +} + +/** + * PooledClass representing the bookkeeping associated with performing a child + * traversal. Allows avoiding binding callbacks. + * + * @constructor ForEachBookKeeping + * @param {!function} forEachFunction Function to perform traversal with. + * @param {?*} forEachContext Context to perform context with. + */ +function ForEachBookKeeping(forEachFunction, forEachContext) { + this.func = forEachFunction; + this.context = forEachContext; + this.count = 0; +} +ForEachBookKeeping.prototype.destructor = function () { + this.func = null; + this.context = null; + this.count = 0; +}; +PooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler); + +function forEachSingleChild(bookKeeping, child, name) { + var func = bookKeeping.func; + var context = bookKeeping.context; + + func.call(context, child, bookKeeping.count++); +} + +/** + * Iterates through children that are typically specified as `props.children`. + * + * The provided forEachFunc(child, index) will be called for each + * leaf child. + * + * @param {?*} children Children tree container. + * @param {function(*, int)} forEachFunc + * @param {*} forEachContext Context for forEachContext. + */ +function forEachChildren(children, forEachFunc, forEachContext) { + if (children == null) { + return children; + } + var traverseContext = ForEachBookKeeping.getPooled(forEachFunc, forEachContext); + traverseAllChildren(children, forEachSingleChild, traverseContext); + ForEachBookKeeping.release(traverseContext); +} + +/** + * PooledClass representing the bookkeeping associated with performing a child + * mapping. Allows avoiding binding callbacks. + * + * @constructor MapBookKeeping + * @param {!*} mapResult Object containing the ordered map of results. + * @param {!function} mapFunction Function to perform mapping with. + * @param {?*} mapContext Context to perform mapping with. + */ +function MapBookKeeping(mapResult, keyPrefix, mapFunction, mapContext) { + this.result = mapResult; + this.keyPrefix = keyPrefix; + this.func = mapFunction; + this.context = mapContext; + this.count = 0; +} +MapBookKeeping.prototype.destructor = function () { + this.result = null; + this.keyPrefix = null; + this.func = null; + this.context = null; + this.count = 0; +}; +PooledClass.addPoolingTo(MapBookKeeping, fourArgumentPooler); + +function mapSingleChildIntoContext(bookKeeping, child, childKey) { + var result = bookKeeping.result; + var keyPrefix = bookKeeping.keyPrefix; + var func = bookKeeping.func; + var context = bookKeeping.context; + + var mappedChild = func.call(context, child, bookKeeping.count++); + if (Array.isArray(mappedChild)) { + mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction.thatReturnsArgument); + } else if (mappedChild != null) { + if (ReactElement.isValidElement(mappedChild)) { + mappedChild = ReactElement.cloneAndReplaceKey(mappedChild, + // Keep both the (mapped) and old keys if they differ, just as + // traverseAllChildren used to do for objects as children + keyPrefix + (mappedChild !== child ? escapeUserProvidedKey(mappedChild.key || '') + '/' : '') + childKey); + } + result.push(mappedChild); + } +} + +function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) { + var escapedPrefix = ''; + if (prefix != null) { + escapedPrefix = escapeUserProvidedKey(prefix) + '/'; + } + var traverseContext = MapBookKeeping.getPooled(array, escapedPrefix, func, context); + traverseAllChildren(children, mapSingleChildIntoContext, traverseContext); + MapBookKeeping.release(traverseContext); +} + +/** + * Maps children that are typically specified as `props.children`. + * + * The provided mapFunction(child, key, index) will be called for each + * leaf child. + * + * @param {?*} children Children tree container. + * @param {function(*, int)} func The map function. + * @param {*} context Context for mapFunction. + * @return {object} Object containing the ordered map of results. + */ +function mapChildren(children, func, context) { + if (children == null) { + return children; + } + var result = []; + mapIntoWithKeyPrefixInternal(children, result, null, func, context); + return result; +} + +function forEachSingleChildDummy(traverseContext, child, name) { + return null; +} + +/** + * Count the number of children that are typically specified as + * `props.children`. + * + * @param {?*} children Children tree container. + * @return {number} The number of children. + */ +function countChildren(children, context) { + return traverseAllChildren(children, forEachSingleChildDummy, null); +} + +/** + * Flatten a children object (typically specified as `props.children`) and + * return an array with appropriately re-keyed children. + */ +function toArray(children) { + var result = []; + mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction.thatReturnsArgument); + return result; +} + +var ReactChildren = { + forEach: forEachChildren, + map: mapChildren, + mapIntoWithKeyPrefixInternal: mapIntoWithKeyPrefixInternal, + count: countChildren, + toArray: toArray +}; + +module.exports = ReactChildren; +},{"142":142,"153":153,"25":25,"57":57}],33:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactClass + */ + +'use strict'; + +var ReactComponent = _dereq_(34); +var ReactElement = _dereq_(57); +var ReactPropTypeLocations = _dereq_(81); +var ReactPropTypeLocationNames = _dereq_(80); +var ReactNoopUpdateQueue = _dereq_(76); + +var assign = _dereq_(24); +var emptyObject = _dereq_(154); +var invariant = _dereq_(161); +var keyMirror = _dereq_(165); +var keyOf = _dereq_(166); +var warning = _dereq_(173); + +var MIXINS_KEY = keyOf({ mixins: null }); + +/** + * Policies that describe methods in `ReactClassInterface`. + */ +var SpecPolicy = keyMirror({ + /** + * These methods may be defined only once by the class specification or mixin. + */ + DEFINE_ONCE: null, + /** + * These methods may be defined by both the class specification and mixins. + * Subsequent definitions will be chained. These methods must return void. + */ + DEFINE_MANY: null, + /** + * These methods are overriding the base class. + */ + OVERRIDE_BASE: null, + /** + * These methods are similar to DEFINE_MANY, except we assume they return + * objects. We try to merge the keys of the return values of all the mixed in + * functions. If there is a key conflict we throw. + */ + DEFINE_MANY_MERGED: null +}); + +var injectedMixins = []; + +var warnedSetProps = false; +function warnSetProps() { + if (!warnedSetProps) { + warnedSetProps = true; + "development" !== 'production' ? warning(false, 'setProps(...) and replaceProps(...) are deprecated. ' + 'Instead, call render again at the top level.') : undefined; + } +} + +/** + * Composite components are higher-level components that compose other composite + * or native components. + * + * To create a new type of `ReactClass`, pass a specification of + * your new class to `React.createClass`. The only requirement of your class + * specification is that you implement a `render` method. + * + * var MyComponent = React.createClass({ + * render: function() { + * return
Hello World
; + * } + * }); + * + * The class specification supports a specific protocol of methods that have + * special meaning (e.g. `render`). See `ReactClassInterface` for + * more the comprehensive protocol. Any other properties and methods in the + * class specification will be available on the prototype. + * + * @interface ReactClassInterface + * @internal + */ +var ReactClassInterface = { + + /** + * An array of Mixin objects to include when defining your component. + * + * @type {array} + * @optional + */ + mixins: SpecPolicy.DEFINE_MANY, + + /** + * An object containing properties and methods that should be defined on + * the component's constructor instead of its prototype (static methods). + * + * @type {object} + * @optional + */ + statics: SpecPolicy.DEFINE_MANY, + + /** + * Definition of prop types for this component. + * + * @type {object} + * @optional + */ + propTypes: SpecPolicy.DEFINE_MANY, + + /** + * Definition of context types for this component. + * + * @type {object} + * @optional + */ + contextTypes: SpecPolicy.DEFINE_MANY, + + /** + * Definition of context types this component sets for its children. + * + * @type {object} + * @optional + */ + childContextTypes: SpecPolicy.DEFINE_MANY, + + // ==== Definition methods ==== + + /** + * Invoked when the component is mounted. Values in the mapping will be set on + * `this.props` if that prop is not specified (i.e. using an `in` check). + * + * This method is invoked before `getInitialState` and therefore cannot rely + * on `this.state` or use `this.setState`. + * + * @return {object} + * @optional + */ + getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED, + + /** + * Invoked once before the component is mounted. The return value will be used + * as the initial value of `this.state`. + * + * getInitialState: function() { + * return { + * isOn: false, + * fooBaz: new BazFoo() + * } + * } + * + * @return {object} + * @optional + */ + getInitialState: SpecPolicy.DEFINE_MANY_MERGED, + + /** + * @return {object} + * @optional + */ + getChildContext: SpecPolicy.DEFINE_MANY_MERGED, + + /** + * Uses props from `this.props` and state from `this.state` to render the + * structure of the component. + * + * No guarantees are made about when or how often this method is invoked, so + * it must not have side effects. + * + * render: function() { + * var name = this.props.name; + * return
Hello, {name}!
; + * } + * + * @return {ReactComponent} + * @nosideeffects + * @required + */ + render: SpecPolicy.DEFINE_ONCE, + + // ==== Delegate methods ==== + + /** + * Invoked when the component is initially created and about to be mounted. + * This may have side effects, but any external subscriptions or data created + * by this method must be cleaned up in `componentWillUnmount`. + * + * @optional + */ + componentWillMount: SpecPolicy.DEFINE_MANY, + + /** + * Invoked when the component has been mounted and has a DOM representation. + * However, there is no guarantee that the DOM node is in the document. + * + * Use this as an opportunity to operate on the DOM when the component has + * been mounted (initialized and rendered) for the first time. + * + * @param {DOMElement} rootNode DOM element representing the component. + * @optional + */ + componentDidMount: SpecPolicy.DEFINE_MANY, + + /** + * Invoked before the component receives new props. + * + * Use this as an opportunity to react to a prop transition by updating the + * state using `this.setState`. Current props are accessed via `this.props`. + * + * componentWillReceiveProps: function(nextProps, nextContext) { + * this.setState({ + * likesIncreasing: nextProps.likeCount > this.props.likeCount + * }); + * } + * + * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop + * transition may cause a state change, but the opposite is not true. If you + * need it, you are probably looking for `componentWillUpdate`. + * + * @param {object} nextProps + * @optional + */ + componentWillReceiveProps: SpecPolicy.DEFINE_MANY, + + /** + * Invoked while deciding if the component should be updated as a result of + * receiving new props, state and/or context. + * + * Use this as an opportunity to `return false` when you're certain that the + * transition to the new props/state/context will not require a component + * update. + * + * shouldComponentUpdate: function(nextProps, nextState, nextContext) { + * return !equal(nextProps, this.props) || + * !equal(nextState, this.state) || + * !equal(nextContext, this.context); + * } + * + * @param {object} nextProps + * @param {?object} nextState + * @param {?object} nextContext + * @return {boolean} True if the component should update. + * @optional + */ + shouldComponentUpdate: SpecPolicy.DEFINE_ONCE, + + /** + * Invoked when the component is about to update due to a transition from + * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState` + * and `nextContext`. + * + * Use this as an opportunity to perform preparation before an update occurs. + * + * NOTE: You **cannot** use `this.setState()` in this method. + * + * @param {object} nextProps + * @param {?object} nextState + * @param {?object} nextContext + * @param {ReactReconcileTransaction} transaction + * @optional + */ + componentWillUpdate: SpecPolicy.DEFINE_MANY, + + /** + * Invoked when the component's DOM representation has been updated. + * + * Use this as an opportunity to operate on the DOM when the component has + * been updated. + * + * @param {object} prevProps + * @param {?object} prevState + * @param {?object} prevContext + * @param {DOMElement} rootNode DOM element representing the component. + * @optional + */ + componentDidUpdate: SpecPolicy.DEFINE_MANY, + + /** + * Invoked when the component is about to be removed from its parent and have + * its DOM representation destroyed. + * + * Use this as an opportunity to deallocate any external resources. + * + * NOTE: There is no `componentDidUnmount` since your component will have been + * destroyed by that point. + * + * @optional + */ + componentWillUnmount: SpecPolicy.DEFINE_MANY, + + // ==== Advanced methods ==== + + /** + * Updates the component's currently mounted DOM representation. + * + * By default, this implements React's rendering and reconciliation algorithm. + * Sophisticated clients may wish to override this. + * + * @param {ReactReconcileTransaction} transaction + * @internal + * @overridable + */ + updateComponent: SpecPolicy.OVERRIDE_BASE + +}; + +/** + * Mapping from class specification keys to special processing functions. + * + * Although these are declared like instance properties in the specification + * when defining classes using `React.createClass`, they are actually static + * and are accessible on the constructor instead of the prototype. Despite + * being static, they must be defined outside of the "statics" key under + * which all other static methods are defined. + */ +var RESERVED_SPEC_KEYS = { + displayName: function (Constructor, displayName) { + Constructor.displayName = displayName; + }, + mixins: function (Constructor, mixins) { + if (mixins) { + for (var i = 0; i < mixins.length; i++) { + mixSpecIntoComponent(Constructor, mixins[i]); + } + } + }, + childContextTypes: function (Constructor, childContextTypes) { + if ("development" !== 'production') { + validateTypeDef(Constructor, childContextTypes, ReactPropTypeLocations.childContext); + } + Constructor.childContextTypes = assign({}, Constructor.childContextTypes, childContextTypes); + }, + contextTypes: function (Constructor, contextTypes) { + if ("development" !== 'production') { + validateTypeDef(Constructor, contextTypes, ReactPropTypeLocations.context); + } + Constructor.contextTypes = assign({}, Constructor.contextTypes, contextTypes); + }, + /** + * Special case getDefaultProps which should move into statics but requires + * automatic merging. + */ + getDefaultProps: function (Constructor, getDefaultProps) { + if (Constructor.getDefaultProps) { + Constructor.getDefaultProps = createMergedResultFunction(Constructor.getDefaultProps, getDefaultProps); + } else { + Constructor.getDefaultProps = getDefaultProps; + } + }, + propTypes: function (Constructor, propTypes) { + if ("development" !== 'production') { + validateTypeDef(Constructor, propTypes, ReactPropTypeLocations.prop); + } + Constructor.propTypes = assign({}, Constructor.propTypes, propTypes); + }, + statics: function (Constructor, statics) { + mixStaticSpecIntoComponent(Constructor, statics); + }, + autobind: function () {} }; + +// noop +function validateTypeDef(Constructor, typeDef, location) { + for (var propName in typeDef) { + if (typeDef.hasOwnProperty(propName)) { + // use a warning instead of an invariant so components + // don't show up in prod but not in __DEV__ + "development" !== 'production' ? warning(typeof typeDef[propName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName) : undefined; + } + } +} + +function validateMethodOverride(proto, name) { + var specPolicy = ReactClassInterface.hasOwnProperty(name) ? ReactClassInterface[name] : null; + + // Disallow overriding of base class methods unless explicitly allowed. + if (ReactClassMixin.hasOwnProperty(name)) { + !(specPolicy === SpecPolicy.OVERRIDE_BASE) ? "development" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to override ' + '`%s` from your class specification. Ensure that your method names ' + 'do not overlap with React methods.', name) : invariant(false) : undefined; + } + + // Disallow defining methods more than once unless explicitly allowed. + if (proto.hasOwnProperty(name)) { + !(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ? "development" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name) : invariant(false) : undefined; + } +} + +/** + * Mixin helper which handles policy validation and reserved + * specification keys when building React classses. + */ +function mixSpecIntoComponent(Constructor, spec) { + if (!spec) { + return; + } + + !(typeof spec !== 'function') ? "development" !== 'production' ? invariant(false, 'ReactClass: You\'re attempting to ' + 'use a component class as a mixin. Instead, just use a regular object.') : invariant(false) : undefined; + !!ReactElement.isValidElement(spec) ? "development" !== 'production' ? invariant(false, 'ReactClass: You\'re attempting to ' + 'use a component as a mixin. Instead, just use a regular object.') : invariant(false) : undefined; + + var proto = Constructor.prototype; + + // By handling mixins before any other properties, we ensure the same + // chaining order is applied to methods with DEFINE_MANY policy, whether + // mixins are listed before or after these methods in the spec. + if (spec.hasOwnProperty(MIXINS_KEY)) { + RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins); + } + + for (var name in spec) { + if (!spec.hasOwnProperty(name)) { + continue; + } + + if (name === MIXINS_KEY) { + // We have already handled mixins in a special case above. + continue; + } + + var property = spec[name]; + validateMethodOverride(proto, name); + + if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) { + RESERVED_SPEC_KEYS[name](Constructor, property); + } else { + // Setup methods on prototype: + // The following member methods should not be automatically bound: + // 1. Expected ReactClass methods (in the "interface"). + // 2. Overridden methods (that were mixed in). + var isReactClassMethod = ReactClassInterface.hasOwnProperty(name); + var isAlreadyDefined = proto.hasOwnProperty(name); + var isFunction = typeof property === 'function'; + var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false; + + if (shouldAutoBind) { + if (!proto.__reactAutoBindMap) { + proto.__reactAutoBindMap = {}; + } + proto.__reactAutoBindMap[name] = property; + proto[name] = property; + } else { + if (isAlreadyDefined) { + var specPolicy = ReactClassInterface[name]; + + // These cases should already be caught by validateMethodOverride. + !(isReactClassMethod && (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY)) ? "development" !== 'production' ? invariant(false, 'ReactClass: Unexpected spec policy %s for key %s ' + 'when mixing in component specs.', specPolicy, name) : invariant(false) : undefined; + + // For methods which are defined more than once, call the existing + // methods before calling the new property, merging if appropriate. + if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) { + proto[name] = createMergedResultFunction(proto[name], property); + } else if (specPolicy === SpecPolicy.DEFINE_MANY) { + proto[name] = createChainedFunction(proto[name], property); + } + } else { + proto[name] = property; + if ("development" !== 'production') { + // Add verbose displayName to the function, which helps when looking + // at profiling tools. + if (typeof property === 'function' && spec.displayName) { + proto[name].displayName = spec.displayName + '_' + name; + } + } + } + } + } + } +} + +function mixStaticSpecIntoComponent(Constructor, statics) { + if (!statics) { + return; + } + for (var name in statics) { + var property = statics[name]; + if (!statics.hasOwnProperty(name)) { + continue; + } + + var isReserved = (name in RESERVED_SPEC_KEYS); + !!isReserved ? "development" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define a reserved ' + 'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' + 'as an instance property instead; it will still be accessible on the ' + 'constructor.', name) : invariant(false) : undefined; + + var isInherited = (name in Constructor); + !!isInherited ? "development" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define ' + '`%s` on your component more than once. This conflict may be ' + 'due to a mixin.', name) : invariant(false) : undefined; + Constructor[name] = property; + } +} + +/** + * Merge two objects, but throw if both contain the same key. + * + * @param {object} one The first object, which is mutated. + * @param {object} two The second object + * @return {object} one after it has been mutated to contain everything in two. + */ +function mergeIntoWithNoDuplicateKeys(one, two) { + !(one && two && typeof one === 'object' && typeof two === 'object') ? "development" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.') : invariant(false) : undefined; + + for (var key in two) { + if (two.hasOwnProperty(key)) { + !(one[key] === undefined) ? "development" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): ' + 'Tried to merge two objects with the same key: `%s`. This conflict ' + 'may be due to a mixin; in particular, this may be caused by two ' + 'getInitialState() or getDefaultProps() methods returning objects ' + 'with clashing keys.', key) : invariant(false) : undefined; + one[key] = two[key]; + } + } + return one; +} + +/** + * Creates a function that invokes two functions and merges their return values. + * + * @param {function} one Function to invoke first. + * @param {function} two Function to invoke second. + * @return {function} Function that invokes the two argument functions. + * @private + */ +function createMergedResultFunction(one, two) { + return function mergedResult() { + var a = one.apply(this, arguments); + var b = two.apply(this, arguments); + if (a == null) { + return b; + } else if (b == null) { + return a; + } + var c = {}; + mergeIntoWithNoDuplicateKeys(c, a); + mergeIntoWithNoDuplicateKeys(c, b); + return c; + }; +} + +/** + * Creates a function that invokes two functions and ignores their return vales. + * + * @param {function} one Function to invoke first. + * @param {function} two Function to invoke second. + * @return {function} Function that invokes the two argument functions. + * @private + */ +function createChainedFunction(one, two) { + return function chainedFunction() { + one.apply(this, arguments); + two.apply(this, arguments); + }; +} + +/** + * Binds a method to the component. + * + * @param {object} component Component whose method is going to be bound. + * @param {function} method Method to be bound. + * @return {function} The bound method. + */ +function bindAutoBindMethod(component, method) { + var boundMethod = method.bind(component); + if ("development" !== 'production') { + boundMethod.__reactBoundContext = component; + boundMethod.__reactBoundMethod = method; + boundMethod.__reactBoundArguments = null; + var componentName = component.constructor.displayName; + var _bind = boundMethod.bind; + /* eslint-disable block-scoped-var, no-undef */ + boundMethod.bind = function (newThis) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + // User is trying to bind() an autobound method; we effectively will + // ignore the value of "this" that the user is trying to use, so + // let's warn. + if (newThis !== component && newThis !== null) { + "development" !== 'production' ? warning(false, 'bind(): React component methods may only be bound to the ' + 'component instance. See %s', componentName) : undefined; + } else if (!args.length) { + "development" !== 'production' ? warning(false, 'bind(): You are binding a component method to the component. ' + 'React does this for you automatically in a high-performance ' + 'way, so you can safely remove this call. See %s', componentName) : undefined; + return boundMethod; + } + var reboundMethod = _bind.apply(boundMethod, arguments); + reboundMethod.__reactBoundContext = component; + reboundMethod.__reactBoundMethod = method; + reboundMethod.__reactBoundArguments = args; + return reboundMethod; + /* eslint-enable */ + }; + } + return boundMethod; +} + +/** + * Binds all auto-bound methods in a component. + * + * @param {object} component Component whose method is going to be bound. + */ +function bindAutoBindMethods(component) { + for (var autoBindKey in component.__reactAutoBindMap) { + if (component.__reactAutoBindMap.hasOwnProperty(autoBindKey)) { + var method = component.__reactAutoBindMap[autoBindKey]; + component[autoBindKey] = bindAutoBindMethod(component, method); + } + } +} + +/** + * Add more to the ReactClass base class. These are all legacy features and + * therefore not already part of the modern ReactComponent. + */ +var ReactClassMixin = { + + /** + * TODO: This will be deprecated because state should always keep a consistent + * type signature and the only use case for this, is to avoid that. + */ + replaceState: function (newState, callback) { + this.updater.enqueueReplaceState(this, newState); + if (callback) { + this.updater.enqueueCallback(this, callback); + } + }, + + /** + * Checks whether or not this composite component is mounted. + * @return {boolean} True if mounted, false otherwise. + * @protected + * @final + */ + isMounted: function () { + return this.updater.isMounted(this); + }, + + /** + * Sets a subset of the props. + * + * @param {object} partialProps Subset of the next props. + * @param {?function} callback Called after props are updated. + * @final + * @public + * @deprecated + */ + setProps: function (partialProps, callback) { + if ("development" !== 'production') { + warnSetProps(); + } + this.updater.enqueueSetProps(this, partialProps); + if (callback) { + this.updater.enqueueCallback(this, callback); + } + }, + + /** + * Replace all the props. + * + * @param {object} newProps Subset of the next props. + * @param {?function} callback Called after props are updated. + * @final + * @public + * @deprecated + */ + replaceProps: function (newProps, callback) { + if ("development" !== 'production') { + warnSetProps(); + } + this.updater.enqueueReplaceProps(this, newProps); + if (callback) { + this.updater.enqueueCallback(this, callback); + } + } +}; + +var ReactClassComponent = function () {}; +assign(ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin); + +/** + * Module for creating composite components. + * + * @class ReactClass + */ +var ReactClass = { + + /** + * Creates a composite component class given a class specification. + * + * @param {object} spec Class specification (which must define `render`). + * @return {function} Component constructor function. + * @public + */ + createClass: function (spec) { + var Constructor = function (props, context, updater) { + // This constructor is overridden by mocks. The argument is used + // by mocks to assert on what gets mounted. + + if ("development" !== 'production') { + "development" !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: https://fb.me/react-legacyfactory') : undefined; + } + + // Wire up auto-binding + if (this.__reactAutoBindMap) { + bindAutoBindMethods(this); + } + + this.props = props; + this.context = context; + this.refs = emptyObject; + this.updater = updater || ReactNoopUpdateQueue; + + this.state = null; + + // ReactClasses doesn't have constructors. Instead, they use the + // getInitialState and componentWillMount methods for initialization. + + var initialState = this.getInitialState ? this.getInitialState() : null; + if ("development" !== 'production') { + // We allow auto-mocks to proceed as if they're returning null. + if (typeof initialState === 'undefined' && this.getInitialState._isMockFunction) { + // This is probably bad practice. Consider warning here and + // deprecating this convenience. + initialState = null; + } + } + !(typeof initialState === 'object' && !Array.isArray(initialState)) ? "development" !== 'production' ? invariant(false, '%s.getInitialState(): must return an object or null', Constructor.displayName || 'ReactCompositeComponent') : invariant(false) : undefined; + + this.state = initialState; + }; + Constructor.prototype = new ReactClassComponent(); + Constructor.prototype.constructor = Constructor; + + injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor)); + + mixSpecIntoComponent(Constructor, spec); + + // Initialize the defaultProps property after all mixins have been merged. + if (Constructor.getDefaultProps) { + Constructor.defaultProps = Constructor.getDefaultProps(); + } + + if ("development" !== 'production') { + // This is a tag to indicate that the use of these method names is ok, + // since it's used with createClass. If it's not, then it's likely a + // mistake so we'll warn you to use the static property, property + // initializer or constructor respectively. + if (Constructor.getDefaultProps) { + Constructor.getDefaultProps.isReactClassApproved = {}; + } + if (Constructor.prototype.getInitialState) { + Constructor.prototype.getInitialState.isReactClassApproved = {}; + } + } + + !Constructor.prototype.render ? "development" !== 'production' ? invariant(false, 'createClass(...): Class specification must implement a `render` method.') : invariant(false) : undefined; + + if ("development" !== 'production') { + "development" !== 'production' ? warning(!Constructor.prototype.componentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', spec.displayName || 'A component') : undefined; + "development" !== 'production' ? warning(!Constructor.prototype.componentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component') : undefined; + } + + // Reduce time spent doing lookups by setting these on the prototype. + for (var methodName in ReactClassInterface) { + if (!Constructor.prototype[methodName]) { + Constructor.prototype[methodName] = null; + } + } + + return Constructor; + }, + + injection: { + injectMixin: function (mixin) { + injectedMixins.push(mixin); + } + } + +}; + +module.exports = ReactClass; +},{"154":154,"161":161,"165":165,"166":166,"173":173,"24":24,"34":34,"57":57,"76":76,"80":80,"81":81}],34:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactComponent + */ + +'use strict'; + +var ReactNoopUpdateQueue = _dereq_(76); + +var canDefineProperty = _dereq_(117); +var emptyObject = _dereq_(154); +var invariant = _dereq_(161); +var warning = _dereq_(173); + +/** + * Base class helpers for the updating state of a component. + */ +function ReactComponent(props, context, updater) { + this.props = props; + this.context = context; + this.refs = emptyObject; + // We initialize the default updater but the real one gets injected by the + // renderer. + this.updater = updater || ReactNoopUpdateQueue; +} + +ReactComponent.prototype.isReactComponent = {}; + +/** + * Sets a subset of the state. Always use this to mutate + * state. You should treat `this.state` as immutable. + * + * There is no guarantee that `this.state` will be immediately updated, so + * accessing `this.state` after calling this method may return the old value. + * + * There is no guarantee that calls to `setState` will run synchronously, + * as they may eventually be batched together. You can provide an optional + * callback that will be executed when the call to setState is actually + * completed. + * + * When a function is provided to setState, it will be called at some point in + * the future (not synchronously). It will be called with the up to date + * component arguments (state, props, context). These values can be different + * from this.* because your function may be called after receiveProps but before + * shouldComponentUpdate, and this new state, props, and context will not yet be + * assigned to this. + * + * @param {object|function} partialState Next partial state or function to + * produce next partial state to be merged with current state. + * @param {?function} callback Called after state is updated. + * @final + * @protected + */ +ReactComponent.prototype.setState = function (partialState, callback) { + !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? "development" !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a ' + 'function which returns an object of state variables.') : invariant(false) : undefined; + if ("development" !== 'production') { + "development" !== 'production' ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : undefined; + } + this.updater.enqueueSetState(this, partialState); + if (callback) { + this.updater.enqueueCallback(this, callback); + } +}; + +/** + * Forces an update. This should only be invoked when it is known with + * certainty that we are **not** in a DOM transaction. + * + * You may want to call this when you know that some deeper aspect of the + * component's state has changed but `setState` was not called. + * + * This will not invoke `shouldComponentUpdate`, but it will invoke + * `componentWillUpdate` and `componentDidUpdate`. + * + * @param {?function} callback Called after update is complete. + * @final + * @protected + */ +ReactComponent.prototype.forceUpdate = function (callback) { + this.updater.enqueueForceUpdate(this); + if (callback) { + this.updater.enqueueCallback(this, callback); + } +}; + +/** + * Deprecated APIs. These APIs used to exist on classic React classes but since + * we would like to deprecate them, we're not going to move them over to this + * modern base class. Instead, we define a getter that warns if it's accessed. + */ +if ("development" !== 'production') { + var deprecatedAPIs = { + getDOMNode: ['getDOMNode', 'Use ReactDOM.findDOMNode(component) instead.'], + isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'], + replaceProps: ['replaceProps', 'Instead, call render again at the top level.'], + replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).'], + setProps: ['setProps', 'Instead, call render again at the top level.'] + }; + var defineDeprecationWarning = function (methodName, info) { + if (canDefineProperty) { + Object.defineProperty(ReactComponent.prototype, methodName, { + get: function () { + "development" !== 'production' ? warning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]) : undefined; + return undefined; + } + }); + } + }; + for (var fnName in deprecatedAPIs) { + if (deprecatedAPIs.hasOwnProperty(fnName)) { + defineDeprecationWarning(fnName, deprecatedAPIs[fnName]); + } + } +} + +module.exports = ReactComponent; +},{"117":117,"154":154,"161":161,"173":173,"76":76}],35:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactComponentBrowserEnvironment + */ + +'use strict'; + +var ReactDOMIDOperations = _dereq_(45); +var ReactMount = _dereq_(72); + +/** + * Abstracts away all functionality of the reconciler that requires knowledge of + * the browser context. TODO: These callers should be refactored to avoid the + * need for this injection. + */ +var ReactComponentBrowserEnvironment = { + + processChildrenUpdates: ReactDOMIDOperations.dangerouslyProcessChildrenUpdates, + + replaceNodeWithMarkupByID: ReactDOMIDOperations.dangerouslyReplaceNodeWithMarkupByID, + + /** + * If a particular environment requires that some resources be cleaned up, + * specify this in the injected Mixin. In the DOM, we would likely want to + * purge any cached node ID lookups. + * + * @private + */ + unmountIDFromEnvironment: function (rootNodeID) { + ReactMount.purgeID(rootNodeID); + } + +}; + +module.exports = ReactComponentBrowserEnvironment; +},{"45":45,"72":72}],36:[function(_dereq_,module,exports){ +/** + * Copyright 2014-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactComponentEnvironment + */ + +'use strict'; + +var invariant = _dereq_(161); + +var injected = false; + +var ReactComponentEnvironment = { + + /** + * Optionally injectable environment dependent cleanup hook. (server vs. + * browser etc). Example: A browser system caches DOM nodes based on component + * ID and must remove that cache entry when this instance is unmounted. + */ + unmountIDFromEnvironment: null, + + /** + * Optionally injectable hook for swapping out mount images in the middle of + * the tree. + */ + replaceNodeWithMarkupByID: null, + + /** + * Optionally injectable hook for processing a queue of child updates. Will + * later move into MultiChildComponents. + */ + processChildrenUpdates: null, + + injection: { + injectEnvironment: function (environment) { + !!injected ? "development" !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : invariant(false) : undefined; + ReactComponentEnvironment.unmountIDFromEnvironment = environment.unmountIDFromEnvironment; + ReactComponentEnvironment.replaceNodeWithMarkupByID = environment.replaceNodeWithMarkupByID; + ReactComponentEnvironment.processChildrenUpdates = environment.processChildrenUpdates; + injected = true; + } + } + +}; + +module.exports = ReactComponentEnvironment; +},{"161":161}],37:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactComponentWithPureRenderMixin + */ + +'use strict'; + +var shallowCompare = _dereq_(140); + +/** + * If your React component's render function is "pure", e.g. it will render the + * same result given the same props and state, provide this Mixin for a + * considerable performance boost. + * + * Most React components have pure render functions. + * + * Example: + * + * var ReactComponentWithPureRenderMixin = + * require('ReactComponentWithPureRenderMixin'); + * React.createClass({ + * mixins: [ReactComponentWithPureRenderMixin], + * + * render: function() { + * return
foo
; + * } + * }); + * + * Note: This only checks shallow equality for props and state. If these contain + * complex data structures this mixin may have false-negatives for deeper + * differences. Only mixin to components which have simple props and state, or + * use `forceUpdate()` when you know deep data structures have changed. + */ +var ReactComponentWithPureRenderMixin = { + shouldComponentUpdate: function (nextProps, nextState) { + return shallowCompare(this, nextProps, nextState); + } +}; + +module.exports = ReactComponentWithPureRenderMixin; +},{"140":140}],38:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactCompositeComponent + */ + +'use strict'; + +var ReactComponentEnvironment = _dereq_(36); +var ReactCurrentOwner = _dereq_(39); +var ReactElement = _dereq_(57); +var ReactInstanceMap = _dereq_(68); +var ReactPerf = _dereq_(78); +var ReactPropTypeLocations = _dereq_(81); +var ReactPropTypeLocationNames = _dereq_(80); +var ReactReconciler = _dereq_(84); +var ReactUpdateQueue = _dereq_(95); + +var assign = _dereq_(24); +var emptyObject = _dereq_(154); +var invariant = _dereq_(161); +var shouldUpdateReactComponent = _dereq_(141); +var warning = _dereq_(173); + +function getDeclarationErrorAddendum(component) { + var owner = component._currentElement._owner || null; + if (owner) { + var name = owner.getName(); + if (name) { + return ' Check the render method of `' + name + '`.'; + } + } + return ''; +} + +function StatelessComponent(Component) {} +StatelessComponent.prototype.render = function () { + var Component = ReactInstanceMap.get(this)._currentElement.type; + return Component(this.props, this.context, this.updater); +}; + +/** + * ------------------ The Life-Cycle of a Composite Component ------------------ + * + * - constructor: Initialization of state. The instance is now retained. + * - componentWillMount + * - render + * - [children's constructors] + * - [children's componentWillMount and render] + * - [children's componentDidMount] + * - componentDidMount + * + * Update Phases: + * - componentWillReceiveProps (only called if parent updated) + * - shouldComponentUpdate + * - componentWillUpdate + * - render + * - [children's constructors or receive props phases] + * - componentDidUpdate + * + * - componentWillUnmount + * - [children's componentWillUnmount] + * - [children destroyed] + * - (destroyed): The instance is now blank, released by React and ready for GC. + * + * ----------------------------------------------------------------------------- + */ + +/** + * An incrementing ID assigned to each component when it is mounted. This is + * used to enforce the order in which `ReactUpdates` updates dirty components. + * + * @private + */ +var nextMountID = 1; + +/** + * @lends {ReactCompositeComponent.prototype} + */ +var ReactCompositeComponentMixin = { + + /** + * Base constructor for all composite component. + * + * @param {ReactElement} element + * @final + * @internal + */ + construct: function (element) { + this._currentElement = element; + this._rootNodeID = null; + this._instance = null; + + // See ReactUpdateQueue + this._pendingElement = null; + this._pendingStateQueue = null; + this._pendingReplaceState = false; + this._pendingForceUpdate = false; + + this._renderedComponent = null; + + this._context = null; + this._mountOrder = 0; + this._topLevelWrapper = null; + + // See ReactUpdates and ReactUpdateQueue. + this._pendingCallbacks = null; + }, + + /** + * Initializes the component, renders markup, and registers event listeners. + * + * @param {string} rootID DOM ID of the root node. + * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction + * @return {?string} Rendered markup to be inserted into the DOM. + * @final + * @internal + */ + mountComponent: function (rootID, transaction, context) { + this._context = context; + this._mountOrder = nextMountID++; + this._rootNodeID = rootID; + + var publicProps = this._processProps(this._currentElement.props); + var publicContext = this._processContext(context); + + var Component = this._currentElement.type; + + // Initialize the public class + var inst; + var renderedElement; + + // This is a way to detect if Component is a stateless arrow function + // component, which is not newable. It might not be 100% reliable but is + // something we can do until we start detecting that Component extends + // React.Component. We already assume that typeof Component === 'function'. + var canInstantiate = ('prototype' in Component); + + if (canInstantiate) { + if ("development" !== 'production') { + ReactCurrentOwner.current = this; + try { + inst = new Component(publicProps, publicContext, ReactUpdateQueue); + } finally { + ReactCurrentOwner.current = null; + } + } else { + inst = new Component(publicProps, publicContext, ReactUpdateQueue); + } + } + + if (!canInstantiate || inst === null || inst === false || ReactElement.isValidElement(inst)) { + renderedElement = inst; + inst = new StatelessComponent(Component); + } + + if ("development" !== 'production') { + // This will throw later in _renderValidatedComponent, but add an early + // warning now to help debugging + if (inst.render == null) { + "development" !== 'production' ? warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`, returned ' + 'null/false from a stateless component, or tried to render an ' + 'element whose type is a function that isn\'t a React component.', Component.displayName || Component.name || 'Component') : undefined; + } else { + // We support ES6 inheriting from React.Component, the module pattern, + // and stateless components, but not ES6 classes that don't extend + "development" !== 'production' ? warning(Component.prototype && Component.prototype.isReactComponent || !canInstantiate || !(inst instanceof Component), '%s(...): React component classes must extend React.Component.', Component.displayName || Component.name || 'Component') : undefined; + } + } + + // These should be set up in the constructor, but as a convenience for + // simpler class abstractions, we set them up after the fact. + inst.props = publicProps; + inst.context = publicContext; + inst.refs = emptyObject; + inst.updater = ReactUpdateQueue; + + this._instance = inst; + + // Store a reference from the instance back to the internal representation + ReactInstanceMap.set(inst, this); + + if ("development" !== 'production') { + // Since plain JS classes are defined without any special initialization + // logic, we can not catch common errors early. Therefore, we have to + // catch them here, at initialization time, instead. + "development" !== 'production' ? warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', this.getName() || 'a component') : undefined; + "development" !== 'production' ? warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', this.getName() || 'a component') : undefined; + "development" !== 'production' ? warning(!inst.propTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', this.getName() || 'a component') : undefined; + "development" !== 'production' ? warning(!inst.contextTypes, 'contextTypes was defined as an instance property on %s. Use a ' + 'static property to define contextTypes instead.', this.getName() || 'a component') : undefined; + "development" !== 'production' ? warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', this.getName() || 'A component') : undefined; + "development" !== 'production' ? warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', this.getName() || 'A component') : undefined; + "development" !== 'production' ? warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', this.getName() || 'A component') : undefined; + } + + var initialState = inst.state; + if (initialState === undefined) { + inst.state = initialState = null; + } + !(typeof initialState === 'object' && !Array.isArray(initialState)) ? "development" !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : invariant(false) : undefined; + + this._pendingStateQueue = null; + this._pendingReplaceState = false; + this._pendingForceUpdate = false; + + if (inst.componentWillMount) { + inst.componentWillMount(); + // When mounting, calls to `setState` by `componentWillMount` will set + // `this._pendingStateQueue` without triggering a re-render. + if (this._pendingStateQueue) { + inst.state = this._processPendingState(inst.props, inst.context); + } + } + + // If not a stateless component, we now render + if (renderedElement === undefined) { + renderedElement = this._renderValidatedComponent(); + } + + this._renderedComponent = this._instantiateReactComponent(renderedElement); + + var markup = ReactReconciler.mountComponent(this._renderedComponent, rootID, transaction, this._processChildContext(context)); + if (inst.componentDidMount) { + transaction.getReactMountReady().enqueue(inst.componentDidMount, inst); + } + + return markup; + }, + + /** + * Releases any resources allocated by `mountComponent`. + * + * @final + * @internal + */ + unmountComponent: function () { + var inst = this._instance; + + if (inst.componentWillUnmount) { + inst.componentWillUnmount(); + } + + ReactReconciler.unmountComponent(this._renderedComponent); + this._renderedComponent = null; + this._instance = null; + + // Reset pending fields + // Even if this component is scheduled for another update in ReactUpdates, + // it would still be ignored because these fields are reset. + this._pendingStateQueue = null; + this._pendingReplaceState = false; + this._pendingForceUpdate = false; + this._pendingCallbacks = null; + this._pendingElement = null; + + // These fields do not really need to be reset since this object is no + // longer accessible. + this._context = null; + this._rootNodeID = null; + this._topLevelWrapper = null; + + // Delete the reference from the instance to this internal representation + // which allow the internals to be properly cleaned up even if the user + // leaks a reference to the public instance. + ReactInstanceMap.remove(inst); + + // Some existing components rely on inst.props even after they've been + // destroyed (in event handlers). + // TODO: inst.props = null; + // TODO: inst.state = null; + // TODO: inst.context = null; + }, + + /** + * Filters the context object to only contain keys specified in + * `contextTypes` + * + * @param {object} context + * @return {?object} + * @private + */ + _maskContext: function (context) { + var maskedContext = null; + var Component = this._currentElement.type; + var contextTypes = Component.contextTypes; + if (!contextTypes) { + return emptyObject; + } + maskedContext = {}; + for (var contextName in contextTypes) { + maskedContext[contextName] = context[contextName]; + } + return maskedContext; + }, + + /** + * Filters the context object to only contain keys specified in + * `contextTypes`, and asserts that they are valid. + * + * @param {object} context + * @return {?object} + * @private + */ + _processContext: function (context) { + var maskedContext = this._maskContext(context); + if ("development" !== 'production') { + var Component = this._currentElement.type; + if (Component.contextTypes) { + this._checkPropTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context); + } + } + return maskedContext; + }, + + /** + * @param {object} currentContext + * @return {object} + * @private + */ + _processChildContext: function (currentContext) { + var Component = this._currentElement.type; + var inst = this._instance; + var childContext = inst.getChildContext && inst.getChildContext(); + if (childContext) { + !(typeof Component.childContextTypes === 'object') ? "development" !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', this.getName() || 'ReactCompositeComponent') : invariant(false) : undefined; + if ("development" !== 'production') { + this._checkPropTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext); + } + for (var name in childContext) { + !(name in Component.childContextTypes) ? "development" !== 'production' ? invariant(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : invariant(false) : undefined; + } + return assign({}, currentContext, childContext); + } + return currentContext; + }, + + /** + * Processes props by setting default values for unspecified props and + * asserting that the props are valid. Does not mutate its argument; returns + * a new props object with defaults merged in. + * + * @param {object} newProps + * @return {object} + * @private + */ + _processProps: function (newProps) { + if ("development" !== 'production') { + var Component = this._currentElement.type; + if (Component.propTypes) { + this._checkPropTypes(Component.propTypes, newProps, ReactPropTypeLocations.prop); + } + } + return newProps; + }, + + /** + * Assert that the props are valid + * + * @param {object} propTypes Map of prop name to a ReactPropType + * @param {object} props + * @param {string} location e.g. "prop", "context", "child context" + * @private + */ + _checkPropTypes: function (propTypes, props, location) { + // TODO: Stop validating prop types here and only use the element + // validation. + var componentName = this.getName(); + for (var propName in propTypes) { + if (propTypes.hasOwnProperty(propName)) { + var error; + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + !(typeof propTypes[propName] === 'function') ? "development" !== 'production' ? invariant(false, '%s: %s type `%s` is invalid; it must be a function, usually ' + 'from React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], propName) : invariant(false) : undefined; + error = propTypes[propName](props, propName, componentName, location); + } catch (ex) { + error = ex; + } + if (error instanceof Error) { + // We may want to extend this logic for similar errors in + // top-level render calls, so I'm abstracting it away into + // a function to minimize refactoring in the future + var addendum = getDeclarationErrorAddendum(this); + + if (location === ReactPropTypeLocations.prop) { + // Preface gives us something to blacklist in warning module + "development" !== 'production' ? warning(false, 'Failed Composite propType: %s%s', error.message, addendum) : undefined; + } else { + "development" !== 'production' ? warning(false, 'Failed Context Types: %s%s', error.message, addendum) : undefined; + } + } + } + } + }, + + receiveComponent: function (nextElement, transaction, nextContext) { + var prevElement = this._currentElement; + var prevContext = this._context; + + this._pendingElement = null; + + this.updateComponent(transaction, prevElement, nextElement, prevContext, nextContext); + }, + + /** + * If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate` + * is set, update the component. + * + * @param {ReactReconcileTransaction} transaction + * @internal + */ + performUpdateIfNecessary: function (transaction) { + if (this._pendingElement != null) { + ReactReconciler.receiveComponent(this, this._pendingElement || this._currentElement, transaction, this._context); + } + + if (this._pendingStateQueue !== null || this._pendingForceUpdate) { + this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context); + } + }, + + /** + * Perform an update to a mounted component. The componentWillReceiveProps and + * shouldComponentUpdate methods are called, then (assuming the update isn't + * skipped) the remaining update lifecycle methods are called and the DOM + * representation is updated. + * + * By default, this implements React's rendering and reconciliation algorithm. + * Sophisticated clients may wish to override this. + * + * @param {ReactReconcileTransaction} transaction + * @param {ReactElement} prevParentElement + * @param {ReactElement} nextParentElement + * @internal + * @overridable + */ + updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) { + var inst = this._instance; + + var nextContext = this._context === nextUnmaskedContext ? inst.context : this._processContext(nextUnmaskedContext); + var nextProps; + + // Distinguish between a props update versus a simple state update + if (prevParentElement === nextParentElement) { + // Skip checking prop types again -- we don't read inst.props to avoid + // warning for DOM component props in this upgrade + nextProps = nextParentElement.props; + } else { + nextProps = this._processProps(nextParentElement.props); + // An update here will schedule an update but immediately set + // _pendingStateQueue which will ensure that any state updates gets + // immediately reconciled instead of waiting for the next batch. + + if (inst.componentWillReceiveProps) { + inst.componentWillReceiveProps(nextProps, nextContext); + } + } + + var nextState = this._processPendingState(nextProps, nextContext); + + var shouldUpdate = this._pendingForceUpdate || !inst.shouldComponentUpdate || inst.shouldComponentUpdate(nextProps, nextState, nextContext); + + if ("development" !== 'production') { + "development" !== 'production' ? warning(typeof shouldUpdate !== 'undefined', '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', this.getName() || 'ReactCompositeComponent') : undefined; + } + + if (shouldUpdate) { + this._pendingForceUpdate = false; + // Will set `this.props`, `this.state` and `this.context`. + this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext); + } else { + // If it's determined that a component should not update, we still want + // to set props and state but we shortcut the rest of the update. + this._currentElement = nextParentElement; + this._context = nextUnmaskedContext; + inst.props = nextProps; + inst.state = nextState; + inst.context = nextContext; + } + }, + + _processPendingState: function (props, context) { + var inst = this._instance; + var queue = this._pendingStateQueue; + var replace = this._pendingReplaceState; + this._pendingReplaceState = false; + this._pendingStateQueue = null; + + if (!queue) { + return inst.state; + } + + if (replace && queue.length === 1) { + return queue[0]; + } + + var nextState = assign({}, replace ? queue[0] : inst.state); + for (var i = replace ? 1 : 0; i < queue.length; i++) { + var partial = queue[i]; + assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial); + } + + return nextState; + }, + + /** + * Merges new props and state, notifies delegate methods of update and + * performs update. + * + * @param {ReactElement} nextElement Next element + * @param {object} nextProps Next public object to set as properties. + * @param {?object} nextState Next object to set as state. + * @param {?object} nextContext Next public object to set as context. + * @param {ReactReconcileTransaction} transaction + * @param {?object} unmaskedContext + * @private + */ + _performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) { + var inst = this._instance; + + var hasComponentDidUpdate = Boolean(inst.componentDidUpdate); + var prevProps; + var prevState; + var prevContext; + if (hasComponentDidUpdate) { + prevProps = inst.props; + prevState = inst.state; + prevContext = inst.context; + } + + if (inst.componentWillUpdate) { + inst.componentWillUpdate(nextProps, nextState, nextContext); + } + + this._currentElement = nextElement; + this._context = unmaskedContext; + inst.props = nextProps; + inst.state = nextState; + inst.context = nextContext; + + this._updateRenderedComponent(transaction, unmaskedContext); + + if (hasComponentDidUpdate) { + transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst); + } + }, + + /** + * Call the component's `render` method and update the DOM accordingly. + * + * @param {ReactReconcileTransaction} transaction + * @internal + */ + _updateRenderedComponent: function (transaction, context) { + var prevComponentInstance = this._renderedComponent; + var prevRenderedElement = prevComponentInstance._currentElement; + var nextRenderedElement = this._renderValidatedComponent(); + if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) { + ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context)); + } else { + // These two IDs are actually the same! But nothing should rely on that. + var thisID = this._rootNodeID; + var prevComponentID = prevComponentInstance._rootNodeID; + ReactReconciler.unmountComponent(prevComponentInstance); + + this._renderedComponent = this._instantiateReactComponent(nextRenderedElement); + var nextMarkup = ReactReconciler.mountComponent(this._renderedComponent, thisID, transaction, this._processChildContext(context)); + this._replaceNodeWithMarkupByID(prevComponentID, nextMarkup); + } + }, + + /** + * @protected + */ + _replaceNodeWithMarkupByID: function (prevComponentID, nextMarkup) { + ReactComponentEnvironment.replaceNodeWithMarkupByID(prevComponentID, nextMarkup); + }, + + /** + * @protected + */ + _renderValidatedComponentWithoutOwnerOrContext: function () { + var inst = this._instance; + var renderedComponent = inst.render(); + if ("development" !== 'production') { + // We allow auto-mocks to proceed as if they're returning null. + if (typeof renderedComponent === 'undefined' && inst.render._isMockFunction) { + // This is probably bad practice. Consider warning here and + // deprecating this convenience. + renderedComponent = null; + } + } + + return renderedComponent; + }, + + /** + * @private + */ + _renderValidatedComponent: function () { + var renderedComponent; + ReactCurrentOwner.current = this; + try { + renderedComponent = this._renderValidatedComponentWithoutOwnerOrContext(); + } finally { + ReactCurrentOwner.current = null; + } + !( + // TODO: An `isValidNode` function would probably be more appropriate + renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent)) ? "development" !== 'production' ? invariant(false, '%s.render(): A valid ReactComponent must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : invariant(false) : undefined; + return renderedComponent; + }, + + /** + * Lazily allocates the refs object and stores `component` as `ref`. + * + * @param {string} ref Reference name. + * @param {component} component Component to store as `ref`. + * @final + * @private + */ + attachRef: function (ref, component) { + var inst = this.getPublicInstance(); + !(inst != null) ? "development" !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : invariant(false) : undefined; + var publicComponentInstance = component.getPublicInstance(); + if ("development" !== 'production') { + var componentName = component && component.getName ? component.getName() : 'a component'; + "development" !== 'production' ? warning(publicComponentInstance != null, 'Stateless function components cannot be given refs ' + '(See ref "%s" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : undefined; + } + var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs; + refs[ref] = publicComponentInstance; + }, + + /** + * Detaches a reference name. + * + * @param {string} ref Name to dereference. + * @final + * @private + */ + detachRef: function (ref) { + var refs = this.getPublicInstance().refs; + delete refs[ref]; + }, + + /** + * Get a text description of the component that can be used to identify it + * in error messages. + * @return {string} The name or null. + * @internal + */ + getName: function () { + var type = this._currentElement.type; + var constructor = this._instance && this._instance.constructor; + return type.displayName || constructor && constructor.displayName || type.name || constructor && constructor.name || null; + }, + + /** + * Get the publicly accessible representation of this component - i.e. what + * is exposed by refs and returned by render. Can be null for stateless + * components. + * + * @return {ReactComponent} the public component instance. + * @internal + */ + getPublicInstance: function () { + var inst = this._instance; + if (inst instanceof StatelessComponent) { + return null; + } + return inst; + }, + + // Stub + _instantiateReactComponent: null + +}; + +ReactPerf.measureMethods(ReactCompositeComponentMixin, 'ReactCompositeComponent', { + mountComponent: 'mountComponent', + updateComponent: 'updateComponent', + _renderValidatedComponent: '_renderValidatedComponent' +}); + +var ReactCompositeComponent = { + + Mixin: ReactCompositeComponentMixin + +}; + +module.exports = ReactCompositeComponent; +},{"141":141,"154":154,"161":161,"173":173,"24":24,"36":36,"39":39,"57":57,"68":68,"78":78,"80":80,"81":81,"84":84,"95":95}],39:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactCurrentOwner + */ + +'use strict'; + +/** + * Keeps track of the current owner. + * + * The current owner is the component who should own any components that are + * currently being constructed. + */ +var ReactCurrentOwner = { + + /** + * @internal + * @type {ReactComponent} + */ + current: null + +}; + +module.exports = ReactCurrentOwner; +},{}],40:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactDOM + */ + +/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/ + +'use strict'; + +var ReactCurrentOwner = _dereq_(39); +var ReactDOMTextComponent = _dereq_(51); +var ReactDefaultInjection = _dereq_(54); +var ReactInstanceHandles = _dereq_(67); +var ReactMount = _dereq_(72); +var ReactPerf = _dereq_(78); +var ReactReconciler = _dereq_(84); +var ReactUpdates = _dereq_(96); +var ReactVersion = _dereq_(97); + +var findDOMNode = _dereq_(122); +var renderSubtreeIntoContainer = _dereq_(137); +var warning = _dereq_(173); + +ReactDefaultInjection.inject(); + +var render = ReactPerf.measure('React', 'render', ReactMount.render); + +var React = { + findDOMNode: findDOMNode, + render: render, + unmountComponentAtNode: ReactMount.unmountComponentAtNode, + version: ReactVersion, + + /* eslint-disable camelcase */ + unstable_batchedUpdates: ReactUpdates.batchedUpdates, + unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer +}; + +// Inject the runtime into a devtools global hook regardless of browser. +// Allows for debugging when the hook is injected on the page. +/* eslint-enable camelcase */ +if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') { + __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({ + CurrentOwner: ReactCurrentOwner, + InstanceHandles: ReactInstanceHandles, + Mount: ReactMount, + Reconciler: ReactReconciler, + TextComponent: ReactDOMTextComponent + }); +} + +if ("development" !== 'production') { + var ExecutionEnvironment = _dereq_(147); + if (ExecutionEnvironment.canUseDOM && window.top === window.self) { + + // First check if devtools is not installed + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') { + // If we're in Chrome or Firefox, provide a download link if not installed. + if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) { + console.debug('Download the React DevTools for a better development experience: ' + 'https://fb.me/react-devtools'); + } + } + + // If we're in IE8, check to see if we are in compatibility mode and provide + // information on preventing compatibility mode + var ieCompatibilityMode = document.documentMode && document.documentMode < 8; + + "development" !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '') : undefined; + + var expectedFeatures = [ + // shims + Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim, + + // shams + Object.create, Object.freeze]; + + for (var i = 0; i < expectedFeatures.length; i++) { + if (!expectedFeatures[i]) { + console.error('One or more ES5 shim/shams expected by React are not available: ' + 'https://fb.me/react-warning-polyfills'); + break; + } + } + } +} + +module.exports = React; +},{"122":122,"137":137,"147":147,"173":173,"39":39,"51":51,"54":54,"67":67,"72":72,"78":78,"84":84,"96":96,"97":97}],41:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactDOMButton + */ + +'use strict'; + +var mouseListenerNames = { + onClick: true, + onDoubleClick: true, + onMouseDown: true, + onMouseMove: true, + onMouseUp: true, + + onClickCapture: true, + onDoubleClickCapture: true, + onMouseDownCapture: true, + onMouseMoveCapture: true, + onMouseUpCapture: true +}; + +/** + * Implements a