using System; using System.IO; using GrassValley.Mseries.AppServer; using GrassValley.Mseries.AppServerLog; using GrassValley.Mseries.ChanStatus; using GrassValley.Mseries.ConfigMgr; using GrassValley.Mseries.Control; using GrassValley.Mseries.DVCapture; using GrassValley.Mseries.Editor; using GrassValley.Mseries.MediaMgr; using GrassValley.Mseries.Security; using GrassValley.Mseries.Status; using GrassValley.Mseries.TransferQueue; // Leave the following "css_reference" lines in when running with CS-Script. They're // more than just comments - they tell CS-Script which DLLs to load if the DLL // name does not match the namespace that it implements. //css_reference Credentials.dll; //css_reference ServerUtil.dll; /// /// This is a sample CS-Script app for controlling the Grass Valley K2 server. /// The code is regular C# code, but it's written for CS-Script which can /// run it as a script from a DOS command prompt. /// /// Go to the K2 AppServer Developer's Guide for more information: /// http://www.gvgdevelopers.com/K2DevGuide/K2DevGuide.html#%5B%5BCS-Script%20Sample%20Scripts%5D%5D /// /// For more information about CS-Script go to: /// http://www.members.optusnet.com.au/~olegshilo/ /// namespace K2Script { class Test { static int Main(string[] args) { try { // get the application's name & create a unique suite name string appName = Environment.GetCommandLineArgs()[0]; string suiteName = appName + "_" + System.Guid.NewGuid().ToString("N"); // fill in these values for your connection (i.e. hardcode them, pass in cmdline arguments, read from file, read from console, etc.) string host = "localhost"; string username = ""; string password = ""; string domain = ""; // Connect to host & pass in credentials. The "using" block disposes connection when done. using ( Connection connection = new Connection(appName, suiteName, host, username, password, domain) ) { // do work only if we have a valid connection if ( connection.IsConnected ) { // create a media mgr using ( IMediaMgr mediaMgr = connection.AppServer.CreateMediaMgr(appName) ) { // define clip to modify string volume = "V:"; string bin = "default"; string clipname = "Clip"; string dataFile = "C:\\temp\\anc_data.N0"; string clipURI = String.Format("edl/cmf//{0}/{1}/{2}/{3}", host, volume, bin, clipname); // get an editor for clip using ( ISimpleEditor editor = (ISimpleEditor) mediaMgr.CreateEditor(clipURI) ) { try { // cast it to a track editor ITrackEditor2 trackEditor = (ITrackEditor2) editor; ///////////////////////////////////////////////////// // Example 1: Merge the ENTIRE datafile into the clip ///////////////////////////////////////////////////// // srcFieldIn = -1 == start of file // srcFieldOut = -1 == end of file, // destFieldPos = 0 == field 0 in destination. note: you can use a timecode string too (i.e. "00:00:00.00") // merge = 1 == merge, rather than replace string ancFileName = trackEditor.MergeAncData (dataFile, -1, -1, 0, 1); // commit the change trackEditor.CommitAncData(); /* ////////////////////////////////////////////////////////////////// // Example 2: Merge PART of the datafile (first 300 fields) into the clip ////////////////////////////////////////////////////////////////// // srcFieldIn = 0 == field 0 // srcFieldOut = 300 == up to field 300 // destFieldPos = 0 == field 0 in destination. note: you can use a timecode string too (i.e. "00:00:00.00") // merge = 1 == merge, rather than replace string ancFileName = trackEditor.MergeAncData (dataFile, 0, 300, 0, 1); // commit the change trackEditor.CommitAncData(); */ /* ////////////////////////////////////////////////////////////////// // Example 3: Replace or Add the clip's ancillary data track ////////////////////////////////////////////////////////////////// // srcFieldIn = -1 == start of file // srcFieldOut = -1 == end of file, // destFieldPos = 0 == field 0 in destination. note: you can use a timecode string too (i.e. "00:00:00.00") // merge = 0 == replace, rather than merge // Note: if replacing or adding (i.e. the original clip does not have an ancillary data track) rather than // merging then you first need to copy the local data file over to the K2 Client's V: drive. To do this, you // should copy the local file to a location and name on the K2 Client's V: drive that looks like // "V:\PDR\\\.N0". Then you can use that file with the TrackEditor's MergeAncData // call to replace the ancillary data track. // first generate unique guid name & path string newDataFile = String.Format("V:\\PDR\\{0}\\{1}.N0", bin, System.Guid.NewGuid().ToString("N")); // if the newDataFile does not exists if ( File.Exists(newDataFile) ) { Console.WriteLine("ERROR: Cannot copy '{0}' to '{1}'. File '{1}' already exists.", dataFile, newDataFile); return -1; } // copy local data file to V: drive File.Copy( dataFile, newDataFile ); // replace the clip's anc data track trackEditor.MergeAncData (newDataFile, -1, -1, 0, 0); // commit the change trackEditor.CommitAncData(); string ancFileName = newDataFile; */ // output new ancillary file info Console.WriteLine("The new ancillary filename is located at '{0}'", ancFileName); } catch (Exception e) { Console.WriteLine(e); } finally { // Very Important: make sure that you detach the editor when you're done. If not, you will // have references to the movie hanging around. This will cause you trouble later when you // try to delete or move the clip, but can't because of outstanding references to the clip. editor.Detach(); } } // when using block goes out of scope the simpleeditor is disposed } // when using block goes out of scope the mediamgr is disposed } } } catch (Exception e) { Console.WriteLine(e); } return 0; } } // Connection helper class: sets up credentials & hostname, connects to K2 public class Connection: IDisposable { private bool _connected = false; private AppServerMgrProxy _appServerMgrProxy = null; private IAppServer _appServer = null; /// /// Object that connects to the specified K2 credentials /// /// The application's name. /// The suite's name. /// The K2's host name. /// The username. /// The password. /// The domain. public Connection(string appname, string suitename, string host, string username, string password, string domain) { try { ////////////////////////// // SETUP ////////////////////////// if ( null == host || host.Length == 0) { Console.WriteLine("Empty host name passed to Connection object."); return; } ////////////////////////// // CONNECT TO K2 ////////////////////////// // create an AppServerMgr proxy object _appServerMgrProxy = new AppServerMgrProxy(); // tell it which K2 we're connecting to _appServerMgrProxy.SetHost(host); // give it the user credentials we want to use if ( username.Length > 0 ) _appServerMgrProxy.SetUserCredentials(username, password, domain, false); // connect to the K2's AppServerMgr if ( !_appServerMgrProxy.Connect() ) { // if the connection failed, report an error and exit Console.WriteLine("ERROR: Could not connect to AppService on host '" + host + "'. Check the host name."); _appServerMgrProxy = null; return; } // if we got here we're connected to K2 AppService ////////////////////////// // CREATE AN APPSERVER ////////////////////////// // now create an AppServer bool newConnection = false; _appServer = _appServerMgrProxy.CreateAppServer(suitename, appname, out newConnection); _connected = true; } catch (Exception e) { Console.WriteLine(e); } } /// /// Gets a value indicating whether this instance is connected. /// /// /// true if this instance is connected; otherwise, false. /// public bool IsConnected { get { return _connected; } } /// /// Gets the AppServerMgr. /// /// The AppServerMgr public AppServerMgrProxy AppServerMgr { get { if ( _appServerMgrProxy == null ) Console.WriteLine("WARNING: AppServerMgrProxy object == null!"); return _appServerMgrProxy; } } /// /// Gets the AppServer /// /// The AppServer public IAppServer AppServer { get { if ( _appServerMgrProxy == null ) Console.WriteLine("WARNING: AppServerProxy object == null!"); return _appServer; } } /// /// Disposes this instance. /// public void Dispose() { if ( _appServer != null ) _appServer.CloseConnection(); } } }