Load skins from original WSZ files instead of individual BMPs
@ -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
@ -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
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 476 B |
Before Width: | Height: | Size: 52 KiB |
@ -1,6 +0,0 @@
|
||||
[Text]
|
||||
Normal=#00FF00
|
||||
Current=#FFFFFF
|
||||
NormalBG=#000000
|
||||
SelectedBG=#0000FF
|
||||
Font=Arial
|
Before Width: | Height: | Size: 3.1 KiB |
@ -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
|
Before Width: | Height: | Size: 4.3 KiB |
@ -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
|
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 28 KiB |
@ -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
|
Before Width: | Height: | Size: 30 KiB |