http://wiki.shoutcast.com/api.php?action=feedcontributions&user=Culix&feedformat=atomWinamp Developer Wiki - User contributions [en]2024-03-28T08:34:30ZUser contributionsMediaWiki 1.22.3http://wiki.shoutcast.com/wiki/User_talk:Skurvy_PirateUser talk:Skurvy Pirate2011-07-07T02:38:09Z<p>Culix: /* Thanks *l</p>
<hr />
<div>== Thanks ==<br />
Thanks for catching the spaces error on the [[Beginner's Basic Plugin Guide]]. Have fun with Winamp! --[[User:Culix|Culix]] 02:38, 7 July 2011 (UTC)</div>Culixhttp://wiki.shoutcast.com/wiki/Visual_DeveloperVisual Developer2011-03-09T03:20:31Z<p>Culix: Reverted edits by Bishop2011 (Talk) to last version by Culix</p>
<hr />
<div>{{Template:NavBar}}<br />
<br />
==What is a Visualization?==<br />
Visualizers or Visualization Plugins are dynamic add-ons that produce images, colors, and textures that change based elements of the music being played. Winamp offers two primary visualization plugins ([[Visual_Developer#AVS_Unleashed | AVS]] & [[Visual_Developer#Milk_Drop_Unleashed | MilkDrop]]) allowing you to create different presets. If you’re feeling invincible, you can even attempt to create your own visualization plugin or you can stay platform. There are many [http://www.winamp.com/plugins/browse/1 visualization plugins] available which users have generated.<br />
<br />
==What is a Preset?==<br />
Presets are outputs of a visualization platform. You can customize the visualizers and get any effect you want. Many users have uploaded such presets in [http://www.winamp.com/plugins/browse/11 Winamp.com]<br />
<br />
==AVS Unleashed==<br />
AVS is the mother of all Winamp visualization plug-ins. It lets the user build a countless number of custom visualizations from an ever-expanding library of effects. AVS supports windowed/fullscreen rendering, preset customization, module stacking, skinnable windows, support for Sonique visual plug-ins, and a ton of other features. AVS is now bundled with all versions of Winamp after v2.6, so everyone can get a taste of its visual sonic goodness.<br />
<br />
===Module References===<br />
Below is some information on AVS modules. WVS is our codename for our global mind control device. With it we shall overtake the world. And have another excuse to take mind-altering substances.<br />
<br />
Currently information about the superscope module is here. It uses all kinds of math stuff. Justin is so smart. You can look here for more general information about making presets.<br />
<br />
====Superscope Reference====<br />
<br />
The superscope allows you to create your own designs.<br />
<br />
To have multiple statements on one line, use a semicolon (;) to delimit the statement. Use parenthesis '( and )' if you are unsure about precedence.<br />
<br />
'''Fields:'''<br />
<br />
{| Border="1"<br />
!Field !! Description<br />
|-<br />
|init || set initial variable values here<br />
|-<br />
|point || This is where the shape of the superscope is defined<br />
|-<br />
|frame || Used to define movement and transformations<br />
|-<br />
|beat || Expression that gets evaluated on the beat<br />
|-<br />
|}<br />
<br />
'''Operators:'''<br />
<br />
{| Border = "1"<br />
!Operator !! Description<br />
|-<br />
|= || assign<br />
|-<br />
|'+,-,/,*' || 'plus, minus, divide, multiply'<br />
|-<br />
|| || convert to integer, and do bitwise or<br />
|-<br />
|& || convert to integer, and do bitwise and<br />
|-<br />
|% || convert to integer, and get remainder<br />
|-<br />
|}<br />
<br />
'''Variables:'''<br />
<br />
{| Border = "1"<br />
!Variables !! Description<br />
|-<br />
|n || number of points to render (set in Init, Beat or Frame)<br />
|-<br />
|x || x coordinate, between -1 and 1<br />
|-<br />
|y || y coordinate, between -1 and 1<br />
|-<br />
|i || position of the scope (0..1). The point position.<br />
|-<br />
|v || value at point i (-1..1)<br />
|-<br />
|b || 1 if beat. 0 for no beat. Used for beat changes<br />
|-<br />
|w || width of screen<br />
|-<br />
|h || height of screen<br />
|-<br />
|red || red value. (0..1). Set this variable to set red value.<br />
|-<br />
|green || green value. (0..1) Set this variable to set green value.<br />
|-<br />
|blue || blue value. (0..1) Set this variable to set blue value.<br />
|-<br />
|t, d || variables commonly used for movement<br />
|-<br />
|}<br />
<br />
'''Functions:'''<br />
{| Border = "1"<br />
!Variables !! Description<br />
|-<br />
|abs(var)|| returns the absolute value of 'var'<br />
|-<br />
|sin(var) || returns the sine of the angle var (expressed in radians)<br />
|-<br />
|cos(var) || returns the cosine of the angle var<br />
|-<br />
|tan(var) || returns the tangent of the angle var<br />
|-<br />
|asin(var) || returns the arcsine of var<br />
|-<br />
|acos(var) || returns the arccosine of var<br />
|-<br />
|atan(var) || returns the arctangent of var<br />
|-<br />
|sqr(var) || returns the square of var<br />
|-<br />
|sqrt(var) || returns the square root of var<br />
|-<br />
|pow(var, var2)|| returns var to the power of var2<br />
|-<br />
|log(var) || returns the log base of var<br />
|-<br />
|log10(var) || returns the log base 10 of var<br />
|-<br />
|sign(var) || returns the sign of var or 0<br />
|-<br />
|min(var, var2)|| returns the smallest value<br />
|-<br />
|max(var, var2) || returns the greatest value<br />
|-<br />
|sigmoid(var, var2)|| returns sigmoid function value of x=var (var2=constraint)<br />
|-<br />
|rand(var) || returns a random value between 0 and var<br />
|-<br />
|band(var, var2)|| boolean and, returns 1 if var and var2 are != 0<br />
|-<br />
|bor(var, var2) || boolean or, returns 1 if var or var2 is != 0<br />
|-<br />
|bnot(var) || boolean not, returns 1 if var == 0 or 0 if var ! = 0<br />
|-<br />
|if(cond, vartrue, varfalse) || if condition is nonzero, returns valtrue, otherwise returns valfalse<br />
|-<br />
|equal(var, var2) || returns 1 if var=var2, else 0<br />
|-<br />
|above(var, var2) || returns 1 if var > var2, else 0<br />
|-<br />
|below(var, var2)|| returns 1 if var<var2, else 0<br />
|-<br />
|}<br />
jjjjjjjj<br />
<br />
===Making Presets===<br />
We are going to attempt to reproduce a simple version of one of my favorite presets: Lone's "No way to go". Successful presets usually start off with one or more Render Modules, and then have a number of Trans Modules added to subtly manipulate the effect. Lone's preset is no exception. Again, before we start, make sure that you have both Winamp and AVS installed:<br />
# Start Winamp and AVS<br />
# Right-click in the AVS window, and select AVS Editor<br />
# In the Editor window, click on Preset. A drop-down menu appears<br />
# Click on New. This creates a new blank preset<br />
# Click on Main. The option to Clear every frame should appear in the right window. If enabled, this will paint the screen black at the beginning of each frame, erasing the previous one. For this preset, leave this option unchecked<br />
# We will now add Effect Modules to this presets. Click on +, then click on Render, then click on Moving Particle. New options should appear in the right half of the window<br />
# Click on the white box labeled "color". A whole new color window should pop up<br />
# Click on a basic color (it helps the effect if it isn't a "pure" color, like orange or purple). Now click OK. The color box should now be the same color that you chose<br />
# Make sure the Onbeat Sizechange option is enabled<br />
# A moving blob of color is a bit interesting, but it could be better. We will now alter how that Moving Particle is displayed by adding some Trans Modules<br />
# Click +, then click Trans, then click Water<br />
# Click +, then click Trans, then click Blur<br />
# Click +, then click Trans, then click Movement. A new list of effects should appear in the right half of the window. Click on sunburster<br />
<br />
Congratulations, we have replicated Lone's Preset! You can also drag an included Effect Module up or down the list to play with sequencing. I hope that you have realized by now that ANY permutation of the existing Modules or setting modification will result in a new effect! Keep experimenting!<br />
<br />
====Advanced Tactics====<br />
<br />
After creating a few original presets, it is natural to want even more options and control. AVS now has a very powerful tool: Effect Lists. To use an Effect List simply as an organizational tool is to squander its potential. The idea is that everything in an effect list gets rendered into a separate buffer before being added to its parent buffer. You now have the power to create completely separate effects off screen, manipulate them freely, possibly blending them together, all before finally displaying the final effect in one shot.<br />
#Open AVS Editor#Create a new preset<br />
#Click on Main, then disable the Clear every frame option<br />
#Click on +, then on Effect List to add an Effect List<br />
#In the Effect List options, make sure the Enabled and Clear every frame check boxes are checked. For the Input blend mode, select Ignore. For the Output blend mode, select Subtractive Blend 1<br />
#Click on +, then on Trans, then on Mosaic<br />
#Click on +, then on Render, then on Simple<br />
#Click on Main, to stop adding to the Effect list<br />
#Click on +, then on Trans, then Fadeout<br />
#In the Fadeout options, Click on the Fade to Color Box, and select a nice red color#Click on +, then on Render, then on Bass Spin<br />
<br />
If you have followed the instructions faithfully, you should get an effect tree that looks like this:<br />
<br />
'''Main'''<br />
* Render / Bass Spin<br />
* Trans / Fadeout<br />
'''Effects List'''<br />
* Render / Simple<br />
* Trans / Mosaic<br />
<br />
That having been done, let's examine this preset:<br />
A Bass Spin is placed into the main parent buffer.<br />
<br />
Then, the Effect List creates a separate, secondary buffer.<br />
<br />
This buffer starts out black (cleared every frame), ignores what is in its parent buffer and a Simple waveform is drawn into it. Notice that the Mosaic modifier ONLY affects the Simple effect as it is totally segregated from the parent buffer.<br />
<br />
Now that all effects in the Effect List have been processed, the secondary buffer is blended back into the parent buffer using the blend mode specified in the Effects List options; in this case, Subtractive Blend 1.<br />
<br />
This results in a dark colored Simple effect overlaid over the white Bass Spins.<br />
<br />
What this means is that you can prevent Trans modifiers from affecting whole groups of modules, which in turn gives you much finer control over the visual effects. I hope this simple tutorial has shed some light on to the mystery of Effect Lists. It took me a bit of head scratching to wrap my mind around the usefulness of parent and child buffers, but now all my old presets seem so primitive. Keep playing with AVS and you will impress yourself! I guarantee it!<br />
<br />
===Writing APEs===<br />
BOX is a quick and dirty demonstration of basic APE structure and the utilization of AVS features. It takes advantage of AVS's built-in beat detection and easy access to the frame buffer to flash a rectangle onscreen on every beat. We also learn how to set up a configuration screen template, load and save configuration settings, and use the default color selector. There is very little fat, so you can use this as a template for future APEs. You can view the main file below.<br />
<br />
====Box Source code====<br />
<br />
You can check a sample [[box source code here]]<br />
<br />
==Milk Drop Unleashed==<br />
'''MilkDrop''' is a music visualizer - a "plug-in" to the Winamp music player. As you listen your music in Winamp, MilkDrop takes you flying through the actual soundwaves you're hearing, and uses beat detection to trigger myriad psychedelic effects, creating a rich visual journey through sound. MilkDrop can also be driven by a live audio feed (microphone or line-in)<br />
<br />
'''MilkDrop 2''' is a major upgrade to the original MilkDrop visualizer, opening up <br />
the power of modern graphics chips and programmable pixel shaders to the realm <br />
of music visualization. Pixel shaders allow dozens, even hundreds of complex <br />
instructions to be executed for every pixel on the screen, every frame. <br />
Other new features include jpg textures, gaussian blurring, a preset "mash-up" <br />
feature, and a prest "back" button. MilkDrop 2 is backwards-compatible with <br />
presets from MilkDrop 1.<br />
<br />
For a comprehensive understanding, please go through the [[MilkDrop Unleashed Guide]]<br />
<br />
To create your own presets, check out the [[MilkDrop_Preset_Authoring]] Guide<br />
<br />
For on-going discussions on Milk Drop, drop in the [http://forums.winamp.com/forumdisplay.php?forumid=81 Milk Drop Forums]<br />
<br />
<br />
<br />
<br />
<br />
==Developer Resources==<br />
* [[Articles#Visualization_Articles|Visual Developer Articles]]<br />
* [[Developers_FAQ#Visual_Developer_FAQ|Visual Developer FAQ]]<br />
* Rovastar's [http://www.milkdrop.co.uk/ MilkDrop Resource Website]<br />
* Download MilkDrop [http://www.nullsoft.com/free/milkdrop/Milkdrop_1.04_Source.zip Source Code]<br />
* [http://forums.winamp.com/forumdisplay.php?forumid=81 MilkDrop Forums]</div>Culixhttp://wiki.shoutcast.com/wiki/Skin_DeveloperSkin Developer2011-02-17T02:10:16Z<p>Culix: Reverted edits by Sanunyonk (Talk) to last version by Culix</p>
<hr />
<div>{{Template:NavBar}}<br />
<br />
<br />
== Classic Skins ==<br />
Classic skins are skins that adhere to the Winamp 2 style model. Classic skins are easier to create than Modern skins but do not allow the author to change the form or function of the player. Classic authors may only replace a standard set of images that alter the player's visual appearance.<br />
<br />
* '''[[Creating Classic Skins]]'''<br />
<br />
== Modern Skins ==<br />
Modern or Freeform skins were originally designed to work with Winamp3. What separates them from the average skin is the fact that they are not confined to the classic rectangular shape. In fact they can be any shape you want them to be and you can put the Winamp control buttons anywhere you want. Some skinners have even added extra buttons that extend the functionality of Winamp right there on the skin. Sounds too good to be true huh? Well these skins require a bit more coding to make and some of the graphics that go into them are quite large. Consequently, Freeform skins may take a bit longer to download from our site and they may take a few extra seconds to load when you switch from one skin to another. But trust me when I say that Freeform skins are worth the extra time and effort. Skin developers have done some incredible things with these skins. You have to check them out.<br />
<br />
* '''[[Creating Modern Skins]]'''<br />
<!-- SkinWizard XML Designer 1.0 --><br />
<br />
<!-- Background elements --><br />
<groupdef id="Backgrounds" name="BckElements"><br />
<layer id="LayerID1" image="common/bck_seek.png" x="19" y="92" /><br />
<layer id="LayerID2" image="common/bck_visualizer.png" x="22" y="25" /><br />
<layer id="LayerID3" image="common/slider_volume_BCK.png" x="212" y="64" /><br />
</groupdef><br />
<br />
<!-- Player Buttons --><br />
<groupdef id="PlayButtons" name="Player Buttons"><br />
<button<br />
id="btnPlay"<br />
action="PLAY" param=""<br />
x="11" y="106"<br />
image="vista/vst_btn_play_N.png"<br />
hoverimage="vista/vst_btn_play_H.png"<br />
downImage="vista/vst_btn_play_D.png"<br />
tooltip="Play"<br />
/><br />
<br />
<button<br />
id="btnPause"<br />
action="PAUSE" param=""<br />
x="61" y="117"<br />
image="vista/vst_btn_pause_N.png"<br />
hoverimage="vista/vst_btn_pause_H.png"<br />
downImage="vista/vst_btn_pause_D.png"<br />
tooltip="Pause"<br />
/><br />
<br />
<button<br />
id="btnStop"<br />
action="STOP" param=""<br />
x="104" y="117"<br />
image="vista/vst_btn_stop_N.png"<br />
hoverimage="vista/vst_btn_stop_H.png"<br />
downImage="vista/vst_btn_stop_D.png"<br />
tooltip="Stop"<br />
/><br />
<br />
<button<br />
id="btnEject"<br />
action="EJECT" param=""<br />
x="146" y="117"<br />
image="vista/vst_btn_open_N.png"<br />
hoverimage="vista/vst_btn_open_H.png"<br />
downImage="vista/vst_btn_open_D.png"<br />
tooltip="Eject / Open"<br />
/><br />
<br />
<button<br />
id="btnPrev"<br />
action="PREV" param=""<br />
x="240" y="116"<br />
image="xp/xp_btn_prev_N.png"<br />
hoverimage="xp/xp_btn_prev_H.png"<br />
downImage="xp/xp_btn_prev_D.png"<br />
tooltip="Previous"<br />
/><br />
<br />
<button<br />
id="btnNext"<br />
action="NEXT" param=""<br />
x="288" y="116"<br />
image="xp/xp_btn_next_N.png"<br />
hoverimage="xp/xp_btn_next_H.png"<br />
downImage="xp/xp_btn_next_D.png"<br />
tooltip="Next"<br />
/><br />
<br />
</groupdef><br />
<br />
<!-- Header and additional buttons --><br />
<groupdef id="grTechButtons" name="Other Buttons"><br />
<togglebutton<br />
id="btnPL"<br />
action="TOGGLE" param="guid:pl"<br />
x="19" y="0"<br />
image="vista/vst_btn_PL_N.png"<br />
activeImage="vista/vst_btn_PL_H.png"<br />
downImage="vista/vst_btn_PL_D.png"<br />
hoverimage="vista/vst_btn_PL_H.png"<br />
tooltip="Playlist"<br />
/><br />
<br />
<togglebutton<br />
id="btnML"<br />
action="TOGGLE" param="guid:ml"<br />
x="47" y="0"<br />
image="vista/vst_btn_ML_N.png"<br />
activeImage="vista/vst_btn_ML_H.png"<br />
downImage="vista/vst_btn_ML_D.png"<br />
hoverimage="vista/vst_btn_ML_H.png"<br />
tooltip="Media library"<br />
/><br />
<br />
<button<br />
id="btnClose"<br />
action="CLOSE" param=""<br />
x="340" y="17"<br />
image="xp/btn_capt_close_N.png"<br />
hoverimage="xp/btn_capt_close_H.png"<br />
downImage="xp/btn_capt_minimize_D.png"<br />
tooltip="Close"<br />
/><br />
<br />
<button<br />
id="ButtonID2"<br />
action="MINIMIZE" param=""<br />
x="340" y="32"<br />
image="xp/btn_capt_minimize_N.png"<br />
hoverimage="xp/btn_capt_minimize_H.png"<br />
downImage="xp/btn_capt_minimize_D.png"<br />
tooltip="Minimize"<br />
/><br />
<br />
</groupdef><br />
<br />
<!-- Components and elements --><br />
<groupdef id="grComponents" name="Components"><br />
<vis id="Visualization"<br />
x="30" y="30"<br />
w="76" h="40"<br />
relatx="0"<br />
alpha="255"<br />
gammagroup="gamma"<br />
ColorBand1="255,255,255"<br />
ColorBand2="255,255,255"<br />
ColorBand3="255,255,255"<br />
ColorBand4="255,255,255"<br />
ColorBand5="255,255,255"<br />
ColorBand6="255,255,255"<br />
ColorBand7="255,255,255"<br />
ColorBand8="255,255,255"<br />
ColorBand9="255,255,255"<br />
ColorBand10="255,255,255"<br />
ColorBand11="255,255,255"<br />
ColorBand12="255,255,255"<br />
ColorBand13="255,255,255"<br />
ColorBand14="255,255,255"<br />
ColorBand15="255,255,255"<br />
ColorBand16="255,255,255"<br />
<br />
colorosc1="255,255,255"<br />
colorosc2="255,255,255"<br />
colorosc3="255,255,255"<br />
colorosc4="255,255,255"<br />
colorosc5="255,255,255"<br />
colorbandpeak="255,255,255"<br />
/><br />
<br />
<Text<br />
id="SongInfo" ticker="1"<br />
display="songname" showlen="1"<br />
x="118" y="26"<br />
w="210" h="17"<br />
fontsize="16" font="" color="255,255,255"<br />
shadowcolor="128,128,128" shadowx="1" shadowy="1"<br />
/><br />
<br />
<text<br />
id="Timer"<br />
display="time"<br />
x="118" y="47"<br />
w="80" h="25"<br />
font=""<br />
fontsize="18"<br />
color="255,255,255"<br />
align="left"<br />
antialias="1" bold="1"<br />
shadowcolor="128,128,128" shadowx="1" shadowy="1"<br />
timeroffstyle="1"<br />
/><br />
<br />
<slider<br />
id="Slider"<br />
action="SEEK"<br />
x="18" y="85"<br />
w="317" h="20"<br />
orientation="horizontal"<br />
thumb="vista/vista_thumb_N.png"<br />
hoverThumb="vista/vista_thumb_H.png"<br />
downThumb="vista/vista_thumb_D.png"<br />
/><br />
<br />
<slider<br />
id="Slider"<br />
action="VOLUME"<br />
x="208" y="63"<br />
w="115" h="12"<br />
orientation="horizontal"<br />
thumb="xp/xp_thumb_N.png"<br />
hoverThumb="xp/xp_thumb_H.png"<br />
downThumb="xp/xp_thumb_H.png"<br />
/><br />
<br />
</groupdef><br />
<br />
<container id="main" name="Main Window" default_x="0" default_y="0" default_visible="1" w="362" h="162"><br />
<layout id="normal" background="common/Background_player.png" w="400" h="300" desktopalpha="1" ><br />
<br />
<group id="Backgrounds" w="362"/><br />
<group id="PlayButtons" w="360" /><br />
<group id="grTechButtons" w="360" /><br />
<group id="grComponents" w="360" /><br />
</layout><br />
<br />
</container><br />
<br />
== ClassicPro Skins ==<br />
ClassicPro skins is a blend of a Classic Winamp skin and a Modern Winamp skin. You don’t need to do any coding to create your skin because all the coding will be done by the ClassicPro plugin. The layout is similar to the Classic Winamp layout but also resizable using a Single-User-Interface ([[SUI]]) to display components.<br />
<br />
[http://cpro.skinconsortium.com/ ClassicPro Official Website]<br />
<br />
* '''[[Creating a ClassicPro Skin]]'''<br />
<br />
==Developer Resources==<br />
*[[Articles#Classic_Skins|Classic Skin Articles]]<br />
*[[Articles#Modern_Skins|Modern Skin Articles]]<br />
*[[Developers_FAQ#Skin_Developer_FAQ|Skin FAQ]]<br />
<br />
==Community Links==<br />
*Forums: [http://forums.winamp.com/forumdisplay.php?s=&forumid=5 Classic Skins]<br />
*Forums: [http://forums.winamp.com/forumdisplay.php?s=&forumid=123 Modern Skins]<br />
*Forums: [http://forums.winamp.com/forumdisplay.php?s=&forumid=18 Skinning Tips and Tricks]<br />
*Forums: [http://forums.winamp.com/forumdisplay.php?s=&forumid=12 Arts and Design]<br />
*Forums: [http://forums.winamp.com/forumdisplay.php?s=&forumid=119 Skin Removal Reporting]<br />
*Upload: [http://www.winamp.com/user/submit Submit Your Skin]<br />
**[http://www.winamp.com/user/submit-skin-classic Submit Classic Skin]<br />
**[http://www.winamp.com/user/submit-skin-modern Submit Modern Skin]<br />
*Browse: [http://www.winamp.com/skins Download Skins]<br />
[[de:Hauptseite]]</div>Culixhttp://wiki.shoutcast.com/wiki/Beginner%27s_Basic_Plugin_GuideBeginner's Basic Plugin Guide2011-01-15T04:06:50Z<p>Culix: add notes on auto-copying .dll as post-build step</p>
<hr />
<div>So you want to write a plugin for Winamp but don't know where to start? This is the page for you. We'll walk you through creating a very basic plugin that does '''nothing'''. You can then expand on the code to do whatever you want.<br />
<br />
==Notes==<br />
This guide assumes you're developing using Visual Studio in a Windows environment. It also assumes you have some familiarity with programming. For people that don't, try using google. We'll have to expand this guide in the future to give out more pointers.<br />
<br />
== Basic credits ==<br />
The following code has been created based on samples from [http://forums.winamp.com/showthread.php?s=&threadid=128915 several] [http://forums.winamp.com/showthread.php?s=&threadid=82651 forum] [http://forums.winamp.com/showthread.php?s=&threadid=103667 threads]. Many thanks go out to forum members Kaboon, kichik, baafie, burek021, and bananskib for their code examples and advice.<br />
<br />
== What you need ==<br />
To begin, you'll need a tool that lets you write code. Check out the [[Plug-in_Developer#Tools|Tools]] page. You can get a free copy of Visual Studio C++ Express [http://www.microsoft.com/Express/ here]. You'll probably also want a copy of Winamp itself, to test your plugin; you can get that on the Winamp site [http://www.winamp.com/player here].<br />
<br />
# Download [http://www.microsoft.com/Express/ Visual C++ Express].<br />
# Double-click the file (it's probably called something like 'vcsetup.exe') and run the installer.<br />
# You're practically good to go!<br />
<br />
== Creating a project ==<br />
The first thing we need to do is create a place to store our code. In Visual Studio this is called a 'project'.<br />
<br />
# Launch Visual Studio by clicking Start -> Programs -> Microsoft Visual C++ Express Edition -> Microsoft Visual C++ Express Edition<br />
# When Visual Studio opens, select File -> New -> Project<br />
# For creating Winamp plugins, we want to create code that compiles into a .dll, which Visual Studio 2008 refers to as a "Class Library". So in the 'New Project' window select Visual C++ -> CLR -> Class Library.<br />
# Give your project a name (see below) and select a location.<br />
<br />
'''Note:''' Winamp classifies plugins based on the first part of their .dll filename, so you will need to properly name the file if you want Winamp to recognize it (details: the Winamp client searches for and loads plugins based on the first part of their filenames. This saves time and space instead of loading all dlls and then detecting which ones are real plugins). Thus, to make our basic plugin we want to name the first part of the file 'gen_'. '''Be sure to start your plugin name with 'gen_' to make it work properly.'''<br />
<br />
All of the examples in this guide will assume you named your plugin 'gen_myplugin', but you can call it whatever you like as long as it starts with 'gen_' (for generic plugin) and ends with '.dll'.<br />
<br />
Once you click okay Visual Studio should create a bunch of boilerplate code for you, and throw some files in your project with names like "resource.h", "stdafx.h", "AssemblyInfo.cpp", and so on. The main files we want to work with are called 'gen_myplugin.h' and 'gen_myplugin.cpp'. If you double-click to view them you should see code that looks something like this:<br />
<br />
<nowiki><contents of gen_myplugin.h></nowiki><br />
<source lang="cpp"><br />
// gen_myplugin.h<br />
<br />
#pragma once<br />
<br />
using namespace System;<br />
<br />
namespace gen_myplugin {<br />
<br />
public ref class Class1<br />
{<br />
// TODO: Add your methods for this class here.<br />
};<br />
}<br />
</source><br />
<nowiki><end contents of gen_myplugin.h></nowiki><br />
<br />
<nowiki><contents of gen_myplugin.cpp></nowiki><br />
<source lang="cpp"><br />
// This is the main DLL file.<br />
<br />
#include "stdafx.h"<br />
<br />
#include "gen_myplugin.h"<br />
<br />
</source><br />
<nowiki><end contents of gen_myplugin.cpp></nowiki><br />
<br />
<br />
We want to edit these files to make a basic plugin.<br />
<br />
== Creating a basic plugin ==<br />
<br />
=== Basic plugin code ===<br />
To create your plugin, just copy/paste the following code into gen_myplugin.h and gen_myplugin.cpp.<br />
<br />
<nowiki><basic gen_myplugin.h></nowiki><br />
<source lang="cpp"><br />
<br />
#ifndef gen_myplugin_h<br />
//---------------------------------------------------------------------------<br />
#define gen_myplugin_h<br />
#include <windows.h><br />
<br />
<br />
// plugin version (don't touch this)<br />
#define GPPHDR_VER 0x10<br />
<br />
// plugin name/title (change this to something you like)<br />
#define PLUGIN_NAME "My first generic Winamp plugin!"<br />
<br />
<br />
// main structure with plugin information, version, name...<br />
typedef struct {<br />
int version; // version of the plugin structure<br />
char *description; // name/title of the plugin <br />
int (*init)(); // function which will be executed on init event<br />
void (*config)(); // function which will be executed on config event<br />
void (*quit)(); // function which will be executed on quit event<br />
HWND hwndParent; // hwnd of the Winamp client main window (stored by Winamp when dll is loaded)<br />
HINSTANCE hDllInstance; // hinstance of this plugin DLL. (stored by Winamp when dll is loaded) <br />
} winampGeneralPurposePlugin;<br />
<br />
<br />
#endif //gen_myplugin_h<br />
</source><br />
<nowiki><end basic gen_myplugin.h></nowiki><br />
<br />
<nowiki><basic gen_myplugin.cpp></nowiki><br />
<source lang="cpp"><br />
/*<br />
<br />
Winamp generic plugin template code.<br />
This code should be just the basics needed to get a plugin up and running.<br />
You can then expand the code to build your own plugin.<br />
<br />
Updated details compiled June 2009 by culix, based on the excellent code examples<br />
and advice of forum members Kaboon, kichik, baafie, burek021, and bananskib.<br />
Thanks for the help everyone!<br />
<br />
*/<br />
<br />
#include "stdafx.h"<br />
#include <windows.h><br />
#include "gen_myplugin.h"<br />
<br />
<br />
// these are callback functions/events which will be called by Winamp<br />
int init(void);<br />
void config(void);<br />
void quit(void);<br />
<br />
<br />
// this structure contains plugin information, version, name...<br />
// GPPHDR_VER is the version of the winampGeneralPurposePlugin (GPP) structure<br />
winampGeneralPurposePlugin plugin = {<br />
GPPHDR_VER, // version of the plugin, defined in "gen_myplugin.h"<br />
PLUGIN_NAME, // name/title of the plugin, defined in "gen_myplugin.h"<br />
init, // function name which will be executed on init event<br />
config, // function name which will be executed on config event<br />
quit, // function name which will be executed on quit event<br />
0, // handle to Winamp main window, loaded by winamp when this dll is loaded<br />
0 // hinstance to this dll, loaded by winamp when this dll is loaded<br />
};<br />
<br />
<br />
// event functions follow<br />
<br />
int init() {<br />
//A basic messagebox that tells you the 'init' event has been triggered.<br />
//If everything works you should see this message when you start Winamp once your plugin has been installed.<br />
//You can change this later to do whatever you want (including nothing)<br />
MessageBox(plugin.hwndParent, L"Init event triggered for gen_myplugin. Plugin installed successfully!", L"", MB_OK);<br />
return 0;<br />
}<br />
<br />
void config() {<br />
//A basic messagebox that tells you the 'config' event has been triggered.<br />
//You can change this later to do whatever you want (including nothing)<br />
MessageBox(plugin.hwndParent, L"Config event triggered for gen_myplugin.", L"", MB_OK);<br />
}<br />
<br />
void quit() {<br />
//A basic messagebox that tells you the 'quit' event has been triggered.<br />
//If everything works you should see this message when you quit Winamp once your plugin has been installed.<br />
//You can change this later to do whatever you want (including nothing)<br />
MessageBox(0, L"Quit event triggered for gen_myplugin.", L"", MB_OK);<br />
}<br />
<br />
<br />
// This is an export function called by winamp which returns this plugin info.<br />
// We wrap the code in 'extern "C"' to ensure the export isn't mangled if used in a CPP file.<br />
extern "C" __declspec(dllexport) winampGeneralPurposePlugin * winampGetGeneralPurposePlugin() {<br />
return &plugin;<br />
}<br />
</source><br />
<nowiki><end basic gen_myplugin.cpp></nowiki><br />
<br />
=== winampGeneralPurposePlugin===<br />
You might be wondering why the last two fields in the winampGeneralPurposePlugin structure are left empty. You might have noticed the reference that is returned as part of the winampGetGeneralPurposePlugin() method. This is the method that the Winamp.exe calls when loading these gen_*.dll files. As part of loading the plugin, the Winamp.exe will store the handle to its main window and the hinstance for the plugin dll into these two fields. Since these are references, these values become available for use by the plugin.<br />
=== Edit dependencies ===<br />
<br />
By default Visual Studio removes some files we need to compile our code. Let's add those back in:<br />
<br />
# Right-click on your project (the folder called 'gen_myplugin' in the Solution Explorer window on the left) and select Properties<br />
# Expand the options to select Configuration Properties -> Linker -> Input<br />
# In the "Additional Dependancies" box, delete the text that says '$(NoInherit)', so the box is blank.<br />
# Click 'Apply', then 'OK', and then save your project.<br />
<br />
=== Compiling the code ===<br />
<br />
Once you have pasted this code into your .h and .cpp files, save your changes and compile the project. You can do this by pressing F7, or selecting Build -> Build Solution. If everything works, you should see some messages in Visual Studio's 'Output' window, with the final line saying something like<br />
<br />
"========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped =========="<br />
<br />
If so, congratulations! You have built your first plugin :) If instead you get an error message, please see the [[Beginner's Basic Plugin Guide#Troubleshooting|Troubleshooting]] section below.<br />
<br />
=== Testing the plugin ===<br />
<br />
If your project builds successfully, it will output a file called 'gen_myplugin.dll' into a 'Debug' or 'Release' folder in the same location you created your project. Look for that file now. We want to copy this file to C:\Program Files\Winamp\Plugins\, which is the folder Winamp examines to find all of its plugins.<br />
<br />
# Copy your plugin .dll file into C:\Program Files\Winamp\Plugins\<br />
# Close and re-open Winamp. If your plugin is installed correctly, you should see a popup window with the Init message you typed inside gen_myplugin.cpp. If so, congrats! Your plugin works.<br />
# You can check to see your plugin name by clicking Options -> Preferences -> Plugins -> General purpose. Your plugin name should appear in that window.<br />
# Click on your plugin to hilight it and then select the 'Configure Selected Plugin' button. This should cause the 'config' message to appear.<br />
# If you exit Winamp, you should now see the Quit message pop up as the program exits.<br />
<br />
=== Bonus Step - automatically copy the .dll ===<br />
If you want you can tell Visual Studio to copy your .dll to the Winamp plugins folder as part of the build process. It's optional but can save you copying it every time. To do this:<br />
<br />
# Right-click on your project and select Properties<br />
# Open 'Configuration Properties' -> 'Build Events' -> 'Post Build Event'<br />
# In the Command Line type <pre>copy $(OutDir)\$(TargetFileName) "C:\Program Files\Winamp\Plugins"</pre><br />
# Enter some Description, such as "copy dll to winamp plugins folder"<br />
# Click 'OK'<br />
<br />
The next time you build your project the .dll will be copied over automatically. Be careful - this means you will always overwrite any existing .dll. Once you are finished making your plugin you may want to remove this step. Also, keep a backup copy.<br />
<br />
== What's next? ==<br />
<br />
So what's next? More guides still need to be written. Eventually there may be a guide for each type of plugin: [[Input_Plugin|Input]], [[Output_Plugin|Output]], [[Visualization_Plugin|Visualization]], [[DSP_Plugin|Audio Effect/DSP]], [[General_Purpose_Plugin|General Purpose]], [[Media_Library_Plugin|Media Library]] and [[Portable_Plugin|Portables]].<br />
<br />
If you're looking to write a plugin, you may want to start by reading through the [[SDK_Contents]] and trying to find a code example that's similar to what you want to do.<br />
<br />
Taking this page as a start of a tutorial on plugins, let's move on to actually calling the Winamp 2 API methods from within our newly created plugin. [[Basic Plugin Guide - Tutorial #2]]<br />
<br />
----<br />
<br />
== Troubleshooting ==<br />
* '''I get an error message that looks like:'''<br />
<br />
<pre><br />
1>gen_myplugin.obj : error LNK2028: unresolved token (0A00001D) "extern "C" int __stdcall <br />
MessageBoxW(struct HWND__ *,wchar_t const *,wchar_t const *,unsigned int)" (?MessageBoxW@@$$J216YGHPAUHWND__@@PB_W1I@Z)<br />
referenced in function "extern "C" int __cdecl MessageBox(struct HWND__ *,wchar_t const *,wchar_t const *,unsigned int)"<br />
(?MessageBox@@$$J0YAHPAUHWND__@@PB_W1I@Z)<br />
<br />
1>gen_myplugin.obj : error LNK2019: unresolved external symbol "extern "C" int __stdcall<br />
MessageBoxW(struct HWND__ *,wchar_t const *,wchar_t const *,unsigned int)" (?MessageBoxW@@$$J216YGHPAUHWND__@@PB_W1I@Z)<br />
referenced in function "extern "C" int __cdecl MessageBox(struct HWND__ *,wchar_t const *,wchar_t const *,unsigned int)" <br />
(?MessageBox@@$$J0YAHPAUHWND__@@PB_W1I@Z)<br />
</pre><br />
<br />
:'''Answer:''' By default Visual Studio Express 2008 doesn't include some files you need in the linker. For example, with our basic code we include windows.h, which is part of user32.dll. However, there is usually a '$(NoInherit)' command in our linker options that tell us not to include user32.dll. To fix this, try the following:<br />
<br />
# Right-click on your project and select Properties<br />
# Expand the options to select Configuration Properties -> Linker -> Input<br />
# In the "Additional Dependancies" box, delete the text that says '$(NoInherit)'.<br />
# Save and recompile<br />
<br />
Note:<br />
In Visual Studio Express 2010 the option is empty per default.<br />
This can be solved by changing the Configuration -> Properties -> Linker -> Input -> "Additional Dependancies" to the following: <br />
"kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)"<br />
<br />
For more information see [http://stackoverflow.com/questions/739952/c-cli-linker-gives-unresolved-token-for-win32-function here] and [http://stackoverflow.com/questions/721387/i-get-lnk2028-when-trying-to-wrap-native-c-class-using-managed-c here].<br />
<br />
* '''* I get an error like'''<br />
<pre><br />
"1>.\gen_myplugin.cpp(25) : error C2146: syntax error : missing ';' before identifier 'plugin'"<br />
</pre><br />
<br />
:'''Answer:''' This could be a namespace error. On this line<br />
<br />
<source lang="cpp"><br />
winampGeneralPurposePlugin plugin = {<br />
</source><br />
<br />
we are creating a variable called 'plugin'. The variable's type, rather than being an integer ('int'), floating point number ('float'), or some other type, is of type 'winampGeneralPurposePlugin', which is a type we have created. This type is created in the header file with the code<br />
<br />
<source lang="cpp"><br />
typedef struct {<br />
int version; <br />
char *description; <br />
int (*init)(); <br />
void (*config)(); <br />
void (*quit)(); <br />
HWND hwndParent; <br />
HINSTANCE hDllInstance; <br />
} winampGeneralPurposePlugin;<br />
</source><br />
<br />
If you used Visual Studio's auto-generated code, you might have a line that looks like this:<br />
<br />
<source lang="cpp"><br />
namespace myplugin {<br />
</source><br />
<br />
<br />
this line is telling Visual Studio to put everything inside the 'myplugin' namespace (read up on namespaces [http://en.wikipedia.org/wiki/Namespace here]). We get rid of the default boilerplate code, including the namespace, to make everything work.<br />
<br />
Alternatively, you can change the declaration of the 'plugin' variable to say<br />
<br />
<source lang="cpp"><br />
myplugin::winampGeneralPurposePlugin plugin = {<br />
</source><br />
<br />
This tells Visual Studio where to look for the winampGeneralPurposePlugin type (i.e., to look inside the 'myplugin' namespace). If you are new to programming or plugin creation, however, you probably don't need (or want) to mess with namespaces.<br />
<br />
* '''I get an error like'''<br />
<br />
<pre><br />
1>.\gen_myplugin.cpp(42) : error C2664: 'MessageBox' : cannot convert parameter 2 from 'const char [5]' to 'LPCTSTR'<br />
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast<br />
</pre><br />
<br />
:'''Answer:''' You need to change the string you pass to the MessageBox function to be of the right type. See the MSDN FAQ entry [http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/c1b08c0a-a803-41c3-ac8c-84eba3be1ddb here]. You can most likely fix this by putting a capital 'L' in front of the string.<br />
<br />
e.g. change <source lang="cpp">MessageBox(plugin.hwndParent, "Somestring", "", MB_OK);</source> to <source lang="cpp">MessageBox(plugin.hwndParent, L"Somestring", L"", MB_OK);</source><br />
<br />
TODO: What's the right way of doing this for plugins?<br />
<pre> The answer here is to leave the Visual Studio option alone (set to use UNICODE) <br />
and use the 'L' on the front of the strings. While you will find some parts of <br />
Winamp still use ANSI strings, it is still meant to be an International application <br />
and that means UNICODE.</pre><br />
<br />
* '''My plugin isn't working / My plugin doesn't show up in the Preferences menu.'''<br />
<br />
:'''Answer:'''Did you name your plugin with the correct prefix, such as 'gen_myplugin'? If not it may not show up in the window.<br />
<br />
TODO: How about other names/plugins? What's the real answer?<br />
<pre> There are two commonly used methods to create plugins. The first is what is known as <br />
Winamp 2, which we will get into shortly. Winamp 2 requires that plugins be prepended <br />
with an identifier to their purpose, i.e., in_, out_, gen_, ml_, etc.<br />
<br />
The second method is known as Wasabi, which is actually a framework used to share <br />
information between application components. Wasabi files do not need a prefix.<br />
</pre><br />
[[Category:Articles]]</div>Culixhttp://wiki.shoutcast.com/wiki/Beginner%27s_Basic_Plugin_GuideBeginner's Basic Plugin Guide2011-01-15T03:50:24Z<p>Culix: /* Basic plugin code */ add #endif comment</p>
<hr />
<div>So you want to write a plugin for Winamp but don't know where to start? This is the page for you. We'll walk you through creating a very basic plugin that does '''nothing'''. You can then expand on the code to do whatever you want.<br />
<br />
==Notes==<br />
This guide assumes you're developing using Visual Studio in a Windows environment. It also assumes you have some familiarity with programming. For people that don't, try using google. We'll have to expand this guide in the future to give out more pointers.<br />
<br />
== Basic credits ==<br />
The following code has been created based on samples from [http://forums.winamp.com/showthread.php?s=&threadid=128915 several] [http://forums.winamp.com/showthread.php?s=&threadid=82651 forum] [http://forums.winamp.com/showthread.php?s=&threadid=103667 threads]. Many thanks go out to forum members Kaboon, kichik, baafie, burek021, and bananskib for their code examples and advice.<br />
<br />
== What you need ==<br />
To begin, you'll need a tool that lets you write code. Check out the [[Plug-in_Developer#Tools|Tools]] page. You can get a free copy of Visual Studio C++ Express [http://www.microsoft.com/Express/ here]. You'll probably also want a copy of Winamp itself, to test your plugin; you can get that on the Winamp site [http://www.winamp.com/player here].<br />
<br />
# Download [http://www.microsoft.com/Express/ Visual C++ Express].<br />
# Double-click the file (it's probably called something like 'vcsetup.exe') and run the installer.<br />
# You're practically good to go!<br />
<br />
== Creating a project ==<br />
The first thing we need to do is create a place to store our code. In Visual Studio this is called a 'project'.<br />
<br />
# Launch Visual Studio by clicking Start -> Programs -> Microsoft Visual C++ Express Edition -> Microsoft Visual C++ Express Edition<br />
# When Visual Studio opens, select File -> New -> Project<br />
# For creating Winamp plugins, we want to create code that compiles into a .dll, which Visual Studio 2008 refers to as a "Class Library". So in the 'New Project' window select Visual C++ -> CLR -> Class Library.<br />
# Give your project a name (see below) and select a location.<br />
<br />
'''Note:''' Winamp classifies plugins based on the first part of their .dll filename, so you will need to properly name the file if you want Winamp to recognize it (details: the Winamp client searches for and loads plugins based on the first part of their filenames. This saves time and space instead of loading all dlls and then detecting which ones are real plugins). Thus, to make our basic plugin we want to name the first part of the file 'gen_'. '''Be sure to start your plugin name with 'gen_' to make it work properly.'''<br />
<br />
All of the examples in this guide will assume you named your plugin 'gen_myplugin', but you can call it whatever you like as long as it starts with 'gen_' (for generic plugin) and ends with '.dll'.<br />
<br />
Once you click okay Visual Studio should create a bunch of boilerplate code for you, and throw some files in your project with names like "resource.h", "stdafx.h", "AssemblyInfo.cpp", and so on. The main files we want to work with are called 'gen_myplugin.h' and 'gen_myplugin.cpp'. If you double-click to view them you should see code that looks something like this:<br />
<br />
<nowiki><contents of gen_myplugin.h></nowiki><br />
<source lang="cpp"><br />
// gen_myplugin.h<br />
<br />
#pragma once<br />
<br />
using namespace System;<br />
<br />
namespace gen_myplugin {<br />
<br />
public ref class Class1<br />
{<br />
// TODO: Add your methods for this class here.<br />
};<br />
}<br />
</source><br />
<nowiki><end contents of gen_myplugin.h></nowiki><br />
<br />
<nowiki><contents of gen_myplugin.cpp></nowiki><br />
<source lang="cpp"><br />
// This is the main DLL file.<br />
<br />
#include "stdafx.h"<br />
<br />
#include "gen_myplugin.h"<br />
<br />
</source><br />
<nowiki><end contents of gen_myplugin.cpp></nowiki><br />
<br />
<br />
We want to edit these files to make a basic plugin.<br />
<br />
== Creating a basic plugin ==<br />
<br />
=== Basic plugin code ===<br />
To create your plugin, just copy/paste the following code into gen_myplugin.h and gen_myplugin.cpp.<br />
<br />
<nowiki><basic gen_myplugin.h></nowiki><br />
<source lang="cpp"><br />
<br />
#ifndef gen_myplugin_h<br />
//---------------------------------------------------------------------------<br />
#define gen_myplugin_h<br />
#include <windows.h><br />
<br />
<br />
// plugin version (don't touch this)<br />
#define GPPHDR_VER 0x10<br />
<br />
// plugin name/title (change this to something you like)<br />
#define PLUGIN_NAME "My first generic Winamp plugin!"<br />
<br />
<br />
// main structure with plugin information, version, name...<br />
typedef struct {<br />
int version; // version of the plugin structure<br />
char *description; // name/title of the plugin <br />
int (*init)(); // function which will be executed on init event<br />
void (*config)(); // function which will be executed on config event<br />
void (*quit)(); // function which will be executed on quit event<br />
HWND hwndParent; // hwnd of the Winamp client main window (stored by Winamp when dll is loaded)<br />
HINSTANCE hDllInstance; // hinstance of this plugin DLL. (stored by Winamp when dll is loaded) <br />
} winampGeneralPurposePlugin;<br />
<br />
<br />
#endif //gen_myplugin_h<br />
</source><br />
<nowiki><end basic gen_myplugin.h></nowiki><br />
<br />
<nowiki><basic gen_myplugin.cpp></nowiki><br />
<source lang="cpp"><br />
/*<br />
<br />
Winamp generic plugin template code.<br />
This code should be just the basics needed to get a plugin up and running.<br />
You can then expand the code to build your own plugin.<br />
<br />
Updated details compiled June 2009 by culix, based on the excellent code examples<br />
and advice of forum members Kaboon, kichik, baafie, burek021, and bananskib.<br />
Thanks for the help everyone!<br />
<br />
*/<br />
<br />
#include "stdafx.h"<br />
#include <windows.h><br />
#include "gen_myplugin.h"<br />
<br />
<br />
// these are callback functions/events which will be called by Winamp<br />
int init(void);<br />
void config(void);<br />
void quit(void);<br />
<br />
<br />
// this structure contains plugin information, version, name...<br />
// GPPHDR_VER is the version of the winampGeneralPurposePlugin (GPP) structure<br />
winampGeneralPurposePlugin plugin = {<br />
GPPHDR_VER, // version of the plugin, defined in "gen_myplugin.h"<br />
PLUGIN_NAME, // name/title of the plugin, defined in "gen_myplugin.h"<br />
init, // function name which will be executed on init event<br />
config, // function name which will be executed on config event<br />
quit, // function name which will be executed on quit event<br />
0, // handle to Winamp main window, loaded by winamp when this dll is loaded<br />
0 // hinstance to this dll, loaded by winamp when this dll is loaded<br />
};<br />
<br />
<br />
// event functions follow<br />
<br />
int init() {<br />
//A basic messagebox that tells you the 'init' event has been triggered.<br />
//If everything works you should see this message when you start Winamp once your plugin has been installed.<br />
//You can change this later to do whatever you want (including nothing)<br />
MessageBox(plugin.hwndParent, L"Init event triggered for gen_myplugin. Plugin installed successfully!", L"", MB_OK);<br />
return 0;<br />
}<br />
<br />
void config() {<br />
//A basic messagebox that tells you the 'config' event has been triggered.<br />
//You can change this later to do whatever you want (including nothing)<br />
MessageBox(plugin.hwndParent, L"Config event triggered for gen_myplugin.", L"", MB_OK);<br />
}<br />
<br />
void quit() {<br />
//A basic messagebox that tells you the 'quit' event has been triggered.<br />
//If everything works you should see this message when you quit Winamp once your plugin has been installed.<br />
//You can change this later to do whatever you want (including nothing)<br />
MessageBox(0, L"Quit event triggered for gen_myplugin.", L"", MB_OK);<br />
}<br />
<br />
<br />
// This is an export function called by winamp which returns this plugin info.<br />
// We wrap the code in 'extern "C"' to ensure the export isn't mangled if used in a CPP file.<br />
extern "C" __declspec(dllexport) winampGeneralPurposePlugin * winampGetGeneralPurposePlugin() {<br />
return &plugin;<br />
}<br />
</source><br />
<nowiki><end basic gen_myplugin.cpp></nowiki><br />
<br />
=== winampGeneralPurposePlugin===<br />
You might be wondering why the last two fields in the winampGeneralPurposePlugin structure are left empty. You might have noticed the reference that is returned as part of the winampGetGeneralPurposePlugin() method. This is the method that the Winamp.exe calls when loading these gen_*.dll files. As part of loading the plugin, the Winamp.exe will store the handle to its main window and the hinstance for the plugin dll into these two fields. Since these are references, these values become available for use by the plugin.<br />
=== Edit dependencies ===<br />
<br />
By default Visual Studio removes some files we need to compile our code. Let's add those back in:<br />
<br />
# Right-click on your project (the folder called 'gen_myplugin' in the Solution Explorer window on the left) and select Properties<br />
# Expand the options to select Configuration Properties -> Linker -> Input<br />
# In the "Additional Dependancies" box, delete the text that says '$(NoInherit)', so the box is blank.<br />
# Click 'Apply', then 'OK', and then save your project.<br />
<br />
=== Compiling the code ===<br />
<br />
Once you have pasted this code into your .h and .cpp files, save your changes and compile the project. You can do this by pressing F7, or selecting Build -> Build Solution. If everything works, you should see some messages in Visual Studio's 'Output' window, with the final line saying something like<br />
<br />
"========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped =========="<br />
<br />
If so, congratulations! You have built your first plugin :) If instead you get an error message, please see the [[Beginner's Basic Plugin Guide#Troubleshooting|Troubleshooting]] section below.<br />
<br />
=== Testing the plugin ===<br />
<br />
If your project builds successfully, it will output a file called 'gen_myplugin.dll' into a 'Debug' or 'Release' folder in the same location you created your project. Look for that file now. We want to copy this file to C:\Program Files\Winamp\Plugins\, which is the folder Winamp examines to find all of its plugins.<br />
<br />
# Copy your plugin .dll file into C:\Program Files\Winamp\Plugins\<br />
# Close and re-open Winamp. If your plugin is installed correctly, you should see a popup window with the Init message you typed inside gen_myplugin.cpp. If so, congrats! Your plugin works.<br />
# You can check to see your plugin name by clicking Options -> Preferences -> Plugins -> General purpose. Your plugin name should appear in that window.<br />
# Click on your plugin to hilight it and then select the 'Configure Selected Plugin' button. This should cause the 'config' message to appear.<br />
# If you exit Winamp, you should now see the Quit message pop up as the program exits.<br />
<br />
== What's next? ==<br />
<br />
So what's next? More guides still need to be written. Eventually there may be a guide for each type of plugin: [[Input_Plugin|Input]], [[Output_Plugin|Output]], [[Visualization_Plugin|Visualization]], [[DSP_Plugin|Audio Effect/DSP]], [[General_Purpose_Plugin|General Purpose]], [[Media_Library_Plugin|Media Library]] and [[Portable_Plugin|Portables]].<br />
<br />
If you're looking to write a plugin, you may want to start by reading through the [[SDK_Contents]] and trying to find a code example that's similar to what you want to do.<br />
<br />
Taking this page as a start of a tutorial on plugins, let's move on to actually calling the Winamp 2 API methods from within our newly created plugin. [[Basic Plugin Guide - Tutorial #2]]<br />
<br />
----<br />
<br />
== Troubleshooting ==<br />
* '''I get an error message that looks like:'''<br />
<br />
<pre><br />
1>gen_myplugin.obj : error LNK2028: unresolved token (0A00001D) "extern "C" int __stdcall <br />
MessageBoxW(struct HWND__ *,wchar_t const *,wchar_t const *,unsigned int)" (?MessageBoxW@@$$J216YGHPAUHWND__@@PB_W1I@Z)<br />
referenced in function "extern "C" int __cdecl MessageBox(struct HWND__ *,wchar_t const *,wchar_t const *,unsigned int)"<br />
(?MessageBox@@$$J0YAHPAUHWND__@@PB_W1I@Z)<br />
<br />
1>gen_myplugin.obj : error LNK2019: unresolved external symbol "extern "C" int __stdcall<br />
MessageBoxW(struct HWND__ *,wchar_t const *,wchar_t const *,unsigned int)" (?MessageBoxW@@$$J216YGHPAUHWND__@@PB_W1I@Z)<br />
referenced in function "extern "C" int __cdecl MessageBox(struct HWND__ *,wchar_t const *,wchar_t const *,unsigned int)" <br />
(?MessageBox@@$$J0YAHPAUHWND__@@PB_W1I@Z)<br />
</pre><br />
<br />
:'''Answer:''' By default Visual Studio Express 2008 doesn't include some files you need in the linker. For example, with our basic code we include windows.h, which is part of user32.dll. However, there is usually a '$(NoInherit)' command in our linker options that tell us not to include user32.dll. To fix this, try the following:<br />
<br />
# Right-click on your project and select Properties<br />
# Expand the options to select Configuration Properties -> Linker -> Input<br />
# In the "Additional Dependancies" box, delete the text that says '$(NoInherit)'.<br />
# Save and recompile<br />
<br />
Note:<br />
In Visual Studio Express 2010 the option is empty per default.<br />
This can be solved by changing the Configuration -> Properties -> Linker -> Input -> "Additional Dependancies" to the following: <br />
"kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)"<br />
<br />
For more information see [http://stackoverflow.com/questions/739952/c-cli-linker-gives-unresolved-token-for-win32-function here] and [http://stackoverflow.com/questions/721387/i-get-lnk2028-when-trying-to-wrap-native-c-class-using-managed-c here].<br />
<br />
* '''* I get an error like'''<br />
<pre><br />
"1>.\gen_myplugin.cpp(25) : error C2146: syntax error : missing ';' before identifier 'plugin'"<br />
</pre><br />
<br />
:'''Answer:''' This could be a namespace error. On this line<br />
<br />
<source lang="cpp"><br />
winampGeneralPurposePlugin plugin = {<br />
</source><br />
<br />
we are creating a variable called 'plugin'. The variable's type, rather than being an integer ('int'), floating point number ('float'), or some other type, is of type 'winampGeneralPurposePlugin', which is a type we have created. This type is created in the header file with the code<br />
<br />
<source lang="cpp"><br />
typedef struct {<br />
int version; <br />
char *description; <br />
int (*init)(); <br />
void (*config)(); <br />
void (*quit)(); <br />
HWND hwndParent; <br />
HINSTANCE hDllInstance; <br />
} winampGeneralPurposePlugin;<br />
</source><br />
<br />
If you used Visual Studio's auto-generated code, you might have a line that looks like this:<br />
<br />
<source lang="cpp"><br />
namespace myplugin {<br />
</source><br />
<br />
<br />
this line is telling Visual Studio to put everything inside the 'myplugin' namespace (read up on namespaces [http://en.wikipedia.org/wiki/Namespace here]). We get rid of the default boilerplate code, including the namespace, to make everything work.<br />
<br />
Alternatively, you can change the declaration of the 'plugin' variable to say<br />
<br />
<source lang="cpp"><br />
myplugin::winampGeneralPurposePlugin plugin = {<br />
</source><br />
<br />
This tells Visual Studio where to look for the winampGeneralPurposePlugin type (i.e., to look inside the 'myplugin' namespace). If you are new to programming or plugin creation, however, you probably don't need (or want) to mess with namespaces.<br />
<br />
* '''I get an error like'''<br />
<br />
<pre><br />
1>.\gen_myplugin.cpp(42) : error C2664: 'MessageBox' : cannot convert parameter 2 from 'const char [5]' to 'LPCTSTR'<br />
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast<br />
</pre><br />
<br />
:'''Answer:''' You need to change the string you pass to the MessageBox function to be of the right type. See the MSDN FAQ entry [http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/c1b08c0a-a803-41c3-ac8c-84eba3be1ddb here]. You can most likely fix this by putting a capital 'L' in front of the string.<br />
<br />
e.g. change <source lang="cpp">MessageBox(plugin.hwndParent, "Somestring", "", MB_OK);</source> to <source lang="cpp">MessageBox(plugin.hwndParent, L"Somestring", L"", MB_OK);</source><br />
<br />
TODO: What's the right way of doing this for plugins?<br />
<pre> The answer here is to leave the Visual Studio option alone (set to use UNICODE) <br />
and use the 'L' on the front of the strings. While you will find some parts of <br />
Winamp still use ANSI strings, it is still meant to be an International application <br />
and that means UNICODE.</pre><br />
<br />
* '''My plugin isn't working / My plugin doesn't show up in the Preferences menu.'''<br />
<br />
:'''Answer:'''Did you name your plugin with the correct prefix, such as 'gen_myplugin'? If not it may not show up in the window.<br />
<br />
TODO: How about other names/plugins? What's the real answer?<br />
<pre> There are two commonly used methods to create plugins. The first is what is known as <br />
Winamp 2, which we will get into shortly. Winamp 2 requires that plugins be prepended <br />
with an identifier to their purpose, i.e., in_, out_, gen_, ml_, etc.<br />
<br />
The second method is known as Wasabi, which is actually a framework used to share <br />
information between application components. Wasabi files do not need a prefix.<br />
</pre><br />
[[Category:Articles]]</div>Culixhttp://wiki.shoutcast.com/wiki/ArticlesArticles2011-01-15T03:42:18Z<p>Culix: /* General */ add link</p>
<hr />
<div>{{Template:NavBar}}<br />
<br />
==Skin Articles==<br />
<br />
===Modern Skins===<br />
*[http://dev.aol.com/article/2007/winamp_skins Winamp Skins Development Tutorial]<br />
*[[Creating a ClassicPro Skin]]<br />
<br />
===ClassicPro Skins===<br />
* [[Creating a ClassicPro Skin]]<br />
<br />
==Visualization Articles==<br />
*[[MilkDrop_Preset_Authoring|MilkDrop Preset Authoring]]<br />
<br />
==Plug-in Articles==<br />
<br />
===General===<br />
*[[Plugin Terminology]]<br />
*[[Beginner's Basic Plugin Guide]]<br />
*[[Basic_Plugin_Guide_-_Tutorial#2|Basic Plugin Guide #2]]<br />
--<br />
* How To create:<br />
**[[APE Plugins|AVS Plugins]]<br />
**[[DSP Plugin|Audio Effects (DSP) plugins]]<br />
** [[General Purpose Plugin|General Purpose plugins]]<br />
** [[Input Plugin|Input plugins]]<br />
** [[Media Library Plugin|Media Library plugins]]<br />
** [[Output Plugin|Output plugins]]<br />
** [[Portable_Plugin|Portable_Plugins]]<br />
** [[Visualization_Plugin|Visualization_Plugins]]<br />
--<br />
* Overview of:<br />
**[[Audio Encoder Plugin|Audio encoders (transcoding, CD ripper)]]<br />
**[[JNetLib|JNetLib networking library]]<br />
**[[Nullsoft Database Engine|Nullsoft Database Engine (NDE)]]<br />
**[[NSV Plugins|NSV Audio and Video decoders]]<br />
**[[System Component Interface]]<br />
**[[Skinning Plugins|WAC Skinning plugins]]<br />
**[[Winamp Orgler]]<br />
**[[XML Parser Object]]<br />
<br />
===API===<br />
*[[Agave Config API]]<br />
*[[Agave Metadata API]]<br />
*[[Album Art API]]<br />
*[[Application API]]<br />
*[[Burner API]]<br />
*[[Decode File API]]<br />
*[[Language API]]<br />
*[[Playlist API]]<br />
*[[Podcasts API]]<br />
*[[Media Core API|Media Core API (Freeform skins only!)]]<br />
*[[Media Library API|Media Library SendMessage API]]<br />
*[[Memory Manager API]]<br />
*[[Random API]]<br />
*[[Replay Gain API]]<br />
*[[Service Manager API]]<br />
*[[Skin API]]<br />
*[[System Callbacks API]]<br />
*[[Tagz API]]<br />
*[[SendMessage API|Winamp 2 API]]<br />
*[[Wasabi|Overview of the Wasabi API]]<br />
<br />
===Services===<br />
*[[File Reader Service]]<br />
*[[Image Writer Service]]<br />
*[[Image Loader Service]]<br />
*[[Text Feed Service]]<br />
<br />
==Online Services Articles==<br />
* [[Tips for Writing an Awesome Online Service]]<br />
* [[Winamp Browser Support]]<br />
<br />
[[Category:Articles]]</div>Culixhttp://wiki.shoutcast.com/wiki/SHOUTcast_DeveloperSHOUTcast Developer2011-01-15T03:32:15Z<p>Culix: add navbar template</p>
<hr />
<div>{{Template:NavBar}}<br />
<br />
=Get Stations on SHOUTcast Radio Directory=<br />
<br />
==Get Top 500 Stations==<br />
'''<span style="color:#FF6600;">Description:</span>''' Get top 500 stations on SHOUTcast Radio directory.<br />
<br />
'''<span style="color:#FF6600;">URL:</span>''' <nowiki>http://api.shoutcast.com/legacy/Top500?k=[Your Dev ID]</nowiki><br />
<br />
'''<span style="color:#FF6600;">Required Parameters:</span>'''<br />
* k - API Dev Key. <br />
<br />
'''<span style="color:#FF6600;">Optional Parameters:</span>'''<br />
* limit - Limit the number of stations to return by passing the limit parameter.<br />
:'''Ex:''' <nowiki>http://api.shoutcast.com/legacy/Top500?k=[Your Dev ID]&limit=5</nowiki><br />
<br />
'''<span style="color:#FF6600;">Sample XML Response:</span>''' (with limits)<br />
<stationlist><br />
<tunein base="/sbin/tunein-station.pls"/><br />
<station name=".977 The Hitz Channel-[SHOUTcast.com]" mt="audio/mpeg" id="9907" br="128"<br />
genre="Pop Rock Top 40"ct="The Fray - You Found Me" lc="4670"/><br />
<station name="HOT FM - Lebih Hangat Daripada Biasa : HOT fm-[SHOUTcast.com]"<br />
mt="audio/mpeg" id="120149" br="24" genre="Malaysia<br />
Malay" ct="LELAKI IDAMAN MELLY_GOESLOW " lc="3961"/><br />
<station name="S K Y . F M - Absolutely Smooth Jazz - the world's smoothest jazz 24 hours a day-[SHOUTcast.com]"<br />
mt="audio/mpeg" id="1264" br="96" genre="Soft Smooth Jazz" <br />
ct="Oli Silk - De-stress Signal" lc="3507"/><br />
<station name="Groove Salad: a nicely chilled plate of ambient beats and grooves. [SomaFM]-[SHOUTcast.com]" <br />
mt="audio/mpeg" id="6687" br="128" genre="Ambient Chill"<br />
ct="Verbrilli Sound - Descender" lc="2680"/><br />
<station name=".977 The 80s Channel-[SHOUTcast.com]" mt="audio/mpeg" id="6803" <br />
br="128" genre="80s Pop Rock" ct="Starship - Nothing`s gonna stop us now (1987)" lc="2192"/><br />
<station name="The Alex Jones Show-[SHOUTcast.com]" mt="audio/mpeg" id="5516" br="32" genre="Talk" <br />
ct="Refeed: Hour 1 (Listen by phone 512-646-5000)" lc="1987"/><br />
</stationlist><br />
<br />
<br />
==Get Stations by Keyword Search==<br />
'''<span style="color:#FF6600;">Description:</span>''' Get stations which match the keyword searched on SHOUTcast Radio Directory.<br />
:'''Note:''' This API returns stations which has keyword match in the following fields Station Name, Now Playing info, Genre.<br />
<br />
'''<span style="color:#FF6600;">URL:</span>''' <nowiki>http://api.shoutcast.com/legacy/stationsearch?k=[Your Dev ID]&search=ambient+beats</nowiki><br />
<br />
'''<span style="color:#FF6600;">Required Parameters:</span>'''<br />
* search - Specify the query to search.<br />
* k - API Dev ID. <br />
<br />
'''<span style="color:#FF6600;">Optional Parameters:</span>'''<br />
* limit - Limits the no of results to be returned.<br />
:'''Ex:''' <nowiki>http://api.shoutcast.com/legacy/stationsearch?k=[Your Dev ID]&search=ambient+beats&limit=10</nowiki><br />
<br />
* limit with pagination - Limits the no of results with pagination included.<br />
:'''Ex:''' <nowiki>http://api.shoutcast.com/legacy/stationsearch?k=[Your Dev ID]&search=ambient+beats&limit=X,Y</nowiki><br />
:* Y is the number of results to return and X is the offset. <br />
<br />
* Filter by Codec type - Get stations which match the codec type requested.<br />
:'''Ex:''' <nowiki>http://api.shoutcast.com/legacy/stationsearch?k=[Your Dev ID]&search=ambient+beats&mt=audio/mpeg</nowiki><br />
:MP3 = audio/mpeg and AAC+ = audio/aacp<br />
<br />
'''<span style="color:#FF6600;">Sample XML Response:</span>'''<br />
<stationlist><br />
<tunein base="/sbin/tunein-station.pls"></tunein><br />
<station name="Groove Salad: a nicely chilled plate of ambient beats and grooves. [SomaFM]-[SHOUTcast.com]"<br />
mt="audio/mpeg" id="6687" br="128" genre="Ambient Chill" ct="Audiomontage - Abyss" lc="241"><br />
</station><br />
<station name="((Metaphoric.me))128k Room42, ambient beats and chill grooves-[SHOUTcast.com]"<br />
mt="audio/mpeg" id="8434" br="128" genre="Ambient Chill" ct="Jazz City - La Noche (Smooth Latin Groove Mix)" lc="83"><br />
</station><br />
<station name="Groove Salad: a nicely chilled plate of ambient beats and grooves. [SomaFM]-[SHOUTcast.com]"<br />
mt="audio/mpeg" id="8010" br="24" genre="Ambient Chill" ct="Audiomontage - Abyss" lc="54"><br />
</station><br />
<station name="Groove Salad: a nicely chilled plate of ambient beats and grooves. [SomaFM]-[SHOUTcast.com]"<br />
mt="audio/mpeg" id="9073" br="56" genre="Ambient Chill" ct="Warheads - Daphne" lc="30"><br />
</station><br />
</stationlist><br />
<br />
<br />
==Get Stations by Genre==<br />
'''<span style="color:#FF6600;">Description:</span>''' Get stations which match the genre specified as query.<br />
<br />
'''<span style="color:#FF6600;">URL:</span>''' <nowiki>http://api.shoutcast.com/legacy/genresearch?k=[Your Dev ID]&genre=classic</nowiki><br />
<br />
'''<span style="color:#FF6600;">Required Parameters:</span>'''<br />
* k - API Dev ID.<br />
<br />
'''<span style="color:#FF6600;">Optional Parameters:</span>'''<br />
* limit - Limits the no of results to be returned.<br />
<br />
* limit with pagination - Limits the no of results with pagination included.<br />
:'''Ex:''' <nowiki>http://api.shoutcast.com/legacy/genresearch?k=[Your Dev ID]&genre=classic&limit=X,Y</nowiki><br />
:* Y is the number of results to return and X is the offset.<br />
<br />
* Filter by Codec type - Get stations which match the codec type requested.<br />
:'''Ex:''' <nowiki>http://api.shoutcast.com/legacy/genresearch?k=[Your Dev ID]&genre=classic&&mt=audio/aacp</nowiki><br />
:MP3 = audio/mpeg and AAC+ = audio/aacp.<br />
<br />
'''<span style="color:#FF6600;">Sample XML Response:</span>'''<br />
<stationlist><br />
<tunein base="/sbin/tunein-station.pls"/><br />
<station name=".977 The Hitz Channel-[SHOUTcast.com]" mt="audio/mpeg" id="9907" br="128"<br />
genre="Pop Rock Top 40" ct="The Fray - You Found Me" lc="4670"/><br />
<station name="HOT FM - Lebih Hangat Daripada Biasa : HOT fm-[SHOUTcast.com]" mt="audio/mpeg" <br />
id="120149" br="24" genre="Malaysia Malay"<br />
ct="LELAKI IDAMAN MELLY_GOESLOW " lc="3961"/><br />
<station name="S K Y . F M - Absolutely Smooth Jazz - the world's smoothest jazz 24 hours a day-[SHOUTcast.com]"<br />
mt="audio/mpeg" id="1264" br="96" genre="Softsmooth Jazz"<br />
ct="Oli Silk -De-stress Signal" lc="3507"/><br />
<station name="Groove Salad: a nicely chilled plate of ambient beats and grooves. [SomaFM]-[SHOUTcast.com]"<br />
mt="audio/mpeg" id="6687" br="128" genre="AmbientChill"<br />
ct="Verbrilli Sound - Descender" lc="2680"/><br />
</stationlist><br />
<br />
<br />
==Get Stations Based on Now Playing Info==<br />
'''<span style="color:#FF6600;">Description:</span>''' Return stations which match a specified query in the now playing node.<br />
<br />
'''<span style="color:#FF6600;">URL:</span>'''<br />
<nowiki>http://api.shoutcast.com/station/nowplaying?k=[Your Dev ID]&ct=rihanna&f=xml</nowiki><br />
<br />
'''<span style="color:#FF6600;">Required Parameters:</span>'''<br />
* ct - Query to search in Now Playing node.<br />
* f - the response format (xml, json, rss). You can choose xml,json or rss based results.<br />
* k - API Dev ID. <br />
<br />
'''<span style="color:#FF6600;">Optional Parameters:</span>'''<br />
* c - The callback function to invoke in the response (appropriate for JSON responses only).<br />
* limit - Limits the no of results to be returned in output.<br />
<br />
'''<span style="color:#FF6600;">Sample XML Response:</span>'''<br />
<response><br />
<statusCode>200</statusCode><br />
<statusText>Ok</statusText><br />
<data><br />
<stationlist><br />
<tunein base="/sbin/tunein-station.pls"/><br />
<station name="Dj Wouner- Radio Fusion-A novidade come?a Aqui!-[SHOUTcast.com]" mt="audio/mpeg" id="139549" <br />
br="64" genre="Various"ct="Rihanna Feat. Chris Brown & Jay-Z - Umbrella" lc="614" ml="2100" nsc="No"/><br />
<station name="R?dio Stronda [ Digital ] Servidor 4-[SHOUTcast.com]" mt="audio/mpeg" id="998783" br="64" <br />
genre="Pop Top Rock Funk Str"ct="T.I. feat Rihanna -Live Your Life" lc="243" ml="70" nsc="No"/><br />
.<br />
.<br />
</stationlist> <br />
</data><br />
</response><br />
<br />
'''<span style="color:#FF6600;">URL (JSON Request):</span>'''<br />
<br />
<nowiki>http://api.shoutcast.com/station/nowplaying?ct=rihanna&f=json&k=[Your Dev ID]</nowiki><br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response:</span>'''<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok"<br />
},<br />
"data":"{<br />
"stationlist":{<br />
"station":[<br />
"tunein":{<br />
"base":"/sbin/tunein-station.pls"<br />
}<br />
{"nsc":"No","genre":"Various","id":"139549","mt":"audio/mpeg","name":"Dj Wouner- <br />
RadioFusion-A novidadecome?a Aqui!-[SHOUTcast.com]","lc":"614","ml":"2100","br":"64",<br />
"ct":"Rihanna Feat. Chris Brown& Jay-Z - Umbrella"},<br />
{"nsc":"No","genre":"Pop Top Rock Funk Str","id":"998783",<br />
"mt":"audio/mpeg","name":"R?dio Stronda[ Digital ] Servidor<br />
4-[SHOUTcast.com]","lc":"243","ml":"70","br":"64","ct":"T.I. feat Rihanna - Live Your ife"},<br />
.<br />
.<br />
]<br />
}<br />
}<br />
}<br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response (with callback):</span>'''<br />
callbackfunctionname(<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok"<br />
},<br />
"data":"{<br />
"stationlist":{<br />
"station":[<br />
"tunein":{<br />
"base":"/sbin/tunein-station.pls"<br />
}<br />
{"nsc":"No","genre":"Various","id":"139549","mt":"audio/mpeg","name":"Dj Wouner- <br />
RadioFusion-A novidadecome?a Aqui!-[SHOUTcast.com]","lc":"614","ml":"2100","br":"64",<br />
"ct":"Rihanna Feat. Chris Brown& Jay-Z - Umbrella"},<br />
{"nsc":"No","genre":"Pop Top Rock Funk Str","id":"998783",<br />
"mt":"audio/mpeg","name":"R?dio Stronda[ Digital ] Servidor<br />
4-[SHOUTcast.com]","lc":"243","ml":"70","br":"64","ct":"T.I. feat Rihanna - Live Your ife"},<br />
.<br />
.<br />
]<br />
}<br />
}<br />
}<br />
)<br />
<br />
<br />
==Get Stations by Bitrate or Codec Type==<br />
'''<span style="color:#FF6600;">Description:</span>''' Get stations which match a particular bitrate or codec type.<br />
<br />
'''<span style="color:#FF6600;">URL:</span>'''<br />
:* Stations filtered by bitrate<br />
::<nowiki>http://api.shoutcast.com/station/advancedsearch?br=128&limit=10&f=xml&k=[Your Dev ID]</nowiki><br />
<br />
:* Stations filtered by media type<br />
::<nowiki>http://api.shoutcast.com/station/advancedsearch?mt=audio/mpeg&limit=10&f=xml&k=[Your Dev ID]</nowiki><br />
<br />
:* Stations filtered by bitrate, media type & genre<br />
::<nowiki>http://api.shoutcast.com/station/advancedsearch?mt=audio/mpeg&br=128&search=Trance&&limit=10&f=xml&k=[Your Dev ID]</nowiki><br />
<br />
'''<span style="color:#FF6600;">Required Parameters:</span>'''<br />
<br />
* f - the response format (xml, json, rss). You can choose xml,json or rss based results.<br />
* k - API Dev ID. <br />
* br - Filter the stations based on bitrate specified.<br />
* mt - Filter the stations based on media type specified.<br />
<br />
'''<span style="color:#FF6600;">Optional Parameters:</span>'''<br />
<br />
* c - The callback function to invoke in the response (appropriate for JSON responses only). <br />
* limit - Limits the no of results to be returned in output.<br />
* genre - Filter stations that match the genre passed.<br />
<br />
'''<span style="color:#FF6600;">Sample XML Response:</span>'''<br />
<response><br />
<statusCode>200</statusCode><br />
<statusText>Ok</statusText><br />
<data><br />
<stationlist><br />
<tunein base="/sbin/tunein-station.pls"/><br />
<station name=".977 The Hitz Channel" mt="audio/mpeg" id="9907" <br />
br="128" genre="Pop Rock Top 40"<br />
ct="Chingy - Balla Baby" lc="11576"/><br />
<station name="TechnoBase.FM - 24h Techno, Dance, Trance, House and More - 128k MP3-[SHOUTcast.com]"<br />
mt="audio/mpeg"id="7429" br="128"genre="Techno Trance Dance House"<br />
ct="We aRe oNe" lc="8308" ml="8500" nsc="No"/><br />
<station name="Absolutely Smooth Jazz - S K Y . F M - the world's smoothest<br />
jazz 24 hours a day-[SHOUTcast.com]" mt="audio/mpeg" id="948"br="96" genre="Soft Smooth Jazz"<br />
ct="Jonathan Butler/Kirk Whalum - Dancing on the Shore" lc="6801" ml="10023" nsc="No"/><br />
.<br />
.<br />
</stationlist> <br />
</data><br />
</response><br />
<br />
'''<span style="color:#FF6600;">URL (JSON Request):</span>'''<br />
* Stations based on bitrate<br />
:<nowiki>http://api.shoutcast.com/station/advancedsearch?br=128&limit=3&f=json&k=[Your Dev ID]</nowiki><br />
<br />
* Stations based on media type<br />
:<nowiki>http://api.shoutcast.com/station/advancedsearch?mt=mpeg&limit=3&f=json&k=[Your Dev ID]</nowiki><br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response:</span>'''<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok"<br />
},<br />
"data":"{<br />
"stationlist":{<br />
"station":[<br />
"tunein":{<br />
"base":"/sbin/tunein-station.pls"<br />
}<br />
{"nsc":"No","genre":"Pop Rock Top 40","id":"9907",mt":"audio/mpeg","name":".977 The<br />
HitzChannel-[SHOUTcast.com]","lc":"11576","ml":"8500","br":"128","ct":"Chingy - Balla Baby"},<br />
{"nsc":"No","genre":"Techno Trance<br />
DanceHouse","id":"7429","mt":"audio/mpeg",<br />
"name":"TechnoBase.FM - 24h<br />
Techno, Dance,Trance, House and More -128kMP3-[SHOUTcast.com]","lc":"8308","ml":"10023",<br />
"br":"128","ct":"We aRe oNe"},<br />
{"nsc":"No","genre":"Soft Smooth Jazz","id":"948","mt":"audio/mpeg",<br />
"name":"Absolutely Smooth Jazz - S K Y . F M - the world's<br />
smoothest jazz 24hours a day-[SHOUTcast.com]","lc":"6801","ml":"18600","br":"96",<br />
"ct":"Jonathan Butler/Kirk Whalum - Dancing on the Shore"},<br />
.<br />
.<br />
]<br />
}<br />
}<br />
}<br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response (with callback):</span>'''<br />
callbackfunctionname(<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok"<br />
},<br />
"data":"{<br />
"stationlist":{<br />
"station":[<br />
"tunein":{<br />
"base":"/sbin/tunein-station.pls"<br />
}<br />
{"nsc":"No","genre":"Pop Rock Top 40","id":"9907",mt":"audio/mpeg","name":".977 The<br />
HitzChannel-[SHOUTcast.com]","lc":"11576","ml":"8500","br":"128","ct":"Chingy - Balla Baby"},<br />
{"sc":"No","genre":"Techno Trance<br />
DanceHouse","id":"7429","mt":"audio/mpeg",<br />
"name":"TechnoBase.FM - 24h<br />
Techno, Dance,Trance, House and More -128kMP3-[SHOUTcast.com]","lc":"8308",<br />
"ml":"10023","br":"128","ct":"We aRe oNe"},<br />
{"nsc":"No","genre":"Soft Smooth Jazz","id":"948","mt":"audio/mpeg",<br />
"name":"Absolutely Smooth Jazz - S K Y . F M - the world's<br />
smoothest jazz 24hours a day-[SHOUTcast.com]","lc":"6801","ml":"18600","br":"96",<br />
"ct":"Jonathan Butler/Kirk Whalum - Dancing on the Shore"},<br />
.<br />
.<br />
]<br />
}<br />
}<br />
}<br />
)<br />
<br />
<br />
==Get Random Stations==<br />
'''<span style="color:#FF6600;">Description:</span>''' Get random stations on SHOUTcast Radio Directory. Random stations can be restricted to the Bitrate/Genre/Media type specified.<br />
<br />
'''<span style="color:#FF6600;">URL:</span>'''<br />
<br />
:* <nowiki>http://api.shoutcast.com/station/randomstations?k=[Your Dev ID]&f=xml</nowiki><br />
::Returns a random station. This API by default returns one random station.<br />
::To get more random stations, set the number of stations to return by passing the limit parameter.<br />
<br />
:* <nowiki>http://api.shoutcast.com/station/randomstations?k=[Your Dev ID]&f=xml&mt=audio/mpeg&br=128&genre=Fresh</nowiki><br />
::Returns a random station. This API by default returns one random station.<br />
::To get more random stations, set the number of stations to return by passing the limit parameter.<br />
<br />
'''<span style="color:#FF6600;">Required Parameters:</span>'''<br />
* f - the response format (xml, json, rss). You can choose xml,json or rss based results.<br />
* k - API Dev ID. <br />
<br />
'''<span style="color:#FF6600;">Optional Parameters:</span>'''<br />
* c - The callback function to invoke in the response (appropriate for JSON responses only). <br />
* br - Bitrate to filter the station result. <br />
* mt - Media type to filter the station result. <br />
* genre - Genre to filter the station result. <br />
* limit - This API by default returns one station. To get more random stations, set the number of stations to return by passing the limit parameter.<br />
<br />
'''<span style="color:#FF6600;">Sample XML Response:</span>'''(Parameter Limit)<br />
<response><br />
<statusCode>200</statusCode><br />
<statusText>Ok</statusText><br />
<data><br />
<stationlist><br />
<tunein base="/sbin/tunein-station.pls"/><br />
<station name="FreshBakedJams.com-[SHOUTcast.com]" mt="audio/mpeg" id="429395" br="128" genre="Fresh BakedJams"<br />
ct="D-Rellz - Story" lc="0" ml="600" nsc="No"/><br />
</stationlist><br />
</data><br />
</response><br />
<br />
'''<span style="color:#FF6600;">URL (JSON Request):</span>'''<br />
<br />
<nowiki>http://api.shoutcast.com/station/nowplaying?ct=rihanna&f=json&k=[Your Dev ID]</nowiki><br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response:</span>'''<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok"<br />
},<br />
"data":"{<br />
"stationlist":{<br />
"station":[<br />
"tunein":{<br />
"base":"/sbin/tunein-station.pls"<br />
}<br />
{"nsc":"No","genre":"Turkish TurkTurkce","id":205936,"mt":"audio/mpeg",<br />
"name":"TRD 1 - Turk Radyo Dunyasi - Turkish World<br />
Radio - SMS: +90 544 644 6226- www.trd.com.tr-[SHOUTcast.com]",<br />
"lc":2,"ml":"600","br":32,"ct":"Nalan -Sonunda Bitti"},<br />
]<br />
}<br />
}<br />
}<br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response (with callback):</span>'''<br />
callbackfunctionname(<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok"<br />
},<br />
"data":"{<br />
"stationlist":{<br />
"station":[<br />
"tunein":{<br />
"base":"/sbin/tunein-station.pls"<br />
}<br />
{"nsc":"No","genre":"Turkish TurkTurkce","id":205936,"mt":"audio/mpeg",<br />
"name":"TRD 1 - Turk Radyo Dunyasi - Turkish World<br />
Radio - SMS: +90 544 644 6226- www.trd.com.tr-[SHOUTcast.com]",<br />
"lc":2,"ml":"600","br":32,"ct":"Nalan -Sonunda Bitti"}, <br />
]<br />
}<br />
}<br />
}<br />
)<br />
<br />
<br />
=Get Genres on SHOUTcast Radio Directory=<br />
<br />
==Get All Genres==<br />
'''<span style="color:#FF6600;">Description:</span>''' Get all the genres on SHOUTcast Radio Directory<br />
<br />
'''<span style="color:#FF6600;">URL:</span>''' <nowiki>http://api.shoutcast.com/legacy/genrelist?k=[Your Dev ID]</nowiki><br />
<br />
'''<span style="color:#FF6600;">Required Parameters:</span>'''<br />
* k - API Dev ID. <br />
<br />
'''<span style="color:#FF6600;">Sample XML Response:</span>'''<br />
<br />
<genrelist><br />
<genre name="30s"/><br />
<genre name="40s"/><br />
<genre name="50s"/><br />
<genre name="60s"/><br />
<genre name="70s"/><br />
<genre name="80s"/><br />
<genre name="90s"/><br />
.<br />
.<br />
</genrelist><br />
<br />
<br />
==Get Primary Genres==<br />
'''<span style="color:#FF6600;">Description:</span>''' Get only the Primary Genres on SHOUTcast Radio Directory<br />
<br />
'''<span style="color:#FF6600;">URL:</span>''' <nowiki>http://api.shoutcast.com/genre/primary?k=[Your Dev ID]&f=xml</nowiki><br />
<br />
'''<span style="color:#FF6600;">Required Parameters:</span>'''<br />
<br />
* f - the response format (xml, json,rss). You can choose xml, json or rss based results.<br />
* k - API Dev ID.<br />
<br />
'''<span style="color:#FF6600;">Optional Parameters:</span>'''<br />
* c - The callback function to invoke in the response (appropriate for JSON responses only).<br />
<br />
'''<span style="color:#FF6600;">Sample XML Response:</span>'''<br />
<response><br />
<statusCode>200</statusCode><br />
<statusText>Ok</statusText><br />
<data><br />
<genrelist> <br />
<genre name="Alternative" id="1" parentid="0" haschildren="true"/><br />
<genre name="Blues" id="24" parentid="0" haschildren="true"/><br />
.<br />
.<br />
.<br />
</genrelist> <br />
</data><br />
</response><br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response:</span>'''<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok"<br />
},<br />
"data":"{<br />
"genrelist":{<br />
"genre":[<br />
{"id":1,"haschildren":true,"name":"Alternative","parentid":0},<br />
{"id":24,"haschildren":true,"name":"Blues","parentid":0},<br />
.<br />
.<br />
]<br />
}<br />
}<br />
}<br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response (with callback):</span>'''<br />
callbackfunctionname(<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok" <br />
},<br />
"data":"{<br />
"genrelist":{<br />
"genre":[<br />
{"id":1,"haschildren":true,"name":"Alternative","parentid":0},<br />
{"id":24,"haschildren":true,"name":"Blues","parentid":0},<br />
.<br />
.<br />
]<br />
}<br />
}<br />
}<br />
)<br />
<br />
<br />
==Get Secondary Genres==<br />
'''<span style="color:#FF6600;">Description:</span>''' Get secondary genre list (if present) for a specified primary genre.<br />
<br />
'''<span style="color:#FF6600;">URL:</span>''' <nowiki>http://api.shoutcast.com/genre/secondary?parentid=0&k=[Your Dev ID]&f=xml</nowiki><br />
<br />
'''<span style="color:#FF6600;">Required Parameters:</span>'''<br />
* parentid - Genreid of the primary genre. You can retreive the entire genre set by passing parentid=0.<br />
* f - the response format (xml, json, rss). You can choose xml,json or rss based results.<br />
* k - API Dev ID.<br />
<br />
'''<span style="color:#FF6600;">Optional Parameters:</span>'''<br />
* c - The callback function to invoke in the response (appropriate for JSON responses only). <br />
<br />
'''<span style="color:#FF6600;">Sample XML Response:</span>'''<br />
<response><br />
<statusCode>200</statusCode><br />
<statusText>Ok</statusText><br />
<data><br />
<genrelist><br />
<genre name="Alternative" id="1" parentid="0" haschildren="true"><br />
<genrelist><br />
<genre name="Adult Alternative" id="2" parentid="1" haschildren="false"/><br />
<genre name="Britpop" id="3" parentid="1" haschildren="false"/><br />
<genre name="Classic Alternative" id="4" parentid="1" haschildren="false"/> <br />
.<br />
.<br />
</genrelist><br />
</genre><br />
</genrelist><br />
</data><br />
<response><br />
<br />
'''<span style="color:#FF6600;">URL (JSON Request):</span>'''<br />
<br />
<nowiki>http://api.shoutcast.com/genre/secondary?parentid=0&f=json&k=[Your Dev ID]</nowiki><br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response:</span>'''<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok"<br />
},<br />
"data":"{<br />
"genrelist":{<br />
"genre":[<br />
"genrelist":{<br />
"genre":[<br />
{"id":1,"haschildren":true,"name":"Alternative","parentid":0},<br />
{"id":24,"haschildren":true,"name":"Blues","parentid":0},<br />
{"id":32,"haschildren":true,"name":"Classical","parentid":0},<br />
.<br />
.<br />
]<br />
}<br />
]<br />
}<br />
}<br />
}<br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response (with callback):</span>'''<br />
callbackfunctionname(<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok"<br />
},<br />
"data":"{<br />
"genrelist":{<br />
"genre":[<br />
"genrelist":{<br />
"genre":[<br />
{"id":1,"haschildren":true,"name":"Alternative","parentid":0},<br />
{"id":24,"haschildren":true,"name":"Blues","parentid":0},<br />
{"id":32,"haschildren":true,"name":"Classical","parentid":0},<br />
.<br />
.<br />
]<br />
}<br />
]<br />
}<br />
}<br />
}<br />
)<br />
<br />
<br />
==Get Genres Details by Passing Genreid==<br />
'''<span style="color:#FF6600;">Description:</span>''' Get details such as Genre Name, Sub Genres (if its a primary genre), has children by passing the genre-id.<br />
<br />
'''<span style="color:#FF6600;">URL:</span>''' <nowiki>http://api.shoutcast.com/genre/secondary?id=25&f=xml&k=[Your Dev ID]</nowiki><br />
<br />
'''<span style="color:#FF6600;">Required Parameters:</span>'''<br />
* id - Input respective genre or sub-genre id.<br />
* f - the response format (xml, json, rss). You can choose xml,json or rss based results.<br />
* k - API Dev ID. <br />
<br />
'''<span style="color:#FF6600;">Optional Parameters:</span>'''<br />
* c - The callback function to invoke in the response (appropriate for JSON responses only). <br />
<br />
'''<span style="color:#FF6600;">Sample XML Response:</span>'''<br />
<response><br />
<statusCode>200 </statusCode><br />
<statusText>Ok </statusText><br />
<data><br />
<genrelist> <br />
<genre name="Acoustic Blues" id="25" parentid="24" haschildren="false"/><br />
</genrelist> <br />
</data><br />
</response><br />
<br />
'''<span style="color:#FF6600;">URL (JSON Request):</span>'''<br />
<br />
<nowiki>http://api.shoutcast.com/genre/secondary?id=25&f=json&k=[Your Dev ID]</nowiki><br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response:</span>'''<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok"<br />
},<br />
"data":"{<br />
"genrelist":{<br />
"genre":{<br />
{"id":25,"haschildren":false,"name":"AcousticBlues","parentid":24}<br />
}<br />
}<br />
}<br />
}<br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response (with callback):</span>'''<br />
callbackfunctionname(<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok" <br />
}, <br />
"data":"{<br />
"genrelist":{<br />
"genre":{<br />
{"id":25,"haschildren":false,"name":"AcousticBlues","parentid":24}<br />
}<br />
}<br />
}<br />
}<br />
)<br />
<br />
<br />
==Get Genres Based on Availability of Sub-Genres==<br />
'''<span style="color:#FF6600;">Description:</span>''' Get genres based on their sub-genre availability at any node level in the genre hierarchy of SHOUTcast.<br />
<br />
'''<span style="color:#FF6600;">URL:</span>'''<br />
:*Genres with sub genres:<br />
::<nowiki>http://api.shoutcast.com/genre/secondary?haschildren=true&f=xml&k=[Your Dev ID]</nowiki><br />
<br />
:*Genres without sub genres:<br />
::<nowiki>http://api.shoutcast.com/genre/secondary?haschildren=false&f=xml&k=[Your Dev ID]</nowiki><br />
<br />
'''<span style="color:#FF6600;">Required Parameters:</span>'''<br />
* haschildren<br />
:* 'true' to get genre or subgenre which has sub-genres.<br />
:* 'false' to get genre or subgenre which does not have sub-genres.<br />
* f - the response format (xml, json, rss). You can choose xml,json or rss based results.<br />
* k - API Dev ID.<br />
<br />
'''<span style="color:#FF6600;">Optional Parameters:</span>'''<br />
* c - The callback function to invoke in the response (appropriate for JSON responses only). <br />
<br />
'''<span style="color:#FF6600;">Sample XML Response:</span>'''<br />
<response><br />
<statusCode>200</statusCode><br />
<statusText>Ok</statusText><br />
<data><br />
<genrelist> <br />
<genre name="Alternative" id="1" parentid="0" haschildren="true"/><br />
<genrelist><br />
<genre name="Adult Alternative" id="2" parentid="1" haschildren="false"/><br />
<genre name="Britpop" id="3" parentid="1" haschildren="false"/><br />
.<br />
.<br />
</genrelist><br />
</genre><br />
<genre name="Blues" id="24" parentid="0" haschildren="true"/><br />
<genrelist><br />
<genre name="Adult Alternative" id="2" parentid="1" haschildren="false"/><br />
<genre name="Britpop" id="3" parentid="1" haschildren="false"/><br />
.<br />
.<br />
</genrelist><br />
</genre><br />
.<br />
.<br />
</genrelist> <br />
</data><br />
</response><br />
<br />
'''<span style="color:#FF6600;">URL (JSON Request):</span>'''<br />
<br />
<nowiki>http://api.shoutcast.com/genre/secondary?haschildren=true&f=json&k=[Your Dev ID]</nowiki><br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response:</span>'''<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok"<br />
},<br />
"data":"{<br />
"genrelist":{<br />
"genre":[<br />
"genrelist":{<br />
"genre":[<br />
{"id":2,"haschildren":false,"name":"AdultAlternative","parentid":1},<br />
{"id":3,"haschildren":false,"name":"Britpop","parentid":1},<br />
{"id":4,"haschildren":false,"name":"ClassicAlternative","parentid":1},<br />
{"id":205,"haschildren":false,"name":"RapMetal","parentid":195},<br />
{"id":195,"haschildren":true,"name":"Metal","parentid":0},<br />
.<br />
.<br />
]<br />
}<br />
]<br />
}<br />
}<br />
}<br />
<br />
<br />
'''<span style="color:#FF6600;">Sample JSON Response (with callback):</span>'''<br />
callbackfunctionname(<br />
{"response":{<br />
"statusCode":200,<br />
"statusText":"Ok"<br />
},<br />
"data":"{<br />
"genrelist":{<br />
"genre":[<br />
"genrelist":{<br />
"genre":[<br />
{"id":2,"haschildren":false,"name":"AdultAlternative","parentid":1},<br />
{"id":3,"haschildren":false,"name":"Britpop","parentid":1},<br />
{"id":4,"haschildren":false,"name":"ClassicAlternative","parentid":1},<br />
{"id":205,"haschildren":false,"name":"RapMetal","parentid":195},<br />
{"id":195,"haschildren":true,"name":"Metal","parentid":0},<br />
.<br />
.<br />
]<br />
}<br />
]<br />
}<br />
}<br />
}<br />
)<br />
<br />
<br />
=Other=<br />
<br />
==How To Tune Into A Station==<br />
<br />
To tune into a station, find the "id" of the station from the API results & make a call to <nowiki>http://yp.shoutcast.com/sbin/tunein-station.pls?id=[Station_id]</nowiki> by appending the station id.<br />
<br />
'''Ex:''' If the station id is 1025, Call => <nowiki>http://yp.shoutcast.com/sbin/tunein-station.pls?id=1025&k=[Your Dev ID]</nowiki><br />
<br />
<br />
==XML Caching==<br />
<br />
Do not cache the XML for more than 1 day, as station ID's can and will change.<br />
<br />
<br />
==Error Codes==<br />
<br />
The Error codes encountered when invalid data is input or passed to access the APIs are as below<br />
<br />
'''HTTP Status Code'''<br />
<br />
:400=Bad Request<br />
<br />
:404=Page Not Found<br />
<br />
:500=Generic Server Error<br />
<br />
:460=Missing required parameter<br />
<br />
:462=Parameter Error<br />
<br />
:440=Invalid Devid<br />
<br />
'''BUSINESS_ERROR'''<br />
<br />
:10001=Internal Server error<br />
<br />
:10002=XML Root Element not matching<br />
<br />
:10003=Error while interacting with private api<br />
<br />
:10002=Cache xml data not found<br />
<br />
'''GENERAL_ERROR'''<br />
<br />
:20001=Unable to find InitialContext<br />
<br />
:20002=Unable to acquire DataSource<br />
<br />
:20003=Unable to load SQL query<br />
<br />
:20004=Unable to load property file<br />
<br />
:20005=Unable to execute SQL query<br />
<br />
:20006=Unable to fetch ResultSet<br />
<br />
:20007=Error in finally block<br />
<br />
:20008=NullPointer Exception Raised<br />
<br />
:20009=Error while adding xml element<br />
<br />
:20010=Number Format Exception<br />
<br />
:20011=Error in creating xml document<br />
<br />
:20012=Null object received<br />
<br />
:20012=XML Data not found in Cache<br />
<br />
:20013=File not found<br />
<br />
:20014=Unable to connect to search api<br />
<br />
:20015=Error while building xml document<br />
<br />
:20016=Error while encoding url string<br />
<br />
:20017=Error while connecting to shoutcast api<br />
<br />
:20018=Error while processing the jsp<br />
<br />
:20019=Error while reading request object<br />
<br />
:20020=Error while sending email<br />
<br />
:20021=Invalid Response Type<br />
<br />
:20022=Maximum Value Exceeded<br />
<br />
:20023=Error while connecting to AKES<br />
<br />
:20024=Error while building AKES response xml document<br />
<br />
:20025=No Data in AKES response xml document<br />
<br />
:20026=Missing required parm : (REFERRER)<br />
<br />
:20027=Invalid key received from<br />
<br />
:20028=Missing devId= or k= param<br />
<br />
:20029=Missing required parm : (k)<br />
<br />
:20030=Missing required parm : (keyType)<br />
<br />
:20027=Deny - authRequired fail<br />
<br />
:20028=Deny - usageLimited fail<br />
<br />
:20029=Deny - rightNotSet fail<br />
<br />
:20030=Deny - referrerUsageLimited fail</div>Culixhttp://wiki.shoutcast.com/wiki/User_talk:DrOUser talk:DrO2011-01-08T22:13:06Z<p>Culix: /* Thanks */</p>
<hr />
<div>== Thanks! ==<br />
Hey DrO, thanks for all of the great work on wiki topics :) I'll try to keep the spam out of your way. --[[User:Culix|Culix]] 22:13, 8 January 2011 (UTC)</div>Culixhttp://wiki.shoutcast.com/wiki/Plug-in_DeveloperPlug-in Developer2010-12-01T03:28:00Z<p>Culix: Reverted edits by RosieLola (Talk) to last version by Culix</p>
<hr />
<div>{{Template:NavBar}}<br />
<br />
==Plug-in Overview==<br />
<br />
===Writing A Plug-in===<br />
Winamp plug-ins are files that extend Winamp's functionality. There are currently seven different plug-in types, each of which extends Winamp in a particular way. Winamp plug-ins are implemented as 32-bit Windows DLLs. Here are the plug-in categories:<br />
<br />
#Input plug-ins: Input plug-ins give Winamp the ability to play additional file types that aren't supported by Nullsoft directly.<br />
#Output plug-ins: Output plug-ins allow Winamp to manifest audio data in different ways.<br />
#General purpose plug-ins: Anything that needs to run continuously in the background or doesn't require audio processing qualifies as a General purpose plug-in.<br />
#DSP/effect plug-ins: DSP Plug-ins manipulate audio data before actually being sent to the speakers (or whatever the Output plug-in decides to do with it).<br />
#Visualization plug-ins: "Vis" plug-ins display some sort of visual effect based on audio that's being decoded by Winamp.<br />
#Language packs: Language packs are used to internationalize Winamp to the language of your choice.<br />
#Media Library plug-ins: Media Library plug-ins extend the media library for instance, for portable devices such as iPods, accessing Media Library databases, etc.<br />
<br />
Most of the plug-in types (with the exception of Language packs) export one function, which is used to query the plug-in of its interface. The way each plug-in is queried varies, and will be covered on a type-by-type basis.<br />
<br />
All of the plug-ins are designed to be written in C or C++, using Microsoft Visual C++ 4.0 or later. Other people have reported success with writing some forms of plug-ins using Delphi, LCC, and Visual Basic. We don't use these alternate development platforms, so we can't really support development on them (writing this page alone took way too much time, wink). The [http://forums.winamp.com/ Winamp forums] are a good place to start.<br />
<br />
====Basic start====<br />
Check out the [[Beginner's Basic Plugin Guide]].<br />
<br />
===Submitting Your Plug-in===<br />
<br />
Once your plug-in is bug-free, the ultimate step is to share your masterpiece with the world. This is where Winamp.com steps in. Submitting your plug-in will allow people all over the world to enjoy the fruits of your labor. To do this, just follow these steps:<br />
<br />
#Go to http://www.winamp.com/user/submit<br />
#Click the "Submit a plug-in" button.<br />
#Fill in the blanks:<br />
##Name: The name of your plug-in.<br />
##Comment: The short blurb that comes up when people browse the plug-ins page.<br />
##Description: The longer blurb that is displayed when people view the plug-in details page.<br />
##Categories: Choose Primary and/or Secondary (optional) categories to properly sort your plug-in.<br />
##Thumbnail: Click on the "Browse" button to find the .gif, .jpg, or .png file on your computer. Note: the image file dimensions should be no larger than 178px by 75px.<br />
##Screenshot: (Full-sized screenshot of your plug-in.) Click on the "Browse" button to find the .gif, .jpg, or .png file on your computer. Note: the image file dimensions should be no larger than 275px by 600px.<br />
##Plug-in File: Click on the "Browse" button to find your PiMP-ed .EXE file on your computer.<br />
#Click the "Submit" Button, and...<br />
#Voila! Your plug-in is on its way to being displayed before the world. <br />
<br />
====Submission Checklist====<br />
Please ensure that your Plugin meets the following terms before submitting it to www.winamp.com:<br />
*Your Plugin is tested and won't blow away other's computers due to silly bugs. For getting your plugin tested, please post it in this [http://forums.winamp.com/forumdisplay.php?s=&forumid=14 forum] first.<br />
*You have packed the Plugin with an installer that auto-detects the Winamp installation directory (or where the plugin should go to in order to work). We recommend using [http://nsis.sourceforge.net/ NSIS]. It is free and you can find an example installer script [http://nsis.sourceforge.net/Winamp_Plugin_Installer_Scripts here].<br />
*You havn't submitted the plugin already. If so, please use the 'edit' function for your plugin shown in your [http://www.winamp.com/user/main User Account Central].<br />
<br />
====Plug-in Category Descriptions====<br />
Please choose the categories thoughtfully. It will make finding your plug-in much easier if it is in the right categories.<br />
<br />
AVS Presets: Any presets or APEs for Nullsoft's AVS plug-in.<br />
DSP/Effect: Manipulates audio data.<br />
Encoding: Plug-ins that encode media.<br />
Games: Any plug-in that takes input and rewards "good" behavior.<br />
General: Does not depend on audio data to run.<br />
Input: Reads new audio file type.<br />
Language Packs: Translates Winamp to a new language.<br />
Output: Converts to new type of audio file or sends audio through alternate path.<br />
Plug-in Skins: Plug-ins that change the look and feel of Winamp.<br />
Portable Devices: Plug-ins that interact with removable media.<br />
Visualizations: Visualization ... plug-ins.<br />
<br />
==Tools==<br />
* Visual Studio 6.0 or higher (Visual Studio 2003 is highly recommended.You can download a free copy of [http://www.microsoft.com/Express Visual Studio Express] from Microsoft. Unfortunately it is a newer version and not full-featured and we cannot guarantee that the SDK examples will work properly with this edition.<br />
* [http://nsis.sourceforge.net Nullsoft Scriptable Install System] or other installer software for packaging your completed plug-in. Check this [http://nsis.sourceforge.net/Winamp_Plugin_Installer_Scripts example] for creating a NSIS Installer for your plugin.<br />
* [http://www.7-zip.org 7-Zip] or other archiver for packaging your WSZ or WAL skin files.<br />
<br />
==SDK Documentation==<br />
The SDK includes everything you'll need to develop a Winamp plug-in. It also includes a basketful of example plug-ins to get you going. It is recommended that you create your plug-in as a subdirectory of the install path ("C:\Program Files\Winamp SDK" by default) as the #include paths of the examples assume this.<br />
<br />
*[[SDK Contents]]<br />
*'''[http://download.nullsoft.com/winamp/plugin-dev/WA5.55_SDK.exe Download SDK]'''<br />
<br />
==Resources==<br />
* [[Articles#Plug-in_Articles|Plug-in Articles]]<br />
* [[Developers_FAQ#Plug-in_Developer_FAQ|Plug-in FAQ]]<br />
<br />
==Community Links==<br />
*Forums: [http://forums.winamp.com/forumdisplay.php?s=&forumid=14 Winamp Developer Forum]<br />
*Upload: [http://www.winamp.com/user/submit-plugin Submit Your Plug-in]<br />
*Browse: [http://www.winamp.com/plugins Download Plug-ins]</div>Culixhttp://wiki.shoutcast.com/wiki/User_talk:CHUser talk:CH2010-11-30T03:35:15Z<p>Culix: /* Thanks */</p>
<hr />
<div>== Thanks ==<br />
Thanks for the note on using Visual Studio 2010. Good luck with your plugin! --[[User:Culix|Culix]] 03:35, 30 November 2010 (UTC)</div>Culixhttp://wiki.shoutcast.com/wiki/Decode_File_APIDecode File API2010-11-30T03:33:27Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>{{stub}}<br />
<br />
Interface name: api_decodefile<br />
<br />
Related interfaces: ifc_audiostream<br />
<br />
Include file: Agave/DecodeFile/api_decodefile.h<br />
<br />
Related files: Agave/DecodeFile/ifc_audiostream.h<br />
<br />
GUID name: decodeFileGUID<br />
<br />
GUID: {9B4188F5-4295-48ab-B50C-F2B0BB56D242}<br />
<br />
Use:<br />
<br />
api_decodefile allows you to decode audio files to PCM. <br />
<br />
Uses by Winamp:<br />
<br />
It is used by the CD Burner to decode files to Red Book audio prior to burning.<br />
<br />
It is used by the Auto Tagger to decode files prior to feed to the analysis engine.<br />
<br />
It is used by the IPC_CONVERTFILE API to decode files prior to feeding the encoder.<br />
<br />
How to use:<br />
<br />
Open an audio stream (ifc_audiostream) by calling OpenAudioBackground(). The passed AudioParameters struct may be filled with requested values; some formats are able to return multiple PCM data types and this can be used to request a particular format. Winamp will also apply resampling, bit decimation and downmixing, although it is not guaranteed to work in all situations. You need to verify the AudioParameters struct after opening the audio - it may have been opened with different parameters than what you wanted or expected!<br />
<br />
The returned ifc_audiostream is then read sequentially. Call ReadAudio() continuously until 0 is returned or an error is reported. The audio stream is closed by calling api_decodefile's CloseAudio() method.<br />
<br />
[[Category:Articles]]</div>Culixhttp://wiki.shoutcast.com/wiki/Winamp_Developer_Wiki_talk:Current_eventsWinamp Developer Wiki talk:Current events2010-11-30T03:33:22Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>== Spam Event? ==<br />
>>Jerk affair "Pork & Beer Style, Dec 20,2009.. @ Sparkling car wash..Montego Bay , Jamaica W.I More Info 1876-7751921<br />
<br />
Okay, I'm moving this to the discussion page until it is verified. Is this a real event? Are you just a spammer? Can you show any info on this event happening and that it is actually related to Winamp? Either way it is over now, but this just looks like spam.<br />
<br />
I'm all for sharing Winamp current events, those would be cool to post, but this just looks like nonsense. My quick google searches don't turn up anything for any such event or place, and the phone number doesn't show up, nor does it appear to use a real Jamaica area code. If this is real please speak up. I am deleting the content from the main page for now. --[[User:Culix|Culix]] 07:08, 21 December 2009 (UTC)</div>Culixhttp://wiki.shoutcast.com/wiki/User_talk:GistbaneUser talk:Gistbane2010-11-30T03:33:18Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>==Dealing with wiki spam==<br />
Hello,<br />
<br />
Sorry to bother you on your userpage, but [[User:Hydrargyrum|Hydrargyrum]] and I were wondering if we could get some help deleting spam pages. We have tried to mark many of the spam pages with the <nowiki>{{deleteme}}</nowiki> template and/or the [[:Category:Requests for Deletion]] category so they can be easily found. Would it be possible to get a sysop such as yourself to delete some of these pages?<br />
<br />
I'm not sure if there is a good way to prevent this spam from happening. I started a discussion on the [[Winamp_Developer_Wiki:Community_Portal#Dealing%20with%20wiki%20spam|Community Portal]] page in case that helps. Would it be possible to try any of those anti-spam measures? Do we use any of them already?<br />
<br />
Thanks for your time! --[[User:Culix|Culix]] 07:00, 19 June 2009 (UTC)<br />
<br />
== Thanks ==<br />
<br />
Wow, thank you very much for the trust and access! I am humbled and honoured. I will try to clean up a few things here, starting with those spam pages. I am out of town this weekend but will see what I can do next week. Thanks again! --[[User:Culix|Culix]] 13:06, 25 June 2009 (UTC)<br />
<br />
== Autoconfirmed users ==<br />
Hey Gistbane, thanks for getting the wiki back up and running! :)<br />
I made a [[Winamp_Developer_Wiki:Community_Portal#Autconfirmed_users|post on the Community Portal about Autoconfirmed users]]. Do you think it would be worth trying something like that? --[[User:Culix|Culix]] 07:48, 8 March 2010 (UTC)</div>Culixhttp://wiki.shoutcast.com/wiki/Talk:Main_PageTalk:Main Page2010-11-30T03:33:15Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>== Linkspam Notice ==<br />
'''Do not post linkspam on this page'''&nbsp;&mdash; it will be removed on sight.<br />
<br />
== Codeblock formatting ==<br />
<br />
Hey everyone,<br />
<br />
Sorry if this is the wrong place to ask this, but is it possible to change the formatting of codeblocks that appear with the <nowiki><source></nowiki> tag? I see Wikipedia's [http://en.wikipedia.org/wiki/C%2B%2B#Language_features C++] article has neat dotted borders that appear around blocks of code, but using the same <nowiki><source lang="cpp"></nowiki> tag on this wiki doesn't seem to add that (it nicely still does the syntax highlighting, however). Is there a way to add those borders? --[[User:Culix|Culix]] 02:39, 10 June 2009 (UTC)<br />
<br />
== Proposal: move glossary ==<br />
<br />
Since the glossary of terms is quite large, would anyone object to moving it on to its own page? Or is it preferable for some reason to keep it on the main page? --[[User:Culix|Culix]] 04:22, 10 June 2009 (UTC)<br />
: I have moved the glossary to [[Glossary|its own page]]. Speak up if you think that's bad. Along the way I had to kill the links to the 'on line service' page to be able to save (see [[Talk:Main_Page#Breadcrumb|this discussion]]); they will need to be restored after we decide how to deal with the spam filter. --[[User:Culix|Culix]] 12:42, 26 June 2009 (UTC)<br />
<br />
== Breadcrumb ==<br />
Would anyone be opposed to making the Breadcrumb at the top of the page a template? I am currently unable to save any page that uses the breadcrumb links because the word 'onl ine' in the link to 'On line Service Developer' triggers the wiki's spam filter :-/ (I can't even use that word while typing this post). e.g. I had to remove that link from the [[Articles]] page in order to save any changes. Perhaps a wiki admin could create a {{Breadcrumb}} template page which could be used at the top of the main pages? It might require some wiki coding to get the links right. Alternatively, could we relax that word out of the spam filter, since it's used in the breadcrumb? --[[User:Culix|Culix]] 14:30, 10 June 2009 (UTC)--[[User:Culix|Culix]] 14:30, 10 June 2009 (UTC)<br />
:The word 'online' has been removed from the spam filter, so saving pages should be easier now. --[[User:Culix|Culix]] 14:46, 8 July 2009 (UTC)<br />
:: I fixed this today by adding the [[Template:NavBar]] template. It seems mediawiki is smart enough not to link to the current page, which is nice. This doesn't follow all of the same behaviour as a [http://en.wikipedia.org/wiki/Breadcrumb_%28navigation%29 breadcrumb], so I named it NavBar instead. If you want to change the behaviour or the name feel free to comment :) --[[User:Culix|Culix]] 04:16, 20 May 2010 (UTC)</div>Culixhttp://wiki.shoutcast.com/wiki/Winamp_Developer_Wiki:Community_PortalWinamp Developer Wiki:Community Portal2010-11-30T03:33:11Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>Welcome to the community portal. This is the place to find out what is happening on the Winamp Wiki! Learn what tasks need to be done and share news about recent events or current activities.<br />
<br />
==Dealing with wiki spam==<br />
As I'm sure you've noticed, this wiki seems to get a fair amount of spam. How can we deal with this? A quick google search turned up the following pages:<br />
# [http://www.mediawiki.org/wiki/Anti-spam_features Basic anti-spam features of mediawiki installations (a neat overview)]<br />
# [http://www.mediawiki.org/wiki/Manual:Combating_spam More overview]<br />
# [http://www.umasswiki.com/wiki/UMassWiki:Blocking_Spam_In_Mediawiki Several tips for stopping spam pages with divs]<br />
<br />
Do you think we could use any of these tips to cut down our spam count? For example, many of the spam pages seem to use the same div tag to prevent viewing of the 'edit' tab. Could we put this tag in our local settinsg spam regex?<br />
<br />
I'm not sure if any sysops have time to work on this right now, but I thought I would start a page for discussion. Thanks for reading. --[[User:Culix|Culix]] 06:57, 19 June 2009 (UTC)<br />
:Okay, I tried a basic test - I think it is the div text 'pos ition:absolute;' that is hiding the edit tab (or at least helping). If you look at [http://dev.winamp.com/w/index.php?title=Young_gunz&oldid=58975 this page before the edit], I am unable to see the edit tab in FireFox 3.0.11. I am, however, able to view the edit tab on [http://dev.winamp.com/w/index.php?title=Young_gunz&oldid=58976 this page after the edit]. And the [http://dev.winamp.com/w/index.php?title=Young_gunz&diff=58976&oldid=58975 only difference] is removing the text 'pos ition:absolute;' from the div tag.<br />
<br />
:Could we use this text to perhaps prevent spammers from saving the page? Or is such an action futile if they just quickly change their spam template? It might raise the bar a little bit. --[[User:Culix|Culix]] 07:09, 19 June 2009 (UTC)<br />
<br />
::So it looks like [[Special:AllPages|most of our pages]] are spam rather than real content :( I think we need a way to deal with these quickly rather than trying to combat them all by hand. How do you feel about creating a bot account and giving it access to delete pages? We could use something like [http://meta.wikimedia.org/wiki/Delete.py this deletion-helper bot] to go through the pages. There are some [http://meta.wikimedia.org/wiki/Pywikipedia_bot_on_non-Wikimedia_projects instructions for using the bot on non-wikimedia projects]. I'm willing to try and use the bot if admins are okay with me creating an account for it. --[[User:Culix|Culix]] 13:01, 26 June 2009 (UTC)<br />
<br />
:::Okay, I manually deleted enough pages to make most of the first 50 [[Special:PopularPages|Popular pages]] point to actual content. With 40,000 pages in the wiki though, it looks like 99% of them are spam, and dealing with all of those by hand would be tedious. After some off-wiki discussion with [[User:Gistbane|Gistbane]], we have a battle plan: some filters will be added to the wiki's blacklist regex, and Gistbane set up an [[User:Antispambot|anti-spam bot]] account to help delete pages.<br />
:::Based on my first test, it looks like it takes about 2.5 hours to delete 1000 pages using the [http://meta.wikimedia.org/wiki/Delete.py deletion script], so that's roughly 100 hours of running the script if we want to clean the whole wiki. This may take a while, but I'll try to run the script for a few hours every day and see how it goes. --[[User:Culix|Culix]] 13:08, 30 June 2009 (UTC)<br />
<br />
--<br />
<br />
Okay, it took 55 hours of running the bot, but 20,206 spam pages have been deleted :) I think this is most of them, not counting user pages (counting user pages it's only about 50%).<br />
<br />
Methodology: I started by going through [[Special:AllPages]] and made a big list of every page on the wiki. I searched through these by hand to try and spot real pages to make sure no real content would be deleted, even if it was an orphan. Everything else was put into 'the spam list'. I then started from the [[Main Page]] and spidered through all real links to actual content (about 100 pages). I cross-referenced this list with the spam list to make sure no known good pages were marked as spam.<br />
<br />
I think my method worked alright, but if you know of a legitimate page that was deleted please let me know! Seeing as the wiki was 0.25% actual content, it's quite possible a page or two was missed ;)<br />
<br />
If no one has objections I am also going to run the bot against all [[Special:ListRedirects|redirects]] that are user pages. I see exactly one user page that is a legitimate redirect, and 20,000+ that point to (now nonexistant) spam pages. --[[User:Culix|Culix]] 07:23, 8 July 2009 (UTC)<br />
: Okay, another 21,242 spam userpages have been deleted. I believe that is everything. If you see more spam, let me know. --[[User:Culix|Culix]] 17:09, 11 July 2009 (UTC)<br />
<br />
==Autconfirmed users==<br />
Wikipedia has the concept of 'autoconfirmed' users. On the english wikipedia, users are restricted in doing some things (like uploading images) until they have made at least 10 edits and had an active account for at least 4 days.<br />
<br />
See here for details:<br />
* [http://en.wikipedia.org/wiki/Wikipedia:User_access_levels#Autoconfirmed_users Autoconfirmed users]<br />
* [http://en.wikipedia.org/wiki/Wikipedia:Uploading_images#Procedure_to_upload Upload procedures]<br />
<br />
Apparently you can control this in MediaWiki by setting the $wgAutoConfirmAge and $wgAutoConfirmCount variables ([http://www.mediawiki.org/wiki/Manual:Configuration_settings#Users see here]).<br />
<br />
Do you think we could do this for the Winamp wiki? It may cut down on our uploaded image spam. What do you think? --[[User:Culix|Culix]] 07:46, 8 March 2010 (UTC)</div>Culixhttp://wiki.shoutcast.com/wiki/Modern_Skin:_Relative_PositioningModern Skin: Relative Positioning2010-11-30T03:33:06Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Tarik</p>
<hr />
<div>Creating a Modern Skin --> [[Modern Skin: Intro|Intro]] --> [[Modern Skin: Winamp 2 to W3+|Winamp 2 to Winamp 3+]] --> [[Modern Skin: Simple Skin Tutorial|Simple Skin Tutorial]] --> [[Modern Skin: XML Intro|XML Intro]] --> [[Modern Skin: Simple Skin Tutorial (Continued)|Simple Skin Tutorial (Continued)]] --> [[Modern Skin: Container| Container]] --> [[Modern Skin: Group|Group]] --> [[Modern Skin: Relative Positioning| Relative Positioning]] --> [[Modern Skin: Complex Skin|Complex Skin]] --> [[Modern Skin: Non-Rect Player| Non-Rect Player]] --> [[Modern Skin: Layer Composition| Layer Composition]] --> [[Modern Skin: Alpha Channels| Alpha Channels]] --> [[Modern Skin: Animatedlayer|Animatedlayer]] --> [[Modern Skin: Snap Points|Snap Points]] --> [[Modern Skin: Drawers|Drawers]] --> [[Modern Skin: Skin Scripting| Skin Scripting]] --> [[Modern Skin: Drawer Scripting| Drawer Scripting]] --> [[Modern Skin: Animating a Skin|Animating a Skin]] --> [[Modern Skin: Maki Overview| Maki Overview]] --> [[Main_Page#Glossary_of_Terms|Glossary]]<br />
<br />
<br />
==What is Relative Positioning?==<br />
<br />
===A. Introduction===<br />
Modern Winamp skinning offers unparalleled flexibility in element placement. You're no longer restricted to specifying X&Y coordinates for an element. Instead, you can define the position of the element relative to your component. When the component resizes, the element will stretch or move with the component. This flexibility frees the skin designer from the hassel of retooling or redrawing the graphic assets over and over again to different size and width. Winamp will do that for you. =)<br />
<br />
===B. Add relativepos.xml to your SimpleTutorial ===<br />
<br />
For this section, I have made another XML file called "relativepos.xml" that you need to include in your SimpleTutorial skin. Download the relativepos.xml here.(Please right-click on the link and choose 'Save As...' or 'Save Link Target As...')<br />
<br />
Place this file in the same directory as your SimpleTutorial skin directory. For most people, the path is "C:\Program Files\Winamp\Skins\SimpleTutorial". Add this line to your Skin.xml in SimpleTutorial:<br />
<br />
[[Image:Rpos_include.png]]<br />
<br />
<br />
This is what your skin.xml should look like after the change: <br />
<br />
<br />
[[Image:Rpos_skinxml.png]]<br />
<br />
<br />
<br />
==RelativePos.xml==<br />
<br />
<br />
[[Image:rpos_xmlcode1.png]]<br />
<br />
<br />
Relativepos.xml uses elements from the SimpleTutorial skin. I am using the "blue-vis-layer.png" and "red-vis-layer.png" in the Player directory. <br />
<br />
<br />
[[Image:Rpos xmlcode2.png]]<br />
<br />
<br />
<br />
[[Image:Blue-vis-layer.png]]<br />
[[Image:Red-vis-layer.png]]<br />
<br />
<br />
==Relative Position 1: Defining X&Y Coordinates==<br />
<br />
<br />
[[Image:Rpos xmlcode3.png]]<br />
<br />
<br />
===A. Register_autopopup="1"===<br />
<br />
Before we delve into the code, I want to go over one feature. Take a look at this tag: [[Image:Rpos autopopup.png]]. When you add this tag to a groupdef, Winamp automatically wraps a container and layout around it and allow you to see the group in a separate window. This is particularly useful when you want to test the behavior of that group separate from everything else. To open that window, right click on the Main Player to bring up the menu. Go to the "Windows" submenu and you'll see the extra windows relativepos.xml has created. Open them up and try them out.<br />
<br />
<br />
[[Image:Rpos menu.png]]<br />
<br />
<br />
===B. Defining X&Y Coordinates===<br />
<br />
<br />
Line 11-19 defines a group with a "blue-vis" layer at the coordinate of (20,30). This is probably what you've been doing all along. As you can see, that the blue-vis layer's location doesn't change if you resize the window. The position is fixed. <br />
<br />
<br />
[[Image:Rpos1 small.png]]<br />
<br />
<nowiki>*</nowiki> Small size window<br />
<br />
<br />
<br />
[[Image:Rpos1 big.png]]<br />
<br />
<nowiki>*</nowiki> Large size window; Blue-vis layer position did not change<br />
<br />
<br />
I encourage you to play with this XML file. If you change the X&Y coordinates on line 14 to (-20, -30), your blue-vis layer will disappear. The reason is that the coordinate specified will be outside the context of your component window and therefore will not be rendered. <br />
<br />
[[Image:Rpos1 left.png]]<br />
<br />
<br />
<br />
==Relative Position 2: Specify the Height and Width==<br />
<br />
<br />
<br />
[[Image:Rpos xmlcode4.png]]<br />
<br />
In group 2, we're defining the height and width of the blus-vis layer that is larger than the image. When you do that, Winamp will stretch the image to that size. Likewise, if you specify height or width that is smaller than the image, Winamp will shrink the image to fit to that size. <br />
<br />
<br />
[[Image:Rpos2 1.png]]<br />
<br />
<nowiki>*</nowiki> RPOS1 window: Height and Width not specified<br />
<br />
<br />
[[Image:Rpos2 2.png]]<br />
<br />
<nowiki>* RPOS2 window: Height and Width defined</nowiki><br />
<br />
<br />
<br />
<br />
==Relative Position 3: RelatX & Negative X Coordinate==<br />
<br />
<br />
<br />
[[Image:Rpos xmlcode5.png]]<br />
<br />
<br />
Line 30-39 defines a group with a "blue-vis" layer at the coordinate of (-120,30). Notice that we have an extra line on line 34: "relatx=1". By setting relatx to 1, you're telling Winamp to start the x-coordinate from the right edge of the window. Note that the X-Coordinate should be negative; otherwise the blue-vis layer will not show up.<br />
<br />
This is a convenient feature if you want an element stick to a specific distance relative to the right edge of the window. Notice that when I resize the window, the blue-vis layer stays fixed distance relative to the right edge of the window. <br />
<br />
<br />
[[Image:Rpos3 small.png]]<br />
<br />
<nowiki>*</nowiki> RPOS3 window with relatx=1<br />
<br />
<br />
[[Image:Rpos3 big.png]]<br />
<br />
<nowiki>*</nowiki> RPOS3 window with relatx=1: window resized<br />
<br />
<br />
[[Image:Rpos3 right.png]]<br />
<br />
<nowiki>*</nowiki> RPOS3 window with relatx=1; coordinate (20,20)<br />
<br />
<br />
<br />
<br />
==Relative Position 4: RelatY & Negative Y Coordinate==<br />
<br />
<br />
[[Image:Rpos xmlcode6.png]]<br />
<br />
<br />
Line 40-49 defines a group with a "blue-vis" layer at the coordinate of (20,-80). Notice theline on line 44: "relaty=1". By setting relaty to 1, you're telling Winamp to start the y-coordinate from the bottom edge of the window. Note that the Y-Coordinate should be negative; otherwise the blue-vis layer will not show up.<br />
<br />
This is a convenient feature if you want an element stick to a specific distance relative to the bottom edge of the window. Notice that when I resize the window, the blue-vis layer stays fixed distance relative to the bottom edge of the window.<br />
<br />
<br />
[[Image:Rpos4 small.png]]<br />
<br />
<nowiki>*</nowiki> RPOS4 window with relaty=1<br />
<br />
<br />
[[Image:Rpos4 big.png]]<br />
<br />
<nowiki>*</nowiki> RPOS4 window with relaty=1: window resized<br />
<br />
<br />
[[Image:Rpos4 bottom.png]]<br />
<br />
<nowiki>*</nowiki> RPOS4 window with relaty=1: coordinate (20,50)<br />
<br />
<br />
<br />
<br />
==Relative Position 5: Relatw and RelatH==<br />
<br />
[[Image:Rpos xmlcode7.png]]<br />
<br />
<br />
Line 50-72 demonstrate the use of relath and relatw. From the beginning of this section we know that by defining height and width different from the original image size, Winamp will automatically stretch or shrink the image to fit that size constraint. What is powerful (and awesome) about modern skins is that you can also tell Winamp to adjust the height and width of an element with respect to the right and bottom edge of the window. This is accomplished through "relath" and "relatw".<br />
<br />
In our example, we defined a blue-vis group (lines 52-60) and a red-vis group that encompasses the blue-vis group (lines 63-72). The blue-vis group is defined with no preset x, y, h or w because we will define them on line 71.<br />
<br />
The magic happens on line 71. With relath set to 1 and relatw set to 1, we're telling Winamp to stretch or shrink the blue-vis layer so that it is 50 pixels away from the right and bottom edge of the window. The blue-vis layer is stretched and the distance is maintained as I expanded the size of the window. <br />
<br />
<br />
[[Image:Rpos5 small.png]]<br />
<br />
<nowiki>*</nowiki> RPOS5 window with relath=1 and relatw=1<br />
<br />
<br />
[[Image:Rpos5 big.png]]<br />
<br />
<nowiki>*</nowiki>RPOS5 window with relath=1 and relatw=1; window resized; Blue-vis layer stretched</div>Culixhttp://wiki.shoutcast.com/wiki/XML_Containing_objectsXML Containing objects2010-11-30T03:33:03Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Pjn123</p>
<hr />
<div>== Description ==<br />
These are the objects, that contain other objects.<br />
<br />
<br />
==<WasabiXML></WasabiXML>==<br />
This object contains the whole skin.<br />
* '''version''' - (int) The version of the Freeform Plugin Core the skin is made for. If the Plugin version is less than written, the warning "The skin is too new" will appear. Othervise, the Plugin will read the code according to this value, using backward compability.<br />
<br />
<br />
==<container></container>==<br />
* '''id''' - (id) The coder-oriented name of the container. This value is used when appealing to this object.<br />
* '''name''' - (str) The human-oriented name of the container, or the "title" of the "window." This value is used by some other GuiObjects, notably the Wasabi:TitleBar object, to be displayed in the system. It does not display automatically. The special string ":componenttitle" will query the contents of the container to find the first windowholder and replace the name assigned to this container with the name of the object held by the windowholder (if any).<br />
* '''default_x''' - (int) The default x position in screen coordinates.<br />
* '''default_y''' - (int) The default y position in screen coordinates.<br />
* '''default_w''' - (int) The default width in scalable units (1 == 1 pixel, if scale==100%)<br />
* '''default_h''' - (int) The default height in scalable units (1 == 1 pixel, if scale==100%)<br />
* '''default_visible''' - (bool) If true, show this container the first time the skin is ever shown (the system will track this value for the user, thereafter).<br />
* '''component''' - (str) If this parameter is set with a guid or groupid, it indicates to the system that inside this component there lives a wndholder object with the same parameter.<br />
* '''dynamic''' - (bool) If true, this means that when the skin is parsed, the container is not created. "Dynamic" containers are meant to be instantiated at runtime by the coder and act as a template to hold any type of content within them. Winamp3 uses dynamic containers to, for instance, provide outer frames for component windows, message boxes, etc. A dynamic container is instantiated when the coder requests it to be, and deleted when the layout is closed. If false (ie: not dynamic), this container will always be instantiated in the system at runtime, and the coder may only "hide" and "show" it.<br />
* '''primaryComponent''' - (String) Defines the primary comonent that should be hold in this container. Useful for SUI Skins in combination with primaryComponent="guid:player" in order to recieve keyboard/mouse actions in our main window.<br />
* '''canclose''' - (bool) Defines if the container can be closed (true) or not (false).<br />
* '''nofocusapponclose''' - (bool) If this Container is closed the main application (Winamp) can be restored from minimized state (true) or not (false).<br />
<br />
<br />
==<layout></layout>==<br />
* '''id''' - (id) The coder-oriented name of the layout. This value is used when appealing to this object.<br />
* '''owner''' - (str) This parameter has the special syntax of "componentid;layoutid" and will cause the OS window this layout represents to always match the current visible state (minimized, restored, etc) of the owning layout.<br />
* '''lockto''' - (str) This parameter has the same syntax as owner, but causes the relative positioning of this window to be locked to the position of the owning layout. If it moves, the owned layout moves along with it.<br />
* '''alpha''' - (int) This 0-255 integer parameter represents the flat alpha to be applied to the entirety of the layout.<br />
* '''desktopalpha''' - (bool) If true, this flag indicates to Wasabi that this layout would like to be drawn with desktop alpha, if that feature is enabled in the system.<br />
* '''indesktop''' - (bool) If true, causes the OS window to be a child of the desktop (under all other OS windows). <br />
* '''linkwidth''' - (str) This string parameter should be the layoutid of a sibling to this layout inside its container. Any changes to the width of this layout will be applied to the linked layout. One use is for a "windowshade" mode that automatically matches width to the "normal" layout. <br />
* '''linkheight''' - (str) Same as linkwidth, but for height. Will allow you to make "vertical" windowshades, should you so desire.<br />
* '''taskbar''' - (bool) This flag causes the layout to have its own taskbar button. (NOT YET IMPLEMENTED!)<br />
* '''move''' - (bool) Can be set to "0" to disable user moving. Useful for maximized mode.<br />
* '''resizable''' - (bool) Can be set to "0" to disable user resizing<br />
* '''scalable''' - (bool) Can be set to "0" to disable user scaling (experimental)<br />
<br />
<br />
==<groupdef></groupdef>==<br />
Groups are the workhorse of user interface design in Wasabi. Groups allow one to define and place in coordinate space a logical collection of GuiObjects that will live within a given rectangle (the boundary of the Group). They are the display-cases in which one keeps one's interface items tidily available to the user. The XML params specific to all groupdefs are:<br />
<br />
* '''background''' - (str) The id of a bitmap element to be stretched as the background of the group (all of the group contents draw on top of this bitmap)<br />
* '''drawbackground''' - (bool) Whether or not to actually draw the background pixels (useful for using the alpha channel of a background bitmap as the drawing region for the group).<br />
* '''default_w''' - (int) The default width for this group, if the group instantiation does not specify what the width should be.<br />
* '''default_h''' - (int) The default height for this group, if the group instantiation does not specify what the height should be.<br />
* '''maximum_w''' - (int) The maximum width for this group, beyond which Wasabi will not allow the group to be resized.<br />
* '''maximum_h''' - (int) The maximum height for this group, beyond which Wasabi will not allow the group to be resized.<br />
* '''minimum_w''' - (int) The minimum width for this group, beyond which Wasabi will not allow the group to be resized.<br />
* '''minimum_h''' - (int) The minimum height for this group, beyond which Wasabi will not allow the group to be resized.<br />
* '''propagatesize''' - (bool) Sends this group's default/minimum/maximum size parameters to the layout which contains the group. ie: if my minimum_h is 200 and my containing layout's minimum_h is 100 and I have my propagatesize flag set, my layout will now have a * '''minimum_h''' of 200, etc.<br />
* '''lockminmax''' - (bool) Locks the minimum and maximum size values to the default size value. Makes the group "nonresizable."<br />
* '''design_w''' - (int) The "design width" of this group. The "design" based sizes allow for a conditional layout of GuiObjects within them. These parameters are used in conjunction with the x1/x2/y1/y2/anchor coordinate system, which will be documented with GuiObjects.<br />
* '''design_h''' - (int) The "design height" of this group.<br />
* '''name''' - (str) A human readable string which will be the "Name" of this group, used by various objects in the system when referring the user to this groupdef. For instance, the TabSheet GuiObject contains one group for each displayed tab, and the name parameter of each group is the string displayed within each corresponding tab. <br />
* '''autowidthsource''' - (str) The id of an object contained within this group from which this group should set its width. For instance, the groupdef that defines the contents of the Checkbox GuiObject sets its width based on the size of the text object within it, which itself will be sized at instantiation depending upon the text placed within that particular text object (See: $/studio/studio/Wacs/wasabi.system/ui/guiobjects/xml/checkbox/checkbox.xml).<br />
* '''autoheightsource''' - (str) The id of an object contained within the group from which this group should set its height. <br />
* '''register_autopopup''' - (bool) This flag causes this group to be listed in the Windows submenu of the Wasabi MainMenu context menu. Its name parameter is displayed as the menu item. If that menu item is then selected, this group will be launched as a layout (in other words, in its own window). This is quite useful for the quick debugging of groupdef objects.<br />
* '''windowtype''' - (str) Specifying a groupdef as being a certain windowtype causes the group to automatically be instantiated and added to the collection specified by that windowtype. See below for more information and a list of what windowtypes currently exist in the system. <br />
* '''inherit_content''' - (bool) This parameter is used to be able to override the contents of a group already defined in the system. To go back to the "blueprints" analogy, this is like finding someone's original blueprints and editing them. The id of this groupdef should match the id of the other groupdef that you wish to modify. See below for examples and more information.<br />
* '''inherit_group''' - (str) This parameter is used to be able to copy the contents of a group already defined in the system as the starting point for one's own group definition. To go back to the "blueprints" analogy, this is like photocopying someone else's blueprints as a starting point for one's own. The param is the id of the other groupdef you wish to inherit.<br />
* '''inherit_params''' - (bool) Specifies whether or not to inherit the params of the inherited group as well as its content. Only meaningful with a valid inherit_group param or if overriding a previous groupdef.<br />
* '''xuitag''' - (str) Specifies that this group definition will create a new Xui object into the system with the given tag string. See Extending Wasabi: Creating XuiObjects for more information.<br />
* '''embed_xui''' - (str) Specifies the id of a contained object to which any XML parameters not valid for a group sent to the instantiation of the group (or the xuitag string) should be forwarded. See Extending Wasabi: Creating XuiObjects for more information.<br />
In addition to these parameters, all parameters that apply to a GuiObject may also be placed on a groupdef. This sets them up as default parameters for when the group is used in a group tag, which the skinner may of course override.<br />
<br />
Please note, as referenced earlier, the layout object is simply a special type of groupdef object, so all of these parameters also apply to it as well.<br />
<br />
Groups are inherently reusable objects, as well. In a process that object oriented programmers should be well familiar with, Groups are first Defined to contain their particular contents and then can be later Instantiated (multiple times, if so desired) within a user interface.<br />
<br />
For the non-programmers among our readers, consider the following analogy: Definition consists of making a set of instructions for how to create something, like the blueprints for a house. Instantiation is the process of creating that something based upon its definition: in this case, giving the blueprints to a General Contractor and waiting the requisite indeterminate number of weeks to have them build that house to your specification. Definition makes a concept. Instantiation converts it into a thing.<br />
<br />
Now imagine the vast expanse of cookie-cutter housing tracts that have proliferated across American suburbia in the past decades. In a single tract, only a small handful of different blueprints were Defined for building the hundreds of homes to be found, and each Instance of those designs has been personalized by its denizens (subject to the CC&R's for that neighborhood, of course). <br />
<br />
In the same way, you may define a Group to contain a specific set of objects with a specific set of parameters (your "instructions"), and then use ("instantiate") that Group over and over again in your user interface with minor tweaks to each usage ("instance").<br />
<br />
The XML tag Wasabi uses for Group Definition is the groupdef tag, while the tag used for Group Instantiation is the group tag. This section will deal specifically with the particularities of Group Definition and the parameters of the groupdef tag, while the group tag will be documented in its own section in the next chapter (along with everything else that is meant to live inside of a groupdef tag). Because the simplest form of a groupdef is rather boring, we'll first cover the parameters for groupdefs and then return to creating sample XML snippets somewhat more complicated and useful than the following (which defines "my group" as merely an instantiation of the contents of "othergroup")<br />
<groupdef id="mygroup"><br />
<group id="othergroup"/><br />
</groupdef></div>Culixhttp://wiki.shoutcast.com/wiki/Modern_Skin:_Simple_Skin_TutorialModern Skin: Simple Skin Tutorial2010-11-30T03:32:59Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>Creating a Modern Skin --> [[Modern Skin: Intro|Intro]] --> [[Modern Skin: Winamp 2 to W3+|Winamp 2 to Winamp 3+]] --> [[Modern Skin: Simple Skin Tutorial|Simple Skin Tutorial]] --> [[Modern Skin: XML Intro|XML Intro]] --> [[Modern Skin: Simple Skin Tutorial (Continued)|Simple Skin Tutorial (Continued)]] --> [[Modern Skin: Container| Container]] --> [[Modern Skin: Group|Group]] --> [[Modern Skin: Relative Positioning| Relative Positioning]] --> [[Modern Skin: Complex Skin|Complex Skin]] --> [[Modern Skin: Non-Rect Player| Non-Rect Player]] --> [[Modern Skin: Layer Composition| Layer Composition]] --> [[Modern Skin: Alpha Channels| Alpha Channels]] --> [[Modern Skin: Animatedlayer|Animatedlayer]] --> [[Modern Skin: Snap Points|Snap Points]] --> [[Modern Skin: Drawers|Drawers]] --> [[Modern Skin: Skin Scripting| Skin Scripting]] --> [[Modern Skin: Drawer Scripting| Drawer Scripting]] --> [[Modern Skin: Animating a Skin|Animating a Skin]] --> [[Modern Skin: Maki Overview| Maki Overview]] --> [[Main_Page#Glossary_of_Terms|Glossary]]<br />
<br />
<br />
In the next section, we will show how to make a simple skin and teach you the basic modern skinning terminologies.<br />
<br />
Before you start, you will need these items.<br />
<br />
==Simple Tutorial Skin File==<br />
<br />
We're going to show you how to make a simaple skin like the one shown below. Download the [http://media.winamp.com/5541/main/downloads/development/skinsmodern/SimpleTutorial.wal "Simple Tutorial Skin" example].<br />
<br />
<br />
[[Image:Simpleskin_blue.png]]<br />
<br />
<br />
When you save the file, make sure that the type of the file is selected to "All Type" and NOT "Winzip" filetype. You should save the file into your skin subdirectory in your Winamp 5 directory. for most people, that path is "C:\Program Files\Winamp\Skins".<br />
<br />
<br />
[[Image:Simpletutsave.png]]<br />
<br />
==Text Editing Programs==<br />
You can use any text editing program to write XML and MAKI script files.<br />
<br />
1) The plain Windows Notepad will do. It is under "Start Menu" => "Programs => "Accessories => "Notepad". Here's what it looks like.<br />
<br />
<br />
[[Image:Notepad.png]]<br />
<br />
<br />
2) However, if you intend to do alot of coding rather a quick editing, we recommed you to use something like [http://www.editplus.com/ EditPlus]. EditPlus will automatically color your HTML and XML code. The coloring makes it easier for you to see your code and find missing closing tags. Here's what it looks like.<br />
<br />
<br />
[[Image:Editplus.png]]<br />
<br />
<br />
You can select the type of coloring by going to "Document" menu => "Change File Type..."<br />
<br />
<br />
[[Image:Editplus_changetype.png]]<br />
<br />
==A Graphics program==<br />
We recommend [http://www.adobe.com/ Adobe Photoshop] or [http://www.corel.com/servlet/Satellite/us/en/Product/1184951547051#tabview=tab0 Paintshop Pro]. Here're some [http://forums.winamp.com/showthread.php?s=&threadid=93803 graphic design tutorials] if you're new to graphics.<br />
<br />
[[Image:Adobe.png]]<br />
<br />
[[Image:Psp.png]]</div>Culixhttp://wiki.shoutcast.com/wiki/Online_Service_Security_PromptsOnline Service Security Prompts2010-11-30T03:32:54Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by SMonty</p>
<hr />
<div>'''Breadcrumb''' -- [[Main_Page|Wiki Main]] : [[Skin Developer]] : [[Visual Developer]] : [[Plug-in Developer]] : [[Online Service Developer]] : [[Articles|Articles Page]] : [[Developers FAQ|FAQ]] : [[Category:Winamp]]<br />
==Winamp Online Services Security==<br />
<br />
Winamp Online Services is a powerful new way for web developers to create engaging content for millions of Winamp users. However, with great power comes great responsibility. Since online services have access to more information from the Winamp client than an ordinary web page, it is very important that we provide some mechanism to provide security for the users. <br />
<br />
There are certain activities that online services can perform that are not considered a security risk For example, examining the current position of a song being played. However, for others a security dialog will be presented whenever a service tries to perform the action for the first time. <br />
<br />
===Security Dialog Prompts===<br />
<br />
Security prompts contain a description of the action being attempted, an indication as to what API the action belongs, allow and deny buttons as well as a checkbox. <br />
<br />
Replies, either Allow or Deny, to security prompts are saved for each online service.<br />
<br />
====Allow====<br />
Allows the online service to perform the action. It will also automatically ALLOW other, related actions. The list below will identify which actions are related.<br />
<br />
====Deny====<br />
Does NOT allow the online service to perform the action. It will also automatically DENY other related actions.<br />
<br />
====Use this response for all security requests for this service==== <br />
When this checkbox is checked, the choice (Allow or Deny) will be used as the response to all subsequent security prompts for this service. This is a quick way to indicate that a particular online service should be allowed or denied (depending on the button pressed) to perform all actions.<br />
<br />
===Grouping APIs by Security Prompt===<br />
<br />
The following APIs and methods will cause a security prompt to appear the first time each service attempts to invoke them. Security responses for each message will then be used automatically for the other api methods listed.:<br />
====This service is trying to control playback====<br />
*API: Transport<br />
*Methods: Prev(), Play(), Stop(), Pause(), Next()<br />
*Description: The online service is attempting to Play, Stop, Pause, Jump to the previous track, or Jump to the next track.<br />
<br />
====This service is trying to monitor playback events====<br />
*API: Transport<br />
*Methods: RegisterForEvents()<br />
*Description: The online service is requesting to be notified when playback events occur. The possible events are Play, Pause, Stop, End of File. Note these events will occur whether initiated from scripts or from the user clicking on the buttons themselves. Some events carry additional information:<br />
**Play provides the filename/URL of the asset being played.<br />
**Stop provides the current position where playback was halted. End of File indicates that the end of the asset has been reached. <br />
**Pause provides a flag indicating whether the player was paused or unpaused.<br />
**End of File happens at the end of an asset before the next one is played.<br />
<br />
====This service is trying to get information about the currently playing song====<br />
*API: Transport<br />
*Methods: GetMetadata()<br />
*Description: The online service is requesting "Metadata" information from the current asset. "Metadata" is additional information that MAY be part of the asset, such as author or title, that is not actually part of the song itself. The existence of metadata depends on the format of the data and whether it was added when the asset was digitized.<br />
<br />
====This service is trying to access your active playlist====<br />
*API: PlayQueue<br />
*Methods: Play(), Enqueue(), Insert(), ClearQueue()<br />
*Description: The online service is trying to alter the Play Queue. It may be trying to play a single asset, add assets to the queue or clear the queue.<br />
<br />
====This service is trying to get information about an item in your Play Queue.====<br />
*API: PlayQueue<br />
*Methods: GetMetadata(), GetTitle(), GetURL()<br />
*Description: The service is trying to gather information about an asset within the play queue. <br />
<br />
====This service is trying to access the playlists in your media library====<br />
*API: PlayLists<br />
*Methods: GetPlaylists(), OpenPlaylist(), SavePlaylist()<br />
*Description: The online service is trying to obtain a list of all Winamp playlists known to your Winamp client. It may also be trying to open a playlist to manipulate the assets within or it may be trying to save a modified playlist.<br />
<br />
====This service is trying to access your bookmarks====<br />
*API: Bookmarks:<br />
*Methods: Add()<br />
*Description: The online service is trying to create a bookmark in your Media Library Bookmarks.<br />
<br />
====This service is trying to subscribe you to a podcast====<br />
*API: Podcasts<br />
*Methods: Add()<br />
*Description: The online service is trying to subscribe to a podcast and add an entry in your Media Library Podcasts<br />
<br />
====This service is trying to provide metadata to Winamp====<br />
*API: MediaCore<br />
*Methods: AddMetadataHook()<br />
*Description: The online service is trying to add metadata for an asset. This might be useful if the online service can provide better metadata than comes as part of the asset itself.<br />
<br />
====This service is trying to access information about media supported by Winamp.====<br />
*API: MediaCore<br />
*Methods: isRegisteredExtension()<br />
*Description: The service is trying to determine if the Winamp client supports a certain encoding formation, for example "mp3".<br />
<br />
====This service is trying to access information about media on your computer.====<br />
*API: MediaCore<br />
*Methods: GetMetadata()<br />
*Description: The online service is attempting to get metadata from an asset.<br />
<br />
====This service is trying to access your playback history====<br />
*API: History<br />
*Methods: Query()<br />
*Description: The Winamp History is a collection of information about the assets you play, how many times they were played and when was the last time they were played. It is used to determine what the users favorite songs are. <br />
<br />
====This service is trying to launch a website in the browser====<br />
*API: Application<br />
*Methods: LaunchURL()<br />
*Description: The online service is trying to launch a new web site in the browser. The browser may be internal to Winamp, which means it could be an online service or it could be launched in an external browser where it does not benefit from the online services api calls.<br />
<br />
====This service is trying to access information about Winamp====<br />
*API: Application<br />
*Properties: version, versionstring, language, languagepack<br />
*Description: The online service is trying to gather information regarding the version of Winamp or the language pack that is being used by Winamp.<br />
<br />
====This service is trying to access your skin settings====<br />
*API: Skins<br />
*Methods: GetClassicColor(), GetPlaylistColor(), GetSkinColor()<br />
*Description: The online service is trying to obtain information regarding the current skin used by the Winamp client. This could be used to sychronize the colors of the service with that of the Winamp player.</div>Culixhttp://wiki.shoutcast.com/wiki/Modern_Skin:_Non-Rect_PlayerModern Skin: Non-Rect Player2010-11-30T03:32:50Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Tarik</p>
<hr />
<div>Creating a Modern Skin --> [[Modern Skin: Intro|Intro]] --> [[Modern Skin: Winamp 2 to W3+|Winamp 2 to Winamp 3+]] --> [[Modern Skin: Simple Skin Tutorial|Simple Skin Tutorial]] --> [[Modern Skin: XML Intro|XML Intro]] --> [[Modern Skin: Simple Skin Tutorial (Continued)|Simple Skin Tutorial (Continued)]] --> [[Modern Skin: Container| Container]] --> [[Modern Skin: Group|Group]] --> [[Modern Skin: Relative Positioning| Relative Positioning]] --> [[Modern Skin: Complex Skin|Complex Skin]] --> [[Modern Skin: Non-Rect Player| Non-Rect Player]] --> [[Modern Skin: Layer Composition| Layer Composition]] --> [[Modern Skin: Alpha Channels| Alpha Channels]] --> [[Modern Skin: Animatedlayer|Animatedlayer]] --> [[Modern Skin: Snap Points|Snap Points]] --> [[Modern Skin: Drawers|Drawers]] --> [[Modern Skin: Skin Scripting| Skin Scripting]] --> [[Modern Skin: Drawer Scripting| Drawer Scripting]] --> [[Modern Skin: Animating a Skin|Animating a Skin]] --> [[Modern Skin: Maki Overview| Maki Overview]] --> [[Main_Page#Glossary_of_Terms|Glossary]]<br />
<br />
<br />
==Introduction==<br />
<br />
Modern Winamp skins bring forth unprecedented flexibility and power to skinning. You are no longer confined to simple rectangular shapes; in fact any shape is possible. Just take a look at these awesome examples. In addition, Winamp3 has been revamped so that any part of the user interface is skinnable.<br />
<br />
You should notice that while the shapes are different, the X and Y coordinate system still applies. The (0,0) coordiante starts at the upper-left corner. The x-coordinate increases at you move to the right and the y-coordinate increases as you move down.<br />
<br />
While the shape of the image can be anything you want, the image itself remains in rectangular form. What happens is that the back ground of the image is transparent; therefore all you see is the shape that you intend to show. To produce the complex designs that you see below, you must overlay many images on top of the each other. To do this, you must use layers. Layer composition is covered in the next section.<br />
<br />
<br />
[[Image:Non-rect mad.png]]<br />
<br />
<br />
[[Image:Non-rect boxer.png]]<br />
<br />
<br />
==Complex Tutorial Modern Skin - The Break Down==<br />
<br />
Complex Tutorial Skin is composed of these parts:<br />
<br />
Everything from Simple Tutorial Modern Skin<br />
A second container: "complex"<br />
Within the "complex" container, a layout called "normal".<br />
<br />
* Group #1: "complex.circle" - to illustrate Layer Composition (Section 3.2)<br />
* Group #2: "complex.circle2" - to illustrate Alpha Channel (Section 3.3)<br />
* Group #3: "complex.circle3" - to illustrate Drawer (Section 3.6 and 4.1)<br />
* Group #4: "complex.circle4" - to illustrate Animated Layer (Section 3.4)<br />
* Group #5: "complex.circle5" - to illustrate Animating Skin (Section 4.2) <br />
<br />
Concepts such as container, layout and group were explained in Section 2. Please refer to them.<br />
<br />
<br />
[[Image:Complexskin_diag.png]]<br />
<br />
<br />
<br />
==Player.XML - Part 1: SimpleTutorialXML.xml==<br />
<br />
<br />
When you open player.xml file for the "Complex Tutorial" skin, you noticed that it has been changed from the one from "Simple Tutorial" skin. We have made changes to it to illustrate new concepts for this section. Part one of the file (line 1-7) gives a brief description of the file and tells you that the components from Simple Tutorial has been moved into a different file: SimpleTutorialXML.xml. We used an <include > tag to incorporate all of the Simple Tutorial's functionalities into our current skin.<br />
<br />
<br />
[[Image:Complex playerxml 1.png]]<br />
<br />
<br />
<br />
<br />
==Player.XML - Part 2: Graphic Elements==<br />
<br />
<br />
[[Image:Triangle-clickme.png]] [[Image:Blue-vis-layer.png]] [[Image:Yellowcircle-arrow.png]] [[Image:Background.png]]<br />
<br />
[[Image:Blue-circle.png]] [[Image:Red-circle.png]] [[Image:Triangle.png]] [[Image:Numfont1.png]]<br />
<br />
<br />
This are the graphics that I've used in creating complex Tutorial skin. One thing to notice is that we like to use PNG file format. Please also use that format too. The graphics files are the parts that we're going to use for our skin. The following are XML code linking graphics to elements. Element definition was covered in last section.<br />
<br />
<br />
[[Image:Complex playerxml 2.png]]</div>Culixhttp://wiki.shoutcast.com/wiki/Modern_Skin:_Maki_OverviewModern Skin: Maki Overview2010-11-30T03:32:44Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>Creating a Modern Skin --> [[Modern Skin: Intro|Intro]] --> [[Modern Skin: Winamp 2 to W3+|Winamp 2 to Winamp 3+]] --> [[Modern Skin: Simple Skin Tutorial|Simple Skin Tutorial]] --> [[Modern Skin: XML Intro|XML Intro]] --> [[Modern Skin: Simple Skin Tutorial (Continued)|Simple Skin Tutorial (Continued)]] --> [[Modern Skin: Container| Container]] --> [[Modern Skin: Group|Group]] --> [[Modern Skin: Relative Positioning| Relative Positioning]] --> [[Modern Skin: Complex Skin|Complex Skin]] --> [[Modern Skin: Non-Rect Player| Non-Rect Player]] --> [[Modern Skin: Layer Composition| Layer Composition]] --> [[Modern Skin: Alpha Channels| Alpha Channels]] --> [[Modern Skin: Animatedlayer|Animatedlayer]] --> [[Modern Skin: Snap Points|Snap Points]] --> [[Modern Skin: Drawers|Drawers]] --> [[Modern Skin: Skin Scripting| Skin Scripting]] --> [[Modern Skin: Drawer Scripting| Drawer Scripting]] --> [[Modern Skin: Animating a Skin|Animating a Skin]] --> [[Modern Skin: Maki Overview| Maki Overview]] --> [[Main_Page#Glossary_of_Terms|Glossary]]<br />
<br />
<br />
==What is Maki==<br />
<br />
<br />
Maki is a user interface and event management scripting system and more. The primary purpose of Maki is to handle all of the user interface behavior. Maki is used to insert functionality in Winamp3. The inserted functionality can range from a new user interface behavior to an alarm clock to a seperate EQ control system. You must not forget that Maki is part of Wasabi, which is used to build Winamp3. It's therefor safe to assume that Wasabi based applications (other than Winamp3) support Maki also. Well, when there are others that is.<br />
<br />
<br />
==What does Maki mean?==<br />
<br />
<br />
'''M'''ake '''A''' '''K'''iller '''I'''nterface<br />
<br />
<br />
==What can Maki do?==<br />
<br />
<br />
Maki as a language can do pretty much everything most scripting languages do. It supports user functions, user classes. It also has a full fledged pre-processor that allows you to include other Maki source files. Maki scripts are actually compiled using the Maki Compiler (MC.EXE, look for it in your Winamp3 directory. Don't worry about the compiler, we'll explain how it works later on).<br />
<br />
So here's a list of what Maki can do, just remember, it might change, but always in a good way, at least, we hope so.<br />
<br />
*Trap and hook events (onClick() do something...)<br />
*Move user interface elements (take button A and move it to position x,y)<br />
*Move and change images (button A has image A, set button A's image to image B)<br />
*Show and Hide Windows.<br />
*Control Winamp3 playback (play, stop, next, etc.)<br />
*Control Winamp3 volume (set the volume to 100%)<br />
*Control Winamp3 equalizer levels (set 60hz to +20db, for you bass addicts.)<br />
*Make an Alarm<br />
*Make a Clock<br />
*etc.<br />
<br />
Now, you might not realise it, but the fact it can trap events and hook events and create new GUI objects on the fly means it can pretty much do anything. Something very important to remember is that some GUI objects need to be "binded" before being able to be used to trap events. The best way to go about this is to remember that objects need to be binded before being used. Here's a short example: <br />
<br />
Global Timer myTimer;<br />
System.onScriptLoaded() {<br />
myTimer = new Timer;<br />
}<br />
myTimer.onTimer() {<br />
//Do cool stuff here.<br />
}<br />
<br />
<br />
==When should I use Maki?==<br />
<br />
<br />
It's always hard to decide if you want to implement something via scripting or component. Always remember that many things can be done with Maki and that implementing something via scripting is also much faster than using a component. This is super true when it comes to user interface behavior in skins. Literaly ANYTHING that has to do with how the user interface (skin) behaves and changes because of user input is pretty darn quick to write in scripting, but you can still do it in a component if you wish.<br />
<br />
Mainly, you have to look at the potential level of complexity of what you're trying to do. You don't want to implement something very complex in script because it will definitely be slower than straight C++ code. <br />
<br />
<br />
==Maki Syntax==<br />
<br />
<br />
Here's where the fun ends for me and I have to start being all serious and actually explain important stuff. Ugh. So, first I'm going to explain general syntax, like what constitutes an instruction, how you terminate lines, etc. Then we'll jump into variables, functions, classes and class members. Here we gooooooooo!<br />
<br />
First off, Maki is NOT case sensitive, so a function named llama can also be called by using Llama. I'd also like to point out the difference between pre-processor statements and actual code statement. Pre-processor statements are read and processed FIRST, before even ONE shred of code is actually compiled. They start with # and end with a carriage return. Actual code starts pretty much with anything but # and ends with a ;. This excludes flow control statements (like if(..) {... ). Now I know it's a bit odd to just read things and not see it, so, how about a little example? *nod*<br />
<br />
First, pre-processor statements:<br />
<br />
#include "../../lib/std.mi"<br />
<br />
#define ACTIVEALPHA (230)<br />
#define INACTIVEALPHA (150)<br />
<br />
The pre-processor statements are pretty self explainatory. I'll explain what they actually mean really soon, just observe the syntax for now.<br />
<br />
Now, a code snippet:<br />
<br />
if (isactive != prev_active) {<br />
prev_active = isactive;<br />
fader.start();<br />
}<br />
<br />
Since if is a control statement and marks the beginning of a code block ( a code block is something in between { .. } ), it doesn't require a ;, the line below it however, isn't a control statement and requires the line to end with a ;. Again, I will explain what everything means later, for now, just observe the syntax.<br />
<br />
<br />
==Maki Datatypes==<br />
<br />
<br />
In this section, we'll go thru all the different datatypes available in Maki and how to use them (And also, a quick overview of what exactly is a variable in Maki). Currently in Maki there are 6 basic types you can use:<br />
<br />
*Boolean<br />
*Int<br />
*Float<br />
*Double<br />
*String<br />
*Object<nowiki>*</nowiki><br />
<br />
<nowiki>*</nowiki> Object is a compound type, we'll see what it means later.<br />
<br />
Now for a description of each of the types. Please note that the variable types aren't case sensitive.<br />
<br />
===Boolean===<br />
<br />
Boolean is a boolean value that can have two states. For us, these states are true (1) and false (0). Here's how you create a Boolean variable and assign a value to it:<br />
<br />
//Create a bool type variable and assign 0 (false) to it.<br />
Boolean state = 0;<br />
<br />
//Assign 1 (true) to our bool variable named state.<br />
state = 1;<br />
<br />
//Assign false (0) to our bool variable named state.<br />
state = false;<br />
<br />
//Assign true (1) to our bool variable named state.<br />
state = true;<br />
<br />
===Int===<br />
<br />
Int is a signed* round integer value from -2 147 483 647 to +2 147 483 648 (this means no decimal values, ever). Here's how you create an Int variable and assign a value to it:<br />
<br />
//Create an int type variable and assign 255 to it.<br />
Int alpha = 255;<br />
<br />
//Assign the value 1000 to our int variable named alpha.<br />
alpha = 1000;<br />
<br />
//Assign the value -1000 to our int variable named alpha.<br />
alpha = -1000;<br />
<br />
<br />
===Float===<br />
<br />
Float is a signed floating point number. Here's how you create a Float variable and assign a value to it:<br />
<br />
//Create a float type variable and assign 0.25 to it.<br />
Float fraction = 0.25;<br />
<br />
//Assign the value 0.5 to our float variable named fraction.<br />
fraction = 0.5;<br />
<br />
//Assign the value -3.5566 to our float variable named fraction.<br />
fraction = -3.5566;<br />
<br />
<br />
===Double===<br />
<br />
Double is a signed floating point number with double precision.<br />
<br />
//Create a float type variable and assign 0.000000125 to it.<br />
Double fraction = 0.000000125;<br />
<br />
//Assign the value 0.5 to our double variable named fraction.<br />
fraction = 0.5;<br />
<br />
//Assign the value -3.5566 to our double variable named fraction.<br />
fraction = -3.5566;<br />
<br />
===String===<br />
<br />
String is a string, it can be of any length. Here's how you create a String variable and assign a value to it:<br />
<br />
//Create a string type variable and assign a sentence to it.<br />
String name = "My real name is not Aus.";<br />
<br />
//Assign the value "Guru" to our string variable named name.<br />
name = "Guru";<br />
<br />
//Assign the value "Francis" to our string variable named name.<br />
name = "Francis";<br />
<br />
===Object===<br />
<br />
Object is a compound type. This means it can have more than just one value associated with it. Infact, you can even attach values to it, and even other objects.<br />
<br />
===Null===<br />
<br />
Null is a special case. You can't create a variable of this type, it is ONLY used in comparaisons and can compare to any type variable and object. You can use it to see if a variable contains something or exists.<br />
<br />
==Maki Operators==<br />
<br />
===Mathematical===<br />
<br />
All basic math operators are available, here's a list of them and what they do.<br />
<br />
[[Image:Table1.png]]<br />
<br />
<br />
===Logical===<br />
<br />
<br />
[[Image:Table2.png]]<br />
<br />
<br />
===Bit===<br />
<br />
<br />
[[Image:Table1.png]]<br />
<br />
<br />
===Assignment===<br />
<br />
<br />
[[Image:Table1.png]]<br />
<br />
==Maki Control Structures==<br />
<br />
Control structures are what influence the flow of the code, certain parts are executed only in certain cases, some a fixed amount of times, some a variable amount of times, etc. Most of the basic control structures found in modern languages are available in Maki. Here's a list of them:<br />
<br />
===if===<br />
<br />
if(state == true) {<br />
state = false;<br />
}<br />
<br />
===if else===<br />
<br />
if(state == true) {<br />
state = false;<br />
} else {<br />
state = true;<br />
}<br />
<br />
===while loop===<br />
<br />
while(state == true) {<br />
...<br />
}<br />
<br />
===do while loop===<br />
<br />
do {<br />
...<br />
} while(state == true);<br />
<br />
===for loop===<br />
<br />
for(int i = 0; i < 10; i++) {<br />
...<br />
}<br />
<br />
==Maki Functions==<br />
<br />
<br />
===How do I create my own Maki functions===<br />
<br />
Functions in Maki need to be declared before they can be used (you can declare and define it if you want also). When declaring a function you need to use the proper prototype line for the function you wish to create. This includes the return value type and the parameters it takes.<br />
<br />
There are two ways you can go about creating functions.<br />
<br />
1) You can group all your function declarations (called prototypes) at the top of your script and then define (write the actual code associated with the functions) them anywhere in the file. Like so:<br />
<br />
#include <br />
<br />
Function Boolean CheckLevel(int Threshold);<br />
Function Int CheckPlaystring(String _Playstring);<br />
<br />
...<br />
<br />
Boolean CheckLevel(int Threshold) {<br />
...<br />
}<br />
<br />
Int CheckPlaystring(String _Playstring) {<br />
...<br />
}<br />
<br />
2) You can declare the function just before defining it. Like so:<br />
<br />
#include <br />
...<br />
Function Boolean CheckLevel(int Threshold);<br />
Boolean CheckLevel(int Threshold) {<br />
...<br />
}<br />
<br />
<br />
The preferred method is the first because it's just much easier to organize things, but, you can do it the other way if you want to.<br />
<br />
===How to read function prototypes===<br />
<br />
Function RETURN_VALUE_TYPE FUNCTION_NAME(PARAM_TYPE PARAM_NAME, ...);<br />
<br />
*RETURN_VALUE_TYPE is the type of the return value, it can be any type supported by Maki, including user classes.<br />
*FUNCTION_NAME is the name of the function you are declaring. It can be any combination of letters and numbers but it MUST start with a letter.<br />
*PARAM_TYPE is the type of the parameter you will be passing to the function, it can be any type supported by Maki, including user classes.<br />
*PARAM_NAME is the name the parameter will have inside the function, it can be any combination of letters and numbers but it MUST start with a letter.<br />
<br />
<br />
The function's name and parameter names CAN NOT use any of the existing Maki keywords.<br />
<br />
==Maki Classes==<br />
<br />
<br />
The already existing Maki classes usually consist of two things: member data and methods. It's very important to remember that user classes do not support methods yet. (needs improvement)<br />
<br />
<br />
==Maki User Classes==<br />
<br />
<br />
(needs improvement)<br />
<br />
==Gerneral Scripting Rules==<br />
<br />
<br />
These are just general things you want to keep in mind when writing Maki scripts and when writing code in general too! :)<br />
<br />
*As a rule of thumb, all uppercase is reserved for constants. So please avoid naming anything that's not a constant all in uppercase.<br />
<br />
==STD.MI Reference==<br />
<br />
<br />
If you'd like to know more about STD.MI simply open it in your favorite text editor and check out the spiffy comments. If you need more help, [http://forums.winamp.com/ check out the forums!]</div>Culixhttp://wiki.shoutcast.com/wiki/Modern_Skin:_Drawer_ScriptingModern Skin: Drawer Scripting2010-11-30T03:32:40Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Tarik</p>
<hr />
<div>Creating a Modern Skin --> [[Modern Skin: Intro|Intro]] --> [[Modern Skin: Winamp 2 to W3+|Winamp 2 to Winamp 3+]] --> [[Modern Skin: Simple Skin Tutorial|Simple Skin Tutorial]] --> [[Modern Skin: XML Intro|XML Intro]] --> [[Modern Skin: Simple Skin Tutorial (Continued)|Simple Skin Tutorial (Continued)]] --> [[Modern Skin: Container| Container]] --> [[Modern Skin: Group|Group]] --> [[Modern Skin: Relative Positioning| Relative Positioning]] --> [[Modern Skin: Complex Skin|Complex Skin]] --> [[Modern Skin: Non-Rect Player| Non-Rect Player]] --> [[Modern Skin: Layer Composition| Layer Composition]] --> [[Modern Skin: Alpha Channels| Alpha Channels]] --> [[Modern Skin: Animatedlayer|Animatedlayer]] --> [[Modern Skin: Snap Points|Snap Points]] --> [[Modern Skin: Drawers|Drawers]] --> [[Modern Skin: Skin Scripting| Skin Scripting]] --> [[Modern Skin: Drawer Scripting| Drawer Scripting]] --> [[Modern Skin: Animating a Skin|Animating a Skin]] --> [[Modern Skin: Maki Overview| Maki Overview]] --> [[Main_Page#Glossary_of_Terms|Glossary]]<br />
<br />
<br />
==What is a MAKI Script?==<br />
<br />
<br />
What is MAKI? MAKI stands for Make A Killer Interface. It is the scripting language for modern Winamp skins. Scripting is used to produce the animations you see in the skin. Scripting is simple. It's easy! Anyone can do it! You'll love it.... Trust me.<br />
<br />
==So how does a MAKI script work?==<br />
<br />
<br />
MAKI scripts are event based. In other word, your functions are used to define behaviors when an event occurs. If you don't define action for that event, the default behavior will be used and the default behavior is defined by Winamp. Scripts are used to override an existing behavior. For example, when you click on the PL button, the playlist container appears. You can override that functionality so that the Media Library also appears. (However, we don't recommend you to do this)<br />
<br />
==What about elements I define in my own skins?==<br />
<br />
<br />
When you define new elements in your skin such as new buttons or sliders (elements that is not in the Default skin), essentially what you're doing is creating new objects. The behavior for that object is nothing.... nada until you specify an action in you XML or in your scripts.<br />
<br />
The script to implement the animation you see below is short and simple. But it demonstrates the power of modern skins: with little programming, you can add functionalities to your skin or user interface. For more about MAKI, please read MAKI Overview.<br />
<br />
<br />
[[Image:Flash3.png]]<br />
<br />
<br />
==Compiling a MAKI script==<br />
<br />
<br />
[[Image:Scripting dir.png]]<br />
<br />
<br />
Here are the basic concepts that you should know before starting.<br />
<br />
<br />
===Directory hierarchy===<br />
<br />
<br />
All your scripts for your skin should be together in a subdirectory. Usually that subdirectory is called "scripts". In terms of hierarchy, that subdirectory is placed under your skin directory. In our example, "scripts" subdirectory is under the "ComplexTutorial" skin directory.<br />
<br />
<br />
===.m and .maki files===<br />
<br />
<br />
A sourcecode file is a text file that you can read and understand with a text program like Notepad or Editplus. The sourcecode file for your script has the .m extension. A compiled file is the result after being compiled by the compiler. It has been optimized (therefore unreadable for you) for the computer to run. The compiled script has the .maki extension.<br />
<br />
<br />
===Compiling a MAKI file===<br />
<br />
<br />
To compile a MAKI scripting, you must use the MAKI Compiler (mc.exe) in your Winamp directory. It is located in the same directory as your Winamp player. Chances are that it is located in "C:\Program Files\Winamp\Studio.exe" directory.<br />
<br />
#Open a DOS Prompt: "Start Menu" => "Run..." => type "command"<br />
#Change path to script directory for your skin. For this example, the path is "C:\Program Files\Winamp\Skins\ComplexTutorial\Scripts"<br />
#Run mc.exe on your script. Because mc.exe is not located in the same directory as your script, you need to type "..\..\..\mc" in order to run it. For our example, it is "..\..\..\mc triangle.m" to compile triangle.m into triangle.maki.<br />
<br />
You can set an environment variable to your Winamp directory so you don't have to type "..\..\..\" to access mc.exe. You can just type "mc triangle.m" instead. (To set an environment variable: Right on "My Computer" => "Advanced" tab => Environment Variables.)<br />
<br />
<br />
[[Image:Scripting dos.png]]<br />
<br />
<br />
==MAKI Script - triangle.m==<br />
<br />
<br />
The drawer animation is done through MAKI Scripting. The script is short and simple but it demonstrates the power of modern skins: with little programming, you can add functionalities to your skin or user interface. In your XML, you need to specify which MAKI script you want to use.<br />
<br />
<br />
[[Image:Scripting drawerxml.png]]<br />
<br />
<br />
Lets break down the script:<br />
<br />
===Introduction Comments:===<br />
<br />
The first part of the script should be a brief introduction to the script. It should talk about the purpose and the functionality of the script.<br />
<br />
<br />
[[Image:Scripting trianglemaki1.png]]<br />
<br />
<br />
===#include Section:===<br />
<br />
<br />
The second part is the #include section. Use "#include" to include any file you need. If you need to call or use another function that is defined in another file, make sure you include that file in your script.<br />
<br />
<br />
[[Image:Scripting trianglemaki2.png]]<br />
<br />
<br />
===Variable Declaration Section===<br />
<br />
Any variable that you'll use in your script, declare them in this section.<br />
<br />
<br />
[[Image:Scripting trianglemaki3.png]]<br />
<br />
<br />
===System.onScriptUnloading() Section===<br />
<br />
When the script is unloaded, this part of the script will run. Typically, you do your clean up in this section. Our triangle script is simple and therefore doesn't need anything in this section.<br />
<br />
<br />
[[Image:Scripting trianglemaki4.png]]<br />
<br />
<br />
===System.onScriptLoaded() Section===<br />
<br />
When the script is first loaded, this part of the script will run. Typically, if anything you want to make happen when the script first start, you do that here. In our example, we initialized some objects and set the initial state for those objects. Just like the previous section, it is perfectly fine to leave this section empty. If you do that, nothing will happen when the script is loaded.<br />
<br />
<br />
[[Image:Scripting trianglemaki5.png]]<br />
<br />
<br />
===Your own functions===<br />
<br />
This section is where you put all your own functions that will define the behavior of your script. Make sure that any variable you use in this function is decared and their initial state has been initialized. For our example, we have two functions.<br />
<br />
*button_triangle.onleftbuttonup(int x,int y) function<br />
<br />
This function responds to the event when the triangle button is pressed. The triangle buttons has two states: open or closed. Depending on the current state, its position is changed so that it is moved.<br />
<br />
*button_triangle.ontargetreached() function<br />
<br />
This function responds to the event when the triangle has reached its destination. What event occurs, the state of the button is changed to its new state.<br />
<br />
<br />
[[Image:Scripting trianglemaki6.png]]</div>Culixhttp://wiki.shoutcast.com/wiki/For_Winamp_2.9/5.xFor Winamp 2.9/5.x2010-11-30T03:32:31Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Explorer09</p>
<hr />
<div>{{ClassicSkin}}<br />
<br />
==Skinning Additional Winamp 2.9/5.x Windows==<br />
<br />
===The Video Window===<br />
<br />
<br />
<br />
[[Image:Video_window.gif]]<br />
<br />
<br />
This file is for the Video window. It is resizeable and tiled, just like the playlist window. The titlebar occupies the two top rows. It's just like the playlist titlebar without the winshade mode and missing the winshade button. The close button is in the default state, beside the little graphic that is tiled across everytime the window is scaled horizontally. <br />
<br />
<br />
<br />
[[Image:Video.gif]]<br />
<br />
'''video.bmp'''<br />
<br />
The next row of graphics contains what would appear on the bottom left corner of the window which has all the video window buttons in their unpressed states. It also contains (from left to right) the left and right borders of the window for vertical scaling, the pressed close button and all the other buttons in their pressed state. The video buttons are (from left to right) full screen, regular size, double size, TV browser and load file. The next row of graphics has the right corner of the window and the bottom tile. The right corner has the resize button. The bottom tile will be used for horizontal scaling. Along this bottom tile, there will be a box to contain the current playing filename.<br />
<br />
==="Gen" Windows===<br />
<br />
<br />
[[Image:Gen.gif]]<br />
<br />
'''gen.bmp'''<br />
<br />
Gen.bmp is used for general purpose windows such as the media library and the AVS window in Winamp versions greater than 2.9. General purpose windows are resizeable and tiled. The first row is th active title bar and the second row is the inactive one. The title bar is divided into six parts. The first part is the top left corner of the window. The second is a fixed bitmap graphic which does not repeat in the title bar. The third section is the main title container. The fourth is another non repeating part of the title bar. The fifth section is used when the window is horizontally scaled. The last piece is the top right corner of the window and it contains the close window button. Below the title bars are the left bottom corner and the right bottom corner. The left one is placed above the right one. The right bottom corner has a resize button. To the right of these bottom corners are the sidewalls of the window. The left sidewall comes first then the right one. These sections are used during resizing. next to these is the close window button. next to this close button are the bottom corner sidewalls. These sections are used to join the sidewalls to the left and right bottom corners of the window. The left corner sidewall comes before the right one. The right one contains part of the resizer button from the bottom right corner of the window. Immediately below these corner sidewalls is a graphic for the bottom of the window. This graphic is tiled when the window is resized. Below this are the font of the titlebar. The highlighted one lies above the non highlighted font. The fonts are of variable width but not height. Both the highlighted and non highlighted fonts must be of the same width. The letters are ordered in the standard English alphabet order. There are no foreign characters. <br />
<br />
<br />
<br />
[[Image:Genex.gif]]<br />
<br />
'''genex.bmp'''<br />
<br />
Genex.bmp is used for the buttons and sliders used in the general purpose windows. It also contains the colour controls for this window. The top button is the active state button. The one right below it is the inactive or pressed state button. These buttons have a four pixel wide border around it. The borders stay 4 pixels thick, no matter the size of the buttons or window. Beside these buttons is a row of pixels used to control the various colors and background of the gen window. The coordinates of the pixels are for as follows (y=0):<br />
<br />
# x=48: item background (background to edits, listviews, etc.)<br />
# x=50: item foreground (text colour of edits, listviews, etc.)<br />
# x=52: window background (used to set the bg color for the dialog)<br />
# x=54: button text colour<br />
# x=56: window text colour<br />
# x=58: colour of dividers and sunken borders<br />
# x=60: selection colour for entries inside playlists (nothing else yet)<br />
# x=62: listview header background colour<br />
# x=64: listview header text colour<br />
# x=66: listview header frame top and left colour<br />
# x=68: listview header frame bottom and right colour<br />
# x=70: listview header frame colour, when pressed<br />
# x=72: listview header dead area colour<br />
# x=74: scrollbar colour #1<br />
# x=76: scrollbar colour #2<br />
# x=78: pressed scrollbar colour #1<br />
# x=80: pressed scrollbar colour #2<br />
# x=82: scrollbar dead area colour <br />
<br />
Below these are the scroll buttons. The first four buttons are these buttons: (from left to right) the scroll up unpressed, scroll down unpressed, scroll up pressed, scroll down pressed. Immediately below these are (from left to right) the scroll left unpressed, scroll right unpressed, scroll left pressed, scroll right pressed. Beside these two rows of scroll buttons are the sliders. The first one from the left is the vertical slider unpressed, the second one is the vertical slider pressed. Beside it, on the top is the horizontal slider unpressed. Below this is the horizontal slider pressed.</div>Culixhttp://wiki.shoutcast.com/wiki/Color_EditorColor Editor2010-11-30T03:32:26Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>== Where are the themes saved? ==<br />
When you save your themes it will save in one of the following places, depending on what type of installation of Winamp you have:<br />
* Multi-User Settings Install (default)<br />
** '''%appdata%/winamp/Plugins/Freeform/wacs/coloreditor/data'''<br />
* Winamp folder Settings<br />
** '''x:/.../winamp/Plugins/Freeform/wacs/coloreditor/data'''<br />
<br />
== Hidden features ==<br />
=== Multi Slider move ===<br />
When you move one of the sliders you can press Ctrl or Shift to move the other 2 sliders too.<br />
This is sometimes usefull of you just want to finetune a certain color.<br />
* '''Ctrl'''+Slide<br />
** All sliders have the same value.<br />
* '''Shift'''+Slide<br />
** The other 2 sliders will now move relative to the one your moving.<br />
<br />
== Winamp 5 Color Editor F.A.Q. ==<br />
<br />
<br />
'''1. Why can't I edit my skin's color themes ? Why is there a “locked” icon in front of them ?<br />
'''<br />
A skin may be zipped, and so the color editor cannot 1) unzip your skin, 2) change the themes definitions, and 3) rezip the skin. Even if it could, or if the skin was unzipped in the first place, the color editor would have to find the file that defines the color themes, and this may be any xml file in the skin.<br />
<br />
The color editor's philosophy is therefore not to touch the skins directly : the only editable color themes are those you create. To edit a color theme, you should clone it first !<br />
<br />
'''2. How can I send my colorthemes to someone without making him edit his skin ?'''<br />
<br />
You should first export your colorthemes using the export button on the color editor, and then install the exported file into the Winamp5 colorthemes directory located at : <br />
<br />
path_to_winamp\plugins\ColorThemes\name_of_the_skin\<br />
<br />
The file you install should have the xml extention and a somewhat unique name so that it does not conflicts with other custom themes packs (ie: not “themes.xml”).<br />
<br />
Upon reloading Winamp5, the themes should now appear in the colorthemes selection box. Note that they will not be editable (see faq 1 above).<br />
<br />
'''3. Why does going from RGB to HSL sometimes slightly changes my color group setting ?'''<br />
<br />
Although all RGB colors have an HSL equivalent and vice-versa, these are not one-to-one equivalents (two RGB colors may have the same HSL equivalent). This is a consequence of the RGB/HSL conversion algorithms.<br />
<br />
'''4. How do I create a new color group ?'''<br />
<br />
Color groups are an integral part of the skin, they change for each skin, and they are defined by the skinner. The color editor's purpose is to let you assign new color values for these color groups, not to let you create more groups in the skin you are using or for the skin you are making.<br />
<br />
'''5. How do I find what color group is used by a given widget ?'''<br />
<br />
The only way to do this for now is to try each color group. A later version may let you flash a specific color group in the skin, but this will be very cpu-intensive (changing a color group reloads all the skins images), but since a given widget may implicitly use more than one colortheme, we would need to have the skinner list these colorthemes explicitly for each widget to be able to let you find this out more easily. This would be a daunting task for the skinner, and so this is not a viable option.<br />
<br />
'''6. Why are there widgets for which there is no color group ?'''<br />
<br />
Either the skinner forgot to define a color group for the graphical elements used by the widget, or you have missed it.<br />
<br />
'''7. What is the difference between “Max Grayscale” and “Avg Grayscale” ?'''<br />
<br />
Max grayscale is computed by getting the maximum value of each red, green and blue color channels, and assigning this value to each three (each pixel is done independently). <br />
Avg (average) grayscale is computed by getting the average value of the red, green and blue color channels, and assigning this value to each three (each pixel is done independently).<br />
<br />
'''8. What is “Saturate channels” ?'''<br />
<br />
“Saturate channels” adds 127 to each pixels's color channel.<br />
<br />
'''9. Why is the resulting color for the graphical element not the color that I see above each slider ?'''<br />
<br />
The color you see above each slider is the color you get for a pixel that has the “Preview source color” values for its color channels. To get an accurate result, you should select a previous source color that is approximately the average color of the graphical element you are tweaking. For instance, if you are changing a graphical element that has only red (ie: it has 0 in its green and blue channels), no matter the poxition of the green and blue sliders, it will not change anything in the element. If that happens, you can use one of the two grayscale checkboxes, so that the element will be grayscaled before the color tweak is applied, or you can use the saturate channels checkbox to boost its color channels so that all three sliders will have an effect. <br />
<br />
'''10. Why does the red (or green or blue) slider has no effect on some widget ?'''<br />
<br />
See faq 9.<br />
<br />
Why does the red green and blue values for each color group goes from -4096 to +4096 rather than from 0 to 255 ?<br />
<br />
The red green and blue values in the xml for a color theme are not a direct representation of the color you get (otherwise, it would make all pixels this value!), they are (arbitrarilly ranged) values that are used to multiply (or divide) each pixels's channel.<br />
<br />
'''11. Why does the hue slider cycles twice over the hue circle ?'''<br />
<br />
The hue slider works just as the RGB sliders do, it changes each pixel color starting from its original channel values. The hue value you select makes the pixel's hue be shifted left or right over the hue circle just as the red (or green or blue) sliders shifts the red (or green or blue) value left or right in the original pixel, and so you can go one complete circle in one direction, or one complete circle in the other. In effect, where photoshop lets you go from 0° to 360° on the hue circle, the color editor lets you go from -360° to +360°<br />
<br />
'''12. Why do the saturation and luminance sliders show a gradient between 2 colors rather than the standard color-to-white and color-to-black gradients ?'''<br />
<br />
Here too, the sliders let you change the original pixels one direction or another, so the saturation slider lets you desaturate a pixel beyond the zero limit (and the luminance slider lets you subtract luminosity bellow the zero limit) of a standard HSL algorithm. In effect, where photoshop lets you go from 0 to 100% for these two components, the color editor lets you go from -100% to +100%.</div>Culixhttp://wiki.shoutcast.com/wiki/MilkDrop_Unleashed_GuideMilkDrop Unleashed Guide2010-11-30T03:32:15Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by SMonty</p>
<hr />
<div>'''Breadcrumb''' -- [[Main_Page|Wiki Main]] : [[Skin Developer]] : [[Visual Developer]] : [[Plug-in Developer]] : [[Articles|Articles Page]] : [[Developers FAQ|FAQ]] : [[Main_Page#Glossary_of_Terms|Glossary]]<br />
<br />
===Installation===<br />
MilkDrop 2 comes with Winamp. To install it, just download and install the latest version of Winamp. During the installation, make sure the "MilkDrop" visualizer option is checked, so that it gets installed, too. <br />
<br />
Once Winamp is installed, launch it. Load some music files into your playlist and start playing some music. (Be sure to play some music before trying to launch the visualizer - otherwise you'll just see a black screen.)<br />
<br />
Once music is playing, hit CTRL+K and a list of visualization plug-ins will appear. Select "MilkDrop 2" from the list. Then click the "Start" button, and it will launch the visualizer. <br />
<br />
Quick Tips: <br />
* If you want to go full-screen, double-click on the visualizer itself.<br />
* CTRL+SHIFT+K starts or stops the visualizer.<br />
* To configure MilkDrop's options, exit the visualizer and hit ALT+K.<br />
<br />
If you have trouble getting MilkDrop to run properly after installation, <br />
try installing various recent WHQL drivers for your video card, or installing <br />
DirectX; doing these two things (especially the first) will fix 99% of<br />
problems. See the Troubleshooting section of the documentation for more<br />
information.<br />
<br />
===Tweaking to achieve best image quality===<br />
<br />
a) Fullscreen Display Mode [first tab of config screen]<br />
<br />
When you run MilkDrop fullscreen, it changes the display mode to whatever you select here. Generally speaking, the speed (framerate) and smoothness of MilkDrop will drop as the resolution (number of pixels on the screen)increases. So, if it's running to slow in fullscreen mode, try selecting a smaller fullscreen display mode. <br />
<br />
b) Canvas Stretch [second tab]<br />
<br />
This option lets you trade resolution [crispness] for speed. If MilkDrop runs too slow, in any mode (windowed/fullscreen/desktop), try cranking up the canvas stretch to, say, 1.5X or 2X. The image will not look as crisp, but MilkDrop will probably run much faster. (Assuming that your graphics chip was the bottleneck.)<br />
<br />
c) Mesh Size [second tab]<br />
<br />
This is the main option that affects how much processor (CPU) MilkDrop uses. If you crank it up far beyond the default, expect to be CPU-bound (where your framerate drops because the CPU is the bottleneck). To get MilkDrop to speed up, drop the Mesh Size back down. The Mesh Size decides how many points on the screen the per-vertex equations will be executed for; the higher the mesh size, the more fidelity you will see in the motion. <br />
<br />
d) Tips for LCD and laptop users<br />
<br />
LCD screens: Note that most LCD screens (flatpanels) usually run at a fixed frequency only - usually 60 Hz - meaning that they update the screen 60 times per second. However, sometimes the video driver reports that it supports other refresh rates, such as 72, 75, 85, etc. It is strongly recommended that [for fullscreen mode, and for Windows in general] you choose a display mode with a 60 Hz refresh rate, for the smoothest possible animation. For this plugin, you will also want to choose Maximum Framerates that divide evenly into 60 - such as 60, 30, 20, 15, 12, 10, 6, 5, and so on - so that the # of times the LCD shows each frame of animation remains constant, resulting in the smoothest possible animation.<br />
<br />
e) color (bit) depth: 16 or 32?<br />
<br />
The answer, nowadays, is a resounding "32". Video memory is plentiful these days; use 32 bit color, for both your windows desktop (...so that MilkDrop's windowed mode can run at 32 bits) and for MilkDrop's Fullscreen Display Mode setting (where "8888" denotes 32 bits). Some ancient video cards don't have enough memory to run MilkDrop properly (or smoothly) in 32 bits, though; you might want to try 16-bit color if your card has less than 32 MB of video memory, if you are using a laptop, or if your video card is significantly old. In the MilkDrop config panel, 16-bit modes show up as "555" or "565".<br />
<br />
If you find that your card runs best in 32-bit color, you should have no problems with brightness levels while running MilkDrop. However, if your card runs best in 16-bit color, you should then adjust the Brightness slider on the second tab of the config panel (which only affects 16-bit color video modes!). The goal is to make the image as bright as possible, without oversaturating it (washing it out, often to bright pink or white). This setting also varies for different cards, depending on how the card rounds color values, so we recommend seeing how bright you can set the slider closer to '0') without oversaturating the image. Usually,a setting of '0' or '2' works the best.<br />
<br />
===Usage===<br />
<br />
'''4.a. Keyboard Commands'''<br />
<br />
The following keys can be used to control MilkDrop while it is running.<br />
(Note: pressing F1 while MilkDrop is running will show you this list)<br />
<br />
GENERAL<br />
escape: exit to winamp<br />
<br />
PRESET LOADING<br />
BACKSPACE: return to previous preset<br />
SPACE: transition to next preset<br />
H: instant Hard cut (to next preset)<br />
R: toggle random (vs. sequential) preset traversal<br />
L: load a specific preset (invokes the 'Load' menu)<br />
+/-: rate current preset (better/worse)<br />
scroll lock: lock/unlock current preset <br />
(keyboard light on means preset is locked)<br />
(prevents random switch to new preset)<br />
A: aggregate preset - loads a random preset,<br />
steals the warp shader from a different random preset,<br />
and steals the composite shader from a third random preset.<br />
D: cycle between various lock-states for the warp and<br />
composite shaders. When one of these shaders is locked,<br />
loading a new preset will load everything *except* the<br />
locked shaders, creating a mix between the two presets.<br />
<br />
PRESET EDITING AND SAVING<br />
M: show/hide the preset-editing menu<br />
S: save new preset (asks you for the new filename)<br />
N: show per-frame variable moNitor<br />
(see [[MilkDrop Preset Authoring]])<br />
<br />
MUSIC PLAYBACK<br />
z/x/c/v/b: navigate playlist (prev/play/pause/stop/next)<br />
U: toggle shuffle<br />
P: show playlist<br />
up/down arrows: volume up/down<br />
left/right arrows: rewind/ffwd 5 seconds<br />
SHIFT + left/right arrows: rewind/ffwd 30 seconds<br />
<br />
FUNCTION KEYS <br />
F1: show help screen<br />
F2: show song title<br />
F3: show song length<br />
F4: show preset name<br />
F5: show fps (frames per second)<br />
F6: show rating of current preset<br />
F7: re-read custom message file (milk_msg.ini) from disk<br />
F8: jump to new directory (for presets)<br />
F9: toggle stereo 3D on/off<br />
<br />
SPRITES AND CUSTOM MESSAGES (FOR VJ's)<br />
T: launch song title animation<br />
Y: enter custom message mode<br />
##: load message ## (where ## is a 2-digit numeric code (00-99) <br />
of a message defined in milk_msg.ini)<br />
*: clear any digits entered.<br />
DELETE: clear message (if visible)<br />
F7: re-read milk_msg.ini from disk<br />
K: enter sprite mode<br />
##: load sprite ## (where ## is a 2-digit numeric code (00-99) <br />
of a sprite defined in milk_img.ini)<br />
*: clear any digits entered.<br />
DELETE: clear newest sprite <br />
SHIFT + DELETE: clear oldest sprite<br />
CTRL+SHIFT+DELETE: clear all sprites<br />
F7: no effect (milk_img.ini is never cached)<br />
SHIFT + K: enter sprite kill mode<br />
##: clear all sprites with code ##<br />
*: clear any digits entered.<br />
CTRL + T/Y: kill song title and/or any custom messages<br />
CTRL + K: kill all sprites<br />
<br />
Note that there are more keys available, but because many<br />
are only relevant to people designing their own presets, <br />
they are listed in the preset authoring guide instead.<br />
<br />
'''4.b. config panel'''<br />
<br />
The configuration panel lets you customize the way MilkDrop runs.<br />
To learn how to get to the configuration panel, see the "Installation"<br />
section above.<br />
<br />
Once you're in the config panel, you'll see a number of tabs<br />
at the top, some dropdown boxes, and some checkboxes. Each<br />
of the tabs at the top brings you to a different page of <br />
configuration options. To get help on a setting, simply click<br />
on the '?' in the upper-right corner of the config panel, <br />
and then click on the setting you want help with.<br />
<br />
'''4.c. preset authoring'''<br />
<br />
Please check the [[MilkDrop Preset Authoring]] guide for instructions on how to create and save your own presets.<br />
<br />
'''4.d. rating system'''<br />
<br />
The built-in rating system allows you to rate each preset on a scale <br />
from 0 to 5. A rating of 5 is very good, while a rating of 0 is<br />
the worst. The ratings decide how often the presets will be randomly<br />
loaded. If a preset has a rating of 0, it will never be randomly<br />
loaded (unless they're all zero; then they all have an equal chance).<br />
<br />
To show the rating for a preset, press F6. You can adjust the <br />
rating for a preset with the +/- keys. When you make adjustments,<br />
they save automatically; there's no need to save the preset to make<br />
the rating change permanent.<br />
<br />
Here's a recommended interpretation of the numeric values:<br />
0 = I never want to see this preset again<br />
1 = very ugly<br />
2 = mediocre<br />
3 = fair<br />
4 = good<br />
5 = downright stimulating<br />
<br />
If a preset seems "lost" because you set its rating to 0 and it<br />
won't ever come back, you can always load it up by hitting 'L'<br />
to conjure the 'Load Preset' menu, finding the preset you want,<br />
loading it, then hitting +.<br />
<br />
'''4.e. custom messages'''<br />
<br />
ABOUT CUSTOM MESSAGES:<br />
The "Custom Message" feature of MilkDrop allows you to display<br />
short text messages on the screen while MilkDrop is running.<br />
They are highly configurable; you can set all of the following<br />
parameters: the font, the size, the positioning, color, bold <br />
state, italic state, and so on; and you can even have it <br />
randomize some of these properties.<br />
<br />
CREATING THE MESSAGES:<br />
You can save up to 100 messages in the file MILK_MSG.INI in<br />
your Winamp\Plugins\ folder. To open this file, go to the <br />
MilkDrop configuration screen (ALT+K from Winamp) and click the<br />
"Edit Custom Messages" button. Or, you can just edit it <br />
manually if you know how; it's plain-text.<br />
<br />
The first thing you see when you open the file is a bunch of<br />
lines that start with two forward slashes (//). These are<br />
comment lines, and they explain the syntax for adding a font<br />
or a message to the file. This is your main reference for<br />
finding out what all the parameters do for the fonts & messages;<br />
it is recommended that you leave this information in the file,<br />
although it can be removed or (modified) and the messages will<br />
still work.<br />
<br />
After the comments come first the fonts, then the messages.<br />
The fonts are simply a way to specify a typeface, bold state,<br />
italics state, and red/green/blue color for the font. You can <br />
configure up to 16 fonts like this (numbered 00-15). These fonts<br />
will serve as template fonts for the custom messages.<br />
<br />
The next section is the actual messages. Each one has a<br />
text message (the 'text' parameter) that will be shown to the<br />
user, and each one references one of the 16 fonts that were<br />
defined in the previous section. You can also specify the<br />
size (size), position (x,y), a growth factor (growth) that<br />
will grow/shrink the message over its lifetime, the number<br />
of seconds to show the message (time), and the fraction of that<br />
time that is spent fading in (fade). <br />
<br />
You can also randomize some of these values: 'randx' and 'randy'<br />
will randomly perturb the (x,y) coordinates every time the message<br />
is shown to the user, and 'randr'/'randg'/'randb' will randomly<br />
perturb the (r,g,b) color in the same way.<br />
<br />
Finally, you can override any of the default properties for the<br />
font that this message uses: (face, bold, ital, r, g, b).<br />
<br />
INVOCATION AND USAGE:<br />
There are two ways to invoke custom messages: one automatic,<br />
the other manual. <br />
<br />
The automatic way is to go to the MilkDrop config panel (ALT+K),<br />
click the 'More Options' button, and set the value in the<br />
'Time between RANDOM custom messages' box to something greater<br />
than zero. This will cause MilkDrop to randomly display custom <br />
messages while it is running, and the average time (in seconds) <br />
between messages will be the value you entered here. If you <br />
wish to disable random custom messages, set this value to -1<br />
(or any negative number). Note that all messages in the file<br />
have an equal change of being picked.<br />
<br />
The manual way is to type in the two-digit code (00-99) of the <br />
message while MilkDrop is running. However, you can't use the <br />
numeric keypad for this - you have to use the numbers at the <br />
TOP of your keyboard to do it. If you mess up while entering<br />
the first digit, just press the '*' key to start over.<br />
<br />
Note that if you change the MILK_MSG.INI file while MilkDrop<br />
is running, you will not be able to see the changes until<br />
you hit F7, which tells MilkDrop to re-read the MILK_MSG.INI <br />
file from disk.<br />
<br />
<br />
'''4.f. sprites'''<br />
<br />
ABOUT SPRITES:<br />
The "Sprite" feature of MilkDrop allows you to display any image of your choice in the foreground (on top of MilkDrop) while it runs. The sprites can fade in and out, move around, respond to the music, and so on. You define them in a file - milk_img.ini in your winamp\plugins directory - much like you define custom messages, each having an identifying code number from 00 through 99 (used to invoke them). However, the way the individual sprites are defined is different; you write code for them, instead of just setting parameter values. This is a little bit tougher to do (it's very much like preset authoring), but adds a great deal of flexibility to what you can do with the sprites.<br />
<br />
CREATING THE SPRITES:<br />
<br />
You can define up to 100 sprites in the file MILK_IMG.INI in your Winamp\Plugins\ folder. To open this file, go to the MilkDrop configuration screen (ALT+K from Winamp) and click the "Edit Sprites" button. Or, you can just edit it manually if you know how; it's plain-text.<br />
<br />
The first thing you see when you open the file is a bunch of lines that start with two forward slashes (//). These are comment lines, and they explain the syntax for creating a sprite. This is your main reference for finding out what all the parameters do for the fonts & messages; it is recommended that you leave this information in the file, although it can be removed (or modified) and the sprites will still work.<br />
<br />
After the comments come the sprite definitions. Each sprite is made up of one parameter that indicates the image file to use (this is the 'img=...' line), and two types of code: initialization code, and regular code. <br />
<br />
The first - initialization code - is executed only once, when you launch the sprite. Use it to do one-time initialization of variables (such as the opacity (a), rotation angle (rot), position (x,y), and so on) or to invent new variables that you will access later. This code is marked by the 'init_1=...', 'init_2=...', etc. lines. The second type of code - marked by 'code_1=...', 'code_2=...', etc. is executed every frame, just prior to plastering the sprite on the screen. Use it to animate the sprite, moving it around (changing x,y), scaling it up and down (sx,sy), fading it in and out (a), changing its color, and so on.<br />
<br />
Please see the comments included in the sample milk_img.ini file<br />
for full details and examples on how to author sprites.<br />
<br />
INVOCATION AND USAGE:<br />
There is currently only one way to invoke sprites: manually. To do this, first press 'K' to enter 'sprite mode' (while running MilkDrop). Now, whenever you type in a two-digit code (00-99), MilkDrop will try to find & launch the sprite you've requested, from the milk_img.ini file. If there is an error, it will display an error message in the upper-right corner. Note that to enter the two-digit code, you can't use the numeric keypad; you have to use the numbers at the TOP of your keyboard. <br />
<br />
If you make an error entering the first digit of the code, just press '*' to start over. If you want to clear the most recently-invoked sprite, press DELETE. If you want to clear the oldest sprite, press SHIFT + DELETE. If you want to clear all sprites, press SHIFT + CTRL + DELETE.<br />
<br />
If you want to clear sprites by their 2-digit code, press SHIFT + K (instead of just 'K') to enter 'sprite kill mode.' Now, when you enter a two-digit code, instead of invoking the sprite, MilkDrop clears all running sprites with that two-digit code.<br />
<br />
===Trouble Shooting===<br />
<br />
If MilkDrop has a critical problem (e.g. fails to load, freezes, etc.)or if the image is distorted, torn, corrupted, or all one solid color, try the following two suggestions to resolve the problem. In 90% of these cases it can be fixed. If you have a different problem, scroll down past this part and try to find the appropriate symptom and its solution.<br />
<br />
====1. UPDATE YOUR VIDEO DRIVER, OR TRY OTHER DRIVERS====<br />
<br />
Almost all display problems are caused by buggy video drivers! A "driver" is a piece of software that translates graphics-related commands from programs, like MilkDrop, into the native language of your specific graphics hardware.<br />
<br />
For desktop machines, there are typically three sources for video drivers: <br />
# those from the *chip* manufacturer's website (usually nvidia.com or ati.com) (best source) <br />
# those from the card manufacturer's website (LeadTEK, PNY, etc.)<br />
# those that shipped with Windows (yuck)<br />
<br />
For laptops:<br />
# the driver from the *laptop* manufacturer<br />
# (maybe) the driver from the graphics chip manufacturer (ATI, Nvidia, etc) - however, it's fairly common to find that the laptop requires a custom driver written by the laptop manufacturer.<br />
# the driver that shipped with Windows (yuck)<br />
<br />
Give them all a shot. Track down every driver you can find for your card, and try it. Try the WHQL ones first - these versions of the drivers have passed "Windows Hardware Quality Labs" certification and are usually the more stable and reliable ones. In general, it's a very good idea to use only Microsoft-certified WHQL drivers for your video card. Often people want to get the newest, fastest beta drivers, but these drivers are almost ALWAYS riddled with new bugs. You can also watch the version number of the drivers a company releases - if the version number just jumped to a new series such as from the 70's to the 80's), watch out, it probably has a lot of bugs that need worked out - give it 3-4 months before expecting the new driver series to work well. With video drivers, the newest isn't always the best!<br />
<br />
Here is a list of some common card/chip manufacturers and where to get their drivers. Don't forget to choose the WHQL driver!<br />
<br />
[http://www.nvidia.com/page/drivers.html NVIDIA driver]<br />
Card manufacturers using NVIDIA (GeForce) graphics chips:<br />
(note - most of these just link you to the nvidia driver above)<br />
[http://www.xfxforce.com/web/support/showSearchDriversProductCode.jspa XFX]<br />
[http://www.evga.com/support/drivers EVGA]<br />
[http://www.bfgtech.com/driverdownload.aspx BFG]<br />
[http://www2.pny.com/support/support.aspx PNY] <br />
[http://ati.amd.com/support/driver.html ATI driver] <br />
Card manufacturers using ATI (Radeon) graphics chips:<br />
[http://www.visiontek.com/teksupport/drivers/drivers.html VisionTek] <br />
[http://www.dmmdownload.com/current.php Diamond] <br />
[http://downloadcenter.intel.com Intel] - then click 'graphics' on the left<br />
[http://www.sis.com/download SiS] - agree, then select 'graphics drivers'<br />
[http://www.s3graphics.com S3] - then click 'drivers'<br />
[http://www.via.com.tw/en/products/graphics VIA] <br />
[http://www.matrox.com/graphics/en/corpo/support/drivers/home.php Matrox]<br />
[http://www.creative.com/language.asp?sDestUrl=/support/downloads Creative Labs]<br />
<br />
<br />
For others - or in general - if your graphics chip is made by Trident, for example, then try a [http://www.google.com/ google] search for:<br />
<br />
Trident graphics driver<br />
<br />
Then click on "support", then "drivers" (or "downloads"), then "graphics driver", and so on.<br />
<br />
====2. [RE]INSTALL DIRECTX====<br />
<br />
Make sure you have a quasi-recent version of Microsoft DirectX installed. In reality, though, almost every PC in the world has DirectX 9 on it at this point, so this shouldn't be a problem. If you go to download it, you'll only be able to find DirectX 10 - this is fine to install, though, as it includes DirectX 9 inside it. As a last resort, though, if you are having problems, you could try re-installing DirectX to see if it helps.<br />
<br />
If you're having a non-critical problem, browse the following list of common problems and their causes and solutions. Note that for each symptom- cause-solution block, there can be multiple symptoms with the same cause and solution, and the same symptom might be listed in multiple blocks.<br />
<br />
If the solutions below don't work for you, please visit the forums at http://forums.winamp.com/forumdisplay.php?forumid=84, where you can read the most recent troubleshooting issues and solutions.<br />
<br />
<br />
ENTRY 1<br />
SYMPTOM:<br />
-any error message saying "Failed to create ..." <br />
or "not enough memory...", or<br />
-only a portion of the screen displays correctly; the rest is <br />
either filled with garbage or badly flickering<br />
CAUSE:<br />
1) Your video card might not have enough memory to run MilkDrop at <br />
the resolution (screen width and height) you've picked, <br />
2) your drivers might be out of date, <br />
3) you might need to reinstall DirectX (very very rare), or<br />
4) your graphics card might be to crappy to *actually* run<br />
pixel shaders well.<br />
SOLUTION: <br />
1) To battle video memory problems:<br />
<br />
Go to the config panel and try smaller video modes (e.g.,<br />
320x240 is smaller than 640x480). Even better is to try<br />
a lower color bit depth; if you'd selected a 32-bit ("8888") <br />
video mode before, try a 16- ("565" or "555") or 24-bit ("888") <br />
one, for example. Note that it might only work in one of them; <br />
so make sure you try them all. Trying these things is especially <br />
important on laptops with limited video memory, or older video <br />
cards with a small amount of video memory.<br />
<br />
Finally, you can try locking the texture size (or "canvas size") <br />
to 256x256 pixels, just to see if that fixes the problem. <br />
If it does, try using a smaller fullscreen video mode to<br />
free up some memory, or if running windowed, close other<br />
graphics-hungry applications.<br />
<br />
2,3) for instructions on how to reinstall DirectX or update <br />
drivers, go here.<br />
<br />
4) Go to the MilkDrop config panel (hit ALT+K) and on the second tab, <br />
in the "Pixel Shaders" box, select "None." Now does MilkDrop run <br />
ok? If so, your video card probably just can't reliably run<br />
pixel shaders, due to either inferior hardware, or it could<br />
be the driver. You can always try setting "Pixel Shaders" <br />
back to "Auto" and then installing a newer (preferably WHQL) <br />
video driver.<br />
<br />
<br />
ENTRY 2<br />
SYMPTOM:<br />
-When I go to the Load Preset menu ('L') in MilkDrop, some of the<br />
presets on disk are missing.<br />
-I downloaded some new presets and put them in my Plugins\MilkDrop2\Presets<br />
directory, but I can't access them from within MilkDrop.<br />
CAUSE:<br />
You probably have an older video card that can't handle the pixel<br />
shaders needed to run some of the presets. MilkDrop automatically<br />
hides any presets from you that you can't run.<br />
SOLUTION:<br />
* You could b uy a new graphics card - one that meets the minimum<br />
recommendation for MilkDrop 2. These cost less than $40.<br />
* You could try forcing MilkDrop to try to run these presets.<br />
Sometimes MilkDrop just hides them from you because it predicts<br />
they will run horribly slow on your graphics card; in case it<br />
is wrong about that, try this. Go into the MilkDrop config<br />
panel (ALT+K) and go to the More Settings tab. Under the <br />
"Pixel Shaders" option, change it from "Auto" to "Shader Model 2"<br />
or "Shader Model 3". Then try to run MilkDrop and see if the<br />
presets appear. If they do, you're in luck; if they don't, your<br />
GPU really doesn't support those shader models.<br />
<br />
<br />
ENTRY 3<br />
SYMPTOM:<br />
MilkDrop always looks the same - it's always showing the same<br />
preset, and it never changes to a new preset unless I tell it to.<br />
CAUSE:<br />
Scroll Lock is on.<br />
SOLUTION:<br />
The Scroll Lock key is how you tell MilkDrop to lock the current<br />
preset - i.e. don't randomly transition to a new preset unless you <br />
do it. The state of the Scroll Lock key is remembered when you<br />
start or stop MilkDrop, too, so be careful of that. If you are<br />
experiencing this problem, you can fix it in any of the following<br />
three ways:<br />
1. hit Scroll Lock while MilkDrop is running (and the viz window is active);<br />
2. load up the MilkDrop config panel (ALT+K), go to the More Settings<br />
tab, and uncheck the "Start milkdrop with preset lock (scroll lock) <br />
key ON" box;<br />
3. if you're using a modern skin, there is a "random" button on<br />
the frame of the window, which is the inverse of the Scroll Lock<br />
state - i.e. you probably have Scroll Lock on and "random" off.<br />
Click the "Random" button to turn random transitions back on<br />
(and notice that scroll lock gets turned off as a result).<br />
<br />
ENTRY 4<br />
SYMPTOM:<br />
I was browsing for presets from within MilkDrop ('L') key and <br />
got lost. How do I get back to my presets?<br />
SOLUTION: <br />
Two ways to fix this. The easiest is to just reset MilkDrop<br />
to its defaults - hit ALT+K to load the MilkDrop config panel,<br />
then click the 'Defaults' button. The next time you launch<br />
MilkDrop, it will start you in the default preset directory.<br />
<br />
To fix it manually (and preserve all your settings), run<br />
MilkDrop, hit F8, and paste in this path:<br />
C:\Program Files\Winamp\Plugins\Milkdrop2\presets<br />
[or equivalent].<br />
<br />
Another way to fix it is to hit 'L', and browse all the way <br />
down to the root folder (repeatedly select ".."), then<br />
go into Program Files, Winamp, Plugins, MilkDrop2, and finally,<br />
presets.<br />
<br />
ENTRY 5<br />
SYMPTOM:<br />
-things flicker through (such as my AIM window ticker, taskbar<br />
clock, web page animations, etc.) when I'm running MilkDrop<br />
in fullscreen mode.<br />
CAUSE:<br />
You're probably running MilkDrop fullscreen at the same<br />
resolution & color depth as your desktop, and Windows isn't <br />
properly handling MilkDrop's request for exclusive access to the<br />
screen, and is still letting other applications paint (draw)<br />
themselves.<br />
SOLUTION:<br />
Change either your Windows desktop resolution or color depth, or <br />
MilkDrop's fullscreen resolution or color depth, so that there<br />
is some difference between the two. (To change your Windows <br />
display settings, go to the Start Menu -> Settings -> Control <br />
Panel -> Display -> Settings tab, and then change the "colors" <br />
or "screen area" settings from there.) Also make sure you're<br />
not using "fake" fullscreen mode (...uncheck this box on the<br />
main screen of the config panel).<br />
<br />
===Known Issues / Misc. / Tips:===<br />
<br />
a. Tip for video capture: if you'd like to save sequences of video <br />
from this plugin, there are several programs out there that will <br />
let you do this. Warning: you will need a ton of free hard drive <br />
space, and a fast CPU helps. A few of these programs are:<br />
"FRAPS" http://www.fraps.com/<br />
"Hypercam" http://www.hyperionics.com<br />
<br />
b. Close other apps:<br />
For the best graphics performance, try to close as many other <br />
applications as you can, before running the plugin, especially <br />
those that tend to work in the background, such as anti-virus <br />
or file-swapping software. Also, if you must leave other <br />
applications open, try to minimize them (i.e. shrink the window <br />
down to the taskbar) so that they stay out of the painting loop.<br />
<br />
c. Windows Vista / Winamp with per-user settings<br />
Be aware that if you're running Vista as a non-admin user,<br />
you can't write to (or delete from) files in the Program Files<br />
directory, which is were MilkDrop 2 is installed. So, anything<br />
you try to write or save (like milkdrop's settings file, milk2.ini; <br />
or presets) will probably end up deep in some user-specific, <br />
virtualized "Program Files" directory somewhere on your hard <br />
drive. Yell at Microsoft for this one!<br />
<br />
Also, if you installed Winamp with per-user settings (instead of <br />
shared settings) - on any OS, not just Vista - be aware that your<br />
.INI files (milk2.ini, milk2_img.ini, milk2_cfg.ini) are all<br />
stored in a folder like this:<br />
<br />
C:\Documents and Settings\\Application Data\Winamp\Plugins <br />
<br />
(Note that 'Application Data' is a hidden folder.) However,<br />
presets, textures, and things like that are all shared between<br />
users, in the real [c:\Program Files]\winamp\plugins\milkdrop2 folder. <br />
If you want to keep your presets separate, you can still do that, <br />
though - just put them in a personal folder, and then seek to it<br />
from within MilkDrop. If you're using per-user settings in Winamp,<br />
it will remember which folder you last used.<br />
<br />
<br />
<br />
===Using Line-In===<br />
-----------------------<br />
If you want to use your sound card's Line-In or CD Audio inputs for<br />
sound data (instead of mp3 files), you can do this. Do the following:<br />
1. CONNECT WIRES<br />
Connect your audio source (a stereo, a live feed, whatever) into<br />
the line-in (or microphone) 1/8" jack on your sound card. You<br />
might want to test & verify that your cable is good before doing <br />
this.<br />
2. SELECT SOUND INPUT CHANNEL & ADJUST VOLUME<br />
In Windows, double-click the speaker icon in your systray (where<br />
the clock is). Then, on the menu, go to Options -> Properties<br />
and select the "Recording" option. Then make sure the Line In<br />
(or Microphone) input channel (whichever is appropriate for<br />
your case) is SELECTED (with a check mark) and that the volume <br />
is close to, or at, the maximum. Hit OK. <br />
3. TELL WINAMP TO USE LINE-IN<br />
Open Winamp, and hit CTRL+L (the "Open Location" hotkey). Now<br />
type in "linein://" as the location you want to open. (Leave out<br />
the quotes and make sure you use FORWARD slashes.) Hit PLAY<br />
('x' key for the lazy), and the little built-in oscilloscope (or <br />
spectrum analyzer) in Winamp should start showing your signal.<br />
4. RUN MILKDROP<br />
Run MilkDrop as usual. If the waves are too small or large, <br />
either adjust the volume from Windows' Volume Control, or adjust<br />
the sound level at the source. <br />
<br />
If you are doing shows using live audio, and if you have a multiple monitor<br />
setup, you might also want to use the "VJ mode" feature, which lets you <br />
control MilkDrop (even editing shaders on the fly, etc.) via a separate monitor.</div>Culixhttp://wiki.shoutcast.com/wiki/SHOUTcast_BroadcasterSHOUTcast Broadcaster2010-11-30T03:32:01Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Friskygeek</p>
<hr />
<div>{{Template:NavBar}}<br />
= SHOUTcast Server and YP Documentation =<br />
<br />
== SHOUTcast YP1.0 Protocol ==<br />
<br />
==== Overview ====<br />
The YP protocol provides a way for shoutcast servers and relays to register themselves so they are searchable on the shoutcast.com web page and directory. The API is a collection of HTTP GET requests, which provide the necessary functionality.<br />
<br />
=== Functions ===<br />
==== addsrv ==== <br />
Adds a new server to the database. Servers should make this call when they start up.<br />
<br />
''' Parameters '''<br />
<br />
* v version. Should be set to one.<br />
* br bitrate. Bitrate in kbs<br />
* p IP port for client connections<br />
* m maximum client connections <br />
* r This parameter is only provided if this server is relaying another server. If so, the value is <addr>:<port> of the relayed server.<br />
* t Name or title of stream<br />
* g Station genre<br />
* url URL of broadcaster<br />
* content Mime-type for content (audio/mpeg or audio/aacp)<br />
* irc IRC address of broadcaster<br />
* icq ICQ address of broadcaster<br />
* aim AIM id of broadcaster<br />
* sid Stream id if relevant<br />
<br />
An HTTP response of 200 indicates the possibility of success. Further information is available in the response headers.<br />
* icy-response Will have the value 'ack' if successful, otherwise it will contain an error message.<br />
* icy-id ID assigned to the server. Value should be checked for zero, which is invalid.<br />
* icy-error Extended error information.<br />
* icy-tchfrq Touch frequency in minutes. The server should call the YP function tchsrv at this interval.<br />
<br />
<br />
==== remsrv ==== <br />
Removes a server from the database. Servers should make this call when they shut down.<br />
<br />
''' Parameters '''<br />
*id ID provided in response to addsrv function<br />
* p IP port for client connections<br />
<br />
An HTTP response of 200 indicates the possibility of success. Further information is available in the response headers.<br />
<br />
* icy-response Will have the value 'ack' if successful, otherwise it will contain an error message<br />
* icy-error Extended error information<br />
<br />
<br />
==== tchsrv ==== <br />
Periodic "touch" function that updates various information about the server. This function should be called at an interval as indicated by the icy-tchfrq response field to '''addsrv'''<br />
<br />
''' Parameters '''<br />
* id Server ID as provided by the addsrv function<br />
* p IP port for client connections<br />
* li Number of listeners currently connected.<br />
* alt Average user listen time in seconds<br />
* ct Current song title<br />
* cm Number of clients connected more than 5 minutes since last tchsrv<br />
* ht Number of client connects since last tchsrv<br />
<br />
An HTTP response of 200 indicates the possibility of success. Further information is available in the response headers.<br />
<br />
* icy-response Will have the value 'ack' if succesful, otherwise it will contain an error message.<br />
* icy-error Extended error information.<br />
* icy-tchfrq New touch frequency<br />
* icy-backup If the server becomes full, clients should be redirected here.<br />
<br />
<br />
<br />
=== YP1 Error List ===<br />
<br />
# Unable to check stream connection - Cannot see your station/computer (URL: "+streamUrl+") from the Internet, disable Internet Sharing/NAT/firewall/ISP cache. <br />
# If we find ‘Location:’ string in the stream content - Terms of Service violator. You are being reported. <br />
# If we find ‘SlamCast’ string in the stream content - Incompatible protocol. <br />
# If we find ‘HTTP/1.0 401 Unauthorized’ string in the stream content - Streams requiring authorization are not public and cannot list here. <br />
# If we found ‘ICY 400 Server Full’ or ‘HTTP/1.0 400 Server Full’ string in the stream content - Cannot verify server since all listener slots are full. Please wait. <br />
# If we found ‘icecast’ string in the stream content - Icecast too easy to hack YP, use SHOUTcast instead. <br />
# IP ban - This network has been permanently banned due to a previous violation of the SHOUTcast directory terms of service. <br />
# If website contains ‘hTtP’ - We no longer list stations utilizing the auto-popup url option <br />
# Improper version - Upgrade to SHOUTcast 1.8 or newer. <br />
# No station name validation - Please give your station a name (in the dsp plugin YP tab). <br />
# No Genre - Please identify this station's genre (in the dsp plugin YP tab). <br />
# Capacity 0 - You must have at least 1 maxuser. <br />
# Improper bitrate - Invalid bitrate. <br />
# Port cannot be zero. <br />
# If station name contains either ‘mp3pro’ or ‘mp3 pro’ - Mp3pro format must be nsv-encapsulated to list here. <br />
# Content type - We do not currently list servers not streaming AAC+, MP3, or NSV. <br />
# Video streams must be at least 64kbps to list here. <br />
# If bitrate > 1024 - Bitrate too large. <br />
# If bitrate < 8 - Bitrate too small. <br />
# touch host, id, port, listeners, alt validation error – 3 <br />
# listeners > 5000, host not set in the request – 99 <br />
# if touch filed to update DB – 100 if update count is 0, else 100 + count of updated records.<br />
# If primary is not public or relay could not register for some reason - Relay url could not register. Try by making primary source public or wait till primary registers.<br />
<br />
<br />
== SHOUTcast / Ultravox 2.1 Protocol ==<br />
==== Overview ====<br />
The SHOUTcast / Ultravox Protocol is an application level streaming protocol that encapsulates stream data in order to abstract the underlying data encoding. The protocol defines the structure of the encapsulation as well as the series of handshakes necessary for setting up a streaming session. It describes the handshaking necessary between the broadcaster and the distribution point as well as the handshaking necessary between the listener and the distribution point. At this time the protocol is not codec dependent, nor is it transport dependent. The protocol is designed with network performance, compatibility, and simplicity in mind. <br />
<br />
At a high level, the broadcaster opens a connection to the distribution point. It provides authentication information and stream details to the distribution point. The distribution point parses the provided information, authenticates the user and then either sets up for streaming the broadcast feed, or denies the broadcaster access. Similarly, a listener may connect to the distribution point, provide authentication information, and request a particular stream. The distribution point will either allow or deny the listener and if allowed will start sending stream data to the listener from it’s internal stream buffer. Recommendations for features of the distribution point buffering scheme and connection handling are also mentioned here, but are an implementation detail and the protocol may lend itself for better solutions based on the streaming architecture.<br />
<br />
==== Ultravox Messages ====<br />
The mechanism by which Ultravox is able to abstract the underlying stream encoding is encapsulation within a simple message structure. Once a broadcaster or listener is connected to the distribution point, Ultravox messages will be the sole communication mechanism.<br />
<br />
The basic Ultravox message format is:<br />
<br />
0 1 2 3 4 5 <br />
0101 1010 AAAA BBBB CCCC DDDD DDDD DDDD EEEE EEEE EEEE EEEE F…………...F 0000 0000<br />
Sync Res QoS Class Type PayLoad Length Payload 0x00<br />
<br />
[Sync byte5A][reserved/QoS][4 bit msg class][12 bit msg type][16 bit msg length][N byte payload][0x00 byte]<br />
<br />
Note: All values of the message are network byte order.<br />
<br />
Sync Byte (0x5A)<br />
<br />
:The sync byte is used to distinguish the beginning of an ultravox message. It allows the listener to seek to a potential valid frame if data gets corrupted between the distribution point and the listener.<br />
<br />
Reserved (A)<br />
QoS (B)<br />
<br />
:QoS information may be passed in the low 4 bits of the reserve byte. The QoS is a four bit value whose high bit specifies whether this packet has to be delivered (useful for UDP). The other 3 bits are the relative priority for send queue. The high 4 bits are currently unused.<br />
<br />
Message Class (C)<br />
<br />
:The message class is used in combination with the message type to uniquely identify an Ultravox message. The reason for separating the unique identifier into two units is for performance reasons. The message classes are defined so that the distribution point can look at the message class and decide whether it needs to examine the payload. Examining the payload requires extra parsing on the part of the distribution point and so will affect the performance when we talk about heavy load. The message classes are defined as:<br />
<br />
{| class="wikitable"<br />
|-<br />
! <br />
! class<br />
! description<br />
|-<br />
| 0x0<br />
| Operations<br />
| Not Defined<br />
|-<br />
| 0x1<br />
| Broadcaster<br />
| BroadcasterDistribution point<br />
|-<br />
| 0x2<br />
| Listener<br />
| Distribution pointListener<br />
|-<br />
| 0x3<br />
| Cacheable Metadata<br />
| BroadcasterListener via distribution point<br />
|-<br />
| 0x4<br />
| Cacheable Metadata<br />
| BroadcasterListener via distribution point<br />
|-<br />
| 0x5<br />
| Pass-through Metadata<br />
| BroadcasterListener via distribution point<br />
|-<br />
| 0x6<br />
| Pass-through Metadata<br />
| BroadcasterListener via distribution point<br />
|-<br />
| 0x7<br />
| Data<br />
| Encoded data (ex: 0x7000 is MP3)<br />
|-<br />
| 0x8<br />
| Data<br />
| Encoded data (ex: 0x8003 is aac/aacplus, 0x8001 is ogg vorbis, 0x7777 is nsv)<br />
|}<br />
<br />
<br />
Message Type (D)<br />
<br />
:The message type is 12 bits in the message header that specify the type of data encapsulated in the message. See Table 1 for details on specific message types.<br />
<br />
Message Length (E)<br />
<br />
:The message length is the fifth and the sixth byte of the message header. It specifies the length of the payload following the message header.<br />
Note: The message length does not include the trailer 0x00 byte.<br />
<br />
Payload (F)<br />
<br />
:The payload contains the data for each message. The payload size is not restricted by the protocol. However, the protocol specifies how a broadcaster, distribution point, and listener need to negotiate and report the maximum size message that will be sent in a single datastream. Some implementations may require that the messages stay under MTU, in which case the distribution point could enforce this during max-payload-size negotiation.<br />
<br />
Trailing 0x00<br />
<br />
:The trailing 0x00 in the payload is used by the listener to determine if a message is malformed. See the Stream Syncing section to learn about how a client finds their place in the datastream if corrupted messages are encountered.<br />
<br />
==== Broadcast Messages ====<br />
<br />
The broadcast protocol describes the message requests from the broadcaster to the distribution point and responses by the distribution point. The messages are used to authenticate the broadcaster, deliver details about the stream to be broadcasted, manage the stream, and terminate the stream.<br />
For most requests made by a broadcaster, the distribution point normally sends the same message class and type back to the broadcaster as a response, indicating success or failure of the request in the encapsulated payload.<br />
<br />
The message types shown below require a payload formatted according to the following criteria:<br />
# The existence of payload data is indicated by a message length > 0<br />
# All payloads for broadcaster messages are ASCIIZ strings (i.e., ASCII-encoded and terminated by a ‘\0’). <br />
# Parameters within the payload are separated by a single colon (“:”) character<br />
<br />
Broadcast messages are defined as:<br />
<br />
Class<br />
Type<br />
Description<br />
Required?<br />
Payload?<br />
Response?<br />
0x1<br />
0x000<br />
N/D<br />
N/A<br />
N/A<br />
N/A<br />
0x1<br />
0x001<br />
Authenticate Broadcast<br />
Yes<br />
Yes<br />
Yes<br />
0x1<br />
0x002<br />
Setup Broadcast<br />
Yes<br />
Yes<br />
Yes<br />
0x1<br />
0x003<br />
Negotiate Buffer Size<br />
Yes<br />
Yes<br />
Yes<br />
0x1<br />
0x004<br />
Standby<br />
Yes<br />
No<br />
Yes<br />
0x1<br />
0x005<br />
Terminate<br />
No<br />
No<br />
No<br />
0x1<br />
0x006<br />
Flush Cached Metadata<br />
No<br />
No<br />
No<br />
0x1<br />
0x007<br />
Require Listener Auth<br />
No<br />
Yes<br />
Yes<br />
0x1<br />
0x008<br />
Negotiate Max Payload Size<br />
Yes<br />
Yes<br />
Yes<br />
0x1<br />
0x009<br />
Request Cipher<br />
Yes<br />
No<br />
Yes<br />
0x1<br />
0x040<br />
Stream mime type<br />
Yes<br />
Yes<br />
Yes<br />
0x1<br />
0x050<br />
File transfer begin<br />
No<br />
Yes<br />
Yes<br />
0x1<br />
0x051<br />
File transfer data<br />
No<br />
Yes<br />
Yes<br />
0x1<br />
0x100<br />
Configure ICY-NAME<br />
No<br />
Yes<br />
Yes<br />
0x1<br />
0x101<br />
Configure ICYGENRE<br />
No<br />
Yes<br />
Yes<br />
0x1<br />
0x102<br />
Configure ICYURL<br />
No<br />
Yes<br />
Yes<br />
0x1<br />
0x103<br />
Configure ICYPUB<br />
No<br />
Yes<br />
Yes<br />
<br />
<br />
There are six major phases of broadcaster communication with the distribution point:<br />
# Cipher key exchange<br />
# Connect/Authentication<br />
# Stream Configuration<br />
# Intro/backup file transfer<br />
# Standby/Data transfer<br />
# Broadcast termination<br />
<br />
= SHOUTcas DNAS / SC_SERV =<br />
<br />
;1. How do I use the on-demand content features of the DNAS?<br />
:Answer: The DNAS installs with a folder called content/. Place any MP3 files inside this directory, and they're ready to be streamed on-demand. The server will even automatically generate a playlist for any individual item of content so you can have browsers automatically pass the content off to a player without having to make playlists yourself.<br />
<br />
:Example: Your server has a file called song.mp3 in the content/ folder. Your SHOUTcast Radio DNAS is running on port 8000 at my.host.com.<br />
:You can listen to my song <A HREF= "http://my.host.com:8000/content/song.pls">here</A><br />
:NOTE: The file song.pls DOES NOT EXIST in your content directory! If a file with the same name exists with the .mp3 extension, the DNAS will automatically generate the .pls file.<br />
:NOTE: Subdirectories DO NOT work for the content section, to help prevent malicious users from tramping around your filesystem.<br />
<br />
;2. Why does the SHOUTcast Radio directory think I'm at a different IP than I really am?<br />
:Answer: The SHOUTcast Radio directory used to run on the honor system. That was, it took you at your word on what IP you were broadcasting at. Since about twenty billion people abused that to send people to not-so-friendly sites, now the directory forces the listed IP to the same IP that sends it the info. Since many ISPs now use content caching on port 80 (the same port that directory data comes from), a different IP address can sometimes appear in the directory. There isn't any solution for this at the moment, save having your ISP disable forced proxying of your address.<br />
<br />
;3. I'm behind a firewall/proxy. Can I still use the DNAS to broadcast?<br />
:Answer: Tricky question. Users behind proxies cannot. Users behind NAT devices can, *provided* the same port the SHOUTcast Radio server runs on is set up to forward from the NAT device to the SHOUTcast Radio server. Users behind firewalls can also get a hole punched so listeners can penetrate. If broadcasters also need to get in from the outside world, you should open the hole for PortBase + 1 (i.e. id SHOUTcast Radio runs on 8000, 8001 should be open for broadcasters to get through as well.)<br />
<br />
= SOURCE PLUG-IN =<br />
<br />
;1. How do I use advanced mode?<br />
:Answer: Read the README that comes with the plug-in. It explains how to make things like crossfading, cd-audio, and voiceovers work. Also, there's a ScreenCam guide which will show exactly what to do.</div>Culixhttp://wiki.shoutcast.com/wiki/GlossaryGlossary2010-11-30T03:31:56Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>{{Template:NavBar}}<br />
<br />
== Glossary of Terms ==<br />
* '''Agent''' - Winamp's taskbar component. Maintains file type associations.<br />
<br />
* '''APE''' - Advanced Plug-in Effect. Third party Effect Module created for AVS.<br />
<br />
* '''AVS''' - Advanced Visualization Studio comes bundled with Winamp. Allows endless user customization.<br />
<br />
* '''Base Skin''' - The standard skin built into Winamp. Also the downloadable template used to create new skins.<br />
<br />
* '''Bookmark''' - Winamp feature that allows quick access to favorite songs or streams.<br />
<br />
* '''Codec''' - Short for coder/decoder. A software program for converting between digital data and analog signals. Winamp uses codecs to play many different kinds of audio files.<br />
<br />
* '''Developer''' - Any one who creates a skin or writes an application or plug-in for Winamp.<br />
<br />
* '''Discussion List''' - A mailing list hosted by Winamp.com to help foster the developer community.<br />
<br />
* '''DLL''' - Dynamically Linked Library. A Win32 property that allows Winamp's plug-in architecture.<br />
<br />
* '''DoubleSize Mode''' - Winamp option that doubles the width and height of the Main and Equalizer components.<br />
<br />
* '''DSP Plug-in''' - A plug-in that manipulates audio data before being sent to the speakers.<br />
<br />
* '''Easter Egg''' - A programming term used for a hidden, often humorous feature.<br />
<br />
* '''Equalizer''' - Winamp component that allows audio tweaking for optimal sound quality.<br />
<br />
* '''FAQ''' - Frequently Asked Questions.<br />
<br />
* '''Forum''' - A message board hosted by Winamp.com to help foster the Winamp community.<br />
<br />
* '''Flounder''' - Any of various marine flatfishes of the families Bothidae and Pleuronectidae, which include important food fishes.<br />
<br />
* '''General Purpose Plug-in''' - A plug-in that does not require access to audio data.<br />
<br />
* '''Input Plug-in''' - A plug-in that adds a new file type to Winamp's list of supported types.<br />
<br />
* '''IPC''' - Inter-process communication. Basically, anytime one program communicates with another.<br />
<br />
* '''Language Pack''' - A special plug-in that translates most Winamp text.<br />
<br />
* '''Llama''' - A domesticated South American ruminant mammal (Lama glama) related to the camel, raised for its soft, fleecy wool. The only animal fully endorsed by Nullsoft.<br />
<br />
* '''Mini-browser''' - Winamp component that allows internet browsing during audio play.<br />
<br />
* '''MP3''' - MPEG-1 Audio Layer 3. A digital audio compression algorithm that acheives a compression factor of about twelve while preserving sound quality.<br />
<br />
* '''NSDN''' - Nullsoft Developers Network. The developers source for official Nullsoft information.<br />
<br />
* '''NSIS''' - Nullsoft Scriptable Install System. Nullsoft's in-house installer utility. Required for plug-in installation.<br />
<br />
* '''Nullsoft''' - Group of benevolent artisans who revolutionize the computer world on a regular basis.<br />
<br />
* '''Output Plug-in''' - A plug-in that directs audio flow to one or more destinations.<br />
<br />
* '''PiMP''' - Plug-in Mini Packager. Predecessor to NSIS.<br />
<br />
* '''PMP''' - Portable Media Player. Creative Zen, Apple iPod, etc. Not to be confused with the original name for NSIS (PiMP).<br />
<br />
* '''Playlist Editor''' - Winamp component that allows easy sorting and sequencing of audio files.<br />
<br />
* '''Plug-in''' - Basis of Winamp architecture. Allows third parties to add functionality to Winamp by "plugging in" additional code.<br />
<br />
* '''Preset''' - Visually pleasing sequence of Effect Modules in AVS or Milkdrop.<br />
<br />
* '''SDK''' - Software Development Kit. All the tools you need to perform a programming job.<br />
<br />
* '''SHOUTcast''' - Nullsoft's internet streaming MP3 solution.<br />
<br />
* '''Skin''' - Interchangeable visual interface for Winamp.<br />
<br />
* '''Visualization Plug-in''' - A plug-in that uses audio data to drive graphics.<br />
<br />
* '''WAL''' - Required format for Modern skins before submittal.<br />
<br />
* '''WAV''' - Widely used uncompressed audio format. Usually more than 10X larger than MP3.<br />
<br />
* '''Winamp''' - The ultimate high-fidelity music player for Windows 2000/XP/Vista. Winamp supports MP3, CD and other audio formats, not to mention hundreds of plug-ins and thousands of skins.<br />
<br />
* '''Winamp.com''' - Official website of Winamp. Houses all approved skins, plug-ins, updates, forums, etc.<br />
<br />
* '''WindowShade Mode''' - Winamp option that shrinks most components to a narrow bar with only most basic functionality.<br />
<br />
* '''WSZ''' - Required format for Classic skins before submittal.<br />
<br />
* '''WVS''' - Obsolete name for AVS.<br />
<br />
== See also ==<br />
* [[Plugin Terminology]]</div>Culixhttp://wiki.shoutcast.com/wiki/Modern_Skin:_Alpha_ChannelsModern Skin: Alpha Channels2010-11-30T03:31:30Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Tarik</p>
<hr />
<div>Creating a Modern Skin --> [[Modern Skin: Intro|Intro]] --> [[Modern Skin: Winamp 2 to W3+|Winamp 2 to Winamp 3+]] --> [[Modern Skin: Simple Skin Tutorial|Simple Skin Tutorial]] --> [[Modern Skin: XML Intro|XML Intro]] --> [[Modern Skin: Simple Skin Tutorial (Continued)|Simple Skin Tutorial (Continued)]] --> [[Modern Skin: Container| Container]] --> [[Modern Skin: Group|Group]] --> [[Modern Skin: Relative Positioning| Relative Positioning]] --> [[Modern Skin: Complex Skin|Complex Skin]] --> [[Modern Skin: Non-Rect Player| Non-Rect Player]] --> [[Modern Skin: Layer Composition| Layer Composition]] --> [[Modern Skin: Alpha Channels| Alpha Channels]] --> [[Modern Skin: Animatedlayer|Animatedlayer]] --> [[Modern Skin: Snap Points|Snap Points]] --> [[Modern Skin: Drawers|Drawers]] --> [[Modern Skin: Skin Scripting| Skin Scripting]] --> [[Modern Skin: Drawer Scripting| Drawer Scripting]] --> [[Modern Skin: Animating a Skin|Animating a Skin]] --> [[Modern Skin: Maki Overview| Maki Overview]] --> [[Main_Page#Glossary_of_Terms|Glossary]]<br />
<br />
<br />
Alpha channel controls the transparency value of an element. By adjusting the alpha value of an element, you can make the element totally transparent or not transparent at all. Winamp3 blends that element with the background image if the transparency of that element is increased.<br />
<br />
Take a look at the two images below. Both images have a red rectangle layer on top of the Boxer skin. The red rectangle in the first image has no transparency: the result is an overlap of images. The second image uses alpha channel to create some transparency: the result is the blending of the red rectangle and the Boxer skin.<br />
<br />
<br />
<br />
[[Image:Layer-notblend.png]]<br />
<br />
<nowiki>*</nowiki> No transparency: images overlap.<br />
<br />
<br />
<br />
[[Image:Layer-blend.png]]<br />
<br />
<nowiki>*</nowiki> Some transparency: images blend.<br />
<br />
<br />
<br />
'''Complex Tutorial'''<br />
<br />
<br />
[[Image:Complexskin diag alpha.png]]<br />
<br />
<br />
In Complex Tutorial, Group #2 (the second circle from the left), has blue triangle blended with the red circle. This is done through Alpha Channel. Note that the graphical asset for this group is the same as the ones used to demonstrate Layer Composition. The only difference is that we adjusted the alpha value for the triangle in this section. Here's the process.<br />
<br />
<br />
<br />
Lets go through in detail how do to each step:<br />
<br />
==Make the Graphics: The Red Circle and Blue Triangle==<br />
<br />
<br />
red-circle.png &nbsp;&nbsp; [[Image:Red-circle.png]]<br />
<br />
triangle.png &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [[Image:Triangle.png]]<br />
<br />
<br />
<br />
<br />
==Define the Elements in the XML Code==<br />
<br />
<br />
[[Image:Layercomp xml.png]]<br />
<br />
<br />
<br />
<br />
==Define Layers Using those Elements==<br />
<br />
<br />
[[Image:Alpha xml1.png]]<br />
<br />
[[Image:Alpha xml2.png]]<br />
<br />
<br />
<br />
<br />
==Place the Layers in the Same Area==<br />
<br />
<br />
[[Image:Alpha xml3.png]]<br />
<br />
<br />
<br />
<br />
==Change the Alpha Value for the Triangle==<br />
<br />
<br />
[[Image:Alpha xml4.png]]</div>Culixhttp://wiki.shoutcast.com/wiki/Tips_for_Writing_an_Awesome_Online_ServiceTips for Writing an Awesome Online Service2010-11-30T03:29:22Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Gistbane</p>
<hr />
<div>==Overview==<br />
<br />
<br />
"A Winamp Online Service is simply a web page"<br />
quote from an unidentified if not too creative web page developer, circa 2009.<br />
<br />
When I first heard the above statement I was somewhat surprised. Winamp Online Services are not just web pages. True, you could create a web page and use it as an Online Service but that would be like, .... well like using your smart phone to just make phone calls. There's so much more creative things that can be done. In this document I'd like to point out some cool things that have already been done with Online Services hopefully generating ideas for even more fantastic mashups.<br />
<br />
To start with, if you are unfamiliar with what an Online Service is, you can find an excellent description of creating, submitting and managing a service at the [[Online_Service_Developer]] page.<br />
<br />
Most importantly, a full description of the JavaScript APIs that can be called from an Online Service can be found at the [[Complete_JavaScript_API_technology_framework]] page. These are the api methods that can make Online Services special, far beyond a 'normal' web page. Not to mention that I also wrote the wiki doc above, so if you like this one, the API reference above would also be good.<br />
<br />
If you happened to actually read the two links listed above, rather than coming back to them after reading this, you may have realized what I will be driving at in this document:<br />
<br />
'''In order to make an absolutely astounding Online Service, the web page must use the underlying APIs to integrate with the Winamp music player.'''<br />
<br />
To restate this, there are facilities to control and retrieve information from the Winamp player. These apis turn a web page into a cool Winamp Online Service. Can you think of some cool things to do with this?....I thought you could. Let's see some Online Services that have already been done.<br />
<br />
==Tour Tracker==<br />
In case you don't know (check out the Winamp Online Services), the Tour Tracker Online Service provides a way for users to see upcoming concert information for the bands they are currently listening to on the Winamp player. There are links on this service to purchase tickets to the concerts. Way easier than the old days. <br />
<br />
Here is some JavaScript code from the Tour Tracker Online Service. <br />
<br />
<code><br />
function getartist() {<br />
if (!artist) {<br />
if (window.external && window.external.Transport) {<br />
artist = window.external.Transport.GetMetadata("artist");<br />
songtitle = window.external.Transport.GetMetadata("title");<br />
<br />
document.location.href="index.php?artist=" + artist;<br />
}<br />
}<br />
}<br />
</code><br />
<br />
This code retrieves the artist name and the title from the currently playing track. So what could you do with that? Well, how about....<br />
<br />
<code><br />
function loadscript() {<br />
// just load ONCE on page-load<br />
if (window.external && window.external.Transport) {<br />
var refreshval = ReadCookie("refresh");<br />
if (refreshval == 1) {<br />
document.getElementById("refreshcheckbox").checked = true;<br />
rc = window.external.Transport.RegisterForEvents(onEvents);<br />
}<br />
}<br />
}<br />
<br />
function unloadscript() {<br />
if (window.external && window.external.Transport) {<br />
rc = window.external.Transport.UnregisterFromEvents(onEvents);<br />
}<br />
}<br />
</code><br />
<br />
Here the JavaScript code is registering to receive 'events' from the Winamp player. The loadscript() function is executed when the web page is first loaded and the unloadscript() is executed when the page is unloaded. The function 'onEvents' is called when events occur in the player. Note that the refresh flag is read from the cookie and is used to set the "refreshcheckbox" UI element on the page. Don't forget to 'Transport.UnregisterFromEvents()' when the page unloads.<br />
<br />
<code><br />
function onEvents(event){<br />
if (event.event == "OnPlay" && document.getElementById<br />
("refreshcheckbox").checked == true) {<br />
if (document.getElementById("WindowBox").style.display=="block") {<br />
// empty then block<br />
// don't switch if user is in the process of purchasing tickets!<br />
} else {<br />
getartist();<br />
}<br />
}<br />
}<br />
</code><br />
<br />
Here is the onEvents handler. event.event == "OnPlay" is the event fired whenever a new music track is started on the Winamp player. What this means is that the Tour Tracker Online Service can retrieve the author and title whenever a new track starts playing. Tour Tracker then uses this information to open a new web page in the browser to a site that can show up-coming concerts for the artist and allow the user to purchase tickets.<br />
<br />
<code><br />
function browsetab(urldata) {<br />
var urltouse = urldata.toLowerCase();<br />
urltouse = urltouse.replace(' ', '-');<br />
window.external.Application.LaunchURL(urltouse);<br />
}<br />
</code><br />
<br />
In the following screenshot, you can see that the currently playing song is 'Stuck with You' by Huey Lewis and the News. The Tour Tracker Online Service appears in the browser, showing scheduled concerts for the band. There is an Auto-Refresh checkbox in the upper right corner of the screen (not visible in the screenshot), that will cause Tour Tracker to automatically bring up concert information (if any) for the artist for the next track (John Waite).<br />
<br />
[[Image:TourTrackerWinampOnlineService.PNG]]<br />
<br />
Now is that 'just' a web page? I think not.<br />
<br />
==AOL Radio==<br />
The AOL Radio Online Service does something else interesting. Here are two screenshots, one with the default Bento skin and another with a custom skin.<br />
<br />
Here's the first<br />
<br />
<br />
[[Image:Radiowithbentoskin.PNG]]<br />
<br />
And here's the second<br />
<br />
[[Image:Radiowithnewskin.PNG]]<br />
<br />
Do you see something different? Okay, Okay, other than the color difference. Did you notice that the AOL Radio Online Service web page changed color also? This is a good example of making an online service blend in with the Winamp player. Also notice the 'Sponsored Links'. This is a good example of NOT making it blend in with the Winamp player. But to be fair, the 'Sponsored Links' is somewhat different than the rest of the page so let's talk about the page itself.<br />
<br />
The AOL Radio Online Service web page uses code like the following to obtain the color and font information about the Winamp player.<br />
<br />
<code><br />
function updateSkinColors()<br />
{<br />
// globals for anyone who wants 'em!<br />
sColorItemBg = window.external.Skin.GetClassicColor(0); <br />
sColorItemFg = window.external.Skin.GetClassicColor(1); <br />
sColorWndBg = window.external.Skin.GetClassicColor(2); <br />
sColorBtnFg = window.external.Skin.GetClassicColor(3); <br />
sColorWndFg = window.external.Skin.GetClassicColor(4); <br />
sColorHilite = window.external.Skin.GetClassicColor(5); <br />
sColorSel = window.external.Skin.GetClassicColor(6); <br />
sColorListHeadBg = window.external.Skin.GetClassicColor(7); <br />
sColorListHeadFont = window.external.Skin.GetClassicColor(8); <br />
sColorListHeadTop = window.external.Skin.GetClassicColor(9); <br />
sColorListHeadMid = window.external.Skin.GetClassicColor(10); <br />
sColorListHeadBot = window.external.Skin.GetClassicColor(11); <br />
sColorListHeadEmpty = window.external.Skin.GetClassicColor(12); <br />
sColorScrollFg = window.external.Skin.GetClassicColor(13); <br />
sColorScrollBg = window.external.Skin.GetClassicColor(14); <br />
sColorScrollInvFg = window.external.Skin.GetClassicColor(15); <br />
sColorScrollInvBg = window.external.Skin.GetClassicColor(16); <br />
sColorScrollEmpty = window.external.Skin.GetClassicColor(17); <br />
sColorSelbarFg = window.external.Skin.GetClassicColor(18); <br />
sColorSelbarBg = window.external.Skin.GetClassicColor(19); <br />
sColorInactSelbarFg = window.external.Skin.GetClassicColor(20); <br />
sColorInactSelbarBg = window.external.Skin.GetClassicColor(21); <br />
<br />
sColorPlFg = window.external.Skin.GetPlaylistColor(0); <br />
sColorPlCurrentFg = window.external.Skin.GetPlaylistColor(1); <br />
sColorPlBg = window.external.Skin.GetPlaylistColor(2); <br />
sColorPlSelbar = window.external.Skin.GetPlaylistColor(3); <br />
sColorPlGenericFg = window.external.Skin.GetPlaylistColor(4); <br />
sColorPlGenericBg = window.external.Skin.GetPlaylistColor(5); <br />
<br />
sFontName = window.external.Skin.font; <br />
sFontSize = window.external.Skin.fontsize; <br />
.<br />
.<br />
.<br />
}<br />
</code><br />
<br />
The page then uses script such as this to change the page to use the same colors and fonts.<br />
<br />
<code><br />
function updateColors()<br />
{<br />
.<br />
.<br />
.<br />
$("#wa_body").css("backgroundColor", sColorItemBg);<br />
$("#nav").css({ backgroundColor: sColorSelbarBg, color: sColorSelbarFg });<br />
$("#upgrade_msg").css("borderColor", sColorSelbarBg);<br />
.<br />
.<br />
.<br />
}<br />
</code><br />
<br />
In the code above we're adjusting the css attributes for the elements identified with id= parameter set to the text after the "#"s. And we set them to the values we retrieved from the Winamp player in the previous function.<br />
<br />
With these functions, you can make an Online Service look totally integrated inside the Winamp player. When done right, it doesn't even look like a separate web page.<br />
<br />
==Song of the Day==<br />
Here is another example of outstanding use of one of the apis, the Transport API.<br />
<br />
Below is a snapshot of the "Song of the Day" Online Service from Spinner.<br />
<br />
[[Image:Songoftheday.PNG]]<br />
<br />
Notice the big, ol' round button in the center of the track information. Notice how the first track has a "Pause" button and all the rest have "Play" buttons. That's because I clicked on the play button for the first song and it started playing and now, I can pause it. If you listen to this track, Winamp will eventually move on to the next track in the playlist and, magically, the buttons will change as Winamp begins to play the next track. Also notice that when you click to play one of the items on the web page, a Playlist is created and the song you selected begins to play. How can this be done? Well, it isn't really magic. You don't need to be Harry Potter to do this.<br />
<br />
This can be done using the Transport, Transport Events and Playqueue apis.<br />
<br />
====Transport====<br />
The Transport API controls the Winamp player, like pushing buttons on the front of a CD player. When the user presses on the buttons on this page, the page calls the following api methods depending on which button was previously being shown:<br />
<br />
window.external.Transport.Play();<br />
or<br />
window.external.Transport.Pause();<br />
<br />
Simple, huh?<br />
===Transport Events===<br />
But how does the web page know to change from the pause image to the play image when the track ends? Conversly, how does it know to switch from play to pause when it starts the next song? The answer is to register for events from the Winamp player. You've seen this already in the first example we talked about, the Tour Tracker Online Service. Remember this api method?<br />
<br />
window.external.Transport.RegisterForEvents(onEvents);<br />
<br />
Note: Don't forget to "UnregisterFromEvents" when you are done.<br />
<br />
The onEvents function is passed a parameter indicating what kind of event occurred. Let's say "OnPlay" or "OnEndOfFile" (actually the end of a track). With these two events you can change the appropriate images.<br />
<br />
===PlayQueue API===<br />
Now what about that queing things to be played thingy? That can be done with the methods of the PlayQueue api. The following api call will clear the list of tracks to be played. You might want to use the Transport.Stop() api to stop the Winamp player as clearing the play queue will not stop the currently playing song.<br />
<br />
window.external.PlayQueue.ClearQueue();<br />
<br />
To enqueue tracks to be played, you need to call....wait for it..... the Enqueue method.<br />
<br />
window.external.PlayQueue.Enqueue(<URL>);<br />
<br />
Where <URL> is replaced with a string containing the URL of the track to be played. Do this for each of the tracks that you want queued.<br />
<br />
Finally, how do we get the song that was clicked to begin playing? Especially if it was not the first one in our newly constructed Playqueue? You do this by changing the value of the PlayQueue cursor property.<br />
<br />
window.external.PlayQueue.cursor = n;<br />
<br />
Where n is the offset into the play queue of the track to be played. Be aware that this value is zero (0) based, meaning the first track in the play queue is at cursor=0.<br />
<br />
Now just use the Transport.Play() method to kick off the music.<br />
<br />
==Finale==<br />
So. We've looked at three different Winamp Online Services. Each one uses apis to do things that 'normal' web pages cannot. The services are more tightly integrated with the Winamp player to cause some very interesting behaviors. Check out the documentation listed at the front of this article and spur on your imagination to create an Awesome Online Service.</div>Culixhttp://wiki.shoutcast.com/wiki/Complete_JavaScript_API_technology_frameworkComplete JavaScript API technology framework2010-11-30T03:29:17Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Blo</p>
<hr />
<div>'''Breadcrumb''' -- [[Main_Page|Wiki Main]] : [[Skin Developer]] : [[Visual Developer]] : [[Plug-in Developer]] : [[Online Service Developer]] : [[Articles|Articles Page]] : [[Developers FAQ|FAQ]] : [[Main_Page#Glossary_of_Terms|Glossary]]<br />
[[Category:Winamp]]<br />
<br />
==Overview==<br />
The purpose of the Winamp Online Service API is to allow content creators to interact with the Winamp client in order to provide to create custom experiences for their users based on the power of Winamp. The overall idea is to include exceptional web sites within Winamp Online Services.<br />
<br />
The Winamp Online Service API is made up of methods that can be called from scripts within web pages rendered by the Winamp client. The API can be invoked using any scripting language supported by the Microsoft Internet Explorer web browser (5.5 and above). For simplicity, examples in this document will use JavaScript.<br />
<br />
==Setup==<br />
The Winamp Online Services API is designed to allow web pages, hosted (displayed) within the embedded browser of the Winamp client, to access the functionality of the client. There are several steps necessary to allow this to take place.<br />
<br />
#Make sure you have the latest version of the Winamp client that supports online services.<br />
#Make sure you have the latest version of the ml_webdev plugin (ml_webdev.dll). The presence of this plugin will create a "Web Dev Test Platform" within the Medial Library pane.<br />
#In order to change the starting web page for the online service, start the Winamp client and configure the plugin. <br />
##Select Options->Preferences->Plug-ins->Media Library. <br />
##Select "API 2 Test Platform" and press "Configure selected plugin". <br />
##On the Web Dev Preferences dialog, set the URL field to the URL of the initial web page for the online service. For example, <nowiki>file://c:\myonlineservice\webdev.html</nowiki><br />
#Click on "Web Dev Test Platform" in the Media Library. You may have to right click and choose refresh to see the new web page.<br />
<br />
You should now see the initial page of your online service in the Winamp embedded browser.<br />
<br />
==window.external==<br />
The Winamp JavaScript API can be accessed through the window.external object in the Document Object Model (DOM) exposed by the IE browser control embedded within the Winamp client. The API methods can only be accessed thru the Winamp client and are not available if the web page is displayed outside of the client.<br />
<br />
The invocation of all methods follow this form<br />
window.external.'''''API'''''.'''''Method'''''<br />
<br />
Properties can also be accessed using a similar form:<br />
window.external.'''''API'''''.'''''Property'''''<br />
<br />
Where ''API'' is a singleton class that defines a group of related methods (i.e., functionality). For example, Transport (Stop, Play, Next, etc) which controls the "buttons" of the Winamp player. <br />
<br />
''Method'' is a function you can call as part of a particular API. For example the following call will stop the Winamp client:<br />
window.external.Transport.Stop();<br />
<br />
''Property'' is an internal variable for the particular API that can be queried and in some cases set. For example the following will provide access to the Winamp client shuffle "button":<br />
var shuffle = window.external.Transport.shuffle; // gets the current state<br />
OR<br />
window.external.Transport.shuffle = true; // turns on shuffle<br />
<br />
See the documentation on each API below for a complete list of methods and properties.<br />
<br />
<!-- == Security Warnings ==<br />
Using the Winamp JavaScript API, an online service web page has access to much more information (read: power) than a normal web page. For example, playlists can be enumerated, and metadata for songs can be retrieved. In order to control these capabilities a security system was implemented so that users are informed whenever an online service first attempts to use an API method or access a property. For example, when an online service attempts to stop playback for the very first time, the user will be notified and asked whether the service should be allowed to do this.<br />
<br />
Note that this security model maintains user choices based on service ID so that the user will be prompted each time a service tries to invoke methods or access properties. In addition, online services updated through the Winamp Online Service submission process, receive new service IDs, causing the users to be prompted again.<br />
<br />
A dialog is presented to the user that describes the action about to be performed and forces the user to choose whether the action should be Allowed or Denied. A third button let's a user to indicate "Always Allow". If the user selects this button, the API will no longer prompt the user for this action (for this particular online service). <br />
<br />
Be aware that choices for certain APIs will affect the entire API and all of its methods and properties. For example, choosing "Always Allow" for Transport.Stop() will also always allow access to the other Tranport methods/properties. Certain other APIs, such as the Application API affect only the action being attempted. Some API methods and properties are considered inconsequential and not governed by this security model at all. The scope of the user's choice will be described within the dialog.<br />
--><br />
<br />
== Transport API ==<br />
The Transport API is used to control the Winamp client. "Transport controls" was the name given to the buttons on the front panel that controlled hardware devices. This name is used in Winamp for the same purpose. It is also used to access information about the currently playing song.<br />
<br />
The Transport API can also be used to register for events involved with asset playback. See the section [[#Transport Events API|Transport Events API]].<br />
<br />
===Methods===<br />
====Prev()====<br />
Transport.Prev() can be used to press the "Previous Track" button on the Winamp player. Invoking Prev() while an asset is already playing will cause the previous asset to begin playback immediately. Invoking Prev() while the player is stopped will cause the previous asset to play next time playback starts.<br />
<br />
Prototype:<br />
bool Prev();<br />
Example:<br />
var rc = window.external.Transport.Prev();<br />
Return Value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
====Play()====<br />
Transport.Play() can be used to press the "Play" button on the Winamp player. Invoking Play() on an asset already playing will cause the asset to restart playback. Pressing Play() on a paused asset will cause it to begin playing from its current position. <br />
<br />
<br />
Prototype:<br />
bool Play();<br />
Example:<br />
var rc = window.external.Transport.Play();<br />
Return Value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
====Pause()====<br />
Transport.Pause() can be used to press the "Pause" button on the Winamp player. Issuing Pause() again, or Play() will cause the asset to continue to play from the location where it was paused.<br />
<br />
Prototype:<br />
bool Pause();<br />
Example:<br />
var rc = window.external.Transport.Pause();<br />
Return Value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
====Stop()====<br />
Transport.Stop() can be used to press the "Stop" button on the Winamp player.<br />
<br />
Prototype:<br />
bool Stop();<br />
Example:<br />
var rc = window.external.Transport.Stop();<br />
Return Value:<br />
A boolean value indicating whether the request was successful.<br />
====Next()====<br />
Transport.Next() can be used to press the "Next Track" button on the Winamp player. Invoking Next() while the player is stopped will cause the next asset to play next time playback starts.<br />
<br />
Prototype:<br />
bool Next();<br />
Example:<br />
var rc = window.external.Transport.Next();<br />
Return Value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
====GetMetadata()====<br />
Transport.GetMetadata() can be used to fetch metadata for the currently playing asset. The "tag" parameter is specific to different asset encoding formats so a knowledge of the metadata field names is necessary to request specific data about an asset. Some field names are common but others are specific to the encoding format of the asset.<br />
<br />
Prototype:<br />
string GetMetadata(tag);<br />
where:<br />
'''tag''' = (string) identifier for the metadata to be returned.<br />
Example:<br />
var metaStr = window.external.Transport.GetMetadata("artist");<br />
Return Value:<br />
A string value containing the requested metadata.<br />
<br />
===Properties===<br />
====bool shuffle====<br />
Transport.shuffle provides access to the Winamp client shuffle "button".<br />
<br />
Example:<br />
var isShuffling = window.external.Transport.shuffle; // get shuffle state<br />
window.external.Transport.shuffle = true; // turns on shuffle<br />
<br />
====bool repeat====<br />
Transport.repeat provides access to the Winamp client repeat "button".<br />
<br />
Example:<br />
var isRepeating = window.external.Transport.repeat; // get repeat state<br />
window.external.Transport.repeat = false; // turns off repeat<br />
<br />
====int position====<br />
Transport.position provides access to the position being played within the current asset. Setting this value can change the location where playback occurs. position is in milliseconds.<br />
<br />
Example:<br />
var position = window.external.Transport.position; // get position in current track<br />
window.external.Transport.position = 221559; // move playback of the current track <br />
// to the specified position.<br />
<br />
====bool playing (read only) ====<br />
Transport.playing indicates whether the Winamp Player is currently playing.<br />
<br />
Example:<br />
var isPlaying = window.external.Transport.playing; // is player playing?<br />
<br />
====bool paused (read only) ====<br />
Transport.paused indicates whether the Winamp Player has been paused.<br />
<br />
Example:<br />
var isPaused = window.external.Transport.paused; // is player paused?<br />
<br />
====int length (read only)====<br />
Transport.length provides access to the length in seconds of the track currently playing.<br />
<br />
Example:<br />
var length = window.external.Transport.length; // get length of current track in secs<br />
<br />
====string url (read only)====<br />
Transport.url provides access to the URL (or filename) of the track currently playing.<br />
<br />
Example:<br />
var url = window.external.Transport.url; // get url of current track<br />
<br />
====string title (read only)====<br />
Transport.title provides access to the title of the track currently playing.<br />
<br />
Example:<br />
var title = window.external.Transport.title; // get title of current track<br />
<br />
==Transport Events API==<br />
The Event mechanism of the Transport API allows javascript programmers to specify a callback method that will be invoked whenever certain Transport events take place. An Event object is passed back to the method from which properties can be accessed that provide more information about the event.<br />
<br />
===RegisterForEvents()===<br />
The RegisterForEvents() method can be used to specify a JavaScript function that is to be called when any Transport Events occur. An event object is passed that indicates the type of event.<br />
<br />
Prototype:<br />
boolean RegisterForEvents(handler);<br />
<br />
Example:<br />
var rc = window.external.Transport.RegisterForEvents(EventHandler);<br />
<br />
Return value:<br />
boolean value indicating whether the request was successful.<br />
<br />
===UnregisterFromEvents()===<br />
The UnregisterFromEvents() method is used to stop receiving notifications about Transport events.<br />
<br />
Note: The original handler used in RegisterForEvents() must be passed back into UnregisterFromEvents().<br />
<br />
Prototype:<br />
boolean UnregisterFromEvents(handler);<br />
<br />
Example:<br />
var rc = window.external.Transport.UnregisterFromEvents(EventHandler);<br />
<br />
Return value:<br />
boolean value indicating whether the request was successful.<br />
<br />
===Events===<br />
The Transport API Event mechanism requires a JavaScript callback method that accepts a single parameter, a reference to a function. This function will be invoked with an "event" object that will indicate the type of event that occurred as well as contain properties containing more information about the event.<br />
<br />
====OnStop====<br />
The OnStop event is triggered when the Winamp client is stopped.<br />
<br />
=====properties=====<br />
integer event.position = contains the position within the file where the "Stop" was issued. position is the number of milliseconds from the start of the asset.<br />
<br />
====OnPlay====<br />
The OnPlay event is triggered when the Winamp client begins playback. If the client is paused and then restarted by "pressing Play", the OnPause event is triggered rather than an OnPlay event.<br />
<br />
=====properties=====<br />
string event.filename = contains the filename/URL of the asset starting playback.<br />
<br />
====OnPause====<br />
The OnPause event is triggered when the Winamp client is paused or unpaused. If the client is started after being paused, by "pressing Play", the OnPause event is triggered rather than an OnPlay event.<br />
<br />
=====properties=====<br />
boolean event.paused = true (the player was paused), false (the player was unpaused)<br />
<br />
====OnEndOfFile====<br />
The OnEndOfFile event is triggered when the player reaches the end of a track.<br />
<br />
=====properties=====<br />
None<br />
<br />
===Callback function===<br />
The callback function is invoked whenever a Transport event is detected. The callback function is specified in both the RegisterForEvents() and UnregisterFromEvents() methods. The method takes a single parameter, which is loaded with an object identifying the event that occurred.<br />
<br />
Example:<br />
function EventHandler(event){<br />
{<br />
if (event.event == "OnStop"){<br />
alert("OnStop: position=" + event.position);<br />
}<br />
else if (event.event == "OnEndOfFile"){<br />
alert("OnEndOfFile");<br />
}<br />
else if (event.event == "OnPause"){<br />
alert("OnPause: paused=" + event.paused);<br />
}<br />
else if (event.event == "OnPlay"){<br />
alert("OnPlay: filename=" + event.filename);<br />
}<br />
else {<br />
alert("Unrecognized Event received");<br />
}<br />
}<br />
<br />
== PlayQueue API ==<br />
Provides access to the play queue ("Winamp Playlist"). If you need access to the currently playing song, use the Transport API instead.<br />
<br />
Note that the Play Queue is the list of assets that are scheduled to be played by the Winamp client. This is not necessarily the same as a user playlist. Once placed in the play queue, assets can be rearrainged or deleted from the play queue without affecting a user playlist. Individual assets can be placed in the play queue without being contained within a user playlist. Additionally, after adding a playlist to the play queue, changes to the playlist will not affect the assets in the play queue.<br />
<br />
===Methods===<br />
====Play()====<br />
The PlayQueue.Play() method stops playback, clears the play queue, enqueues the asset specified by the URL and starts playback. If the URL cannot be found, playback will stop, the play queue will be cleared, the URL (or title and length) will appear in the queue but playback will not be started. <br />
<br />
Prototype:<br />
bool Play(URL);<br />
bool Play(URL, title);<br />
bool Play(URL, title, length);<br />
where:<br />
'''URL''' = (string) identifies the location of the asset, for a file that is<br />
local or on an attached network drive this would be the fully<br />
qualified path and filename. For files served from a web server,<br />
it would be the http URL.<br />
'''title''' = (string) used as the title when initially placed in<br />
the play queue. <br />
'''length''' = (integer) used as the length when initially place<br />
in the play queue<br />
<br />
Note, title and length are displayed in the play queue to identify what is to be played. In order to reduce network activity, the real title and length are only accessed (using the URL) when the asset is about to commence playback. At this point the title and length are updated to their real values.<br />
<br />
Example:<br />
var rc = window.external.PlayQueue.Play("c:\\Winamp\\01 - Hello.mp3",<br />
"My Cool Title",1024);<br />
Return Value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
====Enqueue()====<br />
PlayQueue.Enqueue() is used to add an asset to the play queue. The selected asset is added to the bottom of the queue and current playback is not interrupted.<br />
<br />
Prototype:<br />
bool Enqueue(URL);<br />
bool Enqueue(URL, title);<br />
bool Enqueue(URL, title, length);<br />
'''URL''' = (string) identifies the location of the asset, for a file that is<br />
local or on an attached network drive this would be the fully<br />
qualified path and filename. For files served from a web server,<br />
it would be the http URL.<br />
'''title''' = (string) used as the title when initially placed in<br />
the play queue. <br />
'''length''' = (integer) used as the length when initially place<br />
in the play queue<br />
<br />
Note, title and length are displayed in the play queue to identify what is to be played. In order to reduce network activity, the real title and length are only accessed (using the URL) when the asset is about to commence playback. At this point the title and length are updated to their real values.<br />
<br />
Example:<br />
var rc = window.external.PlayQueue.Enqueue("c:\\Winamp\\01 - Hello.mp3",<br />
"My Cool Title",1024);<br />
Return Value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
====Insert()====<br />
The PlayQueue.Insert() method can add an asset to the play queue at a specific index.<br />
<br />
Prototype:<br />
bool Insert(position, URL);<br />
bool Insert(position, URL, title);<br />
bool Insert(position, URL, title, length);<br />
where:<br />
'''position''' = (integer) a zero based number indicating the location within<br />
the play queue to insert the new asset.<br />
Note: Position is "zero based" so the first entry in the <br />
queue is at position 0.<br />
'''url''' = (string) the URL of the asset to be added<br />
'''title''' = (string) the title to be displayed in the Play Queue.<br />
'''length''' = (integer) the length of the asset to be displayed in <br />
the play queue.<br />
<br />
Note, title and length are displayed in the play queue to identify what is to be played. In order to reduce network activity, the real title and length are only accessed (using the URL) when the asset is about to commence playback. At this point the title and length are updated to their real values.<br />
<br />
Example:<br />
var rc = window.external.PlayQueue.Insert(1, "c:\\mySongs\\mySong.mp3",300);<br />
Return Value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
====ClearQueue()====<br />
The PlayQueue.ClearQueue() method removes all assets from the play queue. This does not stop the current playback. ClearQueue is commonly used to prepare the Play Queue for the addition of new assets.<br />
<br />
Prototype:<br />
bool ClearQueue()<br />
Example:<br />
var rc = window.external.PlayQueue.ClearQueue();<br />
<br />
Return Value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
====GetMetadata()====<br />
PlayQueue.GetMetadata() can be used to obtain asset metadata about an asset in the play queue. <br />
<br />
Prototype:<br />
String GetMetadata(position, metadatatag);<br />
where:<br />
'''position''' - (integer) is the position of the asset within the playlist.<br />
Note: Position is "zero based" so the first entry in the <br />
queue is at position 0.<br />
'''metadatatag''' - (string) is a tag describing which metadata is requested.<br />
<br />
Example:<br />
var mdata = window.external.PlayQueue.GetMetadata(2,"artist");<br />
Return Value:<br />
A String that contains the metadata requested for the asset located at the specified position in the play queue<br />
<br />
====GetTitle()====<br />
PlayQueue.GetTitle() retrieves the title of the asset at the specified position within the play queue.<br />
<br />
Prototype:<br />
String GetTitle(position);<br />
where:<br />
'''position''' - (integer) is the position of the asset within the playlist.<br />
Note: Position is "zero based" so the first entry in the <br />
queue is at position "0".<br />
Example:<br />
var title = window.external.PlayQueue.GetTitle(1);<br />
Return value:<br />
A String containing the Title of the asset at the requested position in the play queue<br />
<br />
====GetURL()====<br />
PlayQueue.GetURL() is used to obtain the URL from the asset at the specified position in the play queue<br />
<br />
Prototype:<br />
String GetURL(position);<br />
where:<br />
'''position''' - (integer) is the position of the asset within the playlist.<br />
Note: Position is "zero based" so the first entry in the <br />
queue is at position "0".<br />
Example:<br />
var url = window.external.PlayQueue.GetURL(1);<br />
Return value:<br />
A String containing the URL of the asset at the rquested position in the play queue.<br />
<br />
===Properties===<br />
====int length (read only)====<br />
PlayQueue.length contains the length of the current play queue<br />
<br />
====int cursor====<br />
PlayQueue.cursor provides access to the position of the currently playing asset within the play queue. This cursor is 0 based, meaning that the first asset in the Play Queue has a cursor value of 0. Valid values range from 0 to the length of the play queue minus one.<br />
<br />
If this value is changed before playback is started, the next asset to play will be the one assigned to this property. However, if a song is already playing and this property is changed, the current asset will continue to play even though this property has been updated. At the point that the current asset playback completes, the player will increment the cursor position and play the next asset in the queue rather than the one to which cursor was set. So, for example, to specify the next asset to play while an asset is currently playing, set the cursor property to the position of the asset to play minus one.<br />
<br />
== Playlists API == <br />
The Playlists API is used to process user playlists.<br />
<br />
===Methods===<br />
====GetPlaylists()====<br />
<br />
Prototype:<br />
Array GetPlaylists();<br />
Example:<br />
var playlists = window.external.Playlists.GetPlaylists();<br />
Return Value:<br />
A array-like object that can be used to examine all user playlists.<br />
<br />
Each element of the array represents a user playlist and contains the following properties<br />
*filename - filename of the playlist<br />
*title - name of the playlist<br />
*playlistId - a unique identifier for the playlist, so you can retrieve it later. Also used with OpenPlaylist/SavePlaylist<br />
*length - total length (time) in seconds. Cached data - not guaranteed to be accurate<br />
*numitems - number of items in the playlist. Cached data - not guaranteed to be accurate<br />
<br />
====OpenPlaylist()====<br />
Playlists.OpenPlaylist() returns a Playlist object for the specified playlist ID. You must use <br />
Playlists.GetPlaylists() before issuing this request.<br />
<br />
Prototype:<br />
Playlist OpenPlaylist(playlistId);<br />
where:<br />
'''playlistId''' - (string) the Id of the playlist to be opened.<br />
Example:<br />
var playlist1 = window.external.Playlists.OpenPlaylist(playlistId);<br />
Return Value:<br />
The Playlist object with the specified playistId.<br />
<br />
====SavePlaylist()====<br />
Playlists.SavePlaylist() saves the specified playlist object with the specified ID.<br />
<br />
Prototype:<br />
bool SavePlaylist(playlistId, playlist_to_save);<br />
where:<br />
'''playlistId''' (string) is the id of the playlist to be saved.<br />
'''playlist_to_save''' (Playlist) is the Playlist object to be saved.<br />
Example:<br />
var rc = window.external.Playlists.SavePlaylist(playlistId, pl);<br />
Return Value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
<br />
<br />
=== Playlist Object ===<br />
Playlist objects can be created/returned by the OpenPlaylist() method as well as various other APIs.<br />
<br />
====Methods====<br />
=====GetItemFilename()=====<br />
The GetItemFilename() method retrieves the filename/URL of the item at the specified index into the playlist.<br />
<br />
Prototype:<br />
String GetItemFilename(position);<br />
where:<br />
'''position''' = (number) position of the item in the playlist for which the filename<br />
should be returned. <br />
Note: Position is "zero based" so the first entry in the <br />
playlist is at position 0.<br />
<br />
Example:<br />
var filename = playlst.GetItemFilename(0);<br />
<br />
Return value:<br />
A string containing the filename/URL of a particular item in the playlist<br />
<br />
=====GetItemTitle()=====<br />
The GetItemTitle() method returns the title of the asset at the requested index.<br />
<br />
Prototype:<br />
String GetItemTitle(position);<br />
where:<br />
'''position''' = (number) position of the item in the playlist for which the title<br />
should be returned.<br />
Note: Position is "zero based" so the first entry in the <br />
playlist is at position 0.<br />
<br />
Example:<br />
var title = playlst.GetItemTitle(0);<br />
<br />
Return value:<br />
The song title of the given item in the playlist<br />
<br />
=====GetItemLength()=====<br />
The GetItemLength() method retrieves the play length of the asset at the requested index.<br />
<br />
Number GetItemLength(position);<br />
where:<br />
'''position''' = (number) position of the item in the playlist for which the length<br />
should be returned.<br />
Note: Position is "zero based" so the first entry in the <br />
playlist is at position 0.<br />
<br />
Example:<br />
var itemLength = playlst.GetItemLength(0);<br />
<br />
Return value:<br />
A number specifying the play length of the asset, in milliseconds.<br />
<br />
=====Reverse()=====<br />
The Reverse() method reverses the order of the assets within a playlist, i.e., the first becomes last and the second becomes second to last, etc.<br />
<br />
Prototype:<br />
Reverse();<br />
<br />
Example:<br />
var rc = playlst.Reverse();<br />
<br />
<br />
=====Swap()=====<br />
The Swap() method exchanges the assets at the two specified positions.<br />
<br />
Prototype:<br />
Swap(Number position1, Number position2)<br />
where: <br />
'''position1''' = (number) the index of the first item to be swapped.<br />
'''position2''' = (number) the index of the second item to be swapped.<br />
Note: position1 and position2 are "zero based" so the first entry in the <br />
playlist is at position 0.<br />
<br />
Example:<br />
var rc = playlst.Swap(0,1);<br />
<br />
=====Randomize()=====<br />
The Randomize() method re-arranges the order of the playlist, placing the assets in random positions.<br />
<br />
Prototype:<br />
Randomize();<br />
<br />
Example:<br />
var rc = playlst.Randomize();<br />
<br />
=====Remove()=====<br />
The Remove() method removes an asset from the playlist. Subsequent assets are moved to lower number positions in the array.<br />
<br />
Prototype:<br />
Remove(position);<br />
where:<br />
'''position''' = (number) the position of the asset to be removed.<br />
Note: Position is "zero based" so the first entry in the <br />
playlist is at position 0.<br />
<br />
Example:<br />
var rc = playlst.Remove(0);<br />
<br />
=====SortByTitle()=====<br />
The SortByTitle() method re-arrainges the order of the playlist so that it is alphabetical order by title.<br />
<br />
Prototype:<br />
SortByTitle();<br />
<br />
Example:<br />
var rc = playlst.SortByTitle();<br />
<br />
=====SortByFilename()=====<br />
The SortByFilename() method re-arrainges the order of the playlist so that it is alphabetical order by filename.<br />
<br />
Prototype:<br />
SortByFilename();<br />
<br />
Example:<br />
var rc = playlst.SortByFilename();<br />
<br />
=====SetItemFilename()=====<br />
Sets the filename of the asset at the specified location in the playlist.<br />
<br />
playlistObj.SetItemFilename(position, filename);<br />
where:<br />
'''position''' = (number) position of the entry in the playlist to alter the filename<br />
'''filename''' = (string) the new filename <br />
Note: Position is "zero based" so the first entry in the <br />
playlist is at position 0.<br />
<br />
Example:<br />
var rc = playlst.SetFilename(0, "c:\\\\myfavorites\\myfavsong.mp3");<br />
<br />
=====SetItemTitle()=====<br />
Sets the title of the asset at the specified location in the playlist.<br />
<br />
Prototype:<br />
SetItemTitle(position, title);<br />
where:<br />
'''position''' = (number) position of the entry in the playlist to alter the filename<br />
'''title''' = (string) the new title <br />
Note: Position is "zero based" so the first entry in the <br />
playlist is at position 0.<br />
<br />
Example:<br />
var rc = playlst.SetItemTitle(0, "My Favorite Title");<br />
<br />
=====SetItemLength()=====<br />
Sets the length of the asset at the specified location in the playlist.<br />
<br />
SetItemLength(position, length);<br />
where:<br />
'''position''' = (number) position of the entry in the playlist to alter the filename<br />
'''length''' = (number) the new length <br />
Note: Position is "zero based" so the first entry in the <br />
playlist is at position 0.<br />
<br />
Example:<br />
var rc = playlst.SetItemLength(0, 1000);<br />
<br />
=====InsertURL()=====<br />
Inserts the specified asset in front of the asset at the specified position. That and subsequent items are "pushed" to a higher position in the array.<br />
<br />
InsertURL(position, url);<br />
InsertURL(position, url, title);<br />
InsertURL(position, url, title, length);<br />
where:<br />
'''position''' = (number) position within the playlist before which to insert the asset<br />
'''url''' = (string) the URL of the asset to be inserted<br />
'''title''' = (string) title of the asset to be inserted<br />
'''length''' = (number) length (milliseconds) of the asset to be inserted<br />
Note: Position is "zero based" so the first entry in the <br />
playlist is at position 0.<br />
Note: title and length are user specified and do not have to match<br />
the actual values of the asset. When the asset is played, the <br />
values will be replaced in the Play Queue when the URL is opened <br />
for playback but will othewise retain the above values in the <br />
playlist.<br />
<br />
Return value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
=====AppendURL()=====<br />
The Playlist.AppendURL() method appends an asset URL to the playlist.<br />
<br />
Playlist.AppendURL(url);<br />
Playlist.AppendURL(url, title);<br />
Playlist.AppendURL(url, title, length);<br />
where:<br />
'''url''' = (string) the URL to the asset to be appended<br />
'''title''' = (string) title of the asset to be appended<br />
'''length''' = (number) length (milliseconds) of the asset to be appended<br />
Note: title and length are user specified and do not have to match<br />
the actual values of the asset. When the asset is played, the <br />
values will be replaced in the Play Queue when the URL is opened <br />
for playback but will othewise retain the above values in the <br />
playlist.<br />
<br />
Return value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
=====Clear()=====<br />
The Playlist.Clear() method will remove all assets from the playlist.<br />
<br />
Playlist.Clear();<br />
<br />
Return value:<br />
A boolean value indicating whether the request was successful<br />
<br />
====Properties====<br />
=====int numitems (read only)=====<br />
The Playlist.numitems property contains the number of assets within the playlist.<br />
<!--<br />
== Playlist Manager API ==<br />
The Playlist Manager API provides methods to read and write playlists from permanent storage.<br />
<br />
===TBD===<br />
--><br />
<br />
== Bookmarks API ==<br />
The Bookmarks API provides methods to manage bookmarks.<br />
===Methods===<br />
====Add()====<br />
<br />
Prototype:<br />
boolean Add(url, title);<br />
where:<br />
'''url''' = (string) The url of the asset to be bookmarked.<br />
'''title''' = (string) A suitable title to be used within the bookmark.<br />
<br />
Example:<br />
var rc = window.external.Bookmarks.Add("c:\myfavs\songstocodeby.mp3", <br />
"Songs To Code By");<br />
<br />
Return value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
== Podcasts API ==<br />
The Podcasts API provides methods to manage Podcasts.<br />
<br />
===Methods===<br />
====Subscribe()====<br />
The Podcasts.Subscribe() method is used to add a channel to the list of podcast subscriptions, automatically subscribe to the podcast and begin downloading of the available episodes. Once downloaded the episodes can be selected for playback.<br />
<br />
Prototype:<br />
bool Subscribe(url);<br />
where:<br />
'''url''' = (string) the Podcast URL to subscribe to.<br />
<br />
Example:<br />
var rc = window.external.PodCasts.Subscribe(<nowiki>"http://services.winamp.com/rss/news"</nowiki>);<br />
<br />
Return value:<br />
boolean value that indicates whether the request was successful.<br />
<br />
== Config API ==<br />
The Config API provides a means by which properties can be saved. Properties added using the Config API are persistent across Winamp launches.<br />
<br />
===Adding and Retrieving Properties===<br />
Adding a property is accomplished by identifying a property and assigning it a value. Once assigned, the value can be retrieved like any other objects properties.<br />
<br />
Example:<br />
window.external.Config.myProperty = "Test";<br />
var myProp = window.external.Config.myProperty; // myProp is set to "Test"<br />
<br />
===Storing and Retrieving advanced data types===<br />
Internally, all properties are stored as strings. If you need to store datatypes more advanced than String, Number, or Boolean, it is recommended that you create a JSON string out of your data type.<br />
<br />
== Security API ==<br />
===Methods===<br />
====GetActionAuthorization()====<br />
The Security.GetActionAuthorization() method can be used to determine whether a user has previously allowed or denied the functioning of a particular API's methods. Group strings match API names.<br />
<br />
Prototype:<br />
number Security.GetActionAuthorization(group);<br />
where:<br />
group = (string) Name of API to check for permission.<br />
<br />
Example:<br />
var rc = window.external.Security.GetActionAuthorization("Transport");<br />
<br />
Return Data:<br />
*-1 = Either the user has not specified whether to allow/deny use of this API or the action usage is unrestricted. <br />
*0 = The user has previously specified to deny use of this API/method.<br />
*1 = The user has previously specified to allow use of this API/method.<br />
<!-- <br />
Transport – Access to the currently playing track, and play controls (play, stop, seek, etc)<br />
<br />
PlayQueue – Access to the play queue (Winamp Playlist)<br />
<br />
Application – general Winamp information – version #, language pack<br />
<br />
Playlists – access to the media library playlists<br />
<br />
Bookmarks – access to the user’s bookmarks (place to bookmark radio streams, etc)<br />
<br />
Skin – access to information about the user’s skin – colors, fonts, etc.<br />
<br />
MediaCore – access to media playback information, such as supported extensions<br />
<br />
Podcasts – access to the user’s media library podcasts<br />
<br />
--><br />
<br />
== MediaCore API ==<br />
===Methods===<br />
==== IsRegisteredExtension() ====<br />
MediaCore.IsRegisteredExtension() method can be used to determine if the Winamp client is able to playback a specific format. The file extension of the asset usually indicates the format. This method is important since Winamp support for different formats is contained within plugins which may or may not exist for use.<br />
<br />
Prototype:<br />
boolean IsRegisteredExtension(ext);<br />
where:<br />
'''ext''' = (string) identifies the format to be queried for support in the form of a <br />
character string of the extension (a starting period is optional).<br />
<br />
Example:<br />
var canPlay = window.external.MediaCore.IsRegisteredExtension("mp3"); <br />
<br />
Return value:<br />
Boolean value indicating whether the format is supported.<br />
<br />
==== GetMetadata() ====<br />
MediaCore.GetMetadata() method can be used to obtain metadata about an asset. This method differs from Transport.GetMetadata() in that the asset does not have to be currently playing. It differs from PlayQueue.GetMetadata() in that it doesn't have to be present in the play queue. <br />
<br />
Prototype:<br />
string GetMetadata(url, tag);<br />
where:<br />
'''url''' = (string) containing the URL for which metadata is to be retrieved.<br />
'''tag''' = (string) the specific piece of metadata to be returned.<br />
<br />
Example:<br />
var art = window.external.MediaCore.GetMetadata(<br />
"c:\\my favs\\myfavorite.mp3","artist");<br />
<br />
Return value:<br />
A string containing the metadata requested.<br />
<br />
==== AddMetadataHook() ====<br />
MediaCore.AddMetadataHook() method can be used to add or override metadata for an asset. For example, some assets such as those that are streamed may not contain metadata. This method allows the online service to add metadata for the specified asset. Subsequent GetMetadata() methods will return this information. Online services can override the metadata present within an asset using this method. This method can be used by services that define or can obtain their own metadata for the assets they provide rather than rely on what might or might not be present in the asset itself.<br />
<br />
Prototype:<br />
string AddMetadataHook(url, tag, value);<br />
where:<br />
'''url''' = (string) containing the URL for which metadata is to be added.<br />
'''tag''' = (string) the specific metadata key for which a value will be added.<br />
'''value''' - (string) the value of the metadata key being added.<br />
<br />
Example:<br />
var rc = window.external.MediaCore.AddMetadataHook(<br />
"c:\\my favs\\myfavorite.mp3","artist","myself");<br />
<br />
Return value:<br />
A boolean value that indicates whether the request was successful.<br />
<br />
==== RemoveMetadataHook() ====<br />
MediaCore.RemoveMetadataHook() method can be used to remove metadata added through the AddMetadataHook() method. Subsequent GetMetadata() requests will return whatever metadata was available previously, if any.<br />
<br />
Prototype:<br />
string RemoveMetadataHook(url, tag);<br />
string RemoveMetadataHook(url);<br />
where:<br />
'''url''' = (string) containing the URL for which metadata is to be removed.<br />
'''tag''' = (string) the specific metadata key for which a value will be removed.<br />
<br />
If only the url parameter is provided, all metadata added with AddMetadataHook() for the specified url will be removed.<br />
<br />
Example:<br />
var rc = window.external.MediaCore.RemoveMetadataHook(<br />
"c:\\my favs\\myfavorite.mp3","artist");<br />
<br />
Return value:<br />
A boolean value that indicates whether the request was successful.<br />
<br />
== History API ==<br />
The History branch of the Media Library pane is actually a database containing information about previously played assets. The History API allows a service to search and retrieve information from this database. By specifying a query string, Winamp will return an array of objects that match the values specified in the query.<br />
<br />
===Methods===<br />
<br />
==== Query() ====<br />
Prototype:<br />
results = History.Query(queryString);<br />
where:<br />
'''queryString''' = a properly formed string to match data to be returned.<br />
<br />
Example:<br />
var results = window.external.History.Query("LASTPLAYED<[now]");<br />
<br />
Return value:<br />
An "array-like" object that contains the results of the query.<br />
<br />
Each entry of the array contains the following properties:<br />
* String filename<br />
* String title<br />
* Number length<br />
* Number playcount<br />
* Date lastplay<br />
<br />
<br />
'''Query String format:'''<br />
<field> <comparison> [value] [<logic operator> <field> <comparison> [value] [...]]<br />
<br />
<br />
'''Fields:'''<br />
{| border="1"<br />
|-<br />
! Keyword<br />
! Description<br />
|-<br />
| LASTPLAY<br />
| Date and time when this asset was last played.<br />
|-<br />
| FILENAME<br />
| Full filename (including path)<br />
|-<br />
| LENGTH<br />
| Length, in seconds (or hh:mm:ss)<br />
|-<br />
| TITLE<br />
| Title<br />
|-<br />
| PLAYCOUNT<br />
| Number of times the asset has been played. <br />
|}<br />
<br />
<br />
'''Comparison Operators:'''<br />
{| border="1"<br />
|-<br />
! Operator<br />
! Description<br />
|-<br />
| '='<br />
| String or integer equals value<br />
|-<br />
| '!='<br />
| String or integer does not equal value <br />
|-<br />
| '<'<br />
| String or integer is less than value<br />
|-<br />
| '>'<br />
| String or integer is greater than value<br />
|-<br />
| '<='<br />
| String or integer is less than or equal to value<br />
|-<br />
| '>='<br />
| String or integer is greater than or equal to value<br />
|-<br />
| HAS<br />
| String contains value<br />
|-<br />
| NOTHAS<br />
| String does not contain value<br />
|-<br />
| LIKE<br />
| String is similar to value ("the" and whitespace are ignored)<br />
|-<br />
| BEGINS<br />
| String begins with value<br />
|-<br />
| BEGINSLIKE<br />
| String begins like value<br />
|-<br />
| ENDS<br />
| String ends with value<br />
|-<br />
| ISEMPTY<br />
| (no comparison value required) TRUE if <field> is empty<br />
|-<br />
| ISNOTEMPTY<br />
| (no comparison value required) TRUE if <field> is not empty<br />
|}<br />
<br />
<br />
'''Values can be:'''<br />
*"strings with spaces" or strings_without_spaces<br />
*integers can be "32" or just 32<br />
*integers for LENGTH can be a plain integer (seconds), or mm:ss or hh:mm:ss<br />
*date/timestamps should be [datetime data], which can be either an absolute or relative time. i.e.: [3 weeks ago], [18:15], [05/30/2003], [yesterday noon], [3 days ago 5 pm], [now], [5 mn before may 30th], etc.<br />
<br />
<!--<br />
== Local Media API (test)==<br />
<br />
===TBD===<br />
<br />
<br />
The LocalMedia API allows a service to search the assets within the Local Media branch of the Media Library. By specifying a query string, Winamp will return an array of objects that match the values specified in the query.<br />
<br />
===Methods===<br />
Prototype:<br />
xx<br />
<br />
Example:<br />
xx<br />
<br />
Return value:<br />
returns an array of objects that match the specified criteria of the query string.<br />
<br />
'''Query String format:'''<br />
<field> <comparison> [value] [<logic operator> <field> <comparison> [value] [...]]<br />
<br />
'''Comparison Operators:'''<br />
{| border="1"<br />
|-<br />
! Keyword<br />
! Description<br />
|-<br />
| TYPE<br />
| 0 for audio files, 1 for video files<br />
|-<br />
| FILENAME<br />
| Full filename (including path)<br />
|-<br />
| LENGTH<br />
| Length, in seconds (or hh:mm:ss)<br />
|-<br />
| ARTIST<br />
| Artist<br />
|-<br />
| ALBUM<br />
| Album<br />
|-<br />
| ALBUMARTIST<br />
| Album Artist<br />
|-<br />
| TITLE<br />
| Title<br />
|-<br />
| TRACKNO<br />
| Track number of file<br />
|-<br />
| GENRE<br />
| Genre<br />
|-<br />
| YEAR<br />
| Year<br />
|-<br />
| COMMENT<br />
| Comment<br />
|-<br />
| COMPOSER<br />
| Composer<br />
|-<br />
| DISC<br />
| Disc number of a CD set<br />
|-<br />
| FILESIZE<br />
| File size, in kilobytes<br />
|-<br />
| FILETIME<br />
| Last known file date/time on disk<br />
|-<br />
| FOLDER<br />
| Containing folder<br />
|-<br />
| LASTUPD<br />
| Date/time of file imported to library or modified in library<br />
|-<br />
| LASTPLAY<br />
| Date/time of last play<br />
|-<br />
| RATING<br />
| Rating value (1-5, or 0 or empty for unrated)<br />
|-<br />
| PLAYCOUNT<br />
| Number of plays<br />
|-<br />
| PUBLISHER<br />
| Publisher or record label<br />
|-<br />
| REPLAYGAIN_ALBUM_GAIN<br />
| ReplayGain Album Gain<br />
|-<br />
| REPLAYGAIN_TRACK_GAIN<br />
| ReplayGain Track Gain<br />
|-<br />
| BITRATE<br />
| Bitrate (in KBPS)<br />
|-<br />
| TRACKS<br />
| Total number of tracks on the disc<br />
|-<br />
| DISCS<br />
| Total number of discs in the set<br />
|-<br />
| ISPODCAST<br />
| 1 for a podcast episode, 0 otherwise<br />
|-<br />
| PODCASTCHANNEL<br />
| The name of the channel for a podcast<br />
|-<br />
| PODCASTPUBDATE<br />
| Date/time when the podcast was published<br />
|}<br />
<br />
<br />
'''Field Names:'''<br />
{| border="1"<br />
|-<br />
! Comparison Operator<br />
! Description<br />
|-<br />
| '='<br />
| String or integer equals value<br />
|-<br />
| '!='<br />
| String or integer does not equal value <br />
|-<br />
| '<'<br />
| String or integer is less than value<br />
|-<br />
| '>'<br />
| String or integer is greater than value<br />
|-<br />
| '<='<br />
| String or integer is less than or equal to value<br />
|-<br />
| '>='<br />
| String or integer is greater than or equal to value<br />
|-<br />
| HAS<br />
| String contains value<br />
|-<br />
| NOTHAS<br />
| String does not contain value<br />
|-<br />
| LIKE<br />
| String is similar to value ("the" and whitespace are ignored)<br />
|-<br />
| BEGINS<br />
| String begins with value<br />
|-<br />
| BEGINSLIKE<br />
| String begins like value<br />
|-<br />
| ENDS<br />
| String ends with value<br />
|-<br />
| ISEMPTY<br />
| (no comparison value required) TRUE if <field> is empty<br />
|-<br />
| ISNOTEMPTY<br />
| (no comparison value required) TRUE if <field> is not empty<br />
|}<br />
<br />
'''Values can be:'''<br />
*"strings with spaces" or strings_without_spaces<br />
*integers can be "32" or just 32<br />
*integers for LENGTH can be a plain integer (seconds), or mm:ss or hh:mm:ss<br />
*date/timestamps should be [datetime data], which can be either an absolute or relative time. i.e.: [3 weeks ago], [18:15], [05/30/2003], [yesterday noon], [3 days ago 5 pm], [now], [5 mn before may 30th], etc.<br />
--><br />
<br />
== Application API ==<br />
===Methods===<br />
<br />
====LaunchURL()====<br />
The Application.LaunchURL() method launches a URL in the bento browser<br />
or default browser. The default browser is launched if force_external = true or in skins that don't define a browser.<br />
<br />
Prototype:<br />
boolean LaunchURL(url, force_external);<br />
where:<br />
'''url''' = (string) The url to open in the browser<br />
'''force_external''' = (boolean) will force the url to be displayed in a browser<br />
outside of the Winamp client.<br />
<br />
Example:<br />
<br />
var rc = LaunchURL(<nowiki>"http://www.winamp.com"</nowiki>, true); <br />
<br />
Return value:<br />
A boolean value indicating whether the request was successful.<br />
<br />
===Properties===<br />
====int version (read only)==== <br />
The version property returns the version number of the browser control within the Winamp client as an integer, e.g. 555 for 5.55, 560 for 5.6<br />
====string versionstring (read only)====<br />
The versionstring property returns the version number of the browser control within the Winamp client as a string, e.g. "5.55" for 5.55<br />
====string language (read only) ====<br />
Language identifier from the currently installed language pack. Follows ISO 639-1 two letter language codes<br />
<br />
====string languagepack (read only) ====<br />
Language pack identifier from the currently installed language pack. follows the form<br />
lc-CC<br />
where lc is the two letter ISO 639-1 language code<br />
and CC is the two letter ISO 3166 country code.<br />
<br />
Note: do not count on the country code being the same as the user's current location.<br />
<!--<br />
== Security API ==<br />
<br />
===Methods===<br />
====GetActionAuthorization()====<br />
<br />
Prototype:<br />
GetActionAuthorization(group, action);<br />
where:<br />
'''group''' = (string) a group of related methods, i.e. the API name.<br />
'''action''' = (string) a specific method within a group.<br />
<br />
Example:<br />
var auth = window.external.Security.GetActionAuthorization("application", <br />
"launchurl");<br />
<br />
Return value: an integer representing the following results<br />
<br />
*ACTION_UNDEFINED = -1,<br />
*ACTION_DISALLOWED = 0,<br />
*ACTION_PROMPT = 1,<br />
*ACTION_ALLOWED = 2,<br />
<br />
--><br />
<br />
== Skin API ==<br />
<br />
The skin color API is a bit of a challenge. This API reflects some the idiosyncrasies of the underlying skinning system. "Classic" skins define a palette of 24 colors for the skin and an additional 6 colors for the playlist editor. "Modern" skins define these as well as any number of other colors retrievable by name (e.g. wasabi.tree.text for the text color on tree views). A website relying on any of these extra "named" colors should be careful to implement a fallback color based on the classic palette, as no named colors exist in classic skins!<br />
<br />
===Methods===<br />
====GetClassicColor()====<br />
The Skin.GetClassicColor() method is used to retrieve color information regarding different Skin UI elements.<br />
<br />
Prototype:<br />
GetClassicColor(classiccolornumber);<br />
where:<br />
'''classiccolornumber''' = (integer) A number in the range 0-23 identifying the Skin's UI element <br />
for which the color should be returned.<br />
<br />
Example:<br />
var wndBgColor = window.external.Skin.GetClassicColor(2);<br />
<br />
Return value:<br />
The HTML color constant used for the specified Skin UI element.<br />
<br />
====Classic Color Numbers====<br />
{| border="1"<br />
|-<br />
! Number<br />
! Description<br />
|-<br />
| 0 <br />
| Item Background<br />
|-<br />
| 1 <br />
| Item Foreground<br />
|-<br />
| 2 <br />
| Window Background<br />
|-<br />
| 3 <br />
| Button Foreground<br />
|-<br />
| 4 <br />
| Window Foreground<br />
|-<br />
| 5 <br />
| Hilite<br />
|-<br />
| 6 <br />
| Selection<br />
|-<br />
| 7 <br />
| List Header Background<br />
|-<br />
| 8 <br />
| List Header Text<br />
|-<br />
| 9 <br />
| List Header Frame Top<br />
|-<br />
| 10 <br />
| List Header Frame Middle<br />
|-<br />
| 11 <br />
| List Header Frame Bottom<br />
|-<br />
| 12 <br />
| List Header Empty Background<br />
|-<br />
| 13 <br />
| Scrollbar Foreground<br />
|-<br />
| 14 <br />
| Scrollbar Background<br />
|-<br />
| 15 <br />
| Scrollbar Inverse Foreground<br />
|-<br />
| 16 <br />
| Scrollbar Inverse Background<br />
|-<br />
| 17 <br />
| Scrollbar Dead Area<br />
|-<br />
| 18 <br />
| Selection Bar Foreground<br />
|-<br />
| 19 <br />
| Selection Bar Background<br />
|-<br />
| 20 <br />
| Inactive Selection Bar Foreground<br />
|-<br />
| 21 <br />
| Inactive Selection Bar Background<br />
|-<br />
| 22 <br />
| Alternating Item Background<br />
|-<br />
| 23 <br />
| Alternating Item Foreground<br />
|}<br />
<br />
====GetPlaylistColor()====<br />
The Skin.GetPlaylistColor() method is used to retrieve color information regarding different Playlist UI elements.<br />
<br />
Prototype:<br />
GetPlaylistColor(playlistcolornumber);<br />
where:<br />
'''playlistcolornumber''' = (integer) a number in the range 0-5 identifying the Playlist's UI <br />
element for which the color should be returned.<br />
<br />
Example:<br />
var normalBgColor = window.external.Skin.GetPlaylistColor(2);<br />
<br />
Return value:<br />
The HTML color constant used for the specified Playlist UI element.<br />
<br />
====Playlist Color Numbers====<br />
{| border="1"<br />
|-<br />
! Number<br />
! Description<br />
|-<br />
| 0 <br />
| Normal<br />
|-<br />
| 1 <br />
| Current<br />
|-<br />
| 2 <br />
| Normal Background<br />
|-<br />
| 3 <br />
| Selected Background<br />
|-<br />
| 4 <br />
| Video Window Status Bar Foreground<br />
|-<br />
| 5 <br />
| Video Window Status Bar Background<br />
|}<br />
<br />
====GetSkinColor()====<br />
The Skin.GetSkinColor() method is used to retrieve color information regarding different Playlist UI elements.<br />
<br />
Prototype:<br />
GetSkinColor(skincolorname);<br />
where:<br />
'''skincolorname''' = (string) identifying the Skin's UI <br />
element for which the color should be returned.<br />
<br />
Example:<br />
var buttonTextColor = window.external.Skin.GetSkinColor("wasabi.button.text");<br />
<br />
Return value:<br />
The HTML color constant used for the specified Playlist UI element.<br />
<br />
====Skin Color Names====<br />
{| border="1"<br />
|-<br />
! Name<br />
! Description<br />
|-<br />
|"wasabi.list.item.selected.fg"<br />
|Selected item text foreground color<br />
|-<br />
|"wasabi.list.column.separator" <br />
|Color of line between columns<br />
|-<br />
|'''Item Lists, Lists with playable items'''<br />
|<br />
|-<br />
|"wasabi.itemlist.outline.current" <br />
|Currently playing outline color<br />
|-<br />
|"wasabi.itemlist.outline.focus" <br />
|Focused item dashed outline color<br />
|-<br />
|"wasabi.itemlist.selborder" <br />
|<br />
|-<br />
|'''Message box'''<br />
|<br />
|-<br />
|"wasabi.msgBox.background" <br />
|Messagebox background color<br />
|-<br />
|"wasabi.textBar.text" <br />
|Text object & message box text color<br />
|-<br />
|"wasabi.textBar.background" <br />
|Text object & message box text background color<br />
|-<br />
|'''Buttons'''<br />
|<br />
|-<br />
|"wasabi.button.text" <br />
|Buttons text color<br />
|-<br />
|"wasabi.button.hiliteText" <br />
|Buttons hilite text color, used by tab windows<br />
|-<br />
|"wasabi.button.dimmedText" <br />
|Buttons dimmed text color, when disabled<br />
|-<br />
|'''Popup menus'''<br />
|<br />
|-<br />
|"wasabi.popup.text" <br />
|Menu items text color<br />
|-<br />
|"wasabi.popup.hiliteText" <br />
|Hilited item text color<br />
|-<br />
|"wasabi.popup.dimmedText" <br />
|Disabled item text color<br />
|-<br />
|'''Components'''<br />
|<br />
|-<br />
|"wasabi.component.title.foreground" <br />
|Old title bar text color when using TTF<br />
|-<br />
|"wasabi.component.title.border" <br />
|Old title bar text outline when using TTF<br />
|-<br />
|'''Labeled Windows'''<br />
|<br />
|-<br />
|"wasabi.labelwnd.foreground" <br />
|Text foreground color<br />
|-<br />
|"wasabi.labelwnd.background" <br />
|Text drop shadow color<br />
|-<br />
|'''Edit Windows'''<br />
|<br />
|-<br />
|"wasabi.edit.selection" <br />
|Selected text<br />
|-<br />
|"wasabi.edit.text" <br />
|Text<br />
|-<br />
|"wasabi.edit.background" <br />
|Text background<br />
|-<br />
|<br />
|<br />
|-<br />
| "wasabi.text.color" <br />
|<br />
|-<br />
| "wasabi.text.color.inverse" <br />
|<br />
|}<br />
<br />
===Properties===<br />
====string name (test)====<br />
The Skin.name property gives access to the name of skin currently in use. Changing this value will change the skin displayed for the player.<br />
<br />
====string font (read only)====<br />
The Skin.font property provides the font name currently used in the player.<br />
<br />
====string fontsize (read only)====<br />
The Skin.fontsize property provides the size of the font currently used in the player.<br />
<br />
== Metadata tag names ==<br />
<br />
When retrieving metadata through Winamp, a freeform string is passed. The popular file formats (MP3, WMA, FLAC, M4A) will respond uniformly to a common base of strings. However, each file format is idiosyncratic in how metadata is stored. Some file types will respond to additional strings which are not documented here.<br />
<br />
Remember that the metadata is only as good as the tagging in the file itself. A poorly tagged track will return poor metadata.<br />
<br />
Common metadata tags<br />
bitrate<br />
length<br />
type<br />
title<br />
artist<br />
albumartist<br />
album<br />
genre<br />
year<br />
disc<br />
publisher<br />
comment<br />
track<br />
composer<br />
conductor</div>Culixhttp://wiki.shoutcast.com/wiki/XML_ReferenceXML Reference2010-11-30T03:29:10Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Pjn123</p>
<hr />
<div>The XML Reference is divided into the following sections:<br />
<br />
== '''[[XML Elements]]''' ==<br />
Use this to define the pictures, colors & fonts you want to use in your skin.<br />
<br />
== '''[[XML GUI Objects]]''' ==<br />
Here you'll find all of the GUI Objects that you can use in your skin.<br />
<br />
== '''[[XML Containing objects]]''' ==<br />
The containing objects help organize your skin. You'll need a container and a layout to display a skin.<br />
Basically you'll place all your GUI Objects in one of these.</div>Culixhttp://wiki.shoutcast.com/wiki/MilkDrop_Preset_AuthoringMilkDrop Preset Authoring2010-11-30T03:29:06Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>== MILKDROP preset authoring guide ==<br />
<br />
Note that there is another, quite comprehensive, Preset Authoring Guide available on the web at http://www.milkdrop.co.uk/, which is continually updated and expanded through the hard work of a few dedicated preset authors. Whereas this guide (the one you are currently viewing) gives the bare technical specifications for writing your own presets, the guide at milkdrop.co.uk 'starts at the beginning' and walks you through all of the mathematics and subtleties of 'rolling your own', explaining things in great detail. The guide at milkdrop.co.uk is very highly recommended to anyone who wishes to learn more about creating their own presets. Also, there is a [[Pixel shader guide]] on this wiki.<br />
<br />
== About Presets ==<br />
<br />
When you watch MilkDrop, you are watching a series of Presets. Each one has its own look and feel, draws the sound waves in a particular way, and has certain motions to it. After some time, you will see a short blend transition, and then you will be watching a new preset. <br />
<br />
A single 'preset' is a collection of parameters that tell MilkDrop how to draw the wave, how to warp the image around, and so on. MilkDrop ships with over 100 built-in presets, each one having a distinct look and feel to it. <br />
<br />
Using MilkDrop's built-in "preset-editing menu" (the M key), you can edit presets on the fly, on-screen, from within the program. You can make slight adjustments to existing presets, then save over them; or you can change lots of things, so the preset doesn't look anything like the original, and then save it under a new name. You can even write insane new mathematical equations, of your own imagination, into your preset files and come up with things that MilkDrop has never done before!<br />
<br />
Each preset is saved as a file with the ".milk" extension, so you can easily send them to your friends or post them on the web. You can also go to http://www.nullsoft.com/free/milkdrop and then jump to the "preset sharing forum" to see what other people have come up with, or post your own cool, new presets. milkdrop.co.uk/ is another great place to download collections of presets made by others like yourself.<br />
<br />
== Preset Authoring - Basic ==<br />
<br />
You can edit the properties of the current preset by hitting 'M', which brings up the "preset-editing menu". From this menu you can use the up and down arrow keys to select an item. Press the RIGHT arrow key to move forward through the menu and select the item (note: you can also hit SPACE or RETURN to do this); ***press the LEFT arrow key to go back to the previous menu.*** <br />
<br />
Pressing 'M' while the menu is already showing will hide the menu; pressing ESCAPE will do the same thing. Press 'M' again to bring the menu back. <br />
<br />
Once you've reached an item on the menu whose value can be edited, use the UP and DOWN arrow keys to increase or decrease its value, respectively. Changes will register immediately. Use PAGE UP and PAGE DOWN to increase the value more quickly. Hold down SHIFT and use the UP/DOWN arrow keys to change the value very slowly. Hit RETURN To keep the new value, or ESC to abort the change.<br />
<br />
If the item you're editing is a text string, you can use the arrow keys to move around. The Insert key can be used to toggle between insert and overtype modes. You can hold shift and use the arrow keys (home, end, left, right) to make a selection, which will be identified by brackets []. You can then use CTRL-C or CTRL-X to copy or cut text. CTRL-P pastes. When finished editing, hit RETURN To keep the new string, or ESC to abort the change.<br />
<br />
You'll want to get into the habit of using SCROLL LOCK whenever you're making changes to a preset that you intend to save; <br />
otherwise, MilkDrop is sure to move you along to a new (random) preset, over time. When the menus are showing, the preset is<br />
automatically temporarily locked, but BE CAREFUL - if you're not also using SCROLL LOCK, then 0.1 seconds after you hide the menu<br />
to take a look at your new masterpiece, MilkDrop might load a random new preset on you, and you'd lose your changes! And you <br />
might then ask me: "how large is large?" And I will tell you: "thirty."<br />
<br />
There are also some hotkeys that will allow you to change certain<br />
common parameters to the current preset. These are listed below.<br />
<br />
MOTION<br />
i/I - zoom in/out<br />
[ / ] - push motion to the left/right (dx)<br />
{ / } - push motion up/down (dy)<br />
< / > - rotate left/right (rot)<br />
o/O - shrink/grow the amplitude of the warp effect<br />
<br />
WAVEFORM<br />
W - cycle through waveforms<br />
j/J - scale waveform down/up<br />
e/E - make the waveform more transparent/more solid<br />
<br />
BRIGHTNESS **<br />
g/G - decrease, increase gamma (brightness) **<br />
<br />
VIDEO ECHO effect **<br />
q/Q - scale 2nd graphics layer down/up **<br />
F - flip 2nd graphics layer (cycles through 4 fixed orientations) **<br />
<br />
** these keys only have an effect if you are running a <br />
MilkDrop 1-era preset. In MilkDrop 2-era presets,<br />
these values are embedded in the shader, so you need<br />
to go into the composite shader and tweak the code.<br />
<br />
== Preset Authoring - Advanced ==<br />
<br />
This section describes how to use the 'per-frame' and 'per-vertex' equations to develop unique new presets.<br />
<br />
<br />
<br />
=== PER-FRAME EQUATIONS ===<br />
<br />
When you hit 'm' to show the preset-editing menu, several items<br />
show up. If you explore the sub-menus, you'll see that<br />
all of the properties that make up the preset you're currently<br />
viewing are there. The values you can specify here (such as<br />
zoom amount, rotation amount, wave color, etc.) are all static<br />
values, meaning that they don't change in time. For example, <br />
take the 'zoom amount' option under the 'motion' submenu. <br />
If this value is 1.0, there is no zoom. If the value is 1.01, <br />
the image zooms in 1% every frame. If the value is 1.10, the <br />
image zooms in 10% every frame. If the value is 0.9, the image <br />
zooms out 10% every frame; and so on.<br />
<br />
However, presets get far more interesting if you can take these <br />
parameters (such as the zoom amount) and animate them (make them <br />
change over time). For example, if you could take the 'zoom <br />
amount' parameter and make it oscillate (vary) between 0.9 and <br />
1.1 over time, the image would cyclically zoom in and out, in <br />
time.<br />
<br />
You can do this - by writing 'per-frame' and 'per-vertex' <br />
equations. Let's start with 'per-frame' equations. These are<br />
executed once per frame. So, if you were to type the following<br />
equation in:<br />
<br />
zoom = zoom + 0.1*sin(time);<br />
<br />
...then the zoom amount would oscillate between 0.9 and 1.1<br />
over time. (Recall from your geometry classes that sin()<br />
returns a value between -1 and 1.) The equation says: "take<br />
the static value of 'zoom', then replace it with that value,<br />
plus some variation." This particular equation would oscillate <br />
(cycle) every 6.28 seconds, since the sin() function's <br />
period is 6.28 (PI*2) seconds. If you wanted it to make it <br />
cycle every 2 seconds, you could use: <br />
<br />
zoom = zoom + 0.1*sin(time*3.14);<br />
<br />
Now, let's say you wanted to make the color of the waveform<br />
(sound wave) that gets plotted on the screen vary through time.<br />
The color is defined by three values, one for each of the main<br />
color components (red, green, and blue), each in the range 0 to 1<br />
(0 is dark, 1 is full intensity). You could use something like this:<br />
<br />
wave_r = wave_r + 0.5*sin(time*1.13);<br />
wave_g = wave_g + 0.5*sin(time*1.23);<br />
wave_b = wave_b + 0.5*sin(time*1.33);<br />
<br />
It's nice to stagger the frequencies (1.13, 1.23, and 1.33) of<br />
the sine functions for the red, green, and blue color components<br />
of the wave so that they cycle at different rates, to avoid them<br />
always being all the same (which would create a greyscale wave).<br />
<br />
Here is a full list of the variables available for writing per-frame <br />
equations:<br />
<br />
NAME WRITABLE? RANGE DESCRIPTION<br />
---- --------- ----- ----------- <br />
zoom yes >0 controls inward/outward motion. 0.9=zoom out 10% per frame, 1.0=no zoom, 1.1=zoom in 10%<br />
zoomexp yes >0 controls the curvature of the zoom; 1=normal<br />
rot yes controls the amount of rotation. 0=none, 0.1=slightly right, -0.1=slightly clockwise, 0.1=CCW<br />
warp yes >0 controls the magnitude of the warping; 0=none, 1=normal, 2=major warping...<br />
cx yes 0..1 controls where the center of rotation and stretching is, horizontally. 0=left, 0.5=center, 1=right<br />
cy yes 0..1 controls where the center of rotation and stretching is, vertically. 0=top, 0.5=center, 1=bottom<br />
dx yes controls amount of constant horizontal motion; -0.01 = move left 1% per frame, 0=none, 0.01 = move right 1%<br />
dy yes controls amount of constant vertical motion; -0.01 = move up 1% per frame, 0=none, 0.01 = move down 1%<br />
sx yes >0 controls amount of constant horizontal stretching; 0.99=shrink 1%, 1=normal, 1.01=stretch 1% <br />
sy yes >0 controls amount of constant vertical stretching; 0.99=shrink 1%, 1=normal, 1.01=stretch 1% <br />
wave_mode yes 0,1,2,3,4,5,6,7 controls which of the 8 types of waveform is drawn<br />
wave_x yes 0..1 position of the waveform: 0 = far left edge of screen, 0.5 = center, 1 = far right<br />
wave_y yes 0..1 position of the waveform: 0 = very bottom of screen, 0.5 = center, 1 = top<br />
wave_r yes 0..1 amount of red color in the wave (0..1),<br />
wave_g yes 0..1 amount of green color in the wave (0..1) <br />
wave_b yes 0..1 amount of blue color in the wave (0..1) <br />
wave_a yes 0..1 opacity of the wave (0..1) [0=transparent, 1=opaque]<br />
wave_mystery yes -1..1 what this parameter does is a mystery. (honestly, though, this value does different things for each waveform; for example, it could control angle at which the waveform was drawn.)<br />
wave_usedots yes 0/1 if 1, the waveform is drawn as dots (instead of lines)<br />
wave_thick yes 0/1 if 1, the waveform's lines (or dots) are drawn with double thickness<br />
wave_additive yes 0/1 if 1, the wave is drawn additively, saturating the image at white<br />
wave_brighten yes 0/1 if 1, all 3 r/g/b colors will be scaled up until at least one reaches 1.0<br />
ob_size yes 0..0.5 thickness of the outer border drawn at the edges of the screen every frame<br />
ob_r yes 0..1 amount of red color in the outer border<br />
ob_g yes 0..1 amount of green color in the outer border<br />
ob_b yes 0..1 amount of blue color in the outer border<br />
ob_a yes 0..1 opacity of the outer border (0=transparent, 1=opaque)<br />
ib_size yes 0..0.5 thickness of the inner border drawn at the edges of the screen every frame<br />
ib_r yes 0..1 amount of red color in the inner border <br />
ib_g yes 0..1 amount of green color in the inner border <br />
ib_b yes 0..1 amount of blue color in the inner border <br />
ib_a yes 0..1 opacity of the inner border (0=transparent, 1=opaque) <br />
mv_r yes 0..1 amount of red color in the motion vectors<br />
mv_g yes 0..1 amount of green color in the motion vectors<br />
mv_b yes 0..1 amount of blue color in the motion vectors<br />
mv_a yes 0..1 opacity of the motion vectors (0=transparent, 1=opaque) <br />
mv_x yes 0..64 the number of motion vectors in the X direction<br />
mv_y yes 0..48 the number of motion vectors in the Y direction<br />
mv_l yes 0..5 the length of the motion vectors (0=no trail, 1=normal, 2=double...)<br />
mv_dx yes -1..1 horizontal placement offset of the motion vectors<br />
mv_dy yes -1..1 vertical placement offset of the motion vectors<br />
decay yes 0..1 controls the eventual fade to black; 1=no fade, 0.9=strong fade, 0.98=recommended<br />
gamma yes >0 controls display brightness; 1=normal, 2=double, 3=triple, etc.<br />
echo_zoom yes >0 controls the size of the second graphics layer<br />
echo_alpha yes >0 controls the opacity of the second graphics layer; 0=transparent (off), 0.5=half-mix, 1=opaque<br />
echo_orient yes 0,1,2,3 selects an orientation for the second graphics layer. 0=normal, 1=flip on x, 2=flip on y, 3=flip on both<br />
darken_center yes 0/1 if 1, help keeps the image from getting too bright by continually dimming the center point<br />
wrap yes 0/1 sets whether or not screen elements can drift off of one side and onto the other<br />
invert yes 0/1 inverts the colors in the image<br />
brighten yes 0/1 brightens the darker parts of the image (non-linear; square root filter)<br />
darken yes 0/1 darkens the brighter parts of the image (non-linear; squaring filter)<br />
solarize yes 0/1 emphasizes mid-range colors<br />
monitor yes any set this value for debugging your preset code; if you hit the 'N' key, <br />
the value of 'monitor' will be posted in the upper-right corner of milkdrop.<br />
for example, setting "monitor = q3;" would let you keep an eye on q3's value.<br />
<br />
time NO >0 retrieves the current time, in seconds, since MilkDrop started running<br />
fps NO >0 retrieves the current framerate, in frames per second.<br />
frame NO retrieves the number of frames of animation elapsed since the program started<br />
progress NO 0..1 progress through the current preset; if preset was just loaded, this is closer to 0; if preset is about to end, this is closer to 1.<br />
-note that if Scroll Lock is on, 'progress' will freeze!<br />
<br />
bass NO >0 retrieves the current amount of bass. 1 is normal; below ~0.7 is quiet; above ~1.3 is loud bass<br />
mid NO >0 -same, but for mids (middle frequencies)<br />
treb NO >0 -same, but for treble (high) frequencies<br />
bass_att NO >0 retrieves an attenuated reading on the bass, meaning that it is damped in time and doesn't change so rapidly.<br />
mid_att NO >0 -same, but for mids (middle frequencies)<br />
treb_att NO >0 -same, but for treble (high) frequencies<br />
<br />
meshx NO 8-128 tells you the user's mesh size in the X direction. always an integer value.<br />
meshy NO 6-96 tells you the user's mesh size in the Y direction. always an integer value.<br />
pixelsx NO 16-4096 width of the viz window, in pixels. If Canvas Stretch is on, this is the pre-stretched size. (same as "texsize.x" for shaders)<br />
pixelsy NO 16-4096 height of the viz window, in pixels. If Canvas Stretch is on, this is the pre-stretched size. (same as "texsize.y" for shaders)<br />
aspectx NO >0 multiply an x-coordinate by this to make the preset look the same at any aspect (window height:width) ratio.<br />
-value: if widescreen, 1; if window is tall, h/w.<br />
aspecty NO >0 multiply a y-coordinate by this to make the preset look the same at any aspect (window height:width) ratio.<br />
-value: if widescreen, w/h; if window is tall, 1.<br />
<br />
blur1_min yes 0..1 Normally these are set to 0 (min) and 1 (max).<br />
blur2_min yes 0..1 You can clamp the values in the blur texture to a tighter<br />
blur3_min yes 0..1 range, though. <br />
blur1_max yes 0..1 This will increase the precision in the blur textures,<br />
blur2_max yes 0..1 but you run the risk of clamping values to your min/max.<br />
blur3_max yes 0..1 If you use the GetBlur1() .. GetBlur3() functions to sample<br />
blur1_edge_darken yes 0..1 the blur texture, they will automatically "unpack" the<br />
values for you in the end!<br />
<br />
q1 yes any } Used to carry values along a chain <br />
q2 yes any } from the preset init code, <br />
q3 yes any } to the preset per-frame code, then on <br />
q4 yes any } to the preset per-vertex code; <br />
q5 yes any } or to the custom shape per-frame code, <br />
q6 yes any } or to the custom wave per-frame code, <br />
q7 yes any } then to the custom wave per-vertex code; <br />
... } or to the [pixel] shader code. <br />
q31 yes any } Click here to see a diagram for the Q vars.<br />
q32 yes any } <br />
<br />
<br />
Some of the variables are read-only, meaning that you shouldn't change<br />
their values them through the equations. You can; it won't stop you; <br />
but the results are unpredictable.<br />
<br />
You can also make up to 30 of your own variables. For example:<br />
<br />
my_volume = (bass + mid + treb)/3;<br />
zoom = zoom + 0.1*(my_volume - 1);<br />
<br />
This would make the zoom amount increase when the music is loud,<br />
and decrease when the music is quiet. <br />
<br />
HOWEVER, custom variables do not carry over from per-frame equations<br />
to per-vertex equations; if you set a custom variable's value in the<br />
per-frame equations, and try to read it in the per-vertex equations,<br />
you will not get the correct value. Instead, you have to "bridge the<br />
gap" using 32 special variables: q1 through q32. This is usually only<br />
used when you want to precompute some custom values in the per-frame <br />
equations for later use in the per-vertex equations (or for use in<br />
the pixel shaders). For a good example of this, see the 'dynamic swirls' <br />
preset. See below for more information on q1-q32.<br />
<br />
=== PER-VERTEX EQUATIONS ===<br />
<br />
So far we've discussed only how to change parameters based on<br />
time. What if you wanted to also vary a parameter, such as the<br />
zoom amount, in different ways, for different locations on the<br />
screen? For example, normally, the result of the 'zoom' parameter<br />
is to just do a flat zoom. This doesn't look very realistic, <br />
because you don't see any perspective in the zoom. It would be<br />
better if we could give a unique zoom amount to each pixel on <br />
the screen; we could make the pixels far away from the center<br />
zoom more, and this would give it more perspective. In order<br />
to do this, we use "per-vertex" equations, instead of per-frame<br />
equations.<br />
<br />
The code for this per-vertex equation is simple:<br />
<br />
zoom = zoom + rad*0.1;<br />
<br />
Where 'rad' is the radius of the pixel if it were cast into<br />
polar coordinates; from another perspective, 'rad' is the distance <br />
of the pixel from the center of the screen. 'rad is zero at the<br />
center, and 1 at the corners. So if we run the above code,<br />
the image will be zoomed into 10% more at the edges of the screen<br />
than at the center.<br />
<br />
The per-vertex equations are really just like the per-frame equations,<br />
except for a variables. The following variables are available<br />
exclusively to per-vertex equations (and not to per-frame equations):<br />
<br />
NAME WRITEABLE? RANGE DESCRIPTION<br />
---- ---------- ----- ----------- <br />
x NO 0..1 retrieves the x-position of the current pixel. At the very left edge of the screen this would be 0; in the middle, 0.5; and at the right, 1. <br />
y NO 0..1 retrieves the y-position of the current pixel. At the very top edge of the screen this would be 0; in the middle, 0.5; and at the bottom, 1. <br />
rad NO 0..1 retrives the distance of the pixel from the center of the screen. At the center of the screen this will be zero, and at the corners, 1. <br />
(The middle of the edges will be 0.707 (half of the square root of 2).<br />
ang NO 0..6.28 retrieves the angle of the current pixel, with respect to the center of the screen. <br />
If the point is to the right of the center, this is zero; above it, it is PI/2 (1.57); to the left, it is PI (3.14); and below, it is 4.71 (PI*3/2). <br />
If it is just a dab below being directly to the right of the center of the screen, the value will approach 6.28 (PI*2). <br />
(note: this is simply the arctangent of y over x, precomputed for you.)<br />
<br />
zoom yes >0 controls inward/outward motion. 0.9=zoom out 10% per frame, 1.0=no zoom, 1.1=zoom in 10%<br />
zoomexp yes >0 controls the curvature of the zoom; 1=normal<br />
rot yes controls the amount of rotation. 0=none, 0.1=slightly right, -0.1=slightly clockwise, 0.1=CCW<br />
warp yes >0 controls the magnitude of the warping; 0=none, 1=normal, 2=major warping...<br />
cx yes 0..1 controls where the center of rotation and stretching is, horizontally. 0=left, 0.5=center, 1=right<br />
cy yes 0..1 controls where the center of rotation and stretching is, vertically. 0=top, 0.5=center, 1=bottom<br />
dx yes controls amount of constant horizontal motion; -0.01 = move left 1% per frame, 0=none, 0.01 = move right 1%<br />
dy yes controls amount of constant vertical motion; -0.01 = move up 1% per frame, 0=none, 0.01 = move down 1%<br />
sx yes >0 controls amount of constant horizontal stretching; 0.99=shrink 1%, 1=normal, 1.01=stretch 1% <br />
sy yes >0 controls amount of constant vertical stretching; 0.99=shrink 1%, 1=normal, 1.01=stretch 1% <br />
<br />
time NO >0 retrieves the current time, in seconds, since MilkDrop started running<br />
fps NO >0 retrieves the current framerate, in frames per second.<br />
frame NO retrieves the number of frames of animation elapsed since the program started<br />
progress NO 0..1 progress through the current preset; if preset was just loaded, this is closer to 0; if preset is about to end, this is closer to 1.<br />
-note that if Scroll Lock is on, 'progress' will freeze!<br />
<br />
bass NO >0 retrieves the current amount of bass. 1 is normal; below ~0.7 is quiet; above ~1.3 is loud bass<br />
mid NO >0 -same, but for mids (middle frequencies)<br />
treb NO >0 -same, but for treble (high) frequencies<br />
bass_att NO >0 retrieves an attenuated reading on the bass, meaning that it is damped in time and doesn't change so rapidly.<br />
mid_att NO >0 -same, but for mids (middle frequencies)<br />
treb_att NO >0 -same, but for treble (high) frequencies<br />
<br />
meshx NO 8-192 tells you the user's mesh size in the X direction. always an integer value.<br />
meshy NO 6-144 tells you the user's mesh size in the Y direction. always an integer value.<br />
pixelsx NO 16-4096 width of the viz window, in pixels. If Canvas Stretch is on, this is the pre-stretched size. (same as "texsize.x" for shaders)<br />
pixelsy NO 16-4096 height of the viz window, in pixels. If Canvas Stretch is on, this is the pre-stretched size. (same as "texsize.y" for shaders)<br />
aspectx NO >0 multiply an x-coordinate by this to make the preset look the same at any aspect (window height:width) ratio.<br />
-value: if widescreen, 1; if window is tall, h/w.<br />
aspecty NO >0 multiply a y-coordinate by this to make the preset look the same at any aspect (window height:width) ratio.<br />
-value: if widescreen, w/h; if window is tall, 1.<br />
<br />
q1 yes any } Used to carry values along a chain <br />
q2 yes any } from the preset init code, <br />
q3 yes any } to the preset per-frame code, then on <br />
q4 yes any } to the preset per-vertex code; <br />
q5 yes any } or to the custom shape per-frame code, <br />
q6 yes any } or to the custom wave per-frame code, <br />
q7 yes any } then to the custom wave per-vertex code;<br />
... } or to the [pixel] shader code. <br />
q31 yes any } Click here to see a diagram for the Q vars.<br />
q32 yes any } <br />
<br />
<br />
The main reason for distinction between per-frame and per-vertex equations<br />
is simple: SPEED. If you have a per-vertex equation that doesn't make use<br />
of the x, y, rad, or ang variables, then there's no reason for it to be<br />
executed per-vertex; it could be executed once per frame, and the result<br />
would be the same. So, here's a maxim to write on the wall:<br />
<br />
"If a per-vertex equation doesn't use at least one of the variables<br />
{ x, y, rad, ang }, then it should be actually be a per-frame <br />
equation."<br />
<br />
You might be wondering how on earth all these formulas could be computed<br />
for every pixel on the screen, every frame, and still yield a high frame<br />
rate. Well, that's the magic of the hamster. And the fact that it really<br />
does the processing only at certain points on the screen, then interpolates<br />
the results across the space between the points. In the config panel,<br />
the "mesh size" option defines how many points (in X and Y) there are at<br />
which the per-vertex equations are actually computed. When you crank this<br />
option up, you start eating up CPU cycles rather quickly.<br />
<br />
<br />
<br />
<br />
=== VARIABLE POOLS; DECLARING YOUR OWN VARIABLES; PERSISTENCE OF VALUES ===<br />
-----------------------<br />
Declaring and using your own variables is easy - in some bit of code <br />
(init equations, per-frame equations, etc.) you just write something like<br />
the following:<br />
<br />
billy = 5.3;<br />
<br />
This creates a variable called 'billy' and sets its value to 5.3. You can<br />
then freely read and/or modify the value of 'billy' within that section<br />
of code.<br />
<br />
However, sometimes it is desireable to create (really, initialize) a variable <br />
in an "init" equations, then use and/or update it in the "per-frame" equations.<br />
You can always do this, because paired init and per-frame equations<br />
share the same variable pool. In addition, the values of user-defined<br />
variables will persist from frame to frame.<br />
<br />
There are three variable "pools" in MilkDrop:<br />
<br />
1. preset init code + preset per-frame code<br />
2. custom wave init + custom wave per-frame code<br />
3. custom shape init + custom shape per-frame code<br />
<br />
So, you can probably guess that if you declare a variable in the preset<br />
init code, you can then read it in the preset per-frame code. You can<br />
also write to it (update it), and its value will persist to the next<br />
frame. All three pools work this way.<br />
<br />
As explained, though, you can't read the value of 'billy' in when in another <br />
variable pool. (This is intentional, and keeps MilkDrop running nice and <br />
fast.) If you want to pass values around between variable pools, you need <br />
to use a set of special variables: q1, q2, q3, etc. on up to q32. See<br />
the next section for details on how they work and how to properly use them.<br />
Just remember: the Q variables (and later, the T variables) are the only ones <br />
that you can use to "jump" between (carry values between) variable pools.<br />
<br />
You might notice that there are two other types of equations that weren't <br />
listed above. They are:<br />
<br />
* preset per-vertex code<br />
* custom wave per-point code<br />
<br />
For these two code sections, persistent values don't really make sense,<br />
because there is no way to properly initialize them. Any user-defined<br />
variables in these code sections should just be treated as scratch<br />
variables, not persisting from frame to frame, from vertex to vertex,<br />
or from point to point (even though technically, they will... but it<br />
probably won't be what you want). The only thing that really makes sense<br />
here is when you want to carry values along from point to point as<br />
you run the custom wave per-point code; to do this, use q1-q32. (See<br />
the next section for a more detailed explanation.) <br />
<br />
<br />
<br />
<br />
=== PRESET INIT CODE; CARRYING VALUES BETWEEN VARIABLE POOLS, USING q1-q32 ===<br />
As we've just seen, you can't normally pass values around between variable <br />
pools. However, there is one mechanism for bridging this gap: the 'Q'<br />
variables. They are named q1, q2, q3, and so on, through q32. Their<br />
main function is to bridge the gap between various variable pools.<br />
<br />
In MilkDrop 1.03 and later, you can write code that is executed only once,<br />
when a preset is loaded (switched to). This 'preset initialization' code <br />
does two useful things:<br />
<br />
1. It allows you to set the initial value of your own (user-defined) <br />
variables (such as 'my_variable'), as just explained. <br />
<br />
2. It allows you to write the default ("sticky") values for q1, q2, q3... <br />
through q32. Whatever these values end up at after the init code, <br />
those are the values that q1-q32 will be reset to at the start of <br />
each frame (...the input to the per-frame equations). If the<br />
per-frame equations change the values of q1-q32, those new values will<br />
propagate on to other variable pools (see the diagram below), but on<br />
the next frame, the values will be reset to the original "sticky" <br />
defaults.<br />
<br />
See the flow chart below for a brief, and complete, glance at how the values<br />
of the Q variables flow throughout MilkDrop.<br />
<br />
<br />
Let's walk through the flow of the chart. <br />
<br />
If you write to the values of q1..q32 from the "preset init code", the values <br />
you write will become the new 'base values' to which q1..q32 are initialized <br />
at the start of each frame, for the per-frame code. So when you access (read) <br />
q1-q32 in the per-frame code, you'll get the values that were *initially* set -<br />
over and over, every frame. You can then modify them (or not) in the per-frame <br />
code, and the (possibly modified values) will then be readable by the per-vertex <br />
code - as well as by all pixel shader code, and others. However, any modified <br />
values will not persist to the next frame; they will be reset again, at the <br />
start of the next frame, to the values they had at the end of the preset init <br />
code.<br />
<br />
In the per-vertex code, the q1-q32 values start (for the first vertex <br />
in any frame) as the values they had at the end of the per-frame code. If you <br />
modify q1-q32 in the per-vertex code, those modified values will carry over <br />
from vertex to vertex. (This isn't a very desireable effect; you should avoid <br />
writing to the Q variables from the per-vertex equations.) Next frame, they <br />
will be reset to whatever value they had at the end of the [next frame's <br />
execution of the] per-frame code. (It's all in the diagram... look at that, <br />
and you'll just get it.)<br />
<br />
There is one trick here. You might notice that the custom wave/shape<br />
init boxes are missing from the diagram. That's because the q<br />
variables coming out of them don't go anywhere. The Q values that come<br />
into the per-frame wave/shape equations come from the preset per-frame<br />
equations, as you can see. But, just to humor you: in the wave/shape init code, <br />
the Q values coming in are the results from the preset init code. Any Q values <br />
you write to there (in the wave/shape init code) will be meaningless; although<br />
you can write to (initialize) your own custom variables, and read those in <br />
later, in the wave/shape per-frame equations! So, really, you can still route<br />
data that way, if you really want to.<br />
<br />
Side note: when you edit the preset init code and apply it (by hitting <br />
CTRL+ENTER), the init code will re-execute immediately. However, when you <br />
edit the regular per-frame/per-vertex code and hit CTRL+ENTER, the preset init <br />
code will NOT be re-executed; the results of the last execution will persist.<br />
If you change per-frame/per-vertex code and want to re-execute the initialization<br />
code (i.e. to randomize it or reset the preset), you'll have to save the preset<br />
and then re-load it.<br />
<br />
(Historical note: nothing here has changed since MilkDrop 1; these diagrams were<br />
just re-designed to be much simpler to read. Actually, there was a bug in <br />
the old diagrams that is now fixed: on frame 0, they showed the Q values <br />
going straight from the (frame 0!?) per-frame code, into the custom <br />
wave/shape init code. On frame 0, those Q values actually come straight from <br />
the preset init code. HOWEVER, they are virtually useless, as discussed above.)<br />
<br />
<br />
<br />
<br />
=== CUSTOM SHAPES AND WAVES ===<br />
----------------------<br />
As of MilkDrop 1.04, two new features are available: custom shapes, and custom <br />
waves. A preset can have up to 4 of each. <br />
<br />
With custom shapes, you can draw an n-sided shape (with 3-100 sides) anywhere <br />
on the screen, at any angle and size, in any color, and at any opacity. You <br />
even have the option to map the previous frame's image onto the shape, which <br />
makes for some incredible possibilities (such as realtime hardware fractals - <br />
see the 'Geiss - Feedback' preset). You can also write per-frame code to <br />
control all of these things about the shape(s). This way, they can react to<br />
the audio or change over time - whatever you can imagine. You are limited to<br />
four custom shapes per preset, however, each one of those can be instanced,<br />
which lets you draw a huge number (up to 1024) of them each frame, if you <br />
want to, and each one can be totally different (as long as the value of<br />
the 'instance' variable ends up influencing the other properties).<br />
<br />
With custom waves, you can draw the waveform (or the frequency spectrum)<br />
wherever, whenever, and however you want; a great addition since MilkDrop <br />
1.03, where only the built-in waveforms were possible. With custom waves<br />
you can also write per-frame code to control the waves, and per-point code<br />
to place every point (or line segment) on the wave exactly where you want,<br />
and in exactly the color you want, and so on.<br />
<br />
Remember those q1-q32 variables that were committed at the end of the preset<br />
initialization code, then reset (to those values) at the beginning of each<br />
frame, and then (potentially) modified in the preset per-frame code? Those<br />
(potentially modified) values of q1-q32 - as they were at the end of the<br />
preset's per-frame code, each frame - are piped into the custom wave & custom <br />
shape per-frame code. So if you read 'q3' in the custom wave per-frame <br />
code, what you're really reading is the value of 'q3' as it was left at the <br />
end of this frame's per-frame code. Again, see the q_vars.gif image <br />
for a diagram of the flow of the values of the q1-q32 varibles.<br />
<br />
For custom waves and shapes, you can modify q1-q32, if you like, in the per-<br />
frame equations. As usual, the values of the Q variables will not persist <br />
from frame to frame, though - they are reset on each new frame, to match<br />
the values they had at the end of the *preset's* per-frame code, this frame. <br />
<br />
For custom waves, you also have one more link in the chain: per-point<br />
(aka per-vertex) code. This code is executed once for each data point in the <br />
waveform. The initial values of q1-q32 coming in (for the first point)<br />
are the values that stood at the end of the custom wave per-frame code,<br />
this frame. If you then modify q1-q32 in the per-point code (or even if you<br />
don't), the values will pass on to the next point. You could, for example, <br />
smooth out a waveform using this.<br />
<br />
THE 'T' VARIABLES<br />
----------------------<br />
There are 8 additional variables available for custom waves and shapes:<br />
t1-t8. These are very similar to the Q variables, but they exist only<br />
for custom waves & shapes. To see how the data flows from variable pool<br />
to variable pool for the T vars, take a look at the diagram below. Like<br />
the Q variables, they exist to help you bridge some gaps between variable<br />
pools. However, the T variables are a bit simpler to understand than the <br />
Q's. The diagram below should explain it all.<br />
<br />
<br />
<br />
<br />
<br />
CUSTOM SHAPE PER-FRAME VARIABLES<br />
----------------------<br />
NAME WRITABLE? RANGE DESCRIPTION<br />
---- --------- ----- ----------- <br />
num_inst no 1-1024 The total # of instances (the number of times to repeat the per-frame equations for, & draw, this shape).<br />
instance no 0..num_inst-1 The current instance number that the equations are being executed for.<br />
sides yes 3-100 the default number of sides that make up the polygonal shape<br />
thick yes 0/1 if ON, the border will be overdrawn 4X to make it thicker, bolder, and more visible<br />
additive yes 0/1 if ON, the shape will ad<br />
<br />
[[Category:Articles]]</div>Culixhttp://wiki.shoutcast.com/wiki/Online_Service_DeveloperOnline Service Developer2010-11-30T03:29:02Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>{{Template:NavBar}}<br />
<br />
[[Category:Winamp]]<br />
==The What and Why of Online Services==<br />
===What is a Winamp Online Service===<br />
A Winamp online service has several distinctive features. The first is that it is a web site that appears embedded within the Winamp client. The second, and more fun feature, is that the web pages so displayed are able to interact with the Winamp Client. The third is that access to the online services is presented to the large Winamp community as part of the Winamp client's Online Services Gallery.<br />
<br />
===Benefits to creating an Online Service===<br />
There are many benefits for developing an Online Service. Before we delve into the list, the most important benefit is distribution. Winamp is a great distribution platform as it has 77 million unique users every month!!<br />
<br />
Hence,<br />
#a) if your website needs page views and more monetization<br />
#b) if your brand needs more eye balls<br />
#c) if your blog needs more readers<br />
#d) if you want to develop an web application which has something to do with music, video, photo, streaming, podcasts, music events, #e-commerce, games then you will never regret making an Online Service in Winamp.<br />
<br />
Try it now!<br />
<br />
===Integrating Online Services with Winamp===<br />
The Online Services API is designed to allow web pages, hosted (displayed) within the embedded browser of the Winamp client, to leverage a series of APIs that can interact with the rest of the Winamp application. In order to make this happen you have to do the following:<br />
<br />
*Make sure you have the latest version of the Winamp client (v5.55 or above). You can download the client from [http://winamp.com/player winamp.com/player]<br />
*Make sure you have the latest version of the Online Services developer plugin (ml_webdev.dll). Get the plugin from this [http://download.nullsoft.com/winamp/plugin-dev/wa_webdev.exe link]. This plugin will create a "WebDev Platform" node within the Medial Library pane. It has it's own special installer.<br />
<br />
In order to change the starting web page for the online service, start the Winamp client and configure the plugin. <br />
#Open the Winamp player<br />
#Select Options->Preferences->Plug-ins->Media Library. <br />
#Select "WebDev Test Platform v2.0" and press "Configure selected plugin". <br />
#On the Web Dev Preferences dialog, set the URL field to the URL of the initial web page for the online service. For example, file://c:\myonlineservice\webdev.html <br />
#Click on "Web Dev Test Platform" in the Media Library. You may have to right click and choose refresh to see the new web page. <br />
You should now see the initial page of your online service in the Winamp embedded browser.<br />
<br />
==Registering an Account==<br />
While you can start developing an online service immediately, you will need to create a Winamp account before you can submit your service. To do this follow these steps:<br />
*Open your favorite web browser and go to http://www.winamp.com<br />
*Choose "Register" from the top of the page.<br />
*Complete the registration process<br />
<br />
==Submitting Your Service==<br />
===The Submission Process===<br />
Once you have come up with an amazing idea for an Online Service that uses Winamp, how do you get it into the Winamp Online Services Gallery so that users can start visiting it? Glad you asked. First you must start by submitting the service to Winamp. After being submitted, the service will go through a Winamp internal review process. If the service passes the review it will then be automatically included in the Winamp Online Services Gallery.<br />
<br />
The progress of your service through these steps can be seen through the use of the "My Profile" link at the top of the Winamp.com main page after logging in.<br />
<br />
====Submitting an Online Service====<br />
*Login to www.winamp.com<br />
**Navigate to www.winamp.com<br />
**Select "Winamp.com: Login" from the top of the page<br />
**Enter the email address and password specified when you registered your account.<br />
**Mouse over the gold "Online Services" button at the top of the screen.<br />
**Choose "submit an online service" from the buttons in the drop down<br />
**Make sure you follow the guidelines specified and press "Proceed".<br />
**Enter the following information on the form:<br />
***Service Name (15 characters max) - This name will be displayed on the first line for the service in the Winamp Gallery.<br />
***Description (750 characters max) - Enter text describing your online service.<br />
***Online Service URL - Enter the URL to launch your service.<br />
***Categories - Select two categories so your service can be grouped with other services.<br />
***Tags - Enter tags so that users can find your service by searching<br />
***Thumbnail Image (optional, .gif, .jpg, .png, max size 178x75 pixels) - Displayed in the Winamp Gallery.<br />
***Installer Image (optional, .gif, .jpg, .png, max size, 64x64 pixels - Displayed by Winamp Installer <br />
***List Icon Image (optional, .gif, .jpg, .pgn, max size: 16x16 pixels - Displayed in the Winamp "Media Library" pane.<br />
***Country - Select the countries which your online service supports.<br />
***Language - Select the languages which your online service supports.<br />
***Customer Support Email Id - An email address where user comments/complaints will be sent.<br />
***Click and read the Terms and Conditions<br />
***Check "Agree to Terms and Conditions<br />
***Click "Finish"<br />
<br />
=====Categories/Types of Online Services=====<br />
*Events<br />
*Streaming<br />
*Podcasts<br />
*Photo<br />
*Music<br />
*Video<br />
*Radio<br />
*E-Commerce<br />
*Artists<br />
*Games<br />
*Internet TV<br />
*Others<br />
<br />
=====Tags Vs. Categories=====<br />
You can tag/categorize a piece of information in your site and allows this piece of information to be searched and indexed. <br />
<br />
So what are categories? Categories help you organize your content under a more familiar taxonomy. By familiar, we mean non-unique and non-personal words; thereby allowing a user to navigate your content with ease knowing what they want. That's the reason why we have fixed the categories. They are Music, Video, Radio, E-Commerce, Photo, Artists, Streaming, Podcast, Games, Internet TV, Events and Other. This will also give you a clear indication on what you can actually create. And if you think you can create something else, there is always the 'Other' category.<br />
<br />
Then why do we need tags? Well, you can personalize your Online Service with your own tags. For e.g. for a hypothetical online service Music Shoppe (Let's say) tags can be 'music shoppe', 'music shop', 'purchase music', 'music shop', 'music store' whereas categories can be broader like 'music' & 'e-commerce'. All you have to do is make them short, crisp, relevant (search compatible) and small in numbers so that they are relevant.<br />
<br />
Tags will be introduced shortly. Till then, please use categories :)<br />
<br />
===Monitoring the Status of your Submission with "My Profile"===<br />
After you have successfully submitted an online service, Winamp will put it through a review process. You can check the status of your online service by examining the "My Profile" link in the upper right of the screen after logging in to www.winamp.com.<br />
<br />
Note that once you go to your profile, there are three links, one for each of the types of submissions you may have made. Choose "Online Services" to see that type.<br />
<br />
The online service will proceed thru the following stages:<br />
<br />
#Online Services in Review - The online service has been submitted and is awaiting review<br />
#Approved Online Services - The service has been reviewed and is waiting to be either published or rejected. An online service should only stay in this state for a short time.<br />
#Published Online Services - The online service was found to be acceptable and is now available in the Winamp Gallery.<br />
#Rejected Online Services - The online service was found to be '''un'''-acceptable and is '''not''' available in the Winamp Gallery.<br />
<br />
===Managing your Online Service with "My Profile"===<br />
Once your online service has been published, there are several things you can do to manage it through the My Profile page.<br />
<br />
====Viewing Service Information====<br />
Each published online service will show the following:<br />
*Unique ID - A ID that uniquely identifies your online service.<br />
*Version # - The current version number of your online service.<br />
*Description - The description you typed when submitting the service.<br />
*First Published on - Date on which this online service was first published. <br />
*Last Edited on - Last date this online services was edited.<br />
*Last Approved on - Last date this online service was approved. <br />
*Reporting On - A section showing the following statistics<br />
**Service has been added - The service is available in the gallery.<br />
**Service has been removed - The service is not available and has been deleted.<br />
**Service has been accessed - The number of times users have accessed the site through the Winamp Client.<br />
**Unique Users - The number of views by unique (i.e., new ip addresses) users.<br />
**Ratings - Average user rating.<br />
**Number of Ratings - How many users have rated the online service<br />
**Abuse Reports - How many abuse reports have been sent against this service.<br />
<br />
====Editing your Online Service Info====<br />
My Profile contains an '''EDIT''' button so you can change the details that you entered when you first submitted the online service for review. This button will take you to a form where you can change these values. Changing the values will increase the version number of the online service and submit the service for review.<br />
<br />
====Removing your Online Service====<br />
My Profile also has a '''REMOVE''' button so the author can delete the online service. To reinstate the service you will have to resubmit it.<br />
<br />
====Hiding your Online Service====<br />
'''Hide from Gallery''' will prevent the online service from appearing in the Winamp client online services gallery. This can be used to temporarily prevent users from subscribing to the service.<br />
<br />
==Style Guide==<br />
<br />
Please reference this wiki page for optimizing how your online service looks/performs inside of Winamp<br />
<br />
[[Winamp_Browser_Support|Winamp Browser Support]]<br />
<br />
==JavaScript APIs==<br />
Here is a summary of the API methods that can be called from an online service.<br />
<br />
For more details on the methods available check out the [[complete JavaScript API technology framework]]<br />
<br />
*Transport API<br />
**Play <br />
**Stop<br />
**Pause<br />
**Advance to next track<br />
**Back up to previous track<br />
**Shuffle<br />
**Repeat<br />
**Event Notifications - so the web page can tell when the events happen<br />
***When the player starts playing<br />
***When the player is stopped<br />
***When the player is paused<br />
***When the player reaches the end of a file <br />
**Metadata - get metadata for currently playing song<br />
**position - change the playback position of currently playing song<br />
<br />
*Playqueue API<br />
**The ability to alter the Winamp Queue of songs about to be played.<br />
***Play - clear the queue and play a song.<br />
***Enqueue - add a song to the queue<br />
***Insert - add a song to the queue at a position<br />
***Clear - clear the queue<br />
***Metadata - get metadata for a song in the queue<br />
<br />
*Playlists API<br />
**Get a list of all playlists<br />
**Open a playlist for alteration<br />
**Save a modified playlist<br />
<br />
*Playlist methods - once a playlist is opened these are available.<br />
**Get and set info about individual items in the playlist<br />
**Swap two songs<br />
**Randomize the order of songs<br />
**Reverse the order of songs<br />
**Sort By Filename<br />
**Sort By Title<br />
**Clear (empty) the playlist<br />
<br />
*Bookmarks API<br />
**Add a bookmark<br />
**TBD<br />
<br />
*Podcasts API<br />
**Subscribe to a Podcast<br />
**More TBD<br />
<br />
*Secuirty API<br />
**In place, but not fully ready<br />
**TBD<br />
<br />
*LocalMedia API<br />
**TBD<br />
<br />
*History API<br />
**Query the History DB - retrieve info about songs played previously<br />
<br />
*Config API<br />
**The ability to store JavaScript properties persistantly.<br />
<br />
*Application API<br />
**Launch the internal Winamp browser.<br />
**Launch an external browser.<br />
**Get the version of the internal browser.<br />
**Get the language pack info<br />
<br />
*Skins API<br />
**Retrieve color and font information regarding the currently assigned Winamp client skin.<br />
<br />
*MediaCore API<br />
**Retrieve metadata for a specified file<br />
**Determine whether a specific file format (file extension) is supported by the Winamp Client.<br />
<br />
==User Feedback==<br />
There are several methods by which users can provide feedback on your online service.<br />
<br />
===Ratings by Users===<br />
The Winamp client allows users to rate your online service. You can see the average rating and the number of times that your service has been rated using the "My Profile" link on winamp.com after logging in. This way you can tell whether thousands of people adore your service, or perhaps it was a single rating from your best friend.<br />
<br />
===Abuse Reporting===<br />
Users can also complain if they find something objectionable. These "abuse reports" may be forwarded to the online service developer to be resolved. So don't do bad things. And no, SlyHawk, parcour will not help you here.<br />
<br />
==Additional Considerations==<br />
===Security===<br />
In order to help protect users from potential abuse by online services, Winamp has implemented a strategy to notify users that a web service is about to issue one of the online service api methods. The warning message will ask the user whether the method should proceed. Each security prompt will be applied to the action being requested as well as certain related actions of the same API. There is also a way to indicate that the selection should be used for ALL other security prompts for the current online service. This prevents the user from being bombarded with what may sound like repetitive requests. If the author of the online service upgrades their service, these choices will be carried forward to the new release.<br />
<br />
For a more in depth discussion of the security prompts go to [[Online Service Security Prompts]].<br />
[[http://www.example.com link title]]</div>Culixhttp://wiki.shoutcast.com/wiki/WSZ_FilesWSZ Files2010-11-30T03:28:58Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Explorer09</p>
<hr />
<div>{{ClassicSkin}}<br />
<br />
==Winamp Skin Zip Files (WSZ)==<br />
<br />
The last step you need to do before unleashing your Skin on the world is to convert it to the WSZ format. How do I do that, you ask? Just follow the following steps:<br />
<br />
#With your trusty zip compression tool of your choice, zip YOUR skin's folder (not the Winamp "Skins" folder) into a .zip file.<br />
#Rename the new file's extension from .zip to .wsz.<br />
#Test it by removing your skin folder, then placing your .WSZ into the Winamp "Skins" folder.<br />
#Run Winamp, then press Alt-S to access the Skin browser. If you see your skin, then everything worked correctly.<br />
#That's it! Pat yourself on the back, then take the next step and submit it to Winamp.com.<br />
<br />
<br />
==WSZ History==<br />
A Winamp skin is composed of 45 files. Most of the files that create a skin are .BMPs (a very common image file type) and a few text files. When skin support was originally implemented, an artist would have to create those skins and place them into a subdirectory of the Winamp Skins folder (usually located in <code>C:\Program Files\Winamp\Skins</code>).<br />
<br />
This started getting messy, because not all of the skin developers were creating subfolders when compressing their skins into a ZIP file for distribution. When an end-user uncompressed the files to the Winamp Skins folder, it would at times overwrite other skins. As a solution, we implemented the functionality into Winamp to read the .ZIP files directly. Then, an end-user would simply place the .ZIP file into their Winamp Skins folder; when using the Skin Browser in Winamp (ALT+S), the skin magically appeared and loaded, if selected.<br />
<br />
This did clean up the mess. However, a new problem then surfaced: The .ZIP file format is a very widely used compression scheme and Winamp was just one of the many dozens of programs available to utilize it. We wanted users to be able to double-click the Skin ZIP file and have Winamp automatically install and load the skin. How do we do that without associating Winamp as the default program for handling skins? Answer: Rename the file extension.<br />
<br />
We simply took all those compressed skins ending with the .ZIP extension and renamed them to end with .WSZ (Winamp Skin Zip). This allowed us to stay with the standard Winamp .ZIP files and not have to convert the thousands of skins available for download on the Internet. Any skins that are submitted to our site with filenames ending with .ZIP are automatically renamed to end with a .WSZ before published.<br />
<br />
Why do all this, you ask? The answer is simple. We wanted to make it so that Winamp would automatically load the skin when a user clicked on a link to download a skin from Internet Explorer, as well as Netscape Navigator. We also wanted to make it so that if a user actually had downloaded the .WSZ file, all they would have to do is double-click it to install it.<br />
<br />
What happens then? Well, when a person installs a .WSZ file, Winamp just copies the file to the Winamp Skins folder so that it can be handled correctly. You can also manually move the .WSZ file into your skin directory and Winamp will recognize it just as well.</div>Culixhttp://wiki.shoutcast.com/wiki/SDK_ContentsSDK Contents2010-11-30T03:28:53Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>The '''Winamp SDK''' is a collection of code and examples projects that illustrate how code can be written for Winamp. If you are looking to write a plugin but don't know where to start, try looking for an example project that does something similar. You can then check out that specific section of code and begin learning how winamp works.<br />
<br />
You can download a copy of the Winamp 5.55 SDK [http://download.nullsoft.com/winamp/plugin-dev/WA5.55_SDK.exe here].<br />
<br />
==SDK Sections==<br />
<br />
* Agave - collection of [[Wasabi API|Wasabi]] objects unique to Winamp 5<br />
** Aave\AlbumArt - [[Album Art API]] interface definition files<br />
** Agave\Component - [[System Component Interface|W5S system component]]interface definition files<br />
** Agave\Config - [[Agave Config API|Winamp 5 configuration]]. Not be confused with the Winamp3 [[Wasabi Config API]]<br />
** Agave\Language - [[Language API]]<br />
** Agave\Metadata - [[Agave Metadata API]]<br />
* burner<br />
* coverdirectory - Cover Directory sample plugin. Demonstrates the [[Album Art API]], [[Service Factory|Service Factories]], and how to build a [[System Component Interface|System Component (W5S)]<br />
* dsp_test - [[Audio Effects plugin|DSP Plugin]] example<br />
* enc_flac - [[Audio Encoder Plugin]] example using the [http://flake-enc.sourceforge.net/ Flake] FLAC encoder. Although the project name is enc_flac, the plugin compiles as enc_flake.dll to allow it to co-exist with the [http://flac.sourceforge.net/api/index.html libFLAC] based encoder that ships with Winamp.<br />
* gen_classicart - Example [[General Purpose Plugin]] which demonstrates creating a Skinned window and the [[Album Art API]]<br />
* gen_ml - Collection of header files that comprise the [[Media Library API]] and the struct definition for creating a [[Media Library Plugin]]. Most of the content is contained in ml.h<br />
* gen_tray - Source code for the System Tray plugin which ships with Winamp.<br />
* in_chain - Example plugin showing how to use another input plugin within your own input plugin<br />
* in_raw - Example [[Input Plugin]]<br />
* in_tone - Example [[Input Plugin]]<br />
* irctell - Example [[System Component Interface|W5S]] plugin demonstrating [[System Callbacks API]] and the old Winamp3 [[Media Core API]] (only available in modern skins)<br />
* maki - Tools and include files for compiling [[maki]] scripts for use in the Modern Skinning engine. More information is available in the [[Skin Developer]] portion of this wiki.<br />
* ml_http - Example [[Media Library Plugin]] demonstrating using embedded IE and the Javascript [[Javascript External Interface|window.external]] interface.<br />
* ml_iso - Example [[Media Library Plugin]] demonstrating the send-to menu<br />
* ml_local - Header files comprising the Local Media Database API<br />
* ml_rg - ?<br />
* ml_wire - ?<br />
* ml_xmlex - Example [[Media Library Plugin]] demonstrating basic media libary UI concepts and the [[XML Parser object]]<br />
* mlExplorer - Standalone executable demonstrating how to use the [[Nullsoft Database Engine|Nullsoft Database Engine (NDE)]] in your own application to read Winamp's media library contents.<br />
* nde - [[Nullsoft Database Engine]] source code<br />
* nsv<br />
* nu<br />
* playlist<br />
* plLoadEx<br />
* ReplayGainAnalysis<br />
* Wasabi<br />
* Winamp<br />
* xml<br />
* xspf</div>Culixhttp://wiki.shoutcast.com/wiki/XML_GUI_ObjectsXML GUI Objects2010-11-30T03:28:48Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Henzz</p>
<hr />
<div>==GuiObject (Global params)==<br />
All the objects to be discussed in this chapter are GuiObjects. This means, among other things, all such objects have the same basic set of parameters which are valid for all of them. All GuiObjects are objects that live with a set of spatial coordinates within a groupdef (or layout). A button, a piece of text, a flat bitmap image, a tree of items, and an edit box would all be different kinds of GuiObjects, and all of the parameters listed here work on all of them.<br />
* '''alpha''' - (int) An integer [0,255] specifying the alpha blend mode of the object (0 is transparent, 255 is opaque). Default is 255.<br />
* '''activealpha''' - (int) A different alpha value [0,255] for the object in its active state.<br />
* '''inactivealpha''' - (int) A different alpha value [0,255] for the object in its inactive state (if you set both activealpha and inactivealpha, it is meaningless to set alpha).<br />
* '''cursor''' - (id) The id of the cursor element to be displayed when the mouse is over this object. You can also use the system cursors. A list can be found here: '''[[Wasabi Appendix: Cursors | Appendix: Cursors]]'''<br />
* '''tooltip''' - (str) A human readable string to display as a tooltip for when the mouse is hovered over this object.<br />
* '''move''' - (bool) Setting this flag causes any dragging of this object to actually drag the entire layout within which the object resides.<br />
* '''renderbasetexture''' - (bool) A flag to tell the system to always use the system's base texture as the background of this object.<br />
* '''cfgattrib''' - (str) A configattrib string assigned to this GuiObject. Here is a list of a few: '''[[Wasabi Appendix: ConfigAttrib | Appendix: ConfigAttrib]]'''<br />
* '''visible''' - (bool) Whether or not the object should be displayed in its group or layout.<br />
* '''x''' - (int) The X position of the object in its group or layout.<br />
* '''y''' - (int) The Y position of the object in its group or layout.<br />
* '''w''' - (int) The width of the object in its group or layout.<br />
* '''h''' - (int) The height of the object in its group or layout.<br />
* '''relatx''' - (int) This [0,2] integer determines if the X position should be calculated by normal ("0"), relative ("1") or proportional ("2") units. See below.<br />
* '''relaty''' - (int) This [0,2] integer determines if the Y position should be calculated by normal ("0"), relative ("1") or proportional ("2") units. See below.<br />
* '''relatw''' - (int) This [0,2] integer determines if the width should be calculated by normal ("0"), relative ("1") or proportional ("2") units. See below.<br />
* '''relath''' - (int) This [0,2] integer determines if the height should be calculated by normal ("0"), relative ("1") or proportional ("2") units. See below.<br />
* '''fitparent''' - (bool) This parameter is used instead of x;y;w;h parameters and means that the object covers all the area of the parent object.<br />
* '''x1''' - (int) The X position of the left edge of the object in its group or layout. Only works inside definitions with design_w parameters set.<br />
* '''y1''' - (int) The Y position of the top edge of the object in its group or layout. Only works inside definitions with design_h parameters set.<br />
* '''x2''' - (int) The X position of the right edge of the object in its group or layout. Only works inside definitions with design_w parameters set.<br />
* '''y2''' - (int) The Y position of the bottom edge of the object in its group or layout. Only works inside definitions with design_h parameters set.<br />
* '''anchor''' - (str) A list of one or more of the following keywords, delimited by the pipe (|) character: "top|bottom|left|right" these anchors work with x1/y1/x2/y2 positioning to fix the edge of the object its distance from the edges of the group or layout which contains it.<br />
* '''sysmetricsx''' - (bool) This flag will cause this object to be resized by having its X position multiplied by the OS scalar coefficient.<br />
* '''sysmetricsy''' - (bool) This flag will cause this object to be resized by having its Y position multiplied by the OS scalar coefficient. <br />
* '''sysmetricsw''' - (bool) This flag will cause this object to be resized by having its width multiplied by the OS scalar coefficient.<br />
* '''sysmetricsh''' - (bool) This flag will cause this object to be resized by having its height multiplied by the OS scalar coefficient.<br />
* '''rectrgn''' - (bool) Setting this flag causes the engine to ignore the object's region for handling "mouse over object" detection and only use the bounding rectangle. <br />
* '''regionop''' - (int) An integer enumeration [-2,1] for what kind of region-operation to perform with this object's calculated region against its parent's region. See below for more information. <br />
* '''sysregion''' - (int) Param alias for regionop.<br />
* '''wantfocus''' - (bool) This flag determines whether or not an object ever gets the focus at all.<br />
* '''focusonclick''' - (bool) This flag determines whether or not an object gets the focus when clicked. <br />
* '''taborder''' - (int) This value indicates the "tab order" of the object within the group or layout in which it resides. When the user hits the tab key, the interface focus moves to the next greater object in tab order. Objects with equal tab order will be ordered in the reverse of their insertion order in XML (last object in is first in default tab order). <br />
* '''nodblclick''' - (bool) This flag blocks doubleclick events from being received by this object.<br />
* '''noleftclick''' - (bool) This flag blocks left click events from being received by this object.<br />
* '''norightclick''' - (bool) This flag blocks right click events from being received by this object.<br />
* '''nomousemove''' - (bool) This flag blocks mouse move events from being received by this object.<br />
* '''nocontextmenu''' - (bool) This flag blocks the main context menu from being displayed for rightclick.<br />
* '''ghost''' - (bool) This flag causes the object to be transparent to all user interface events such that all the mouse messages pass to the object(s) visibly underneath it.<br />
* '''notify'''(0-9) - (str) A string to be used as a parameter to the onNotify event for the object upon instantiation. The notify strings 0-9 will be sent in order.<br />
* '''droptarget''' - (id) The id of an object to which all of this object's drag and drop events will be redirected.<br />
<br />
==='''Appendixes'''===<br />
*'''[[Wasabi Appendix: ConfigAttrib | Appendix: ConfigAttrib]]'''<br />
*'''[[Wasabi Appendix: Cursors | Appendix: Cursors]]'''<br />
<br />
<br />
==<button/> & <togglebutton/>==<br />
The button is a simple concept in Wasabi - you push it, it activates something. It can either be used as a substrate for a script (ie: put a script and a button in the same groupdef, and you can handle complex button functionality with the script) or it can be used by itself to launch an action into the system when pressed. You can implement your own action handlers in code, but some global actions predefined to be handled by the system are also available.<br />
<br />
* '''image''' - (id) The id of the bitmap element to display in its "normal" state. <br />
* '''downimage''' - (id) The id of the bitmap element to display when the user is pressing down on the button.<br />
* '''hoverimage''' - (id) The id of the bitmap element to display when the user is hovering the mouse over the button.<br />
* '''activeimage''' - (id) The id of the bitmap element to display when the object is in its "active" state (usually only used by togglebutton, but available on the basic button object to allow the user to create extended functionality in script).<br />
* '''text''' - (str) A string of text to be rendered on top of the button's currrent state image. In this way, you can create a single button graphic and reuse it to create internationally localizable buttons.<br />
* '''action''' - (str) The action to fire if the button is clicked (when it enters into its downstate).<br />
* '''param''' - (str) The param to go with the action fired if the button is clicked.<br />
* '''borders''' - (bool) Set this flag if you want to be a styled button.<br />
* '''style''' - (str) Set the style value if you set the borders flag, to tell wasabi what type of button style you want.<br />
** "button_normal" "osbutton_normal" "osbutton_close" "osbutton_minimize" and "osbutton_maximize"<br />
* '''retcode''' - (int) Specifies the "modal return code" for the button. Only valid with the "endmodal" system action.<br />
* '''cbtarget''' - (id) The optional "component bucket target" for this button. Only valid with "cb_next" or "cb_prev" system actions. A componentbucket is another name for the thinger -- this allows you to have targetted button controls for more than one componentbucket in a user interface.<br />
* '''action_target''' - (id) This will send the specified action only to the object whose id is listed here. The param parameter is ignored in this case and this string is sent as the param data for the action. Most objects don't understand being sent actions (this is an extended functionality), so this won't do anything in most cases.<br />
* '''center_image''' - (bool) Setting this flag causes the image to be centered against the object rectangle. This parameter is only important when both borders and an image are specified on a single object. <br />
<br />
Example:<br />
<button x="50" y="10" action="VID_FS" image="vis.fs.1" hoverImage="vis.fs.2" downImage="vis.fs.3"/><br />
<button x="10" y="40" w="100" h="20" borders="1" style="osbutton_normal" text="Click Here"/><br />
<br />
==='''Appendix'''===<br />
* '''[[Wasabi Appendix: Action List | Appendix: Action List]]'''<br />
<br />
<br />
==<nstatesbutton/>==<br />
The nstatesbutton is a specialized kind of togglebutton whose purpose is to cycle through a number of different visual states. The parameters beyond togglebutton that it implements are:<br />
* '''nstates''' - (int) The number of discrete states in which the object may exist.<br />
* '''cfgvals''' - (str) A semicolon delimited list of values to represent custom config values for the multiple states. Default is the current state number. See below.<br />
The nstatesbutton uses special handling of the image, downimage, hoverimage, and activeimage parameters expressed by the button object (from which this object is derived). The nstatesbutton will actually append the state number to the four image parameter strings to calculate the bitmap ids to be loaded for the current object state. Remember, like most everything else in a computer, this "current state value" counts from 0 and is therefore in the range [0, nstates-1].<br />
<br />
If the object is bound to a configuration attribute, that attribute will be set with a cfgval every time the nstatesbutton transitions to a new state. If the cfgvals parameter is not set, the attribute will simply be set with the current state value. If the cfgvals parameter is set, it will parse the string and set the config attrib with the n'th substring corresponding to the current state value.<br />
<br />
The following snippet fully describes two nstatesbutton objects with three states each, one using full images for its visual display, one using themed Wasabi borders with three different state logos:<br />
<elements><br />
<bitmap id="nimg0"/> <br />
<bitmap id="dimg0"/> <br />
<bitmap id="himg0"/><br />
<bitmap id="nimg1"/> <br />
<bitmap id="dimg1"/> <br />
<bitmap id="himg1"/><br />
<bitmap id="nimg2"/> <br />
<bitmap id="dimg2"/> <br />
<bitmap id="himg2"/><br />
<bitmap id="logo0"/><br />
<bitmap id="logo1"/><br />
<bitmap id="logo2"/><br />
</elements><br />
<groupdef id="some.random.groupdef"><br />
<nstatesbutton id="three.freeform.states"<br />
nstates="3" cfgvals="one;two;three"<br />
image="nimg" downimage="dimg" hoverimage="himg"<br />
/><br />
<nstatesbutton id="three.themed.states"<br />
nstates="3" image="logo" borders="1" center_image="1"<br />
/><br />
</groupdef><br />
If the "three.freeform.states" nstatesbutton were assigned to a configattrib, that attribute would be filled with the values "one" "two" and "three" in order. If the "three.themed.states" were instead assigned to a configattrib, it would be filled with the default values "0" "1" and "2" in order.<br />
<br />
<br />
==<images/>==<br />
The images object is object that displays a certain image based on the position of a slider. This object is very similar to [[Animationlayer]] except that this animation's current frame will be determined by the position of a slider. An example of implementation is the old Classic Winamp skins where the volume slider background changes colour from green to red depending on its position (0%-100%). This object is currently under development and not all sliders are supported. Currently only Volume and Panning(Balance) sliders can be used as sources.<br />
<br />
* '''images''' - (id) A bitmap element for the array of images that will be used.<br />
* '''source''' - (id) Id of the slider that will determine the current animation frame.<br />
* '''imagesspacing''' - (int) The hight of each animation frame in the bitmap element. This will determine the total number of frames, (300/15=20)<br />
<br />
Example:<br />
<images source="volume" x="0" y="0" w="68" h="13"<br />
images="main.volpan.volume" imagesspacing="15"/><br />
<br />
<images source="balance" x="73" y="0" w="38" h="13"<br />
images="main.volpan.balance" imagesspacing="15"/><br />
<br />
<slider id="Volume" action="VOLUME" x="1" y="0" w="68" h="13"<br />
thumb="main.volpan.thumb" downThumb="main.volpan.thumb.pressed"/><br />
<br />
<slider id="Pan" action="PAN" x="74" y="0" w="38" h="13"<br />
thumb="main.volpan.thumb" downThumb="main.volpan.thumb.pressed"/><br />
<br />
==<PlaylistDirectory/>==<br />
The PlaylistDirectory object is simply a list with all the saved playlist from the media library. Please remember that this object is always on top of other objects, so you'll have to hide it via maki if you dont want it to be visible. This object was introduced in Winamp 5.5(skinversion 1.3)<br />
<br />
<br />
==<AlbumArt/>==<br />
The AlbumArt object is a simple GuiObject that displays a picture of the album cover of the song thats playing in Winamp. Please note that if you want do something to this object in a maki script you'll have to define it as a guiobject and not as a layer.<br />
* '''notfoundImage''' - (id) A bitmap element that used if Winamp cant find any cover for the song.<br />
* '''align''' - (str) One of the following three possible strings: "left" "center" "right" -- Default is "left".<br />
* '''valign''' - (str) One of the following three possible strings: "top" "center" "bottom" -- Default is "top".<br />
* '''source''' - (str) Path+Filename of file that you want to display in this object.<br />
* '''stretched''' - (bool) Stretch the albumart to the size of the object.<br />
<br />
<br />
==<grid/>==<br />
The grid object is a very nice object for creating stretchable images that still look good on the edges. It is a graphic, like a layer, but unlike layer it is created by applying nine different bitmaps, stretching five of them. There are, as you might guess, nine parameters<br />
<br />
* '''topleft''' - (id) A bitmap element for the top left section of the grid.<br />
* '''top''' - (id) A bitmap element for the top middle section of the grid.<br />
* '''topright''' - (id) A bitmap element for the top right section of the grid.<br />
* '''left''' - (id) A bitmap element for the middle left section of the grid.<br />
* '''middle''' - (id) A bitmap element for the center section of the grid.<br />
* '''right''' - (id) A bitmap element for the middle right section of the grid.<br />
* '''bottomleft''' - (id) A bitmap element for the bottom left section of the grid.<br />
* '''bottom''' - (id) A bitmap element for the bottom middle section of the grid.<br />
* '''bottomright''' - (id) A bitmap element for the bottom right section of the grid. <br />
<br />
Essentially, the given rectangle of the grid is intersected with 2 horizontal and 2 vertical lines. The topleft, topright, bottomleft, and bottomright bitmap elements will not be resized. The top, left, middle, right, and bottom bitmap elements, however, will be stretched to make all fit the grid rectangle. Using intelligently sized bitmap elements is fairly critical for this object. If you're having trouble, try starting with all of your bitmap elements as equal-sized squares.<br />
<br />
Example:<br />
<grid x="70" y="25" w="-74" relatw="1" h="20" topleft="main.text.left" top="main.text.center" topright="main.text.right"/><br />
<br />
<br />
==<Winamp:Browser/>==<br />
This is basically the browser you'll see in the Bento Winamp skin. You'll also need Winamp 5.54 (skinversion 1.34) for it to work.<br />
<br />
- '''home''' - (str) Url for the default homepage for the browser xui.<br />
<br />
<br />
==<browser/>==<br />
The browser object embeds an external browser technology window (such as IE or Mozilla) into the user interface with which you can load and render HTML directly.<br />
* '''url''' - (str) The url to be displayed.<br />
* '''mainmb''' - (bool) Setting this flag makes this browser object the "main mini-browser" for the system.<br />
* '''targetname''' - (str) This allows this browser object to be set as a specific HTML target.<br />
* '''scrollbars''' - (str) An enumerated string to determine how the system should handle the embedded browser's scrollbars. See below.<br />
Numerous interfaces in Wasabi refer to or control the "main" mini-browser. Setting the mainmb flag will cause the last browser object which processed its mainmb param to be the main. In other words, please don't set this flag on more than one object if you actually care which one is the main.<br />
Scrollbars are important for big browser windows, but can interfere with the simple rendering of HTML content as part of a Wasabi UI. To this end, the skinner can control how the scrollbars of the embedded browser are displayed by setting the scrollbars parameter to one of the following four string values: "auto" "never" "always" or "default" - default is to allow the HTML page to specify, all others override.<br />
<br />
<br />
==<Wasabi:Frame/>==<br />
The Wasabi:Frame object is a themed control whose purpose is to provide a movable interface between two rectangular areas, much like the concept of an HTML frame. Here are its parameters:<br />
<br />
* '''orientation''' - (str) One of the following four string values: "v" "vertical" "h" "horizontal" (Default is vertical).<br />
* '''left''' - (id) The group to be instantiated in the left or top frame.<br />
* '''right''' - (id) The group to be instantiated in the right or bottom frame.<br />
* '''top''' - (id) The group to be instantiated in the left or top frame.<br />
* '''bottom''' - (id) The group to be instantiated in the right or bottom frame.<br />
* '''from''' - (str) One of the following string values: "l" "left" "t" "top" or "r" "right" "b" "bottom" (Default is left).<br />
* '''width''' - (int) How many pixels from the chosen edge to start.<br />
* '''height''' - (int) How many pixels from the chosen edge to start.<br />
* '''resizable''' - (bool) Set this flag to allow the user to change the position of the framedivider. Default is to allow it to be resizable.<br />
* '''maxwidth''' - (int) The maximum amount of pixels you are able to move the poppler if resizable.<br />
* '''minwidth''' - (int) The minimum amount of pixels you are able to move the poppler if resizable (If you go below this value the poppler will snap to 0).<br />
* '''vgrabber''' - (string) The centered bitmap of the Grabber.<br />
* '''vbitmap''' - (string) The stretched bitmap of the Grabber.<br />
<br />
In the following simple example, the "top" and "bottom" groups are displayed in a resizable frame object:<br />
<groupdef id="top"><br />
<text text="Top" align="center" x="0" y="0" w="0" h="0" relatw="1" relath="1"/><br />
</groupdef><br />
<groupdef id="bottom"><br />
<text text="Bottom" align="center" x="0" y="0" w="0" h="0" relatw="1" relath="1"/><br />
</groupdef><br />
<groupdef id="both"><br />
<Wasabi:Frame<br />
orientation="horizontal"<br />
top="top" bottom="bottom" <br />
x="0" y="0" w="0" h="0"<br />
relatw="1" relath="1"<br />
/><br />
</groupdef><br />
<br />
<br />
==<Wasabi:CheckBox/>==<br />
The Wasabi:Checkbox object exists only as a namespaced object because it is expected to have only a single themed appearance. The Wasabi:Checkbox object is used for both checkbox functionality and radiobutton functionality, depending up on the specification of its parameters. It consists of a combination of a togglebutton and a text object to create a single functional user interface object.<br />
* '''text''' - (str) The text to display as part of the checkbox.<br />
* '''radioid''' - (id) If the button is to be used as part of a radio group, specify id of the parent Wasabi:RadioGroup object here.<br />
* '''radioval''' - (int) If the button is to be used as part of a radio group, specify its unique integer value here.<br />
* '''action''' - (str) see button.<br />
* '''param''' - (str) see button.<br />
* '''action_target''' - (id) see button.<br />
As with togglebutton, this is a very useful object for binding to a configuration attribute. It is very popular in preferences interfaces. If the object has a value for radioval, that will be the value set into the attribute if the object is activated.<br />
<br />
<br />
==<Wasabi:DropDownList/>==<br />
The Wasabi:DropDownList is a themed dialog object. It may be statically filled via a parameter or dynamically through script or by binding it to a text feed from code. A Wasabi:DropDownList object may be bound to an integer configuration attribute.<br />
* '''items''' - (str) A semicolon delimited list of items to be displayed in the dropdown area.<br />
* '''feed''' - (id) The id of a text feed to provide a semicolon delimited list of items to be displayed in the dropdown area.<br />
* '''select''' - (int) Specifies an item to be selected.<br />
* '''listheight''' - (int) Allows the skinner to specify the height of the dropdown area in pixels.<br />
* '''maxitems''' - (int) Allows the skinner to specify the max height of the dropdown area in lines of text. If the dropdown area has fewer lines of text than this value when this value is set, the dropdown area is sized to show no more than is needed.<br />
<br />
<br />
==<Wasabi:ComboBox/>==<br />
The Wasabi:ComboBox is a special type of object which combines dropdownlist functionality with an edit field as well. It has the same parameters as Wasabi:DropDownList.<br />
<br />
<br />
==<Wasabi:HistoryEditBox/>==<br />
The Wasabi:HistoryEditBox is an even more specialized version of this object family, its only purpose is to remember the last 64 items of text typed into it. It has one extra parameter over Wasabi:DropDownList: <br />
* '''navbuttons''' - (bool) Setting this flag will include the navigation buttons on the object. Default is to have the buttons.<br />
<br />
<br />
==<componentbucket/>==<br />
The componentbucket is a fancy name for the Thinger. More precisely, in Winamp3, the "Thinger Window" is a window which implements a very simple horizontal componentbucket. The object itself may be instantiated horizontally or vertically and the scrolling of the display within it should be controlled by button objects using "cb_next" and "cb_prev" action parameters and setting the cbtarget parameter to this object. The object has the following parameters:<br />
* '''leftmargin''' - (int) The number of extra pixels to pad the left (or top) edge of the total component bucket scrolling display.<br />
* '''rightmargin''' - (int) The number of extra pixels to pad the right (or bottom) edge of the total component bucket scrolling display.<br />
* '''spacing''' - (int) The number of extra pixels to place between each bucket icon.<br />
* '''vertical''' - (bool) Whether or not the display should scroll vertically or horizontally. Default is horizontal.<br />
A simple "thinger group" follows:<br />
<groupdef id="some.thinger.group.thing"><br />
<button id="mythinger.up" x="0" y="0"<br />
h="20" w="0" relatw="1"<br />
image="mythinger.up.normal" <br />
hoverimage="mythinger.up.hover" <br />
downimage="mythinger.up.down"<br />
action="CB_PREV" cbtarget="mythinger"<br />
/><br />
<button id="mythinger.down" x="0" y="-20"<br />
h="20" w="0" relatw="1" relaty="1"<br />
image="mythinger.down.normal" <br />
hoverimage="mythinger.down.hover" <br />
downimage="mythinger.down.down"<br />
action="CB_NEXT" cbtarget="mythinger"<br />
/><br />
<componentbucket id="mythinger" vertical="1" x="0" y="20" w="0" h="-40" relath="1"/> <br />
</groupdef><br />
<br />
<br />
==<customobject/>==<br />
The customobject is a useful tool for temporarily instantiating a group into a user interface. It has only one parameter:<br />
groupid - (id) Instantiate the specified group into my defined area.<br />
By finding your customobject in script and simply calling setXmlParam on it to give it new values for groupid, you can switch between the instantiation of multiple groups in a single user interface space.<br />
<br />
<br />
==<edit/> & <Wasabi:EditBox/>==<br />
The edit control is, as you might guess, a text entry field. Some versions of Wasabi currently embed an OS edit control into the rectangular area defined by this object. This embedded control will not blend properly with the rest of the skin's painting, it will always paint on top of everything else. Keep this in mind when developing skins for widest compatibility.<br />
* '''text''' - (str) Set the text in the edit field to this value.<br />
* '''action''' - (str) Will accept the string "mb_url" to cause this edit box to automatically send its value as an url to the main minibrowser.<br />
* '''multiline''' - (bool) Determines if the box is a single or multiple line input style.<br />
* '''vscroll''' - (bool) Causes the edit window to have a vertical scroller. Default is off.<br />
* '''autohscroll''' - (bool) Causes the horizontal area to scroll if necessary. Default is on.<br />
* '''autoenter''' - (bool) Causes the system to automatically send a "done" event when the user stops typing past a certain timeout. Default is off.<br />
* '''password''' - (bool) Causes the echoed characters to be single marks for password purposes. Default is off.<br />
An edit object may be bound to a string configuration attribute.<br />
<br />
Here's the definition of Wasabi:EditBox:<br />
<groupdef<br />
id="wasabi.edit" h="20"<br />
inherit_group="wasabi.objectframe.group"<br />
xuitag="Wasabi:EditBox" embed_xui="wasabi.edit.box"<br />
><br />
<edit id="wasabi.edit.box" x="1" y="1" w="-2" h="-2" relatw="1" relath="1"/><br />
</groupdef><br />
<br />
<br />
==<grid/>==<br />
The grid object is a very nice object for creating stretchable images that still look good on the edges. It is a graphic, like a layer, but unlike layer it is created by applying nine different bitmaps, stretching five of them. There are, as you might guess, nine parameters<br />
<br />
* '''topleft''' - (id) A bitmap element for the top left section of the grid.<br />
* '''top''' - (id) A bitmap element for the top middle section of the grid.<br />
* '''topright''' - (id) A bitmap element for the top right section of the grid.<br />
* '''left''' - (id) A bitmap element for the middle left section of the grid.<br />
* '''middle''' - (id) A bitmap element for the center section of the grid.<br />
* '''right''' - (id) A bitmap element for the middle right section of the grid.<br />
* '''bottomleft''' - (id) A bitmap element for the bottom left section of the grid.<br />
* '''bottom''' - (id) A bitmap element for the bottom middle section of the grid.<br />
* '''bottomright''' - (id) A bitmap element for the bottom right section of the grid. <br />
<br />
Essentially, the given rectangle of the grid is intersected with 2 horizontal and 2 vertical lines. The topleft, topright, bottomleft, and bottomright bitmap elements will not be resized. The top, left, middle, right, and bottom bitmap elements, however, will be stretched to make all fit the grid rectangle. Using intelligently sized bitmap elements is fairly critical for this object. If you're having trouble, try starting with all of your bitmap elements as equal-sized squares.<br />
<br />
Example:<br />
<grid x="70" y="25" w="-74" relatw="1" h="20" topleft="main.text.left" top="main.text.center" topright="main.text.right"/><br />
<br />
<br />
==<group/>==<br />
Groups are instantiated by using the group tag. Groups, when instantiated within a layout or some other groupdef, take the standard GuiObject params in order to define the group's instantiated size and properties, and then all of the contents of the group will be instantiated within the space it defines. At instantiation, a group will express a specified boundary rectangle and, thus, the positions of objects within it depending upon relative, proportional, or design coordinate systems may then be calculated.<br />
<br />
To specify which groupdef to instantiate, set the id parameter of the group tag to the id of the desired groupdef. The instantiation of each group can be so customized, however, group instantiates also may be assigned their own custom id to allow each instantiate to be found by code or script:<br />
* '''id''' (id) - The groupdef to be instantiated.<br />
* '''instance_id''' (str) - A new id value with which to be able find this particular instantiate.<br />
<br />
The following snippet will create two instantiates of the source group, with one specially customized (in the assumption that the "specialchild.maki" script will be handling the fact one is going to be special) :<br />
<groupdef id="child"><br />
<layer image="childimg" x="0" y="0" w="0" h="0" relatw="0" relath="0"/><br />
</groupdef><br />
<groupdef id="parent"><br />
<group id="child" x="0" y="0" w="0" relatw="0" h="90"/><br />
<group id="child" instance_id="special"<br />
notify="This is a special notification for this obj."<br />
x="0" y="90" w="0" relatw="0" h="-90" relath="1"/><br />
<script file="specialchild.maki"/><br />
</groupdef><br />
<br />
<br />
==<grouplist/>==<br />
A grouplist is, oddly enough, an object whose purpose is to accept and display a list of multiple groups. For instance, Wasabi's popup menu is a grouplist. A grouplist is expected to be filled in script, and it has no interesting parameters.<br />
<br />
<br />
==<layer/>==<br />
In Wasabi, the layer is analogous to the same-named object in photoshop. It is simply a nice bitmap graphic to be displayed in the user interface (with the standard alpha and region effects available to all guiobject derived objects, based by default on the properties of the bitmap element it houses). Here are its parameters:<br />
* '''image''' - (id) The id of the bitmap element to be used for display.<br />
* '''inactiveimage''' - (id) A secondary id to be displayed if this guiobject is set to "inactive" status.<br />
* '''region''' - (id) The id of a different bitmap element to use as the source of this object's region.<br />
* '''tile''' - (bool) Setting this flag will tile the image if the rectangular size of the layer is different than the rectangular size of the bitmap. The default is to stretch.<br />
* '''resize''' - (str) A specific string enumerating which direction one should allow the resizing of the parent layout if this object's region is gripped and dragged by the user. Incompatible with the move parameter on guiobject. See below.<br />
* '''scale''' - (str) A specific string enumerating which direction one should allow the scaling of the parent layout if this object's region is gripped and dragged by the user. Incompatible with the move parameter on guiobject. See below.<br />
* '''dblclickaction''' - (str) The string of an action to be sent into the system if this object is doubleclicked within its region.<br />
The resize and scale parameters transform the simple layer graphic into interactive gui objects in the system by enabling them to be dragged by the user to resize or change the scale of the parent layout. The eight possible values for these parameters are "top" "left" "right" "bottom" "topleft" "topright" "bottomleft" and "bottomright." If both resize and scale are set on a single layer, the object will act as a resizer by default but as a scaler if the ALT key is held down.<br />
<br />
<br />
==<animatedlayer/>==<br />
An animatedlayer is a series of frames of sprite animation displayed in the GUI. The frames of animation are specified in the bitmap element which is given in the image parameter to this object. The animation is expected to be a specific progression of frames of a fixed size, also to be specified via parameters on the object. Each frame of animation will have its own region. The animatedlayer object inherits directly from the layer object, so all of the above parameters are valid, along with these specific to animation:<br />
* '''frameheight''' - (int) The height in pixels of each cell of animation. If frameheight is set, the animation will be assumed to be a vertical strip of cells in the given bitmap.<br />
* '''framewidth''' - (int) The width in pixels of each cell of animation. If framewidth is set, the animation will be assumed to be a horizontal strip of cells in the given bitmap.<br />
* '''elementframes''' - (int) The number of total frames of animation. If this value is set, the animation will be assumed to be comprised of multiple bitmap elements whose ids are resolved by using the value of the image parameter as a printf-compatible formatting string with a single integer parameter. See below.<br />
* '''start''' - (int) The frame index which should be used as the beginning frame of the animation. Default is the first frame of the defined animation list.<br />
* '''end''' - (int) The frame index which should be used as the terminating frame of the animation. Default is the last frame of the defined animation list.<br />
* '''speed''' - (int) The delay in ms between each frame, on average. Default is 200 ms.<br />
* '''realtime''' - (bool) Setting this flag will force-redraw the animation area the moment the new frame is meant to be seen. Default behaviour is to wait for and go along with the other invalidations from the rest of the UI on the main thread's draw loop. Expect use of this flag to have a high impact on system performance on slower machines. In other words, don't use it unless you know what you're doing.<br />
* '''autoreplay''' - (bool) Setting this flag will cause the animation to repeat to the beginning frame once it has displayed the terminating frame of animation. Default is ON.<br />
* '''autoplay''' - (bool) Setting this flag will cause the animation to begin playing the moment it is loaded into the user interface. Default is OFF. See below.<br />
* '''debug''' - (bool) Setting this flag will cause the system to draw the current frame number of the animation on top of the animation graphics, for, as you might guess, debug purposes.<br />
<br />
You must note that animations are usually meant to be "triggered" through script, as too many live animations happily blitting their way through a deep and complex user interface using lots of alpha blending, et al, can cause significant performance bottlenecks on slow computers (especially if your users aren't expecting your application to be eating all of the machine resources). With this in mind, if you just create an animated layer and drop it into a skin, it will not begin animating unless you set the autoplay parameter.<br />
<br />
There are three different ways to present animation frames to this object. The frames may either all be concatenated into a vertical or horizontal "filmstrip" style bitmap element -- in which case the height or width of each animation cell (respectively) should be set with the frameheight or framewidth parameter. <br />
The third way to give this object its animation frames is more complex and consists of loading multiple bitmap elements with each bitmap representing one frame of animation. This is done by first setting the elementframes parameter with the number of frames to be loaded, then by using a special formatting string as the image parameter. For those familiar with the printf function, when the elementframes parameter is set, that integer will be run in a for loop and the image name will be used as the formatting string to a printf function that takes only the current integer in the for loop as a parameter.<br />
For those unfamiliar with printf, this will seem a bit confusing. Somewhere in the string you pass to the image parameter, you should have the two characters %d, and these characters will be replaced by the character representation of the number as it loads bitmap elements. If you want to have 0-loaded prefix characters (for instance "01-09" instead of "1-9"), you can place %02d into your image parameter, and if there aren't enough characters in the number to make up 2 full digits, the number will be left-padded with the zero character. You can just as easily use any number of padding characters as well. <br />
I highly suspect this all still makes little sense, so let me give you a simplified example (missing important parameters) to show three different animated layers each loading three sets of differently named bitmaps:<br />
<elements><br />
<bitmap id="bmp1"/> <br />
<bitmap id="bmp2"/> <br />
<bitmap id="bmp3"/> <br />
<bitmap id="bmp01img"/><br />
<bitmap id="bmp02img"/><br />
<bitmap id="bmp03img"/><br />
<bitmap id="b00001mp"/><br />
<bitmap id="b00002mp"/><br />
<bitmap id="b00003mp"/><br />
</elements><br />
<groupdef id="whatever"><br />
<animatedlayer image="bmp%d" elementframes="3"/><br />
<animatedlayer image="bmp%02dimg" elementframes="3"/><br />
<animatedlayer image="b%05dmp" elementframes="3"/><br />
</groupdef><br />
<br />
<br />
==<layoutstatus/>==<br />
The layoutstatus implements the small statusbar that can be found at the bottom of many of the default normal layouts which can contain status text, appcmds buttons, and a proportionally completed progress bar. The two parameters to this object control what appcmds will be allowed in the status bar:<br />
* '''exclude''' - (str) A semicolon delimited list of names of appcmds which should not be shown by this control.<br />
* '''include_only''' - (str) A semicolon delimited list of names of appcmds which will be the only appcmds allowed to be shown by this control.<br />
For the most part, these layoutstatus objects are only controllable from code.<br />
<br />
<br />
==<list/>==<br />
The list object is similar but not identical to the Win32 list common control. It is an optionally multicolumnar list whose purpose is to display multiple pieces of information per horizontal row. It may be filled directly by encoding the contents in the XML, by attaching the object to a proper text feed, or by calling methods on the object from script. The parameters for this object are:<br />
* '''items''' - (str) A properly delimited string of data used to fill the list. See below.<br />
* '''multiselect''' - (bool) This flag, when set, allows the user to select multiple items in the list. Default is to allow multiselect.<br />
* '''autodeselect''' - (bool) This flag, when set, causes selection of any single item in the list to automatically deselect all other items in the list. Default is to not autodeselect.<br />
* '''select''' - (str) The text of a list item to be selected.<br />
* '''antialias''' - (bool) Setting this flag causes the text to be rendered antialiased if possible.<br />
* '''feed''' - (id) The id of a text feed to be used to fill this list.<br />
* '''hoverselect''' - (bool) This flag causes list items to be selected if the user hovers over them. Default is to not hoverselect.<br />
* '''sort''' - (bool) This flag causes the list to sort itself. Default is to not sort.<br />
* '''selectonupdown''' - (bool) This flag causes the list to interpret the keyboard commands to mean "change my selection to the item." Default is to select on keyboard events.<br />
* '''numcolumns''' - (int) How many columns to show. Default is one.<br />
* '''columwidths''' - (int) A semicolon delimited list of integers specifying how to size the column widths in this list. See below.<br />
* '''columnlabels''' - (str) A semicolon delimited list of strings to be used as the multiple column labels.<br />
The list object depends upon being fed numerous strings with proper syntax in order to properly generate and populate a complex list display. The syntax for the items parameter (which is the same syntax as the feed must provide) is to delimit each full row in the list with the ';' semicolon character and to delimit each column entry per row with the ',' character. The columnwidths and columnlabels also require a semicolon (';') delimited list of data, one entry per column. Note that if -1 is given as a width, those columns will be of dynamic width and split up the leftover pixels among themselves. The default is one column with no labels and a width of -1.<br />
<br />
Here is a sample list object with 3 rows and 3 columns:<br />
<list id="three.by.three"<br />
items="row1,text,1;row2,moretext,2;row3,stilltext,3"<br />
numcolumns="3" columnwidths="50,-1,50"<br />
multiselect="0" autodeselect="1"<br />
/><br />
<br />
<br />
==<mouseredir/>==<br />
This object simply redirects all mouse events from its region to the target object specified in the parameter:<br />
* '''target''' - (id) The target object to get mouse events.<br />
This is useful for when some objects get overlapped by nonfunctional graphics when laying out complex interfaces.<br />
<br />
<br />
==<Wasabi:RadioGroup/>==<br />
The Wasabi:RadioGroup object is an invisible object whose purpose is to centralize the functionality of multiple Wasabi:CheckBox objects instantiated in radiobutton mode. The radioid params on the Wasabi:CheckBox instantiates should give the id of one of these Wasabi:RadioGroup objects. It has no unique parameters. Here is a snippet of simple radiobutton functionality:<br />
<Wasabi:RadioGroup id="enableddisabled"/><br />
<Wasabi:CheckBox x="50" y="110" w="60"<br />
text="Enabled" radioid="enableddisabled"<br />
cfgattrib="{9149C445-3C30-4E04-8433-5A518ED0FDDE};Enable desktop alpha"<br />
radioval="1"<br />
/><br />
<Wasabi:CheckBox x="-125" y="110" w="62" relatx="1"<br />
text="Disabled" radioid="enableddisabled"<br />
cfgattrib="{9149C445-3C30-4E04-8433-5A518ED0FDDE};Enable desktop alpha"<br />
radioval="0"<br />
/><br />
<br />
<br />
==<rect/>==<br />
A nice flat rectangle. It may be either filled or hollow, and if hollow you may specify only some edges drawn. Here are its parameters:<br />
* '''color''' - (id) The id of a color element, or an comma delimited integer triplet RGB value. Default is "255,00,255" (an ugly color to remind you to set it).<br />
* '''filled''' - (bool) This flag causes the entire rectangular area to be filled with color. Default is to not be filled.<br />
* '''edges''' - (str) A pipe ("|") delimited set of one or all of the following: "left" "right" "top" "bottom" Default is all, ie: "left|right|top|bottom".<br />
<br />
<br />
==<script/>==<br />
Scripts allow for the simple creation of UI functionality without requiring C++ code. While scripts are "compiled" into "script binaries," these script binaries are special to wasabi and, more importantly, can be run by any compatible Wasabi runtime on any OS to which Wasabi has a runtime. Scripts are bound like GuiObjects into layout or groupdef sections using the script tag and have the ability to find and modify the nearby sibling and child objects once the UI has been fully instantiated. Scripts have two important parameters:<br />
* '''file''' - (str) The filename of the .maki file to load, relative to this xml file.<br />
* '''param''' - (str) A string that will be available to the instance of the .maki file as an instance specific parameter.<br />
Note that a single .maki file may be instantiated as a script object numerous times over, and each instantiation can have its own specific parameter data. Judicious use of this feature can help minimize your reliance on hardcoded strings and limited flexibility in your scripting.<br />
<br />
<br />
==<slider/> & <Wasabi:HSlider/> & <Wasabi:VSlider/>==<br />
The slider object consists of a background set of images, and a thumb. The thumb is constrained to move in one dimension -- horizontally or vertically, depending upon its orientation. The distance in pixels travelled by the thumb across its total distance is interpollated to produce a value between the low and high boundary integers which is assigned to any configuration attribute which may happen to be attached. Here are the parameters for slider:<br />
* '''barleft''' - (id) The bitmap element for the left or top position of the slider.<br />
* '''barmiddle''' - (id) The bitmap element for the middle, stretched, position of the slider.<br />
* '''barright''' - (id) The bitmap element for the right or bottom position of the slider.<br />
* '''thumb''' - (id) The bitmap element for the slider thumb.<br />
* '''downthumb''' - (id) The bitmap element for the slider thumb when held by the user.<br />
* '''hoverthumb''' - (id) The bitmap element for the slider thumb when the user's mouse is above it.<br />
* '''orientation''' - (str) Either "v" or "vertical" to make the slider vertical, otherwise it will be horizontal.<br />
* '''low''' - (int) Set the low-value boundary. Default is 0.<br />
* '''high''' - (int) Set the high-value boundary. Default is 255.<br />
<br />
<br />
==<snappoint/>==<br />
The snappoint is an invisible point that will attract other snappoint objects with the same id in any other layout and make them want to dock, like little magnets. These objects have only the following subset of guiobject XML parameters:<br />
* '''id''' - (id) All snappoint objects with the same id will snap to each other. Different ids ignore each other.<br />
* '''x''' - (int) The x position of the snappoint, see: guiobject.<br />
* '''y''' - (int) The y position of the snappoint, see: guiobject.<br />
* '''relatx''' - (int) The horizontal coordinate space of the snappoint, see: guiobject.<br />
* '''relaty''' - (int) The vertical coordinate space of the snappoint, see: guiobject.<br />
<br />
<br />
==<Wasabi:TabSheet/>==<br />
The Wasabi:TabSheet object contains multiple group instances within it and allows the user to switch between the display of those groups by the ability to click on a list of tab buttons at the top of the rectangular area of the Wasabi:TabSheet. The name parameter of each groupdef is displayed as the text in the tab which corresponds to it. Here are the Wasabi:TabSheet parameters:<br />
* '''windowtype''' - (str) A windowtype string which will instantiate one of every groupdef with the same windowtype and every window class registered with a window creation service to include this windowtype.<br />
* '''children''' - (id) A semicolon delimited list of groupdef ids to also be instantiated as children of this tabsheet.<br />
* '''type''' - (int) There are two different themed display styles for Wasabi:TabSheet. One is with multiple tabs (sheet style), one is with a single button on top that will popup a menu with all the possible tab choices (sidecar style). The Default is sheet style, which is a value of -2. Any other value besides -2 will give you sidecar style.<br />
* '''content_margin_top''' - (int) A margin in pixels to offset the content from the client rectangle of the Wasabi:Tabsheet.<br />
* '''content_margin_left''' - (int) A margin in pixels to offset the content from the client rectangle of the Wasabi:Tabsheet.<br />
* '''content_margin_right''' - (int) A margin in pixels to offset the content from the client rectangle of the Wasabi:Tabsheet.<br />
* '''content_margin_bottom''' - (int) A margin in pixels to offset the content from the client rectangle of the Wasabi:Tabsheet.<br />
<br />
<br />
==<text/> & <Wasabi:Text/>==<br />
The text object is for using the system to render some text in the font of your choice.<br />
Since Winamp 5.5 (skinversion 1.3) text objects can have multiple lines. For a new line use this "/n"<br />
<br />
* '''display''' - (str) Either a specific system display string or the string identifier of a text feed. Setting this value will override the text parameter. See below.<br />
* '''ticker''' - (bool) Setting this flag causes the object to scroll left and right if the text does not fit the rectangular area of the text object.<br />
* '''antialias''' - (bool) Setting this flag causes the text to be rendered antialiased if possible.<br />
* '''text''' - (str) A static string to be displayed.<br />
* '''default''' - (str) A parameter alias for text.<br />
* '''font''' - (id) The id of a bitmapfont or truetypefont element. If no element with that id can be found, the OS will be asked for a font with that name instead.<br />
* '''fontsize''' - (int) The size to render the chosen font.<br />
* '''align''' - (str) One of the following three possible strings: "left" "center" "right" -- Default is "left."<br />
* '''valign''' - (str) One of the following three possible strings: "top" "center" "bottom" -- Default is "top."<br />
* '''color''' - (int) The comma delimited RGB color of the text.<br />
* '''shadowcolor''' - (int) The comma delimited RGB color for underrendered shadow text.<br />
* '''shadowx''' - (int) The x offset of the shadowrender.<br />
* '''shadowy''' - (int) The y offset of the shadowrender.<br />
* '''timeroffstyle''' - (int) How to display an empty timer: "0" = " : ", "1" = "00:00", and "2"="" (if one is displaying time)<br />
* '''timecolonwidth''' - (int) How many extra pixels wider or smaller should the colon be when displaying time. Default is -1.<br />
* '''nograb''' - (bool) Setting this flag will cause the text object to ignore left button down messages. Default is off.<br />
* '''showlen''' - (bool) Setting this flag will cause the text display to be appended with the length in minutes and seconds of the current song. Default is off.<br />
* '''forcefixed''' - (bool) Force the system to attempt to render the display string with fixed-width font spacing.<br />
* '''forceupcase''' - (bool) Force the system to make the display string all uppercase before display.<br />
* '''forceuppercase''' - (bool) Force the system to make the display string all uppercase before display.<br />
* '''forcelocase''' - (bool) Force the system to make the display string all lowercase before display.<br />
* '''forcelowercase''' - (bool) Force the system to make the display string all lowercase before display. <br />
* '''bold''' - (bool) Render the display string in bold.<br />
* '''wrap''' - (bool) Setting this flag will cause the text to wrap in its rectangular space. Default is off.<br />
* '''dblclickaction''' - (str) A string in the form "SWITCH;layout" where layout is the id of a layout in this object's parent container. No other actions function on this object. This action is deprecated.<br />
* '''offsetx''' - (int) Extra pixels to be added to or subtracted from the calculated x value for the display string to render.<br />
* '''offsety''' - (int) Extra pixels to be added to or subtracted from the calculated x value for the display string to render.<br />
"SONGNAME" - The name string of the currently playing song (from metadb).<br />
"SONGINFO" - The full info string of the currently playing song (from metadb).<br />
"SONGARTIST" - The artist string of the currently playing song (from metadb).<br />
"SONGTITLE" - The title string of the currently playing song (from metadb).<br />
"SONGALBUM" - The album string of the currently playing song (from metadb).<br />
"SONGLENGTH" - The length string of the currently playing song (from metadb).<br />
"TIME" - The length string of the currently playing song.<br />
"TIMEELAPSED" - The elapsed time string of the currently playing song.<br />
"TIMEREMAINING" - The time remaining string of the currently playing song.<br />
"COMPONENTBUCKET" - The id of the componentbucket (thinger) item the mousecursor is currently hovering above.<br />
"SONGBITRATE" - The bitrate string of the currently playing song (from metadb).<br />
"SONGSAMPLERATE" - The sample string of the currently playing song (from metadb).<br />
<br />
*** Broken Action (Winamp 5) ***<br />
"NORMALIZER:STATUS" - The current status of the audio normalizer.<br />
<br />
Example:<br />
<text x="81" y="11" w="25" h="21" antialias="0" text="Read This" align="center" color="0,0,0" bold="1"/> <br />
<br />
<br />
==<Wasabi:TitleBox/>==<br />
The Wasabi:TitleBox object is a nice way to put a simple rectangular frame and title around your content groups. It has the following parameters:<br />
* '''title''' - (str) The string to display in the title area. Default is to use the name parameter of the content group.<br />
* '''content''' - (id) The id of the groupdef to instantiate as content.<br />
* '''centered''' - (bool) Setting this flag will center the title text. Default is to not be centered (and be left justified).<br />
* '''suffix''' - (str) A string which will be appended to the title before it is displayed. In this way, if you instantiate multiple groups as content, each name change can still have a string appended.<br />
<br />
<br />
==<Wasabi:Titlebar/>==<br />
The Wasabi:TitleBar is the graphically themed bar that is placed at the top of all of the Wasabi:StandardFrame windows. It has the same parameters as the text object, which control the text display of the titlebar.<br />
<br />
<br />
==<tree/>==<br />
The tree object displays a hierarchical set of information with multiple items, where each item may in turn have multiple subitems. Let's examine its parameters:<br />
* '''items''' - (str) A specially formatted string describing the hierarchical creation of the tree info. See below.<br />
* '''feed''' - (str) The string identifier of a text feed which should provide a string in the same format as the items parameter.<br />
* '''sorted''' - (bool) Setting this flag will cause all of the tree items to be sorted before display. Default is to sort.<br />
* '''childtabs''' - (bool) Setting this flag will cause all tree items with children to display a tab graphic beside them. Default is to show tab graphics.<br />
* '''expandroot''' - (bool) Setting this flag will cause all root tree items to display with their children pre-expanded. Default is to pre-expand root tree items.<br />
The syntax required to describe the hierarchy of tree items is a semicolon delimited list of objects in the form "name(list)" where name is the string to display for that tree item and list is another semicolon delimited list of objects which are the direct children of name. <br />
<br />
The following snippet will create a tree with one root node that has three child nodes, with each child node having differing numbers of sub nodes:<br />
<tree id="example.tree"<br />
x="0" y="0" w="0" h="0" relatw="1" relath="1"<br />
items="root(child1(sub1;sub2);child2;child3(sub3))"<br />
/><br />
<br />
<br />
==<vis/>==<br />
The vis object is the multistate audio visualization display. It has a multitude of parameters for how simple it is:<br />
* '''colorallbands''' - (int) The comma delimited RGB triplet to color all the spectroscope bands.<br />
* '''colorband1''' - (int) The comma delimited RGB triplet to color spectroscope band 1.<br />
* '''colorband2''' - (int) The comma delimited RGB triplet to color spectroscope band 2.<br />
* '''colorband3''' - (int) The comma delimited RGB triplet to color spectroscope band 3.<br />
* '''colorband4''' - (int) The comma delimited RGB triplet to color spectroscope band 4.<br />
* '''colorband5''' - (int) The comma delimited RGB triplet to color spectroscope band 5.<br />
* '''colorband6''' - (int) The comma delimited RGB triplet to color spectroscope band 6.<br />
* '''colorband7''' - (int) The comma delimited RGB triplet to color spectroscope band 7.<br />
* '''colorband8''' - (int) The comma delimited RGB triplet to color spectroscope band 8.<br />
* '''colorband9''' - (int) The comma delimited RGB triplet to color spectroscope band 9.<br />
* '''colorband10''' - (int) The comma delimited RGB triplet to color spectroscope band 10.<br />
* '''colorband11''' - (int) The comma delimited RGB triplet to color spectroscope band 11.<br />
* '''colorband12''' - (int) The comma delimited RGB triplet to color spectroscope band 12.<br />
* '''colorband13''' - (int) The comma delimited RGB triplet to color spectroscope band 13.<br />
* '''colorband14''' - (int) The comma delimited RGB triplet to color spectroscope band 14.<br />
* '''colorband15''' - (int) The comma delimited RGB triplet to color spectroscope band 15.<br />
* '''colorband16''' - (int) The comma delimited RGB triplet to color spectroscope band 16.<br />
* '''colorbandpeak''' - (int) The comma delimited RGB triplet to color the spectroscope peak line.<br />
* '''colorallosc''' - (int) The comma delimited RGB triplet to color the whole oscilloscope.<br />
* '''colorosc1''' - (int) The comma delimited RGB triplet to color oscilloscope section 1.<br />
* '''colorosc2''' - (int) The comma delimited RGB triplet to color oscilloscope section 2.<br />
* '''colorosc3''' - (int) The comma delimited RGB triplet to color oscilloscope section 3.<br />
* '''colorosc4''' - (int) The comma delimited RGB triplet to color oscilloscope section 4.<br />
* '''colorosc5''' - (int) The comma delimited RGB triplet to color oscilloscope section 5.<br />
* '''channel''' - (int) One of three values for which channel to monitor: "1" is left channel, "2" is right channel, "3" is stereo. Default is stereo.<br />
* '''fliph''' - (bool) If this flag is set, it blits the vis pixels flipped horizontally.<br />
* '''flipv''' - (bool) If this flag is set, it blits the vis pixels flipped vertically.<br />
* '''mode''' - (int) One of three values for which mode to display: "0" is no display, "1" is spectroscope, "2" is oscilloscope. Default is to read from a config item.<br />
When the user clicks on the vis, it will cycle between its three modes.<br />
<br />
<br />
==<eqvis/>==<br />
The eqvis object is rather specific to media players, as it is the spline display for the eq settings in the Wasabi Media Player.<br />
* '''colortop''' - (str) A color value or color element id for the top portion of the spline display.<br />
* '''colormiddle''' - (str) A color value or color element id for the middle portion of the spline display.<br />
* '''colorbottom''' - (str) A color value or color element id for the bottom portion of the spline display.<br />
* '''colorpreamp''' - (str) A color value or color element id for the preamp bar in the spline display.<br />
<br />
<br />
==<gradient/>==<br />
The gradient object creates a rectangular color gradient. The available parameters are:<br />
* '''gradient_x1''' - (float) A floating point value for the left side of the rectangle. Default is 0.0<br />
* '''gradient_y1''' - (float) A floating point value for the top side of the rectangle. Default is 0.0<br />
* '''gradient_x2''' - (float) A floating point value for the right side of the rectangle. Default is 1.0<br />
* '''gradient_x1''' - (float) A floating point value for the bottom side of the rectangle. Default is 1.0<br />
* '''points''' - (str) A complex string defining color values for at least two value points with which to build the gradients. See below.<br />
The points syntax is a semicolon delimited list of key=value pairs where the key is a floatingpoint number representing a point in the "gradient space" and the value is an RGB triplet (assumed full alpha) or RGBA quad. For instance, the following object would create a smooth gradient between red in the top left and green at half alpha in the bottom right:<br />
<gradient id="red.to.green"<br />
x="0" y="0" w="0" h="0" <br />
relatw="1" relath="1"<br />
points="0.0=255,0,0,255;1.0=0,255,0,128"<br />
/><br />
<br />
<br />
==<Wasabi:StandardFrame:Status/>==<br />
<br />
==<Wasabi:StandardFrame:NoStatus/>==<br />
<br />
==<Wasabi:StandardFrame:Modal/>==<br />
<br />
==<Wasabi:StandardFrame:Static/>==<br />
The Wasabi:StandardFrame objects are rectangular frames you can use to encapsulate your own layout contents within the currently themed standard frame. They all have the following parameters:<br />
* '''content''' - (id) The id of the groupdef to instantiate within the Wasabi:StandardFrame.<br />
* '''padtitleleft''' - (int) The distance in pixels to pad the title to the left.<br />
* '''padtitleright''' - (int) The distance in pixels to pad the title to the right.<br />
* '''shade''' - (id) The id of the layout within our container we should switch to if the titlebar is doubleclicked (ie: the id of the windowshade layout). Default is no functionality.<br />
The Wasabi:StandardFrame:Status object has a status bar, while the Wasabi:StandardFrame:NoStatus does not. The Wasabi:StandardFrame:Static object inherits from Wasabi:StandardFrame:NoStatus and also instantiates the wasabi panel graphics. The Wasabi:StandardFrame:Modal object does all that and also removes the control menus to make a fully modal dialog frame.<br />
<br />
<br />
==<wndholder/>==<br />
A wndholder object, similar to a customobject, holds user interface windows based upon what param is given. The wndholder can also hold window types by guid or groupdef instantiations by id. Here are its parameters:<br />
* '''hold''' - (id) A semicolon delimited list of guids or groupdef ids to hold.<br />
* '''component''' - (id) A parameter alias for hold.<br />
* '''param''' - (id) A parameter alias for hold.<br />
* '''noshowcmdbar''' - (bool) Setting this flag will disable the Wasabi command bar.<br />
* '''noanimatedrects''' - (bool) Setting this flag will disable animated rectangle motion.<br />
* '''disableanimatedrects''' - (bool) A parameter alias for noanimatedrects.<br />
* '''autoopen''' - (bool) Setting this flag will cause the object to auto open.<br />
* '''autoclose''' - (bool) Setting this flag will cause the object to auto close.<br />
Using a wndholder object indicates to the system that you want to be the "container of record" for the possible requested guids when they are launched by the system through, for instance, the C++ coder registering his window class with registerAutopopup(), which calls the underlying api->skinwnd_createByGuid(). The container within which this wndholder is instantiated should also be given a component parameter with the same values. This component parameter is simply a hint to Wasabi that a wndholder object that will accept that component parameter lives within the container.<br />
<br />
<br />
==<objdirview/>==<br />
The objdirview object displays a tree of hierarchical information to the user, based on a code concept called an Object Directory. An Object Directory is, in essence, just a container of arbitrary items so this object is merely the display of its contents. Here are its parameters:<br />
* '''dir''' - (str) The string identifier of the objdir to which this object should connect.<br />
* '''target''' - (id) The id of an object to which this object may direct the actions of its internal items being selected.<br />
* '''displaytarget''' - (id) The id of a customobject which will be assigned to display the display group parameter of the currently selected objdir item.<br />
* '''defaultdisplay''' - (id) The id of a groupdef to display inside displaytarget if no objdir items are selected.<br />
When items in the objdirview are selected, the objdir is sent an event telling it that an item was selected. The target parameter from XML is included in the data sent in that event. However, the implemented functionality for that event is wholly at the discretion of the programmer implementing the specific objdir in question. For the QueryDir object used in Winamp3's media library, the target param is for a nearby queryline object to be told the selection is changing. Your mileage may vary with other objects.<br />
<br />
<br />
==<Wasabi:PathPicker/>==<br />
The Wasabi:PathPicker object is a simple object to display a text string of a directory path chosen by the user. When the user clicks on the object, a dir selection service is started, allowing the user to choose a directory path. Attach this object to a string configuration attribute and you have a simple way for users to choose directories as preferences. The Wasabi:PathPicker object has no unique parameters.<br />
<br />
<br />
==<querydrag/>==<br />
The querydrag object is used to create a visual "drag source" for a nearby queryresults object. The user may click and drag this object and by doing so representationally drag the text of the current query in the queryresults object (which can be dropped into a playlist editor to fill its contents with the results of that query). It has only two parameters:<br />
* '''image''' - (id) The bitmap element to display.<br />
* '''source''' - (id) The source queryresults object. Default is the nearest.<br />
If no valid source can be found, this object silently fails to drag.<br />
<br />
<br />
==<queryline/>==<br />
The invisible queryline object is used to host a text query to be applied to a queryresults object. One possible use would be to write a script linking the text in a Wasabi:HistoryEditBox to the query parameter of a queryline. And, speaking of its parameters, here they are:<br />
* '''querylist''' - (id) The id of the queryresults which will take the query. Default is to not connect (ie: this param is kinda sorta mandatoryish if you want anything interesting to happen).<br />
* '''query''' - (str) The string of the query itself.<br />
* '''auto''' - (bool) Whether or not to execute an autoquery based on the query parameter (ie: "search on the name column for this substring" instead of "run this query"). Default is to use the string directly as a query (not autoquery).<br />
<br />
<br />
==<queryresults/>==<br />
The queryresults object is the an invisible binding object that coordinates the filtration of the database by numerous multiple other objects. The queryline and filterlist objects eventually define a single output from the database, and this information is kept in the queryresults object. It has only one parameter:<br />
title - (str) The human readable title for your queryresults. I have no idea why this would be important.<br />
Magically, it seems, placing a queryresults object in the same group next to a PlaylistEditor object makes that PlaylistEditor get filled with the queryresults information. I have no idea how this can be, and sense the telltale signs of powerful dark necromancy at work, here.</div>Culixhttp://wiki.shoutcast.com/wiki/Skin_DeveloperSkin Developer2010-11-30T03:28:43Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>{{Template:NavBar}}<br />
<br />
<br />
== Classic Skins ==<br />
Classic skins are skins that adhere to the Winamp 2 style model. Classic skins are easier to create than Modern skins but do not allow the author to change the form or function of the player. Classic authors may only replace a standard set of images that alter the player's visual appearance.<br />
<br />
* '''[[Creating Classic Skins]]'''<br />
<br />
== Modern Skins ==<br />
Modern or Freeform skins were originally designed to work with Winamp3. What separates them from the average skin is the fact that they are not confined to the classic rectangular shape. In fact they can be any shape you want them to be and you can put the Winamp control buttons anywhere you want. Some skinners have even added extra buttons that extend the functionality of Winamp right there on the skin. Sounds too good to be true huh? Well these skins require a bit more coding to make and some of the graphics that go into them are quite large. Consequently, Freeform skins may take a bit longer to download from our site and they may take a few extra seconds to load when you switch from one skin to another. But trust me when I say that Freeform skins are worth the extra time and effort. Skin developers have done some incredible things with these skins. You have to check them out.<br />
<br />
* '''[[Creating Modern Skins]]'''<br />
<!-- SkinWizard XML Designer 1.0 --><br />
<br />
<!-- Background elements --><br />
<groupdef id="Backgrounds" name="BckElements"><br />
<layer id="LayerID1" image="common/bck_seek.png" x="19" y="92" /><br />
<layer id="LayerID2" image="common/bck_visualizer.png" x="22" y="25" /><br />
<layer id="LayerID3" image="common/slider_volume_BCK.png" x="212" y="64" /><br />
</groupdef><br />
<br />
<!-- Player Buttons --><br />
<groupdef id="PlayButtons" name="Player Buttons"><br />
<button<br />
id="btnPlay"<br />
action="PLAY" param=""<br />
x="11" y="106"<br />
image="vista/vst_btn_play_N.png"<br />
hoverimage="vista/vst_btn_play_H.png"<br />
downImage="vista/vst_btn_play_D.png"<br />
tooltip="Play"<br />
/><br />
<br />
<button<br />
id="btnPause"<br />
action="PAUSE" param=""<br />
x="61" y="117"<br />
image="vista/vst_btn_pause_N.png"<br />
hoverimage="vista/vst_btn_pause_H.png"<br />
downImage="vista/vst_btn_pause_D.png"<br />
tooltip="Pause"<br />
/><br />
<br />
<button<br />
id="btnStop"<br />
action="STOP" param=""<br />
x="104" y="117"<br />
image="vista/vst_btn_stop_N.png"<br />
hoverimage="vista/vst_btn_stop_H.png"<br />
downImage="vista/vst_btn_stop_D.png"<br />
tooltip="Stop"<br />
/><br />
<br />
<button<br />
id="btnEject"<br />
action="EJECT" param=""<br />
x="146" y="117"<br />
image="vista/vst_btn_open_N.png"<br />
hoverimage="vista/vst_btn_open_H.png"<br />
downImage="vista/vst_btn_open_D.png"<br />
tooltip="Eject / Open"<br />
/><br />
<br />
<button<br />
id="btnPrev"<br />
action="PREV" param=""<br />
x="240" y="116"<br />
image="xp/xp_btn_prev_N.png"<br />
hoverimage="xp/xp_btn_prev_H.png"<br />
downImage="xp/xp_btn_prev_D.png"<br />
tooltip="Previous"<br />
/><br />
<br />
<button<br />
id="btnNext"<br />
action="NEXT" param=""<br />
x="288" y="116"<br />
image="xp/xp_btn_next_N.png"<br />
hoverimage="xp/xp_btn_next_H.png"<br />
downImage="xp/xp_btn_next_D.png"<br />
tooltip="Next"<br />
/><br />
<br />
</groupdef><br />
<br />
<!-- Header and additional buttons --><br />
<groupdef id="grTechButtons" name="Other Buttons"><br />
<togglebutton<br />
id="btnPL"<br />
action="TOGGLE" param="guid:pl"<br />
x="19" y="0"<br />
image="vista/vst_btn_PL_N.png"<br />
activeImage="vista/vst_btn_PL_H.png"<br />
downImage="vista/vst_btn_PL_D.png"<br />
hoverimage="vista/vst_btn_PL_H.png"<br />
tooltip="Playlist"<br />
/><br />
<br />
<togglebutton<br />
id="btnML"<br />
action="TOGGLE" param="guid:ml"<br />
x="47" y="0"<br />
image="vista/vst_btn_ML_N.png"<br />
activeImage="vista/vst_btn_ML_H.png"<br />
downImage="vista/vst_btn_ML_D.png"<br />
hoverimage="vista/vst_btn_ML_H.png"<br />
tooltip="Media library"<br />
/><br />
<br />
<button<br />
id="btnClose"<br />
action="CLOSE" param=""<br />
x="340" y="17"<br />
image="xp/btn_capt_close_N.png"<br />
hoverimage="xp/btn_capt_close_H.png"<br />
downImage="xp/btn_capt_minimize_D.png"<br />
tooltip="Close"<br />
/><br />
<br />
<button<br />
id="ButtonID2"<br />
action="MINIMIZE" param=""<br />
x="340" y="32"<br />
image="xp/btn_capt_minimize_N.png"<br />
hoverimage="xp/btn_capt_minimize_H.png"<br />
downImage="xp/btn_capt_minimize_D.png"<br />
tooltip="Minimize"<br />
/><br />
<br />
</groupdef><br />
<br />
<!-- Components and elements --><br />
<groupdef id="grComponents" name="Components"><br />
<vis id="Visualization"<br />
x="30" y="30"<br />
w="76" h="40"<br />
relatx="0"<br />
alpha="255"<br />
gammagroup="gamma"<br />
ColorBand1="255,255,255"<br />
ColorBand2="255,255,255"<br />
ColorBand3="255,255,255"<br />
ColorBand4="255,255,255"<br />
ColorBand5="255,255,255"<br />
ColorBand6="255,255,255"<br />
ColorBand7="255,255,255"<br />
ColorBand8="255,255,255"<br />
ColorBand9="255,255,255"<br />
ColorBand10="255,255,255"<br />
ColorBand11="255,255,255"<br />
ColorBand12="255,255,255"<br />
ColorBand13="255,255,255"<br />
ColorBand14="255,255,255"<br />
ColorBand15="255,255,255"<br />
ColorBand16="255,255,255"<br />
<br />
colorosc1="255,255,255"<br />
colorosc2="255,255,255"<br />
colorosc3="255,255,255"<br />
colorosc4="255,255,255"<br />
colorosc5="255,255,255"<br />
colorbandpeak="255,255,255"<br />
/><br />
<br />
<Text<br />
id="SongInfo" ticker="1"<br />
display="songname" showlen="1"<br />
x="118" y="26"<br />
w="210" h="17"<br />
fontsize="16" font="" color="255,255,255"<br />
shadowcolor="128,128,128" shadowx="1" shadowy="1"<br />
/><br />
<br />
<text<br />
id="Timer"<br />
display="time"<br />
x="118" y="47"<br />
w="80" h="25"<br />
font=""<br />
fontsize="18"<br />
color="255,255,255"<br />
align="left"<br />
antialias="1" bold="1"<br />
shadowcolor="128,128,128" shadowx="1" shadowy="1"<br />
timeroffstyle="1"<br />
/><br />
<br />
<slider<br />
id="Slider"<br />
action="SEEK"<br />
x="18" y="85"<br />
w="317" h="20"<br />
orientation="horizontal"<br />
thumb="vista/vista_thumb_N.png"<br />
hoverThumb="vista/vista_thumb_H.png"<br />
downThumb="vista/vista_thumb_D.png"<br />
/><br />
<br />
<slider<br />
id="Slider"<br />
action="VOLUME"<br />
x="208" y="63"<br />
w="115" h="12"<br />
orientation="horizontal"<br />
thumb="xp/xp_thumb_N.png"<br />
hoverThumb="xp/xp_thumb_H.png"<br />
downThumb="xp/xp_thumb_H.png"<br />
/><br />
<br />
</groupdef><br />
<br />
<container id="main" name="Main Window" default_x="0" default_y="0" default_visible="1" w="362" h="162"><br />
<layout id="normal" background="common/Background_player.png" w="400" h="300" desktopalpha="1" ><br />
<br />
<group id="Backgrounds" w="362"/><br />
<group id="PlayButtons" w="360" /><br />
<group id="grTechButtons" w="360" /><br />
<group id="grComponents" w="360" /><br />
</layout><br />
<br />
</container><br />
<br />
== ClassicPro Skins ==<br />
ClassicPro skins is a blend of a Classic Winamp skin and a Modern Winamp skin. You don’t need to do any coding to create your skin because all the coding will be done by the ClassicPro plugin. The layout is similar to the Classic Winamp layout but also resizable using a Single-User-Interface ([[SUI]]) to display components.<br />
<br />
[http://cpro.skinconsortium.com/ ClassicPro Official Website]<br />
<br />
* '''[[Creating a ClassicPro Skin]]'''<br />
<br />
==Developer Resources==<br />
*[[Articles#Classic_Skins|Classic Skin Articles]]<br />
*[[Articles#Modern_Skins|Modern Skin Articles]]<br />
*[[Developers_FAQ#Skin_Developer_FAQ|Skin FAQ]]<br />
<br />
==Community Links==<br />
*Forums: [http://forums.winamp.com/forumdisplay.php?s=&forumid=5 Classic Skins]<br />
*Forums: [http://forums.winamp.com/forumdisplay.php?s=&forumid=123 Modern Skins]<br />
*Forums: [http://forums.winamp.com/forumdisplay.php?s=&forumid=18 Skinning Tips and Tricks]<br />
*Forums: [http://forums.winamp.com/forumdisplay.php?s=&forumid=12 Arts and Design]<br />
*Forums: [http://forums.winamp.com/forumdisplay.php?s=&forumid=119 Skin Removal Reporting]<br />
*Upload: [http://www.winamp.com/user/submit Submit Your Skin]<br />
**[http://www.winamp.com/user/submit-skin-classic Submit Classic Skin]<br />
**[http://www.winamp.com/user/submit-skin-modern Submit Modern Skin]<br />
*Browse: [http://www.winamp.com/skins Download Skins]<br />
[[de:Hauptseite]]</div>Culixhttp://wiki.shoutcast.com/wiki/Plugin_TerminologyPlugin Terminology2010-11-30T03:28:40Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>== winamp plugin filename conventions ==<br />
Most plugin types are identified by Winamp by the filename<br />
* in_*.dll - input plugins<br />
* out_*.dll - output plugins<br />
* gen_*.dll - general purpose plugins<br />
* vis_*.dll - visualizer plugins<br />
* dsp_*.dll - audio effects plugins<br />
* ml_*.dll - media library plugins (loaded by gen_ml.dll)<br />
* pmp_*.dll - portable media player plugins (loaded by ml_pmp.dll... a plugin type loaded by a plugin of a plugin. hah!)<br />
* nsvdec_*.dll - NSV decoder plugins<br />
* enc_*.dll - audio encoder plugins<br />
* W5S (Winamp 5 System) plugins located in c:\program files\winamp\system do not have to follow any special filename convention except for the .w5s file extension<br />
* WAC (Winamp Component) plugins located in c:\program files\winamp\plugins\freeform\wacs do not have to follow any special filename conventions, either, except for the .wac file extension. WAC files are loaded by gen_ff.dll<br />
<br />
<br />
== code naming conventions ==<br />
* IPC: Inter-Plugin Communications. The constants which define the old SendMessage API are prefixed with IPC_<br />
* Wasabi: Winamp Service Architecture Binary Interface. A system to allow sharing of C++ objects between different plugins and components. Think of it as a very lightweight version of COM.<br />
* Agave: project codename for Winamp 5.12 (when the Wasabi service manager was merged into Winamp 5. It may or may not have involved a lot of tequila). The name "Agave" is used in the SDK to refer to Wasabi components that are unique to Winamp's media platform. For example: the Wasabi Language API could be used in other (non-Winamp) Wasabi applications, but the Agave Playlist Manager makes very little sense outside of a media application.<br />
<br />
Wasabi interfaces are all built using the Dispatchable base class. A naming convention has been established to help developers understand the intent of the interface.<br />
* ifc: interface. Wasabi interfaces not associated with the service manager are prefixed with this, e.g. ifc_window<br />
* api: Wasabi interfaces which expose a singleton object meant to be used as a global API. e.g. api_application<br />
* svc: service. Wasabi interfaces which define a service are prefixed with this, e.g. svc_playlisthandler<br />
* obj: object. Wasabi interfaces which define an object created by the service manager are prefixed with this. e.g. obj_xml for an instance of an XML parser.<br />
<br />
<br />
== See also==<br />
* [[Glossary]]<br />
<br />
[[Category:Articles]]</div>Culixhttp://wiki.shoutcast.com/wiki/Editing_the_Configuration_FilesEditing the Configuration Files2010-11-30T03:28:36Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Explorer09</p>
<hr />
<div>{{ClassicSkin}}<br />
<br />
Any skin file is not complete without first finishing up the configuration files. These configuration files control such things as the background and foreground colors of the Winamp visualizations, or areas that are designated areas to be displayed to the end user. There are three text files that allow you to change these various aspects of Winamp. The first of the three that we will cover is called VisColor.txt.<br />
<br />
==Configuration File | VisColor.txt==<br />
<br />
VisColor.txt is the file that sets the colors for the Visualization panel. It contains 24 lines. Each line is an RGB value followed by a comment. (See RGB for more Info). Here is a brief explanation of the lines:<br />
<br />
* Row 0 is the background color of the visualization area.<br />
* Row 1 is the color of the dots that appear in the visualization area<br />
* Rows 2 through 17 affect the colors of the Spectrum Analyzer. Row 2 is the peak value, the highest part of the graphical bar that is visible. This means that when you hit a high frequency, the top of the bar becomes the color specified. As you move from row to row, you can color each level of the frequency spectrum a different color to signify the peak levels of the frequencies in the file you are playing at that moment.<br />
* Rows 18 to 22 pertain to the oscilloscope colors. They function in the same fashion as the Spectrum Analyzer. Row 18 controls the colors that is displayed at the troughs and the row 22 is the color that is displayed at the crest. Each row between 18 and 22 sets a different level of the whole wave.<br />
* Row 23 gives the color used to mark the last peak value. Let's take a look at what this all means, here are some screenshots with example images to help you get a clearer perspective.<br />
<br />
<br />
[[Image:Vis.gif]]<br />
<br />
The result with row 0 set to 0,0,0 and row 1 set to 255,255,255<br />
<br />
<br />
==Configuration File | Pledit.txt==<br />
<br />
Pledit.txt gives the font colors and font face for the Playlist Editor track listing as well as the MiniBrowser URL display, located at the bottom of the MiniBrowser.<br />
<br />
Here are some sample settings for pledit.txt is:<br />
<br />
'''[Text]'''<br />
<br />
Normal=#FF8924<br />
<br />
Current=#FFFF00<br />
<br />
NormalBG=#1A120A<br />
<br />
SelectedBG=#944E11<br />
<br />
MbFG=#FF8924<br />
<br />
MbBG=#1A120A<br />
<br />
Font=Comic Sans MS<br />
<br />
<br />
The funny six-character values beginning with "#" are hexadecimal RBG values (see Hex RGB). Each row has a different setting:<br />
<br />
* Normal - Color of the regular text (Playlist).<br />
* Current - Color of the current track text (Playlist).<br />
* NormalBG - Background for normal text (Playlist).<br />
* SelectedBG - Background for the selected text (Playlist)<br />
* MbFG - Text color in the MiniBrowser status bar. (MiniBrowser)<br />
* MbBG - Text background in the MiniBrowser status bar. (MiniBrowser)<br />
* Font - Font face that's used in both windows<br />
<br />
==Configuration File | Region.txt==<br />
<br />
So you want a skin with areas that are simply put, transparent? Well, this is a highly tricky task. The file you need is called region.txt and the way to do it is a lot like playing connect-the-dots.<br />
<br />
Region.txt provides a set of names such as Normal, WindowShade and so fourth. These set points define how many points make up each window. Another set defines how to draw the picture over Winamp.<br />
<br />
Region.txt has 4 regions (the sets). They are delimited with the following tags:<br />
<br />
<br />
[Normal]<br />
<br />
[WindowShade]<br />
<br />
[Equalizer]<br />
<br />
[EqualizerWS]<br />
<br />
<br />
Each of these provides a list that constist of two parts. The first gives the number of points that make up a region. The second is a list of the points used to make those regions.<br />
<br />
<br />
The lines are:<br />
<br />
NumPoints=<br />
<br />
PointList=<br />
<br />
<br />
The NumPoints list must be on a single line with comma separated numbers.<br />
<br />
Example: NumPoints = 4, 4<br />
<br />
Each number, x, says to read the next x points of the list and plot the region they define. The points list is comma seperated pairs of x,y co-ordinates. For example:<br />
<br />
<br />
[Normal]<br />
<br />
NumPoints = 4, 4<br />
<br />
PointList = 0,1, 275,1, 275,14, 0,14, 3,15,<br />
<br />
272,15, 272,113, 3,113<br />
<br />
<br />
Defines two rectangular regions to be drawn. For more information read the comments in the region.txt file in the base skin. You will find a little more explanation in this file. The only item missing is the EqualizerWS group which is new and will be defined at a later time. "Normal" defines the regions drawn for the main window, WindowShade is the regions drawn in the windowshade mode. Equalizer and EqualizerWS are the same as above. Use the examples above to work out the other points. <br />
<br />
<br />
==Configuration File | RGB==<br />
<br />
<br />
RGB stands for "Red, Green, Blue". A certain combination of each of these colors at various percentages can make millions of different colors. For example, combining 100% Blue and 100% Green will make the brightest achievable Yellow. Using this model, RGB has become a method of defining color.<br />
<br />
Since a computer displays light using pixels which are really three lights one Red one Green and one Blue (well close enough description for our purposes), we can define a color as the amount of red, green and blue. The ranges we use to help put into perceptive for each of the colors on a computer, we use 0 all the way to 255. Basically, that means, there are 256 different shades of each of those primary three colors, and any combination of those three shades will result in a color. For example, 128, 128, and 128 would make a gray in about the middle of the spectrum. Here are the different values of each of those colors.<br />
<br />
<br />
[[Image:Skins-classic-config.gif]]<br />
<br />
<br />
==Configuration File | Hexadecimal==<br />
<br />
<br />
Hexadecimal RGB numbers are exactly the same as RGB, except the value is represented in Hexadecimal notation. Digit position has less meaning (no hundreds tens and units). And each digit can be 0-9 then A-F. To convert from Hex to Decimal use Windows Calculator in Scientific mode.</div>Culixhttp://wiki.shoutcast.com/wiki/MainMain2010-11-30T03:28:29Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Explorer09</p>
<hr />
<div>{{ClassicSkin}}<br />
<br />
<br />
==Skinning The Main Window==<br />
The Winamp main window is probably the most complex window, graphics wise, of all its windows. There are many things going on in that one window at all times. Each part of the main window is divided up into various bitmap images. Here is a list of the images below that actually create the main window. <br />
<br />
<br />
[[Image:Winamp.gif]]<br />
<br />
<br />
*Main.bmp<br />
*Titlebar.bmp<br />
*CButtons.bmp<br />
*ShufRep.bmp<br />
*Volume.bmp<br />
*Balance.bmp<br />
*MonoSter.bmp<br />
*Posbar.bmp<br />
*Playpaus.bmp<br />
*Numbers.bmp<br />
*Text.bmp<br />
<br />
<br />
===Winamp Skins | Main.bmp===<br />
<br />
<br />
[[Image:main.gif]]<br />
<br />
<br />
This file provides the background image for Winamp, sections of the other bitmaps are cropped and layered over this background image to create the various states of "on" and "off", buttons, sliders, etc. Many skin artists (skinners) create their own main.bmp image as well as the other components to make their skin as unique as possible. Although the regions in which the buttons can actually be clicked, the artists have a certain amount of pixels to play with for each element. This will enable the skinner to give the illusion of making smaller more precise controls, transparent controls, or even just big silly dumb ones if they wish. The possibilities are simply endless. The skin components are all bitmaps and therefore *cannot support animation or transparencies* The only way to achieve transparency is to use the overlapping area of main.bmp as the background in the various components.<br />
<br />
<br />
<br />
===Winamp Skins | Titlebar.bmp===<br />
<br />
<br />
[[Image:titlebar.gif]]<br />
<br />
<br />
Titlebar.bmp provides the title bars for the all the various skinned windows of Winamp. The first of the bars are the graphics for Winamp's main window when that window has focus (the current window on your desktop is said to have the 'focus', and on that window the currently selected control also has the 'focus'). The second bar is the main window's title bar when it does not have the focus. The third and fourth bars provide the graphics for Winamp running in Window Shade mode. The fifth and sixth bars are special. They provide the graphics for the title bar when the Winamp Easter Egg is active. (Easter Eggs are usually useless aspects of a piece of software that the software developers include as a joke or to give credit to something. It's just the programmers trying to have a little fun. do not worry about these last two bars for now.)<br />
<br />
To the left of the title bars are a selection of graphics for the windows buttons in their various states.<br />
<br />
<br />
[[Image:winbut.gif]]<br />
<br />
<br />
The top row consists of the images for system menu (a.k.a. Winamp's Main Menu), the minimize button, as well as the close button in it's normal state (the way the buttons would look if they weren't clicked). The second row consists of the same set of buttons, however in the pressed state (the way the buttons would look if they were clicked). The third row is the graphics for the WindowShade button where the left image is the image of the button not pressed, and the left is the image of the button pressed. The fourth row contains the images for the button that restores Winamp or its various windows from WindowShade mode to its expanded form, the images being in the same order, the left being not pressed, and the right being the pressed state.<br />
<br />
The fifth and final row consists of the images that create the progress bar for Winamp when Winamp is in WindowShade mode. The first part of the row consists of the image for which the seek bar rests in, followed by the slider in various states.<br />
<br />
To the right of the title bars are the graphics for the CuttleBar, which is a little strip of buttons to the left of the visualization area of the Winamp main window. At the top the strip is shown in it's un-pressed state. To the right of the first strip is a version of the strip with all the labels removed, this is for the people who turn off the CuttleBar in Winamp's Preferences window. The next row of strips are simply the different states of the CuttleBar with copy of the strip in each of it's five states, one state for each button being pressed.<br />
<br />
When modifying the title bar it's important to remember that if you change the appearance of your buttons in the main title bar images, you should also change all the graphics that are relevant to the title bar to match so that they don't look out of place when you press them and remove the focus from the button you had just pressed. Also note that you can not add graphics for components that do not exist, for example adding a spot in WindowShade mode for track title scrolling would not make sense, due to the fact that Winamp wasn't coded with that in mind, leaving that spot you created blank.<br />
<br />
<br />
<br />
===Winamp Skins | ShufRep.bmp===<br />
<br />
<br />
<br />
[[Image:Cbuttons.gif]]<br />
<br />
<br />
The cbuttons.bmp image provides the images for Winamp's playback control buttons. The top row displays the buttons un-pressed or in their normal state, the second row of graphics are the same buttons except in the pressed state. Remember when skinning this set of components that transparency does not exist, if the button is incorporated into the background, you will have to place the background into the cbuttons.bmp.<br />
<br />
===Winamp Skins | ShufRep.bmp===<br />
<br />
<br />
<br />
[[Image:Shufrep.gif]]<br />
<br />
<br />
Shufrep.bmp provides the graphics for both states of the Shuffle-Play button, Play/Loop button (Repeat), Equalizer button as well as the Playlist button. The top row is the (repeat) loop and shuffle in the off state, the second row, are the loop and shuffle button in the off, clicked state(the button being pressed while the shuffle/loop buttons were in the off state). The third row is loop and shuffle button in the on state, and the fourth row are the buttons being clicked in the on state.<br />
<br />
The bottom four images make up the graphics for the Equalizer and Playlist editor buttons in both two states. The first is the Equalizer button in the off state. The second button is the Playlist button in the off state. The third is the Equalizer off state and pressed at the same time. The fourth being the Playlist button in the same state. The next row is the exact same thing, however, instead of the buttons being in the off state, they are on.<br />
<br />
The same conditions in regards to transparency that apply for the Cbuttons.bmp image apply for this image as well.<br />
<br />
<br />
<br />
<br />
===Winamp Skins | Volume.bmp===<br />
<br />
<br />
[[Image:Volume.gif]]<br />
<br />
<br />
The volume.bmp file (partial shown here enlarged at the left) contains a set of of bars and two slider graphics. Depending on how high or low the level of the volume is, Winamp selects one of the bars to demonstrate the level at which the volume is currently at. If the volume is all the way down, it displays the more green bars, if all the way up, it displays the more yellow bars. The first bar is the volume at its lowest level, the last bar is the volume at its maximum level. Fiddle with these graphics yourselves to find out which bar is which level. The bottom contains the sliders control images. The first image being the slider, which is in the clicked, the second being in the un-clicked state.<br />
<br />
<br />
<br />
===Winamp Skins | Balance.bmp===<br />
<br />
<br />
[[Image:Bal.gif]]<br />
<br />
<br />
Balance.bmp works virtually identitical to volume.bmp, however, the images in balance need to illustrate the volume coming from either the left, right, or both speakers. This is done by swaying from green to red when moving the slider from one of the sides towards center. Simply color all the bars the way you would do for the volume.bmp and the outcome should be the same.<br />
<br />
<br />
<br />
===Winamp Skins | MonoSter.bmp===<br />
<br />
<br />
[[Image:Monoster.gif]]<br />
<br />
<br />
Monoster.bmp provides the indication that the audio source is running in Stereo or Mono mode. The top row shows the "in stereo" indicator as well as the "in mono", indicator. The second row shows the "stereo off" and "mono off" indicators. When Winamp is playing in stereo sound, the "stereo on" with the "mono off" indicators are displayed. When the audio is in mono, the opposite is displayed.<br />
<br />
<br />
<br />
===Winamp Skins | Posbar.bmp===<br />
<br />
<br />
[[Image:Posbar.gif]]<br />
<br />
<br />
The posbar.bmp, shown here enlarged, provides the track for the song position slider. At the right side of the image, the song seek slider is shown in both states, pressed and not pressed.<br />
<br />
<br />
<br />
===Winamp Skins | Playpaus.bmp===<br />
<br />
<br />
[[Image:playpaus.gif]]<br />
<br />
<br />
The playpaus.bmp file provides indicators that the file being played is playing, paused or stopped. The final item shows whether the file is synchronized or buffered or a break in transmission has been found.<br />
<br />
===Winamp Skins | Numbers.bmp===<br />
<br />
<br />
[[Image:Numbers.gif]]<br />
<br />
<br />
The numbers.bmp file provides the images for displaying the numbers used in the time display, located directly above the visualizations area.<br />
<br />
<br />
<br />
===Winamp Skins | Text.bmp===<br />
<br />
<br />
[[Image:Text.gif]]<br />
<br />
<br />
Text.bmp is performs the same job that numbers.bmp, however, this image isn't as limited in use as numbers.bmp. Text.bmp provides all the text that is used for the track area, Playlist editor, and anywhere else that Winamp uses text within the skinned interface.<br />
<nowiki>Insert non-formatted text here</nowiki></div>Culixhttp://wiki.shoutcast.com/wiki/Album_Art_APIAlbum Art API2010-11-30T03:28:23Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>Agave/AlbumArt/api_albumart.h<br />
{{stub}}</div>Culixhttp://wiki.shoutcast.com/wiki/EqualizerEqualizer2010-11-30T03:28:20Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Explorer09</p>
<hr />
<div>{{ClassicSkin}}<br />
<br />
==Skinning The Equalizer Window==<br />
<br />
Here's the finished Winamp Equalizer:<br />
<br />
<br />
[[Image:Equalizer.gif]]<br />
<br />
<br />
Compared to what it takes to skin the main window, the Equalizer window is far simpler. The Equalizer is composed of two bitmaps, the first being Eqmain.bmp.<br />
<br />
<br />
[[Image:Eqmain.gif]]<br />
<br />
'''Eqmain.bmp'''<br />
<br />
<br />
The first item in the image is the blank background of Equalizer window that, once running, will have the button graphics layered over it, just like in the case of main.bmp. Below the graphic of the Equalizer background, there is a set of buttons. The leftmost button graphics, one atop the other, is for the close button for the Equalizer window. The one on top is the normal, unlicked state, as the other is the pressed, or clicked state for the close button.<br />
<br />
To the right of the close buttons are the Equalizer On and Auto buttons in their four states (Off, On, Off-Pressed, On-Pressed).<br />
<br />
Below the graphics of the buttons, there are the title bars, in both states, selected as well as unselected. This is now followed by the slider that allows you to control EQ settings in both the selected and unselected states at the begining of the next row. To the right of the slider button, you see as set of graphics, which go from green to red. This set of graphics create one of the bands that will be placed in each part of the 10 bands of the Equalizer window, one of them is also used for the PreAmp slider.<br />
<br />
Next, to the right of the equalizer bars are the two states of the Preset button, both pressed and not pressed.<br />
<br />
The last row of images will require you to take a closer look:<br />
<br />
<br />
[[Image:Eq.gif]]<br />
<br />
<br />
This graphic provides the background for the EQ spline, which shows you what position the settings are for the equalizer bands. To the right is the rainbow strip, that graphic gives the colors palete for the equalizer spline graph.<br />
<br />
Towards the center of the Eqmain.bmp, there are the title bars, both active and inactive modes. if you notice, there is a button to cause the Equalizer to enter WindowShade mode, however, there is no button for when you press it down, that little graphic is within the other file that creates the EQ window called Eq_ex.bmp.<br />
<br />
<br />
[[Image:Eq_ex.gif]]<br />
<br />
'''Eq_ex.bmp'''<br />
<br />
<br />
Eq_ex.bmp was an image added to the skins later on, it is the file that illustrates to the user the controls that are present in Winamp's Equalizer while in WindowShade mode. The EQ has two controls while in WindowShade, the volume, to the left, and the balance, which is to the right.<br />
<br />
At the top of the Eq_ex.bmp file, there are the two title bars with Winamp's EQ in WindowShade mode. Notice that there are little tracks for which the volume and balance controls rest in.<br />
<br />
The next row contains the graphics for both sliders, one for the volume, and the other for the balance. This is then followed by the pressed or clicked version of the WindowShade mode graphic. To the right of that graphic, we have un-clicked version of the close button. Finally the next row contains the graphic for the clicked version of the maximize (from WindowShade) button, as well as the clicked version of the close button for the Equalizer.</div>Culixhttp://wiki.shoutcast.com/wiki/AVSAVS2010-11-30T03:28:16Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Explorer09</p>
<hr />
<div>{{ClassicSkin}}<br />
<br />
==Skinning The AVS Window==<br />
<br />
This file is layed out much like the other Winamp bitmaps. Once again, the image is divided into various segments only divided by spaces between the sections. The first component in the image, in the upper left-hand corner, is the close button in a pressed state. This close button when pressed will close the AVS window as well as turn off the plug-in.<br />
<br />
<br />
<br />
[[Image:Avs.gif]]<br />
<br />
'''avs.bmp'''<br />
<br />
<br />
<br />
The next graphic, directly to the right of it, is the upper left most section of the AVS title bar. Be sure not to allow any text to go past the end of the allowed graphic size due to the fact that it will be displayed incorrectly.<br />
<br />
Directly to the left of that graphic is the graphic of the title bar which is used to tile horizontally. This graphic should be symmetrical due to the fact that as the AVS window is stretched horizontally, this image is continually duplicated to give the illusion of a stretching title bar.<br />
<br />
At the upper rightmost section of the image is the close button for the AVS window in an un-pressed state.<br />
<br />
The next row of images contains two really long columns followed by three flat row graphics. The leftmost column is the left border of the AVS window followed by the right column being the right border of the AVS window. The next graphic is the leftmost section that composes the bottom of the AVS window. To the right of it is a little section which is tiled horizontally as the window stretches, just like its title bar counterpart. The final graphic, the rightmost graphic of the second row, is the rightmost section which completes the bottom of the AVS window.<br />
<br />
That wasn't too tough, was it? Not at all! This should probably take no more than an hour or so to skin and creates an all around fuller affect if skinned with the same "scheme" of the Winamp interface.</div>Culixhttp://wiki.shoutcast.com/wiki/Pixel_Shader_BasicsPixel Shader Basics2010-11-30T03:28:12Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>== Introduction ==<br />
This article assumes you've read through the wonderful [[MilkDrop_Preset_Authoring | Preset Authoring Guide]] and will attempt to build on the information there. By the end you should have a solid understanding of how pixel shaders work in Milkdrop.<br />
== Overview of Pixel Shaders ==<br />
Simply put, a pixel shader is a tool that applies a set of instructions to every pixel in a display window. In almost every modern video game pixel shaders are used to create realistic lighting and shading effects in 3D scenes. A pixel Shader takes in information about models, textures, light sources and materials, applies a set of instructions to this data and returns a single float4 value, which holds the current pixel's red, blue, green and alpha channel values. <br />
<br />
Pixel shaders in Milkdrop are a bit simpler, because we're limited to working in 2 dimensions without things like models or light sources. In addition, the final return value of our pixel shaders is a float3, leaving out the alpha channel. But the principle is still the same; when we write the code for a pixel shader we are giving it a set of instructions to perform on every pixel in the display window, which it uses to find the final color value for that pixel, which is assigned to ''ret''.<br />
<br />
It's important to understand that the two pixel shaders in Milkdrop, the warp shader and the composite shader, do very different things. We'll go over exactly how they're different later in the article, for now just keep in mind that they do not do the same thing.<br />
<br />
== Textures ==<br />
In the Milkdrop pixel shaders a texture is simply a sampling source. They can be sampled using the tex2D() function, or the tex3D function if you're sampling from a 3D noise volume. There are 3 types of textures we can access in Milkdrop; sampler_main, [[MilkDrop_Preset_Authoring#NOISE_TEXTURES | noise textures]] and [[MilkDrop_Preset_Authoring#READING_TEXTURES_FROM_DISK | custom textures]]. The latter two are covered very well in the preset authoring guide, so we'll just take a moment to say a few things about sampler_main.<br />
=== sampler_main ===<br />
We can think of this texture as a screenshot of the display window. This snapshot is taken by Milkdrop just before it executes the Warp Shader, and is passed to the Warp Shader as sampler_main. Using sampler_main we can get the color value of the current pixel either by calling tex2D(sampler_main, uv), or by calling GetPixel(uv). <br />
<br />
There is one important difference between the Warp Shader and the Composite Shader when it comes to sampler_main; Milkdrop takes a ''new'' snapshot of the scene after the Warp Shader has finished executing, and passes this new snapshot to the Composite Shader. What this means is that the Warp Shader actively ''alters'' the scene, while the Composite Shader only returns a ''copy'' of the scene to display. In other words, anything the Composite Shader does, does not affect the rest of Milkdrop because it only alters a copy of the scene, instead of the scene itself. The Warp Shader alters the scene itself, and anything it does ''will'' affect the rest of Milkdrop.<br />
<br />
== UV Coordinates ==<br />
A pixel shader needs some way of knowing which pixel it's currently working on, and which pixel you want to sample in a texture. In Milkdrop these concepts are represented by ''uv'', which is a float2 with x and y values between 0..1. The top left corner of the scene has the coordinates (0.0,0.0), while the bottom right corner is (1.0,1.0). How Milkdrop generates these values between 0..1 is not so important, what's important is that it stores the dimensions of the display window ''and'' the size of a single pixel in the float4 variable '''texsize.xyzw'''. Lets suppose we have a display window of size 600x400, in this case texsize will hold the following values:<br />
* texsize.x = 600<br />
* texsize.y = 400<br />
* texsize.z = 1/600 = 0.0017<br />
* texsize.w = 1/400 = 0.0025<br />
A pixel shader always moves from left to right, starting in the upper left corner with pixel (0,0). Next it will increment to (move to) the next pixel, and because the size of a single pixel along the x axis for our supposed window is 0.0017 the current uv value is changed from (0,0) to (0.0017,0). For our window, the pixel shader does this 600 times, each time adding 0.0017 to the uv.x value and keeping uv.y the same. After 600 increments it's reached the right side of the screen, (1,0), so it moves back to the left side and starts with the next line of pixels, the uv value is now (0,0.0025). This process gets repeated for the entire display window, in our hypothetical case a total of 240,000 times. <br />
<br />
This also means the shader code you write will be executed 240,000 times for that frame, for a window size of 1680x1050 that number increases to 1.7 million times, per frame! At 60 fps this means your graphics card is executing your instructions 106 million times per second, per shader! Something to think about the next time one of the more intense presets brings your machine to its knees.<br />
<br />
Getting back to our example, remember that sampler_main contains a copy of the scene in the form of a texture. We know enough now to read the following instruction:<br />
ret = tex2D(sampler_main, uv);<br />
as "Set ret to the rgb values from the sampler_main texture at the coordinates of the current pixel". <br />
=== Modifying the uv coordinates ===<br />
Some very interesting effects can be achieved by modifying the uv coordinates before you sample a texture. The theory behind this is very straight forward because there are really only two things we can do, translate and scale. <br />
<br />
==== Translation ====<br />
Lets say we want to create a movement effect similar to dx (aka Translation (X) in the Motion menu) that moves the entire scene one pixel to the left each frame. In mathematical terms this is called a Translation, and you achieve it by modifying the uv values like so:<br />
ret = tex2D(sampler_main, float2(uv.x + texsize.z, uv.y));<br />
which reads as "Set ret to the rgb values from the sampler_main texture at one pixel to the right of the current pixel". When we do this for every pixel we've in effect moved the entire scene one pixel to the left. Conversely, subtracting texsize.z from uv.x would move the scene one pixel to the right. To move the scene 2 pixels to the left we just multiply texsize.z by 2. <br />
<br />
==== Scaling ====<br />
In the same way that translation is achieved by addition and subtraction, scaling is achieved by multiplying and dividing. An important note though, by dividing we really mean to multiply by a decimal fraction, uv*0.5 instead of uv/2 for example. This is because a computer can perform multiplication much faster than division, so we multiply whenever we can. <br />
<br />
When we scale uv what we're really doing is increasing or decreasing the sampling area. For example, the instruction uv*0.5 will cut the available sampling area in half, and the sampling box now goes from (0,0) to (0.5,0.5). Notice this also means that the pixel ratio between the display window and the sampling area is no longer 1:1, one pixel from the sampling area gets scaled up to be ''4 pixels'' in the display window. The effect of this is that the sampling area is blown up to fit the display window, and you lose some resolution in the process. The entire process is less confusing if we see it in action in the '''Composite Shader''':<br />
<gallery caption= widths="250px" heights="196px"><br />
Image:Mdscale1.png | uv*1<br />
Image:Mdscale05.png | uv*0.5<br />
Image:Mdscale205.png | 0.25 + uv*0.5<br />
</gallery><br />
Notice in the third image we've moved the sampling area to the center of the texture. It's easy to see why this works, all we've done is add 0.25 to the coordinates so that the box now extends from (0.25,0.25) to (0.75,0.75). <br />
<br />
==== Comp shader vs Warp shader ====<br />
It's important to note that the effects of these transformations are very different in the two Milkdrop shaders. Remember, the composite shader treats sampler_main as a static texture and returns a modified ''copy'' of it that Milkdrop displays. Think of it as a camera, when we apply a translation to the uv coordinates we are moving the camera. When we scale the coordinates we are zooming the camera in or out. At the end the camera takes a picture of what it sees and returns that picture.<br />
<br />
In the warp shader, on the other hand, we're really ''changing the scene'' when we transform the uv coordinates. And this transformation gets compounded in each successive frame. A lot of cool effects like fractals and error diffusion dither take advantage of this. Consider the Zoom effect in the Motion menu. To replicate this with pixel shaders we add the following instruction to the '''warp shader''':<br />
uv = 0.5 + (uv-0.5)*0.95;<br />
This causes the scene to zoom ''in'' and does exactly the same thing as setting Zoom Amount to 1.05 in the Motion menu.<br />
<br />
=== Texture Wrap ===<br />
Remember that uv coordinates are always values between 0..1, so what happens if we multiply (0.75,0.75) by 2 to get the coordinate (1.5,1.5)? The answer depends on which sampling mode you've chosen to use on your texture; wrap or clamp. Clamp mode (fc and pc) will use 1.0 for any coordinate value larger than 1, or 0 for any value smaller than 0, so (1.5,-0.4) becomes (1,0). Wrap mode (fw and pw) will simply roll the coordinates back to 0 (or 1) when the values are over 1.0 (or under 0) and then add the remainder. (1.5,-0.4) becomes (0.5,0.6). Note when the values are greater than 1 wrap mode always returns just the fractional component, so writing this:<br />
uv = (1.5,1.5);<br />
tex2D(sampler_'''fc'''_main, frac(uv)); <br />
will return exactly the same result as <br />
uv = (1.5,1.5);<br />
tex2D(sampler_'''fw'''_main, uv);<br />
because by encasing uv inside frac() we ensure the coordinate values will never be >= 1.0. If the values are negative numbers then it's not the same, because for example -0.1 will be turned into 0.9, not 0.1. In practical terms, wrap mode will tile a texture when the uv coordinates go out of bounds.<br />
<br />
In clamp mode any x or y coordinate value larger than 1.0 will cause tex2D() to return the color value at the right edge or bottom edge of the screen respectively. Any x or y coordinate smaller than 0 (negative) will return the color value at the left edge or top edge of the screen respectively.<br />
<br />
== Color Values ==<br />
All of the work done inside a pixel shader is done to find a single set of values; the rgb color values of the current pixel. This is what you assign to ''ret'' at the end of your shader code, and this is what Milkdrop draws onto the screen for that pixel. All the fancy mathematics we see in shader code is done to manipulate color values in one form or another, because that's all a pixel shader can do.<br />
<br />
=== RGB basics ===<br />
In Milkdrop shaders color values are always stored as a float3 that represents the amount of red, green and blue color at a particular point. In the body of your shader code these values can be any number at all, but the final values that are assigned to ret at the end of your shader must be between 0..1 or they will be clamped to either 0 or 1. A negative value will be 0, a value greater than 1 will be 1. Here are a few other notes about color values, working with ''ret'':<br />
* '''1-ret''' returns the inverse of the color, assuming it is clamped to the 0..1 range<br />
* '''saturate(ret)''' clamps the color to the 0..1 range<br />
* '''ret.zyx''' causes the red and blue channels to trade places<br />
* '''ret.x''' gives a float1 with the value of the red channel<br />
* '''lum(ret)''' basically returns the greyscale version of the color<br />
<br />
One important note is that Milkdrop uses 8 bit values for the color channels, which is a fancy way of saying that there are 256 possible shades in each channel, giving a maximum precision of 0.004.<br />
=== Color in Comp shader vs Warp shader ===<br />
Just as with uv transformations, color manipulation works differently in the warp shader than it does in the composite shader. Adding the following instruction,<br />
ret += 0.01;<br />
to the warp shader will quickly white out the entire scene, while adding the same line to the composite shader will make hardly any difference. Again, this is because the effects in the warp shader are compounded with each successive frame, it will keep adding 0.01 to the pixel's color with each new frame until all 3 channels reach 1.0 and get clamped there. This is why any color correction (like giving the entire scene a green tint) should be done in the composite shader.<br />
=== Basic color examples ===<br />
To give give the entire preset a green tint we could add this instruction to the composite shader:<br />
ret *= float3(0.5, 1.0, 0.5);<br />
Which would cut the red and blue color values in half, allowing more of the green to show through. <br />
<br />
To make the entire scene brighter we could add this instruction to the composite shader:<br />
ret *= 3;<br />
Which simply multiplies each channel by 3, making them brighter. Keep in mind final output will still be clamped to 1.0, you can't get any brighter than pure white!<br />
<br />
<br />
For a more advanced use of color, why don't we combine it with uv translation? Consider the following instructions in the '''warp shader''':<br />
float3 temp = tex2D(sampler_main, uv);<br />
float2 myuv = float2( uv.x + 0.05*temp.x, uv.y);<br />
ret = tex2D(sampler_main, myuv);<br />
Here we first sample the colors of the current pixel from sampler_main and assign them to temp. In the next line we create a new coordinate value that multiplies 0.05 by the value of temp's red channel and adds it to uv.x, while keeping uv.y the same. Where temp's red channel is 1.0 we're adding 0.05 to uv.x, where the red channel is 0.5 we're only adding 0.025 to x, and where the red channel is 0 we're keeping uv.x the same. The effect of this is a translation based on how much red is in the current pixel. A lot of neat effects can be done with this, including the [[painterly]] effect.<br />
== Important note about ATI cards ==<br />
Due to some obscure bug in either Milkdrop's source or ATI's drivers, PS 3.0 in Milkdrop will not work on any ATI card. As a temporary fix to this problem PS 2.X support has been added to Milkdrop. There aren't many differences between the two version as far as we're concerned, so try to keep your presets limited to PS 2.0 or PS 2.X, which should give you more than enough [http://dev.winamp.com/wiki/Advanced_Pixel_Shader_Concepts#Instruction_Slots instruction slots] to play with.<br />
<br />
A second bug affects the Xx00 and 9x00 line of Radeon cards, that has to do with the _fw_ and _pw_ sampling modes for textures (made worse by the fact that _fw_ is the default sampling mode). To have this display properly encase the uv coordinates in frac() like this;<br />
tex2D(sampler_main, frac(uv));<br />
This bug seems to be fixed on the Radeon HD line of cards (both the 3xxx's and the 4xxx's).</div>Culixhttp://wiki.shoutcast.com/wiki/Nullsoft_Database_EngineNullsoft Database Engine2010-11-30T03:28:08Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>The Nullsoft Database Engine powers the local media library, history, and the CD metadata database. It is relative simple and has a small query language. Most winamp data can be found in the file 'main.dat', which on Windows machines is usually stored in a location like "C:\Documents and Settings\<nowiki><username></nowiki>\Application Data\Winamp\Plugins\ml\" (citation needed).<br />
<br />
For more information describing the Nullsoft Database Engine format, see [http://code.google.com/p/ndephp/wiki/NDEFormat here].<br />
<br />
==External Links==<br />
* [http://code.google.com/p/ndephp/ NDEPHP] - an open source project that can read the database using PHP.<br />
<br />
{{stub}}<br />
<br />
[[Category:Articles]]</div>Culixhttp://wiki.shoutcast.com/wiki/Creating_a_ClassicPro_SkinCreating a ClassicPro Skin2010-11-30T03:28:05Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>==What is ClassicPro?==<br />
ClassicPro is a plugin for Winamp that will allow you to use a new type of skin in Winamp Media Player. What makes this type of skin different from normal modern skins is that all the coding stuff is already done in one central place so you don't need to be a programmer to create a great Winamp skin anymore! <br />
The advantages are not just for the skinners though, artistic people can now create great skins easily, and this means we'll see more beautiful skins by great artists!<br />
<br />
ClassicPro skins use an advanced single-user-interface which is really easy to use. The great thing is cPro appeals both to the advanced Winamp user and the minimalistic user who would for example just want to use the playlist. This means ClassicPro will probably fit you like a glove no matter who you are!<br />
If you are used to a Classic Winamp skin and didn't want to switch to the modern skins of the past then we urge you to give this a test drive since this skin type was designed especially for the old school user who might need a minimalistic approach to their favourite media player.<br />
<br />
The 2 main key focus points in the development was as follows:<br />
* Performance - Winamp must load quick and use as little resources running as possible<br />
* Easy Interface - The interface must be easy to understand and give enough play for the experienced users too<br />
<br />
[http://cpro.skinconsortium.com/ Download ClassicPro plugin]<br />
<br />
==Introduction to ClassicPro skins==<br />
[[Image:http://cpro.skinconsortium.com/images/cpro-promo1_04.jpg]]<br />
<br />
<br />
ClassicPro skins are basically pre-coded Winamp Modern Skins. The advantage of this is that the skinner dont have to spend months coding the skin anymore and can just edit a few picture files and have a fully working skin. All the coding of the skin is installed in one central place by the cPro plugin and then this plugin is maintained by the developer. So when the plugin installs new features or fixes your skin will automatically have them too.<br />
<br />
For more information make a post at their forums:<br />
[http://forums.skinconsortium.com SkinConsortium Forums]<br />
<br />
<br />
==Tools needed to create a skin==<br />
* Graphics Editor<br />
** Paint, Corel PSP, Adobe PS, GIMP, Paint.NET<br />
* Text Editor<br />
** Notepad, Notepad2, Notepad++<br />
* Archiver<br />
** 7zip, WinZip, WinRar<br />
* ClassicPro plug-in<br />
** [http://cpro.skinconsortium.com/ Download ClassicPro plugin]<br />
<br />
<br />
==Tutorials==<br />
* [http://cpro.skinconsortium.com/index.php?content=manual Skinners Guide to ClassicPro] by pjn123<br />
** This is the manual released by the developers<br />
* [http://wilian.deviantart.com/art/ClassicPro-Template-pack-95549517 ClassicPro Template pack and Manual] by Wilian & Veroka<br />
** This is a more in depth look at creating cPro skins. Really great for beginners.<br />
** Comes with great base skin for you to start off with<br />
<br />
[[Category:Articles]]</div>Culixhttp://wiki.shoutcast.com/wiki/Visual_DeveloperVisual Developer2010-11-30T03:28:00Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>{{Template:NavBar}}<br />
<br />
==What is a Visualization?==<br />
Visualizers or Visualization Plugins are dynamic add-ons that produce images, colors, and textures that change based elements of the music being played. Winamp offers two primary visualization plugins ([[Visual_Developer#AVS_Unleashed | AVS]] & [[Visual_Developer#Milk_Drop_Unleashed | MilkDrop]]) allowing you to create different presets. If you’re feeling invincible, you can even attempt to create your own visualization plugin or you can stay platform. There are many [http://www.winamp.com/plugins/browse/1 visualization plugins] available which users have generated.<br />
<br />
==What is a Preset?==<br />
Presets are outputs of a visualization platform. You can customize the visualizers and get any effect you want. Many users have uploaded such presets in [http://www.winamp.com/plugins/browse/11 Winamp.com]<br />
<br />
==AVS Unleashed==<br />
AVS is the mother of all Winamp visualization plug-ins. It lets the user build a countless number of custom visualizations from an ever-expanding library of effects. AVS supports windowed/fullscreen rendering, preset customization, module stacking, skinnable windows, support for Sonique visual plug-ins, and a ton of other features. AVS is now bundled with all versions of Winamp after v2.6, so everyone can get a taste of its visual sonic goodness.<br />
<br />
===Module References===<br />
Below is some information on AVS modules. WVS is our codename for our global mind control device. With it we shall overtake the world. And have another excuse to take mind-altering substances.<br />
<br />
Currently information about the superscope module is here. It uses all kinds of math stuff. Justin is so smart. You can look here for more general information about making presets.<br />
<br />
====Superscope Reference====<br />
<br />
The superscope allows you to create your own designs.<br />
<br />
To have multiple statements on one line, use a semicolon (;) to delimit the statement. Use parenthesis '( and )' if you are unsure about precedence.<br />
<br />
'''Fields:'''<br />
<br />
{| Border="1"<br />
!Field !! Description<br />
|-<br />
|init || set initial variable values here<br />
|-<br />
|point || This is where the shape of the superscope is defined<br />
|-<br />
|frame || Used to define movement and transformations<br />
|-<br />
|beat || Expression that gets evaluated on the beat<br />
|-<br />
|}<br />
<br />
'''Operators:'''<br />
<br />
{| Border = "1"<br />
!Operator !! Description<br />
|-<br />
|= || assign<br />
|-<br />
|'+,-,/,*' || 'plus, minus, divide, multiply'<br />
|-<br />
|| || convert to integer, and do bitwise or<br />
|-<br />
|& || convert to integer, and do bitwise and<br />
|-<br />
|% || convert to integer, and get remainder<br />
|-<br />
|}<br />
<br />
'''Variables:'''<br />
<br />
{| Border = "1"<br />
!Variables !! Description<br />
|-<br />
|n || number of points to render (set in Init, Beat or Frame)<br />
|-<br />
|x || x coordinate, between -1 and 1<br />
|-<br />
|y || y coordinate, between -1 and 1<br />
|-<br />
|i || position of the scope (0..1). The point position.<br />
|-<br />
|v || value at point i (-1..1)<br />
|-<br />
|b || 1 if beat. 0 for no beat. Used for beat changes<br />
|-<br />
|w || width of screen<br />
|-<br />
|h || height of screen<br />
|-<br />
|red || red value. (0..1). Set this variable to set red value.<br />
|-<br />
|green || green value. (0..1) Set this variable to set green value.<br />
|-<br />
|blue || blue value. (0..1) Set this variable to set blue value.<br />
|-<br />
|t, d || variables commonly used for movement<br />
|-<br />
|}<br />
<br />
'''Functions:'''<br />
{| Border = "1"<br />
!Variables !! Description<br />
|-<br />
|abs(var)|| returns the absolute value of 'var'<br />
|-<br />
|sin(var) || returns the sine of the angle var (expressed in radians)<br />
|-<br />
|cos(var) || returns the cosine of the angle var<br />
|-<br />
|tan(var) || returns the tangent of the angle var<br />
|-<br />
|asin(var) || returns the arcsine of var<br />
|-<br />
|acos(var) || returns the arccosine of var<br />
|-<br />
|atan(var) || returns the arctangent of var<br />
|-<br />
|sqr(var) || returns the square of var<br />
|-<br />
|sqrt(var) || returns the square root of var<br />
|-<br />
|pow(var, var2)|| returns var to the power of var2<br />
|-<br />
|log(var) || returns the log base of var<br />
|-<br />
|log10(var) || returns the log base 10 of var<br />
|-<br />
|sign(var) || returns the sign of var or 0<br />
|-<br />
|min(var, var2)|| returns the smallest value<br />
|-<br />
|max(var, var2) || returns the greatest value<br />
|-<br />
|sigmoid(var, var2)|| returns sigmoid function value of x=var (var2=constraint)<br />
|-<br />
|rand(var) || returns a random value between 0 and var<br />
|-<br />
|band(var, var2)|| boolean and, returns 1 if var and var2 are != 0<br />
|-<br />
|bor(var, var2) || boolean or, returns 1 if var or var2 is != 0<br />
|-<br />
|bnot(var) || boolean not, returns 1 if var == 0 or 0 if var ! = 0<br />
|-<br />
|if(cond, vartrue, varfalse) || if condition is nonzero, returns valtrue, otherwise returns valfalse<br />
|-<br />
|equal(var, var2) || returns 1 if var=var2, else 0<br />
|-<br />
|above(var, var2) || returns 1 if var > var2, else 0<br />
|-<br />
|below(var, var2)|| returns 1 if var<var2, else 0<br />
|-<br />
|}<br />
jjjjjjjj<br />
<br />
===Making Presets===<br />
We are going to attempt to reproduce a simple version of one of my favorite presets: Lone's "No way to go". Successful presets usually start off with one or more Render Modules, and then have a number of Trans Modules added to subtly manipulate the effect. Lone's preset is no exception. Again, before we start, make sure that you have both Winamp and AVS installed:<br />
# Start Winamp and AVS<br />
# Right-click in the AVS window, and select AVS Editor<br />
# In the Editor window, click on Preset. A drop-down menu appears<br />
# Click on New. This creates a new blank preset<br />
# Click on Main. The option to Clear every frame should appear in the right window. If enabled, this will paint the screen black at the beginning of each frame, erasing the previous one. For this preset, leave this option unchecked<br />
# We will now add Effect Modules to this presets. Click on +, then click on Render, then click on Moving Particle. New options should appear in the right half of the window<br />
# Click on the white box labeled "color". A whole new color window should pop up<br />
# Click on a basic color (it helps the effect if it isn't a "pure" color, like orange or purple). Now click OK. The color box should now be the same color that you chose<br />
# Make sure the Onbeat Sizechange option is enabled<br />
# A moving blob of color is a bit interesting, but it could be better. We will now alter how that Moving Particle is displayed by adding some Trans Modules<br />
# Click +, then click Trans, then click Water<br />
# Click +, then click Trans, then click Blur<br />
# Click +, then click Trans, then click Movement. A new list of effects should appear in the right half of the window. Click on sunburster<br />
<br />
Congratulations, we have replicated Lone's Preset! You can also drag an included Effect Module up or down the list to play with sequencing. I hope that you have realized by now that ANY permutation of the existing Modules or setting modification will result in a new effect! Keep experimenting!<br />
<br />
====Advanced Tactics====<br />
<br />
After creating a few original presets, it is natural to want even more options and control. AVS now has a very powerful tool: Effect Lists. To use an Effect List simply as an organizational tool is to squander its potential. The idea is that everything in an effect list gets rendered into a separate buffer before being added to its parent buffer. You now have the power to create completely separate effects off screen, manipulate them freely, possibly blending them together, all before finally displaying the final effect in one shot.<br />
#Open AVS Editor#Create a new preset<br />
#Click on Main, then disable the Clear every frame option<br />
#Click on +, then on Effect List to add an Effect List<br />
#In the Effect List options, make sure the Enabled and Clear every frame check boxes are checked. For the Input blend mode, select Ignore. For the Output blend mode, select Subtractive Blend 1<br />
#Click on +, then on Trans, then on Mosaic<br />
#Click on +, then on Render, then on Simple<br />
#Click on Main, to stop adding to the Effect list<br />
#Click on +, then on Trans, then Fadeout<br />
#In the Fadeout options, Click on the Fade to Color Box, and select a nice red color#Click on +, then on Render, then on Bass Spin<br />
<br />
If you have followed the instructions faithfully, you should get an effect tree that looks like this:<br />
<br />
'''Main'''<br />
* Render / Bass Spin<br />
* Trans / Fadeout<br />
'''Effects List'''<br />
* Render / Simple<br />
* Trans / Mosaic<br />
<br />
That having been done, let's examine this preset:<br />
A Bass Spin is placed into the main parent buffer.<br />
<br />
Then, the Effect List creates a separate, secondary buffer.<br />
<br />
This buffer starts out black (cleared every frame), ignores what is in its parent buffer and a Simple waveform is drawn into it. Notice that the Mosaic modifier ONLY affects the Simple effect as it is totally segregated from the parent buffer.<br />
<br />
Now that all effects in the Effect List have been processed, the secondary buffer is blended back into the parent buffer using the blend mode specified in the Effects List options; in this case, Subtractive Blend 1.<br />
<br />
This results in a dark colored Simple effect overlaid over the white Bass Spins.<br />
<br />
What this means is that you can prevent Trans modifiers from affecting whole groups of modules, which in turn gives you much finer control over the visual effects. I hope this simple tutorial has shed some light on to the mystery of Effect Lists. It took me a bit of head scratching to wrap my mind around the usefulness of parent and child buffers, but now all my old presets seem so primitive. Keep playing with AVS and you will impress yourself! I guarantee it!<br />
<br />
===Writing APEs===<br />
BOX is a quick and dirty demonstration of basic APE structure and the utilization of AVS features. It takes advantage of AVS's built-in beat detection and easy access to the frame buffer to flash a rectangle onscreen on every beat. We also learn how to set up a configuration screen template, load and save configuration settings, and use the default color selector. There is very little fat, so you can use this as a template for future APEs. You can view the main file below.<br />
<br />
====Box Source code====<br />
<br />
You can check a sample [[box source code here]]<br />
<br />
==Milk Drop Unleashed==<br />
'''MilkDrop''' is a music visualizer - a "plug-in" to the Winamp music player. As you listen your music in Winamp, MilkDrop takes you flying through the actual soundwaves you're hearing, and uses beat detection to trigger myriad psychedelic effects, creating a rich visual journey through sound. MilkDrop can also be driven by a live audio feed (microphone or line-in)<br />
<br />
'''MilkDrop 2''' is a major upgrade to the original MilkDrop visualizer, opening up <br />
the power of modern graphics chips and programmable pixel shaders to the realm <br />
of music visualization. Pixel shaders allow dozens, even hundreds of complex <br />
instructions to be executed for every pixel on the screen, every frame. <br />
Other new features include jpg textures, gaussian blurring, a preset "mash-up" <br />
feature, and a prest "back" button. MilkDrop 2 is backwards-compatible with <br />
presets from MilkDrop 1.<br />
<br />
For a comprehensive understanding, please go through the [[MilkDrop Unleashed Guide]]<br />
<br />
To create your own presets, check out the [[MilkDrop_Preset_Authoring]] Guide<br />
<br />
For on-going discussions on Milk Drop, drop in the [http://forums.winamp.com/forumdisplay.php?forumid=81 Milk Drop Forums]<br />
<br />
<br />
<br />
<br />
<br />
==Developer Resources==<br />
* [[Articles#Visualization_Articles|Visual Developer Articles]]<br />
* [[Developers_FAQ#Visual_Developer_FAQ|Visual Developer FAQ]]<br />
* Rovastar's [http://www.milkdrop.co.uk/ MilkDrop Resource Website]<br />
* Download MilkDrop [http://www.nullsoft.com/free/milkdrop/Milkdrop_1.04_Source.zip Source Code]<br />
* [http://forums.winamp.com/forumdisplay.php?forumid=81 MilkDrop Forums]</div>Culixhttp://wiki.shoutcast.com/wiki/Creating_Custom_CursorsCreating Custom Cursors2010-11-30T03:27:56Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Explorer09</p>
<hr />
<div>{{ClassicSkin}}<br />
<br />
A commonly overlooked skinning property is Winamp cursors. That is, the little arrow that you use to navigate through Winamp doesn't necessarily have to be an arrow. There are 27 different cursor states that Winamp can be in. Wouldn't it be cool if each one had specialized art that matched your skin? All you would need is an icon editing tool, and that idea becomes reality. <br />
<br />
==Cursor Filenames==<br />
<br />
The Base skin comes with the following cursors:<br />
<br />
*CLOSE.CUR: (Main Menu X)<br />
*EQCLOSE.CUR: (EQ Close)<br />
*EQNORMAL.CUR: (EQ Normal)<br />
*EQSLID.CUR: (EQ Up and Down Slides)<br />
*EQTITLE.CUR: (EQ Titlebar)<br />
*MAINMENU.CUR: (Main Menu Menu Button-topleft)<br />
*MIN.CUR: (Main Menu Minimize Button)<br />
*NORMAL.CUR: (Main Menu Normal Arrow)<br />
*PCLOSE.CUR: (Playlist Close)<br />
*PNORMAL.CUR: (Playlist Normal)<br />
*POSBAR.CUR: (Main Menu Song Position)<br />
*PSIZE.CUR: (Playlist Expansion Mode)<br />
*PTBAR.CUR: (Playlist Top Bar)<br />
*PVSCROLL.CUR: (Playlist vertical button)<br />
*PWINBUT.CUR: (Playlist Windowshade Mode)<br />
*PWSNORM.CUR: (Playlist Windowshade Normal)<br />
*PWSSIZE.CUR: (Playlist Windowshade Size Explainsion)<br />
*SONGNAME.CUR: (Song Name Scroll)<br />
*TITLEBAR.CUR: (Main Menu Name Bar)<br />
*VOLBAL.CUR: (Main Menu Volume Balance)<br />
*VOLBAR.CUR: (Main Menu Volume Switch)<br />
*WINBUT.CUR: (Main Menu Windowshade Mode)<br />
*WSCLOSE.CUR: (Windowshade Close)<br />
*WSMIN.CUR: (WindowShade Main Minimize)<br />
*WSNORMAL.CUR: (Windowshade Normal)<br />
*WSPOSBAR.CUR: (Windowshade Song Position)<br />
*WSWINBUT.CUR: (Windowshade Exit Windowshade Mode)</div>Culixhttp://wiki.shoutcast.com/wiki/Media_Library_APIMedia Library API2010-11-30T03:27:41Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>== Messages sent to your plugin's MessageProc ==<br />
<source lang="cpp"><br />
// return values from the winampUninstallPlugin(HINSTANCE hdll, HWND parent, int param)<br />
// which determine if we can uninstall the plugin immediately or on winamp restart<br />
//<br />
// uninstall support was added from 5.0+ and uninstall now support from 5.5+<br />
// it is down to you to ensure that if uninstall now is returned that it will not cause a crash<br />
// (ie don't use if you've been subclassing the main window)<br />
#define ML_PLUGIN_UNINSTALL_NOW 0x1<br />
#define ML_PLUGIN_UNINSTALL_REBOOT 0x0<br />
<br />
// messages your plugin may receive on MessageProc()<br />
<br />
#define ML_MSG_TREE_BEGIN 0x100<br />
#define ML_MSG_TREE_ONCREATEVIEW 0x100 // param1 = param of tree item, param2 is HWND of parent. return HWND if it is us<br />
<br />
#define ML_MSG_TREE_ONCLICK 0x101 // param1 = param of tree item, param2 = action type (below), param3 = HWND of main window<br />
#define ML_ACTION_RCLICK 0 // return value should be nonzero if ours<br />
#define ML_ACTION_DBLCLICK 1<br />
#define ML_ACTION_ENTER 2<br />
#define ML_ACTION_LCLICK 3<br />
<br />
#define ML_MSG_TREE_ONDROPTARGET 0x102 // param1 = param of tree item, param2 = type of drop (ML_TYPE_*), param3 = pointer to data (or NULL if querying).<br />
// return -1 if not allowed, 1 if allowed, or 0 if not our tree item<br />
<br />
#define ML_MSG_TREE_ONDRAG 0x103 // param1 = param of tree item, param2 = POINT * to the mouse position, and param3 = (int *) to the type<br />
// set *(int*)param3 to the ML_TYPE you want and return 1, if you support drag&drop, or -1 to prevent d&d.<br />
<br />
#define ML_MSG_TREE_ONDROP 0x104 // param1 = param of tree item, param2 = POINT * to the mouse position<br />
// if you support dropping, send the appropriate ML_IPC_HANDLEDROP using SendMessage() and return 1, otherwise return -1.<br />
<br />
#define ML_MSG_TREE_ONKEYDOWN 0x105 // Send when key pressed <br />
// param1 = param of tree item;<br />
// param2 = pointer to NMTVKEYDOWN<br />
// param3 = tree hwnd<br />
// return 0 if it's not yours, 1 if it is<br />
<br />
#define ML_MSG_TREE_END 0x1FF // end of tree specific messages<br />
<br />
<br />
#define ML_MSG_ONSENDTOBUILD 0x300 // you get sent this when the sendto menu gets built<br />
// param1 = type of source, param2 param to pass as context to ML_IPC_ADDTOSENDTO<br />
// be sure to return 0 to allow other plugins to add their context menus<br />
<br />
<br />
// if your sendto item is selected, you will get this with your param3 == your user32 (preferably some<br />
// unique identifier (like your plugin message proc). See ML_IPC_ADDTOSENDTO<br />
#define ML_MSG_ONSENDTOSELECT 0x301<br />
// param1 = type of source, param2 = data, param3 = user32<br />
<br />
// return TRUE and do a config dialog using param1 as a HWND parent for this one<br />
#define ML_MSG_CONFIG 0x400<br />
<br />
</source><br />
<br />
== Messages you can send to the Media Library HWND ==<br />
<source lang="cpp"><br />
<br />
#define ML_TYPE_UNKNOWN -1<br />
#define ML_TYPE_ITEMRECORDLIST 0 // if this, cast obj to itemRecordList<br />
#define ML_TYPE_FILENAMES 1 // double NULL terminated char * to files, URLS, or playlists<br />
#define ML_TYPE_STREAMNAMES 2 // double NULL terminated char * to URLS, or playlists ( effectively the same as ML_TYPE_FILENAMES, but not for files)<br />
#define ML_TYPE_CDTRACKS 3 // if this, cast obj to itemRecordList (CD tracks) -- filenames should be cda://<drive letter>,<track index>. artist/album/title might be valid (CDDB)<br />
#define ML_TYPE_QUERYSTRING 4 // char * to a query string<br />
#define ML_TYPE_PLAYLIST 5 // mlPlaylist *<br />
#define ML_TYPE_ITEMRECORDLISTW 6 // if this, cast obj to itemRecordListW<br />
// added from 5.36+<br />
#define ML_TYPE_FILENAMESW 7 // double NULL terminated wchar_t * to files, URLS, or playlists<br />
#define ML_TYPE_STREAMNAMESW 8 // double NULL terminated wchar_t * to URLS, or playlists ( effectively the same as ML_TYPE_FILENAMESW, but not for files)<br />
#define ML_TYPE_PLAYLISTS 9 // mlPlaylist **, null terminated<br />
#define ML_TYPE_TREEITEM 69 // uhh?<br />
<br />
typedef struct<br />
{<br />
const wchar_t *filename;<br />
const wchar_t *title;<br />
// only fill in the following two if already know. don't calculate it just for the struct. <br />
// put -1 for "don't know"<br />
int numItems; <br />
int length; // in seconds. <br />
} mlPlaylist;<br />
<br />
// if you wish to put your tree items under "devices", use this constant for ML_IPC_ADDTREEITEM<br />
#define ML_TREEVIEW_ID_DEVICES 10000<br />
<br />
<br />
<br />
// children communicate back to the media library by SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,param,ML_IPC_X);<br />
#define WM_ML_IPC WM_USER+0x1000<br />
<br />
<br />
#define ML_IPC_GETCURRENTVIEW 0x090 // Returns HWND to the currently selected view or NULL if nothing selected or error. (WA 5.22 and higher)<br />
<br />
<br />
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br />
// Old Tree Item API (deprecated)<br />
//<br />
#define ML_IPC_ADDTREEITEM 0x0101 // pass mlAddTreeItemStruct as the param<br />
#define ML_IPC_SETTREEITEM 0x0102 // pass mlAddTreeItemStruct with id valid<br />
#define ML_IPC_DELTREEITEM 0x0103 // pass param of tree item to remove<br />
#define ML_IPC_GETCURTREEITEM 0x0104 // returns current tree item param or 0 if none<br />
#define ML_IPC_SETCURTREEITEM 0x0105 // selects the tree item passed, returns 1 if found, 0 if not<br />
#define ML_IPC_GETTREE 0x0106 // returns a HMENU with all the tree items. the caller needs to delete the returned handle! pass mlGetTreeStruct as the param<br />
<br />
/* deprecated. Use MLTREEITEM instead */<br />
typedef struct {<br />
INT_PTR parent_id; //0=root, or ML_TREEVIEW_ID_*<br />
char *title;<br />
int has_children;<br />
INT_PTR this_id; //filled in by the library on ML_IPC_ADDTREEITEM<br />
} mlAddTreeItemStruct;<br />
<br />
typedef struct {<br />
int item_start; // TREE_PLAYLISTS, TREE_DEVICES...<br />
int cmd_offset; // menu command offset if you need to make a command proxy, 0 otherwise<br />
int max_numitems; // maximum number of items you wish to insert or -1 for no limit<br />
} mlGetTreeStruct;<br />
<br />
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br />
/// For Predixis, with Love<br />
/// deprecatded (never use!!!)<br />
///<br />
#define ML_IPC_ADDTREEITEM_EX 0x0111 // pass mlAddTreeItemStructEx as the param<br />
#define ML_IPC_SETTREEITEM_EX 0x0112 // pass mlAddTreeItemStructEx with this_id valid<br />
<br />
typedef struct {<br />
INT_PTR parent_id; //0=root, or ML_TREEVIEW_ID_*<br />
char *title;<br />
int has_children;<br />
INT_PTR this_id; //filled in by the library on ML_IPC_ADDTREEITEM<br />
int imageIndex; // index of the image you want to be associated with your item<br />
} mlAddTreeItemStructEx;<br />
<br />
/// deprecatded (never use!!!)<br />
#define ML_IPC_ADDTREEIMAGE 0x110 // adds tree image to the ml. Use mlAddTreeImageStruct as the param.<br />
/// end of predixis special<br />
<br />
<br />
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br />
// Tree Item API (starting from 5.3)<br />
//<br />
#define ML_IPC_TREEITEM_GETHANDLE 0x120 // Gives you HANDLE to the item with specified ID in the param<br />
#define ML_IPC_TREEITEM_GETCHILD 0x121 // Returns HANDLE to the child item for the item HANDLE specified as a param. <br />
#define ML_IPC_TREEITEM_GETNEXT 0x122 // Returns HANDLE to the next item for the item HANDLE specified as a param.<br />
#define ML_IPC_TREEITEM_GETSELECTED 0x123 // Returns HANDLE to selected item.<br />
#define ML_IPC_TREEITEM_GETINFO 0x124 // Pass MLTREEITEMINFO as a param. return TRUE - if ok<br />
#define ML_IPC_TREEITEM_SETINFO 0x125 // Pass MLTREEITEMINFO as a param. return TRUE - if ok<br />
#define ML_IPC_TREEITEM_ADD 0x126 // Adds new item using MLTREEITEM passed as a param<br />
#define ML_IPC_TREEITEM_DELETE 0x127 // Deletes tree item. Pass HANDLE as a param.<br />
#define ML_IPC_TREEITEM_SELECT 0x128 // Selects tree item. Pass HANDLE as a param. <br />
#define ML_IPC_TREEITEM_GETROOT 0x129 // Gets first item.<br />
#define ML_IPC_TREEITEM_INSERT 0x130 // like ML_IPC_TREEITEM_ADD, but id becomes an "insert after" ID<br />
#define ML_IPC_TREEITEM_GETCHILD_ID 0x131 // Returns ID to the child item for the item ID specified as a param. <br />
#define ML_IPC_TREEITEM_GETNEXT_ID 0x132 // Returns ID to the next item for the item ID specified as a param.<br />
#define ML_IPC_TREEITEM_ADDW 0x133 // Adds new item using MLTREEITEMW passed as a param<br />
#define ML_IPC_TREEITEM_INSERTW 0x134 // like ML_IPC_TREEITEM_ADDW, but id becomes an "insert after" ID<br />
#define ML_IPC_TREEITEM_SETINFOW 0x135 // Pass MLTREEITEMINFOW as a param. return TRUE - if ok<br />
#define ML_IPC_TREEITEM_GETINFOW 0x136 // Pass MLTREEITEMINFO as a param. return TRUE - if ok<br />
#define MLTI_ROOT (INT_PTR)TVI_ROOT // can be used in ML_IPC_TREEITEM_GETCHILD<br />
<br />
typedef struct {<br />
size_t size; // size of this struct<br />
UINT_PTR id; // depends on contxext<br />
UINT_PTR parentId; // 0 = root, or ML_TREEVIEW_ID_*<br />
char *title; // pointer to the buffer contained item name. <br />
size_t titleLen; // used for GetInfo <br />
BOOL hasChildren; // TRUE - has children<br />
int imageIndex; // index of the associated image<br />
} MLTREEITEM;<br />
<br />
typedef struct {<br />
MLTREEITEM item; // item data<br />
UINT mask; // one or more of MLTI_* flags<br />
UINT_PTR handle; // Handle to the item. If handle is NULL item->id will be used<br />
} MLTREEITEMINFO;<br />
<br />
typedef struct {<br />
size_t size; // size of this struct<br />
UINT_PTR id; // depends on context<br />
UINT_PTR parentId; // 0 = root, or ML_TREEVIEW_ID_*<br />
wchar_t *title; // pointer to the buffer contained item name. <br />
size_t titleLen; // used for GetInfo <br />
BOOL hasChildren; // TRUE - has children<br />
int imageIndex; // index of the associated image<br />
} MLTREEITEMW;<br />
<br />
typedef struct {<br />
MLTREEITEMW item; // item data<br />
UINT mask; // one or more of MLTI_* flags<br />
UINT_PTR handle; // Handle to the item. If handle is NULL item->id will be used<br />
} MLTREEITEMINFOW;<br />
// Flags that used in the MLTREEITEMINFO struct<br />
#define MLTI_CHILDREN TVIF_CHILDREN<br />
#define MLTI_IMAGE TVIF_IMAGE<br />
#define MLTI_TEXT TVIF_TEXT<br />
#define MLTI_ID TVIF_PARAM<br />
<br />
<br />
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br />
// Tree image (starting from 5.3)<br />
//<br />
<br />
#define ML_IPC_TREEIMAGE_ADD 0x140 // adds tree image to the ml. Use MLTREEIMAGE as the param.<br />
<br />
typedef struct _COLOR24<br />
{<br />
unsigned char rgbBlue;<br />
unsigned char rgbGreen;<br />
unsigned char rgbRed;<br />
}COLOR24; // color struct <br />
<br />
typedef void (*BMPFILTERPROC)(const COLOR24*, const COLOR24*, COLOR24*); // color filter procedure <br />
// you got two colors: color1 and color2 (usualy BG and FG colors) also you as a third parameter<br />
// you get a pixel color value that you need (can) modify <br />
<br />
#define FILTER_NO ((BMPFILTERPROC)NULL)<br />
#define FILTER_DEFAULT1 ((BMPFILTERPROC)1)<br />
#define FILTER_DEFAULT2 ((BMPFILTERPROC)2)<br />
<br />
#define MLTREEIMAGE_NONE 0<br />
#define MLTREEIMAGE_DEFAULT 1<br />
#define MLTREEIMAGE_BRANCH 2 // calculates at the time <br />
#define MLTREEIMAGE_BRANCH_EXPANDED 3<br />
#define MLTREEIMAGE_BRANCH_COLLAPSED 4<br />
#define MLTREEIMAGE_BRANCH_NOCHILD 5<br />
<br />
typedef struct {<br />
HINSTANCE hinst; // hInstance<br />
int resourceId; // resource id <br />
int imageIndex; // set image to specified index (specify -1 to get a new index back)<br />
BMPFILTERPROC filterProc; // pointer to the filter proc to use or one of the FILTER_*<br />
int width; // reserved<br />
int height; // reserved<br />
} MLTREEIMAGE; // basicly ml will read your reosurce when it will need to create your image<br />
<br />
#define ML_IPC_NEWPLAYLIST 0x107 // pass hwnd for dialog parent as param<br />
#define ML_IPC_IMPORTPLAYLIST 0x108 // pass hwnd for dialog parent as param<br />
#define ML_IPC_IMPORTCURRENTPLAYLIST 0x109<br />
#define ML_IPC_GETPLAYLISTWND 0x10A<br />
#define ML_IPC_SAVEPLAYLIST 0x10B // pass hwnd for dialog parent as param<br />
#define ML_IPC_OPENPREFS 0x10C<br />
<br />
#define ML_IPC_PLAY_PLAYLIST 0x010D // plays the playlist pointed to by the tree item passed, returns 1 if found, 0 if not<br />
#define ML_IPC_LOAD_PLAYLIST 0x010E // loads the playlist pointed to by the tree item passed into the playlist editor, returns 1 if found, 0 if not<br />
<br />
#define ML_IPC_REFRESH_PREFS 0x10F // this doesn't belong in here <br />
<br />
<br />
/** ------------------ <br />
** ml_playlists <br />
** ------------------ */<br />
<br />
#define PL_FLAG_SHOW 1<br />
#define PL_FLAG_SWITCH 2<br />
#define PL_FLAGS_IMPORT 4 // set to have ml_playlists make a copy (only valid for mlAddPlaylist)<br />
#define PL_FLAG_FILL_FILENAME 8 // only valid for mlMakePlaylist<br />
<br />
typedef struct <br />
{<br />
size_t size; // size of this struct<br />
const wchar_t *playlistName; // set to NULL (or empty string) to prompt the user for a name<br />
const wchar_t *filename;<br />
int flags; // see PL_FLAG_* above<br />
// the following two items can be optionally filled in (set to -1 otherwise)<br />
// if they aren't set, the playlist file will have to be opened and parsed<br />
// so prepopulating is faster (assuming if you already know the data)<br />
int numItems; // set to -1 if you don't know. <br />
int length; // in seconds, set to -1 if you don't know<br />
} mlAddPlaylist;<br />
<br />
#define ML_IPC_PLAYLIST_ADD 0x180 // call to add a new playlist file to the Playlists treeview. pass an mlAddPlaylist *<br />
<br />
typedef struct <br />
{<br />
size_t size; // size of this struct<br />
const wchar_t *playlistName; // set to NULL (or empty string) to prompt the user for a name<br />
int type; //ML_TYPE_ITEMRECORDLIST, etc<br />
void *data; // object to load<br />
int flags; // see PL_FLAG_* above<br />
wchar_t filename[MAX_PATH]; // this will get populated if PL_FLAG_FILL_NAME is set<br />
} mlMakePlaylistV2;<br />
<br />
// old structure, here to make it easy to do a sizeof() check<br />
typedef struct <br />
{<br />
size_t size; // size of this struct<br />
const wchar_t *playlistName; // set to NULL (or empty string) to prompt the user for a name<br />
int type; //ML_TYPE_ITEMRECORDLIST, etc<br />
void *data; // object to load<br />
int flags; // see PL_FLAG_* above<br />
} mlMakePlaylist;<br />
<br />
/* Call to add a new playlist to the Playlists treeview. <br />
It will be automatically created based on the data you pass<br />
type & data follow the same specifications as send-to, drag-and-drop, etc.<br />
*/<br />
#define ML_IPC_PLAYLIST_MAKE 0x181 // call to create a new playlist in the treeview based on passed information. pass an mlMakePlaylist *<br />
#define ML_IPC_PLAYLIST_COUNT 0x182<br />
#define ML_IPC_PLAYLIST_INFO 0x183 // pass in the struct below. returns "1" on success and "0" on failure<br />
<br />
typedef struct<br />
{<br />
// you fill this in<br />
size_t size; // size of this struct<br />
size_t playlistNum; // number of the playlist you want to retrieve (0 index)<br />
// ml_playlists fills these in<br />
wchar_t playlistName[128];<br />
wchar_t filename[MAX_PATH];<br />
int numItems;<br />
int length; // in seconds<br />
} mlPlaylistInfo;<br />
<br />
<br />
/** ------------------ <br />
** <br />
** ------------------ */<br />
<br />
#define ML_IPC_GETFILEINFO 0x0200 // pass it a &itemRecord with a valid filename (and all other fields NULL), and it will try to fill in the rest<br />
#define ML_IPC_FREEFILEINFO 0x0201 // pass it a &itemRecord tha twas filled by getfileinfo, it will free the strings it allocated<br />
<br />
#define ML_IPC_HANDLEDRAG 0x0300 // pass it a &mlDropItemStruct it will handle cursors etc (unless flags has the lowest bit set), and it will set result appropriately:<br />
#define ML_IPC_HANDLEDROP 0x0301 // pass it a &mlDropItemStruct with data on drop:<br />
<br />
#define ML_IPC_SENDTOWINAMP 0x302 // send with a mlSendToWinampStruct:<br />
typedef struct {<br />
int type; //ML_TYPE_ITEMRECORDLIST, etc<br />
void *data; // object to play<br />
<br />
int enqueue; // low bit set specifies enqueuing, and second bit NOT set specifies that <br />
// the media library should use its default behavior as the user configured it (if <br />
// enqueue is the default, the low bit will be flipped by the library)<br />
} mlSendToWinampStruct;<br />
<br />
<br />
typedef struct {<br />
char *desc; // str<br />
intptr_t context; // context passed by ML_MSG_ONSENDTOBUILD<br />
intptr_t user32; // use some unique ptr in memory, you will get it back in ML_MSG_ONSENDTOSELECT...<br />
} mlAddToSendToStruct;<br />
#define ML_IPC_ADDTOSENDTO 0x0400<br />
<br />
typedef struct {<br />
wchar_t *desc; // str<br />
intptr_t context; // context passed by ML_MSG_ONSENDTOBUILD<br />
intptr_t user32; // use some unique ptr in memory, you will get it back in ML_MSG_ONSENDTOSELECT...<br />
} mlAddToSendToStructW;<br />
#define ML_IPC_ADDTOSENDTOW 0x0401 // pass mlAddToSendToStructW<br />
<br />
// used to make a submenu in sendto<br />
// pass mlAddToSendToStructW, set desc to 0 to start, set valid desc to end<br />
// user32 is unused <br />
#define ML_IPC_BRANCHSENDTO 0x0402 <br />
<br />
// follow same rules as ML_IPC_ADDTOSENDTOW, but adds to branch instead of main send-to menu<br />
#define ML_IPC_ADDTOBRANCH 0x403 // pass mlAddToSendToStructW<br />
<br />
<br />
<br />
#define ML_IPC_HOOKTITLE 0x0440 // this is like winamp's IPC_HOOK_TITLES... :) param1 is waHookTitleStruct<br />
#define ML_IPC_HOOKEXTINFO 0x441 // called on IPC_GET_EXTENDED_FILE_INFO_HOOKABLE, param1 is extendedFileInfoStruct<br />
#define ML_IPC_HOOKEXTINFOW 0x442 // called on IPC_GET_EXTENDED_FILE_INFO_HOOKABLEW, param1 is extendedFileInfoStructW<br />
#define ML_IPC_HOOKTITLEW 0x0443 // this is like winamp's IPC_HOOK_TITLESW... :) param1 is waHookTitleStructW<br />
<br />
#define ML_HANDLEDRAG_FLAG_NOCURSOR 1<br />
#define ML_HANDLEDRAG_FLAG_NAME 2<br />
<br />
typedef struct {<br />
int type; //ML_TYPE_ITEMRECORDLIST, etc<br />
void *data; // NULL if just querying<br />
<br />
int result; // filled in by client: -1 if dont allow, 0 if dont know, 1 if allow.<br />
<br />
POINT p; // cursor pos in screen coordinates<br />
int flags; <br />
<br />
char *name; // only valid if ML_HANDLEDRAG_FLAG_NAME<br />
<br />
} mlDropItemStruct;<br />
<br />
<br />
#define ML_IPC_SKIN_LISTVIEW 0x0500 // pass the hwnd of your listview. returns a handle to use with ML_IPC_UNSKIN_LISTVIEW<br />
#define ML_IPC_UNSKIN_LISTVIEW 0x0501 // pass the handle you got from ML_IPC_SKIN_LISTVIEW<br />
#define ML_IPC_LISTVIEW_UPDATE 0x0502 // pass the handle you got from ML_IPC_SKIN_LISTVIEW<br />
#define ML_IPC_LISTVIEW_DISABLEHSCROLL 0x0503 // pass the handle you got from ML_IPC_SKIN_LISTVIEW<br />
#define ML_IPC_LISTVIEW_DISABLEVSCROLL 0x050A // pass the handle you got from ML_IPC_SKIN_LISTVIEW<br />
#define ML_IPC_LISTVIEW_SHOWSORT 0x0504 // use LV_SKIN_SHOWSORT<br />
#define ML_IPC_LISTVIEW_SORT 0x0505 // use LV_SKIN_SORT<br />
<br />
typedef struct <br />
{<br />
INT_PTR listView;<br />
BOOL showSort;<br />
} LV_SKIN_SHOWSORT;<br />
<br />
typedef struct<br />
{<br />
INT_PTR listView;<br />
int columnIndex;<br />
BOOL ascending;<br />
} LV_SKIN_SORT;<br />
<br />
<br />
#define ML_IPC_SKIN_COMBOBOX 0x0508 // pass the hwnd of your combobox to skin, returns a ahndle to use with ML_IPC_UNSKIN_COMBOBOX<br />
#define ML_IPC_UNSKIN_COMBOBOX 0x0509 // pass the handle from ML_IPC_SKIN_COMBOBOX<br />
<br />
#define ML_IPC_SKIN_WADLG_GETFUNC 0x0600 <br />
// 1: return int (*WADlg_getColor)(int idx); // pass this an index, returns a RGB value (passing 0 or > 3 returns NULL)<br />
// 2: return int (*WADlg_handleDialogMsgs)(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); <br />
// 3: return void (*WADlg_DrawChildWindowBorders)(HWND hwndDlg, int *tab, int tabsize); // each entry in tab would be the id | DCW_*<br />
// 32: return void (*childresize_init)(HWND hwndDlg, ChildWndResizeItem *list, int num);<br />
// 33: return void (*childresize_resize)(HWND hwndDlg, ChildWndResizeItem *list, int num);<br />
// 66: return (HFONT) font to use for dialog elements, if desired (0 otherwise)<br />
<br />
// itemRecord type for use with ML_TYPE_ITEMRECORDLIST, as well as many other functions<br />
typedef struct<br />
{<br />
char *filename;<br />
char *title;<br />
char *album;<br />
char *artist;<br />
char *comment;<br />
char *genre;<br />
int year;<br />
int track;<br />
int length;<br />
char **extended_info;<br />
// currently defined extended columns (while they are stored internally as integers<br />
// they are passed using extended_info as strings):<br />
// use getRecordExtendedItem and setRecordExtendedItem to get/set.<br />
// for your own internal use, you can set other things, but the following values<br />
// are what we use at the moment. Note that setting other things will be ignored<br />
// by ML_IPC_DB*.<br />
// <br />
//"RATING" file rating. can be 1-5, or 0 or empty for undefined<br />
//"PLAYCOUNT" number of file plays.<br />
//"LASTPLAY" last time played, in standard time_t format<br />
//"LASTUPD" last time updated in library, in standard time_t format<br />
//"FILETIME" last known file time of file, in standard time_t format<br />
//"FILESIZE" last known file size, in kilobytes.<br />
//"BITRATE" file bitrate, in kbps<br />
//"TYPE" - "0" for audio, "1" for video<br />
<br />
} itemRecord;<br />
<br />
typedef struct <br />
{<br />
itemRecord *Items;<br />
int Size;<br />
int Alloc;<br />
} itemRecordList;<br />
<br />
#include <time.h><br />
<br />
typedef struct<br />
{<br />
wchar_t *filename;<br />
wchar_t *title;<br />
wchar_t *album;<br />
wchar_t *artist;<br />
wchar_t *comment;<br />
wchar_t *genre;<br />
wchar_t *albumartist; <br />
wchar_t *replaygain_album_gain; // these are strings rather than float's to differentiate between '0 gain' and 'not defined'<br />
wchar_t *replaygain_track_gain; // these are strings rather than float's to differentiate between '0 gain' and 'not defined'<br />
wchar_t *publisher;<br />
wchar_t *composer;<br />
int year;<br />
int track;<br />
int tracks;<br />
int length;<br />
int rating; // file rating. can be 1-5, or 0 for undefined<br />
int playcount; // number of file plays.<br />
__time64_t lastplay; // last time played, in standard time_t format<br />
__time64_t lastupd; // last time updated in library, in standard time_t format<br />
__time64_t filetime; // last known file time of file, in standard time_t format<br />
int filesize; //last known file size, in kilobytes.<br />
int bitrate; // file bitrate, in kbps<br />
int type; // 0 for audio, 1 for video<br />
int disc; // disc number<br />
int discs; // number of discs<br />
int bpm;<br />
wchar_t **extended_info; <br />
// currently defined extended columns (while they are stored internally as integers<br />
// they are passed using extended_info as strings):<br />
// use getRecordExtendedItem and setRecordExtendedItem to get/set.<br />
// for your own internal use, you can set other things, but the following values<br />
// are what we use at the moment. Note that setting other things will be ignored<br />
// by ML_IPC_DB*.<br />
// <br />
<br />
} itemRecordW;<br />
<br />
typedef struct <br />
{<br />
itemRecordW *Items;<br />
int Size;<br />
int Alloc;<br />
} itemRecordListW;<br />
<br />
//<br />
// all return 1 on success, -1 on error. or 0 if not supported, maybe?<br />
<br />
// pass these a mlQueryStruct<br />
// results should be zeroed out before running a query, but if you wish you can run multiple queries and <br />
// have it concatenate the results. tho it would be more efficient to just make one query that contains both,<br />
// as running multiple queries might have duplicates etc.<br />
// in general, though, if you need to treat "results" as if they are native, you should use<br />
// copyRecordList to save a copy, then free the results using ML_IPC_DB_FREEQUERYRESULTS.<br />
// if you need to keep an exact copy that you will only read (and will not modify), then you can<br />
// use the one in the mlQueryStruct.<br />
<br />
#define ML_IPC_DB_RUNQUERY 0x0700 <br />
#define ML_IPC_DB_RUNQUERY_SEARCH 0x0701 // "query" should be interpreted as keyword search instead of query string<br />
#define ML_IPC_DB_RUNQUERY_FILENAME 0x0702 // searches for one exact filename match of "query"<br />
#define ML_IPC_DB_RUNQUERY_INDEX 0x703 // retrieves item #(int)query<br />
<br />
#define ML_IPC_DB_FREEQUERYRESULTS 0x0705 // frees memory allocated by ML_IPC_RUNQUERY (empties results)<br />
typedef struct <br />
{<br />
char *query;<br />
int max_results; // can be 0 for unlimited<br />
itemRecordList results;<br />
} mlQueryStruct;<br />
<br />
/* Unicode versions of the above */<br />
<br />
#define ML_IPC_DB_RUNQUERYW 0x1700<br />
#define ML_IPC_DB_RUNQUERY_SEARCHW 0x1701 // "query" should be interpreted as keyword search instead of query string<br />
#define ML_IPC_DB_RUNQUERY_FILENAMEW 0x1702 // searches for one exact filename match of "query"<br />
#define ML_IPC_DB_RUNQUERY_INDEXW 0x1703 // retrieves item #(int)query<br />
#define ML_IPC_DB_FREEQUERYRESULTSW 0x1705 // frees memory allocated by ML_IPC_RUNQUERYW (empties results)<br />
typedef struct <br />
{<br />
wchar_t *query;<br />
int max_results; // can be 0 for unlimited<br />
itemRecordListW results;<br />
} mlQueryStructW;<br />
<br />
/* ----------------------------- */<br />
<br />
// pass these an (itemRecord *) to add/update.<br />
// note that any NULL fields in the itemRecord won't be updated, <br />
// and year, track, or length of -1 prevents updating as well.<br />
#define ML_IPC_DB_UPDATEITEM 0x0706 // returns -2 if item not found in db<br />
#define ML_IPC_DB_ADDORUPDATEITEM 0x0707<br />
<br />
#define ML_IPC_DB_REMOVEITEM 0x0708 // pass a char * to the filename to remove. returns -2 if file not found in db.<br />
<br />
typedef struct <br />
{<br />
char* fileName; // file name to add<br />
int meta_mode; // metadata get mode (0 - don't use metadata, 1 - use metadata; -1 - read from user settings (ini file)<br />
int gues_mode; // metadata guessing mode (0 - smart, 1 - simple; 2 - no, -1 - read from user settings (ini file)<br />
} LMDB_FILE_ADD_INFO;<br />
<br />
#define ML_IPC_DB_UPDATEFILE 0x0710 // Update File in the Local Media Data Base (return -2 if file record not found)<br />
#define ML_IPC_DB_ADDORUPDATEFILE 0x0711 // Adds or Updates File in the Local Media Data Base.<br />
<br />
/* Unicode versions of the above */<br />
<br />
// pass these an (itemRecordW *) to add/update.<br />
// note that any NULL fields in the itemRecordW won't be updated, <br />
// and year, track, or length of -1 prevents updating as well.<br />
#define ML_IPC_DB_UPDATEITEMW 0x1706 // returns -2 if item not found in db<br />
#define ML_IPC_DB_ADDORUPDATEITEMW 0x1707<br />
<br />
typedef struct <br />
{<br />
wchar_t* fileName; // file name to add<br />
int meta_mode; // metadata get mode (0 - don't use metadata, 1 - use metadata; -1 - read from user settings (ini file)<br />
int gues_mode; // metadata guessing mode (0 - smart, 1 - simple; 2 - no, -1 - read from user settings (ini file)<br />
} LMDB_FILE_ADD_INFOW;<br />
<br />
#define ML_IPC_DB_UPDATEFILEW 0x1710 // Update File in the Local Media Data Base (return -2 if file record not found) NOTE that this call is broken on 5.33. Only use on 5.34+<br />
#define ML_IPC_DB_ADDORUPDATEFILEW 0x1711 // Adds or Updates File in the Local Media Data Base.<br />
<br />
/* ----------------------------- */<br />
<br />
<br />
#define ML_IPC_DB_SYNCDB 0x0709 // sync db if dirty flags are set. good to do after a batch of updates.<br />
<br />
<br />
<br />
<br />
// these return 0 if unsupported, -1 if failed, 1 if succeeded<br />
<br />
// pass a winampMediaLibraryPlugin *. Will not call plugin's init() func. <br />
// YOU MUST set winampMediaLibraryPlugin->hDllInstance to NULL, and version to MLHDR_VER<br />
// 5.25+: You can set hDllInstance to valid value. <br />
// This IPC will return -1 on failure, so a good check against old verions<br />
// is to try with hDllInstance set, if it returns -1, try again with hDllInstance=0<br />
#define ML_IPC_ADD_PLUGIN 0x0750 <br />
#define ML_IPC_REMOVE_PLUGIN 0x0751 // winampMediaLibraryPlugin * of plugin to remove. Will not call plugin's quit() func<br />
<br />
#define ML_IPC_SEND_PLUGIN_MESSAGE 0x0752 // sends message to plugins (wParam = 0, lParam = pointer to the pluginMessage struct)<br />
// pluginMessage struct<br />
typedef struct {<br />
int messageType;<br />
INT_PTR param1;<br />
INT_PTR param2;<br />
INT_PTR param3;<br />
} pluginMessage;<br />
<br />
#define ML_IPC_ENSURE_VISIBLE 0x753 // ensures that the media library is visible<br />
#define ML_IPC_IS_VISIBLE 0x754 // queries the current visibility status<br />
<br />
#define ML_IPC_GET_PARENTAL_RATING 0x755 <br />
<br />
#define ML_IPC_TOGGLE_VISIBLE 0x756<br />
<br />
// this gets sent to any child windows of the library windows, and then (if not<br />
// handled) the library window itself<br />
<br />
#define WM_ML_CHILDIPC WM_APP+0x800 // avoids conflicts with any windows controls<br />
#define ML_CHILDIPC_DROPITEM 0x100 // lParam = 100, wParam = &mlDropItemStruct<br />
<br />
// current item ratings<br />
#define ML_IPC_SETRATING 0x0900 // lParam = 0 to 5, rates current track -- inserts it in the db if it's not in it yet <br />
#define ML_IPC_GETRATING 0x0901 // return the current track's rating or 0 if not in db/no rating<br />
<br />
// playlist entry rating<br />
typedef struct {<br />
int plentry;<br />
int rating;<br />
} pl_set_rating;<br />
<br />
#define ML_IPC_PL_SETRATING 0x0902 // lParam = pointer to pl_set_rating struct<br />
#define ML_IPC_PL_GETRATING 0x0903 // lParam = playlist entry, returns the rating or 0 if not in db/no rating<br />
<br />
typedef struct {<br />
HWND dialog_parent; // Use this window as a parent for the query editor dialog<br />
const char *query; // The query to edit, or "" / null for new query<br />
} ml_editquery; <br />
<br />
#define ML_IPC_EDITQUERY 0x904 // lParam = pointer to ml_editquery struct, returns 0 if edition was canceled and 1 on success<br />
// After returning, and if ok was clicked, the struct contains a pointer to the edited query. this pointer is static : <br />
// - do *not* free it<br />
// - if you need to keep it around, strdup it, as it may be changed later by other plugins calling ML_IPC_EDITQUERY.<br />
<br />
typedef struct { <br />
HWND dialog_parent; // Use this window as a parent for the view editor dialog<br />
const char *query; // The query to edit, or "" / null for new views<br />
const char *name; // Name of the view (ignored for new views)<br />
int mode; // View mode (0=simple view, 1=artist/album view, -1=hide mode radio boxes)<br />
} ml_editview; <br />
<br />
#define ML_IPC_EDITVIEW 0x905 // lParam = pointer to ml_editview struct, returns 0 if edition was canceled and 1 on success<br />
// After returning, and if ok was clicked, the struct contains the edited values. String pointers are static: <br />
// - do *not* free them <br />
// - if you need to keep them around, strdup them, as they may be changed later by other plugins calling ML_IPC_EDITQUERY.<br />
<br />
#define ML_IPC_SET_FILE_RATING 0x0906 // lParam = 0 to 5, rates current track -- inserts it in the db if it's not in it yet <br />
#define ML_IPC_GET_FILE_RATING 0x0907 // return the current track's rating or 0 if not in db/no rating<br />
<br />
// playlist entry rating<br />
typedef struct {<br />
const char* fileName;<br />
int newRating;<br />
} file_set_rating;<br />
<br />
#define ML_IPC_SMARTVIEW_COUNT 0x0908 // returns the number of smartviews. no parameter required<br />
#define ML_IPC_SMARTVIEW_INFO 0x0909 // pass a mlSmartViewInfo*. returns 1 on success and 0 on failure<br />
#define ML_IPC_SMARTVIEW_ADD 0x0910 // pass a mlSmartViewInfo* with filled in size, name, query, mode, iconImgIndex. treeitemid gets filled in. returns 1 on success and 0 on failure<br />
<br />
typedef struct<br />
{<br />
// you fill these in<br />
size_t size; // set to sizeof(mlSmartViewInfo)<br />
size_t smartViewNum;<br />
// ml_local fills these in<br />
wchar_t smartViewName[128];<br />
wchar_t smartViewQuery[512];<br />
int mode;<br />
int iconImgIndex;<br />
int treeItemId;<br />
} mlSmartViewInfo;<br />
<br />
<br />
#define ML_IPC_SET_FILE_RATINGW 0x0911 // lParam = 0 to 5, rates current track -- inserts it in the db if it's not in it yet <br />
#define ML_IPC_GET_FILE_RATINGW 0x0912 // return the current track's rating or 0 if not in db/no rating<br />
<br />
// playlist entry rating<br />
typedef struct {<br />
const wchar_t *fileName;<br />
int newRating;<br />
} file_set_ratingW;<br />
</source><br />
<br />
[[Category:Articles]]<br />
[[Category:Articles that need work]]</div>Culixhttp://wiki.shoutcast.com/wiki/Creating_Modern_SkinsCreating Modern Skins2010-11-30T03:27:36Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Culix</p>
<hr />
<div>==Description/Overview of Modern Skinning==<br />
<br />
Modern or Freeform skins were originally designed to work with Winamp3. What separates them from the average skin is the fact that they are not confined to the classic rectangular shape. In fact they can be any shape you want them to be and you can put the Winamp control buttons anywhere you want. Some skinners have even added extra buttons that extend the functionality of Winamp right there on the skin. Sounds too good to be true huh? Well these skins require a bit more coding to make and some of the graphics that go into them are quite large. Consequently, Freeform skins may take a bit longer to download from our site and they may take a few extra seconds to load when you switch from one skin to another. But trust me when I say that Freeform skins are worth the extra time and effort. Skin developers have done some incredible things with these skins. You have to check them out.<br />
<br />
== XML ==<br />
Here is your reference guide for XML coding.<br />
* '''[[XML Reference]]'''<br />
<br />
==Tools Needed to Build a Modern Skin==<br />
*'''[http://download.nullsoft.com/winamp/plugin-dev/WaSDP_1.1.exe Winamp Skin Development Pack]'''<br />
*[[Color Editor]]<br />
<br />
==Individual Components==<br />
<br />
*[[Modern Skin: Intro|Intro]]<br />
*[[Modern Skin: Winamp 2 to W3+|Winamp 2 to Winamp 3+]]<br />
*[[Modern Skin: Simple Skin Tutorial|Simple Skin Tutorial]]<br />
*[[Modern Skin: XML Intro|XML Intro]]<br />
*[[Modern Skin: Simple Skin Tutorial (Continued)|Simple Skin Tutorial (Continued)]]<br />
*[[Modern Skin: Container| Container]]<br />
*[[Modern Skin: Group|Group]]<br />
*[[Modern Skin: Relative Positioning| Relative Positioning]]<br />
*[[Modern Skin: Complex Skin|Complex Skin]]<br />
*[[Modern Skin: Non-Rect Player| Non-Rect Player]]<br />
*[[Modern Skin: Layer Composition| Layer Composition]]<br />
*[[Modern Skin: Alpha Channels| Alpha Channels]]<br />
*[[Modern Skin: Animatedlayer|Animatedlayer]]<br />
*[[Modern Skin: Snap Points|Snap Points]]<br />
*[[Modern Skin: Drawers|Drawers]]<br />
*[[Modern Skin: Skin Scripting| Skin Scripting]]<br />
*[[Modern Skin: Drawer Scripting| Drawer Scripting]]<br />
*[[Modern Skin: Animating a Skin|Animating a Skin]]<br />
*[[Modern Skin: Maki Overview| Maki Overview]]<br />
*[[Main_Page#Glossary_of_Terms|Glossary]]<br />
<br />
<br />
===Downloadable PDF===<br />
You can [http://media.winamp.com/5541/main/downloads/development/skinsmodern/Winamp-Modern-Skins-Tutorial.pdf download the tutorial] in PDF format for quick reference anytime</div>Culixhttp://wiki.shoutcast.com/wiki/The_Base_SkinThe Base Skin2010-11-30T03:27:32Z<p>Culix: Reverted edits by Iseficibuw (Talk) to last version by Explorer09</p>
<hr />
<div>{{ClassicSkin}}<br />
<br />
<!-- ==The Winamp Base Skin== --><br />
The Base Skin is a copy of the default skin built into Winamp. All you have to do to skin Winamp is paint over or replace a skin component with your own design and, ''voilà'', your own personalized version of Winamp. You can replace any or all of the components in a skin. Anything you don't replace will use its Base Skin counterpart. Naturally, the Base Skin components will look out of place, so we suggest changing every file.<br />
<br />
The Base Skin can be split into six logical segments, consisting of the following files:<br />
<br />
1) [[Main]]:<br />
:Main.bmp: Main Frame<br />
:Titlebar.bmp: Titlebar<br />
:Cbuttons.bmp: Control Buttons<br />
:Shufrep.bmp: Shuffle and Repeat Buttons<br />
:Volume.bmp: Volume Bar<br />
:Balance.bmp: Balance Bar<br />
:Monoster.bmp: Mono/Stereo Indicators<br />
:Posbar.bmp: Position Bar<br />
:Playpaus.bmp: Play/Paused Indicators<br />
:Numbers.bmp: Digit Reference<br />
:Text.bmp: Text Reference<br />
<br />
2) [[Equalizer]]:<br />
:Eqmain.bmp: Equalizer Main Frame<br />
:Eq_ex.bmp: Equalizer Window Shade Bar<br />
<br />
3) [[Playlist]]:<br />
:Pledit.bmp: Playlist Editor Frame/Buttons<br />
<br />
4) [[Mini-browser]]:<br />
:Mb.bmp: Mini-browser Frame<br />
<br />
5) [[AVS]]:<br />
:Avs.bmp: AVS Frame<br />
<br />
6) [[For Winamp 2.9/5.x]]: <!-- Thanks to Jellby --><br />
:Video.bmp: Video Window<br />
:Gen.bmp: General Purpose Window<br />
:Genex.bmp: General Purpose Buttons and Sliders</div>Culix