The Back Room

Tag: Flash

Automated Testing of Bar Code Scanners for Flash Museum Installations.

by Bruce on Jul.22, 2010, under Hardware, Software

We have a Flash application that takes an input from a bar code scanner via serial keys in windows. Each time a ticket is read by the scanner, it’s translated into a keyboard input, and that is sent to the Flash application. The application can then analyze the string of characters, validate them through php with a Microsoft SQL database, and return whatever info we need. It’s a good example of integrating Flash with an external input device – the scanner. Although the scanner we’re using requires a few pieces of software to send keyboard command (because of the way it works with the touchscreen), most just emulate a keyboard input when an item is scanned.

Because what we’re making has to work hundreds of times a day, every day, we needed a way to do some solid stress testing. It wasn’t practical to have one of us sit in front of a computer with a ticket and scan it every 5 seconds to make sure that our application and the hardware were functioning properly. So, Charles came up with the idea to trigger a small servo motor to scan a ticket every XX number of seconds. In about two hours, he had the device you see below. It is pretty utilitarian, but  the main function is to just make sure the ticket scans properly, so it doesn’t have to be too sexy. The program is actually a modified version of the servo motor example that ships with the Make Controller that we have used in a few exhibits. The controller is pretty handy for connecting Flash to all sorts of external devices.

We’re not showing the actual program we’re testing, but instead you can see the input from the scanner appear on notepad. It helped us assure that our software could take the continuous input of thousands of scans a day and still be functioning well.

6 Comments :, , , , more...

Using Adobe Flash/AIR for Museum Touch Screen Kiosk Application Development

by Bruce on Nov.20, 2009, under Hardware, Software

If you’ve never developed a touch screen application before, there’s a lot to think about that makes it different from a browser based or native application. It’s impossible to go through the full breadth of things to consider, but I figured posting a few helpful tips might be good.

Well Spaced and Big Button Sensing Areas
So, this does not necessarily mean giant buttons. Often that’s a good solution, since museum visitors are not just those familiar with computers but include many folks who don’t interact daily with computers. Really though, it’s about making sure that the sensing areas of buttons are forgiving enough to work with clumsy fingers, and to account for the different alignment people will get from looking at the screen from different angles. If you touch a screen from a low angle on what you see as the button area, and then change your perspective, that button area can be drastically different from above. A mouse is absolute. The button is the button. But with a fingers on a large screen, it can actually chance. So, large sensing areas for the buttons, and don’t put them too close together to account for different perspectives and clumsy fingers.

Consider Hand Position
When using a touch screen, a person uses their hand, thus creating a natural block for some of the screen area. With a mouse pointer, it’s small enough that unless an interface is very tiny, it won’t block anything when using it to select menu items, etc. But, with a finger, you’ve got a whole hand attached. So, imagine you have a screen where you have 5 buttons. Each button makes a change to a large image in the center of the screen. Although many web pages have navigation and other items at the top, this makes little sense in our scenario, because you want to see how your selection is changing the screen. If the buttons are at the top, you’ll have to move your hand away each time you press one to see the results. It may make more sense to place buttons along the bottom, or the right side. Although it may seem biased, you have to consider that most people are right handed, and if you have to favor one or the other, then choose right. The main thing to get from this one is just to think about where people’s hands are going to be and if they’ll be blocking items you need them to see when operating the screen.

Choose the Best Viewing Angle
This has more to do with fabrication than the software programming. You should make sure you consider who the audience is when choosing what angle and height to put the screen at. It seems like a basic enough idea, but there are many times when we haven’t been involved in the hardware or installation decisions of an institution, and they’ve installed a touch screen for children flat on a table that’s 36 inches high. How can a kid see that properly without standing on something? Or, a kiosk is supposed to take a photo of a person to put on postcard and email home, yet the camera is pointing almost at the floor, so if you’re over 3 feet tall, you’re bending awkwardly and contorting to get in the picture. Little things like this really affect the usability of a screen.

Hide the Mouse
I really don’t understand museum exhibits that have mice showing. I think people leave it there so that you see where you’re clicking and navigating. The thing is, you don’t want people to walk up to a touchscreen and see it as just a computer program running. You want them to walk up and see it as an experience that is something they can’t get at home. You can click on buttons at home, but you can’t touch a screen and move elements around the same way you can on a touch screen. Having the mouse pointer on screen breaks up your interface and reminds people they’re just looking at a computer screen.

