"Fossies" - the Fresh Open Source Software Archive

Member "audacious-plugins-3.10.1/src/glspectrum/gl-spectrum.cc" (26 Dec 2018, 11225 Bytes) of package /linux/misc/audacious-plugins-3.10.1.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "gl-spectrum.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.10_vs_3.10.1.

    1 /*
    2  * OpenGL Spectrum Analyzer for Audacious
    3  * Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini
    4  *
    5  * Based on the XMMS plugin:
    6  * Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and
    7  *                     4Front Technologies
    8  *
    9  * This program is free software; you can redistribute it and/or modify it under
   10  * the terms of the GNU General Public License as published by the Free Software
   11  * Foundation; either version 2 of the License, or (at your option) any later
   12  * version.
   13  *
   14  * This program is distributed in the hope that it will be useful, but WITHOUT
   15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   16  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
   17  * details.
   18  *
   19  * You should have received a copy of the GNU General Public License along with
   20  * this program; if not, write to the Free Software Foundation, Inc.,
   21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   22  */
   23 
   24 #include <math.h>
   25 #include <string.h>
   26 
   27 #include <libaudcore/i18n.h>
   28 #include <libaudcore/plugin.h>
   29 
   30 #include <gdk/gdk.h>
   31 #include <gtk/gtk.h>
   32 
   33 #include <GL/gl.h>
   34 
   35 #ifdef GDK_WINDOWING_X11
   36 #include <GL/glx.h>
   37 #include <gdk/gdkx.h>
   38 #endif
   39 
   40 #ifdef GDK_WINDOWING_WIN32
   41 #include <gdk/gdkwin32.h>
   42 #endif
   43 
   44 #define NUM_BANDS 32
   45 #define DB_RANGE 40
   46 
   47 #define BAR_SPACING (3.2f / NUM_BANDS)
   48 #define BAR_WIDTH (0.8f * BAR_SPACING)
   49 
   50 static const char gl_about[] =
   51  N_("OpenGL Spectrum Analyzer for Audacious\n"
   52     "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n\n"
   53     "Based on the XMMS plugin:\n"
   54     "Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, "
   55     "and 4Front Technologies\n\n"
   56     "License: GPLv2+");
   57 
   58 class GLSpectrum : public VisPlugin
   59 {
   60 public:
   61     static constexpr PluginInfo info = {
   62         N_("OpenGL Spectrum Analyzer"),
   63         PACKAGE,
   64         gl_about,
   65         nullptr, // prefs
   66         PluginGLibOnly
   67     };
   68 
   69     constexpr GLSpectrum () : VisPlugin (info, Visualizer::Freq) {}
   70 
   71     bool init ();
   72 
   73     void * get_gtk_widget ();
   74 
   75     void clear ();
   76     void render_freq (const float * freq);
   77 };
   78 
   79 EXPORT GLSpectrum aud_plugin_instance;
   80 
   81 static float logscale[NUM_BANDS + 1];
   82 static float colors[NUM_BANDS][NUM_BANDS][3];
   83 
   84 #ifdef GDK_WINDOWING_X11
   85 static Display * s_display;
   86 static Window s_xwindow;
   87 static GLXContext s_context;
   88 #endif
   89 
   90 #ifdef GDK_WINDOWING_WIN32
   91 static HWND s_hwnd;
   92 static HDC s_hdc;
   93 static HGLRC s_glrc;
   94 #endif
   95 
   96 static GtkWidget * s_widget = nullptr;
   97 
   98 static int s_pos = 0;
   99 static float s_angle = 25, s_anglespeed = 0.05f;
  100 static float s_bars[NUM_BANDS][NUM_BANDS];
  101 
  102 bool GLSpectrum::init ()
  103 {
  104     for (int i = 0; i <= NUM_BANDS; i ++)
  105         logscale[i] = powf (256, (float) i / NUM_BANDS) - 0.5f;
  106 
  107     for (int y = 0; y < NUM_BANDS; y ++)
  108     {
  109         float yf = (float) y / (NUM_BANDS - 1);
  110 
  111         for (int x = 0; x < NUM_BANDS; x ++)
  112         {
  113             float xf = (float) x / (NUM_BANDS - 1);
  114 
  115             colors[x][y][0] = (1 - xf) * (1 - yf);
  116             colors[x][y][1] = xf;
  117             colors[x][y][2] = yf;
  118         }
  119     }
  120 
  121     return true;
  122 }
  123 
  124 /* stolen from the skins plugin */
  125 /* convert linear frequency graph to logarithmic one */
  126 static void make_log_graph (const float * freq, float * graph)
  127 {
  128     for (int i = 0; i < NUM_BANDS; i ++)
  129     {
  130         /* sum up values in freq array between logscale[i] and logscale[i + 1],
  131            including fractional parts */
  132         int a = ceilf (logscale[i]);
  133         int b = floorf (logscale[i + 1]);
  134         float sum = 0;
  135 
  136         if (b < a)
  137             sum += freq[b] * (logscale[i + 1] - logscale[i]);
  138         else
  139         {
  140             if (a > 0)
  141                 sum += freq[a - 1] * (a - logscale[i]);
  142             for (; a < b; a ++)
  143                 sum += freq[a];
  144             if (b < 256)
  145                 sum += freq[b] * (logscale[i + 1] - b);
  146         }
  147 
  148         /* fudge factor to make the graph have the same overall height as a
  149            12-band one no matter how many bands there are */
  150         sum *= (float) NUM_BANDS / 12;
  151 
  152         /* convert to dB */
  153         float val = 20 * log10f (sum);
  154 
  155         /* scale (-DB_RANGE, 0.0) to (0.0, 1.0) */
  156         val = 1 + val / DB_RANGE;
  157 
  158         graph[i] = aud::clamp (val, 0.0f, 1.0f);
  159     }
  160 }
  161 
  162 void GLSpectrum::render_freq (const float * freq)
  163 {
  164     make_log_graph (freq, s_bars[s_pos]);
  165     s_pos = (s_pos + 1) % NUM_BANDS;
  166 
  167     s_angle += s_anglespeed;
  168     if (s_angle > 45 || s_angle < -45)
  169         s_anglespeed = -s_anglespeed;
  170 
  171     if (s_widget)
  172         gtk_widget_queue_draw (s_widget);
  173 }
  174 
  175 void GLSpectrum::clear ()
  176 {
  177     memset (s_bars, 0, sizeof s_bars);
  178 
  179     if (s_widget)
  180         gtk_widget_queue_draw (s_widget);
  181 }
  182 
  183 static void draw_rectangle (float x1, float y1, float z1, float x2, float y2,
  184  float z2, float r, float g, float b)
  185 {
  186     glColor3f (r, g, b);
  187 
  188     glBegin (GL_POLYGON);
  189     glVertex3f (x1, y2, z1);
  190     glVertex3f (x2, y2, z1);
  191     glVertex3f (x2, y2, z2);
  192     glVertex3f (x1, y2, z2);
  193     glEnd ();
  194 
  195     glColor3f (0.65f * r, 0.65f * g, 0.65f * b);
  196 
  197     glBegin (GL_POLYGON);
  198     glVertex3f (x1, y1, z1);
  199     glVertex3f (x1, y2, z1);
  200     glVertex3f (x1, y2, z2);
  201     glVertex3f (x1, y1, z2);
  202     glEnd ();
  203 
  204     glBegin (GL_POLYGON);
  205     glVertex3f (x2, y2, z1);
  206     glVertex3f (x2, y1, z1);
  207     glVertex3f (x2, y1, z2);
  208     glVertex3f (x2, y2, z2);
  209     glEnd ();
  210 
  211     glColor3f (0.8f * r, 0.8f * g, 0.8f * b);
  212 
  213     glBegin (GL_POLYGON);
  214     glVertex3f (x1, y1, z1);
  215     glVertex3f (x2, y1, z1);
  216     glVertex3f (x2, y2, z1);
  217     glVertex3f (x1, y2, z1);
  218     glEnd ();
  219 }
  220 
  221 static void draw_bar (float x, float z, float h, float r, float g, float b)
  222 {
  223     draw_rectangle (x, 0, z, x + BAR_WIDTH, h, z + BAR_WIDTH,
  224      r * (0.2f + 0.8f * h), g * (0.2f + 0.8f * h), b * (0.2f + 0.8f * h));
  225 }
  226 
  227 static void draw_bars ()
  228 {
  229     glPushMatrix ();
  230     glTranslatef (0.0f, -0.5f, -5.0f);
  231     glRotatef (38.0f, 1.0f, 0.0f, 0.0f);
  232     glRotatef (s_angle + 180.0f, 0.0f, 1.0f, 0.0f);
  233 
  234     for (int i = 0; i < NUM_BANDS; i ++)
  235     {
  236         float z = -1.6f + (NUM_BANDS - i) * BAR_SPACING;
  237 
  238         for (int j = 0; j < NUM_BANDS; j ++)
  239         {
  240             draw_bar (1.6f - BAR_SPACING * j, z,
  241              s_bars[(s_pos + i) % NUM_BANDS][j] * 1.6,
  242              colors[i][j][0], colors[i][j][1], colors[i][j][2]);
  243         }
  244     }
  245 
  246     glPopMatrix ();
  247 }
  248 
  249 static gboolean draw_cb (GtkWidget * widget)
  250 {
  251 #ifdef GDK_WINDOWING_X11
  252     if (! s_context)
  253         return false;
  254 #endif
  255 
  256 #ifdef GDK_WINDOWING_WIN32
  257     if (! s_glrc)
  258         return false;
  259 #endif
  260 
  261     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  262 
  263     draw_bars ();
  264 
  265 #ifdef GDK_WINDOWING_X11
  266     glXSwapBuffers (s_display, s_xwindow);
  267 #endif
  268 
  269 #ifdef GDK_WINDOWING_WIN32
  270     SwapBuffers (s_hdc);
  271 #endif
  272 
  273     return true;
  274 }
  275 
  276 static void aspect_viewport(GLint width, GLint height)
  277 {
  278     glViewport (0, 0, width, height);
  279     glMatrixMode (GL_PROJECTION);
  280     glLoadIdentity ();
  281     glFrustum (-1.1f, 1, -1.5f, 1, 2, 10);
  282     glMatrixMode (GL_MODELVIEW);
  283     glLoadIdentity ();
  284 }
  285 
  286 static void widget_realized ()
  287 {
  288     GdkWindow * window = gtk_widget_get_window (s_widget);
  289 
  290 #ifdef GDK_WINDOWING_X11
  291     GdkScreen * screen = gdk_window_get_screen (window);
  292     int nscreen = GDK_SCREEN_XNUMBER (screen);
  293 
  294     s_display = GDK_SCREEN_XDISPLAY (screen);
  295     s_xwindow = GDK_WINDOW_XID (window);
  296 
  297     /* Create s_context */
  298     int attribs[] = {
  299      GLX_RGBA,
  300      GLX_RED_SIZE, 1,
  301      GLX_GREEN_SIZE, 1,
  302      GLX_BLUE_SIZE, 1,
  303      GLX_ALPHA_SIZE, 0,
  304      GLX_DOUBLEBUFFER,
  305      GLX_DEPTH_SIZE, 1,
  306      None
  307     };
  308 
  309     XVisualInfo * xvinfo = glXChooseVisual (s_display, nscreen, attribs);
  310     g_return_if_fail (xvinfo);
  311 
  312     /* Fix up visual/colormap */
  313     GdkVisual * visual = gdk_x11_screen_lookup_visual (screen, xvinfo->visualid);
  314     g_return_if_fail (visual);
  315 
  316     gtk_widget_set_visual (s_widget, visual);
  317 
  318     s_context = glXCreateContext (s_display, xvinfo, 0, true);
  319     g_return_if_fail (s_context);
  320 
  321     XFree (xvinfo);
  322 
  323     glXMakeCurrent (s_display, s_xwindow, s_context);
  324 #endif
  325 
  326 #ifdef GDK_WINDOWING_WIN32
  327     s_hwnd = (HWND) GDK_WINDOW_HWND (window);
  328     s_hdc = GetDC (s_hwnd);
  329 
  330     PIXELFORMATDESCRIPTOR desc = {
  331      sizeof (PIXELFORMATDESCRIPTOR),
  332      1,                                 // version number (?)
  333      PFD_DRAW_TO_WINDOW |               // format must support window
  334      PFD_SUPPORT_OPENGL |               // format must support OpenGL
  335      PFD_DOUBLEBUFFER,                  // must support double buffering
  336      PFD_TYPE_RGBA,                     // request an RGBA format
  337      24,                                // select a 8:8:8 bit color depth
  338      0, 0, 0, 0, 0, 0,                  // color bits ignored (?)
  339      0,                                 // no alpha buffer
  340      0,                                 // shift bit ignored (?)
  341      0,                                 // no accumulation buffer
  342      0, 0, 0, 0,                        // accumulation bits ignored (?)
  343      16,                                // 16-bit z-buffer (depth buffer)
  344      0,                                 // no stencil buffer
  345      0,                                 // no auxiliary buffer (?)
  346      PFD_MAIN_PLANE,                    // main drawing layer
  347      0,                                 // reserved (?)
  348      0, 0, 0                            // layer masks ignored (?)
  349     };
  350 
  351     int format = ChoosePixelFormat (s_hdc, & desc);
  352     g_return_if_fail (format != 0);
  353 
  354     SetPixelFormat (s_hdc, format, & desc);
  355 
  356     s_glrc = wglCreateContext (s_hdc);
  357     g_return_if_fail (s_glrc);
  358 
  359     wglMakeCurrent (s_hdc, s_glrc);
  360 #endif
  361 
  362     /* Initialize OpenGL */
  363     GtkAllocation alloc;
  364     gtk_widget_get_allocation (s_widget, & alloc);
  365 
  366     aspect_viewport (alloc.width, alloc.height);
  367 
  368     glEnable (GL_DEPTH_TEST);
  369     glDepthFunc (GL_LESS);
  370     glDepthMask (GL_TRUE);
  371     glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
  372     glClearColor (0, 0, 0, 1);
  373 }
  374 
  375 static void widget_destroyed ()
  376 {
  377     s_widget = nullptr;
  378 
  379 #ifdef GDK_WINDOWING_X11
  380     if (s_context)
  381     {
  382         glXMakeCurrent (s_display, None, nullptr);
  383         glXDestroyContext (s_display, s_context);
  384         s_context = nullptr;
  385     }
  386 
  387     s_display = nullptr;
  388 #endif
  389 
  390 #ifdef GDK_WINDOWING_WIN32
  391     if (s_glrc)
  392     {
  393         wglMakeCurrent (s_hdc, nullptr);
  394         wglDeleteContext (s_glrc);
  395         s_glrc = nullptr;
  396     }
  397 
  398     if (s_hdc)
  399     {
  400         ReleaseDC (s_hwnd, s_hdc);
  401         s_hdc = nullptr;
  402     }
  403 
  404     s_hwnd = nullptr;
  405 #endif
  406 }
  407 
  408 static void widget_resize (GtkWidget * widget, GdkEvent * event, gpointer data)
  409 {
  410     aspect_viewport (event->configure.width, event->configure.height);
  411 }
  412 
  413 void * GLSpectrum::get_gtk_widget ()
  414 {
  415     if (s_widget)
  416         return s_widget;
  417 
  418     s_widget = gtk_drawing_area_new ();
  419 
  420     g_signal_connect (s_widget, "expose-event", (GCallback) draw_cb, nullptr);
  421     g_signal_connect (s_widget, "realize", (GCallback) widget_realized, nullptr);
  422     g_signal_connect (s_widget, "destroy", (GCallback) widget_destroyed, nullptr);
  423     g_signal_connect (s_widget, "configure-event", (GCallback) widget_resize, nullptr);
  424 
  425     /* Disable GTK double buffering */
  426     gtk_widget_set_double_buffered (s_widget, false);
  427 
  428     return s_widget;
  429 }