Desenvolvendo um plugin de visualização para o XMMS (Parte 1)

Aprenda a como desenvolver um plugin de visualização para o XMMS utilizando OpenGL. Este artigo nos apresenta um belo exemplo prático de como fazer.

[ Hits: 21.348 ]

Por: Denis Zanin em 23/07/2003


Começando a programar o plugin de visualização



Para que vocês comecem a entender bem o processo de criação, desenvolvi este exemplo bem simples.

Nele, há um barra (primeiramente em 2D, depois nos outros exemplos transformaremos ela em 3D) que varia conforme a música.
Exemplo (main.c):

#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <xmms/plugin.h>
#include <xmms/util.h>
#include <SDL/SDL.h>
#include <SDL/SDL_thread.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>

static void vol_init(void);
static void vol_cleanup(void);
static void vol_about(void);
static void vol_configure(void);
static void vol_playback_start(void);
static void vol_playback_stop(void);
static void vol_render_freq(gint16 freq_data[2][256]);

SDL_Surface *surface;

VisPlugin vol_vtable = {
  0,
  0,

  0,                     // Session ID
  "VoL's Plugin - Exemplo 01", //título do plugin de visualização

  0, // # PCM channels para render_pcm()
  1, // # freq channels requeridos para render_freq()

  vol_init,           // Função chamada quando o plugin é ativado
  vol_cleanup,        // Função chamada quando o plugin é fechado
  vol_about,          // Mostra a tela de informação
  vol_configure,      // Mostra a tela de configuração
  0,                     //
  vol_playback_start, // Função chamada quando a música começa
  vol_playback_stop,  // Função chamada quando a música para
  0,                     //
  vol_render_freq     //
};

VisPlugin *get_vplugin_info(void)
{
  return &vol_vtable;
}

SDL_Thread *worker_thread;
enum { GO, STOP } thread_control;
SDL_mutex *mutex;
gint16 shared_freq_data[2][256];
GLuint  base;

void worker_func(void)
{
  // criando a janela, e é onde definimos o tamanho da janela a ser criada
  if (!SDL_SetVideoMode(600, 600, 32, SDL_OPENGL)) {
    printf ("Failed to create window\n");
    vol_vtable.disable_plugin (&vol_vtable);
    return;
  }
  
  SDL_WM_SetCaption("VivaOLinux's Plugin - Exemplo 01", "VivaOLinux's Plugin - Exemplo 01"); //inserindo um nome para a janela

  glViewport(0,0,600,600);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45.0f, 600/600, 0.1f, 100.0f);
  glMatrixMode(GL_MODELVIEW);
  glClear(GL_COLOR_BUFFER_BIT);
  glShadeModel(GL_SMOOTH);
  glClearDepth(3.0f);
  glDepthFunc(GL_LEQUAL);
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

//aqui começa toda a criação da barra ...
  while (thread_control == GO) {
    float height;

    SDL_mutexP(mutex);
    height = shared_freq_data[0][0] / 1024.0;

    SDL_mutexV(mutex);

    glLoadIdentity();
    glTranslatef( 0.0f,-0.25f,-1.0f);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(0.5f, 1.0f, 1.0f); //cor da barra

    
    glBegin(GL_POLYGON); //começamos aqui a desenhar a barra
    glVertex3f(-0.05f, -0.008f, 0.0f);
    glVertex3f( 0.05f, -0.008f, 0.0f);
    glVertex3f( 0.05f,height, 0.0f);
    glVertex3f(-0.05f,height, 0.0f);
    glEnd();

    glFinish();
    
    SDL_GL_SwapBuffers();

    xmms_usleep(1000000 / 70);
  }

  printf("Worker thread: Saindo...\n");
}

static void vol_init(void)
{
  printf("VivaOLinux's plugin: Inicializando...\n");

  if (SDL_Init (SDL_INIT_VIDEO) < 0) {
    printf ("Failed to initialize SDL\n");
    vol_vtable.disable_plugin (&vol_vtable);
    return;
  }

  // Start worker thread
  thread_control = GO;
  mutex = SDL_CreateMutex();
  memset(shared_freq_data, 0, sizeof(gint16) * 2 * 256);
  worker_thread = SDL_CreateThread ((void *) worker_func, NULL);
}

static void vol_cleanup(void)
{
  printf("VivaOLinux's plugin: Limpar\n");
  thread_control = STOP;
  SDL_WaitThread(worker_thread, NULL);
  SDL_DestroyMutex(mutex);
  SDL_Quit();
  printf("VivaOLinux's plugin: Limpar\n");
}

void about_close_clicked (GtkWidget * w, GtkWidget ** window)
{
  gtk_widget_destroy (*window);
  *window = NULL;
}

void about_closed (GtkWidget * w, GdkEvent * e, GtkWidget ** window)
{
  about_close_clicked (w, window);
}

/* Nesta função desenvolveremos, em GTK,  a tela de ABOUT do plugin do xmms. Para que você entenda melhor, é só compilar este plugin exemplo e clicar em ABOUT antes de ativa-lo. */

