libvisual.cpp

来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 418 行

CPP
418
字号
/*************************************************************************** *   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"intmain( 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 inttryConnect( 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 SDLnamespace 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

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?