Visual Studio Express

From A-SMIL.org
Jump to: navigation, search

Microsoft Visual Studio Express Editions are the preferred tools for creating digital signage management software over AdAPI SOAP network interface.

Contents

Download

Basic project configuration

To write software for controlling AdAPI devices using Microsoft Visual C# Express, one creates a project for a “Windows Forms Application”:

Creating an AdAPI project from Microsoft Visual Studio

Visual Studio provides a rich application development environment for making Windows-based software. We will illustrate how to link any Visual Studio project to a SMIL player via the Adfotain API (a.k.a. AdAPI).

Session management

Each SMIL player is access protected so a session log-in/log-out is needed for the Adfotain API to properly perform. To create a sample program that links with a player to perform log-in/log-out session management, start by adding a button to the program. See the “button1” control added to the center of “Form1” window.

Minimal UI for testing the session management API

The next step is to import the WSDL definition for the SOAP API. WSDL (Web Service Definition Language) is a W3C standard for specifying software APIs. You can extract it from the “adapi-1_0.wsdl” page which you can import into Visual Studio. From the menu bar, select “Project/Add Service Reference…” to bring up this menu.

Adding Service Reference within Visual Studio to include WSDL definition

Click on the “Advanced…” button to bring up the next dialog box. Then click the “Add Web Reference…” button to reach the following screen.

Adding WSDL as a Web Reference in Visual Studio

In the URL box, enter the file path to the “adapi-1_0.wsdl” file. You should see the following.

Selecting “adapi-1_0.wsdl” file for import as Web Service

In the “Web reference name” entry box, type “Adapi” as the imported class name. You can choose any name convenient to you but for the purpose of illustration we will use this name. After the WSDL is successfully included, a class named “Adapi” will appear in the project tree under the “Web Services” path.

Before we start coding, we need to import one more reference from Microsoft Dot Net library. Go to menu “Project/Add Reference…” and include “System.Net” library. We will need its NetworkCredential, CredentialCache, and CookieContainer classes to talk to the Adfotain API library.

Now we can create code for the button by double-clicking on the button itself. This opens up the code editor for the button1_Click() function. Enter the following code for this function.

private void button1_Click(object sender, EventArgs e)
{
    Adapi.Session session = new Adapi.Session();
 
    System.Net.NetworkCredential credential = new
        System.Net.NetworkCredential("admin", "");
    session.Credentials = credential;
 
    System.Net.CookieContainer cookiejar = new System.Net.CookieContainer();
    session.CookieContainer = cookiejar;
 
    string urlPlayerRoot = "http://player";
    Session.Url = new Uri( new Uri(urlPlayerRoot),
        new Uri(Session.Url).PathAndQuery).ToString();
 
    try
    {
        session.Login();
        MessageBox.Show("Session logged in");
 
        // Do work here
 
        session.Logout();
        MessageBox.Show("Session logged out");
    }
    catch (Exception ex)
    {
        String msg = ex.Message;
        MessageBox.Show(msg);
    }
}

In the sample code above, Adapi is the class that wraps our Adfotain API. It contains the Session class which manages command sessions.

Before one can log-in to a session, one needs to authenticate himself with the media player using the HTTP Authentication protocol. We use the “System.Net.NetworkCredential” classes to carry out HTTP authentication. The default user name for the SMIL player is “admin”, and default password an empty string.

The variable “urlPlayerRoot” needs to be assigned a URL string that resolves to the root URL of the media player. Remember to replace “hostname” with your media player host name or IP (without the final slash). Players default to running SOAP over port 80, so it is not necessary to specify a port in the URL.

In order to maintain session on-top of the HTTP protocol, we need to make use of the HTTP cookie mechanism through the “System.Net.CookieContainer” class as illustrated. After creating a new cookie container, one needs to assign it to the CookieContainer property of the Adapi.Session object “session.”

Before making the Adfotain API calls, make sure the “Url” property of the Adapi.Session object is assigned to point to the URL of your media player. This way SOAP will be able to locate the player and communicate with it.

The main code that calls login() and logout() are placed inside a “try” block so any exceptions from network libraries and HTTP protocol can be caught as they occur.

Uploading files to player

Once you can successfully log-in to a session, you may then use the remainder of Adfotain API classes. The following sample illustrates how to play a dynamically-generated SMIL file using the Adfotain API.