Give Clear Direction
An interface must give users clear direction about what to do. Children will walk up to an exhibit and start banging away on the screen and they’ll figure it out. It’s the visitors that are new to touch screens and computer interactive programs that will just stand and stare at the screen, not sure what to do next. Things need to be clearly defined, and text must be readable. Sure, many people won’t read the directions, not matter how much you highlight them, but they need to be able to understand what to do by visual clues. There is a lot that can be written about creating touch screen interfaces, but my overall comment here is make sure people understand what to do.

I’m open to suggestions here, and I am not saying my comments are the be-all and end-all, but we’ve certainly learned a lot from working in this area for years. Some other miscellaneous items to consider:

- There are no rollOver or rollOut commands. Tooltips, highlights, etc. won’t work since it’s just about single touches.
- It’s good to use high contrast colors to make sure it’s visible to as many people as possible
- Choose a type of touch screen technology that works for what you need. (Capacitive, Resistive, SAW, etc.)

Anyone else have any tips?


4 Comments :, , , , , , more...

Slow Loading and Issues Playing mp4 Video Files With Flash and IIS

by Charles on Nov.02, 2009, under Software

If you are streaming mp4 files with Flash or using IIS with mp4 files, it is likely that you may have had a few issues.  The problems normally range from irregular video playback to no playback at all.

Mp4 Files and IIS

IIS 7 (and I assume 6) by default does not have mp4 (or even .f4v) files added to its known MIME types.  This will not allow Mp4 files to playback in your flash applications even if you have implemented them correctly in your code.  In order to fix this, you simply have to add a handler mapping for it.  I will demonstrate how to do this in IIS.

Assuming you have it installed, in Administrative tools -> Internet Information Services (IIS) Manager you will find an icon for MIME Types on the default website selection menu.  Click Add in the top left.  For File name Extension: enter .mp4 and MIME type enter video/mpeg.  After doing this, you should be able to playback the video assuming you don’t have a metadata issue, which I will describe below.

Adding an mp4 MIME Type in IIS7

Adding an mp4 MIME Type in IIS7

The IIS7 Default Website Icons

The IIS7 Default Website Icons

Mp4 Files and Metadata With Flash

When doing video playback in Flash I have always been a huge fan of using Netconnections in conjunction with the Netstream class.  Although this is not as easy as using the FLVPlayback component, I feel like it gives me a lot more control of the video playback.  If you are familiar with using Netstream, you will know that there is a continual event called onMetadata that gets called when starting playback of a video.  I normally use this as a trigger to do things like resize the video.

With mp4 files generated by most video encoding and editing software, you will not receive the onMetadata event until the end of the file!  That means in order to even start playback, your users would have to download the entire video!  This is because the metadata of an MP4 file typically gets stored at the end of the file.  There are a free software tools that you can use to move this metadata to the front and allow the mp4 file to be streamed.

2 Comments :, , , , more...

Delete an XML Node in Flash and other XML tips for Adobe Flash/Air

by Bruce on Oct.16, 2009, under Software

I am not going to make this a huge run-down of how to use XML in Flash, but instead share a few tips I’ve come across while incorporating it into my applications. If you’re looking for a place to start from the beginning and get the basics of using XML with Flash, then I’d go here to kirupa.com

Use a Configuration File

Since we mostly develop stand-alone exhibits for public spaces, there is some basic configuration information that we want in all of our programs and so each application has its own config XML with some standard parameters, and some that are specific to the application. The file we load at the start of each program has a config node, which will hold much of the items we use for every application. It might look like this …

<config>
<timeout>90</timeout>
<attractScreen>attract.swf</attractScreen>
<showMouse>0</showMouse>
</config>

It loads values that the application will use to determine the time the program waits to go to the attract loop, the location of the attract loop file, and whether or not the mouse should be shown at program startup. Another common thing that is done with our config XML is loading any dynamic text into the program, so it’s easy to change this text and it won’t have to be done by a programmer. There’s a text node and it holds a few different items that we may use.

<text>
<intro>Please Choose a category</intro>
<menuInstructions>Now, select a submenu below to start exploring.</menuInstructions>
<outro>Thanks for visiting, we hope you enjoy the rest of your day!</outro>
</text>