static void vol_about(void)
{
  static GtkWidget *window_about = NULL;
  GtkWidget *vbox, *button, *close, *label;

  printf("VivaOLinux's plugin: Sobre...\n");

  if (window_about)
    return;

  window_about = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window_about), "Sobre VoL's Plugin");
  gtk_window_set_policy (GTK_WINDOW (window_about), FALSE, FALSE, FALSE);
  gtk_window_set_position (GTK_WINDOW (window_about), GTK_WIN_POS_MOUSE);
  vbox = gtk_vbox_new (FALSE, 4);
  gtk_container_add (GTK_CONTAINER (window_about), vbox);
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
  gtk_widget_show (vbox);

  label = gtk_label_new ("Viva O Linux - Plugin de Exemplo no-1 \n\n\
18-07-2003 Denis Z Silva - _vir0se - BrasNet - #vivaolinux\n Homepage: \
<http://www.vivaolinux.com.br>\n\
E-mail: <virose@bol.com.br>\n\n\
Este plugin foi desenvolvido para o artigo da VivaOLinux.\n\n\
O artigo de como se programar um plugin pode ser encontrado em: \n\
<http://www.vivaolinux.com.br>. \n\
Valeus !");
  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 8);
  gtk_widget_show (label);

  button = gtk_hbutton_box_new ();
  gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 8);
  gtk_widget_show (button);

  close = gtk_button_new_with_label ("OK");
  GTK_WIDGET_SET_FLAGS (close, GTK_CAN_DEFAULT);
  gtk_window_set_default (GTK_WINDOW (window_about), close);
  gtk_hbutton_box_set_layout_default (GTK_BUTTONBOX_END);
  gtk_box_pack_end (GTK_BOX (button), close, FALSE, FALSE, 8);
  gtk_widget_show (close);

  gtk_signal_connect (GTK_OBJECT (close), "clicked",
      GTK_SIGNAL_FUNC (about_close_clicked), &window_about);
  gtk_signal_connect (GTK_OBJECT (window_about), "delete-event",
      GTK_SIGNAL_FUNC (about_closed), &window_about);

  gtk_widget_show (window_about);
}

// Idem a função de cima, mas sendo esta para a configuração do plugin.
// Para maiores informações de como programar em GTK, vá em: <http://www.gtk.org/>

static void vol_configure(void)
{
  static GtkWidget *window_about = NULL;
  GtkWidget *vbox, *button, *close, *label;

  printf("VivaOLinux's plugin: Configuracao\n");

  if (window_about)
    return;

  window_about = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window_about), "Configurando VoL's Plugin...");
  gtk_window_set_policy (GTK_WINDOW (window_about), FALSE, FALSE, FALSE);
  gtk_window_set_position (GTK_WINDOW (window_about), GTK_WIN_POS_MOUSE);
  vbox = gtk_vbox_new (FALSE, 4);
  gtk_container_add (GTK_CONTAINER (window_about), vbox);
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
  gtk_widget_show (vbox);

  label = gtk_label_new ("Viva O Linux - Plugin de Exemplo no-1 \n\n\
Esta e a tela de configuração do VoL's plugin.\n\
No próximo exemplo eu irei explicar melhor como utilizar esta tela.\n\n\
Ate La. ;-)");
  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 8);
  gtk_widget_show (label);

  button = gtk_hbutton_box_new ();
  gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 8);
  gtk_widget_show (button);

  close = gtk_button_new_with_label ("OK");
  GTK_WIDGET_SET_FLAGS (close, GTK_CAN_DEFAULT);
  gtk_window_set_default (GTK_WINDOW (window_about), close);
  gtk_hbutton_box_set_layout_default (GTK_BUTTONBOX_END);
  gtk_box_pack_end (GTK_BOX (button), close, FALSE, FALSE, 8);
  gtk_widget_show (close);

  gtk_signal_connect (GTK_OBJECT (close), "clicked",
      GTK_SIGNAL_FUNC (about_close_clicked), &window_about);
  gtk_signal_connect (GTK_OBJECT (window_about), "delete-event",
      GTK_SIGNAL_FUNC (about_closed), &window_about);

  gtk_widget_show (window_about);
}

static void vol_playback_start(void)
{
  printf("VivaOLinux's plugin: Playback iniciando...\n");
}

static void vol_playback_stop(void)
{
  printf("VivaOLinux's plugin: Playback parando...\n");

  SDL_mutexP(mutex);
  memset(shared_freq_data, 0, sizeof(gint16) * 2 * 256);
  SDL_mutexV(mutex);
}

static void vol_render_freq(gint16 freq_data[2][256])
{
  int channel, bucket;

  SDL_mutexP(mutex);
  for (channel = 0; channel < 2; channel++) {
    for (bucket = 0; bucket < 256; bucket++) {
      shared_freq_data[channel][bucket] = freq_data[channel][bucket];
    }
  }
  SDL_mutexV(mutex);
}

Os comentários sobre o que significa cada linha você encontra no código-fonte.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Criando os arquivos para a instalação do plugin
   3. Começando a programar o plugin de visualização
   4. Compilando e instalando o plugin de visualização
Outros artigos deste autor
Nenhum artigo encontrado.
Leitura recomendada

Dynamic libraries com libtool

Como funcionam os alocadores de memória do STD C?

Alocação dinâmica

Bug afeta todas as distros

Tratamento de exceções na linguagem C

  
Comentários
[1] Comentário enviado por cesarcardoso em 23/07/2003 - 12:25h

O artigo é fantástico e espero que continue assim!

Aliás, merecia um artigo só pra essa arte de criar Makefile.am e configure.in...

[2] Comentário enviado por fabio em 23/07/2003 - 23:27h

Mereceu até um screenshot com o plugin rodando :)
http://www.vivaolinux.com.br/screenshots/verScreenshot.php?codigo=169

[3] Comentário enviado por removido em 14/11/2006 - 17:34h

Muito bom o artigo, parabéns!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts