scope.c 10.1 KB
Newer Older
Sam Hocevar's avatar
 
Sam Hocevar committed
1 2 3 4
/*****************************************************************************
 * scope.c : Scope effect module
 *****************************************************************************
 * Copyright (C) 2002 VideoLAN
5
 * $Id: scope.c,v 1.11 2002/07/31 20:56:51 sam Exp $
Sam Hocevar's avatar
 
Sam Hocevar committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 *
 * Authors: Samuel Hocevar <sam@zoy.org>
 *
 * 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.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>                                      /* malloc(), free() */
#include <string.h>                                              /* strdup() */
#include <errno.h>

31 32 33
#include <vlc/vlc.h>
#include <vlc/aout.h>
#include <vlc/vout.h>
Sam Hocevar's avatar
 
Sam Hocevar committed
34

Sam Hocevar's avatar
 
Sam Hocevar committed
35 36
#define SCOPE_WIDTH 320
#define SCOPE_HEIGHT 240
Sam Hocevar's avatar
 
Sam Hocevar committed
37 38 39 40 41 42 43 44
#define SCOPE_ASPECT (VOUT_ASPECT_FACTOR*SCOPE_WIDTH/SCOPE_HEIGHT)

/*****************************************************************************
 * aout_sys_t: scope audio output method descriptor
 *****************************************************************************
 * This structure is part of the audio output thread descriptor.
 * It describes some scope specific variables.
 *****************************************************************************/
45
struct aout_sys_t
Sam Hocevar's avatar
 
Sam Hocevar committed
46
{
47
    aout_fifo_t *p_aout_fifo;
Sam Hocevar's avatar
 
Sam Hocevar committed
48

49
    aout_thread_t *p_aout;
50 51
    vout_thread_t *p_vout;
};
Sam Hocevar's avatar
 
Sam Hocevar committed
52

53
/*****************************************************************************
54
 * Local prototypes
55
 *****************************************************************************/
56 57
static int  Open         ( vlc_object_t * );             
static void Close        ( vlc_object_t * );                   
58

59 60 61
static int  SetFormat    ( aout_thread_t * );  
static int  GetBufInfo   ( aout_thread_t *, int );
static void Play         ( aout_thread_t *, byte_t *, int );
Sam Hocevar's avatar
 
Sam Hocevar committed
62 63

/*****************************************************************************
64
 * Module descriptor
Sam Hocevar's avatar
 
Sam Hocevar committed
65
 *****************************************************************************/
66 67 68 69 70 71
vlc_module_begin();
    set_description( _("scope effect") ); 
    set_capability( "audio output", 0 );
    set_callbacks( Open, Close );
    add_shortcut( "scope" );
vlc_module_end();
Sam Hocevar's avatar
 
Sam Hocevar committed
72 73

/*****************************************************************************
74
 * Open: open a scope effect plugin
Sam Hocevar's avatar
 
Sam Hocevar committed
75
 *****************************************************************************/
76
static int Open( vlc_object_t *p_this )
Sam Hocevar's avatar
 
