How to: Make a Screen Saver that Plays Movie Trailers? (Easter Egg Included in ...

:

Introduction

I decided to build a screensaver that plays movie trailers. The purpose was to learn about how screensavers worked and build a random movie trailer screensaver. The code pulls the trailers from the trailer API at http://api.traileraddict.com. I chose trailer addict because the XML for retrieving movie trailers was simple. In addition, I have an Easter egg in my original code which I am leaving out of this article to help make it brief and easily manageable. However, the executable does include an Easter egg, so feel free to try it out.

Making/Coding Screen Saver Form

For this article, I have named the screensaver form: frmScreenSaver. The following properties are important to set and need to be set for frmScreenSaver:

  1. FormBorderStyle - None
  2. WindowsState - Maximized (after you finishing debugging the screensaver)
  3. MinimizeBox - False
  4. MaximizeBox - False
  5. ShowInTaskbar - False (can set to true during debugging)

In addition, the Shockwave Flash component needs to be added to frmScreenSaver (can be added to the toolbox via COM component tab in Choose Toolbox Items Dialog) and resized to fit onto the whole form. frmScreenSaver is shown in Dialog 1 below with the Shockwave Flash Object added.

Dialog 1 - frmScreenSaver with ShockWave Flash Object

In Figure 1, the screensaver form code below first loads the option information from an XML file (will show code for saving/loading XML file later below). Next, it proceeds to adding a timer interval of 500 ms to the timer on the form so that the first trailer will load fast. The formsize variable below was used to make the trailer automatically size to fullscreen after debugging of the application was finished. Then, the timer is started and the loaded options are checked for the timer interval. If no interval is selected, the default is 60 secs (60000 ms). Third, a random movie trailer is pulled from a collection of 6 from the category set in the options form and the trailer is supposed to start playing automatically (I was having trouble playing the trailer automatically with trailer addicts API). Finally, the key press events are added to allow an escape key to be pressed to escape the screensaver (oddly, mouse capture events do not work with the flash ActiveX control or I might have used them improperly).

Figure 1 - frmScreenSaver code

Public Class frmScreenSaver
    Private FirstTrailer As Boolean  

    Private Sub frmScreenSaver_Load(sender As Object, e As EventArgs) Handles Me.Load

        myoptions.LoadOptions()
        'have the first trailers timer be low so it will start playing quicker
        TrailerRotateTimer.Interval = 500
        TrailerRotateTimer.Stop()
        Dim formsize As Size
        formsize.Height = Me.Size.Height
        formsize.Width = Me.Size.Width
        Video.Size = formsize
        Video.AllowFullScreen = True
        Video.Visible = True
        TrailerRotateTimer.Start()
    End Sub   

    Private Sub TrailerRotateTimer_Tick(sender As Object, e As EventArgs) _
		Handles TrailerRotateTimer.Tick
        If FirstTrailer = False Then
            Select Case myoptions.TrailerPlayTime
                Case Is = 60
                    TrailerRotateTimer.Interval = 60000
                    FirstTrailer = True
                Case Is = 90
                    TrailerRotateTimer.Interval = 90000
                    FirstTrailer = True
                Case Is = 120
                    TrailerRotateTimer.Interval = 120000
                    FirstTrailer = True
                Case Else
                    TrailerRotateTimer.Interval = 60000
                    FirstTrailer = True
            End Select

        End If
        Dim randnum As New Random()
        Dim firstvideo As String = myoptions.TrailerUrlCollection.Item(randnum.Next(0, 5))
        ' Video.Movie = firstvideo
        Video.Stop()
        Video.LoadMovie(0, firstvideo)

        If Video.IsPlaying = False Then
            ' Video.Playing = True
            Video.Play()
            Video.Playing = True
            Video.Loop = False
        End If
    End Sub
    Private Sub frmScreenSaver_KeyPress(sender As Object, e As KeyPressEventArgs) Handles Me.KeyPress
        If e.KeyChar <> "" Then
            Application.Exit()
        End If
    End Sub
    Private Sub Video_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) _
		Handles Video.PreviewKeyDown
        If e.KeyCode = Keys.Escape Then
            Application.Exit()
        End If
    End Sub
End Class

Making/Coding frmOptions

