static void CleanThread ( vout_thread_t * );
static void EndThread ( vout_thread_t * );
-static void VideoFormatImportRgb( video_format_t *, const picture_heap_t * );
-static void PictureHeapFixRgb( picture_heap_t * );
-
static void vout_Destructor ( vlc_object_t * p_this );
/* Object variables callbacks */
{
vout_thread_t *p_vout = (vout_thread_t*)p_filter->p_owner;
- vlc_mutex_lock( &p_vout->picture_lock );
+ vlc_mutex_lock( &p_vout->p->picture_lock );
vout_UsePictureLocked( p_vout, p_pic );
- vlc_mutex_unlock( &p_vout->picture_lock );
+ vlc_mutex_unlock( &p_vout->p->picture_lock );
}
static int video_filter_buffer_allocation_init( filter_t *p_filter, void *p_data )
/* If we now have a video output, check it has the right properties */
if( p_vout )
{
- vlc_mutex_lock( &p_vout->change_lock );
+ vlc_mutex_lock( &p_vout->p->change_lock );
/* We don't directly check for the "vout-filter" variable for obvious
* performance reasons. */
free( psz_filter_chain );
}
+#warning "FIXME: Check RGB masks in vout_Request"
+ /* FIXME: check RGB masks */
if( p_vout->fmt_render.i_chroma != vlc_fourcc_GetCodec( VIDEO_ES, p_fmt->i_chroma ) ||
p_vout->fmt_render.i_width != p_fmt->i_width ||
p_vout->fmt_render.i_height != p_fmt->i_height ||
p_vout->p->b_filter_change )
{
- vlc_mutex_unlock( &p_vout->change_lock );
+ vlc_mutex_unlock( &p_vout->p->change_lock );
/* We are not interested in this format, close this vout */
vout_CloseAndRelease( p_vout );
p_vout->fmt_render.i_sar_num = i_sar_num;
p_vout->fmt_render.i_sar_den = i_sar_den;
-
- p_vout->render.i_aspect = (int64_t)i_sar_num *
- p_vout->fmt_render.i_width *
- VOUT_ASPECT_FACTOR /
- i_sar_den /
- p_vout->fmt_render.i_height;
- p_vout->i_changes |= VOUT_ASPECT_CHANGE;
+ p_vout->p->i_changes |= VOUT_ASPECT_CHANGE;
}
- vlc_mutex_unlock( &p_vout->change_lock );
+ vlc_mutex_unlock( &p_vout->p->change_lock );
vlc_object_release( p_vout );
}
int i_index; /* loop variable */
vlc_value_t text;
- unsigned int i_width = p_fmt->i_width;
- unsigned int i_height = p_fmt->i_height;
- vlc_fourcc_t i_chroma = vlc_fourcc_GetCodec( VIDEO_ES, p_fmt->i_chroma );
config_chain_t *p_cfg;
char *psz_parser;
char *psz_name;
- if( i_width <= 0 || i_height <= 0 )
+ if( p_fmt->i_width <= 0 || p_fmt->i_height <= 0 )
return NULL;
+ const vlc_fourcc_t i_chroma = vlc_fourcc_GetCodec( VIDEO_ES, p_fmt->i_chroma );
vlc_ureduce( &p_fmt->i_sar_num, &p_fmt->i_sar_den,
p_fmt->i_sar_num, p_fmt->i_sar_den, 50000 );
if( p_fmt->i_sar_num <= 0 || p_fmt->i_sar_den <= 0 )
return NULL;
- unsigned int i_aspect = (int64_t)p_fmt->i_sar_num *
- i_width *
- VOUT_ASPECT_FACTOR /
- p_fmt->i_sar_den /
- i_height;
/* Allocate descriptor */
static const char typename[] = "video output";
* will be initialized later in InitThread */
for( i_index = 0; i_index < 2 * VOUT_MAX_PICTURES + 1; i_index++)
{
- p_vout->p_picture[i_index].i_status = FREE_PICTURE;
- p_vout->p_picture[i_index].i_type = EMPTY_PICTURE;
- p_vout->p_picture[i_index].b_slow = 0;
+ p_vout->p->p_picture[i_index].i_status = FREE_PICTURE;
+ p_vout->p->p_picture[i_index].i_type = EMPTY_PICTURE;
+ p_vout->p->p_picture[i_index].b_slow = 0;
}
/* Initialize the rendering heap */
p_vout->fmt_render = *p_fmt; /* FIXME palette */
p_vout->fmt_in = *p_fmt; /* FIXME palette */
- p_vout->render.i_width = i_width;
- p_vout->render.i_height = i_height;
- p_vout->render.i_chroma = i_chroma;
- p_vout->render.i_aspect = i_aspect;
+ p_vout->fmt_render.i_chroma =
+ p_vout->fmt_in.i_chroma = i_chroma;
+ video_format_FixRgb( &p_vout->fmt_render );
+ video_format_FixRgb( &p_vout->fmt_in );
- p_vout->render.i_rmask = p_fmt->i_rmask;
- p_vout->render.i_gmask = p_fmt->i_gmask;
- p_vout->render.i_bmask = p_fmt->i_bmask;
-
- p_vout->render.i_last_used_pic = -1;
- p_vout->render.b_allow_modify_pics = 1;
+ p_vout->p->render.i_last_used_pic = -1;
/* Zero the output heap */
I_OUTPUTPICTURES = 0;
- p_vout->output.i_width = 0;
- p_vout->output.i_height = 0;
- p_vout->output.i_chroma = 0;
- p_vout->output.i_aspect = 0;
-
- p_vout->output.i_rmask = 0;
- p_vout->output.i_gmask = 0;
- p_vout->output.i_bmask = 0;
/* Initialize misc stuff */
- p_vout->i_changes = 0;
- p_vout->b_autoscale = 1;
- p_vout->i_zoom = ZOOM_FP_FACTOR;
- p_vout->b_fullscreen = 0;
- p_vout->i_alignment = 0;
+ p_vout->p->i_changes = 0;
+ p_vout->p->b_fullscreen = 0;
p_vout->p->render_time = 10;
p_vout->p->c_fps_samples = 0;
vout_statistic_Init( &p_vout->p->statistic );
vout_snapshot_Init( &p_vout->p->snapshot );
/* Initialize locks */
- vlc_mutex_init( &p_vout->picture_lock );
+ vlc_mutex_init( &p_vout->p->picture_lock );
vlc_cond_init( &p_vout->p->picture_wait );
- vlc_mutex_init( &p_vout->change_lock );
+ vlc_mutex_init( &p_vout->p->change_lock );
vlc_mutex_init( &p_vout->p->vfilter_lock );
/* Mouse coordinates */
return NULL;
}
- vlc_mutex_lock( &p_vout->change_lock );
+ vlc_mutex_lock( &p_vout->p->change_lock );
while( !p_vout->p->b_ready )
{ /* We are (ab)using the same condition in opposite directions for
* b_ready and b_done. This works because of the strict ordering. */
assert( !p_vout->p->b_done );
- vlc_cond_wait( &p_vout->p->change_wait, &p_vout->change_lock );
+ vlc_cond_wait( &p_vout->p->change_wait, &p_vout->p->change_lock );
}
- vlc_mutex_unlock( &p_vout->change_lock );
+ vlc_mutex_unlock( &p_vout->p->change_lock );
if( p_vout->p->b_error )
{
{
assert( p_vout );
- vlc_mutex_lock( &p_vout->change_lock );
+ vlc_mutex_lock( &p_vout->p->change_lock );
p_vout->p->b_done = true;
vlc_cond_signal( &p_vout->p->change_wait );
- vlc_mutex_unlock( &p_vout->change_lock );
+ vlc_mutex_unlock( &p_vout->p->change_lock );
vout_snapshot_End( &p_vout->p->snapshot );
/* Destroy the locks */
vlc_cond_destroy( &p_vout->p->change_wait );
vlc_cond_destroy( &p_vout->p->picture_wait );
- vlc_mutex_destroy( &p_vout->picture_lock );
- vlc_mutex_destroy( &p_vout->change_lock );
+ vlc_mutex_destroy( &p_vout->p->picture_lock );
+ vlc_mutex_destroy( &p_vout->p->change_lock );
vlc_mutex_destroy( &p_vout->p->vfilter_lock );
/* */
/* */
void vout_ChangePause( vout_thread_t *p_vout, bool b_paused, mtime_t i_date )
{
- vlc_mutex_lock( &p_vout->change_lock );
+ vlc_mutex_lock( &p_vout->p->change_lock );
assert( !p_vout->p->b_paused || !b_paused );
- vlc_mutex_lock( &p_vout->picture_lock );
+ vlc_mutex_lock( &p_vout->p->picture_lock );
p_vout->p->i_picture_displayed_date = 0;
p_pic->date += i_duration;
}
vlc_cond_signal( &p_vout->p->picture_wait );
- vlc_mutex_unlock( &p_vout->picture_lock );
+ vlc_mutex_unlock( &p_vout->p->picture_lock );
spu_OffsetSubtitleDate( p_vout->p->p_spu, i_duration );
}
else
{
- vlc_mutex_unlock( &p_vout->picture_lock );
+ vlc_mutex_unlock( &p_vout->p->picture_lock );
}
p_vout->p->b_paused = b_paused;
p_vout->p->i_pause_date = i_date;
- vlc_mutex_unlock( &p_vout->change_lock );
+ vlc_mutex_unlock( &p_vout->p->change_lock );
}
void vout_GetResetStatistic( vout_thread_t *p_vout, int *pi_displayed, int *pi_lost )
void vout_Flush( vout_thread_t *p_vout, mtime_t i_date )
{
- vlc_mutex_lock( &p_vout->picture_lock );
+ vlc_mutex_lock( &p_vout->p->picture_lock );
p_vout->p->i_picture_displayed_date = 0;
- for( int i = 0; i < p_vout->render.i_pictures; i++ )
+ for( int i = 0; i < p_vout->p->render.i_pictures; i++ )
{
- picture_t *p_pic = p_vout->render.pp_picture[i];
+ picture_t *p_pic = p_vout->p->render.pp_picture[i];
if( p_pic->i_status == READY_PICTURE ||
p_pic->i_status == DISPLAYED_PICTURE )
}
}
vlc_cond_signal( &p_vout->p->picture_wait );
- vlc_mutex_unlock( &p_vout->picture_lock );
+ vlc_mutex_unlock( &p_vout->p->picture_lock );
}
void vout_FixLeaks( vout_thread_t *p_vout, bool b_forced )
{
int i_pic, i_ready_pic;
- vlc_mutex_lock( &p_vout->picture_lock );
+ vlc_mutex_lock( &p_vout->p->picture_lock );
- for( i_pic = 0, i_ready_pic = 0; i_pic < p_vout->render.i_pictures && !b_forced; i_pic++ )
+ for( i_pic = 0, i_ready_pic = 0; i_pic < p_vout->p->render.i_pictures && !b_forced; i_pic++ )
{
- const picture_t *p_pic = p_vout->render.pp_picture[i_pic];
+ const picture_t *p_pic = p_vout->p->render.pp_picture[i_pic];
if( p_pic->i_status == READY_PICTURE )
{
break;
}
}
- if( i_pic < p_vout->render.i_pictures && !b_forced )
+ if( i_pic < p_vout->p->render.i_pictures && !b_forced )
{
- vlc_mutex_unlock( &p_vout->picture_lock );
+ vlc_mutex_unlock( &p_vout->p->picture_lock );
return;
}
msg_Err( p_vout, "pictures leaked, resetting the heap" );
/* Just free all the pictures */
- for( i_pic = 0; i_pic < p_vout->render.i_pictures; i_pic++ )
+ for( i_pic = 0; i_pic < p_vout->p->render.i_pictures; i_pic++ )
{
- picture_t *p_pic = p_vout->render.pp_picture[i_pic];
+ picture_t *p_pic = p_vout->p->render.pp_picture[i_pic];
msg_Dbg( p_vout, "[%d] %d %d", i_pic, p_pic->i_status, p_pic->i_refcount );
p_pic->i_refcount = 0;
}
}
vlc_cond_signal( &p_vout->p->picture_wait );
- vlc_mutex_unlock( &p_vout->picture_lock );
+ vlc_mutex_unlock( &p_vout->p->picture_lock );
}
void vout_NextPicture( vout_thread_t *p_vout, mtime_t *pi_duration )
{
- vlc_mutex_lock( &p_vout->picture_lock );
+ vlc_mutex_lock( &p_vout->p->picture_lock );
const mtime_t i_displayed_date = p_vout->p->i_picture_displayed_date;
}
while( !p_vout->p->b_picture_displayed && !p_vout->p->b_picture_empty )
- vlc_cond_wait( &p_vout->p->picture_wait, &p_vout->picture_lock );
+ vlc_cond_wait( &p_vout->p->picture_wait, &p_vout->p->picture_lock );
*pi_duration = __MAX( p_vout->p->i_picture_displayed_date - i_displayed_date, 0 );
/* TODO advance subpicture by the duration ... */
- vlc_mutex_unlock( &p_vout->picture_lock );
+ vlc_mutex_unlock( &p_vout->p->picture_lock );
}
void vout_DisplayTitle( vout_thread_t *p_vout, const char *psz_title )
if( !var_InheritBool( p_vout, "osd" ) )
return;
- vlc_mutex_lock( &p_vout->change_lock );
+ vlc_mutex_lock( &p_vout->p->change_lock );
free( p_vout->p->psz_title );
p_vout->p->psz_title = strdup( psz_title );
- vlc_mutex_unlock( &p_vout->change_lock );
+ vlc_mutex_unlock( &p_vout->p->change_lock );
}
spu_t *vout_GetSpu( vout_thread_t *p_vout )
* modified inside this function.
* XXX You have to enter it with change_lock taken.
*****************************************************************************/
-static int ChromaCreate( vout_thread_t *p_vout );
-static void ChromaDestroy( vout_thread_t *p_vout );
-
static int InitThread( vout_thread_t *p_vout )
{
int i;
msg_Dbg( p_vout, "got %i direct buffer(s)", I_OUTPUTPICTURES );
- if( !p_vout->fmt_out.i_width || !p_vout->fmt_out.i_height )
- {
- p_vout->fmt_out.i_width = p_vout->fmt_out.i_visible_width =
- p_vout->output.i_width;
- p_vout->fmt_out.i_height = p_vout->fmt_out.i_visible_height =
- p_vout->output.i_height;
- p_vout->fmt_out.i_x_offset = p_vout->fmt_out.i_y_offset = 0;
-
- p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
- }
+ assert( p_vout->fmt_out.i_width > 0 && p_vout->fmt_out.i_height > 0 );
if( !p_vout->fmt_out.i_sar_num || !p_vout->fmt_out.i_sar_num )
{
- p_vout->fmt_out.i_sar_num = p_vout->output.i_aspect *
- p_vout->fmt_out.i_height;
- p_vout->fmt_out.i_sar_den = VOUT_ASPECT_FACTOR *
- p_vout->fmt_out.i_width;
+ /* FIXME is it possible to end up here ? */
+ p_vout->fmt_out.i_sar_num = 1;
+ p_vout->fmt_out.i_sar_den = 1;
}
vlc_ureduce( &p_vout->fmt_out.i_sar_num, &p_vout->fmt_out.i_sar_den,
/* FIXME removed the need of both fmt_* and heap infos */
/* Calculate shifts from system-updated masks */
- PictureHeapFixRgb( &p_vout->render );
- VideoFormatImportRgb( &p_vout->fmt_render, &p_vout->render );
-
- PictureHeapFixRgb( &p_vout->output );
- VideoFormatImportRgb( &p_vout->fmt_out, &p_vout->output );
+ video_format_FixRgb( &p_vout->fmt_render );
+ video_format_FixRgb( &p_vout->fmt_out );
/* print some usefull debug info about different vout formats
*/
p_vout->fmt_out.i_sar_num, p_vout->fmt_out.i_sar_den,
p_vout->fmt_out.i_rmask, p_vout->fmt_out.i_gmask, p_vout->fmt_out.i_bmask );
- assert( p_vout->output.i_width == p_vout->render.i_width &&
- p_vout->output.i_height == p_vout->render.i_height &&
- p_vout->output.i_chroma == p_vout->render.i_chroma );
+ assert( p_vout->fmt_out.i_width == p_vout->fmt_render.i_width &&
+ p_vout->fmt_out.i_height == p_vout->fmt_render.i_height &&
+ p_vout->fmt_out.i_chroma == p_vout->fmt_render.i_chroma );
/* Check whether we managed to create direct buffers similar to
* the render buffers, ie same size and chroma */
* for memcpy operations */
for( i = 1; i < VOUT_MAX_PICTURES; i++ )
{
- if( p_vout->p_picture[ i ].i_type != DIRECT_PICTURE &&
+ if( p_vout->p->p_picture[ i ].i_type != DIRECT_PICTURE &&
I_RENDERPICTURES >= VOUT_MIN_DIRECT_PICTURES - 1 &&
- p_vout->p_picture[ i - 1 ].i_type == DIRECT_PICTURE )
+ p_vout->p->p_picture[ i - 1 ].i_type == DIRECT_PICTURE )
{
/* We have enough direct buffers so there's no need to
* try to use system memory buffers. */
break;
}
- PP_RENDERPICTURE[ I_RENDERPICTURES ] = &p_vout->p_picture[ i ];
+ PP_RENDERPICTURE[ I_RENDERPICTURES ] = &p_vout->p->p_picture[ i ];
I_RENDERPICTURES++;
}
*/
b_has_wrapper = !vout_OpenWrapper( p_vout, p_vout->p->psz_module_name );
- vlc_mutex_lock( &p_vout->change_lock );
+ vlc_mutex_lock( &p_vout->p->change_lock );
if( b_has_wrapper )
p_vout->p->b_error = InitThread( p_vout );
if( p_vout->p->b_title_show && p_vout->p->psz_title )
DisplayTitleOnOSD( p_vout );
- vlc_mutex_lock( &p_vout->picture_lock );
+ vlc_mutex_lock( &p_vout->p->picture_lock );
/* Look for the earliest picture but after the last displayed one */
picture_t *p_last = p_vout->p->p_picture_displayed;;
const bool b_picture_interlaced = p_vout->p->b_picture_interlaced;
const int i_picture_interlaced_state = (!!p_vout->p->b_picture_interlaced) - (!!b_picture_interlaced_last);
- vlc_mutex_unlock( &p_vout->picture_lock );
+ vlc_mutex_unlock( &p_vout->p->picture_lock );
if( p_picture == NULL )
i_idle_loops++;
}
/* Give back change lock */
- vlc_mutex_unlock( &p_vout->change_lock );
+ vlc_mutex_unlock( &p_vout->p->change_lock );
/* Sleep a while or until a given date */
if( display_date != 0 )
else
{
/* Wait until a frame is being sent or a spurious wakeup (not a problem here) */
- vlc_mutex_lock( &p_vout->picture_lock );
- vlc_cond_timedwait( &p_vout->p->picture_wait, &p_vout->picture_lock, current_date + VOUT_IDLE_SLEEP );
- vlc_mutex_unlock( &p_vout->picture_lock );
+ vlc_mutex_lock( &p_vout->p->picture_lock );
+ vlc_cond_timedwait( &p_vout->p->picture_wait, &p_vout->p->picture_lock, current_date + VOUT_IDLE_SLEEP );
+ vlc_mutex_unlock( &p_vout->p->picture_lock );
}
/* On awakening, take back lock and send immediately picture
* to display. */
/* Note: p_vout->p->b_done could be true here and now */
- vlc_mutex_lock( &p_vout->change_lock );
+ vlc_mutex_lock( &p_vout->p->change_lock );
/*
* Display the previously rendered picture
/* Drop the filtered picture if created by video filters */
if( p_filtered_picture != NULL && p_filtered_picture != p_picture )
{
- vlc_mutex_lock( &p_vout->picture_lock );
+ vlc_mutex_lock( &p_vout->p->picture_lock );
vout_UsePictureLocked( p_vout, p_filtered_picture );
- vlc_mutex_unlock( &p_vout->picture_lock );
+ vlc_mutex_unlock( &p_vout->p->picture_lock );
}
if( p_picture != NULL )
break;
}
- if( p_vout->i_changes & VOUT_ON_TOP_CHANGE )
- p_vout->i_changes &= ~VOUT_ON_TOP_CHANGE;
+ if( p_vout->p->i_changes & VOUT_ON_TOP_CHANGE )
+ p_vout->p->i_changes &= ~VOUT_ON_TOP_CHANGE;
- if( p_vout->i_changes & VOUT_PICTURE_BUFFERS_CHANGE )
+ if( p_vout->p->i_changes & VOUT_PICTURE_BUFFERS_CHANGE )
{
/* This happens when the picture buffers need to be recreated.
* This is useful on multimonitor displays for instance.
*
* Warning: This only works when the vout creates only 1 picture
* buffer!! */
- p_vout->i_changes &= ~VOUT_PICTURE_BUFFERS_CHANGE;
+ p_vout->p->i_changes &= ~VOUT_PICTURE_BUFFERS_CHANGE;
- vlc_mutex_lock( &p_vout->picture_lock );
+ vlc_mutex_lock( &p_vout->p->picture_lock );
vout_EndWrapper( p_vout );
msg_Err( p_vout, "InitThread after VOUT_PICTURE_BUFFERS_CHANGE failed" );
vlc_cond_signal( &p_vout->p->picture_wait );
- vlc_mutex_unlock( &p_vout->picture_lock );
+ vlc_mutex_unlock( &p_vout->p->picture_lock );
if( p_vout->p->b_error )
break;
exit_thread:
/* End of thread */
EndThread( p_vout );
- vlc_mutex_unlock( &p_vout->change_lock );
+ vlc_mutex_unlock( &p_vout->p->change_lock );
if( b_has_wrapper )
vout_CloseWrapper( p_vout );
{
/* Wait until a `close' order */
while( !p_vout->p->b_done )
- vlc_cond_wait( &p_vout->p->change_wait, &p_vout->change_lock );
+ vlc_cond_wait( &p_vout->p->change_wait, &p_vout->p->change_lock );
}
/*****************************************************************************
/* Destroy all remaining pictures */
for( i_index = 0; i_index < 2 * VOUT_MAX_PICTURES + 1; i_index++ )
{
- if ( p_vout->p_picture[i_index].i_type == MEMORY_PICTURE )
+ if ( p_vout->p->p_picture[i_index].i_type == MEMORY_PICTURE )
{
- free( p_vout->p_picture[i_index].p_data_orig );
+ free( p_vout->p->p_picture[i_index].p_data_orig );
}
}
/* following functions are local */
-/**
- * This function copies all RGB informations from a picture_heap_t into
- * a video_format_t
- */
-static void VideoFormatImportRgb( video_format_t *p_fmt, const picture_heap_t *p_heap )
-{
- p_fmt->i_rmask = p_heap->i_rmask;
- p_fmt->i_gmask = p_heap->i_gmask;
- p_fmt->i_bmask = p_heap->i_bmask;
- p_fmt->i_rrshift = p_heap->i_rrshift;
- p_fmt->i_lrshift = p_heap->i_lrshift;
- p_fmt->i_rgshift = p_heap->i_rgshift;
- p_fmt->i_lgshift = p_heap->i_lgshift;
- p_fmt->i_rbshift = p_heap->i_rbshift;
- p_fmt->i_lbshift = p_heap->i_lbshift;
-}
-
-/**
- * This funtion copes all RGB informations from a video_format_t into
- * a picture_heap_t
- */
-static void VideoFormatExportRgb( const video_format_t *p_fmt, picture_heap_t *p_heap )
-{
- p_heap->i_rmask = p_fmt->i_rmask;
- p_heap->i_gmask = p_fmt->i_gmask;
- p_heap->i_bmask = p_fmt->i_bmask;
- p_heap->i_rrshift = p_fmt->i_rrshift;
- p_heap->i_lrshift = p_fmt->i_lrshift;
- p_heap->i_rgshift = p_fmt->i_rgshift;
- p_heap->i_lgshift = p_fmt->i_lgshift;
- p_heap->i_rbshift = p_fmt->i_rbshift;
- p_heap->i_lbshift = p_fmt->i_lbshift;
-}
-
-/**
- * This function computes rgb shifts from masks
- */
-static void PictureHeapFixRgb( picture_heap_t *p_heap )
-{
- video_format_t fmt;
-
- /* */
- fmt.i_chroma = p_heap->i_chroma;
- VideoFormatImportRgb( &fmt, p_heap );
-
- /* */
- video_format_FixRgb( &fmt );
-
- VideoFormatExportRgb( &fmt, p_heap );
-}
-
/*****************************************************************************
* object variables callbacks: a bunch of object variables are used by the
* interfaces to interact with the vout.
if( i_stop <= i_start )
return;
- vlc_assert_locked( &p_vout->change_lock );
+ vlc_assert_locked( &p_vout->p->change_lock );
vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN,
p_vout->p->psz_title, NULL,