Revert previous commit, was incorrect
[amarok.git] / src / vis / libvisual / libvisual.cpp
blob7b23a3cc32aa27b9783c0581cc2b6b55489ba38b
1 /***************************************************************************
2 * Copyright (C) 2004, 2005 Max Howell <max.howell@methylblue.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 ***************************************************************************/
11 extern "C"
13 #include <sys/types.h> //this must be _before_ sys/socket on freebsd
14 #include <sys/socket.h>
15 #include <sys/un.h>
16 #include <unistd.h>
19 #include <cstdlib>
20 #include <cstring>
21 #include <iostream>
22 #include "libvisual.h"
25 int
26 main( int argc, char** argv )
28 if( argc <= 1 || std::strcmp( argv[1], "--list" ) == 0 )
30 visual_init( &argc, &argv );
32 #if 0
33 VisList *list = visual_actor_get_list();
35 for( VisListEntry *entry = list->head->next; entry != list->tail; entry = entry->next )
37 VisPluginInfo *info = static_cast<VisActor*>(entry->data)->plugin->ref->info;
39 std::cout << info->name << '|' << info->about << std::endl;
41 #endif
43 const char *plugin = 0;
45 while( (plugin = visual_actor_get_next_by_name( plugin )) )
46 std::cout << plugin << '\n';
48 std::exit( 0 );
50 else if( argc == 3 )
51 Vis::plugin = argv[2];
54 //connect to socket
55 const int sockfd = tryConnect( argv[1] );
57 //register fd/pid combo with Amarok
59 pid_t pid = ::getpid();
60 char buf[32] = "REG";
61 *(pid_t*)&buf[4] = pid;
63 ::send( sockfd, buf, 4 + sizeof(pid_t), 0 );
66 //init
67 SDL::init();
68 Vis::init( argc, argv );
71 //main loop
72 // 1. we sleep for a bit, listening for messages from Amarok
73 // 2. render a frame
75 timeval tv;
76 fd_set fds;
77 int nbytes = 0;
78 uint render_time = 0;
80 while( nbytes != -1 && SDL::event_handler() )
82 //set the time to wait
83 tv.tv_sec = 0;
84 tv.tv_usec = render_time > 16 ? 0 : (16 - render_time) * 1000; //60Hz
86 //get select to watch the right file descriptor
87 FD_ZERO( &fds );
88 FD_SET( sockfd, &fds );
90 ::select( sockfd+1, &fds, 0, 0, &tv );
92 if( FD_ISSET( sockfd, &fds) ) {
93 //Amarok sent us some data
95 char command[16];
96 ::recv( sockfd, command, 16, 0 );
98 if( std::strcmp( command, "fullscreen" ) == 0 )
99 SDL::toggleFullScreen();
102 //request pcm data
103 ::send( sockfd, "PCM", 4, 0 );
104 nbytes = ::recv( sockfd, Vis::pcm_data, 1024 * sizeof( int16_t ), 0 );
106 render_time = LibVisual::render();
109 ::close( sockfd );
111 return 0;
114 static int
115 tryConnect( const char *path )
117 const int fd = ::socket( AF_UNIX, SOCK_STREAM, 0 );
119 if( fd != -1 )
121 struct sockaddr_un local;
123 std::strcpy( &local.sun_path[ 0 ], path );
124 local.sun_family = AF_UNIX;
126 std::cout << "[Amk] Connecting to: " << path << '\n';
128 if( connect( fd, (struct sockaddr*)&local, sizeof(local) ) == -1 )
130 ::close( fd );
132 std::cerr << "[Amk] Could not connect\n";
133 std::exit( -1 );
137 return fd;
141 namespace SDL
143 static inline void
144 init()
146 if( SDL_Init( SDL_INIT_VIDEO ) )
148 std::cerr << "Could not initialize SDL: " << SDL_GetError() << std::endl;
149 std::exit( -2 );
152 std::atexit( SDL::quit );
155 static void
156 quit()
158 //FIXME crashes!
159 //visual_bin_destroy( Vis::bin );
160 //visual_quit();
162 SDL_FreeSurface( screen );
163 SDL_Quit();
166 static inline void
167 set_pal()
169 if (Vis::pal)
170 for( int i = 0; i < 256; i ++ )
172 SDL::pal[i].r = Vis::pal->colors[i].r;
173 SDL::pal[i].g = Vis::pal->colors[i].g;
174 SDL::pal[i].b = Vis::pal->colors[i].b;
177 SDL_SetColors( screen, SDL::pal, 0, 256 );
180 static void
181 create( int width, int height )
183 SDL_FreeSurface( screen );
185 if( Vis::pluginIsGL )
187 const SDL_VideoInfo *videoinfo = SDL_GetVideoInfo();
189 if( videoinfo == NULL )
191 std::cerr << "CRITICAL: Could not get video info\n";
192 std::exit( -2 );
196 videoflags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE | SDL_RESIZABLE;
197 videoflags |= videoinfo->hw_available ? SDL_HWSURFACE : SDL_SWSURFACE;
199 if( videoinfo->blit_hw ) videoflags |= SDL_HWACCEL;
201 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
203 screen = SDL_SetVideoMode( width, height, 16, videoflags );
205 else screen = SDL_SetVideoMode( width, height, Vis::video->bpp * 8, SDL_RESIZABLE );
207 visual_video_set_buffer( Vis::video, screen->pixels );
208 visual_video_set_pitch( Vis::video, screen->pitch );
211 static bool
212 event_handler()
214 SDL_Event event;
215 VisEventQueue *vevent;
217 while( SDL_PollEvent( &event ) )
219 vevent = visual_plugin_get_eventqueue( visual_actor_get_plugin( visual_bin_get_actor( Vis::bin ) ) );
221 switch( event.type )
223 case SDL_KEYUP:
224 visual_event_queue_add_keyboard( vevent, (VisKey)event.key.keysym.sym, event.key.keysym.mod, VISUAL_KEY_UP );
225 break;
227 case SDL_KEYDOWN:
228 visual_event_queue_add_keyboard (vevent, (VisKey)event.key.keysym.sym, event.key.keysym.mod, VISUAL_KEY_DOWN);
230 switch( event.key.keysym.sym )
232 //PLUGIN CONTROLS
233 case SDLK_F11:
234 case SDLK_TAB:
235 SDL::toggleFullScreen();
236 break;
238 case SDLK_ESCAPE:
239 if( SDL::isFullScreen() )
240 SDL::toggleFullScreen();
241 break;
243 case SDLK_LEFT:
244 Vis::prevActor();
245 goto morph;
247 case SDLK_RIGHT:
248 Vis::nextActor();
250 morph:
251 SDL::lock();
252 visual_bin_set_morph_by_name( Vis::bin, (char*)"alphablend" );
253 visual_bin_switch_actor_by_name( Vis::bin, (char*)Vis::plugin );
254 SDL::unlock();
256 SDL_WM_SetCaption( Vis::plugin, 0 );
258 break;
260 default:
263 break;
265 case SDL_VIDEORESIZE:
266 Vis::resize( event.resize.w, event.resize.h );
267 break;
269 case SDL_MOUSEMOTION:
270 visual_event_queue_add_mousemotion (vevent, event.motion.x, event.motion.y);
271 break;
273 case SDL_MOUSEBUTTONDOWN:
274 if (event.button.button == SDL_BUTTON_RIGHT)
276 SDL::toggleFullScreen();
277 break;
279 visual_event_queue_add_mousebutton (vevent, event.button.button, VISUAL_MOUSE_DOWN, 0, 0);
280 break;
282 case SDL_MOUSEBUTTONUP:
283 visual_event_queue_add_mousebutton (vevent, event.button.button, VISUAL_MOUSE_UP, 0, 0);
284 break;
286 case SDL_QUIT:
287 return false;
289 default:
294 return true;
296 } //namespace SDL
299 namespace LibVisual
301 static int
302 upload_callback( VisInput*, VisAudio *audio, void* )
304 VisBuffer buf;
306 visual_buffer_init( &buf, pcm_data, 1024, 0 );
307 visual_audio_samplepool_input( audio->samplepool, &buf, VISUAL_AUDIO_SAMPLE_RATE_44100,
308 VISUAL_AUDIO_SAMPLE_FORMAT_S16, VISUAL_AUDIO_SAMPLE_CHANNEL_STEREO );
310 return 0;
313 static void
314 resize( int width, int height )
316 visual_video_set_dimension( video, width, height );
318 SDL::create( width, height );
320 visual_bin_sync( bin, false );
323 static void
324 init( int &argc, char **&argv )
326 VisVideoDepth depth;
328 visual_init( &argc, &argv );
330 bin = visual_bin_new ();
331 depth = visual_video_depth_enum_from_value( 24 );
333 if( !plugin ) plugin = visual_actor_get_next_by_name( 0 );
334 if( !plugin ) exit( "Actor plugin not found!" );
336 visual_bin_set_supported_depth( bin, VISUAL_VIDEO_DEPTH_ALL );
338 if( NULL == (video = visual_video_new()) ) exit( "Cannot create a video surface" );
339 if( visual_video_set_depth( video, depth ) < 0 ) exit( "Cannot set video depth" );
341 visual_video_set_dimension( video, 320, 200 );
343 if( visual_bin_set_video( bin, video ) ) exit( "Cannot set video" );
345 visual_bin_connect_by_names( bin, (char*)plugin, 0 );
347 if( visual_bin_get_depth( bin ) == VISUAL_VIDEO_DEPTH_GL )
349 visual_video_set_depth( video, VISUAL_VIDEO_DEPTH_GL );
350 pluginIsGL = true;
353 SDL::create( 320, 200 );
355 SDL_WM_SetCaption( plugin, 0 );
357 /* Called so the flag is set to false, seen we create the initial environment here */
358 visual_bin_depth_changed( bin );
360 VisInput *input = visual_bin_get_input( bin );
361 if( visual_input_set_callback( input, upload_callback, NULL ) < 0 ) exit( "Cannot set input plugin callback" );
363 visual_bin_switch_set_style( bin, VISUAL_SWITCH_STYLE_MORPH );
364 visual_bin_switch_set_automatic( bin, true );
365 visual_bin_switch_set_steps( bin, 100 );
367 visual_bin_realize( bin );
368 visual_bin_sync( bin, false );
370 std::cout << "[Amk] Libvisual version " << visual_get_version() << '\n';
371 std::cout << "[Amk] bpp: " << video->bpp << std::endl;
372 std::cout << "[Amk] GL: " << (pluginIsGL ? "true\n" : "false\n");
375 static uint
376 render()
378 /* On depth change */
379 if( visual_bin_depth_changed( bin ) )
381 SDL::lock();
383 pluginIsGL = (visual_bin_get_depth( bin ) == VISUAL_VIDEO_DEPTH_GL);
385 SDL::create( SDL::screen->w, SDL::screen->h );
386 visual_bin_sync( bin, true );
388 SDL::unlock();
391 long ticks = -SDL_GetTicks();
393 if( pluginIsGL )
395 visual_bin_run( bin );
397 SDL_GL_SwapBuffers();
399 } else {
401 SDL::lock();
403 visual_video_set_buffer( video, SDL::screen->pixels );
404 visual_bin_run( bin );
406 SDL::unlock();
408 Vis::pal = visual_bin_get_palette( bin );
409 SDL::set_pal();
411 SDL_Flip( SDL::screen );
414 ticks += SDL_GetTicks();
415 return ticks;
417 } //namespace LibVisual