198 lines
No EOL
6.6 KiB
C#
198 lines
No EOL
6.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
using JD.Adobe.Service.API;
|
|
using JD.Adobe.Service.ExecutableManagement;
|
|
using Microsoft.AspNet.SignalR;
|
|
using Plume.Core.Events;
|
|
using Plume.Core.Logging;
|
|
using Plume.Interfaces.Services;
|
|
using Shuttle.Api.ClientAPI;
|
|
using Shuttle.Servers;
|
|
using Shuttle.Servers.Hubs;
|
|
using Shuttle.Servers.Managers.AsyncProviders;
|
|
using Shuttle.Servers.Managers.Clients;
|
|
using Shuttle.Servers.Managers.Events;
|
|
using Shuttle.Servers.Managers.Items;
|
|
using Shuttle.Servers.Managers.Notifications;
|
|
|
|
namespace JD.Adobe.Service.Implementation
|
|
{
|
|
public abstract class AdobeService : IAdobeService
|
|
{
|
|
private readonly object _lock = new object();
|
|
private readonly HashSet<TargetAppInfo> _targets = new HashSet<TargetAppInfo>();
|
|
private readonly ISignalrServer _signalrServer;
|
|
private readonly EventInvoker _eventInvoker;
|
|
private IAdobeEvents _adobeEvents;
|
|
|
|
protected readonly AdobeExecutableManager _adobeExecutableManager;
|
|
protected IAsyncProvider _asyncProvider;
|
|
protected IClientManager _clientManager;
|
|
protected bool _isInitialized = false;
|
|
|
|
protected ILogger Logger { get; }
|
|
|
|
public event Action<TargetAppInfo> OnTargetAdded;
|
|
public event Action<TargetAppInfo> OnTargetRemoved;
|
|
|
|
public event Action<TargetAppInfo, string> OnProjectFileChanged;
|
|
public event Action<TargetAppInfo> OnTargetFocused;
|
|
|
|
protected AdobeService(ILogger logger, string serverUrl)
|
|
{
|
|
if (serverUrl == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(serverUrl));
|
|
}
|
|
|
|
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
_signalrServer = new SignalrServer(serverUrl);
|
|
_eventInvoker = new EventInvoker(Logger);
|
|
_adobeExecutableManager = new AdobeExecutableManager(Logger);
|
|
}
|
|
|
|
protected abstract void InitializeImpl(IServiceContext context);
|
|
|
|
public void Initialize(IServiceContext context)
|
|
{
|
|
_asyncProvider = new AsyncProvider();
|
|
var aeHubContext = GlobalHost.ConnectionManager.GetHubContext<ClientHub, IAfterEffectsClient>();
|
|
var psHubContext = GlobalHost.ConnectionManager.GetHubContext<ClientHub, IPhotoshopClient>();
|
|
_clientManager = new ClientManager(Logger, aeHubContext, psHubContext);
|
|
|
|
_clientManager.OnTargetConnection += AddTarget;
|
|
_clientManager.OnTargetDisconnection += RemoveTarget;
|
|
|
|
var eventManager = new EventManager(Logger, _clientManager);
|
|
eventManager.OnAppFocused += OnAppFocused;
|
|
eventManager.OnProjectOpened += OnProjectOpened;
|
|
eventManager.OnProjectClosed += OnProjectClosedEvent;
|
|
_adobeEvents = eventManager;
|
|
|
|
_signalrServer.Initialize(Logger, _clientManager,
|
|
itemDepository: new ItemDepository(Logger, _asyncProvider),
|
|
operationNotificationListener: new OperationNotificationListener(Logger, _asyncProvider),
|
|
eventNotificationListener: eventManager);
|
|
|
|
_signalrServer.Start();
|
|
|
|
_adobeExecutableManager.Initialize();
|
|
|
|
InitializeImpl(context);
|
|
}
|
|
|
|
public ICollection<TargetAppInfo> GetAvailableTargets()
|
|
{
|
|
ICollection<TargetAppInfo> results;
|
|
lock (_lock)
|
|
{
|
|
results = new List<TargetAppInfo>(_targets);
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
public abstract Task<TargetAppInfo> StartNewInstance(AdobeApplicationType appType);
|
|
|
|
public void Dispose()
|
|
{
|
|
_clientManager.OnTargetConnection -= AddTarget;
|
|
_clientManager.OnTargetDisconnection -= RemoveTarget;
|
|
|
|
_adobeEvents.OnAppFocused -= OnAppFocused;
|
|
_adobeEvents.OnProjectOpened -= OnProjectOpened;
|
|
_adobeEvents.OnProjectClosed -= OnProjectClosedEvent;
|
|
|
|
_signalrServer.Dispose();
|
|
}
|
|
|
|
private void AddTarget(TargetAppInfo target)
|
|
{
|
|
if (target == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(target));
|
|
}
|
|
|
|
if (TargetAppInfo.IsEmpty(target))
|
|
{
|
|
throw new ArgumentException($"{nameof(target)} cannot be the empty target.", nameof(target));
|
|
}
|
|
|
|
bool added;
|
|
lock (_lock)
|
|
{
|
|
added = _targets.Add(target);
|
|
}
|
|
|
|
if (!added)
|
|
{
|
|
throw new ArgumentException($"Target '{target.ShuttleId}' ({target.ConnectionId}) was already known by {this.GetType().Name}.");
|
|
}
|
|
|
|
_eventInvoker.SafeInvokeEventAsync(OnTargetAdded, target);
|
|
}
|
|
|
|
private void RemoveTarget(TargetAppInfo target)
|
|
{
|
|
if (target == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(target));
|
|
}
|
|
|
|
if (TargetAppInfo.IsEmpty(target))
|
|
{
|
|
throw new ArgumentException($"{nameof(target)} cannot be the empty target.", nameof(target));
|
|
}
|
|
|
|
bool removed;
|
|
lock (_lock)
|
|
{
|
|
removed = _targets.Remove(target);
|
|
}
|
|
|
|
if (!removed)
|
|
{
|
|
throw new ArgumentException($"Target '{target.ShuttleId}' ({target.ConnectionId}) was not known by {this.GetType().Name} in the first place.");
|
|
}
|
|
|
|
_eventInvoker.SafeInvokeEventAsync(OnTargetRemoved, target);
|
|
}
|
|
|
|
protected void ThrowIfUnknown(TargetAppInfo target)
|
|
{
|
|
if (target == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(target));
|
|
}
|
|
|
|
bool isKnown;
|
|
lock (_lock)
|
|
{
|
|
isKnown = _targets.Contains(target);
|
|
}
|
|
|
|
if (isKnown)
|
|
{
|
|
return;
|
|
}
|
|
|
|
throw new ArgumentException($"Unknown target '{target.ShuttleId}' ({target.ConnectionId})");
|
|
}
|
|
|
|
private void OnProjectClosedEvent(TargetAppInfo target, string projectFile)
|
|
{
|
|
_eventInvoker.SafeInvokeEventAsync(OnProjectFileChanged, target, projectFile);
|
|
}
|
|
|
|
private void OnProjectOpened(TargetAppInfo target, string projectFile)
|
|
{
|
|
_eventInvoker.SafeInvokeEventAsync(OnProjectFileChanged, target, projectFile);
|
|
}
|
|
|
|
private void OnAppFocused(TargetAppInfo target)
|
|
{
|
|
_eventInvoker.SafeInvokeEventAsync(OnTargetFocused, target);
|
|
}
|
|
}
|
|
} |