Sam Hocevar committed
77
{
78
    aout_thread_t *p_aout = (aout_thread_t *)p_this;
Sam Hocevar's avatar
 
Sam Hocevar committed
79 80
    char *psz_method;

Sam Hocevar's avatar
 
Sam Hocevar committed
81 82 83 84
    /* Allocate structure */
    p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
    if( p_aout->p_sys == NULL )
    {
85
        msg_Err( p_aout, "out of memory" );
Sam Hocevar's avatar
 
Sam Hocevar committed
86
        return -1;
Sam Hocevar's avatar
 
Sam Hocevar committed
87 88
    }

89
    psz_method = config_GetPsz( p_aout, "aout" );
Sam Hocevar's avatar
 
Sam Hocevar committed
90 91 92 93 94 95 96 97 98 99 100 101 102
    if( psz_method )
    {
        if( !*psz_method )
        {
            free( psz_method );
            return -1;
        }
    }
    else
    {
        return -1;
    }

Sam Hocevar's avatar
 
Sam Hocevar committed
103
    /* Open video output */
Sam Hocevar's avatar
 
Sam Hocevar committed
104
    p_aout->p_sys->p_vout =
105
        vout_CreateThread( p_aout, SCOPE_WIDTH, SCOPE_HEIGHT,
106
                           VLC_FOURCC('I','4','2','0'), SCOPE_ASPECT );
Sam Hocevar's avatar
 
Sam Hocevar committed
107

Sam Hocevar's avatar
 
Sam Hocevar committed
108 109
    if( p_aout->p_sys->p_vout == NULL )
    {
110
        msg_Err( p_aout, "no suitable vout module" );
Sam Hocevar's avatar
 
Sam Hocevar committed
111 112 113 114
        free( p_aout->p_sys );
        return -1;
    }

Sam Hocevar's avatar
 
Sam Hocevar committed
115
    /* Open audio output  */
116 117 118 119 120 121 122 123 124
    p_aout->p_sys->p_aout = vlc_object_create( p_aout, VLC_OBJECT_AOUT );

    p_aout->p_sys->p_aout->i_format   = p_aout->i_format;
    p_aout->p_sys->p_aout->i_rate     = p_aout->i_rate;
    p_aout->p_sys->p_aout->i_channels = p_aout->i_channels;

    p_aout->p_sys->p_aout->p_module =
                  module_Need( p_aout->p_sys->p_aout, "audio output", "" );
    if( p_aout->p_sys->p_aout->p_module == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
125
    {
126
        msg_Err( p_aout, "no suitable aout module" );
127
        vlc_object_destroy( p_aout->p_sys->p_aout );
128
        vout_DestroyThread( p_aout->p_sys->p_vout );
Sam Hocevar's avatar
 
Sam Hocevar committed
129 130 131 132
        free( p_aout->p_sys );
        return -1;
    }

133 134 135 136 137 138
    vlc_object_attach( p_aout->p_sys->p_aout, p_aout );

    p_aout->pf_setformat = SetFormat;
    p_aout->pf_getbufinfo = GetBufInfo;
    p_aout->pf_play = Play;

Sam Hocevar's avatar
 
Sam Hocevar committed
139 140 141 142
    return( 0 );
}

/*****************************************************************************
143
 * SetFormat: set the output format
Sam Hocevar's avatar
 
Sam Hocevar committed
144
 *****************************************************************************/
145
static int SetFormat( aout_thread_t *p_aout )
Sam Hocevar's avatar
 
Sam Hocevar committed
146
{
Sam Hocevar's avatar
 
Sam Hocevar committed
147
    int i_ret;
Sam Hocevar's avatar
 
Sam Hocevar committed
148

Sam Hocevar's avatar
 
Sam Hocevar committed
149
    /* Force the output method */
150 151 152
    p_aout->p_sys->p_aout->i_format = p_aout->i_format;
    p_aout->p_sys->p_aout->i_channels = p_aout->i_channels;
    p_aout->p_sys->p_aout->i_rate = p_aout->i_rate;
Sam Hocevar's avatar
 
Sam Hocevar committed
153

Sam Hocevar's avatar
 
Sam Hocevar committed
154 155 156
    /*
     * Initialize audio device
     */
157
    i_ret = p_aout->p_sys->p_aout->pf_setformat( p_aout->p_sys->p_aout );
Sam Hocevar's avatar
 
Sam Hocevar committed
158 159 160 161 162 163

    if( i_ret )
    {
        return i_ret;
    }

164 165
    if( p_aout->p_sys->p_aout->i_format != p_aout->i_format
         || p_aout->p_sys->p_aout->i_channels != p_aout->i_channels )
Sam Hocevar's avatar
 
Sam Hocevar committed
166
    {
167
        msg_Err( p_aout, "plugin is not very cooperative" );
Sam Hocevar's avatar
 
Sam Hocevar committed
168 169 170
        return 0;
    }

171 172 173
    p_aout->i_channels = p_aout->p_sys->p_aout->i_channels;
    p_aout->i_format = p_aout->p_sys->p_aout->i_format;
    p_aout->i_rate = p_aout->p_sys->p_aout->i_rate;
Sam Hocevar's avatar
 
Sam Hocevar committed
174 175

    return 0;
Sam Hocevar's avatar
 
Sam Hocevar committed
176 177 178
}

/*****************************************************************************
179
 * GetBufInfo: buffer status query
Sam Hocevar's avatar
 
Sam Hocevar committed
180
 *****************************************************************************/
181
static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
Sam Hocevar's avatar
 
Sam Hocevar committed
182
{
183 184
    return p_aout->p_sys->p_aout->pf_getbufinfo( p_aout->p_sys->p_aout,
                                                 i_buffer_limit );
Sam Hocevar's avatar
 
Sam Hocevar committed
185 186 187
}

/*****************************************************************************
188
 * Play: play a sound samples buffer
Sam Hocevar's avatar
 
Sam Hocevar committed
189 190 191
 *****************************************************************************
 * This function writes a buffer of i_length bytes in the socket
 *****************************************************************************/
192
static void Play( aout_thread_t *p_aout, byte_t *p_buffer, int i_size )
Sam Hocevar's avatar
 
Sam Hocevar committed
193 194
{
    picture_t *p_outpic;
Sam Hocevar's avatar
 
Sam Hocevar committed
195 196
    int i_index, i_image;
    u8  *ppp_area[2][3];
Sam Hocevar's avatar
 
Sam Hocevar committed
197 198
    u16 *p_sample;

Sam Hocevar's avatar
 
Sam Hocevar committed
199
    /* Play the real sound */
200
    p_aout->p_sys->p_aout->pf_play( p_aout->p_sys->p_aout, p_buffer, i_size );
Sam Hocevar's avatar
 
Sam Hocevar committed
201 202

    for( i_image = 0; (i_image + 1) * SCOPE_WIDTH * 8 < i_size ; i_image++ )
Sam Hocevar's avatar
 
Sam Hocevar committed
203
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
204 205
        /* Don't stay here forever */
        if( mdate() >= p_aout->date - 10000 )
Sam Hocevar's avatar
 
Sam Hocevar committed
206
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
207
            break;
Sam Hocevar's avatar
 
Sam Hocevar committed
208 209
        }

Sam Hocevar's avatar
 
Sam Hocevar committed
210 211 212 213 214 215 216 217 218 219
        /* This is a new frame. Get a structure from the video_output. */
        while( ( p_outpic = vout_CreatePicture( p_aout->p_sys->p_vout, 0, 0, 0 ) )
                  == NULL )
        {
            if( p_aout->b_die )
            {
                return;
            }
            msleep( VOUT_OUTMEM_SLEEP );
        }
Sam Hocevar's avatar
 
Sam Hocevar committed
220

Sam Hocevar's avatar
 
Sam Hocevar committed
221 222
        /* Blank the picture */
        for( i_index = 0 ; i_index < p_outpic->i_planes ; i_index++ )
Sam Hocevar's avatar
 
Sam Hocevar committed
223
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
224 225
            memset( p_outpic->p[i_index].p_pixels, i_index ? 0x80 : 0x00,
                    p_outpic->p[i_index].i_lines * p_outpic->p[i_index].i_pitch );
Sam Hocevar's avatar
 
Sam Hocevar committed
226 227
        }

