1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
using DirectShowLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Tango.Video.DirectShow
{
internal class SampleGrabberImpl : ISampleGrabberCB
{
#region delegates
public delegate int BufferCallback(double SampleTime, IntPtr pBuffer, int BufferLen);
public delegate int BufferCallback2(double sampleTime, IMediaSample pSample);
#endregion
#region Members
readonly BufferCallback _callback;
readonly BufferCallback2 _callback2;
#endregion
#region Constructor
public SampleGrabberImpl(BufferCallback callback, BufferCallback2 callback2 = null)
{
_callback = callback;
_callback2 = callback2;
}
#endregion
#region ISampleGrabberCB Members
public int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
{
if (_callback != null)
{
return _callback(SampleTime, pBuffer, BufferLen);
}
return 0;
}
public int SampleCB(double SampleTime, IMediaSample pSample)
{
if (_callback2 != null)
{
return _callback2(SampleTime, pSample);
}
Marshal.ReleaseComObject(pSample);
return 0;
}
#endregion
}
}
or: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */using CommandLine;
using Ionic.Zip;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Tango.AdvancedInstaller;
using Tango.Core;
using Tango.Core.Cryptography;
using Tango.Core.Helpers;
using Tango.Git;
using Tango.MachineStudio.Common.Web;
using Tango.Transport.Web;
using Tango.Web;
namespace Tango.MachineStudio.Common.Publish
{
public class MachineStudioPublisher : ExtendedObject
{
private MachineStudioWebClient _client;
/// <summary>
/// Occurs on publish progress.
/// </summary>
public event EventHandler<PublishProgressEventArgs> PublishProgress;
private PublishOptions _options;
/// <summary>
/// Gets or sets the publish options.
/// </summary>
public PublishOptions Options
{
get { return _options; }
set { _options = value; RaisePropertyChangedAuto(); }
}
/// <summary>
/// Initializes a new instance of the <see cref="MachineStudioPublisher"/> class.
/// </summary>
public MachineStudioPublisher()
{
_client = new MachineStudioWebClient();
Options = new PublishOptions();
}
/// <summary>
/// Initializes a new instance of the <see cref="MachineStudioPublisher"/> class.
/// </summary>
/// <param name="publishOptions">The publish options.</param>
public MachineStudioPublisher(PublishOptions publishOptions) : this()
{
Options = publishOptions;
}
/// <summary>
/// Gets the latest version.
/// </summary>
/// <returns></returns>
public async Task<String> GetRemoteVersion()
{
_client.Environment = Options.Environment;
var response = await _client.GetLatestVersion(new LatestVersionRequest());
return response.Version;
}
/// <summary>
/// Gets the latest version.
/// </summary>
/// <returns></returns>
public async Task<String> GetRemoteVersion(DeploymentSlot environment)
{
_client.Environment = environment;
var response = await _client.GetLatestVersion(new LatestVersionRequest());
return response.Version;
}
/// <summary>
/// Gets the latest version.
/// </summary>
/// <returns></returns>
public String GetLocalVersion()
{
return FileVersionInfo.GetVersionInfo(GetMachineStudioExecutablePath()).ProductVersion;
}
/// <summary>
/// Gets the machine studio executable path.
/// </summary>
/// <returns></returns>
public String GetMachineStudioExecutablePath()
{
String appPath = Path.Combine(Options.GetApplicationPath(), "Tango.MachineStudio.UI.exe");
return appPath;
}
/// <summary>
/// Login to machine service and returns an access token.
/// </summary>
/// <returns></returns>
private Task Login()
{
return Task.Factory.StartNew(() =>
{
return _client.Login(new LoginRequest()
{
Email = Options.Email,
Password = Options.Password,
Version = GetLocalVersion(),
}).Result;
});
}
/// <summary>
/// Publish a machine studio version using the specified <see cref="Options"/>.
/// </summary>
/// <returns></returns>
public Task Publish()
{
_client.Environment = Options.Environment;
String appPath = GetMachineStudioExecutablePath();
String folder = Options.GetApplicationPath();
if (!File.Exists(appPath))
{
throw new FileNotFoundException($"Could not locate the machine studio executable at {appPath}.");
}
if (!String.IsNullOrWhiteSpace(Options.InstallerProject))
{
if (!File.Exists(Options.InstallerProject))
{
throw new FileNotFoundException($"Installer project not found at '{Options.InstallerProject}'.");
}
if (!Directory.Exists(Options.InstallerOutputFolder))
{
throw new DirectoryNotFoundException($"Installer output folder does not exists '{Options.InstallerOutputFolder}'.");
}
}
String tempFile = TemporaryManager.CreateFile();
return Task.Factory.StartNew(() =>
{
try
{
OnPublishProgress(0, 100, $"Logging in to machine service at {Options.Environment.ToAddress()}...");
Login().Wait();
OnPublishProgress(0, 100, $"Fetching remote version from {Options.Environment.ToAddress()}...");
String remote_version = GetRemoteVersion().Result;
String local_version = GetLocalVersion();
OnPublishProgress(0, 100, $"Remote version: {remote_version}");
OnPublishProgress(0, 100, $"Local version: {local_version}");
if (Version.Parse(local_version) <= Version.Parse(remote_version))
{
throw new InvalidOperationException($"The local version '{local_version}' is not greater than the remote version '{remote_version}'.");
}
if (Options.CreateTag)
{
String repoPath = Path.GetFullPath("../../../../../");
using (GitRepositoryManager git = new GitRepositoryManager(repoPath, Options.Email, Options.PersonalAccessToken))
{
OnPublishProgress(0, 100, "Checking repository changes...");
int changes = git.GetChanges().Count;
if (changes > 0)
{
throw new InvalidOperationException($"There are {changes} uncommitted changes on the repository. Please commit and push all changes before creating the Tag");
}
OnPublishProgress(0, 100, "Checking outgoing commits...");
int commits = git.GetOutgoingCommits().Count;
if (commits > 0)
{
throw new InvalidOperationException($"There are {commits} outgoing commits on the repository. Please push all commits before creating the Tag");
}
String tagVersion = System.Version.Parse(GetLocalVersion()).ToString(3);
String tagName = $"Machine_Studio_v{tagVersion}";
String tagDescription = $"Snapshot of Machine Studio v{tagVersion}";
git.Progress += (x, e) =>
{
OnPublishProgress(e.Progress.Value, e.Progress.Maximum, $"Pushing Tag '{tagName}'...");
};
OnPublishProgress(0, 100, $"Creating Tag '{tagName}'...");
git.CreatePushTag(tagName, tagDescription, "Roy Ben Shabat");
}
}
OnPublishProgress(0, 100, $"Requesting version upload...");
var response = _client.UploadVersion(new UploadVersionRequest()
{
Version = local_version,
Comments = Options.Comments,
WithInstaller = !String.IsNullOrWhiteSpace(Options.InstallerProject),
}).Result;
if (!String.IsNullOrWhiteSpace(Options.InstallerProject))
{
String output_folder = Options.InstallerOutputFolder;
OnPublishProgress(0, 100, $"Building installer project...");
InstallerBuilder installerBuilder = new InstallerBuilder(Options.InstallerProject);
String installer_name = $"Machine Studio Installer_v{Version.Parse(local_version).ToString(3)}.exe";
String output_file = Path.Combine(output_folder, installer_name);
installerBuilder.Build(local_version, output_file).Wait();
Thread.Sleep(5000);
OnPublishProgress(0, 100, $"Uploading installer '{installer_name}'...");
using (StorageBlobUploader uploader = new StorageBlobUploader(response.InstallerBlobAddress, output_file))
{
uploader.Progress += (x, e) =>
{
OnPublishProgress(e.Current, e.Total, $"Uploading installer {(((double)e.Current / (double)e.Total) * 100d).ToString("0.0")}%...", true);
};
uploader.Upload().Wait();
}
}
OnPublishProgress(0, 100, $"Starting version packaging...");
using (ZipFile zip = new ZipFile())
{
foreach (var directory in Directory.GetDirectories(folder))
{
zip.AddDirectory(directory, $"/{Path.GetFileName(directory)}");
}
var files = Directory.GetFiles(folder, "*.*", SearchOption.TopDirectoryOnly).ToList();
foreach (var file in files)
{
zip.AddFile(file, "/");
}
zip.SaveProgress += (x, e) =>
{
if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry)
{
OnPublishProgress(e.EntriesSaved + 1, e.EntriesTotal, $"Compressing files {(((double)(e.EntriesSaved + 1) / (double)e.EntriesTotal) * 100d).ToString("0.0")}%...", true);
}
};
zip.ParallelDeflateThreshold = -1;
zip.Save(tempFile);
}
OnPublishProgress(0, 100, $"Starting version upload...");
using (StorageBlobUploader uploader = new StorageBlobUploader(response.BlobAddress, tempFile))
{
uploader.Progress += (x, e) =>
{
OnPublishProgress(e.Current, e.Total, $"Uploading version {(((double)e.Current / (double)e.Total) * 100d).ToString("0.0")}%...", true);
};
uploader.Upload().Wait();
}
OnPublishProgress(100, 100, $"Finalizing version upload...");
_client.NotifyVersionUploadCompleted(new UploadCompletedRequest()
{
Token = response.Token,
}).Wait();
remote_version = GetRemoteVersion().Result;
local_version = GetLocalVersion();
OnPublishProgress(0, 0, $"Remote version: {remote_version}");
OnPublishProgress(0, 0, $"Local version: {local_version}");
if (remote_version != local_version)
{
throw new InvalidOperationException("The remote version does not seems to have been updated.");
}
OnPublishProgress(0, 0, "Version published successfully.");
}
catch (Exception ex)
{
OnPublishProgress(0, 100, $"Failed: {ex.Message}");
throw ex;
}
finally
{
PathHelper.TryDeleteFile(tempFile);
}
});
}
/// <summary>
/// Raises the publish progress event.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="total">The total.</param>
/// <param name="message">The message.</param>
protected virtual void OnPublishProgress(double progress, double total, String message, bool singleLine = false)
{
PublishProgress?.Invoke(this, new PublishProgressEventArgs()
{
Progress = progress,
Total = total,
Message = message,
SingleLineRecommended = singleLine,
});
}
}
}
|