It’s important to pull that stuff out of the code and into easily configurable external files. It’s very common to have a client call and let you know that they think wording should be changed, or that the timeout happens too fast on a particular exhibit, and the ability for that change to be made by them is valuable.

Deleting an XML Node

So, to add a node to an existing XML instance in Flash, the most basic function is appendChild(). If you have two variables holding XML, and want to add one to the other, it could be as simple as …

myXML.appendChild(myXML2.copy());

This will vary depending on what you want to do specifically, but that’s the basic idea. So, if you want to delete a child from XML, you’d think you would just use a function like removeChild() or deleteChild(). Sorry, that’s not how it works. You actually have to use the fairly odd delete command. And, it doesn’t even get values fed like a regular function. If you had your XML that held photo nodes and wanted to delete the second item, it would look like …

delete myXML.photo[1];

It is not intuitive at all, and I am sure there is some reason it’s done that way based on the object model and available functions in the different classes, but it’s still a bit difficult to figure out.

Creating XML in Flash

For some applications, you may want to create a variable that holds XML for whatever reason. Now, if you’re just making a copy of or adding to some existing XML, it’s pretty straightforward. But, if you create the XML from scratch, there’s one important step that if you skip, will cause your XML not to work properly. You have to create a top level <data> node in it to hold your child nodes. If you don’t do that, it may not act as it should. So, if I am doing some sort of searching or sorting, and want to create a brand new XML that holds photo nodes from another XML document that fit certain search criteria, I can’t just say …

var newXML:XML = new XML();
newXML.appendChild(photoXML.photo[2]);
newXML.appendChild(photoXML.photo[5]);
//try to trace out the new XML, but you’ll see nothing
trace(newXML);

What you have to do is create a <data> tag when you make that new XML, so that it will have a node to append the children to. So, instead try …

var newXML:XML = <data></data>
newXML.appendChild(photoXML.photo[2]);
newXML.appendChild(photoXML.photo[5]);
//Now you’ll see the new XML nodes reflected
trace(newXML);

So, make sure you create that top level to allow items to be manipulated with code.

1 Comment :, , more...

Flash Video Smoothing FLVs with ActionScript 3

by Bruce on Sep.09, 2009, under Software, Web

On more than one occasion, I’ve needed to allow smoothing of video in my Flash projects. Of course, it’s always best to compress video to being the size that you need, but if you want to allow any zoom effects on the video, allow the user to resize it, or maybe create a low-res version for use on the web, you’ll need to enable smoothing on the video. The performance takes a hit, since the computer playing back the content needs to do some math to make the video look good, but if you’re in a controlled environment, or have a reasonable idea of the audience’s install base, then smoothing is a viable option. I’ll mention two methods of playing back video – using the NetStream class, and using the FLVPlayback class. They each require a different method to enable the smoothing.

The NetStream is streaming at its most basic. You create a connection and stream the content. It takes more code to create the netstream (rather than using an FLVPlayback component that’s on the stage already), but it’s a little more clear how to smooth the video, since you just set the smoothing property of whatever your video is true. Here’s how you might stream something with NetStream, with the smoothing part added.


var video:Video = new Video();
var nc:NetConnection = new NetConnection();
var ns:NetStream;
//
//Call the function below
startVideo();
//
//This function adds the video elements
function startVideo(){
//Add the video to the stage
addChild(video);
//
//connect the netStream/netConnection with the video
nc.connect(null);
ns = new NetStream(nc);
ns.client = {onMetaData:ns_onMetaData, NetStatusEvent:ns_onPlayStatus};
video.attachNetStream(ns);
ns.play("YOUR_VIDEO.flv");
//
//Start with video being smoothed
video.smoothing = true;
}
//
function ns_onMetaData(_data:Object){
//put stuff here if you want.
}
//
function ns_onPlayStatus(e:NetStatusEvent){
//put other stuff here if you want.
}
//
//See the difference between video being smoothed and not smoothed by
//pressing "s"
stage.addEventListener(KeyboardEvent.KEY_DOWN, checkKey);
function checkKey(e:KeyboardEvent):void{
if (e.keyCode == 83){
video.smoothing = !video.smoothing
}
}

So, that’s if you use NetStream to add your video. If you have an FLVPlayback component on your stage, then you have to first extract the video stream from it, and then you can apply smoothing to that. You can’t just set a property of the FLVPlayback, since none exists for smoothing.

function smoothVideo(){
var myVideo = FLVPlayback_Instance.getVideoPlayer(0);
myVideo.smoothing = true;
}

Turn the smoothing on and off in the example below to see the effects.

You can see very clearly the difference in the details of the ships and in how smooth the text edges look. Performance does take a slight hit, but it's hard to see in this small video if you have a decent machine. Anyway, there are a few other sites out there that mention this, but I was dealing with it the other day, and thought a good before/after video example would be good.

Leave a Comment :, , , , more...

A Few Ways of Getting Data From PHP Into Flash

by Charles on Aug.28, 2009, under Software

An Example of a Flash image viewer inside html

An Example of a Flash image viewer inside html

I have recently been working on a web project that requires getting data from a database and loading it into a flash application that is embedded within a php-based web-page.   My weapon of choice for this project has been including the data in a flashvar inside the embed code.  There are two other methods that I wanted to highlight in this article as well.  So to summarize I will be highlighting the following methods of getting data into a web-embedded flash application.

  1. Use the server-side language to place your data inside a flashvar in the embed code
  2. Have flash do a URLRequest to a server-side script that returns straight xml/plaintext..etc
  3. Have flash do a URL Request straight to a html page and parse the html!

Using the server-side language to place your data inside a flashvar

Because a server-side languages like ASP or PHP runs before any of the client side scripts of a web-page are loaded, you can use it throughout a page to insert data wherever you want; even in the <head> section of the html.  So what I am doing in the latest web project I am working on is using a php function to print a large chunk of database extracted text directly into the embed code.  Let’s take a look at the embed code.  I am using the popular swfobject script too.


<script type="text/javascript">
var flashvars = {};
flashvars.photoDataInput = "<?php echo( $TrailController -> Get_XML_For_Flash() );?>";
var params = {};
var attributes = {};
swfobject.embedSWF("FlashImageViewer.swf", "myAlternativeContent", "800", "560", "9.0.0", false, flashvars, params, attributes);
</script>

The magic part is down in the script that includes the “FlashImageViewer.swf”.  See the line that is “flashvars.photoDataInput=”<?php echo( $TrailController -> Get_XML_For_Flash() );?>”;”  This function inside of my php script will actually print out a HUGE string of xml that I read into my flash application then cast to xml.  Lets view the source of the page so you can see what I mean:

dataintoflash2

In the source I have highlighted the xml that php is printing.  An excerpt is: “<VRTrail><config><photos><singlePhoto><path>http://localhost/g2OCTAAug2009/g2data/albums/Wyoming/Independence_Rock/Media/Location/Ind_rocktouristsIMG_7260.jpg</path><caption>Vi”.

So how do we get this inside of the flash application?  Inside of the main class of the flash image viewer I have a function that loads the flashvars variable:

private function loadFlashVars():void {
var tmpObj:Object = LoaderInfo(this.root.loaderInfo).parameters;


if( tmpObj["photoDataInput"] != undefined) {
PhotoXML = XML(tmpObj["photoDataInput"]);
}
}

See how I am casting it to XML?  I can then use the great xml parsing in Actionscript 3 to take care of loading the photos!

Have Flash do a URL Request to a server-side script that outputs straight xml
This is a fundamental principal of how Asynchronous JavaScript programming (AJAX) works on the web.  You can also use flash to do it as well.  However, if you do it this way, search engines wont have an opportunity to index your content.

Have Flash do a URL Request Straight to a html page and parse the html
Based on my previous work in SEO, and from what I have read, it really seems like this is the best way to load data into flash on the web; although it can be a bit annoying at times.  Let me give you an example too.  On the In Pursuit of a Dream Movie site, the “Now Showing” page actually uses this technique to load the show times!  Take a look at the flash site:

In Pursuit of a Dream Now Showing Site

In Pursuit of a Dream Now Showing Site

You’re going to need to disable meta redirection to look at this.  Now, take a look at this URL: http://www.octa-trails.org/In-Pursuit-of-a-Dream/Now-Showing.html If you happen to stumble on this page through a search engine, you’ll be auto-redirected to the index where the flash application is.  Now, how do we parse the html in Flash?

