[cosmetics] update date in GPL header
[vuplus_xbmc] / xbmc / visualizations / Milkdrop / MilkdropXBMC.cpp
1 /*
2  *      Copyright (C) 2004-2013 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "vis_milkdrop/Plugin.h"
22 #include "../../addons/include/xbmc_vis_dll.h"
23 #include "XmlDocument.h"
24 #include <string>
25 #include <direct.h>
26
27 CPlugin* g_plugin=NULL;
28 char g_visName[512];
29
30 #define PRESETS_DIR "zip://special%3A%2F%2Fxbmc%2Faddons%2Fvisualization.milkdrop%2Fpresets%2F"
31
32 bool g_UserPackFolder;
33 std::string g_configFile;
34
35 int lastPresetIndx =0;
36 char lastPresetDir[1024] = "";
37 bool lastLockedStatus = false;
38
39 // Sets a new preset file or directory and make it active. Also recovers last state of the preset if it is the same as last time
40 void SetPresetDir(const char *pack)
41 {
42   int len = strlen(pack);
43   if (len >= 4 && strcmp(pack + len - 4, ".zip") == 0)
44   {
45     // Zip file
46     strcpy(g_plugin->m_szPresetDir, PRESETS_DIR);
47     strcat(g_plugin->m_szPresetDir,  pack);
48     strcat(g_plugin->m_szPresetDir, "/");
49   }
50   else if (len >= 4 && strcmp(pack + len - 4, ".rar") == 0)
51   {
52     // Rar file
53     strcpy(g_plugin->m_szPresetDir, PRESETS_DIR);
54     strcat(g_plugin->m_szPresetDir,  pack);
55     strcat(g_plugin->m_szPresetDir, "/");
56   }
57   else
58   {
59     // Normal folder
60     strcpy(g_plugin->m_szPresetDir,  pack);
61   }
62   if (strcmp (g_plugin->m_szPresetDir, lastPresetDir) == 0)
63   {
64     // If we have a valid last preset state AND the preset file(dir) is the same as last time
65     g_plugin->UpdatePresetList();
66     g_plugin->m_bHoldPreset = lastLockedStatus;
67     g_plugin->m_nCurrentPreset = lastPresetIndx;
68     strcpy(g_plugin->m_szCurrentPresetFile, g_plugin->m_szPresetDir);
69     strcat(g_plugin->m_szCurrentPresetFile, g_plugin->m_pPresetAddr[g_plugin->m_nCurrentPreset]);
70     g_plugin->LoadPreset(g_plugin->m_szCurrentPresetFile, g_plugin->m_fBlendTimeUser);
71   }
72   else
73     // If it is the first run or a newly chosen preset pack we choose a random preset as first
74     g_plugin->LoadRandomPreset(g_plugin->m_fBlendTimeUser);
75 }
76
77 void Preinit()
78 {
79   if(!g_plugin)
80   {
81     g_plugin = new CPlugin;
82     g_plugin->PluginPreInitialize(0, 0);
83   }
84 }
85
86 extern "C" ADDON_STATUS ADDON_Create(void* hdl, void* props)
87 {
88   if (!props)
89     return ADDON_STATUS_UNKNOWN;
90
91   VIS_PROPS* visprops = (VIS_PROPS*)props;
92   _mkdir(visprops->profile);
93
94   Preinit();
95   if(!g_plugin || !g_plugin->PluginInitialize((LPDIRECT3DDEVICE9)visprops->device, visprops->x, visprops->y, visprops->width, visprops->height, visprops->pixelRatio))
96     return ADDON_STATUS_UNKNOWN;
97
98   return ADDON_STATUS_NEED_SAVEDSETTINGS; // We need some settings to be saved later before we quit this plugin
99 }
100
101 extern "C" void Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, const char* szSongName)
102 {}
103
104
105 extern "C" void ADDON_Stop()
106 {
107   if(g_plugin)
108   {
109     g_plugin->PluginQuit();
110     delete g_plugin;
111     g_plugin = NULL;
112   }
113 }
114
115 unsigned char waves[2][512];
116
117 //-- Audiodata ----------------------------------------------------------------
118 // Called by XBMC to pass new audio data to the vis
119 //-----------------------------------------------------------------------------
120 extern "C" void AudioData(const float* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength)
121 {
122         int ipos=0;
123         while (ipos < 512)
124         {
125                 for (int i=0; i < iAudioDataLength; i+=2)
126                 {
127       waves[0][ipos] = char (pAudioData[i] * 255.0f);
128       waves[1][ipos] = char (pAudioData[i+1]  * 255.0f);
129                         ipos++;
130                         if (ipos >= 512) break;
131                 }
132         }
133 }
134
135 extern "C" void Render()
136 {
137         g_plugin->PluginRender(waves[0], waves[1]);
138
139 }
140
141 extern "C" void GetInfo(VIS_INFO* pInfo)
142 {
143         pInfo->bWantsFreq = false;
144         pInfo->iSyncDelay = 0;
145 }
146
147 //-- OnAction -----------------------------------------------------------------
148 // Handle XBMC actions such as next preset, lock preset, album art changed etc
149 //-----------------------------------------------------------------------------
150 extern "C" bool OnAction(long flags, const void *param)
151 {
152   bool ret = false;
153         if (flags == VIS_ACTION_NEXT_PRESET)
154         {
155                 g_plugin->LoadNextPreset(g_plugin->m_fBlendTimeUser);
156                 ret = true;
157         }
158         else if (flags == VIS_ACTION_PREV_PRESET)
159         {
160                 g_plugin->LoadPreviousPreset(g_plugin->m_fBlendTimeUser);
161                 ret = true;
162         }
163   else if (flags == VIS_ACTION_LOAD_PRESET && param)
164   {
165     g_plugin->m_nCurrentPreset = *(int *)param;
166           strcpy(g_plugin->m_szCurrentPresetFile, g_plugin->m_szPresetDir);     // note: m_szPresetDir always ends with '\'
167           strcat(g_plugin->m_szCurrentPresetFile, g_plugin->m_pPresetAddr[g_plugin->m_nCurrentPreset]);
168     g_plugin->LoadPreset(g_plugin->m_szCurrentPresetFile, g_plugin->m_fBlendTimeUser);
169     ret = true;
170   }
171   else if (flags == VIS_ACTION_LOCK_PRESET)
172   {
173     g_plugin->m_bHoldPreset = !g_plugin->m_bHoldPreset;
174     ret = true;
175   }
176   else if (flags == VIS_ACTION_RANDOM_PRESET)
177   {
178     g_plugin->LoadRandomPreset(g_plugin->m_fBlendTimeUser);
179     ret = true;
180   }
181     return ret;
182 }
183
184 void LoadSettings()
185 {}
186
187 //-- GetPresets ---------------------------------------------------------------
188 // Return a list of presets to XBMC for display
189 //-----------------------------------------------------------------------------
190 extern "C" unsigned int GetPresets(char ***presets)
191 {
192   if (!presets || !g_plugin) return 0;
193   *presets = g_plugin->m_pPresetAddr;
194   return g_plugin->m_nPresets;
195 }
196
197 //-- GetPreset ----------------------------------------------------------------
198 // Return the index of the current playing preset
199 //-----------------------------------------------------------------------------
200 extern "C" unsigned GetPreset()
201 {
202   if (g_plugin)
203     return g_plugin->m_nCurrentPreset;
204   return 0;
205 }
206
207 //-- IsLocked -----------------------------------------------------------------
208 // Returns true if this add-on use settings
209 //-----------------------------------------------------------------------------
210 extern "C" bool IsLocked()
211 {
212   if(g_plugin)
213     return g_plugin->m_bHoldPreset;
214   else
215     return false;
216 }
217
218 //-- Destroy-------------------------------------------------------------------
219 // Do everything before unload of this add-on
220 // !!! Add-on master function !!!
221 //-----------------------------------------------------------------------------
222 extern "C" void ADDON_Destroy()
223 {
224   ADDON_Stop();
225 }
226
227 //-- HasSettings --------------------------------------------------------------
228 // Returns true if this add-on use settings
229 // !!! Add-on master function !!!
230 //-----------------------------------------------------------------------------
231 extern "C" bool ADDON_HasSettings()
232 {
233   return true;
234 }
235
236 //-- GetStatus ---------------------------------------------------------------
237 // Returns the current Status of this visualisation
238 // !!! Add-on master function !!!
239 //-----------------------------------------------------------------------------
240 extern "C" ADDON_STATUS ADDON_GetStatus()
241 {
242   return ADDON_STATUS_OK;
243 }
244
245 //-- GetSettings --------------------------------------------------------------
246 // Return the settings for XBMC to display
247 //-----------------------------------------------------------------------------
248
249 extern "C" unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet)
250 {
251   return 0;
252 }
253
254 //-- FreeSettings --------------------------------------------------------------
255 // Free the settings struct passed from XBMC
256 //-----------------------------------------------------------------------------
257
258 extern "C" void ADDON_FreeSettings()
259 {
260 }
261
262 //-- UpdateSetting ------------------------------------------------------------
263 // Handle setting change request from XBMC
264 //-----------------------------------------------------------------------------
265 extern "C" ADDON_STATUS ADDON_SetSetting(const char* id, const void* value)
266 {
267   if (!id || !value || !g_plugin)
268     return ADDON_STATUS_UNKNOWN;
269
270   if (strcmp(id, "###GetSavedSettings") == 0) // We have some settings to be saved in the settings.xml file
271   {
272     if (strcmp((char*)value, "0") == 0)
273     {
274       strcpy((char*)id, "lastpresetfolder");
275       strcpy((char*)value, g_plugin->m_szPresetDir);
276     }
277     if (strcmp((char*)value, "1") == 0)
278     {
279       strcpy((char*)id, "lastlockedstatus");
280       strcpy((char*)value, (g_plugin->m_bHoldPreset ? "true" : "false"));
281     }
282     if (strcmp((char*)value, "2") == 0)
283     {
284       strcpy((char*)id, "lastpresetidx");
285       sprintf ((char*)value, "%i", g_plugin->m_nCurrentPreset);
286     }
287     if (strcmp((char*)value, "3") == 0)
288     {
289       strcpy((char*)id, "###End");
290     }
291     return ADDON_STATUS_OK;
292   }
293   // It is now time to set the settings got from xmbc
294   if (strcmp(id, "Use Preset") == 0)
295     OnAction(34, &value);
296   else if (strcmp(id, "Automatic Blend Time") == 0)
297     g_plugin->m_fBlendTimeAuto = (float)(*(int*)value + 1);
298   else if (strcmp(id, "Time Between Presets") == 0)
299     g_plugin->m_fTimeBetweenPresets = (float)(*(int*)value*5 + 5);
300   else if (strcmp(id, "Additional Random Time") == 0)
301     g_plugin->m_fTimeBetweenPresetsRand = (float)(*(int*)value*5 + 5);
302   else if (strcmp(id, "Enable Hard Cuts") == 0)
303     g_plugin->m_bHardCutsDisabled = *(bool*)value == false;
304   else if (strcmp(id, "Loudness Threshold For Hard Cuts") == 0)
305     g_plugin->m_fHardCutLoudnessThresh = (float)(*(int*)value)/5.0f + 1.25f;
306   else if (strcmp(id, "Average Time Between Hard Cuts") == 0)
307     g_plugin->m_fHardCutHalflife = (float)*(int*)value*5 + 5;
308   else if (strcmp(id, "Maximum Refresh Rate") == 0)
309     g_plugin->m_max_fps_fs = *(int*)value*5 + 20;
310   else if (strcmp(id, "Enable Stereo 3d") == 0)
311     g_plugin->m_bAlways3D = *(bool*)value;
312   else if (strcmp(id, "lastlockedstatus") == 0)
313     lastLockedStatus = *(bool*)value;
314   else if (strcmp(id, "lastpresetidx") == 0)
315     lastPresetIndx = *(int*)value;
316   else if (strcmp(id, "lastpresetfolder") == 0)
317     strcpy(lastPresetDir, (char*)value);
318   else if (strcmp(id, "Preset Shuffle Mode") == 0)
319     g_plugin->m_bSequentialPresetOrder = !*(bool*)value;
320   else if (strcmp(id, "Preset Pack") == 0)
321   {
322     if (*(int*)value == 0)
323       {
324       g_UserPackFolder = false;;
325       SetPresetDir ("WA51-presets(265).zip");
326       }
327     else if (*(int*)value == 1)
328     {
329       g_UserPackFolder = false;
330       SetPresetDir ("Winamp-presets(436).zip");
331     }
332     else if (*(int*)value == 2)
333       g_UserPackFolder = true;
334   }
335   else if (strcmp(id, "User Preset Folder") ==0 )
336   {
337     if (g_UserPackFolder) SetPresetDir ((char*)value);
338   }
339   else
340     return ADDON_STATUS_UNKNOWN;
341
342   return ADDON_STATUS_OK;
343 }
344
345 //-- GetSubModules ------------------------------------------------------------
346 // Return any sub modules supported by this vis
347 //-----------------------------------------------------------------------------
348 extern "C" unsigned int GetSubModules(char ***names)
349 {
350   return 0; // this vis supports 0 sub modules
351 }