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: 20.789 ]

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

Algum humor e C++ Design Patterns (parte 1)

Compilando Templates C++

SDL e C - Uma dupla sensacional

Parâmetros interessantes do scanf e do printf em C

A mágica do polimorfismo e seus conceitos na ótica de C/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