dataintoflash4

The secret is to actually transform the html into XML!  You can do this by removing everything above and below the body tags.  This is the Actionscript 3 function that I use to parse the html on the now showing page AFTER I have extracted everything between the html <body> tags.

/*
* DATE: 7/13/2009
* AUTHOR: Charles Palen
* NAME: parseForNowShowing
* DESCRIPTION: Call this to parse for the Now-Showing.html page.  Inserts all the parsed items into the array
* Now showing page has the following html format
*     <h2>March 12-14, 2010
Great Western Film Fest</h2>
<h3>Wrangler Hall
23 Fordham Street
Somewhere, Ohio 01772</h3>
<a href=”http://www.bostonproductions.com”>Visit website for more info</a>
*
*
*     <h2>October 25, 2009
7:30PM
WGBH – American Experience</h2>
<a href=”http://www.fileplanet.com”>Visit website for more info</a>
*
* May or may not contain a h3, h2, AND link
*/
private function parseForNowShowing(_InputString:String):void {
var convertedXML:XML = new XML(_InputString);

// These get used over and over as we parse
var MainHeadline:String;
var OptionalSubHeading:String;
var OptionalLink:String;
var OptionalLinkURL:String;

for each(var container:XML in convertedXML.div) {

// Blank everything for each round
MainHeadline = “”;
OptionalSubHeading = “”;
OptionalLink = “”;
OptionalLinkURL = “”;

for each(var heading:XML in container.h2) {
MainHeadline = heading.text()[0].split(”\r\n”).join(”\n”);
}

for each(var subHeading:XML in container.h3) {
OptionalSubHeading = subHeading.text()[0].split(”\r\n”).join(”\n”);
}

for each(var link:XML in container.a) {
OptionalLink = link.text()[0].split(”\r\n”).join(”\n”);
if (link.attribute(”href”) != “”) {

OptionalLinkURL = link.attribute(”href”);
}
}

var TmpTextField:TextField = new TextField();
TmpTextField.selectable = false;
TmpTextField.embedFonts = true;
TmpTextField.antiAliasType = AntiAliasType.ADVANCED;

var HeadlineFormat:TextFormat = new TextFormat();
HeadlineFormat.size = 12;
HeadlineFormat.bold = true;
HeadlineFormat.font = HeadingFont.fontName;
HeadlineFormat.color = 0xFFFFFF;

var SubHeadlineFormat:TextFormat = new TextFormat();
SubHeadlineFormat.size = 9;
SubHeadlineFormat.color = 0xFFFFFF;
SubHeadlineFormat.font = SubHeadingFont.fontName;

var OptionalLinkFormat:TextFormat = new TextFormat();
OptionalLinkFormat.size = 9;
OptionalLinkFormat.color = 0xFFFFFF;
OptionalLinkFormat.font = SubHeadingFont.fontName;

var currentSize:int = 0;

// Append and format the main headline
if(MainHeadline != “”) {
TmpTextField.appendText(MainHeadline);
TmpTextField.setTextFormat(HeadlineFormat, 0, TmpTextField.length);
}

// Append and format the Optiona SubHeading
if (OptionalSubHeading != “”) {
currentSize = TmpTextField.length;
TmpTextField.appendText(”\n” + OptionalSubHeading);
TmpTextField.setTextFormat(SubHeadlineFormat, currentSize, TmpTextField.length);
}

//Append and format the OptionalLink
if (OptionalLink != “”) {
currentSize = TmpTextField.length;
TmpTextField.appendText(”\n\n” + OptionalLink);
TmpTextField.setTextFormat(OptionalLinkFormat, currentSize, TmpTextField.length);
}

HoldingArray[0].push(TmpTextField);
HoldingArray[1].push(OptionalLinkURL);

// If the element had a link make it clickable
if (OptionalLinkURL != “”) {
addLinkClickListenerToItem();
}
/*
trace(”—– ROUND ————”);
trace(”Main HL:” + MainHeadline);
trace(”Optional HL:” + OptionalSubHeading);
trace(”Optional Link:” + OptionalLink);
trace(”Optional Link URL:” + OptionalLinkURL);
*/
}

// Parsing finished notify people data is ready
notifyDataIsReady();
}

1 Comment :, , , , more...

Unconventional Flash Testing Methods for Real World Applications

by Charles on Apr.21, 2009, under Electrical Engineering, Software

A pannel of lights being controlled via ethernet

A panel of lights being controlled via ethernet

In relation to the line of work we are in, our Flash applications don’t normally fit into the mainstream web application paradigm.  Often we interface with special hardware, touch screens, and systems with more than one monitor in non-standard orientations.  We also have to ensure that our applications can run non-stop for a minimum of a full day and potentially seven days a week.

One of the Many Test Setups

One of the Many Test Setups

In order to try and simulate the final production environment, when developing software; Bruce and I like to test applications on the hardware it will be run on in situ for several days at a time.  On one corner of the desk that I work at, we have a big three touch screen configuration that we often hook machines into for testing.

Monitoring the Hardware Using a Webcam

Monitoring the Hardware Using a Webcam

Recently while testing large touch screen monitors, the company pool table was occupied for several days with 40-inch vertical monitors and their associated computers.

For situations requiring interaction with hardware such as a telegraph, we will often isolate the piece of hardware in our studio and run it for days while controlling it via the local network.  A cool way of monitoring the hardware being tested in the studio from our office in the backroom is to use a webcam and Red5.  In the images I am using Red5s sample broadcast and subscriber applications.

Leave a Comment :, , , more...

Adobe Flash and Director

by Bruce on Apr.06, 2009, under Software

flash_vs_directorWhen I started developing interactive exhibits for museums and other institutions, everything was done in Macromedia Director. Flash was there, but it only could do some animations and only very light interaction. Director could do it all, connect to printers, interact with databases, play video, etc. So, for years it was all Director, all the time. But, a few years ago, we came to the realization that Flash had grown enough to start using it for some exhibits, and it actually became necessary for others, where the program might need to be put online as well. Sure, Director can publish to Shockwave, but the installed base is much lower than Flash, and it came with a few bumps, like a mandatory form to fill out on Macromedia’s site with contact information. Flash had a seamless installation and an installed base of over 98% of all web users. Director had failed to see an update in years, and was starting to lose the developers who helped make it the powerhouse it was. So, when I got a project that needed database integration that might need to also live online, I made the switch, and I have really never gone back.

Sure, Director is better at some stuff than Flash. Without making this all about a side by side comparison, it integrates with the operating systems better, allowing easy file writing, connections to external devices (something we do often) and more options on how it displays itself on a system. We solved that here by using small pieces of software to allow Flash to connect to what we need it to. For instance, a recent installation included multiple mice, a serial connection to the museum control system, and a connection to a network server to allow communication among 5 systems. Director was not involved at all, and the system works very well. The overall performance and graphics rendering is better than what I believe we would have gotten with Director.

Director has just come out with its latest version, 11.5. It does add some new features, but unfortunately does not deal with many of the things that cause us to move away from it in the first place. First of all, it has no support for ActionScript 3.0. This is what we write all of our Flash projects in, and is a necessity if we wanted to integrate some of those components into a project. It also maintains a layering system that when using multiple layers of buttons and graphics, becomes unwieldy. There is nominal improvement in graphics playback, but many of the Xtra developers have stopped developing plug-ins because of the general lack of interest in the software. It is good for some 3-D game development, as well as supporting direct use of a number of different media types like QuickTime, WAV files, Mpegs, etc. Flash is fairly limited in this regard to a few media types that it can handle and many file types must be converted to be used. Flash recently introduced support for .h264 encoded video, which we use for most of our encoding now, so that has been a big plus.

Using Flash for the bulk of our programs allows us to post interactive exhibits for easy previewing in the browser, to post online versions of exhibits much quicker and to a broader audience, and to develop, if we need to, completely open source with Flex and other available tools. I have been happy with what we’ve produced for the industry with Flash, and particularly happy with how we’ve been able to integrate with a number of pieces of software and hardware. The introduction of Adobe AIR development has added a lot of tools that Director brought to the table. You can write files, have embedded web browsers, control some interaction with the operating system, etc.

Overall, we still use Director occasionally, but it looks like the development of it as a software platform is gravitating more towards gaming and 3D. For the foreseeable future, we’ll be using Flash as the front end for the bulk of our programs, but it’s all about the user experience, so if there is something that comes along that helps us improve that, we’ll take a look at it.

Leave a Comment :, , more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...