frmOptions was easy to code and only had five controls: two labels, a combobox named cboGenre, another combobox named cboPlayTime, and a button named BtnSave. Dialog 2 provides a preview of what frmOptions looks like.

Dialog 2 - frmOptions

Figure 2 shows how the load code loads the options and selects the option already set previously in the XML file. In addition, it shows the code for the BtnSave click event which calls RetrieveVideos which retrieves 6 videos from the API service, retrieves the pause time in-between screensavers, and saves the information to an XML file.

Figure 2 - frmOptions code

Public Class frmOptions
    Private Sub frmOptions_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        myoptions.LoadOptions()
        If myoptions.VideoGenreSelection <> "" Then
            cboGenre.SelectedIndex = cboGenre.Items.IndexOf(myoptions.VideoGenreSelection)
        Else
            cboGenre.SelectedIndex = 0
        End If
    End Sub

    Private Sub BtnSave_Click(sender As Object, e As EventArgs) Handles BtnSave.Click
        myoptions.IsTransparent = False
        If cboGenre.SelectedIndex > -1 Then
            myoptions.TrailerUrlCollection = ProgramServices.RetrieveVideos_
			(cboGenre.Items.Item(cboGenre.SelectedIndex))
            myoptions.VideoGenreSelection = cboGenre.Items.Item(cboGenre.SelectedIndex)
            If IsNumeric(cboPlayTime.Text) Then
                myoptions.TrailerPlayTime = CInt(cboPlayTime.Text)
            End If
            myoptions.SaveOptions()
            Me.Close()
        Else
            MsgBox("need to have a genre selected!")
        End If
    End Sub
End Class

Retrieving Videos from TrailerAddict

Now, we actually show how the videos are retrieved from Trailer Addicts movie trailer service. I created a class called ProgramServices and a Shared Function called RetrieveVideos to retrieve the trailers from trailer addict. This line:

Dim url As String = "http://api.traileraddict.com/?actor=" + genre.ToLower + "&count=6"

retrieves the XML that contains the 6 different trailer urls. To try out different options, go to http://www.traileraddict.com and play with it (look for the gears icon that has a tool-tip with API in it to see the url you can use to get your result). I used actor because it allows me to separate out the trailers by genre. The rest of the code in Figure 3 retrieves the trailer id of each trailer which I add to a variable called templst and return to be saved in the XML options file. Note: This section of code with the address automatically returns the SWF player for each trailer: http://v.traileraddict.com/emd/

Figure 3 - ProgramServices class

Imports System.Net
Imports System.Text
Imports System.IO
Public Class ProgramServices

    Public Shared Function RetrieveVideos(genre As String) As List(Of String)
        Dim templst As New List(Of String)
        'retrieve top 4 videos and add them to the list
        Dim url As String = "http://api.traileraddict.com/?actor=" + _
        genre.ToLower + "&count=6"
        Dim req As HttpWebRequest = WebRequest.Create(url)
        Dim resp As HttpWebResponse = req.GetResponse()
        Dim enc As Encoding = System.Text.Encoding.GetEncoding(1252)
        Dim loResponseStream As StreamReader =
        New StreamReader(resp.GetResponseStream(), enc)
        Dim Response As String = loResponseStream.ReadToEnd()
        Dim xmlfile As XDocument = XDocument.Parse(Response)
        Dim videos As IEnumerable(Of XElement) = From t In xmlfile.Descendants("trailers") Select t
        For Each video As XElement In videos
            For Each trailer As XElement In video.Elements("trailer")
                templst.Add("http://v.traileraddict.com/emd/"+_
                trailer.Element("trailer_id").Value+"?id=" + _
                trailer.Element("trailer_id").Value)
            Next
        Next
        loResponseStream.Close()
        resp.Close()

        Return templst
    End Function

End Class

Saving/Opening from/to Options XML file

Saving to the options XML file is easy. I reference some code from this article for saving to the XML file but changed some code to make it applicable for my scenario: http://www.devasp.net/net/articles/display/566.html. Figure 4 shows the whole code for saving to the XML file. I would go into explaining the whole thing but looking at it, most of it is self explanatory. However, to help people better understand the code, there are some important things to mention:

My settings file is named settings.opt and will be created/loaded from wherever the screensaver is placed, m_VideoTrailerUrl is the list of movie trailer urls that are retrieved from trailer addicts API (in string format), and m_GSelection is the genre selection (defaults to Sci-fi), and m_TrailerPlayTime is the time each trailer has to play (defaults to 60 seconds).

Figure 4 - Options Class code

Option Strict On

Imports System.Xml.Serialization
Imports System.Xml
Imports System.IO
<serializable> Public Class Options

    Private m_VideoTrailerUrl As List(Of String)
    Private m_IsTransparent As Boolean = True
    Private m_GSelection As String = "Sci-fi"
    Private m_TrailerPlayTime As Integer = 60
    ' Set the OptionsPath to the current location with a fixed file name.
    Private OptionsPath As String = Application.StartupPath & "\settings.opt"

    ' This property returns whether the screen saver should use transparency
    '   when drawing the shapes to the screen.
    Public Property IsTransparent() As Boolean
        Get
            Return m_IsTransparent
        End Get
        Set(ByVal Value As Boolean)
            m_IsTransparent = Value
        End Set
    End Property

    ' This property returns what genre video to retrieve from the trailer service.
    Public Property VideoGenreSelection() As String
        Get
            Return m_GSelection
        End Get
        Set(value As String)
            m_GSelection = value
        End Set
    End Property
    Public Property TrailerPlayTime As Integer
        Get
            Return m_TrailerPlayTime
        End Get
        Set(value As Integer)
            m_TrailerPlayTime = value
        End Set
    End Property

    ' This property returns what speed the screen saver should use 
    '   when drawing to the screen.
    Public Property TrailerUrlCollection As List(Of String)
        Get
            Return m_VideoTrailerUrl
        End Get
        Set(ByVal Value As List(Of String))
            m_VideoTrailerUrl = Value
        End Set
    End Property

    ' --- Class Methods ---

    ' This function returns 'true' if the options file exists, 'false' otherwise.
    Public Function IsOptionFileExisting() As Boolean
        Dim myIO As New System.IO.FileInfo(OptionsPath)
        Return myIO.Exists()
    End Function

    ' This function loads the user defined options.  First, it checks to see
    '   if an options file exists. If it does, the options are loaded from it.
    '   If the file doesn't exist, one is created with the defaults.
    Public Sub LoadOptions()

        Dim myOptions As New Options   ' An Options object to use

        ' Check to see if an Option file exists, if so, load it!  Else
        '   create one.
        If myOptions.IsOptionFileExisting() Then

            ' Load the options
            ' Create an XmlSerializer to use for retrieving options values
            Dim mySerializer As New XmlSerializer(GetType(Options))
            ' Create a StreamReader to point to the options file
            Dim myTextReader As New StreamReader(OptionsPath)
            ' Create an XmlTextReader to actually read the options.
            Dim myXmlReader As New Xml.XmlTextReader(myTextReader)

            ' First verify that the file can be deserialized into an Option
            '   object format.
            If mySerializer.CanDeserialize(myXmlReader) Then
                ' Deserialize the object
                myOptions = CType(mySerializer.Deserialize(myXmlReader), Options)
            Else
                ' Save a new Options file
                myOptions.SaveOptions()
            End If

            ' Close the IO objects we've used.
            myXmlReader.Close()
            myTextReader.Close()

            ' Set the properties for this Options object to those retrieved
            '   from the file (or else use the defaults from the temporary
            '   Options object, if the file could not be deserialized).
            Me.m_GSelection = myOptions.m_GSelection
            Me.m_IsTransparent = myOptions.IsTransparent
            Me.m_VideoTrailerUrl = myOptions.m_VideoTrailerUrl

        End If
    End Sub

    ' This function saves the user defined options to disk.
    Public Sub SaveOptions()

        ' Create a stream writer to overwrite any files currently there, so that
        '   the fresh options can be saved.
        Dim myWriter As New System.IO.StreamWriter(OptionsPath)

        ' Create an XML Serializer to serialize the object
        Dim myXmlSerializer As New XmlSerializer(Me.GetType())

        ' Serialize the current Options object (Me) to disk.
        myXmlSerializer.Serialize(myWriter, Me)

        ' Close the writer.
        myWriter.Close()

    End Sub

End Class

Other Related Articles