The appearance of nearly every aspect of DWJukebox is controlled by a skin file. The skin file is a simple text file that contains pointers to all images used by a skin, the definition of the control scheme used for the jukebox, the definition of the output style of the jukebox, and definitions for any interactive elements such as displays, indicators, buttons and sounds.
At this point, I have put my time into trying to finish the jukebox, so I have not written a skin builder. Fortunately, building a skin is not that hard. Things to remember:
- All coordinates and measurements are relative to the background image, not the actual resolution. - Pixels in the background image are always assumed to be square; they will be corrected for the aspect ratio of the monitor, resolution and orientation at runtime to stay square.
Designing a skin comes down to:
- Selecting the background image - Set the selection method and range of selection keys - Set the location, size, color, and number of lines of the displays (or disable them) - Define the appearance of the titlestrips - Define the size and location of one or more grid(s) of titlestrips - Define any interactive icons - Define any sounds.
Basic skins are very easy. Here, for example, is the classic.skn with the comments stripped out to make it shorter:
[skin] background=bgclassc.jpg [Selection] SelectionMethod=Alphanumeric UseZero=False HighLetter=D HighNumber=4 [Display1] # Now Playing display enabled=True x=157 y=202 w=282 h=80 lines=4 color=palegreen bgcolor=black [Display2] # Song List display enabled=True x=595 y=202 w=282 h=80 lines=4 color=palegreen bgcolor=black [Display3] # Selection display enabled=True x=496 y=258 w=42 h=25 color=palegreen bgcolor=black [Display4] # Credit Display enabled=True x=496 y=214 w=42 h=25 color=palegreen bgcolor=black [TitleStrips] Background=jb45lb01.jpg AddQuotes=True ForceUpperCaseTitles=True ForceUpperCaseArtists=True SongsPerStrip=Double Font=bluehigh.ttf FontSize=26 FontColor=black SmallFont=bluecond.ttf SmallFontSize=26 Width=320 Height=108 [StripGrid] x=162 y=308 rows=4 cols=2 rowspace=2 colspace=60 order=Horizontal
That is all there is to a basic skin. Where it gets more complicated is when you start adding icons that create or react to jukebox events; these icons are of course critical for touchscreen use. For this, we shift gears and look at default.skn. I'll skip all of the stuff covered above and go right to the icons:
[Icon1] x=464 y=193 w=93 h=94 OnImage=instron.bmp OffImage=instroff.bmp Clickable=False Action=MSG_CREDITS [Icon2] x=624 y=281 w=11 h=11 OnImage=r-ledoff.bmp OffImage=r-ledon.bmp Clickable=False Action=MSG_POPULAR [Icon3] x=738 y=281 w=11 h=11 OnImage=r-ledon.bmp OffImage=r-ledoff.bmp Clickable=False Action=MSG_POPULAR [Icon4] x=477 y=413 w=33 h=33 FocusColor=yellow ShadowColor=Black Clickable=True Action=BTN_A [Icon5] x=514 y=413 w=33 h=33 FocusColor=yellow ShadowColor=Black Clickable=True Action=BTN_1
(This is just a subset of the 17 icons in default.skn, but the rest are like Icon4 and Icon5.)
Here we see the two different kinds of icons: non-clickable icons, which simply react to events, and clickable icons, which both create and react to events. Correspondingly, there are two kinds of events an icon can send or receive: BTN_ events, which act as if one of the buttons were pressed when sent, and MSG_ events, which report on the state of the jukebox.
As a general rule, clickable BTN_ messages almost always represent physical buttons, and non-clickable MSG_ messages almost always represent lights or a similar status indicator.
Clickable icons should always send BTN_ events; non-clickable icons can react to either BTN_ or MSG_ events. The BTN_ events are listed in controls.ini; the MSG_ events are listed in readme.txt.
BTN_ events always un-set themselves after 1/10th of a second, and MSG_ events un-set themselves when the condition is no longer true. A perfect example is to compare BTN_PAUSE vs. MSG_SONGPAUSED. When BTN_PAUSE is pressed, either on the keyboard or by clicking a clickable icon assigned to it, the BTN_PAUSE message is processed, which pauses the current song and pushes BTN_PAUSE and MSG_SONGPAUSED onto the message queue, and a -BTN_PAUSE (unset BTN_PAUSE) onto the timer queue. The user interface sees the BTN_PAUSE and causes whatever icons are assigned to it to display their OnImage, or if no OnImage is assigned it makes the OffImage (or the background if no OffImage is assigned) appear to be "pressed" by shifting it a couple of pixels down and to the right. The same thing happens with MSG_SONGPAUSED, so if you have an OffImage that looks like an unlit LED and an OnImage that looks like a lit LED, the LED for that icon will appear to "light" in response to MSG_SONGPAUSED. A tenth of a second later, -BTN_PAUSE is sent to the user interface, reverting any icons assigned to it back to their OffImage (or the background if no OffImage is assigned), but the song is still paused. When BTN_PAUSE is pressed again, the process repeats, except this time processing the message results in starting the song and sending BTN_PAUSE and -MSG_SONGPAUSED to the interface, and again -BTN_PAUSE to the timer queue. If the clickable icon instead was set to MSG_SONGPAUSED, nothing would happen, as the jukebox engine doesn't react to MSG_ messages, only BTN_ messages.
MSG_ISDOS is a special case; it is set on startup if running in DOSCab and unset if running in Windows. This allows you to show an instruction label or logo differently depending on which operating system is running.
NOTE: It is not necessary to add button icons to enable a button unless the skin is to be used with a touchscreen, mouse, or via the GUI navigation buttons.
Skins can contain pointers to sounds that are triggered when a button is pressed or an event occurs. Sounds can be set to trigger either when a message or button is set or unset. To specify that a sound should be played when a message or button is unset, prefix the message or button name with a minus sign.
Here is a sample sound definition set:
[Sounds] BTN_COIN1=coin.wav BTN_COIN2=coin.wav BTN_ANY=btnclick.wav MSG_START=startup.wav