1 /* XMMS - Cross-platform multimedia player
2 * Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * Wed May 24 10:49:37 CDT 2000
21 * Fixes to threading/context creation for the nVidia X4 drivers by
22 * Christian Zander <phoenix@minion.de>
26 * Ported to XBMC by d4rk
27 * Also added 'hSpeed' to animate transition between bar heights
29 * Ported to GLES 2.0 by Gimli
32 #define __STDC_LIMIT_MACROS
34 #include "addons/include/xbmc_vis_dll.h"
40 #include "VisGUIShader.h"
43 #define M_PI 3.141592654f
45 #define DEG2RAD(d) ( (d) * M_PI/180.0f )
47 //OpenGL wrapper - allows us to use same code of functions draw_bars and render
48 #define GL_PROJECTION MM_PROJECTION
49 #define GL_MODELVIEW MM_MODELVIEW
51 #define glPushMatrix() vis_shader->PushMatrix()
52 #define glPopMatrix() vis_shader->PopMatrix()
53 #define glTranslatef(x,y,z) vis_shader->Translatef(x,y,z)
54 #define glRotatef(a,x,y,z) vis_shader->Rotatef(DEG2RAD(a),x,y,z)
55 #define glPolygonMode(a,b) ;
56 #define glBegin(a) vis_shader->Enable()
57 #define glEnd() vis_shader->Disable()
58 #define glMatrixMode(a) vis_shader->MatrixMode(a)
59 #define glLoadIdentity() vis_shader->LoadIdentity()
60 #define glFrustum(a,b,c,d,e,f) vis_shader->Frustum(a,b,c,d,e,f)
62 GLenum g_mode = GL_TRIANGLES;
63 float g_fWaveform[2][512];
64 const char *frag = "precision mediump float; \n"
65 "varying lowp vec4 m_colour; \n"
68 " gl_FragColor = m_colour; \n"
71 const char *vert = "attribute vec4 m_attrpos;\n"
72 "attribute vec4 m_attrcol;\n"
73 "attribute vec4 m_attrcord0;\n"
74 "attribute vec4 m_attrcord1;\n"
75 "varying vec4 m_cord0;\n"
76 "varying vec4 m_cord1;\n"
77 "varying lowp vec4 m_colour;\n"
78 "uniform mat4 m_proj;\n"
79 "uniform mat4 m_model;\n"
82 " mat4 mvp = m_proj * m_model;\n"
83 " gl_Position = mvp * m_attrpos;\n"
84 " m_colour = m_attrcol;\n"
85 " m_cord0 = m_attrcord0;\n"
86 " m_cord1 = m_attrcord1;\n"
89 CVisGUIShader *vis_shader = NULL;
91 #elif defined(HAS_SDL_OPENGL)
93 GLenum g_mode = GL_FILL;
99 GLfloat x_angle = 20.0, x_speed = 0.0;
100 GLfloat y_angle = 45.0, y_speed = 0.5;
101 GLfloat z_angle = 0.0, z_speed = 0.0;
102 GLfloat heights[16][16], cHeights[16][16], scale;
103 GLfloat hSpeed = 0.05;
105 #if defined(HAS_SDL_OPENGL)
106 void draw_rectangle(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2)
110 glVertex3f(x1, y1, z1);
111 glVertex3f(x2, y1, z1);
112 glVertex3f(x2, y2, z2);
114 glVertex3f(x2, y2, z2);
115 glVertex3f(x1, y2, z2);
116 glVertex3f(x1, y1, z1);
120 glVertex3f(x1, y1, z1);
121 glVertex3f(x2, y1, z2);
122 glVertex3f(x2, y2, z2);
124 glVertex3f(x2, y2, z2);
125 glVertex3f(x1, y2, z1);
126 glVertex3f(x1, y1, z1);
130 void draw_bar(GLfloat x_offset, GLfloat z_offset, GLfloat height, GLfloat red, GLfloat green, GLfloat blue )
134 if (g_mode == GL_POINT)
135 glColor3f(0.2, 1.0, 0.2);
137 if (g_mode != GL_POINT)
139 glColor3f(red,green,blue);
140 draw_rectangle(x_offset, height, z_offset, x_offset + width, height, z_offset + 0.1);
142 draw_rectangle(x_offset, 0, z_offset, x_offset + width, 0, z_offset + 0.1);
144 if (g_mode != GL_POINT)
146 glColor3f(0.5 * red, 0.5 * green, 0.5 * blue);
147 draw_rectangle(x_offset, 0.0, z_offset + 0.1, x_offset + width, height, z_offset + 0.1);
149 draw_rectangle(x_offset, 0.0, z_offset, x_offset + width, height, z_offset );
151 if (g_mode != GL_POINT)
153 glColor3f(0.25 * red, 0.25 * green, 0.25 * blue);
154 draw_rectangle(x_offset, 0.0, z_offset , x_offset, height, z_offset + 0.1);
156 draw_rectangle(x_offset + width, 0.0, z_offset , x_offset + width, height, z_offset + 0.1);
159 #elif defined(HAS_GLES)
161 void draw_bar(GLfloat x_offset, GLfloat z_offset, GLfloat height, GLfloat red, GLfloat green, GLfloat blue )
163 // avoid zero sized bars, which results in overlapping triangles of same depth and display artefacts
164 height = std::max(height, 1e-3f);
166 red * 0.1f, green * 0.1f, blue * 0.1f,
167 red * 0.2f, green * 0.2f, blue * 0.2f,
168 red * 0.3f, green * 0.3f, blue * 0.3f,
169 red * 0.4f, green * 0.4f, blue * 0.4f,
170 red * 0.5f, green * 0.5f, blue * 0.5f,
171 red * 0.6f, green * 0.6f, blue * 0.6f,
172 red * 0.7f, green * 0.7f, blue * 0.7f,
173 red * 0.8f, green * 0.8f, blue *0.8f
176 x_offset + 0.0f, 0.0f, z_offset + 0.0f,
177 x_offset + 0.1f, 0.0f, z_offset + 0.0f,
178 x_offset + 0.1f, 0.0f, z_offset + 0.1f,
179 x_offset + 0.0f, 0.0f, z_offset + 0.1f,
180 x_offset + 0.0f, height, z_offset + 0.0f,
181 x_offset + 0.1f, height, z_offset + 0.0f,
182 x_offset + 0.1f, height, z_offset + 0.1f,
183 x_offset + 0.0f, height, z_offset + 0.1f
207 GLint posLoc = vis_shader->GetPosLoc();
208 GLint colLoc = vis_shader->GetColLoc();
210 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
211 glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, 0, ver);
213 glEnableVertexAttribArray(posLoc);
214 glEnableVertexAttribArray(colLoc);
216 glDrawElements(g_mode, 36, GL_UNSIGNED_BYTE, idx);
218 glDisableVertexAttribArray(posLoc);
219 glDisableVertexAttribArray(colLoc);
226 GLfloat x_offset, z_offset, r_base, b_base;
228 glClear(GL_DEPTH_BUFFER_BIT);
230 glTranslatef(0.0,-0.5,-5.0);
231 glRotatef(x_angle,1.0,0.0,0.0);
232 glRotatef(y_angle,0.0,1.0,0.0);
233 glRotatef(z_angle,0.0,0.0,1.0);
235 glPolygonMode(GL_FRONT_AND_BACK, g_mode);
236 glBegin(GL_TRIANGLES);
238 for(y = 0; y < 16; y++)
240 z_offset = -1.6 + ((15 - y) * 0.2);
242 b_base = y * (1.0 / 15);
243 r_base = 1.0 - b_base;
245 for(x = 0; x < 16; x++)
247 x_offset = -1.6 + ((float)x * 0.2);
248 if (::fabs(cHeights[y][x]-heights[y][x])>hSpeed)
250 if (cHeights[y][x]<heights[y][x])
251 cHeights[y][x] += hSpeed;
253 cHeights[y][x] -= hSpeed;
255 draw_bar(x_offset, z_offset,
256 cHeights[y][x], r_base - (float(x) * (r_base / 15.0)),
257 (float)x * (1.0 / 15), b_base);
261 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
265 //-- Create -------------------------------------------------------------------
266 // Called on load. Addon should fully initalize or return error status
267 //-----------------------------------------------------------------------------
268 ADDON_STATUS ADDON_Create(void* hdl, void* props)
271 return ADDON_STATUS_UNKNOWN;
273 scale = 1.0 / log(256.0);
275 #if defined(HAS_GLES)
276 vis_shader = new CVisGUIShader(vert, frag);
279 return ADDON_STATUS_UNKNOWN;
281 if(!vis_shader->CompileAndLink())
284 return ADDON_STATUS_UNKNOWN;
288 scale = 1.0 / log(256.0);
290 return ADDON_STATUS_NEED_SETTINGS;
293 //-- Render -------------------------------------------------------------------
294 // Called once per frame. Do all rendering here.
295 //-----------------------------------------------------------------------------
296 extern "C" void Render()
299 glMatrixMode(GL_PROJECTION);
302 glFrustum(-1, 1, -1, 1, 1.5, 10);
303 glMatrixMode(GL_MODELVIEW);
306 glEnable(GL_DEPTH_TEST);
307 glDepthFunc(GL_LESS);
308 glPolygonMode(GL_FRONT, GL_FILL);
309 //glPolygonMode(GL_BACK, GL_FILL);
324 glMatrixMode(GL_PROJECTION);
326 glDisable(GL_DEPTH_TEST);
330 extern "C" void Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, const char* szSongName)
334 for(x = 0; x < 16; x++)
336 for(y = 0; y < 16; y++)
338 cHeights[y][x] = 0.0;
350 extern "C" void AudioData(const float* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength)
356 int xscale[] = {0, 1, 2, 3, 5, 7, 10, 14, 20, 28, 40, 54, 74, 101, 137, 187, 255};
358 for(y = 15; y > 0; y--)
360 for(i = 0; i < 16; i++)
362 heights[y][i] = heights[y - 1][i];
366 for(i = 0; i < NUM_BANDS; i++)
368 for(c = xscale[i], y = 0; c < xscale[i + 1]; c++)
370 if (c<iAudioDataLength)
372 if((int)(pAudioData[c] * (INT16_MAX)) > y)
373 y = (int)(pAudioData[c] * (INT16_MAX));
380 val = (logf(y) * scale);
388 //-- GetInfo ------------------------------------------------------------------
389 // Tell XBMC our requirements
390 //-----------------------------------------------------------------------------
391 extern "C" void GetInfo(VIS_INFO* pInfo)
393 pInfo->bWantsFreq = false;
394 pInfo->iSyncDelay = 0;
398 //-- GetSubModules ------------------------------------------------------------
399 // Return any sub modules supported by this vis
400 //-----------------------------------------------------------------------------
401 extern "C" unsigned int GetSubModules(char ***names)
403 return 0; // this vis supports 0 sub modules
406 //-- OnAction -----------------------------------------------------------------
407 // Handle XBMC actions such as next preset, lock preset, album art changed etc
408 //-----------------------------------------------------------------------------
409 extern "C" bool OnAction(long flags, const void *param)
415 //-- GetPresets ---------------------------------------------------------------
416 // Return a list of presets to XBMC for display
417 //-----------------------------------------------------------------------------
418 extern "C" unsigned int GetPresets(char ***presets)
423 //-- GetPreset ----------------------------------------------------------------
424 // Return the index of the current playing preset
425 //-----------------------------------------------------------------------------
426 extern "C" unsigned GetPreset()
431 //-- IsLocked -----------------------------------------------------------------
432 // Returns true if this add-on use settings
433 //-----------------------------------------------------------------------------
434 extern "C" bool IsLocked()
439 //-- Stop ---------------------------------------------------------------------
440 // This dll must cease all runtime activities
441 // !!! Add-on master function !!!
442 //-----------------------------------------------------------------------------
443 extern "C" void ADDON_Stop()
447 //-- Destroy ------------------------------------------------------------------
448 // Do everything before unload of this add-on
449 // !!! Add-on master function !!!
450 //-----------------------------------------------------------------------------
451 extern "C" void ADDON_Destroy()
453 #if defined(HAS_GLES)
462 //-- HasSettings --------------------------------------------------------------
463 // Returns true if this add-on use settings
464 // !!! Add-on master function !!!
465 //-----------------------------------------------------------------------------
466 extern "C" bool ADDON_HasSettings()
471 //-- GetStatus ---------------------------------------------------------------
472 // Returns the current Status of this visualisation
473 // !!! Add-on master function !!!
474 //-----------------------------------------------------------------------------
475 extern "C" ADDON_STATUS ADDON_GetStatus()
477 return ADDON_STATUS_OK;
480 //-- GetSettings --------------------------------------------------------------
481 // Return the settings for XBMC to display
482 // !!! Add-on master function !!!
483 //-----------------------------------------------------------------------------
484 extern "C" unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet)
489 //-- FreeSettings --------------------------------------------------------------
490 // Free the settings struct passed from XBMC
491 // !!! Add-on master function !!!
492 //-----------------------------------------------------------------------------
494 extern "C" void ADDON_FreeSettings()
498 //-- SetSetting ---------------------------------------------------------------
499 // Set a specific Setting value (called from XBMC)
500 // !!! Add-on master function !!!
501 //-----------------------------------------------------------------------------
502 extern "C" ADDON_STATUS ADDON_SetSetting(const char *strSetting, const void* value)
504 if (!strSetting || !value)
505 return ADDON_STATUS_UNKNOWN;
507 if (strcmp(strSetting, "bar_height")==0)
509 switch (*(int*) value)
512 scale = 1.f / log(256.f);
516 scale = 2.f / log(256.f);
520 scale = 3.f / log(256.f);
524 scale = 0.33f / log(256.f);
529 scale = 0.5f / log(256.f);
532 return ADDON_STATUS_OK;
534 else if (strcmp(strSetting, "speed")==0)
536 switch (*(int*) value)
559 return ADDON_STATUS_OK;
561 else if (strcmp(strSetting, "mode")==0)
563 #if defined(HAS_SDL_OPENGL)
564 switch (*(int*) value)
580 switch (*(int*) value)
583 g_mode = GL_LINE_LOOP;
587 g_mode = GL_LINES; //no points on gles!
592 g_mode = GL_TRIANGLES;
598 return ADDON_STATUS_OK;
601 return ADDON_STATUS_UNKNOWN;
604 //-- Announce -----------------------------------------------------------------
605 // Receive announcements from XBMC
606 // !!! Add-on master function !!!
607 //-----------------------------------------------------------------------------
608 extern "C" void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data)