Load skins from original WSZ files instead of individual BMPs

This commit is contained in:
Elliot Shepherd 2014-11-16 17:20:25 +11:00
parent 0381b5e421
commit 56db746c35
25 changed files with 101 additions and 186 deletions

View File

@ -72,6 +72,10 @@
<a id='about' target='_blank' href='https://github.com/captbaritone/winamp2-js'></a>
</div>
<p style="position: absolute; bottom: 0;">by <a href='https://twitter.com/captbaritone'>@captbaritone</a> - <a href='https://github.com/captbaritone/winamp2-js'>GitHub</a></p>
<script src="http://stuk.github.io/jszip/dist/jszip.js"></script>
<script src="http://stuk.github.io/jszip-utils/dist/jszip-utils.js"></script>
<script src="media.js"></script>
<script src="skin.js"></script>
<script src="font.js"></script>

114
skin.js
View File

@ -35,32 +35,112 @@ SkinManager = function() {
}
// For local dev, we want to use the asset we have locally
this.useLocalDefaultSkin = function() {
self.setSkinByUrl('skins/default');
this.setSkinByName = function() {
self.setSkinByWszUrl('default');
}
// I have a collection of skins on GitHub to make loading remote skins
// easier. rawgit.com changes this into a free CDN
this.setSkinByName = function(name) {
url = "https://cdn.rawgit.com/captbaritone/winamp-skins/master/v2/" + name;
url = "https://cdn.rawgit.com/elliots/winamp2-js/master/skins/" + name + ".wsz";
self.setSkinByUrl(url);
}
// Given the URL of a skin directory, set the current skin
this.setSkinByUrl = function(skinPath) {
// Make sure we have a trailing slash. Two slashes are > than none
skinPath += "/";
// Given the url of an original Winamp WSZ file, set the current skin
this.setSkinByUrl = function(url) {
var style = document.getElementById('skin');
// XXX Ideally we would empty the style tag here, but I don't know how.
// Appending overwrites, which has the same net effect, but after
// several skin changes, this tag will get pretty bloated.
var cssRules = '';
for(var selector in self._skinImages) {
var imagePath = skinPath + self._skinImages[selector];
var value = "background-image: url(" + imagePath + ");";
cssRules += selector + "{" + value + "}\n";
style.appendChild(document.createTextNode(cssRules));
JSZipUtils.getBinaryContent(url, function(err, data) {
if (err) {
alert('Failed to load skin ' + url + ' : ' + err);
}
try {
var zip = new JSZip(data);
var style = document.getElementById('skin');
var cssRules = '';
for(var selector in self._skinImages) {
var file = zip.filter(function (relativePath, file){
return new RegExp(self._skinImages[selector], 'i').test(relativePath)
})[0];
if (!file) {
console.log("Warning: Couldn't find file:" + self._skinImages[selector])
} else {
var value = "background-image: url(data:image/bmp;base64," + btoa(file.asBinary()) + ")"
cssRules += selector + "{" + value + "}\n";
}
}
style.appendChild(document.createTextNode(cssRules));
} catch(e) {
alert('Failed to load skin ' + url + ' : ' + e.message);
}
})
}
}
;(function () {
var object = typeof exports != 'undefined' ? exports : this; // #8: web workers
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
function InvalidCharacterError(message) {
this.message = message;
}
InvalidCharacterError.prototype = new Error;
InvalidCharacterError.prototype.name = 'InvalidCharacterError';
// encoder
// [https://gist.github.com/999166] by [https://github.com/nignag]
object.btoa || (
object.btoa = function (input) {
for (
// initialize result and counter
var block, charCode, idx = 0, map = chars, output = '';
// if the next input index does not exist:
// change the mapping table to "="
// check if d has no fractional digits
input.charAt(idx | 0) || (map = '=', idx % 1);
// "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
output += map.charAt(63 & block >> 8 - idx % 1 * 8)
) {
charCode = input.charCodeAt(idx += 3/4);
if (charCode > 0xFF) {
throw new InvalidCharacterError("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
}
block = block << 8 | charCode;
}
return output;
});
// decoder
// [https://gist.github.com/1020396] by [https://github.com/atk]
object.atob || (
object.atob = function (input) {
input = input.replace(/=+$/, '');
if (input.length % 4 == 1) {
throw new InvalidCharacterError("'atob' failed: The string to be decoded is not correctly encoded.");
}
for (
// initialize result and counters
var bc = 0, bs, buffer, idx = 0, output = '';
// get next character
buffer = input.charAt(idx++);
// character found in table? initialize bit storage and add its ascii value;
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
// and if not first of each 4 characters,
// convert the first 8 bits to one ascii character
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
) {
// try to find character in table (0-63, not found => -1)
buffer = chars.indexOf(buffer);
}
return output;
});
}());

BIN
skins/base-2.91.wsz Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

View File

@ -1,6 +0,0 @@
[Text]
Normal=#00FF00
Current=#FFFFFF
NormalBG=#000000
SelectedBG=#0000FF
Font=Arial

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -1,105 +0,0 @@
; I stole this from the Complex skin, cause hey I thought it was cool :)
; (and cause I'm too lazy to document it myself. :)
; The original author is Adam Kennedy <adamk@iname.com>
;
; Hope you don't mind Adam :)
;
;
; -Justin
;
;
; P.S. you can use the section names [WindowShade] and [Equalizer]
; for obvious purposes =)
;
;
; REGION.TXT STRUCTURE FOR DEFINING SKIN MASKS
;
;The region information comes without any supporting documentation
;so I thought I might as well make some.
;
;The region.txt in WinAmp 1.92 allows us to some interesting things with transparencies
;But how does it work?
;
;Well, basically, it lets you define a set of polygons. Anything inside a polygon is drawn. Anything not in a polygon is not drawn. Simple heh?
;For how to define it have a look below at the first block. Un-comment it now. Don't worry about commenting the actual one lower down, if WinAmp finds multiple definitions, it only does the first and ignores the rest
;
;How to make a mask
;1. Type [Normal]. Real simple that one. (My guess is it is just for forward compatibility)
;2. Just type the NumPoints= and leave the number blank, we'll fill it in later
;3. OK, now for the fun part.
; The co-ordinates you should type in are the OUTSIDE pixel co-ordinates in x,y format.
; Start at the top lefthand corner and work your way CLOCKWISE around you polygon.
; Now WinAmp ONLY accepts the PointList as one line of comma seperated variables.
; You can use spaces, but DONT GO ONTO A NEW LINE. Clear? Good. :)
; One last thing, don't type the first position again at the end, WinAmp joins them.
; Putting a space between each pair is simply common sense, right?
;4. Once your done, count the number of co-ords, and fill in that number for NumPoints.
;
;Oh, as a side note, the x variables go from 0 to 275, and the y from 0 to 116.
;So if you look at the first example you can see I've gone across the second top line, gone down a bit, ducked in one pixel, gone down to the bottom, and across and back up the other side, putting another ledge on the other side.
;This does the outside border, and chops some bits out on the top and edges
;[Normal]
;NumPoints=8 ;Do this LAST!
;PointList=0,1, 275,1, 275,14, 274,14, 274,115, 1,115, 1,14, 0,14
;Cool heh? Very subtle effect. Now lets try a more complex one, with multiple polygons
;For your first hard(ish) mask, I suggest defining each element as a seperate mask.
;It makes them a bit easier to think about.
;First, lets define an area that JUST does the titlebar.
;[Normal]
;NumPoints=4
;PointList=0,1, 275,1, 275,14, 0,14
;Simple as can be :)
;Go ahead, uncomment it and have a look. Just remember to recomment everything above it
;Doing your areas one at a time does speed the process up a bit
;Now lets define JUST the area sort of inside the outer ring
;[Normal]
;NumPoints = 4
;PointList = 3,15, 272,15, 272,113, 3,113
;Right, so say we want a mask that has, the titlebar AND the main area.
;We just add them together
; [Normal]
; NumPoints = 4, 4 ;Make sure to get the order right(although it doesnt matter here =P )
; PointList = 0,1, 275,1, 275,14, 0,14, 3,15, 272,15, 272,113, 3,113
;Dont forget to add that extra comma after the first set.
; Having that bigger gap that lets you "keep it in your head" easier, it's a good idea
;OK, now lets try something tricky. We are going to make a mask for just one green line around the outside of the skin
;This introduces the other "big thing" with masks. Have a look at the first three co-ordinates below. You can see the first two moves we make are to go one to the side and then go down to the bottom. Looking at the last co-ordinate you can see we will come back up at the end, making a line two wide, right?
;WRONG!! Here comes the big important phrase.
;IF YOU ARNT FOLLOWING THE OUTSIDE EDGE, YOUR CO-ORDINATES MARK TRANSPARENT SPACE LIMITS
;That's right. Because I don't make a square, because I have to turn "inside" the box, I am only marking space, and what I end up with is a mask with one green line.
;WARNING: Leave your skins dialog open when you do this one. :)
;[Normal]
;NumPoints = 8
;PointList = 1,14, 2,14, 2,114, 273,114, 273,14, 274,14, 274,115, 1,115
;OK, as the final touch lets add lets the border we just made to the other two.
;You should be able to work this out on your own
;[Normal]
;NumPoints = 4, 4, 8
;PointList = 0,1, 275,1, 275,14, 0,14, 3,15, 272,15, 272,113, 3,113, 1,14, 2,14, 2,114, 273,114, 273,14, 274,14, 274,115, 1,115
;hmm... that still looks a bit tacky down the bottom right
;So I'm going to modify it a bit
;See if you can work out what I've had to alter just by looking at the display of it
;[Normal]
;NumPoints = 4, 4, 8
;PointList = 0,1, 275,1, 275,14, 0,14, 3,15, 272,15, 272,80, 3,80, 1,14, 2,14, 2,81, 273,81, 273,14, 274,14, 274,115, 1,115
; Justin's whacked trans skin :) in one, big lame messy line
; [Normal]
; NumPoints=20,4,4,4,8,4,4,6,6,4,4,4,4
; PointList=0,0,19,0,19,11,114,11,114,0,156,0,156,11,243,11,243,0,275,0,275,13,266,13,266,22,264,22,264,13,111,13,111,22,109,22,109,13,0,13, 109,22,266,22,266,36,109,36, 16,88,130,88,130,105,16,105, 136,89,157,89,157,104,136,104, 22,13,22,62,102,62,102,13,100,13,100,24,24,24,24,13, 0,0,275,0,275,3,0,3, 16,72,264,72,264,81,16,81, 0,13,0,78,16,78,16,75,4,75,4,13, 275,13,275,78,264,78,264,75,272,75,272,13, 14,78,16,78,16,105,14,105, 130,81,132,81,132,105,130,105, 146,81,146,89,148,89,148,81, 130,96,136,96,136,98,130,98
;THE END
;
;Post-Script
;The other good thing about doing your mask in bits and pieces like this is that can make multiple versions so you can change as your whims change

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -1,34 +0,0 @@
Coppied from winamp/wa_dlg.h from the Winamp 2.9 ML SDK.
1) gen.bmp has a generic window frame for plugins to use.
its format is similar to the minibrowser's.
In addition gen.bmp includes a font for the titlebar, in both
highlight and no-highlight modes. The font is variable width,
and it uses the first color before the letter A as the delimiter.
The no-highlight form of letter must be the same width as the
highlight form.
2) genex.bmp has button and scrollbar images, as well as some individual
pixels that describe the colors for the dialog. The button and
scrollbar images should be self explanatory (note that the buttons
have 4 pixel sized edges that are not stretched, and the center is
stretched), and the scrollbars do something similar.
The colors start at (48,0) and run every other pixel. The meaning
of each pixel is:
x=48: item background (background to edits, listviews etc)
x=50: item foreground (text color of edit/listview, etc)
x=52: window background (used to set the bg color for the dialog)
x=54: button text color
x=56: window text color
x=58: color of dividers and sunken borders
x=60: selection color for listviews/playlists/etc
x=62: listview header background color
x=64: listview header text color
x=66: listview header frame top color
x=68: listview header frame middle color
x=70: listview header frame bottom color
x=72: listview header empty color
x=74: scrollbar foreground color
x=76: scrollbar background color
x=78: inverse scrollbar foreground color
x=80: inverse scrollbar background color
x=82: scrollbar dead area color

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

View File

@ -1,24 +0,0 @@
0,0,0, // color 0 = black
24,33,41, // color 1 = grey for dots
239,49,16, // color 2 = top of spec
206,41,16, // 3
214,90,0, // 4
214,102,0, // 5
214,115,0, // 6
198,123,8, // 7
222,165,24, // 8
214,181,33, // 9
189,222,41, // 10
148,222,33, // 11
41,206,16, // 12
50,190,16, // 13
57,181,16, // 14
49,156,8, // 15
41,148,0, // 16
24,132,8, // 17 = bottom of spec
255,255,255, // 18 = osc 1
214,214,222, // 19 = osc 2 (slightly dimmer)
181,189,189, // 20 = osc 3
160,170,175, // 21 = osc 4
148,156,165, // 22 = osc 4
150, 150, 150, // 23 = analyzer peak dots

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB