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.