using System; using System.Collections; using System.Threading; using System.Xml; 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; 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 ) { using ( IMediaMgr mediaMgr = connection.AppServer.CreateMediaMgr(appName) ) { // define clip to modify and imported WAV clip string clip = "edl/cmf//local/V:/default/Clip"; string wavClip = "edl/cmf//local/V:/default/wavClip"; // Note: this test app is using an imported clip named "wavClip". If you wanted to import a temporary clip that // you did not want to appear in AppCenter's list of clips, you could import a clip and give it a name that starts // with a tilde (~). All clips starting with tilde's are treated as temporary clips. They will not appear in AppCenter's // list of clips and they will automatically be deleted after a little while... // get editors for both clips ISimpleEditor wavEditor = (ISimpleEditor) mediaMgr.CreateEditor(wavClip); ISimpleEditor clipEditor = (ISimpleEditor) mediaMgr.CreateEditor(clip); ITrackEditor clipTrackEditor = (ITrackEditor) clipEditor; // get the XML representation of the WAV clip string wavXml; wavEditor.GetXml("", out wavXml); // Console.WriteLine(wavXml); // we're finished with wavEditor, so get rid of the editor and clean up wavEditor.Detach(); wavEditor.Dispose(); // load the XML string into an XML document so we can parse for Tracks XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(wavXml); // load the namespace into a namespace manager. used for parsing the xml doc XmlNamespaceManager namespaceManager = new XmlNamespaceManager(xmlDoc.NameTable); namespaceManager.AddNamespace("ns", @"PdrDB__1.0"); // loop thru all tracks and look for audio tracks only (i.e TrackType="PdrAudioTrack". Uncomment the above // Console.WriteLine(wavXml) to see all XML data including other TrackTypes.) XmlNodeList trackList = xmlDoc.SelectNodes(("//ns:XML/ns:Data/ns:Movie/ns:Track"), namespaceManager); // if our clip has tracks, loop thru all tracks if (trackList.Count > 0) { // setup enumerator for loop IEnumerator trackNodeEnum = trackList.GetEnumerator(); bool bMoreTracks = trackNodeEnum.MoveNext(); do { // Get the TrackType, TrackNumber, and TrackId attribues from the Track node XmlNode trackNode = (XmlNode)trackNodeEnum.Current; string trackType = trackNode.Attributes.GetNamedItem("TrackType").Value; int trackNumber = Int32.Parse ( trackNode.Attributes.GetNamedItem("TrackNumber").Value ); string trackId = trackNode.Attributes.GetNamedItem("TrackId").Value; // if we found a "PdrAudioTrack, add it to the Clip if ( 0 == String.Compare( trackType, "PdrAudioTrack", true) ) { Console.WriteLine("Track type: {0} number: {1} ID: {2}", trackType, trackNumber, trackId); // add WAV audio track to Clip int addedTrackIndex; string addedTrackId; clipTrackEditor.AddTrack(wavClip, trackId, Int32.MinValue, Int32.MaxValue, 0, out addedTrackIndex, out addedTrackId); Console.WriteLine("Added track index: {0} ID: {1}", addedTrackIndex, addedTrackId); // Let's also setup a label for this track. You can see these in AppCenter in clip properties page under the Tracks button. string label = "xyz"; Console.WriteLine("Set track {0} label to '{1}'", addedTrackId, label); clipTrackEditor.SetTrackLabel(addedTrackId, label); /* uncomment to test // delete tracks from Clip Console.WriteLine("Delete track {0}", addedTrackId); clipTrackEditor.DeleteTrack(addedTrackId); */ /* uncomment to test // move track position in Clip int position = 0; Console.WriteLine("Move track {0} to position {1}", addedTrackId, position); clipTrackEditor.MoveTrack(addedTrackId, position); */ Console.WriteLine(); } bMoreTracks = trackNodeEnum.MoveNext(); } while (bMoreTracks); } // if trackList.Count > 0 // cleanup - make sure you detach or movie ref will remain open! clipEditor.Detach(); clipEditor.Dispose(); clipEditor = null; } } } } catch (SystemException se) { Console.WriteLine(se); } 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 (SystemException se) { Console.WriteLine(se); } } /// /// 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(); } } }