ATEM C# Macro control

Ask software engineering and SDK questions for developers working on Mac OS X, Windows or Linux.
  • Author
  • Message
Offline

John Yeomans

  • Posts: 2
  • Joined: Thu Feb 25, 2016 2:02 am

ATEM C# Macro control

PostThu Feb 25, 2016 2:22 pm

i am working on a project in c#
i am trying to make a program that has 6 buttons.
each button needs to fire a macro on the ATEM.
i am stuck.

i have connected to the switcher. step one done.
i can not find a command to quary the switcher for a list of macros in the switcher.
i all so have not been able to set up a processes that works to implement the IBMDSwitcherMacroControl
i am failing at the callback....
i am not a great programmer, a beginner with c# in fact, i have a few things under my belt.
i under stand the steps but not the correct processes.

i have three days on this and am running out of time. this switcher goes out on the road again.
this is not something i have to get done before it leaves. i will just loose access to it for testing.

i am just trying to understand this thing well enough well i have the gear in the shop to work with.

if any one can shed some lite on this i would be thankful
for the help.
Offline

Ian Morrish

  • Posts: 580
  • Joined: Sun Jan 18, 2015 9:24 pm
  • Location: New Zealand

Re: ATEM C# Macro control

PostFri Feb 26, 2016 7:54 am

Hi John,
Like you I'm not a programmer but struggling to build a library so I can automate ATM from Windows PowerShell. (https://github.com/imorrish/atemlib which I branched from another project to get me started)
Just started trying to add macro support, so far to get existing macros ,I have deduced from the API...
public uint GetMacroCount()
{
this.Connect();
uint macroCount;
IBMDSwitcherMacroPool switcherMacroPool = (IBMDSwitcherMacroPool)this.switcher;
switcherMacroPool.GetMaxCount(out macroCount);
return macroCount;
}
public string GetMacro(uint index)
{
this.Connect();
string macroName;
IBMDSwitcherMacroPool switcherMacroPool = (IBMDSwitcherMacroPool)this.switcher;
switcherMacroPool.GetDescription(index, out macroName);
return macroName;
}
Don't have access to an ATEM to try this until the weekend but always complicated getting callback defined but basics for run should be...
public int RunMacro(uint index)
{
this.Connect();
IBMDSwitcherMacroControl switcherMacroControl = (IBMDSwitcherMacroControl)this.switcher;
switcherMacroControl.Run(index);
Regards,
Ian Morrish
Video Integrated Scripting Environment
(Windows PowerShell with ATEM driver + more)
https://ianmorrish.wordpress.com
Offline

John Yeomans

  • Posts: 2
  • Joined: Thu Feb 25, 2016 2:02 am

Re: ATEM C# Macro control

PostFri Feb 26, 2016 3:17 pm

thank you,

i will dig in to this soon. i may not have time today.
but i will start on this ASAP

thanks again
Offline

Ian Morrish

  • Posts: 580
  • Joined: Sun Jan 18, 2015 9:24 pm
  • Location: New Zealand

Re: ATEM C# Macro control

PostFri Feb 26, 2016 8:22 pm

Well, surprisingly that worked for me (gives me even more motivation to keep learning C#).
Difference might be that from PowerShell I'm running in single-threaded apartment (STA) but I know Winforms don't. It would pay to look at the BMD SDK C# sample application as to how they did the simple transition button.

What would be really nice if BMD provided a full c# class library exposing all functionality. No doubt I'm doing it all wrong and will probably have to rework once I know better (anyone want to help?).
https://github.com/imorrish/atemlib/blo ... /Macro.ps1

Regards,
Ian
Regards,
Ian Morrish
Video Integrated Scripting Environment
(Windows PowerShell with ATEM driver + more)
https://ianmorrish.wordpress.com
Offline

Oscar Moreno

  • Posts: 29
  • Joined: Thu Apr 21, 2016 3:28 pm

Re: ATEM C# Macro control

PostFri Apr 29, 2016 4:50 pm

Hi, wondering if anyone could help me with this. I would like to integrate the Macro control into a client I'm working on. The client will control a CasparCG server and an ATEM 2 M/E switcher we have in our studio. The only thing I really need to do on the ATEM 2 M/E is the code to run a macro. For what I understand I will need to first connect to the switcher and then the code to send the command to run the macro. I've already added InteropServices and BMDSwitcherAPI to the code but I do need helpwith making the connection to the switcher.

Just so you know, I am a beginner C# programmer . . . .

Here's the full code of the client

Code: Select all
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using CasparCGNETConnector;
using CasparCGClientForm;

//ATEM 2 M/E Switcher interface
using System.Runtime.InteropServices;
using BMDSwitcherAPI;

namespace CasparCGClientForm
{
    public partial class Form1 : Form
    {       
        //Create a global server connection variable
        ICasparCGConnection con;

         // create a variable to check for lower third on or off
        Boolean l3state;

 
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //start with a trap to catch a failed connection
            try
            {
                //This starts the connection to the CasparCG server - crate server parameter variables
                int serverPort;
                String server;

                // Retrieve textbox values...
                server = servertextBox.Text;
                serverPort = Int32.Parse(porttextBox.Text);
                Console.WriteLine(serverPort);

                //Create a new connection object...
                con = new CasparCGConnection(server, serverPort);

                //...and establish a connection
                con.connect();

                //Use threading
                new Thread(() =>
                {
                }).Start();
            }
            catch //The connection to the server failed
            {
                MessageBox.Show("Connection Failed");
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //Run a macro on the ATEM switcher - Obviously this will not work
            IBMDSwitcherMacroControl playMacro;
            playMacro = new IBMDSwitcherMacroControl;
            playMacro(3);

            // Retrieve template infos so we know which fields are available and such
            // create template variable and object
            CasparCGTemplate template1;
            template1 = new CasparCGTemplate("WMES\\CGSAMPLE");
            template1.fillMediaInfo(ref con);

            // Set value for the lower3_title
            template1.getData().getInstance("lower3_title").getProperty("text").Value = "CasparCGNETConnector";

            //Build the command string
            string templateData = newslower3rd_command(this.anchorName_textBox.Text, this.anchorTitle_textBox.Text);

            // Update or play the template
            AbstractCommand cmd;
            CasparCGMovie playvideo;
            if (l3state == false)
            {
               
                playvideo = new CasparCGMovie("WMES\\[06] LOWER THIRD");
                con.sendCommand("WMES\\[06] LOWER THIRD");

            }
            cmd = new CgAddCommand(1, 5, template1, 0, true, templateData);
            cmd.execute(ref con);
        }


        private string  newslower3rd_command(string l3name, string l3title)
        {
            string tmpInstlower3_title = "lower3_title";
            string tmpInstlower3_titleValue = l3name;
            string tmpInstlower3_subtitle = "lower3_subtitle";
            string tmpInstlower3_subtitleValue = l3title;
            string tmpInslower3_station_number = "lower3_station_number";
            string tmpInstlower3_station_numberValue = this.stationNumb_textBox.Text;
            string tmpInstlower3_station_id = "lower3_station_id";
            string tmpInstlower3_station_idValue = this.stationid_textBox.Text;
            string tmpInsttwitter_url = "twitter_url";
            string tmpInsttwitter_urlValue = this.twitterhandle_textBox.Text;
            string tmpInststation_number = "station_number";
            string tmpInststation_numberValue = this.stationNumb_textBox.Text;
            string tmpInstupper3_station_id = "upper3_station_id";
            string tmpInstupper3_station_idValue = this.stationid_textBox.Text;
            string tmpInstlive_text = "live_text";
            string tmpInstlive_textValue = this.liveMsg_textBox.Text;
            string tmpInstlower3_temp = "lower3_temp";
            string tmpInstlower3_tempValue = this.temperature_textBox.Text;

            object[] objArray;
            objArray = new object[11];
            objArray[0] = "<templateData>";
            objArray[1] = "<componentData id=\"" + tmpInstlower3_title + "\"><data id=\"text\" value=\"" + tmpInstlower3_titleValue + "\"/></componentData>";
            objArray[2] = "<componentData id=\"" + tmpInstlower3_subtitle + "\"><data id=\"text\" value=\"" + tmpInstlower3_subtitleValue + "\"/></componentData>";
            objArray[3] = "<componentData id=\"" + tmpInslower3_station_number + "\"><data id=\"text\" value=\"" + tmpInstlower3_station_numberValue + "\"/></componentData>";
            objArray[4] = "<componentData id=\"" + tmpInstlower3_station_id + "\"><data id=\"text\" value=\"" + tmpInstlower3_station_idValue + "\"/></componentData>";
            objArray[5] = "<componentData id=\"" + tmpInsttwitter_url + "\"><data id=\"text\" value=\"" + tmpInsttwitter_urlValue + "\"/></componentData>";
            objArray[6] = "<componentData id=\"" + tmpInststation_number + "\"><data id=\"text\" value=\"" + tmpInststation_numberValue + "\"/></componentData>";
            objArray[7] = "<componentData id=\"" + tmpInstupper3_station_id + "\"><data id=\"text\" value=\"" + tmpInstupper3_station_idValue + "\"/></componentData>";
            objArray[8] = "<componentData id=\"" + tmpInstlive_text + "\"><data id=\"text\" value=\"" + tmpInstlive_textValue + "\"/></componentData>";
            objArray[9] = "<componentData id=\"" + tmpInstlower3_temp + "\"><data id=\"text\" value=\"" + tmpInstlower3_tempValue + "\"/></componentData>";
            objArray[10] = "</templateData>";
            string templateData = string.Concat(objArray);
            return templateData;
        }



        private void Form1_Load(object sender, EventArgs e)
        {
 
            // TODO: This line of code loads data into the 'dbWMESDataSetCrewList.Crew_List' table. You can move, or remove it, as needed.
            this.crew_ListTableAdapter.Fill(this.dbWMESDataSetCrewList.Crew_List);
            // TODO: This line of code loads data into the 'dbWMESDataSet.DaysOfWeek' table. You can move, or remove it, as needed.
            this.daysOfWeekTableAdapter.Fill(this.dbWMESDataSet.DaysOfWeek);
            // TODO: This line of code loads data into the 'dbWMESDataSet.Station_Configuration' table. You can move, or remove it, as needed.
            this.station_ConfigurationTableAdapter.Fill(this.dbWMESDataSet.Station_Configuration);
            // TODO: This line of code loads data into the 'dbWMESDataSet.AnchorsAndGuests' table. You can move, or remove it, as needed.
            this.anchorsAndGuestsTableAdapter.Fill(this.dbWMESDataSet.AnchorsAndGuests);

        }

        private void label3_Click(object sender, EventArgs e)
        {

        }

        private void groupBox2_Enter(object sender, EventArgs e)
        {

        }

        private void stationConfigurationBindingSource_CurrentChanged(object sender, EventArgs e)
        {

        }

        private void dataGridView2_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }
    }
}

Return to Software Developers

Who is online

Users browsing this forum: No registered users and 27 guests