Sam Hocevar's avatar
 
Sam Hocevar committed
228 229 230
        /* We only support 2 channels for now */
        for( i_index = 0 ; i_index < 2 ; i_index++ )
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
231 232 233 234 235 236 237
            int j;
            for( j = 0 ; j < 3 ; j++ )
            {
                ppp_area[i_index][j] =
                    p_outpic->p[j].p_pixels + i_index * p_outpic->p[j].i_lines
                                / p_aout->i_channels * p_outpic->p[j].i_pitch;
            }
Sam Hocevar's avatar
 
Sam Hocevar committed
238
        }
Sam Hocevar's avatar
 
Sam Hocevar committed
239

Sam Hocevar's avatar
 
Sam Hocevar committed
240 241 242
        for( i_index = 0, p_sample = (u16*)p_buffer;
             i_index < SCOPE_WIDTH;
             i_index++ )
Sam Hocevar's avatar
 
Sam Hocevar committed
243
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
            int i;
            u8 i_value;

            for( i = 0 ; i < 2 ; i++ )
            {
                /* Left channel */
                i_value = *p_sample++ / 256 + 128;
                *(ppp_area[0][0]
                   + p_outpic->p[0].i_pitch * i_index / SCOPE_WIDTH
                   + p_outpic->p[0].i_lines * i_value / 512
                       * p_outpic->p[0].i_pitch) = 0xbf;
                *(ppp_area[0][1]
                   + p_outpic->p[1].i_pitch * i_index / SCOPE_WIDTH
                   + p_outpic->p[1].i_lines * i_value / 512
                      * p_outpic->p[1].i_pitch) = 0xff;

                /* Right channel */
                i_value = *p_sample++ / 256 + 128;
                *(ppp_area[1][0]
                   + p_outpic->p[0].i_pitch * i_index / SCOPE_WIDTH
                   + p_outpic->p[0].i_lines * i_value / 512
                      * p_outpic->p[0].i_pitch) = 0x9f;
                *(ppp_area[1][2]
                   + p_outpic->p[2].i_pitch * i_index / SCOPE_WIDTH
                   + p_outpic->p[2].i_lines * i_value / 512
                      * p_outpic->p[2].i_pitch) = 0xdd;
            }
Sam Hocevar's avatar
 
Sam Hocevar committed
271 272
        }

Sam Hocevar's avatar
 
Sam Hocevar committed
273 274
        /* Display the picture - FIXME: find a better date :-) */
        vout_DatePicture( p_aout->p_sys->p_vout, p_outpic,
Sam Hocevar's avatar
 
Sam Hocevar committed
275
                          p_aout->date + i_image * 20000 );
Sam Hocevar's avatar
 
Sam Hocevar committed
276 277 278 279
        vout_DisplayPicture( p_aout->p_sys->p_vout, p_outpic );

        p_buffer += SCOPE_WIDTH * 4;
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
280 281 282
}

/*****************************************************************************
283
 * Close: close the plugin
Sam Hocevar's avatar
 
Sam Hocevar committed
284
 *****************************************************************************/
285
static void Close( vlc_object_t *p_this )
Sam Hocevar's avatar
 
Sam Hocevar committed
286
{
287 288 289 290 291 292 293 294
    aout_thread_t *p_aout = (aout_thread_t *)p_this;

    /* Kill audio output */
    module_Unneed( p_aout->p_sys->p_aout, p_aout->p_sys->p_aout->p_module );
    vlc_object_detach_all( p_aout->p_sys->p_aout );
    vlc_object_destroy( p_aout->p_sys->p_aout );

    /* Kill video output */
295
    vout_DestroyThread( p_aout->p_sys->p_vout );
296

Sam Hocevar's avatar
 
Sam Hocevar committed
297 298 299
    free( p_aout->p_sys );
}