You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
418 lines
11 KiB
418 lines
11 KiB
/***************************************************************************
|
|
* Copyright (C) 2004, 2005 Max Howell <max.howell@methylblue.com> *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
extern "C"
|
|
{
|
|
#include <sys/types.h> //this must be _before_ sys/socket on freebsd
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <unistd.h>
|
|
}
|
|
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
#include "libvisual.h"
|
|
|
|
|
|
int
|
|
main( int argc, char** argv )
|
|
{
|
|
if( argc <= 1 || std::strcmp( argv[1], "--list" ) == 0 )
|
|
{
|
|
visual_init( &argc, &argv );
|
|
|
|
#if 0
|
|
VisList *list = visual_actor_get_list();
|
|
|
|
for( VisListEntry *entry = list->head->next; entry != list->tail; entry = entry->next )
|
|
{
|
|
VisPluginInfo *info = static_cast<VisActor*>(entry->data)->plugin->ref->info;
|
|
|
|
std::cout << info->name << '|' << info->about << std::endl;
|
|
}
|
|
#endif
|
|
|
|
const char *plugin = 0;
|
|
|
|
while( (plugin = visual_actor_get_next_by_name( plugin )) )
|
|
std::cout << plugin << '\n';
|
|
|
|
std::exit( 0 );
|
|
}
|
|
else if( argc == 3 )
|
|
Vis::plugin = argv[2];
|
|
|
|
|
|
//connect to socket
|
|
const int sockfd = tryConnect( argv[1] );
|
|
|
|
//register fd/pid combo with Amarok
|
|
{
|
|
pid_t pid = ::getpid();
|
|
char buf[32] = "REG";
|
|
*(pid_t*)&buf[4] = pid;
|
|
|
|
::send( sockfd, buf, 4 + sizeof(pid_t), 0 );
|
|
}
|
|
|
|
//init
|
|
SDL::init();
|
|
Vis::init( argc, argv );
|
|
|
|
|
|
//main loop
|
|
// 1. we sleep for a bit, listening for messages from Amarok
|
|
// 2. render a frame
|
|
|
|
timeval tv;
|
|
fd_set fds;
|
|
int nbytes = 0;
|
|
uint render_time = 0;
|
|
|
|
while( nbytes != -1 && SDL::event_handler() )
|
|
{
|
|
//set the time to wait
|
|
tv.tv_sec = 0;
|
|
tv.tv_usec = render_time > 16 ? 0 : (16 - render_time) * 1000; //60Hz
|
|
|
|
//get select to watch the right file descriptor
|
|
FD_ZERO( &fds );
|
|
FD_SET( sockfd, &fds );
|
|
|
|
::select( sockfd+1, &fds, 0, 0, &tv );
|
|
|
|
if( FD_ISSET( sockfd, &fds) ) {
|
|
//Amarok sent us some data
|
|
|
|
char command[16];
|
|
::recv( sockfd, command, 16, 0 );
|
|
|
|
if( std::strcmp( command, "fullscreen" ) == 0 )
|
|
SDL::toggleFullScreen();
|
|
}
|
|
|
|
//request pcm data
|
|
::send( sockfd, "PCM", 4, 0 );
|
|
nbytes = ::recv( sockfd, Vis::pcm_data, 1024 * sizeof( int16_t ), 0 );
|
|
|
|
render_time = LibVisual::render();
|
|
}
|
|
|
|
::close( sockfd );
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
tryConnect( const char *path )
|
|
{
|
|
const int fd = ::socket( AF_UNIX, SOCK_STREAM, 0 );
|
|
|
|
if( fd != -1 )
|
|
{
|
|
struct sockaddr_un local;
|
|
|
|
std::strcpy( &local.sun_path[ 0 ], path );
|
|
local.sun_family = AF_UNIX;
|
|
|
|
std::cout << "[Amk] Connecting to: " << path << '\n';
|
|
|
|
if( connect( fd, (struct sockaddr*)&local, sizeof(local) ) == -1 )
|
|
{
|
|
::close( fd );
|
|
|
|
std::cerr << "[Amk] Could not connect\n";
|
|
std::exit( -1 );
|
|
}
|
|
}
|
|
|
|
return fd;
|
|
}
|
|
|
|
|
|
namespace SDL
|
|
{
|
|
static inline void
|
|
init()
|
|
{
|
|
if( SDL_Init( SDL_INIT_VIDEO ) )
|
|
{
|
|
std::cerr << "Could not initialize SDL: " << SDL_GetError() << std::endl;
|
|
std::exit( -2 );
|
|
}
|
|
|
|
std::atexit( SDL::quit );
|
|
}
|
|
|
|
static void
|
|
quit()
|
|
{
|
|
//FIXME crashes!
|
|
//visual_bin_destroy( Vis::bin );
|
|
//visual_quit();
|
|
|
|
SDL_FreeSurface( screen );
|
|
SDL_Quit();
|
|
}
|
|
|
|
static inline void
|
|
set_pal()
|
|
{
|
|
if (Vis::pal)
|
|
for( int i = 0; i < 256; i ++ )
|
|
{
|
|
SDL::pal[i].r = Vis::pal->colors[i].r;
|
|
SDL::pal[i].g = Vis::pal->colors[i].g;
|
|
SDL::pal[i].b = Vis::pal->colors[i].b;
|
|
}
|
|
|
|
SDL_SetColors( screen, SDL::pal, 0, 256 );
|
|
}
|
|
|
|
static void
|
|
create( int width, int height )
|
|
{
|
|
SDL_FreeSurface( screen );
|
|
|
|
if( Vis::pluginIsGL )
|
|
{
|
|
const SDL_VideoInfo *videoinfo = SDL_GetVideoInfo();
|
|
|
|
if( videoinfo == NULL )
|
|
{
|
|
std::cerr << "CRITICAL: Could not get video info\n";
|
|
std::exit( -2 );
|
|
}
|
|
|
|
int
|
|
videoflags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE | SDL_RESIZABLE;
|
|
videoflags |= videoinfo->hw_available ? SDL_HWSURFACE : SDL_SWSURFACE;
|
|
|
|
if( videoinfo->blit_hw ) videoflags |= SDL_HWACCEL;
|
|
|
|
SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
|
|
|
|
screen = SDL_SetVideoMode( width, height, 16, videoflags );
|
|
}
|
|
else screen = SDL_SetVideoMode( width, height, Vis::video->bpp * 8, SDL_RESIZABLE );
|
|
|
|
visual_video_set_buffer( Vis::video, screen->pixels );
|
|
visual_video_set_pitch( Vis::video, screen->pitch );
|
|
}
|
|
|
|
static bool
|
|
event_handler()
|
|
{
|
|
SDL_Event event;
|
|
VisEventQueue *vevent;
|
|
|
|
while( SDL_PollEvent( &event ) )
|
|
{
|
|
vevent = visual_plugin_get_eventqueue( visual_actor_get_plugin( visual_bin_get_actor( Vis::bin ) ) );
|
|
|
|
switch( event.type )
|
|
{
|
|
case SDL_KEYUP:
|
|
visual_event_queue_add_keyboard( vevent, (VisKey)event.key.keysym.sym, event.key.keysym.mod, VISUAL_KEY_UP );
|
|
break;
|
|
|
|
case SDL_KEYDOWN:
|
|
visual_event_queue_add_keyboard (vevent, (VisKey)event.key.keysym.sym, event.key.keysym.mod, VISUAL_KEY_DOWN);
|
|
|
|
switch( event.key.keysym.sym )
|
|
{
|
|
//PLUGIN CONTROLS
|
|
case SDLK_F11:
|
|
case SDLK_TAB:
|
|
SDL::toggleFullScreen();
|
|
break;
|
|
|
|
case SDLK_ESCAPE:
|
|
if( SDL::isFullScreen() )
|
|
SDL::toggleFullScreen();
|
|
break;
|
|
|
|
case SDLK_LEFT:
|
|
Vis::prevActor();
|
|
goto morph;
|
|
|
|
case SDLK_RIGHT:
|
|
Vis::nextActor();
|
|
|
|
morph:
|
|
SDL::lock();
|
|
visual_bin_set_morph_by_name( Vis::bin, (char*)"alphablend" );
|
|
visual_bin_switch_actor_by_name( Vis::bin, (char*)Vis::plugin );
|
|
SDL::unlock();
|
|
|
|
SDL_WM_SetCaption( Vis::plugin, 0 );
|
|
|
|
break;
|
|
|
|
default:
|
|
;
|
|
}
|
|
break;
|
|
|
|
case SDL_VIDEORESIZE:
|
|
Vis::resize( event.resize.w, event.resize.h );
|
|
break;
|
|
|
|
case SDL_MOUSEMOTION:
|
|
visual_event_queue_add_mousemotion (vevent, event.motion.x, event.motion.y);
|
|
break;
|
|
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
if (event.button.button == SDL_BUTTON_RIGHT)
|
|
{
|
|
SDL::toggleFullScreen();
|
|
break;
|
|
}
|
|
visual_event_queue_add_mousebutton (vevent, event.button.button, VISUAL_MOUSE_DOWN, 0, 0);
|
|
break;
|
|
|
|
case SDL_MOUSEBUTTONUP:
|
|
visual_event_queue_add_mousebutton (vevent, event.button.button, VISUAL_MOUSE_UP, 0, 0);
|
|
break;
|
|
|
|
case SDL_QUIT:
|
|
return false;
|
|
|
|
default:
|
|
;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
} //namespace SDL
|
|
|
|
|
|
namespace LibVisual
|
|
{
|
|
static int
|
|
upload_callback( VisInput*, VisAudio *audio, void* )
|
|
{
|
|
VisBuffer buf;
|
|
|
|
visual_buffer_init( &buf, pcm_data, 1024, 0 );
|
|
visual_audio_samplepool_input( audio->samplepool, &buf, VISUAL_AUDIO_SAMPLE_RATE_44100,
|
|
VISUAL_AUDIO_SAMPLE_FORMAT_S16, VISUAL_AUDIO_SAMPLE_CHANNEL_STEREO );
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
resize( int width, int height )
|
|
{
|
|
visual_video_set_dimension( video, width, height );
|
|
|
|
SDL::create( width, height );
|
|
|
|
visual_bin_sync( bin, false );
|
|
}
|
|
|
|
static void
|
|
init( int &argc, char **&argv )
|
|
{
|
|
VisVideoDepth depth;
|
|
|
|
visual_init( &argc, &argv );
|
|
|
|
bin = visual_bin_new ();
|
|
depth = visual_video_depth_enum_from_value( 24 );
|
|
|
|
if( !plugin ) plugin = visual_actor_get_next_by_name( 0 );
|
|
if( !plugin ) exit( "Actor plugin not found!" );
|
|
|
|
visual_bin_set_supported_depth( bin, VISUAL_VIDEO_DEPTH_ALL );
|
|
|
|
if( NULL == (video = visual_video_new()) ) exit( "Cannot create a video surface" );
|
|
if( visual_video_set_depth( video, depth ) < 0 ) exit( "Cannot set video depth" );
|
|
|
|
visual_video_set_dimension( video, 320, 200 );
|
|
|
|
if( visual_bin_set_video( bin, video ) ) exit( "Cannot set video" );
|
|
|
|
visual_bin_connect_by_names( bin, (char*)plugin, 0 );
|
|
|
|
if( visual_bin_get_depth( bin ) == VISUAL_VIDEO_DEPTH_GL )
|
|
{
|
|
visual_video_set_depth( video, VISUAL_VIDEO_DEPTH_GL );
|
|
pluginIsGL = true;
|
|
}
|
|
|
|
SDL::create( 320, 200 );
|
|
|
|
SDL_WM_SetCaption( plugin, 0 );
|
|
|
|
/* Called so the flag is set to false, seen we create the initial environment here */
|
|
visual_bin_depth_changed( bin );
|
|
|
|
VisInput *input = visual_bin_get_input( bin );
|
|
if( visual_input_set_callback( input, upload_callback, NULL ) < 0 ) exit( "Cannot set input plugin callback" );
|
|
|
|
visual_bin_switch_set_style( bin, VISUAL_SWITCH_STYLE_MORPH );
|
|
visual_bin_switch_set_automatic( bin, true );
|
|
visual_bin_switch_set_steps( bin, 100 );
|
|
|
|
visual_bin_realize( bin );
|
|
visual_bin_sync( bin, false );
|
|
|
|
std::cout << "[Amk] Libvisual version " << visual_get_version() << '\n';
|
|
std::cout << "[Amk] bpp: " << video->bpp << std::endl;
|
|
std::cout << "[Amk] GL: " << (pluginIsGL ? "true\n" : "false\n");
|
|
}
|
|
|
|
static uint
|
|
render()
|
|
{
|
|
/* On depth change */
|
|
if( visual_bin_depth_changed( bin ) )
|
|
{
|
|
SDL::lock();
|
|
|
|
pluginIsGL = (visual_bin_get_depth( bin ) == VISUAL_VIDEO_DEPTH_GL);
|
|
|
|
SDL::create( SDL::screen->w, SDL::screen->h );
|
|
visual_bin_sync( bin, true );
|
|
|
|
SDL::unlock();
|
|
}
|
|
|
|
long ticks = -SDL_GetTicks();
|
|
|
|
if( pluginIsGL )
|
|
{
|
|
visual_bin_run( bin );
|
|
|
|
SDL_GL_SwapBuffers();
|
|
|
|
} else {
|
|
|
|
SDL::lock();
|
|
|
|
visual_video_set_buffer( video, SDL::screen->pixels );
|
|
visual_bin_run( bin );
|
|
|
|
SDL::unlock();
|
|
|
|
Vis::pal = visual_bin_get_palette( bin );
|
|
SDL::set_pal();
|
|
|
|
SDL_Flip( SDL::screen );
|
|
}
|
|
|
|
ticks += SDL_GetTicks();
|
|
return ticks;
|
|
}
|
|
} //namespace LibVisual
|