First we wrap the glue logic in a class “AdApiWrapper” to simplify programming.

    public class AdApiWrapper 
    {
        public Adapi.Session Session;
        public Adapi.MediaControl MediaControl;
        public Adapi.ContentManager Contents;
 
        private string m_ServerRootUrl;
        private System.Net.CookieContainer m_SessionCookie;
 
        public AdApiWrapper(string ServerRootUrl, 
                          string UserName, string Password)
        {
            m_ServerRootUrl = ServerRootUrl;
 
            Session = new Adapi.Session();
            MediaControl = new Adapi.MediaControl();
            Contents = new Adapi.ContentManager();
 
            System.Net.NetworkCredential credential = new
                System.Net.NetworkCredential(UserName, Password);
            Session.Credentials = credential;
 
            m_SessionCookie = new System.Net.CookieContainer();
            Session.CookieContainer = m_SessionCookie;
            MediaControl.CookieContainer = m_SessionCookie;
            Contents.CookieContainer = m_SessionCookie;
 
            Session.Url = new Uri(new Uri(m_ServerRootUrl),
                new Uri(Session.Url).PathAndQuery).ToString();
            MediaControl.Url = new Uri(new Uri(m_ServerRootUrl),
                new Uri(MediaControl.Url).PathAndQuery).ToString();
            Contents.Url = new Uri(new Uri(m_ServerRootUrl),
                new Uri(Contents.Url).PathAndQuery).ToString();
        }

The first part of the AdApi is very similar to the earlier code, adding initialization for the MediaControl and ContentManager classes. MediaControl class is used for controlling playback progress, and ContentManager manages files on the player. To play a dynamically generated SMIL file, follow the steps below:

  1. Initiate an AdApi session through Session.Login();
  2. Push the SMIL file (conventionally named “index.smil”) as well as accompanying media files into the media player using the ContentManager.CreateObject() call. The call returns an HTTP URI which you then use to “PUT” the SMIL file into the player;
  3. When uploads are complete, call MediaControl.Play() to play the SMIL script.

The following code segment, which adds to the AdApiWrapper class above, illustrates using the ContentManager API and HTTP PUT mechanism in Visual C#.

        public string PushSmil( string urlTarget, string smil )
        {
            int cbPayload = Encoding.UTF8.GetByteCount(smil);
            byte[] payload = Encoding.UTF8.GetBytes(smil);
            string contentType = "application/smil";
 
            string puturlIndex;
            string objidIndex = Contents.CreateObject(
                urlTarget, contentType, (ulong)cbPayload, DateTime.Now,
                "", "", Adapi.DigestAlgorithm.NONE, 0, null, out puturlIndex);
 
            System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)
                System.Net.WebRequest.Create(puturlIndex);
            req.Method = "PUT";
            req.ContentType = contentType;
            req.ContentLength = cbPayload;
            req.CookieContainer = m_SessionCookie; // to track session
 
            bool bPutOk = false;
            try
            {
                System.IO.StreamWriter writer = new System.IO.StreamWriter(
                    req.GetRequestStream());
                writer.Write(payload);
 
                System.Net.HttpWebResponse resp
                    = (System.Net.HttpWebResponse)req.GetResponse();
                System.IO.StreamReader reader = new System.IO.StreamReader(
                    resp.GetResponseStream());
 
                char[] RespCode = new char[3];
                int cbRead = reader.Read(RespCode, 0, 3);
                bPutOk = (3 == cbRead && (new string(RespCode) == "200"));
            }
            catch (Exception)
            {
                // Ignore exceptions and fail through return code
            }
 
            if(bPutOk)
                return objidIndex; 
            else
                return null;
        }
    }

Given the wrapper class, the code for pushing a dynamically-generated SMIL becomes quite intuitive.

Sending command to play SMIL on player

After uploading the SMIL script (“index.smil”) and accompanying media files to the player, you can issue MediaControl.Play() to start playback of the uploaded SMIL script.

    public partial class Form1 : Form
    {
        private AdApiWrapper m_Toolbox;
 
        public Form1()
        {
            m_Toolbox = new AdApiWrapper("http://player/", "admin", ""); 
 
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                m_Toolbox.Session.Login();
 
                string urlTarget = "file:///user-data/index.smil";
 
                string smil = "<smil><head/><body>" +
                    "<smilText dur=\"10s\">Hello, world.</smilText>" +
                    "</body></smil>";
 
                m_Toolbox.PushSmil(urlTarget, smil);
 
                m_Toolbox.MediaControl.Play("display:0", urlTarget, "");
 
                m_Toolbox.Session.Logout();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }

With the mechanism in place, we can quickly create feature-rich digital signage by creating a powerful content generation engine.

Related