From: Vásáry Dániel Date: Thu, 16 Nov 2017 16:07:57 +0000 (+0000) Subject: git-tfs-id: [http://tfs.userrendszerhaz.hu:8080/tfs/DefaultCollection]$/MediaCube... X-Git-Url: http://git.useribm.hu/?a=commitdiff_plain;h=2fc65451399da8cce5b84bab9947d023a5e11a16;p=mediacube.git git-tfs-id: [tfs.userrendszerhaz.hu:8080/tfs/DefaultCollection]$/MediaCube;C30735 --- diff --git a/client/DxPlay/DxPlay.csproj b/client/DxPlay/DxPlay.csproj index 43376c7c..504dc315 100644 --- a/client/DxPlay/DxPlay.csproj +++ b/client/DxPlay/DxPlay.csproj @@ -224,6 +224,12 @@ + + + + + + ResXFileCodeGenerator StringResource.Designer.cs diff --git a/client/DxPlay/PlayerForm.Designer.cs b/client/DxPlay/PlayerForm.Designer.cs index 7dfe2840..4f651645 100644 --- a/client/DxPlay/PlayerForm.Designer.cs +++ b/client/DxPlay/PlayerForm.Designer.cs @@ -3,10 +3,9 @@ using System.Windows.Forms; namespace DxPlay { partial class PlayerForm : Form { - private Panel panelVideo; + private Panel pVideo; private Button btnPlay; private Button btnPause; - private Panel panel2; private TextBox textCurrentTC; private Button btnStop; private TextBox txtStartTC; @@ -40,21 +39,21 @@ namespace DxPlay { this.components = new System.ComponentModel.Container(); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PlayerForm)); - this.panelVideo = new System.Windows.Forms.Panel(); - this.panel2 = new System.Windows.Forms.Panel(); - this.btnStop = new System.Windows.Forms.Button(); - this.btnPlay = new System.Windows.Forms.Button(); - this.btnPause = new System.Windows.Forms.Button(); + this.pVideo = new System.Windows.Forms.Panel(); this.textCurrentTC = new System.Windows.Forms.TextBox(); this.txtStartTC = new System.Windows.Forms.TextBox(); this.txtEndTC = new System.Windows.Forms.TextBox(); this.panel3 = new System.Windows.Forms.Panel(); this.labelStatus = new System.Windows.Forms.Label(); + this.trackBar1 = new DxPlay.ColorSlider(); this.label2 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label(); - this.trackBar1 = new DxPlay.ColorSlider(); this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.panelPlayer = new System.Windows.Forms.Panel(); + this.pControls = new System.Windows.Forms.FlowLayoutPanel(); + this.btnPlay = new System.Windows.Forms.Button(); + this.btnStop = new System.Windows.Forms.Button(); + this.btnPause = new System.Windows.Forms.Button(); this.dgSegments = new System.Windows.Forms.DataGridView(); this.bsSegments = new System.Windows.Forms.BindingSource(this.components); this.menuButtonSegmentActions = new DxPlay.MenuButton(); @@ -64,90 +63,48 @@ namespace DxPlay { this.deleteSegmentToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.actualPositionToIntroToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.actualPositionToOutroToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.panel2.SuspendLayout(); this.panel3.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); this.splitContainer1.SuspendLayout(); this.panelPlayer.SuspendLayout(); + this.pControls.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dgSegments)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.bsSegments)).BeginInit(); this.ctxmSegmentActions.SuspendLayout(); this.SuspendLayout(); // - // panelVideo - // - this.panelVideo.BackColor = System.Drawing.Color.Black; - this.panelVideo.Dock = System.Windows.Forms.DockStyle.Fill; - this.panelVideo.Location = new System.Drawing.Point(0, 0); - this.panelVideo.Name = "panelVideo"; - this.panelVideo.Size = new System.Drawing.Size(675, 447); - this.panelVideo.TabIndex = 10; - this.panelVideo.TabStop = true; - this.panelVideo.SizeChanged += new System.EventHandler(this.panel1_SizeChanged); - this.panelVideo.MouseDown += new System.Windows.Forms.MouseEventHandler(this.panel1_MouseDown); - // - // panel2 - // - this.panel2.BackColor = System.Drawing.SystemColors.Control; - this.panel2.Controls.Add(this.btnStop); - this.panel2.Controls.Add(this.btnPlay); - this.panel2.Controls.Add(this.btnPause); - this.panel2.Dock = System.Windows.Forms.DockStyle.Bottom; - this.panel2.Location = new System.Drawing.Point(0, 510); - this.panel2.Name = "panel2"; - this.panel2.Size = new System.Drawing.Size(675, 34); - this.panel2.TabIndex = 14; + // pVideo // - // btnStop - // - this.btnStop.Image = global::DxPlay.Properties.Resources.Stop; - this.btnStop.Location = new System.Drawing.Point(89, 3); - this.btnStop.Name = "btnStop"; - this.btnStop.Size = new System.Drawing.Size(80, 25); - this.btnStop.TabIndex = 16; - this.btnStop.Text = "Stop"; - this.btnStop.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - this.btnStop.Click += new System.EventHandler(this.btnStop_Click); - // - // btnPlay - // - this.btnPlay.Image = global::DxPlay.Properties.Resources.Play; - this.btnPlay.Location = new System.Drawing.Point(3, 3); - this.btnPlay.Name = "btnPlay"; - this.btnPlay.Size = new System.Drawing.Size(80, 25); - this.btnPlay.TabIndex = 1; - this.btnPlay.Text = "Play"; - this.btnPlay.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - this.btnPlay.Click += new System.EventHandler(this.btnPlay_Click); - // - // btnPause - // - this.btnPause.Image = global::DxPlay.Properties.Resources.Pause; - this.btnPause.Location = new System.Drawing.Point(175, 3); - this.btnPause.Name = "btnPause"; - this.btnPause.Size = new System.Drawing.Size(80, 25); - this.btnPause.TabIndex = 11; - this.btnPause.Text = "Pause"; - this.btnPause.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - this.btnPause.Click += new System.EventHandler(this.btnPause_Click); + this.pVideo.BackColor = System.Drawing.Color.Black; + this.pVideo.Dock = System.Windows.Forms.DockStyle.Fill; + this.pVideo.Location = new System.Drawing.Point(0, 0); + this.pVideo.Name = "pVideo"; + this.pVideo.Size = new System.Drawing.Size(675, 433); + this.pVideo.TabIndex = 10; + this.pVideo.TabStop = true; + this.pVideo.SizeChanged += new System.EventHandler(this.panel1_SizeChanged); + this.pVideo.MouseDown += new System.Windows.Forms.MouseEventHandler(this.panel1_MouseDown); // // textCurrentTC // - this.textCurrentTC.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.textCurrentTC.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.textCurrentTC.BackColor = System.Drawing.Color.White; this.textCurrentTC.BorderStyle = System.Windows.Forms.BorderStyle.None; this.textCurrentTC.Font = new System.Drawing.Font("Calibri", 16F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238))); - this.textCurrentTC.Location = new System.Drawing.Point(284, 13); + this.textCurrentTC.Location = new System.Drawing.Point(284, 12); this.textCurrentTC.Name = "textCurrentTC"; this.textCurrentTC.ReadOnly = true; this.textCurrentTC.Size = new System.Drawing.Size(108, 27); this.textCurrentTC.TabIndex = 15; + this.textCurrentTC.TabStop = false; this.textCurrentTC.Text = "00:00:00.00"; // // txtStartTC // this.txtStartTC.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.txtStartTC.BackColor = System.Drawing.Color.White; this.txtStartTC.BorderStyle = System.Windows.Forms.BorderStyle.None; this.txtStartTC.Font = new System.Drawing.Font("Calibri", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); this.txtStartTC.ForeColor = System.Drawing.SystemColors.WindowText; @@ -156,67 +113,51 @@ namespace DxPlay { this.txtStartTC.ReadOnly = true; this.txtStartTC.Size = new System.Drawing.Size(66, 17); this.txtStartTC.TabIndex = 16; + this.txtStartTC.TabStop = false; this.txtStartTC.Text = "00:00:00.00"; // // txtEndTC // this.txtEndTC.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.txtEndTC.BackColor = System.Drawing.Color.White; this.txtEndTC.BorderStyle = System.Windows.Forms.BorderStyle.None; this.txtEndTC.Font = new System.Drawing.Font("Calibri", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); this.txtEndTC.ForeColor = System.Drawing.SystemColors.WindowText; - this.txtEndTC.Location = new System.Drawing.Point(603, 21); + this.txtEndTC.Location = new System.Drawing.Point(605, 24); this.txtEndTC.Name = "txtEndTC"; this.txtEndTC.ReadOnly = true; this.txtEndTC.Size = new System.Drawing.Size(65, 17); this.txtEndTC.TabIndex = 17; + this.txtEndTC.TabStop = false; this.txtEndTC.Text = "00:00:00.00"; + this.txtEndTC.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; // // panel3 // this.panel3.Controls.Add(this.labelStatus); + this.panel3.Controls.Add(this.trackBar1); this.panel3.Controls.Add(this.label2); this.panel3.Controls.Add(this.label1); this.panel3.Controls.Add(this.txtStartTC); this.panel3.Controls.Add(this.txtEndTC); this.panel3.Controls.Add(this.textCurrentTC); this.panel3.Dock = System.Windows.Forms.DockStyle.Bottom; - this.panel3.Location = new System.Drawing.Point(0, 447); + this.panel3.Location = new System.Drawing.Point(0, 433); this.panel3.Name = "panel3"; - this.panel3.Size = new System.Drawing.Size(675, 41); + this.panel3.Size = new System.Drawing.Size(675, 51); this.panel3.TabIndex = 19; // // labelStatus // - this.labelStatus.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.labelStatus.Anchor = System.Windows.Forms.AnchorStyles.Bottom; this.labelStatus.Font = new System.Drawing.Font("Calibri", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); - this.labelStatus.Location = new System.Drawing.Point(281, 5); + this.labelStatus.Location = new System.Drawing.Point(281, 4); this.labelStatus.Name = "labelStatus"; this.labelStatus.Size = new System.Drawing.Size(111, 13); this.labelStatus.TabIndex = 20; this.labelStatus.Text = "NO INPUT"; this.labelStatus.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // - // label2 - // - this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.label2.AutoSize = true; - this.label2.Font = new System.Drawing.Font("Calibri", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); - this.label2.Location = new System.Drawing.Point(618, 5); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(54, 13); - this.label2.TabIndex = 19; - this.label2.Text = "DURATION"; - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Font = new System.Drawing.Font("Calibri", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); - this.label1.Location = new System.Drawing.Point(4, 6); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(33, 13); - this.label1.TabIndex = 18; - this.label1.Text = "START"; - // // trackBar1 // this.trackBar1.BackColor = System.Drawing.Color.Transparent; @@ -228,10 +169,10 @@ namespace DxPlay { this.trackBar1.ElapsedInnerColor = System.Drawing.Color.Black; this.trackBar1.ElapsedOuterColor = System.Drawing.Color.DarkGray; this.trackBar1.LargeChange = ((uint)(0u)); - this.trackBar1.Location = new System.Drawing.Point(0, 488); + this.trackBar1.Location = new System.Drawing.Point(0, 41); this.trackBar1.Maximum = 1; this.trackBar1.Name = "trackBar1"; - this.trackBar1.Size = new System.Drawing.Size(675, 22); + this.trackBar1.Size = new System.Drawing.Size(675, 10); this.trackBar1.SmallChange = ((uint)(1u)); this.trackBar1.TabIndex = 18; this.trackBar1.Text = "colorSlider1"; @@ -244,6 +185,28 @@ namespace DxPlay { this.trackBar1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.trackBar1_MouseDown); this.trackBar1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.trackBar1_MouseUp); // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.label2.Font = new System.Drawing.Font("Calibri", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.label2.Location = new System.Drawing.Point(605, 5); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(68, 13); + this.label2.TabIndex = 19; + this.label2.Text = "DURATION"; + this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.label1.Font = new System.Drawing.Font("Calibri", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.label1.Location = new System.Drawing.Point(3, 5); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(69, 13); + this.label1.TabIndex = 18; + this.label1.Text = "START"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // // splitContainer1 // this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; @@ -264,16 +227,71 @@ namespace DxPlay { // // panelPlayer // - this.panelPlayer.Controls.Add(this.panelVideo); + this.panelPlayer.Controls.Add(this.pVideo); this.panelPlayer.Controls.Add(this.panel3); - this.panelPlayer.Controls.Add(this.trackBar1); - this.panelPlayer.Controls.Add(this.panel2); + this.panelPlayer.Controls.Add(this.pControls); this.panelPlayer.Dock = System.Windows.Forms.DockStyle.Fill; this.panelPlayer.Location = new System.Drawing.Point(0, 0); this.panelPlayer.Name = "panelPlayer"; this.panelPlayer.Size = new System.Drawing.Size(675, 544); this.panelPlayer.TabIndex = 0; // + // pControls + // + this.pControls.AutoSize = true; + this.pControls.Controls.Add(this.btnPlay); + this.pControls.Controls.Add(this.btnStop); + this.pControls.Controls.Add(this.btnPause); + this.pControls.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pControls.Location = new System.Drawing.Point(0, 484); + this.pControls.Name = "pControls"; + this.pControls.Size = new System.Drawing.Size(675, 60); + this.pControls.TabIndex = 20; + // + // btnPlay + // + this.btnPlay.AutoSize = true; + this.btnPlay.BackColor = System.Drawing.Color.White; + this.btnPlay.FlatAppearance.BorderSize = 0; + this.btnPlay.Image = global::DxPlay.Properties.Resources.ic_play_arrow_black_24dp_2x; + this.btnPlay.Location = new System.Drawing.Point(3, 3); + this.btnPlay.Name = "btnPlay"; + this.btnPlay.Size = new System.Drawing.Size(54, 54); + this.btnPlay.TabIndex = 1; + this.btnPlay.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; + this.btnPlay.UseVisualStyleBackColor = false; + this.btnPlay.Click += new System.EventHandler(this.btnPlay_Click); + // + // btnStop + // + this.btnStop.AutoSize = true; + this.btnStop.BackColor = System.Drawing.Color.White; + this.btnStop.FlatAppearance.BorderSize = 0; + this.btnStop.FlatStyle = System.Windows.Forms.FlatStyle.Popup; + this.btnStop.Image = global::DxPlay.Properties.Resources.ic_stop_black_24dp_2x; + this.btnStop.Location = new System.Drawing.Point(63, 3); + this.btnStop.Name = "btnStop"; + this.btnStop.Size = new System.Drawing.Size(54, 54); + this.btnStop.TabIndex = 16; + this.btnStop.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; + this.btnStop.UseVisualStyleBackColor = false; + this.btnStop.Click += new System.EventHandler(this.btnStop_Click); + // + // btnPause + // + this.btnPause.AutoSize = true; + this.btnPause.BackColor = System.Drawing.Color.White; + this.btnPause.FlatAppearance.BorderSize = 0; + this.btnPause.FlatStyle = System.Windows.Forms.FlatStyle.Popup; + this.btnPause.Image = global::DxPlay.Properties.Resources.ic_pause_black_24dp_2x; + this.btnPause.Location = new System.Drawing.Point(123, 3); + this.btnPause.Name = "btnPause"; + this.btnPause.Size = new System.Drawing.Size(54, 54); + this.btnPause.TabIndex = 11; + this.btnPause.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; + this.btnPause.UseVisualStyleBackColor = false; + this.btnPause.Click += new System.EventHandler(this.btnPause_Click); + // // dgSegments // this.dgSegments.AllowUserToAddRows = false; @@ -366,6 +384,7 @@ namespace DxPlay { // this.AllowDrop = true; this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.BackColor = System.Drawing.Color.White; this.ClientSize = new System.Drawing.Size(936, 544); this.Controls.Add(this.splitContainer1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); @@ -382,7 +401,6 @@ namespace DxPlay { this.DragEnter += new System.Windows.Forms.DragEventHandler(this.Form1_DragEnter); this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.PlayerForm_KeyDown); this.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.PlayerForm_PreviewKeyDown); - this.panel2.ResumeLayout(false); this.panel3.ResumeLayout(false); this.panel3.PerformLayout(); this.splitContainer1.Panel1.ResumeLayout(false); @@ -390,6 +408,9 @@ namespace DxPlay { ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); this.splitContainer1.ResumeLayout(false); this.panelPlayer.ResumeLayout(false); + this.panelPlayer.PerformLayout(); + this.pControls.ResumeLayout(false); + this.pControls.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.dgSegments)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.bsSegments)).EndInit(); this.ctxmSegmentActions.ResumeLayout(false); @@ -412,6 +433,7 @@ namespace DxPlay { private ToolStripMenuItem deleteSegmentToolStripMenuItem; private ToolStripMenuItem actualPositionToIntroToolStripMenuItem; private ToolStripMenuItem actualPositionToOutroToolStripMenuItem; + private FlowLayoutPanel pControls; } } diff --git a/client/DxPlay/PlayerForm.cs b/client/DxPlay/PlayerForm.cs index f3965e63..4bea8a2b 100644 --- a/client/DxPlay/PlayerForm.cs +++ b/client/DxPlay/PlayerForm.cs @@ -49,9 +49,9 @@ namespace DxPlay { deleteSegmentToolStripMenuItem.Text = StringResource.SZEGMENS_TORLESE; menuButtonSegmentActions.Text = StringResource.SZEGMENSEK; - btnPause.Text = StringResource.SZUNET; - btnPlay.Text = StringResource.LEJATSZAS; - btnStop.Text = StringResource.LEALLITAS; + //btnPause.Text = StringResource.SZUNET; + //btnPlay.Text = StringResource.LEJATSZAS; + //btnStop.Text = StringResource.LEALLITAS; labelStatus.Text = StringResource.NINCS_BEMENET; label1.Text = StringResource.INDULASI_PONT; label2.Text = StringResource.HOSSZ; @@ -65,7 +65,7 @@ namespace DxPlay { trackBar1.Value = 0; trackBar1.Minimum = 0; - m_play = new DxPlayer(panelVideo, ref m_mediaDescription); + m_play = new DxPlayer(pVideo, ref m_mediaDescription); if (m_play.IsError) throw new Exception(selectedFile); @@ -155,7 +155,7 @@ namespace DxPlay { private void panel1_SizeChanged(object sender, EventArgs e) { if (m_play != null) - m_play.UpdateVideoWindow(panelVideo); + m_play.UpdateVideoWindow(pVideo); } private void trackBar1_MouseDown(object sender, MouseEventArgs e) { diff --git a/client/DxPlay/Properties/Resources.Designer.cs b/client/DxPlay/Properties/Resources.Designer.cs index 35fa24ad..a26553f5 100644 --- a/client/DxPlay/Properties/Resources.Designer.cs +++ b/client/DxPlay/Properties/Resources.Designer.cs @@ -60,6 +60,66 @@ namespace DxPlay.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap ic_pause_black_24dp_1x { + get { + object obj = ResourceManager.GetObject("ic_pause_black_24dp_1x", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap ic_pause_black_24dp_2x { + get { + object obj = ResourceManager.GetObject("ic_pause_black_24dp_2x", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap ic_play_arrow_black_24dp_1x { + get { + object obj = ResourceManager.GetObject("ic_play_arrow_black_24dp_1x", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap ic_play_arrow_black_24dp_2x { + get { + object obj = ResourceManager.GetObject("ic_play_arrow_black_24dp_2x", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap ic_stop_black_24dp_1x { + get { + object obj = ResourceManager.GetObject("ic_stop_black_24dp_1x", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap ic_stop_black_24dp_2x { + get { + object obj = ResourceManager.GetObject("ic_stop_black_24dp_2x", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/client/DxPlay/Properties/Resources.resx b/client/DxPlay/Properties/Resources.resx index 0437d4d7..7082277d 100644 --- a/client/DxPlay/Properties/Resources.resx +++ b/client/DxPlay/Properties/Resources.resx @@ -130,4 +130,22 @@ ..\Resources\Stop.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\ic_pause_black_24dp_1x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ic_pause_black_24dp_2x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ic_play_arrow_black_24dp_1x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ic_play_arrow_black_24dp_2x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ic_stop_black_24dp_1x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ic_stop_black_24dp_2x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/client/DxPlay/Resources/ic_pause_black_24dp_1x.png b/client/DxPlay/Resources/ic_pause_black_24dp_1x.png new file mode 100644 index 00000000..6145664b Binary files /dev/null and b/client/DxPlay/Resources/ic_pause_black_24dp_1x.png differ diff --git a/client/DxPlay/Resources/ic_pause_black_24dp_2x.png b/client/DxPlay/Resources/ic_pause_black_24dp_2x.png new file mode 100644 index 00000000..74068eae Binary files /dev/null and b/client/DxPlay/Resources/ic_pause_black_24dp_2x.png differ diff --git a/client/DxPlay/Resources/ic_play_arrow_black_24dp_1x.png b/client/DxPlay/Resources/ic_play_arrow_black_24dp_1x.png new file mode 100644 index 00000000..d78c57ba Binary files /dev/null and b/client/DxPlay/Resources/ic_play_arrow_black_24dp_1x.png differ diff --git a/client/DxPlay/Resources/ic_play_arrow_black_24dp_2x.png b/client/DxPlay/Resources/ic_play_arrow_black_24dp_2x.png new file mode 100644 index 00000000..f208795f Binary files /dev/null and b/client/DxPlay/Resources/ic_play_arrow_black_24dp_2x.png differ diff --git a/client/DxPlay/Resources/ic_stop_black_24dp_1x.png b/client/DxPlay/Resources/ic_stop_black_24dp_1x.png new file mode 100644 index 00000000..0588f0b4 Binary files /dev/null and b/client/DxPlay/Resources/ic_stop_black_24dp_1x.png differ diff --git a/client/DxPlay/Resources/ic_stop_black_24dp_2x.png b/client/DxPlay/Resources/ic_stop_black_24dp_2x.png new file mode 100644 index 00000000..b002ab78 Binary files /dev/null and b/client/DxPlay/Resources/ic_stop_black_24dp_2x.png differ diff --git a/client/DxPlay/StringResource.Designer.cs b/client/DxPlay/StringResource.Designer.cs index c4c11017..8b057bc4 100644 --- a/client/DxPlay/StringResource.Designer.cs +++ b/client/DxPlay/StringResource.Designer.cs @@ -115,7 +115,7 @@ namespace DxPlay { } /// - /// Looks up a localized string similar to Indulási pont. + /// Looks up a localized string similar to Kezdés. /// internal static string INDULASI_PONT { get { diff --git a/client/DxPlay/StringResource.resx b/client/DxPlay/StringResource.resx index 7c58c97d..f1442fd4 100644 --- a/client/DxPlay/StringResource.resx +++ b/client/DxPlay/StringResource.resx @@ -136,7 +136,7 @@ Indítás - Indulási pont + Kezdés Kilépés diff --git a/client/IntegrationTests/IntegrationTests.csproj b/client/IntegrationTests/IntegrationTests.csproj index 13d952e0..e086cdb7 100644 --- a/client/IntegrationTests/IntegrationTests.csproj +++ b/client/IntegrationTests/IntegrationTests.csproj @@ -96,6 +96,10 @@ ..\packages\MongoDB.Driver.Core.2.4.4\lib\net45\MongoDB.Driver.Core.dll + + False + lib\mysql.data.dll + ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll @@ -110,6 +114,7 @@ ..\packages\System.Console.4.3.0\lib\net46\System.Console.dll + ..\packages\System.Net.NameResolution.4.3.0\lib\net46\System.Net.NameResolution.dll @@ -173,6 +178,9 @@ + + + diff --git a/client/IntegrationTests/MaestroIT.cs b/client/IntegrationTests/MaestroIT.cs index 580337b9..6615d49e 100644 --- a/client/IntegrationTests/MaestroIT.cs +++ b/client/IntegrationTests/MaestroIT.cs @@ -14,6 +14,8 @@ using System.Security; using BethesdaConsentFormWCFSvc; using System.IO; using System.Text.RegularExpressions; +using MySql.Data.MySqlClient; +using System.Text; namespace IntegrationTests { public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid { @@ -234,6 +236,45 @@ namespace IntegrationTests { string[] files = Directory.GetFiles("\\\\10.10.1.100\\BRAAVOS\\Archive"); } + [TestMethod] + public void TestMySQL() { + string server = "192.168.3.10"; + string database = "echotv"; + string uid = "vasary"; + string password = "vasarydani"; + string connectionString = "SERVER=" + server + ";" + "DATABASE=" + + database + ";" + "UID=" + uid + ";" + "PASSWORD=" + password + ";Convert Zero Datetime=true;"; + + + MySqlConnection connection = new MySqlConnection(connectionString); + try { + connection.Open(); + //Query(connection, "SHOW TABLES;"); + Query(connection, "SELECT * FROM archive_records;"); + connection.Close(); + } + catch (MySqlException ex) { + Debug.WriteLine(ex.Message); + } + } + + private void Query(MySqlConnection connection, string sql) { + MySqlCommand command = connection.CreateCommand(); + command.CommandText = sql; + MySqlDataReader Reader = command.ExecuteReader(); + StringBuilder sb = new StringBuilder(); + while (Reader.Read()) { + for (int i = 0; i < Reader.FieldCount; i++) { + if (Reader.IsDBNull(i)) + sb.Append("null, "); + else + sb.Append(Reader.GetValue(i).ToString() + ", "); + } + + Debug.WriteLine(sb.ToString()); + sb.Clear(); + } + } } -} \ No newline at end of file + } \ No newline at end of file diff --git a/client/Maestro/Commons/MorpheusXML.cs b/client/Maestro/Commons/MorpheusXML.cs index 71b314a3..828911af 100644 --- a/client/Maestro/Commons/MorpheusXML.cs +++ b/client/Maestro/Commons/MorpheusXML.cs @@ -1,4 +1,5 @@ using DxPlay; +using Maestro.Metadata; using System; using System.Collections.Generic; using System.Globalization; @@ -14,6 +15,7 @@ using System.Xml; XMLTEST011 Teszt Mozi 00000914 + PROGRAMME //PROGRAMME, COMMERCIAL, JUNCTION ISILON @@ -31,7 +33,52 @@ namespace Commons { return tc?.Replace(":", "").Replace(".", ""); } - public static byte[] ToXML(string title, string fileName, string deviceID, List segments) { + public static byte[] ToXML(string title, string fileName, string deviceID, string type, List segments) { + if (String.IsNullOrEmpty(title)) + throw new NullReferenceException("Hiányzik a cél állomány címe."); + if (String.IsNullOrEmpty(fileName)) + throw new NullReferenceException("Hiányzik a cél állomány neve."); + if (String.IsNullOrEmpty(deviceID)) + throw new NullReferenceException("Hiányzik a cél állomány eszköz leírója."); + + byte[] result = null; + XmlDocument doc = new XmlDocument(); + XmlElement rootElement = (XmlElement)doc.AppendChild(doc.CreateElement("ImportItems")); + + + Timecode duration = new Timecode(); + Timecode tcIn = segments[0].TCIn; + Timecode tcOut = segments[segments.Count - 1].TCOut; + duration.Set(tcOut.Frames - tcIn.Frames); + XmlNode importItemNode = rootElement.AppendChild(doc.CreateElement("ImportItem")); + XmlElement itemElement = doc.CreateElement("Item"); + importItemNode.AppendChild(itemElement); + itemElement.AppendChild(doc.CreateElement("Material_Id")).InnerText = fileName; + itemElement.AppendChild(doc.CreateElement("Title")).InnerText = title; + itemElement.AppendChild(doc.CreateElement("On_Air_Duration")).InnerText = FlattenTC(duration.ToString()); + itemElement.AppendChild(doc.CreateElement("Material_Type")).InnerText = type; + + XmlElement instanceElement = doc.CreateElement("Instance"); + importItemNode.AppendChild(instanceElement); + instanceElement.AppendChild(doc.CreateElement("Long_File_Id")).InnerText = fileName; + instanceElement.AppendChild(doc.CreateElement("Device_Id")).InnerText = deviceID; + instanceElement.AppendChild(doc.CreateElement("Quality_Check")).InnerText = DateTime.Now.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture); + instanceElement.AppendChild(doc.CreateElement("Timecode_In")).InnerText = FlattenTC(tcIn.ToString()); + instanceElement.AppendChild(doc.CreateElement("Timecode_Out")).InnerText = FlattenTC(tcOut.ToString()); + + UTF8Encoding encoding = new UTF8Encoding(false, true); + using (MemoryStream output = new MemoryStream()) { + using (XmlTextWriter writer = new XmlTextWriter(output, encoding)) { + writer.Formatting = Formatting.Indented; + writer.WriteStartDocument(); + doc.Save(writer); + } + result = output.ToArray(); + } + return result; + } + + public static byte[] ToXMLMultiSegments(string title, string fileName, string deviceID, string type, List segments) { if (String.IsNullOrEmpty(title)) throw new NullReferenceException("Hiányzik a cél állomány címe."); if (String.IsNullOrEmpty(fileName)) @@ -52,6 +99,8 @@ namespace Commons { itemElement.AppendChild(doc.CreateElement("Material_Id")).InnerText = fileName; itemElement.AppendChild(doc.CreateElement("Title")).InnerText = title; itemElement.AppendChild(doc.CreateElement("On_Air_Duration")).InnerText = FlattenTC(duration.ToString()); + itemElement.AppendChild(doc.CreateElement("Material_Type")).InnerText = type; + XmlElement instanceElement = doc.CreateElement("Instance"); importItemNode.AppendChild(instanceElement); instanceElement.AppendChild(doc.CreateElement("Long_File_Id")).InnerText = fileName; @@ -77,6 +126,7 @@ namespace Commons { } return result; } + } } \ No newline at end of file diff --git a/client/Maestro/Commons/WindowsIdentityMembers.cs b/client/Maestro/Commons/WindowsIdentityMembers.cs new file mode 100644 index 00000000..097c6f00 --- /dev/null +++ b/client/Maestro/Commons/WindowsIdentityMembers.cs @@ -0,0 +1,249 @@ +using Microsoft.Win32.SafeHandles; +using System; +using System.Diagnostics; +using System.DirectoryServices.AccountManagement; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security; +using System.Security.Permissions; +using System.Security.Principal; + +namespace Maestro.Commons { + + class WindowsIdentityManager { + + [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, + int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] + public extern static bool CloseHandle(IntPtr handle); + + public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid { + private SafeTokenHandle() + : base(true) { + } + + [DllImport("kernel32.dll")] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool CloseHandle(IntPtr handle); + + protected override bool ReleaseHandle() { + return CloseHandle(handle); + } + } + + [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")] + public static void DoLogin(string domainName, string userName, string password) { + SafeTokenHandle safeTokenHandle; + const int LOGON32_PROVIDER_DEFAULT = 0; + const int LOGON32_PROVIDER_WINNT35 = 1; + const int LOGON32_PROVIDER_WINNT40 = 2; + const int LOGON32_PROVIDER_WINNT50 = 3; + const int LOGON32_LOGON_INTERACTIVE = 2; + const int LOGON32_LOGON_NETWORK = 3; + const int LOGON_TYPE_NEW_CREDENTIALS = 9; + + // Call LogonUser to obtain a handle to an access token. + bool returnValue = LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle); + + if (!returnValue) { + int ret = Marshal.GetLastWin32Error(); + Debug.WriteLine("LogonUser failed with error code : {0}", ret); + throw new Exception("Windows bejelentkezési hiba. Kód: " + ret); + } + + using (safeTokenHandle) { + Debug.WriteLine("Before impersonation: " + WindowsIdentity.GetCurrent().Name); + // Use the token handle returned by LogonUser. + using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle())) { + using (WindowsImpersonationContext impersonatedUser = newId.Impersonate()) { + + // Check the identity. + Debug.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name); + } + } + // Releasing the context object stops the impersonation + // Check the identity. + Debug.WriteLine("After closing the context: " + WindowsIdentity.GetCurrent().Name); + } + + } + + static void Test(string[] args) { + // Retrieve the Windows account token for the current user. + IntPtr logonToken = LogonUser(); + + // Constructor implementations. + IntPtrConstructor(logonToken); + IntPtrStringConstructor(logonToken); + IntPtrStringTypeConstructor(logonToken); + IntPrtStringTypeBoolConstructor(logonToken); + + // Property implementations. + UseProperties(logonToken); + + // Method implementations. + GetAnonymousUser(); + ImpersonateIdentity(logonToken); + + Debug.WriteLine("This sample completed successfully; " + + "press Enter to exit."); + Console.ReadLine(); + } + + // Create a WindowsIdentity object for the user represented by the + // specified Windows account token. + private static void IntPtrConstructor(IntPtr logonToken) { + // Construct a WindowsIdentity object using the input account token. + WindowsIdentity windowsIdentity = new WindowsIdentity(logonToken); + + Debug.WriteLine("Created a Windows identity object named " + + windowsIdentity.Name + "."); + } + + + // Create a WindowsIdentity object for the user represented by the + // specified account token and authentication type. + private static void IntPtrStringConstructor(IntPtr logonToken) { + // Construct a WindowsIdentity object using the input account token + // and the specified authentication type. + string authenticationType = "WindowsAuthentication"; + WindowsIdentity windowsIdentity = + new WindowsIdentity(logonToken, authenticationType); + + Debug.WriteLine("Created a Windows identity object named " + + windowsIdentity.Name + "."); + } + + // Create a WindowsIdentity object for the user represented by the + // specified account token, authentication type, and Windows account + // type. + private static void IntPtrStringTypeConstructor(IntPtr logonToken) { + // Construct a WindowsIdentity object using the input account token, + // and the specified authentication type, and Windows account type. + string authenticationType = "WindowsAuthentication"; + WindowsAccountType guestAccount = WindowsAccountType.Guest; + WindowsIdentity windowsIdentity = + new WindowsIdentity(logonToken, authenticationType, guestAccount); + + Debug.WriteLine("Created a Windows identity object named " + + windowsIdentity.Name + "."); + } + + // Create a WindowsIdentity object for the user represented by the + // specified account token, authentication type, Windows account type, and + // Boolean authentication flag. + private static void IntPrtStringTypeBoolConstructor(IntPtr logonToken) { + // Construct a WindowsIdentity object using the input account token, + // and the specified authentication type, Windows account type, and + // authentication flag. + string authenticationType = "WindowsAuthentication"; + WindowsAccountType guestAccount = WindowsAccountType.Guest; + bool isAuthenticated = true; + WindowsIdentity windowsIdentity = new WindowsIdentity( + logonToken, authenticationType, guestAccount, isAuthenticated); + + Debug.WriteLine("Created a Windows identity object named " + + windowsIdentity.Name + "."); + } + // Access the properties of a WindowsIdentity object. + private static void UseProperties(IntPtr logonToken) { + WindowsIdentity windowsIdentity = new WindowsIdentity(logonToken); + string propertyDescription = "The Windows identity named "; + + // Retrieve the Windows logon name from the Windows identity object. + propertyDescription += windowsIdentity.Name; + + // Verify that the user account is not considered to be an Anonymous + // account by the system. + if (!windowsIdentity.IsAnonymous) { + propertyDescription += " is not an Anonymous account"; + } + + // Verify that the user account has been authenticated by Windows. + if (windowsIdentity.IsAuthenticated) { + propertyDescription += ", is authenticated"; + } + + // Verify that the user account is considered to be a System account + // by the system. + if (windowsIdentity.IsSystem) { + propertyDescription += ", is a System account"; + } + // Verify that the user account is considered to be a Guest account + // by the system. + if (windowsIdentity.IsGuest) { + propertyDescription += ", is a Guest account"; + } + + // Retrieve the authentication type for the + String authenticationType = windowsIdentity.AuthenticationType; + + // Append the authenication type to the output message. + if (authenticationType != null) { + propertyDescription += (" and uses " + authenticationType); + propertyDescription += (" authentication type."); + } + + Debug.WriteLine(propertyDescription); + + // Display the SID for the owner. + Console.Write("The SID for the owner is : "); + SecurityIdentifier si = windowsIdentity.Owner; + Debug.WriteLine(si.ToString()); + // Display the SIDs for the groups the current user belongs to. + Debug.WriteLine("Display the SIDs for the groups the current user belongs to."); + IdentityReferenceCollection irc = windowsIdentity.Groups; + foreach (IdentityReference ir in irc) + Debug.WriteLine(ir.Value); + TokenImpersonationLevel token = windowsIdentity.ImpersonationLevel; + Debug.WriteLine("The impersonation level for the current user is : " + token.ToString()); + } + + // Retrieve the account token from the current WindowsIdentity object + // instead of calling the unmanaged LogonUser method in the advapi32.dll. + public static IntPtr LogonUser() { + IntPtr accountToken = WindowsIdentity.GetCurrent().Token; + Debug.WriteLine("Token number is: " + accountToken.ToString()); + return accountToken; + } + + // Get the WindowsIdentity object for an Anonymous user. + private static void GetAnonymousUser() { + // Retrieve a WindowsIdentity object that represents an anonymous + // Windows user. + WindowsIdentity windowsIdentity = WindowsIdentity.GetAnonymous(); + } + + // Impersonate a Windows identity. + public static WindowsImpersonationContext ImpersonateIdentity() { + IntPtr logonToken = LogonUser(); + return ImpersonateIdentity(logonToken); + } + + private static WindowsImpersonationContext ImpersonateIdentity(IntPtr logonToken) { + // Retrieve the Windows identity using the specified token. + WindowsIdentity windowsIdentity = new WindowsIdentity(logonToken); + + // Create a WindowsImpersonationContext object by impersonating the + // Windows identity. + WindowsImpersonationContext impersonationContext = + windowsIdentity.Impersonate(); + + Debug.WriteLine("Name of the identity after impersonation: " + WindowsIdentity.GetCurrent().Name + "."); + Debug.WriteLine(windowsIdentity.ImpersonationLevel); + // Stop impersonating the user. + //impersonationContext.Undo(); + + // Check the identity name. + //Console.Write("Name of the identity after performing an Undo on the"); + //Debug.WriteLine(" impersonation: " + + // WindowsIdentity.GetCurrent().Name); + + return impersonationContext; + } + } +} diff --git a/client/Maestro/Configuration/ConfigurationInfo.cs b/client/Maestro/Configuration/ConfigurationInfo.cs index 53dc80c4..876ffa75 100644 --- a/client/Maestro/Configuration/ConfigurationInfo.cs +++ b/client/Maestro/Configuration/ConfigurationInfo.cs @@ -23,7 +23,7 @@ namespace Maestro.Configuration { } public class GlobalInfo { - public string UserDomain { get; set; } + public Connection UserDomain { get; set; } } public class ConfigurationInfo { @@ -61,7 +61,7 @@ namespace Maestro.Configuration { public int KillDateDays { get; set; } public Connection Remote { get; set; } public bool SaveSegments { get; set; } - public bool CreateSubFolder { get; set; } + public string SubFolderFormat { get; set; } public string Tag { get; set; } public bool SaveArchiveMetadata { get; set; } public bool SaveMorpheusMetadata { get; set; } diff --git a/client/Maestro/Configuration/configuration-editor.json b/client/Maestro/Configuration/configuration-editor.json index 72689711..5324669d 100644 --- a/client/Maestro/Configuration/configuration-editor.json +++ b/client/Maestro/Configuration/configuration-editor.json @@ -46,7 +46,7 @@ "processor": "FTPTargetProcessor", "outputFormat": "%ID%-%SOURCENAME%", "tag": "Betöltés", - "createSubFolder": true, + "subFolderFormat": "%IDROOT%", "killDateDays": 7, "saveArchiveMetadata": false, "remote": { @@ -61,7 +61,7 @@ "processor": "FTPTargetProcessor", "outputFormat": "%ID%-%SOURCENAME%", "tag": "Betöltés", - "createSubFolder": true, + "subFolderFormat": "%IDROOT%", "killDateDays": 7, "saveArchiveMetadata": false, "remote": { diff --git a/client/Maestro/Configuration/configuration-nle.json b/client/Maestro/Configuration/configuration-nle.json index 62fd3d09..3ec60cf9 100644 --- a/client/Maestro/Configuration/configuration-nle.json +++ b/client/Maestro/Configuration/configuration-nle.json @@ -46,7 +46,7 @@ "processor": "FTPTargetProcessor", "outputFormat": "%ID%-%SOURCENAME%", "tag": "Betöltés", - "createSubFolder": true, + "subFolderFormat": "%IDROOT%", "killDateDays": 7, "saveArchiveMetadata": false, "remote": { @@ -61,7 +61,7 @@ "processor": "FTPTargetProcessor", "outputFormat": "%ID%-%SOURCENAME%", "tag": "Betöltés", - "createSubFolder": true, + "subFolderFormat": "%IDROOT%", "killDateDays": 7, "saveArchiveMetadata": false, "remote": { diff --git a/client/Maestro/Configuration/configuration-playout.json b/client/Maestro/Configuration/configuration-playout.json index 38a7a689..6834ae47 100644 --- a/client/Maestro/Configuration/configuration-playout.json +++ b/client/Maestro/Configuration/configuration-playout.json @@ -68,7 +68,7 @@ "processor": "FXPTargetProcessor", "outputFormat": "%ID%", "tag": "Újravágás", - "createSubFolder": true, + "subFolderFormat": "%IDROOT%", "remote": { "address": "ftp://10.10.1.100/PLAYOUT_NLE", "userName": "mediacube", diff --git a/client/Maestro/Configuration/configuration-sxs.json b/client/Maestro/Configuration/configuration-sxs.json index a3a97954..ef4dea4f 100644 --- a/client/Maestro/Configuration/configuration-sxs.json +++ b/client/Maestro/Configuration/configuration-sxs.json @@ -1,6 +1,6 @@ { "title": "SxS", - "active": false, + "active": true, "startInTray": false, "enableCustomMetadataId": true, "player": { @@ -12,7 +12,7 @@ "$type": "UNCSource", "filter": "avi,wav,mxf", "local": { - "address": "file://e:/XDROOT/Clip" + "address": "file://c:/x" } }, "metadatas": [ @@ -43,14 +43,14 @@ "targets": [ { "label": "Hír nyersanyag betöltés", - "processor": "UNCTargetProcessor", + "processor": "FTPTargetProcessor", "outputFormat": "%ID%-%SOURCENAME%", "tag": "Betöltés", - "createSubFolder": true, + "subFolderFormat": "%IDROOT%%TEXT%", "killDateDays": 7, "saveArchiveMetadata": false, "remote": { - "address": "file://10.10.1.100/BRAAVOS/OCTOPUS", + "address": "ftp://10.10.1.100/OCTOPUS", "userName": "mediacube", "password": "Dn8t4gfHcK98o8hyPgLDhr5SgSji4JCxsfpMJsODikUp3nXgrM0UNCi45lLAK8ZOnmEneO44P9qpJ4QDqhctN6MxZodjJgdZTyoZKmSa+ECzEzLr/wPYNgxVaXrVotEy", "timeout": 1000 @@ -58,14 +58,14 @@ }, { "label": "Magazin nyersanyag betöltés", - "processor": "UNCTargetProcessor", + "processor": "FTPTargetProcessor", "outputFormat": "%ID%-%SOURCENAME%", "tag": "Betöltés", - "createSubFolder": true, + "subFolderFormat": "%IDROOT%", "killDateDays": 7, "saveArchiveMetadata": false, "remote": { - "address": "file://10.10.1.100/BRAAVOS/PLAYOUT_NLE", + "address": "ftp://10.10.1.100/PLAYOUT_NLE", "userName": "mediacube", "password": "Dn8t4gfHcK98o8hyPgLDhr5SgSji4JCxsfpMJsODikUp3nXgrM0UNCi45lLAK8ZOnmEneO44P9qpJ4QDqhctN6MxZodjJgdZTyoZKmSa+ECzEzLr/wPYNgxVaXrVotEy", "timeout": 1000 @@ -73,12 +73,12 @@ }, { "label": "Lebonyba küldés", - "processor": "UNCTargetProcessor", + "processor": "FTPTargetProcessor", "outputFormat": "%ID%", "tag": "Lebony", "killDateDays": 7, "remote": { - "address": "file://10.10.1.100/BRAAVOS/PLAYOUT_CHECK", + "address": "ftp://10.10.1.100/PLAYOUT_CHECK", "userName": "mediacube", "password": "Dn8t4gfHcK98o8hyPgLDhr5SgSji4JCxsfpMJsODikUp3nXgrM0UNCi45lLAK8ZOnmEneO44P9qpJ4QDqhctN6MxZodjJgdZTyoZKmSa+ECzEzLr/wPYNgxVaXrVotEy", "timeout": 1000 @@ -86,12 +86,12 @@ }, { "label": "Archiválás", - "processor": "UNCTargetProcessor", + "processor": "FTPTargetProcessor", "outputFormat": "%ID%", "tag": "Archiválás", "saveArchiveMetadata": true, "remote": { - "address": "file://10.10.1.100/BRAAVOS/ARCHIVE", + "address": "ftp://10.10.1.100/ARCHIVE", "userName": "mediacube", "password": "Dn8t4gfHcK98o8hyPgLDhr5SgSji4JCxsfpMJsODikUp3nXgrM0UNCi45lLAK8ZOnmEneO44P9qpJ4QDqhctN6MxZodjJgdZTyoZKmSa+ECzEzLr/wPYNgxVaXrVotEy", "timeout": 1000 diff --git a/client/Maestro/Configuration/global.json b/client/Maestro/Configuration/global.json index aa5d8afc..6c7a8f4d 100644 --- a/client/Maestro/Configuration/global.json +++ b/client/Maestro/Configuration/global.json @@ -1,3 +1,7 @@ { - "userDomain": "intra.echotv.hu" + "userDomain": { + "address": "intra.echotv.hu", + "userName": "echotest", + "password": "F3QcfkSEW7hq+FcEraq9xv4UdHHeVoOh7jBH1G1k9SzEayTXyiT4WQ7XKtBO/ygnCpRU97AXoKXKoqXIGP8QlVkFurRqwzo8mywEb1q2VW7dUjkJcLFtLDkqQjM39+N9" + } } diff --git a/client/Maestro/LoginForm.Designer.cs b/client/Maestro/LoginForm.Designer.cs new file mode 100644 index 00000000..a94a714d --- /dev/null +++ b/client/Maestro/LoginForm.Designer.cs @@ -0,0 +1,223 @@ +namespace Maestro { + partial class LoginForm { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() { + this.components = new System.ComponentModel.Container(); + this.pButtons = new System.Windows.Forms.FlowLayoutPanel(); + this.btnOk = new System.Windows.Forms.Button(); + this.btnCancel = new System.Windows.Forms.Button(); + this.pLayout = new System.Windows.Forms.FlowLayoutPanel(); + this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.label1 = new System.Windows.Forms.Label(); + this.loginFormBindingSource = new System.Windows.Forms.BindingSource(this.components); + this.label2 = new System.Windows.Forms.Label(); + this.txtUserName = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.txtPassword = new System.Windows.Forms.TextBox(); + this.pButtons.SuspendLayout(); + this.pLayout.SuspendLayout(); + this.flowLayoutPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.loginFormBindingSource)).BeginInit(); + this.SuspendLayout(); + // + // pButtons + // + this.pButtons.Controls.Add(this.btnOk); + this.pButtons.Controls.Add(this.btnCancel); + this.pButtons.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; + this.pButtons.Location = new System.Drawing.Point(4, 142); + this.pButtons.Margin = new System.Windows.Forms.Padding(4); + this.pButtons.Name = "pButtons"; + this.pButtons.Size = new System.Drawing.Size(413, 34); + this.pButtons.TabIndex = 7; + // + // btnOk + // + this.btnOk.AutoSize = true; + this.btnOk.Dock = System.Windows.Forms.DockStyle.Left; + this.btnOk.Location = new System.Drawing.Point(299, 4); + this.btnOk.Margin = new System.Windows.Forms.Padding(4); + this.btnOk.Name = "btnOk"; + this.btnOk.Size = new System.Drawing.Size(110, 27); + this.btnOk.TabIndex = 1; + this.btnOk.Text = "Bejelentkezés"; + this.btnOk.UseVisualStyleBackColor = true; + this.btnOk.Click += new System.EventHandler(this.btnOk_Click); + // + // btnCancel + // + this.btnCancel.AutoSize = true; + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Dock = System.Windows.Forms.DockStyle.Right; + this.btnCancel.Location = new System.Drawing.Point(191, 4); + this.btnCancel.Margin = new System.Windows.Forms.Padding(4); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(100, 27); + this.btnCancel.TabIndex = 3; + this.btnCancel.Text = "Mégsem"; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // + // pLayout + // + this.pLayout.Controls.Add(this.flowLayoutPanel1); + this.pLayout.Controls.Add(this.label2); + this.pLayout.Controls.Add(this.txtUserName); + this.pLayout.Controls.Add(this.label3); + this.pLayout.Controls.Add(this.txtPassword); + this.pLayout.Controls.Add(this.pButtons); + this.pLayout.Dock = System.Windows.Forms.DockStyle.Fill; + this.pLayout.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; + this.pLayout.Location = new System.Drawing.Point(0, 0); + this.pLayout.Margin = new System.Windows.Forms.Padding(4); + this.pLayout.Name = "pLayout"; + this.pLayout.Size = new System.Drawing.Size(421, 182); + this.pLayout.TabIndex = 8; + this.pLayout.WrapContents = false; + // + // flowLayoutPanel1 + // + this.flowLayoutPanel1.Controls.Add(this.pictureBox1); + this.flowLayoutPanel1.Controls.Add(this.label1); + this.flowLayoutPanel1.Location = new System.Drawing.Point(4, 4); + this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(4); + this.flowLayoutPanel1.Name = "flowLayoutPanel1"; + this.flowLayoutPanel1.Size = new System.Drawing.Size(413, 34); + this.flowLayoutPanel1.TabIndex = 8; + // + // pictureBox1 + // + this.pictureBox1.Image = global::Maestro.Properties.Resources.mediacube_logo_v2_half_hard_edge; + this.pictureBox1.Location = new System.Drawing.Point(3, 3); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(27, 27); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.pictureBox1.TabIndex = 9; + this.pictureBox1.TabStop = false; + // + // label1 + // + this.label1.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.loginFormBindingSource, "DomainName", true)); + this.label1.Location = new System.Drawing.Point(37, 0); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(57, 30); + this.label1.TabIndex = 0; + this.label1.Text = "Domain"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // loginFormBindingSource + // + this.loginFormBindingSource.DataSource = this; + this.loginFormBindingSource.Position = 0; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(4, 42); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(84, 17); + this.label2.TabIndex = 2; + this.label2.Text = "Felhasználó"; + // + // txtUserName + // + this.txtUserName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtUserName.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.loginFormBindingSource, "UserName", true)); + this.txtUserName.Location = new System.Drawing.Point(4, 63); + this.txtUserName.Margin = new System.Windows.Forms.Padding(4); + this.txtUserName.Name = "txtUserName"; + this.txtUserName.Size = new System.Drawing.Size(413, 23); + this.txtUserName.TabIndex = 3; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(4, 90); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(48, 17); + this.label3.TabIndex = 4; + this.label3.Text = "Jelszó"; + // + // txtPassword + // + this.txtPassword.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtPassword.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.loginFormBindingSource, "Password", true)); + this.txtPassword.Location = new System.Drawing.Point(4, 111); + this.txtPassword.Margin = new System.Windows.Forms.Padding(4); + this.txtPassword.Name = "txtPassword"; + this.txtPassword.Size = new System.Drawing.Size(413, 23); + this.txtPassword.TabIndex = 5; + this.txtPassword.UseSystemPasswordChar = true; + // + // LoginForm + // + this.AcceptButton = this.btnOk; + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.btnCancel; + this.ClientSize = new System.Drawing.Size(421, 182); + this.ControlBox = false; + this.Controls.Add(this.pLayout); + this.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Margin = new System.Windows.Forms.Padding(4); + this.Name = "LoginForm"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Maestro bejelentkezés"; + this.TopMost = true; + this.pButtons.ResumeLayout(false); + this.pButtons.PerformLayout(); + this.pLayout.ResumeLayout(false); + this.pLayout.PerformLayout(); + this.flowLayoutPanel1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.loginFormBindingSource)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.FlowLayoutPanel pButtons; + private System.Windows.Forms.Button btnOk; + private System.Windows.Forms.Button btnCancel; + private System.Windows.Forms.FlowLayoutPanel pLayout; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox txtUserName; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox txtPassword; + private System.Windows.Forms.BindingSource loginFormBindingSource; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; + private System.Windows.Forms.PictureBox pictureBox1; + } +} \ No newline at end of file diff --git a/client/Maestro/LoginForm.cs b/client/Maestro/LoginForm.cs new file mode 100644 index 00000000..3591f0af --- /dev/null +++ b/client/Maestro/LoginForm.cs @@ -0,0 +1,24 @@ +using System; +using System.Windows.Forms; + +namespace Maestro { + public partial class LoginForm : Form { + public string DomainName { get; set; } + public string UserName { get; set; } + public string Password { get; set; } + + public LoginForm() { + InitializeComponent(); + } + + private void btnOk_Click(object sender, EventArgs e) { + DialogResult = DialogResult.OK; + Close(); + } + + private void btnCancel_Click(object sender, EventArgs e) { + DialogResult = DialogResult.Cancel; + Close(); + } + } +} diff --git a/client/Maestro/LoginForm.resx b/client/Maestro/LoginForm.resx new file mode 100644 index 00000000..e1a37309 --- /dev/null +++ b/client/Maestro/LoginForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 17, 17 + + + 17, 17 + + \ No newline at end of file diff --git a/client/Maestro/Maestro.csproj b/client/Maestro/Maestro.csproj index eeccd38a..18a7638b 100644 --- a/client/Maestro/Maestro.csproj +++ b/client/Maestro/Maestro.csproj @@ -169,9 +169,16 @@ + + + Form + + + LoginForm.cs + Form @@ -224,6 +231,9 @@ ArchiveMetadataForm.cs + + LoginForm.cs + MaestroForm.cs Designer @@ -275,6 +285,7 @@ + @@ -341,6 +352,7 @@ + diff --git a/client/Maestro/MaestroForm.Metadata.cs b/client/Maestro/MaestroForm.Metadata.cs index 5a320c8b..0b81ad46 100644 --- a/client/Maestro/MaestroForm.Metadata.cs +++ b/client/Maestro/MaestroForm.Metadata.cs @@ -95,7 +95,10 @@ namespace Maestro { private void OnArchiveMetadataClick(object sender, EventArgs e) { if (archiveMetadata == null) archiveMetadata = GetArchiveMetadata(); - if (archiveMetadata == null || !archiveMetadata.IsFilled) { + + //if (archiveMetadata == null || !archiveMetadata.IsFilled) { + //MC metaadta esetén nincs cím + if (archiveMetadata == null) { MessageBox.Show("Nem található archív metaadat!"); return; } @@ -352,7 +355,7 @@ namespace Maestro { }; } - private void OnTrafficIDSelected(string id, int variantID) { + private void OnTrafficIDSelected(string id, int variantID, string text) { octopusIDSelector.ClearSelection(); archiveMetadata = null; if (id == null) { @@ -363,6 +366,7 @@ namespace Maestro { SelectedMetadata = new MetadataInfo() { Kind = metadataType, ID = id, + MetadataText = text, VariantID = variantID }; } diff --git a/client/Maestro/MaestroForm.Source.cs b/client/Maestro/MaestroForm.Source.cs index 553fa0b6..b631363b 100644 --- a/client/Maestro/MaestroForm.Source.cs +++ b/client/Maestro/MaestroForm.Source.cs @@ -224,32 +224,6 @@ namespace Maestro { //Cursor.Current = Cursors.Default; } - private void LookupTraffic(MetadataType metadataType) { - TrafficAPI api = trafficIDSelector.trafficAPI; - List result = null; - switch (metadataType) { - case MetadataType.TrafficMaterial: - result = api.GetMaterials(SelectedSource?.Prefix, false); - break; - case MetadataType.TrafficPromo: - result = api.GetPromos(SelectedSource?.Prefix, false); - break; - case MetadataType.TrafficAD: - result = api.GetADs(SelectedSource?.Prefix, false); - break; - } - if (result == null || result.Count == 0) { - MessageBox.Show(this, StringResources.NINCS_TALALAT); - return; - } - if (result.Count == 1) - OnTrafficIDSelected(result[0].MediaID, result[0].VariantID); - else { - TrafficLookupResultSelector lookupResult = new TrafficLookupResultSelector(result, OnTrafficIDSelected); - lookupResult.ShowDialog(); - } - } - private void picClearFilter_Click(object sender, EventArgs e) { txtSourceFilter.Text = null; bindingSource.Filter = null; diff --git a/client/Maestro/Program.cs b/client/Maestro/Program.cs index e4d849e2..5746cdb2 100644 --- a/client/Maestro/Program.cs +++ b/client/Maestro/Program.cs @@ -1,29 +1,24 @@ -using Commons; -using LinkDotNet.MessageHandling; +using LinkDotNet.MessageHandling; using LinkDotNet.MessageHandling.Contracts; +using Maestro.Commons; using Maestro.Configuration; using Maestro.Properties; using NLog; -using NLog.Targets; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.DirectoryServices.AccountManagement; -using System.Drawing; -using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Security.AccessControl; using System.Security.Principal; -using System.Text; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; -using System.Xml; -using System.Xml.Linq; namespace Maestro { @@ -74,9 +69,6 @@ namespace Maestro { } } } - //Application.EnableVisualStyles(); - //Application.SetCompatibleTextRenderingDefault(false); - //Application.Run(new TrayApplicationContext()); } } @@ -87,36 +79,50 @@ namespace Maestro { private const string CONFIG_ERROR = "Nem található aktív konfiguráció."; private const string SYSCONFIG_ERROR = "Nem található a 'global.json' rendszer konfiguráció."; private const string CONFIGURATION_FOLDER = "./Configuration"; + private const string DOMAIN_QUERY_ERROR = "A bejelentkezett felhasználó domain információja nem elérhető."; + private const string NOSPLASH = "nosplash"; + private const string NOLOGIN = "nologin"; private static Logger logger = LogManager.GetCurrentClassLogger(); private NotifyIcon trayIcon; private ConcurrentBag forms = new ConcurrentBag(); private IMessageBus messageBus = new MessageBus(); public TrayApplicationContext() { + string str = Regex.Replace("Aéá.ú-óüöA", "[^0-9A-Za-z-._]", "_"); + Debug.WriteLine(str); } - public void Start() { + private bool HasCommandlineParameter(string parameter) { String[] arguments = Environment.GetCommandLineArgs(); - if (!arguments.ToList().Contains("nosplash")) { + return arguments.ToList().Contains(parameter); + } + + public void Start() { + if (!HasCommandlineParameter(NOSPLASH)) { Splash splash = new Splash(); Task.Run(() => { Application.Run(splash); }); } - CreateForms(); + string[] configFiles = Directory.GetFiles(CONFIGURATION_FOLDER, JSON_WILDCARD); + if (configFiles.Length == 0) + throw new Exception(CONFIG_ERROR); + + CheckGlobalConfig(configFiles); + if (!HasCommandlineParameter(NOLOGIN)) + CheckUser(); + CreateForms(configFiles); CreateTrayIcon(); } - private void CreateForms() { - string[] files = Directory.GetFiles(CONFIGURATION_FOLDER, JSON_WILDCARD); - if (files.Length == 0) - throw new Exception(CONFIG_ERROR); - - CheckGlobalConfig(files); - foreach (String file in files) { + private void CreateForms(string[] configFiles) { + foreach (String file in configFiles) { string audioRecorderFile = Path.Combine(CONFIGURATION_FOLDER, AUDIORECORDER_JSON); if (file.Equals(audioRecorderFile)) continue; + string globalFile = Path.Combine(CONFIGURATION_FOLDER, GLOBAL_JSON); + if (file.Equals(globalFile)) + continue; CreateForm(file); } if (forms.Count == 0) @@ -125,18 +131,60 @@ namespace Maestro { private void CheckGlobalConfig(string[] files) { string globalFile = Path.Combine(CONFIGURATION_FOLDER, GLOBAL_JSON); - if (files.Contains(globalFile)) { - GlobalInfo global = Loader.Get(globalFile); - if (String.IsNullOrEmpty(global.UserDomain)) - throw new Exception(SYSCONFIG_ERROR); - else { - //using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, global.UserDomain)) { - // bool isValid = pc.ValidateCredentials("echotest", "aA123456+"); - // Debug.WriteLine("User valid: " + isValid); - //} - } - } else + if (!files.Contains(globalFile)) + throw new Exception(SYSCONFIG_ERROR); + } + + private bool IsDomainUser(string userName, string domainName) { + string[] domain = userName.Split('\\'); + if (domain.Length < 2) + throw new Exception(DOMAIN_QUERY_ERROR); + string userDomainName = domain[0]; + if (userDomainName.Contains(".")) + userDomainName = userDomainName.Split('.')[0]; + if (domainName.ToLower().Equals(userDomainName.ToLower())) + return true; + return false; + } + + private void CheckUser() { + string globalFile = Path.Combine(CONFIGURATION_FOLDER, GLOBAL_JSON); + GlobalInfo global = Loader.Get(globalFile); + string domainName = global.UserDomain.Address.ToString(); + if (String.IsNullOrEmpty(domainName)) throw new Exception(SYSCONFIG_ERROR); + else { + string userName = WindowsIdentity.GetCurrent().Name; + if (IsDomainUser(userName, domainName)) + return; + userName = global.UserDomain.UserName; + string password = global.UserDomain.Password; + LoginForm loginForm = null; + try { + using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domainName)) { + while (true) { + bool isValid = pc.ValidateCredentials(userName, password); + if (isValid) + break; + + if (loginForm == null) + loginForm = new LoginForm(); + else + MessageBox.Show("Hibás a felhasználói név, vagy hibás a jelszó."); + + DialogResult result = loginForm.ShowDialog(); + if (result == DialogResult.Cancel) + throw new Exception("Bejelentkezés nélkül a Maestro alkalmazás nem indítható el."); + userName = loginForm.UserName; + password = loginForm.Password; + } + } + } + catch (Exception e) { + throw new Exception("Hiba a hitelesítő adatok lekérdezésekor. A rendszer üzenete: " + e.Message); + } + + } } private void CreateForm(string file) { @@ -247,6 +295,7 @@ namespace Maestro { trayIcon.Visible = false; trayIcon.Dispose(); } + } } } diff --git a/client/Maestro/Properties/DataSources/LoginForm.datasource b/client/Maestro/Properties/DataSources/LoginForm.datasource new file mode 100644 index 00000000..583e8b6f --- /dev/null +++ b/client/Maestro/Properties/DataSources/LoginForm.datasource @@ -0,0 +1,10 @@ + + + + Maestro.LoginForm, Maestro, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null + \ No newline at end of file diff --git a/client/Maestro/Properties/Resources.Designer.cs b/client/Maestro/Properties/Resources.Designer.cs index 641caf4d..18be0c5e 100644 --- a/client/Maestro/Properties/Resources.Designer.cs +++ b/client/Maestro/Properties/Resources.Designer.cs @@ -100,6 +100,16 @@ namespace Maestro.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap mediacube_logo_v2_half_hard_edge { + get { + object obj = ResourceManager.GetObject("mediacube_logo_v2_half_hard_edge", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). /// diff --git a/client/Maestro/Properties/Resources.resx b/client/Maestro/Properties/Resources.resx index 3008b809..e2629027 100644 --- a/client/Maestro/Properties/Resources.resx +++ b/client/Maestro/Properties/Resources.resx @@ -139,4 +139,7 @@ ..\Resources\ic_playlist_add_check_black_24dp_1x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\mediacube_logo_v2_half_hard_edge.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/client/Maestro/Resources/installforge-installer-project.ifp b/client/Maestro/Resources/installforge-installer-project.ifp index 899a0df4..24818498 100644 Binary files a/client/Maestro/Resources/installforge-installer-project.ifp and b/client/Maestro/Resources/installforge-installer-project.ifp differ diff --git a/client/Maestro/Resources/mediacube_logo_v2_half_hard_edge.png b/client/Maestro/Resources/mediacube_logo_v2_half_hard_edge.png new file mode 100644 index 00000000..5135f8db Binary files /dev/null and b/client/Maestro/Resources/mediacube_logo_v2_half_hard_edge.png differ diff --git a/client/Maestro/Splash.Designer.cs b/client/Maestro/Splash.Designer.cs index 7a16fb25..f4ab6bc6 100644 --- a/client/Maestro/Splash.Designer.cs +++ b/client/Maestro/Splash.Designer.cs @@ -26,9 +26,10 @@ this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Splash)); this.splashTimer = new System.Windows.Forms.Timer(this.components); - this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.picWorld = new System.Windows.Forms.PictureBox(); this.labelVersion = new System.Windows.Forms.Label(); - ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.label1 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.picWorld)).BeginInit(); this.SuspendLayout(); // // splashTimer @@ -37,38 +38,51 @@ this.splashTimer.Interval = 2000; this.splashTimer.Tick += new System.EventHandler(this.splashTimer_Tick); // - // pictureBox1 + // picWorld // - this.pictureBox1.BackColor = System.Drawing.Color.Transparent; - this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image"))); - this.pictureBox1.Location = new System.Drawing.Point(16, 0); - this.pictureBox1.Name = "pictureBox1"; - this.pictureBox1.Size = new System.Drawing.Size(320, 349); - this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; - this.pictureBox1.TabIndex = 0; - this.pictureBox1.TabStop = false; + this.picWorld.BackColor = System.Drawing.Color.Transparent; + this.picWorld.Image = ((System.Drawing.Image)(resources.GetObject("picWorld.Image"))); + this.picWorld.Location = new System.Drawing.Point(16, 0); + this.picWorld.Name = "picWorld"; + this.picWorld.Size = new System.Drawing.Size(320, 349); + this.picWorld.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.picWorld.TabIndex = 0; + this.picWorld.TabStop = false; // // labelVersion // this.labelVersion.BackColor = System.Drawing.Color.Transparent; - this.labelVersion.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238))); - this.labelVersion.ForeColor = System.Drawing.Color.LightGray; - this.labelVersion.Location = new System.Drawing.Point(16, 281); + this.labelVersion.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.labelVersion.ForeColor = System.Drawing.Color.White; + this.labelVersion.Location = new System.Drawing.Point(16, 295); this.labelVersion.Name = "labelVersion"; this.labelVersion.Size = new System.Drawing.Size(317, 23); this.labelVersion.TabIndex = 1; - this.labelVersion.Text = "label1"; + this.labelVersion.Text = "0.0.0"; this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // + // label1 + // + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238))); + this.label1.ForeColor = System.Drawing.Color.White; + this.label1.Location = new System.Drawing.Point(17, 277); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(317, 23); + this.label1.TabIndex = 2; + this.label1.Text = "Maestro"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // // Splash // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage"))); + this.BackgroundImage = global::Maestro.Properties.Resources.mediacube_logo_v2_half_hard_edge; this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; - this.ClientSize = new System.Drawing.Size(348, 361); + this.ClientSize = new System.Drawing.Size(350, 361); + this.Controls.Add(this.label1); this.Controls.Add(this.labelVersion); - this.Controls.Add(this.pictureBox1); + this.Controls.Add(this.picWorld); this.DoubleBuffered = true; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.Name = "Splash"; @@ -76,7 +90,7 @@ this.Text = "Splash"; this.TopMost = true; this.TransparencyKey = System.Drawing.SystemColors.Control; - ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.picWorld)).EndInit(); this.ResumeLayout(false); } @@ -84,7 +98,8 @@ #endregion private System.Windows.Forms.Timer splashTimer; - private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.PictureBox picWorld; private System.Windows.Forms.Label labelVersion; + private System.Windows.Forms.Label label1; } } \ No newline at end of file diff --git a/client/Maestro/Splash.cs b/client/Maestro/Splash.cs index 86f5c444..df785bd1 100644 --- a/client/Maestro/Splash.cs +++ b/client/Maestro/Splash.cs @@ -1,23 +1,12 @@ using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Diagnostics; using System.Drawing; -using System.Linq; using System.Reflection; -using System.Text; -using System.Threading.Tasks; using System.Windows.Forms; namespace Maestro { public partial class Splash : Form { public Splash() { InitializeComponent(); - //Assembly assembly = Assembly.GetExecutingAssembly(); - //FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location); - //labelVersion.Text = fvi.FileVersion; - Version version = Assembly.GetEntryAssembly().GetName().Version; labelVersion.ForeColor = Color.White; labelVersion.Text = String.Format("v{0}.{1}.{2}", version.Major, version.Minor, version.Build); @@ -25,7 +14,6 @@ namespace Maestro { private void splashTimer_Tick(object sender, EventArgs e) { BeginInvoke(new Action(() => Close())); - //Close(); } } diff --git a/client/Maestro/Splash.resx b/client/Maestro/Splash.resx index 302e5997..c4eb1867 100644 --- a/client/Maestro/Splash.resx +++ b/client/Maestro/Splash.resx @@ -121,7 +121,7 @@ 17, 17 - + R0lGODlhWAJ0ATAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQNFAAAACH5BA0UAAAALAAAAABYAnQBgf// //DkQla06QAAAAL+hI+py93hYoSy2oubEIvmD4bieHjkqWwqyjpmC8fA20KrjOcMzfL6z+AofMCicXj8 @@ -9189,1020 +9189,6 @@ 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 \ No newline at end of file diff --git a/client/Maestro/Targets/FTPTargetProcessor.cs b/client/Maestro/Targets/FTPTargetProcessor.cs index b452ddef..5ff420f0 100644 --- a/client/Maestro/Targets/FTPTargetProcessor.cs +++ b/client/Maestro/Targets/FTPTargetProcessor.cs @@ -3,10 +3,9 @@ using Maestro.Configuration; using NLog; using System; using System.IO; +using System.Linq; using System.Net; using System.Windows.Forms; -using Model; -using System.Threading; namespace Maestro.Targets { @@ -124,6 +123,25 @@ namespace Maestro.Targets { return result; } + protected override string DetermineWorkingDirectory(Connection connection) { + string result = null; + if (!String.IsNullOrEmpty(parameters.TargetConfig.SubFolderFormat)) { + string name = GetDynamicName(parameters.TargetConfig.SubFolderFormat); + //TODO ellenőrizni, hogy mi van placeholder esetén + if (parameters.TargetConfig.SubFolderFormat.Contains("%TEXT%")) { + string pattern = name.Split('-')[0] + "-"; + targetFTP.SetWorkingDirectory(connection.Address.LocalPath); + FtpListItem item = targetFTP.GetListing()?.Where(i => i.Type.Equals(FtpFileSystemObjectType.Directory) && i.Name.StartsWith(pattern)).FirstOrDefault(); + if (item != null) + name = item.Name; + targetFTP.SetWorkingDirectory("/"); + } + result = Path.Combine(connection.Address.LocalPath, name); + } else + result = connection.Address.LocalPath; + return result; + } + protected void TerminateClient(FtpClient ftpClient) { if (ftpClient != null) { ftpClient.Disconnect(); diff --git a/client/Maestro/Targets/UNCTargetProcessor.cs b/client/Maestro/Targets/UNCTargetProcessor.cs index 2b48519d..f908c73b 100644 --- a/client/Maestro/Targets/UNCTargetProcessor.cs +++ b/client/Maestro/Targets/UNCTargetProcessor.cs @@ -10,6 +10,7 @@ using Maestro.Commons; using Commons; using Maestro.Metadata; using System.Globalization; +using System.Text.RegularExpressions; namespace Maestro.Targets { @@ -25,6 +26,9 @@ namespace Maestro.Targets { private const string KILLDATE_FILE = "{0}.{1}.killdate"; private const string METADATA_FILE = "{0}.json"; private const string DEFAULT_EXTENSION = ".MXF"; + private const string NORMALIZE_TEXT_PATTERN = "[^0-9A-Za-z-._]"; + private const string NORMALIZE_TEXT_REPLACEMENT = "_"; + protected FileInfo inputFile; protected string workingDir; protected TargetProcessorParameter parameters; @@ -140,7 +144,19 @@ namespace Maestro.Targets { string title = parameters.ArchiveMetadata?.itemTitle; if (!title.Equals(parameters.ArchiveMetadata?.mediaTitle)) title += " - " + parameters.ArchiveMetadata?.mediaTitle; - byte[] content = MorpheusXML.ToXML(title, name, parameters.TargetConfig.DeviceIDMorpheus, parameters.MovieSegments); + string type = null; + switch (parameters.MetadataKind) { + case MetadataType.TrafficMaterial: + type = "PROGRAMME"; + break; + case MetadataType.TrafficPromo: + type = "COMMERCIAL"; + break; + case MetadataType.TrafficAD: + type = "JUNCTION"; + break; + } + byte[] content = MorpheusXML.ToXML(title, name, parameters.TargetConfig.DeviceIDMorpheus, type, parameters.MovieSegments); EnsureDirectoryExistence(parameters.TargetConfig.PathMorpheusMetadata); UploadContent(name + ".xml", content); } @@ -175,13 +191,17 @@ namespace Maestro.Targets { } } - protected String DetermineWorkingDirectory(Connection connection) { + protected virtual string DetermineWorkingDirectory(Connection connection) { string result = null; - if (parameters.TargetConfig.CreateSubFolder) { - string subDir = ID; - if (ID.Contains("_")) - subDir = ID.Split('_')[0]; - result = Path.Combine(connection.Address.LocalPath, ID); + if (!String.IsNullOrEmpty(parameters.TargetConfig.SubFolderFormat)) { + string name = GetDynamicName(parameters.TargetConfig.SubFolderFormat); + if (parameters.TargetConfig.SubFolderFormat.Contains("%TEXT%")) { + string pattern = name.Split('-')[0] + "-*"; + string[] dirs = Directory.GetDirectories(connection.Address.LocalPath, pattern); + if (dirs.Length > 0) + name = dirs[0]; + } + result = Path.Combine(connection.Address.LocalPath, name); } else result = connection.Address.LocalPath; return result; @@ -257,12 +277,36 @@ namespace Maestro.Targets { return "/".Equals(workingDir) ? fileName : Path.Combine(path, fileName); } - protected virtual string CreateOutputFileName() { - string nameWithoutExtension = parameters.TargetConfig.OutputFormat + public static String RemoveDiacritics(String s) { + String normalizedString = s.Normalize(NormalizationForm.FormD); + StringBuilder stringBuilder = new StringBuilder(); + + for (int i = 0; i < normalizedString.Length; i++) { + Char c = normalizedString[i]; + if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) + stringBuilder.Append(c); + } + + return stringBuilder.ToString(); + } + + protected string GetDynamicName(string text) { + string idRoot = ID.Contains(NORMALIZE_TEXT_REPLACEMENT) ? ID.Split(NORMALIZE_TEXT_REPLACEMENT[0])[0] : ID; + string result = text .Replace("%ID%", ID) - .Replace("%TEXT%", parameters.MetadataText) + .Replace("%IDROOT%", idRoot) + .Replace("%TEXT%", "-" + RemoveDiacritics(parameters.MetadataText)) .Replace("%SOURCENAME%", Path.GetFileNameWithoutExtension(InputName)) .Replace("%TIMESTAMP%", DateTime.Now.ToString("yyyyMMddhhmmss", CultureInfo.InvariantCulture)); + // replace hungarian and special characters + result = Regex.Replace(result, NORMALIZE_TEXT_PATTERN, NORMALIZE_TEXT_REPLACEMENT); + if (result.Length > 100) + result = result.Substring(0, 100); + return result; + } + + protected virtual string CreateOutputFileName() { + string nameWithoutExtension = GetDynamicName(parameters.TargetConfig.OutputFormat); string extension = InputName.Contains(".") ? InputName.Substring(InputName.LastIndexOf(".")) : DEFAULT_EXTENSION; extension = extension.ToUpper(); string result = String.Format(FILENAME, nameWithoutExtension, extension); diff --git a/client/OctopusClient/OctopusIDSelector.cs b/client/OctopusClient/OctopusIDSelector.cs index e975ab2e..2a07b2e1 100644 --- a/client/OctopusClient/OctopusIDSelector.cs +++ b/client/OctopusClient/OctopusIDSelector.cs @@ -126,7 +126,8 @@ namespace OctopusClient { label += String.Format($" {story.Name}"); TreeNode storyNode = treeOctopus.Nodes.Add(ID, label); - storyNode.Tag = ID; + storyNode.Tag = story; + if (configuration.DisableStoryCheck) HideCheckBox(treeOctopus, storyNode); else { @@ -177,9 +178,11 @@ namespace OctopusClient { treeOctopus.SelectedNode = selectedNode; } - if (selectedNode.Checked) - IDChangedEvent?.Invoke(selectedNode.Tag as string, selectedNode.Name, selectedNode.Text); - else + if (selectedNode.Checked) { + Story story = selectedNode.Tag as Story; + string text = String.Format($"{story.Name}_{story.Format}"); + IDChangedEvent?.Invoke(story.ParentStoryID, selectedNode.Name, text); + } else IDChangedEvent?.Invoke(null, null, null); } @@ -187,7 +190,6 @@ namespace OctopusClient { return client; } - /// /// Hides the checkbox for the specified node on a TreeView control. /// diff --git a/client/PlanAIRClient/TrafficIDSelector.cs b/client/PlanAIRClient/TrafficIDSelector.cs index 169c0fbc..2b1d005d 100644 --- a/client/PlanAIRClient/TrafficIDSelector.cs +++ b/client/PlanAIRClient/TrafficIDSelector.cs @@ -6,7 +6,7 @@ using LinkDotNet.MessageHandling.Contracts; using System.Drawing; namespace TrafficClient { - public delegate void OnSelectedIDChanged(string ID, int variantID); + public delegate void OnSelectedIDChanged(string ID, int variantID, string text); public partial class TrafficIDSelector : UserControl { public TrafficAPI trafficAPI { get; private set; } @@ -81,14 +81,14 @@ namespace TrafficClient { } private void OnSelectionChanged(DataGridViewRow actualRow) { - TrafficItem res = actualRow.DataBoundItem as TrafficItem; - if (String.IsNullOrEmpty(res.MediaID)) { - TrafficVersion v = trafficAPI.CreateMaterialVersion(res.EpisodeID); + TrafficItem trafficItem = actualRow.DataBoundItem as TrafficItem; + if (String.IsNullOrEmpty(trafficItem.MediaID)) { + TrafficVersion v = trafficAPI.CreateMaterialVersion(trafficItem.EpisodeID); if (v != null) { - res.MediaID = v.MediaID; - res.VariantID = v.VariantID; + trafficItem.MediaID = v.MediaID; + trafficItem.VariantID = v.VariantID; } - if (res.VariantID == 0 || String.IsNullOrEmpty(res.MediaID)) + if (trafficItem.VariantID == 0 || String.IsNullOrEmpty(trafficItem.MediaID)) return; } DataGridViewCheckBoxCell actualCell = actualRow.Cells[0] as DataGridViewCheckBoxCell; @@ -99,10 +99,10 @@ namespace TrafficClient { selectedCell.Value = !(bool)selectedCell.Value; bool selected = (bool)selectedCell.Value; Debug.WriteLine("Selection {0}", selected); - if (selected) { - IDChangedEvent?.Invoke(res.MediaID, res.VariantID); - } else - IDChangedEvent?.Invoke(null, 0); + if (selected) + IDChangedEvent?.Invoke(trafficItem.MediaID, trafficItem.VariantID, trafficItem.Title); + else + IDChangedEvent?.Invoke(null, 0, null); } public void ClearSelection() { @@ -122,6 +122,7 @@ namespace TrafficClient { } private void OnTypeFilterChanged(object sender, EventArgs e) { + dtScheduled.Enabled = rbMaterial.Checked; RefreshResults(); } diff --git a/server/-configuration/dsm.opt b/server/-configuration/dsm.opt index cdd39f70..0a0a0ded 100644 --- a/server/-configuration/dsm.opt +++ b/server/-configuration/dsm.opt @@ -1,3 +1,3 @@ SErvername MEDIACUBE -*traceflags api -*tracefile /opt/mediacube/tsm.trace \ No newline at end of file +traceflags api +tracefile /opt/mediacube/log/tsm.trace \ No newline at end of file diff --git a/server/-product/log4j2.xml b/server/-product/log4j2.xml index 63f6235b..2ea650ba 100644 --- a/server/-product/log4j2.xml +++ b/server/-product/log4j2.xml @@ -19,7 +19,7 @@ - + @@ -32,7 +32,7 @@ - + @@ -41,13 +41,13 @@ - + - + diff --git a/server/-product/mediacube.product b/server/-product/mediacube.product index 5dc889b3..da453c87 100644 --- a/server/-product/mediacube.product +++ b/server/-product/mediacube.product @@ -9,43 +9,45 @@ -consoleLog -console 5555 - -Dfile.encoding=UTF-8 --agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8888 --Djavax.ws.rs.ext.RuntimeDelegate=org.jboss.resteasy.spi.ResteasyProviderFactory - -#System --Djetty.home=/opt/mediacube/configuration/jetty --Dlog4j.configurationFile=/opt/mediacube/configuration/log4j2.xml --Djobengine.jobsteps.root=/opt/mediacube/configuration/executors --Djobengine.jobtemplates.root=/opt/mediacube/configuration/jobtemplates --Djobengine.jobscheduling.config=/opt/mediacube/configuration/scheduledjobs.json - --Dorg.eclipse.equinox.http.jetty.http.port=80 --Dorg.eclipse.epp.logging.aeri.skipReports=true --Declipse.ignoreApp=true --Dosgi.noShutdown=true --Djobengine.loglevel=INFO --Djetty.etc.config.urls=etc/user-jetty.xml,etc/user-jetty-ssl.xml,etc/user-jetty-ssl-context.xml,etc/user-jetty-http.xml,etc/user-jetty-https.xml - - #Database --Djobengine.db.url=jdbc:db2://localhost:50000/mc:retrieveMessagesFromServerOnGetMessage=true; --Djobengine.db.user=db2admin --Djobengine.db.password=password --Djobengine.nosql.db.url=jdbc:db2://localhost:50000/mc:retrieveMessagesFromServerOnGetMessage=true; --Djobengine.nosql.db.user=db2admin --Djobengine.nosql.db.password=password --Djobengine.nosql.db.schema=test - -#Octopus --Djobengine.octopus.api.address=http://10.10.1.11/api/v1 --Djobengine.octopus.api.user=mam --Djobengine.octopus.api.password=napocska + -Xms512m +-Xmx1024m +-Dfile.encoding=UTF-8 +-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8888 +-Djavax.ws.rs.ext.RuntimeDelegate=org.jboss.resteasy.spi.ResteasyProviderFactory -#Selenio --Djobengine.selenio.address=http://10.10.1.71:44000/TranscodeMgrWS?wsdl --Djobengine.selenio.projectfilepath=\\10.10.1.71\Data\Blueprints\MP4_H264_AAC_v4.zenium +#System +-Djetty.home=/opt/mediacube/configuration/jetty +-Dlog4j.configurationFile=/opt/mediacube/configuration/log4j2.xml +-Djobengine.jobsteps.root=/opt/mediacube/configuration/executors +-Djobengine.jobtemplates.root=/opt/mediacube/configuration/jobtemplates +-Djobengine.jobscheduling.config=/opt/mediacube/configuration/scheduledjobs.json -#Nexio +-Dorg.eclipse.equinox.http.jetty.http.port=80 +-Dorg.eclipse.epp.logging.aeri.skipReports=true +-Declipse.ignoreApp=true +-Dosgi.noShutdown=true +-Djobengine.loglevel=INFO +-Djetty.etc.config.urls=etc/user-jetty.xml,etc/user-jetty-ssl.xml,etc/user-jetty-ssl-context.xml,etc/user-jetty-http.xml,etc/user-jetty-https.xml + + #Database +-Djobengine.db.url=jdbc:db2://localhost:50000/mc:retrieveMessagesFromServerOnGetMessage=true; +-Djobengine.db.user=db2admin +-Djobengine.db.password=password +-Djobengine.nosql.db.url=jdbc:db2://localhost:50000/mc:retrieveMessagesFromServerOnGetMessage=true; +-Djobengine.nosql.db.user=db2admin +-Djobengine.nosql.db.password=password +-Djobengine.nosql.db.schema=test + +#Octopus +-Djobengine.octopus.api.address=http://10.10.1.11/api/v1 +-Djobengine.octopus.api.user=mam +-Djobengine.octopus.api.password=napocska + +#Selenio +-Djobengine.selenio.address=http://10.10.1.71:44000/TranscodeMgrWS?wsdl +-Djobengine.selenio.projectfilepath=\\10.10.1.71\Data\Blueprints\MP4_H264_AAC_v4.zenium + +#Nexio -Dnexio.host=10.10.1.55 -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts diff --git a/server/-product/pom.xml b/server/-product/pom.xml index 8e7050e8..f02b54d0 100644 --- a/server/-product/pom.xml +++ b/server/-product/pom.xml @@ -291,8 +291,8 @@ /command "open ${remote.address} -hostkey=""${remote.hostkey}""" - "call pcs resource disable mediacube_script" - "call sleep 5" + + "call rm -rf ${remote.location}" "call mkdir ${remote.location}" "lcd ${local.location}" diff --git a/server/user.jobengine.executors/src/user/jobengine/server/steps/TSMBackupStep.java b/server/user.jobengine.executors/src/user/jobengine/server/steps/TSMBackupStep.java index 1ff54b96..9271e46b 100644 --- a/server/user.jobengine.executors/src/user/jobengine/server/steps/TSMBackupStep.java +++ b/server/user.jobengine.executors/src/user/jobengine/server/steps/TSMBackupStep.java @@ -60,7 +60,7 @@ public class TSMBackupStep extends JobStep { if (killDateDays > 0) { KillDateFile killDateFile = new KillDateFile(sourceMediaFile.getParent().toString(), sourceMediaFile.getFileName().toString()); - killDateFile.create(killDateDays); + killDateFile.create(killDateDays, getMarker()); } } catch (Exception e) { logger.catching(e); diff --git a/server/user.jobengine.executors/src/user/jobengine/server/steps/TSMRestoreStep.java b/server/user.jobengine.executors/src/user/jobengine/server/steps/TSMRestoreStep.java index 48fbcf8c..e41cbe62 100644 --- a/server/user.jobengine.executors/src/user/jobengine/server/steps/TSMRestoreStep.java +++ b/server/user.jobengine.executors/src/user/jobengine/server/steps/TSMRestoreStep.java @@ -58,7 +58,7 @@ public class TSMRestoreStep extends JobStep { if (killDateDays > 0) { KillDateFile killDateFile = new KillDateFile(targetPath, targetFileName); - killDateFile.create(killDateDays); + killDateFile.create(killDateDays, getMarker()); } } catch (Exception e) { diff --git a/server/user.jobengine.executors/src/user/jobengine/server/steps/TranscodeSELENIOStep.java b/server/user.jobengine.executors/src/user/jobengine/server/steps/TranscodeSELENIOStep.java index 0659150d..4624113b 100644 --- a/server/user.jobengine.executors/src/user/jobengine/server/steps/TranscodeSELENIOStep.java +++ b/server/user.jobengine.executors/src/user/jobengine/server/steps/TranscodeSELENIOStep.java @@ -152,9 +152,9 @@ public class TranscodeSELENIOStep extends JobStep { if (transcodeTask == null) throw new NullPointerException("Unable to query transcode task, server response is empty for transcode input: " + sourceFile); - Integer estimate = transcodeTask.getEstimateSecondsRemaining(); - if (estimate != null) - logger.info("Estimate {}", estimate); + // Integer estimate = transcodeTask.getEstimateSecondsRemaining(); + // if (estimate != null) + // logger.info("Estimate {}", estimate); Double progress = transcodeTask.getProgress(); if (progress != null) jobRuntime.incrementProgress((int) Math.round(progress * 100)); diff --git a/server/user.jobengine.osgi.commons/src/user/commons/octopus/OctopusAPI.java b/server/user.jobengine.osgi.commons/src/user/commons/octopus/OctopusAPI.java index 2b57a447..daa69089 100644 --- a/server/user.jobengine.osgi.commons/src/user/commons/octopus/OctopusAPI.java +++ b/server/user.jobengine.osgi.commons/src/user/commons/octopus/OctopusAPI.java @@ -116,7 +116,7 @@ public class OctopusAPI implements IOctopusAPI { QueryBuilder.start("scheduledStart").lessThan(calStop.getTime()).get()).get(); } - logger.info(query); + //logger.info(query); DBCursor find = collection.find(query).sort(new BasicDBObject("scheduledStart", new BasicDBList(1, "$date"))); if (find.hasNext()) result = find.toArray(); diff --git a/server/user.jobengine.osgi.db/src/user/jobengine/db/ItemDAOEx.java b/server/user.jobengine.osgi.db/src/user/jobengine/db/ItemDAOEx.java index d12647de..b60264e1 100644 --- a/server/user.jobengine.osgi.db/src/user/jobengine/db/ItemDAOEx.java +++ b/server/user.jobengine.osgi.db/src/user/jobengine/db/ItemDAOEx.java @@ -53,7 +53,7 @@ public class ItemDAOEx { qf.format("(SELECT ii.ID %1$s) ORDER BY i.TITLE", innerQuery); } - logger.info(resultQuery.toString()); + logger.trace(resultQuery.toString()); return resultQuery.toString(); } @@ -65,7 +65,7 @@ public class ItemDAOEx { else typeQuery = String.format("SELECT ii.ITEMTYPEID, CAST(COUNT(DISTINCT(ii.ID)) AS BIGINT) %s GROUP BY ii.ITEMTYPEID", innerQuery); - logger.info(typeQuery.toString()); + logger.trace(typeQuery.toString()); PreparedStatement st = null; ResultSet rs = null; try { @@ -85,7 +85,7 @@ public class ItemDAOEx { results.add(sr); } } catch (Exception e) { - e.printStackTrace(); + logger.catching(e); } finally { try { if (rs != null) diff --git a/server/user.jobengine.osgi.server/src/user/jobengine/server/JobStepExecutor.java b/server/user.jobengine.osgi.server/src/user/jobengine/server/JobStepExecutor.java index 7ecf7cbb..770202e0 100644 --- a/server/user.jobengine.osgi.server/src/user/jobengine/server/JobStepExecutor.java +++ b/server/user.jobengine.osgi.server/src/user/jobengine/server/JobStepExecutor.java @@ -38,8 +38,7 @@ public class JobStepExecutor implements IJobStepExecutor { step = createStepObject(); if (step == null) throw new Exception("Step object is null"); - logger.info("Executing job {}-{}, step {}, thread name {}", jobRuntime.getId(), jobRuntime.getName(), step.getClass().getSimpleName(), - getName()); + logger.info("Executing job {}-{}, step {} ({})", jobRuntime.getId(), jobRuntime.getName(), step.getClass().getSimpleName(), getName()); //TODO ez biztosan kell? //jobRuntime.IncrementPriority(); @@ -50,7 +49,7 @@ public class JobStepExecutor implements IJobStepExecutor { jobEngine.sendMessage(new JobStepCompletedMessage(jobRuntime.getId(), outputs)); } } catch (Exception e) { - logger.error("Error executing job {}-{}, thread name {}", jobRuntime.getId(), jobRuntime.getName(), getName()); + logger.error("Error executing job {}-{} ({})", jobRuntime.getId(), jobRuntime.getName(), getName()); Throwable t = e.getCause() == null ? e : e.getCause(); logger.catching(t); jobEngine.suspendJob(t, jobRuntime); @@ -206,7 +205,7 @@ public class JobStepExecutor implements IJobStepExecutor { public void submit(IJobRuntime jobRuntime) { queue.put(jobRuntime); jobRuntime.setDescription(stepClass.getSimpleName()); - logger.info("Executor got ! {}", jobRuntime); + //logger.info("Executor got ! {}", jobRuntime); } } diff --git a/server/user.jobengine.osgi.server/src/user/jobengine/server/steps/KillDateFile.java b/server/user.jobengine.osgi.server/src/user/jobengine/server/steps/KillDateFile.java index ae95f199..76d46eba 100644 --- a/server/user.jobengine.osgi.server/src/user/jobengine/server/steps/KillDateFile.java +++ b/server/user.jobengine.osgi.server/src/user/jobengine/server/steps/KillDateFile.java @@ -12,7 +12,12 @@ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Set; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; + public class KillDateFile { + private static final Logger logger = LogManager.getLogger(); private static final String KILLDATE_NAME = "%s.%s.killdate"; private static final String YYYY_M_MDD = "yyyyMMdd"; private static final String STATUSFOLDER = ".STATUS"; @@ -24,7 +29,7 @@ public class KillDateFile { this.fileName = fileName; } - public void create(int days) throws IOException { + public void create(int days, Marker marker) throws IOException { Path statusPath = Paths.get(filePath, STATUSFOLDER); File statusFolder = statusPath.toFile(); if (!statusFolder.exists() || !statusFolder.isDirectory()) { @@ -37,6 +42,9 @@ public class KillDateFile { SimpleDateFormat dateFormat = new SimpleDateFormat(YYYY_M_MDD); String killDateFileName = String.format(KILLDATE_NAME, fileName, dateFormat.format(killDate.getTime())); Path killDatePath = Paths.get(filePath, STATUSFOLDER, killDateFileName); - Files.createFile(killDatePath); + if (Files.exists(killDatePath)) + logger.warn(marker, "Az '{}' állomány már létezik.", killDatePath); + else + Files.createFile(killDatePath); } } diff --git a/server/user.jobengine.osgi.services/src/user/jobengine/osgi/rest/jobengine/JobengineService.java b/server/user.jobengine.osgi.services/src/user/jobengine/osgi/rest/jobengine/JobengineService.java index 3935a0f3..c2a98113 100644 --- a/server/user.jobengine.osgi.services/src/user/jobengine/osgi/rest/jobengine/JobengineService.java +++ b/server/user.jobengine.osgi.services/src/user/jobengine/osgi/rest/jobengine/JobengineService.java @@ -28,7 +28,7 @@ public class JobengineService { private IItemManager itemManager = ComponentBinder.getItemManagerService(); public JobengineService() { - logger.info("Created"); + //logger.info("Created"); } @POST diff --git a/server/user.tsm.client/META-INF/MANIFEST.MF b/server/user.tsm.client/META-INF/MANIFEST.MF index d9bd0f46..931b99ee 100644 --- a/server/user.tsm.client/META-INF/MANIFEST.MF +++ b/server/user.tsm.client/META-INF/MANIFEST.MF @@ -5,3 +5,4 @@ Bundle-SymbolicName: user.tsm.client;singleton:=true Bundle-Version: 1.2.0 Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Export-Package: user.tsm.client +Import-Package: org.apache.logging.log4j diff --git a/server/user.tsm.client/src/user/tsm/client/TSMBufferedClient.java b/server/user.tsm.client/src/user/tsm/client/TSMBufferedClient.java index fb4c356c..c554ddc9 100644 --- a/server/user.tsm.client/src/user/tsm/client/TSMBufferedClient.java +++ b/server/user.tsm.client/src/user/tsm/client/TSMBufferedClient.java @@ -3,6 +3,9 @@ package user.tsm.client; import java.io.FileNotFoundException; import java.io.IOException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import user.tsm.client.api.internal.DataBlk; import user.tsm.client.api.internal.DsmEndTxnExIn; import user.tsm.client.api.internal.DsmEndTxnExOut; @@ -16,7 +19,7 @@ import user.tsm.client.api.internal.TSMAPI; import user.tsm.client.api.internal.TSMAPIConstants; public class TSMBufferedClient extends TSMClient { - + private static final Logger logger = LogManager.getLogger(); private static final String APPNAME = "JOBENGINE"; short rc = 0; private DataBlk dataBlk; @@ -28,8 +31,32 @@ public class TSMBufferedClient extends TSMClient { super(APPNAME); } - public int recievePartial(byte[] buffer, TSMObject object, PartialObjData partialObjData) throws NullPointerException, FileNotFoundException, IOException, - TSMException { + public void finishReceive() throws TSMException { + // dsmEndGetObj + rc = TSMAPI.dsmEndGetObj(dsmHandle); + if (rc != TSMAPIConstants.DSM_RC_OK) { + TSMAPI.dsmEndGetData(dsmHandle); + throw new TSMException(dsmHandle, rc); + } + // dsmEndGetData + rc = TSMAPI.dsmEndGetData(dsmHandle); + if (rc != TSMAPIConstants.DSM_RC_OK) { + throw new TSMException(dsmHandle, rc); + } + dataBlk = null; + } + + public void finishSend() throws TSMException, JNIException { + if (dataBlk != null) { + rc = TSMAPI.dsmEndSendObj(dsmHandle); + if (rc != TSMAPIConstants.DSM_RC_OK) + throw new TSMException(dsmHandle, rc); + rc = vote(TSMAPIConstants.DSM_VOTE_COMMIT); + } + } + + public int recievePartial(byte[] buffer, TSMObject object, PartialObjData partialObjData) + throws NullPointerException, FileNotFoundException, IOException, TSMException { int result = 0; if (dataBlk == null) { @@ -81,43 +108,10 @@ public class TSMBufferedClient extends TSMClient { return result; } - public void finishReceive() throws TSMException { - // dsmEndGetObj - rc = TSMAPI.dsmEndGetObj(dsmHandle); - if (rc != TSMAPIConstants.DSM_RC_OK) { - TSMAPI.dsmEndGetData(dsmHandle); - throw new TSMException(dsmHandle, rc); - } - // dsmEndGetData - rc = TSMAPI.dsmEndGetData(dsmHandle); - if (rc != TSMAPIConstants.DSM_RC_OK) { - throw new TSMException(dsmHandle, rc); - } - dataBlk = null; - } - - public void finishSend() throws TSMException, JNIException { - if (dataBlk != null) { - rc = TSMAPI.dsmEndSendObj(dsmHandle); - if (rc != TSMAPIConstants.DSM_RC_OK) - throw new TSMException(dsmHandle, rc); - DsmEndTxnExIn endTxnExIn = new DsmEndTxnExIn(); - endTxnExIn.setDsmHandle(dsmHandle); - endTxnExIn.setVote(TSMAPIConstants.DSM_VOTE_COMMIT); - DsmEndTxnExOut endTxnExOut = new DsmEndTxnExOut(); - rc = TSMAPI.dsmEndTxnEx(endTxnExIn, endTxnExOut); - if (rc != TSMAPIConstants.DSM_RC_OK) { - throw new TSMException(dsmHandle, rc, endTxnExOut.getReason()); - } - } - } - - public void send(byte[] buffer, TSMBackupFileObject object, int byteCount) throws NullPointerException, FileNotFoundException, IOException, TSMException { + public void send(byte[] buffer, TSMBackupFileObject object, int byteCount) throws Exception { short rc; try { if (dataBlk == null) { - dataBlk = new DataBlk(); - dataBlk.setBufferPtr(buffer); rc = TSMAPI.dsmBeginTxn(dsmHandle); if (rc != TSMAPIConstants.DSM_RC_OK) throw new TSMException(dsmHandle, rc); @@ -143,45 +137,32 @@ public class TSMBufferedClient extends TSMClient { throw new TSMException(dsmHandle, rc); } + dataBlk = new DataBlk(); + dataBlk.setBufferPtr(buffer); dataBlk.setBufferLen(byteCount); rc = TSMAPI.dsmSendData(dsmHandle, dataBlk); if (rc != TSMAPIConstants.DSM_RC_OK) throw new TSMException(dsmHandle, rc); object.bytesWorked(byteCount); + } catch (Exception e) { + vote(TSMAPIConstants.DSM_VOTE_ABORT); + throw e; + } + } - // if ((length = byteCount) > 0) { - // dataBlk.setBufferLen(length); - // rc = TSMAPI.dsmSendData(dsmHandle, dataBlk); - // if (rc != TSMAPIConstants.DSM_RC_OK) - // throw new TSMException(dsmHandle, rc); - // object.bytesWorked(length); - // if (length < prevLength) { - // finishSend(); - // } - // } - } catch (JNIException e1) { - DsmEndTxnExIn endTxnExIn = new DsmEndTxnExIn(); - endTxnExIn.setDsmHandle(dsmHandle); - endTxnExIn.setVote(TSMAPIConstants.DSM_VOTE_ABORT); - DsmEndTxnExOut endTxnExOut = new DsmEndTxnExOut(); - try { - TSMAPI.dsmEndTxnEx(endTxnExIn, endTxnExOut); - } catch (Exception e) { - } - ; - throw new TSMException("Internal error: " + e1.getMessage()); - } catch (TSMException e2) { - DsmEndTxnExIn endTxnExIn = new DsmEndTxnExIn(); - endTxnExIn.setDsmHandle(dsmHandle); - endTxnExIn.setVote(TSMAPIConstants.DSM_VOTE_ABORT); - DsmEndTxnExOut endTxnExOut = new DsmEndTxnExOut(); - try { - TSMAPI.dsmEndTxnEx(endTxnExIn, endTxnExOut); - } catch (Exception e) { - } - ; - throw e2; - } finally { + private short vote(byte vote) throws TSMException { + short result = TSMAPIConstants.DSM_RC_OK; + DsmEndTxnExIn endTxnExIn = new DsmEndTxnExIn(); + endTxnExIn.setDsmHandle(dsmHandle); + endTxnExIn.setVote(vote); + DsmEndTxnExOut endTxnExOut = new DsmEndTxnExOut(); + try { + result = TSMAPI.dsmEndTxnEx(endTxnExIn, endTxnExOut); + } catch (Exception e) { + logger.catching(e); } + if (result != TSMAPIConstants.DSM_RC_OK) + throw new TSMException(dsmHandle, rc, endTxnExOut.getReason()); + return result; } }