Introduction
The idea of presenting media on a screen using mobile phones and QR-codes came up during a brainstorm meeting. There was a need to visualize information of our projects in some interactive way. With information and QR-codes printed on traditional paper sheets together with an interactive flat screen, the result would probably give the visitor some extra curiosity.
An example of an application is a screen connected to a computer with the
server application below. On the server you put four different movies.
Under the screen you put four QR-codes corresponding to each movie. The
visitor can then scan the QR-code with his/her mobile phone and start
the corresponding movie on the screen.
To achieve this the server side would need some HTTP web server that listens
for HTTP calls and open a file or application locally on the server. The server
is then connected to a screen where the chosen
application/movie/picture/presentation is shown. The only information possible
to store in a QR-code and usable for this purpose is a
URL string. Therefore the HTTP server has to be able to open files provided in a URL string, using the REST architecture.
The HTTP has also to be started by an active computer user. If this would be implemented as
a service it would not be possible to show anything on a normally configured screen connection in Windows.
The big pros with this approach is that QR-cdes can easily be read by a mobile phone that you always have
available. In an exhibition you often want to interact with the system,
extra hardware for integration is expensive. Instead you can use your
visitor's mobile device as the tool. The only thing you would need is to buy a cheep computer and connect
that to a fancy screen. Then you let your visitors scan QR-codes to
answering questions, start movies, start presentations, or whatever.
The files that are allowed to be opened are defined in the code as a folder. To open a file in the folder the file name is provided within the arguments provided in the
HTTP REST call, e.g.,
http://Myserver:8080/?file=openme.txt.
Using the code
The code is simple and configurable depending on how you want to show your files. For movies and PowerPoint, I send arguments to expand the media to full screen. Please refer to the specific software manual to get the know
of how to interact with the software.
To create a QR-code that will be used for starting an application you use any QR-creator available on
the internet, e.g.,
http://qrcode.kaywa.com/. For the connection string you need the
address or IP to the server, the port used, and the file or homepage to show on
the server-side,
i.e.: http://your-address:your-port/?file=your-file.
To start the server side application you start the exe file in administration mode (needed to listen to ports, at least for me). The default port is 8080 and is changed either in the code or by giving the port as an argument.
E.g., create a shortcut and specify the port in the command field for the shortcut properties.
I added support for steaming videos to the requesting device. This is done by adding the argument
local=true to the REST call,
i.e., http://your-address:your-port/?file=your-file&local=true.
The Code
The main loop basically starts a HttpListener
and answers all calls by calling
StartProgram
with the file provided in the REST argument and responds by "Started" or an exception if the file did not exist or any exception occured.
private static string httpfilesource = "http://desenergy.selfip.org/";
private static string filefolder = "C:\\Videos\\";
private static void Main(string[] args)
{
var server = new HttpListener();
int port;
if (args != null && args.Length > 0 && int.TryParse(args[0], out port))
server.Prefixes.Add(@"http://*:" + port + "/");
else
server.Prefixes.Add(@"<a href="http:
while (true)
{
server.Start();
HttpListenerContext context = server.GetContext();
NameValueCollection query = context.Request.QueryString;
bool local = false;
string file = query["file"];
if (query["local"] != null)
local = "true".ToLowerInvariant() == query["local"].ToLowerInvariant();
string exc = "";
string responseString = "";
try
{
if (file != null)
{
if (local)
{
responseString = "<HTML><BODY><video width=\"320\" height=\""
+ "240\" controls=\"controls\">"
+ "<source src=\"" + httpfilesource + file
+ "\" type=\"video/ogg\" />"
+ "Your browser does not support the video tag."
+ "</video></BODY></HTML>";
}
else
{
StartProgram(filefolder + file);
responseString = "<HTML><BODY> Startad </BODY></HTML>";
}
}
}
catch (Exception e)
{
exc = e.ToString();
}
HttpListenerResponse response = context.Response;
if (exc != "")
responseString = "<HTML><BODY> Exception =" +
exc + " </BODY></HTML>";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
}
}
The next step is to implement the StartProgram
function.
Files provided to the StartProgram
function are by default executed by the server. Windows file association will take care of how to execute the file. However, in this implementation
I need to start some files in full screen, e.g., start movies, PowerPoint, WordFiles, and homepages in full screen from start.
To achieve the full screen the application sends start argument to the actual application itself. The arguments send depend on the application used, but the actual document or media is always provided as one of the arguments.
The default program for special programs is defined in constant strings. Be aware that the strings to open specific programs differ from installation to installation. If you want a more rigid design you can access the
Registry to get the file folders.
The method basically first cleans the filename for some problems with Nordic letters, then analyses the string and starts it with the correct application. If there is no default application for the file type,
the application tries to start the file itself.
private const String Reader = @"C:\Program Files (x86)\Adobe\Acrobat 10.0\Acrobat\Acrobat.exe";
private const String Explorer = @"C:\Program Files (x86)\Internet Explorer\iexplore.exe";
private const String PowerPoint = @"C:\Program Files (x86)\Microsoft Office\Office14\POWERPNT.EXE";
private const String WinWord = @"C:\Program Files (x86)\Microsoft Office\Office14\winword.exe";
private const String WMPlayer = @"C:\Program Files\Windows Media Player\wmplayer.exe";
private static void StartProgram(string s)
{
string file = String.Copy(s);
if (file != null)
{
file = file .Replace("ö", "ö");
file = file.Replace("ä", "ä");
file = file.Replace("Ã¥", "å");
}
string t;
try
{
t = file.Remove(0, file.LastIndexOf(".", StringComparison.Ordinal));
}
catch
{
t = s;
}
if (file.StartsWith("http://"))
{
StartProcess(Explorer,
"-k " + "\"" + file + "\"");
}
else
{
switch (t.ToLowerInvariant())
{
case ".ppt":
case ".pptx":
StartProcess(PowerPoint,
"/S " + "\"" + file + "\"");
break;
case ".doc":
case ".docx":
StartProcess(WinWord,
"/fullscreen " + "\"" + file + "\"");
break;
case ".mpg":
case ".mpeg":
case ".mp4":
case ".avi":
case ".ogg":
StartProcess(WMPlayer,
"\"" + file + "\"" + " /fullscreen");
break;
case ".pdf":
StartProcess(Reader,
"\"" + file + "\"");
break;
default:
StartProcess(file, null);
break;
}
}
}
The last part closes the previous process and and starts the new one. The previous process is stored in a static field and can
therefore be closed before the next process is started.
private static Process _process;
private static void StartProcess(string program, string argumentfile)
try
{
if (_process != null)
_process.CloseMainWindow();
}
catch (Exception)
{
}
_process = new Process
{
StartInfo =
{
FileName = program,
Arguments = argumentfile,
WindowStyle = ProcessWindowStyle.Maximized
}
};
_process.Start();
}
Points of Interest
If you do not want to open up your computers to the outside world you can have an open wireless network that provides the only way to connect to servers.