@ -32,91 +32,229 @@
# include <time.h>
# include <assert.h>
# include "timeline.h"
# include <libweston/libweston.h>
# include <libweston/weston-log.h>
# include "timeline.h"
# include "weston-log-internal.h"
WL_EXPORT int weston_timeline_enabled_ ;
struct timeline_emit_context {
FILE * cur ;
FILE * out ;
unsigned series ;
struct weston_log_subscription * subscription ;
} ;
static unsigned
timeline_new_id ( void )
/** Create a timeline subscription and hang it off the subscription
*
* Called when the subscription is created .
*
* @ ingroup internal - log
*/
void
weston_timeline_create_subscription ( struct weston_log_subscription * sub ,
void * user_data )
{
static unsigned idc ;
struct weston_timeline_subscription * tl_sub = zalloc ( sizeof ( * tl_sub ) ) ;
if ( ! tl_sub )
return ;
if ( + + idc = = 0 )
+ + idc ;
wl_list_init ( & tl_sub - > objects ) ;
return idc ;
/* attach this timeline_subscription to it */
weston_log_subscription_set_data ( sub , tl_sub ) ;
}
static int
check_series ( struct timeline_emit_context * ctx ,
struct weston_timeline_object * to )
static void
weston_timeline_destroy_subscription_object ( struct weston_timeline_subscription_object * sub_obj )
{
if ( to - > series = = 0 | | to - > series ! = ctx - > series ) {
to - > series = ctx - > series ;
to - > id = timeline_new_id ( ) ;
return 1 ;
/* remove the notify listener */
wl_list_remove ( & sub_obj - > destroy_listener . link ) ;
sub_obj - > destroy_listener . notify = NULL ;
wl_list_remove ( & sub_obj - > subscription_link ) ;
free ( sub_obj ) ;
}
if ( to - > force_refresh ) {
to - > force_refresh = 0 ;
return 1 ;
/** Destroy the timeline subscription and all timeline subscription objects
* associated with it .
*
* Called when ( before ) the subscription is destroyed .
*
* @ ingroup internal - log
*/
void
weston_timeline_destroy_subscription ( struct weston_log_subscription * sub ,
void * user_data )
{
struct weston_timeline_subscription * tl_sub =
weston_log_subscription_get_data ( sub ) ;
struct weston_timeline_subscription_object * sub_obj , * tmp_sub_obj ;
if ( ! tl_sub )
return ;
wl_list_for_each_safe ( sub_obj , tmp_sub_obj ,
& tl_sub - > objects , subscription_link )
weston_timeline_destroy_subscription_object ( sub_obj ) ;
free ( tl_sub ) ;
}
return 0 ;
static bool
weston_timeline_check_object_refresh ( struct weston_timeline_subscription_object * obj )
{
if ( obj - > force_refresh = = true ) {
obj - > force_refresh = false ;
return true ;
}
return false ;
}
static struct weston_timeline_subscription_object *
weston_timeline_subscription_search ( struct weston_timeline_subscription * tl_sub ,
void * object )
{
struct weston_timeline_subscription_object * sub_obj ;
wl_list_for_each ( sub_obj , & tl_sub - > objects , subscription_link )
if ( sub_obj - > object = = object )
return sub_obj ;
return NULL ;
}
static struct weston_timeline_subscription_object *
weston_timeline_subscription_object_create ( void * object ,
struct weston_timeline_subscription * tm_sub )
{
struct weston_timeline_subscription_object * sub_obj ;
sub_obj = zalloc ( sizeof ( * sub_obj ) ) ;
sub_obj - > id = + + tm_sub - > next_id ;
sub_obj - > object = object ;
/* when the object is created so that it has the chance to display the
* object ID , we set the refresh status ; it will only be re - freshed by
* the backend ( or part parts ) when the underlying objects has suffered
* modifications */
sub_obj - > force_refresh = true ;
wl_list_insert ( & tm_sub - > objects , & sub_obj - > subscription_link ) ;
return sub_obj ;
}
static void
weston_timeline_destroy_subscription_object_notify ( struct wl_listener * listener , void * data )
{
struct weston_timeline_subscription_object * sub_obj ;
sub_obj = wl_container_of ( listener , sub_obj , destroy_listener ) ;
weston_timeline_destroy_subscription_object ( sub_obj ) ;
}
static struct weston_timeline_subscription_object *
weston_timeline_subscription_output_ensure ( struct weston_timeline_subscription * tl_sub ,
struct weston_output * output )
{
struct weston_timeline_subscription_object * sub_obj ;
sub_obj = weston_timeline_subscription_search ( tl_sub , output ) ;
if ( ! sub_obj ) {
sub_obj = weston_timeline_subscription_object_create ( output , tl_sub ) ;
sub_obj - > destroy_listener . notify =
weston_timeline_destroy_subscription_object_notify ;
wl_signal_add ( & output - > destroy_signal ,
& sub_obj - > destroy_listener ) ;
}
return sub_obj ;
}
static struct weston_timeline_subscription_object *
weston_timeline_subscription_surface_ensure ( struct weston_timeline_subscription * tl_sub ,
struct weston_surface * surface )
{
struct weston_timeline_subscription_object * sub_obj ;
sub_obj = weston_timeline_subscription_search ( tl_sub , surface ) ;
if ( ! sub_obj ) {
sub_obj = weston_timeline_subscription_object_create ( surface , tl_sub ) ;
sub_obj - > destroy_listener . notify =
weston_timeline_destroy_subscription_object_notify ;
wl_signal_add ( & surface - > destroy_signal ,
& sub_obj - > destroy_listener ) ;
}
return sub_obj ;
}
static void
fprint_quoted_string ( FILE * fp , const char * str )
fprint_quoted_string ( struct weston_log_subscription * sub , const char * str )
{
if ( ! str ) {
fprintf ( fp , " null " ) ;
weston_log_subscription_printf ( sub , " null " ) ;
return ;
}
fprintf ( fp , " \" %s \" " , str ) ;
weston_log_subscription_printf ( sub , " \" %s \" " , str ) ;
}
static void
emit_weston_output_print_id ( struct weston_log_subscription * sub ,
struct weston_timeline_subscription_object * sub_obj ,
const char * name )
{
if ( ! weston_timeline_check_object_refresh ( sub_obj ) )
return ;
weston_log_subscription_printf ( sub , " { \" id \" :%u, "
" \" type \" : \" weston_output \" , \" name \" : " , sub_obj - > id ) ;
fprint_quoted_string ( sub , name ) ;
weston_log_subscription_printf ( sub , " } \n " ) ;
}
static int
emit_weston_output ( struct timeline_emit_context * ctx , void * obj )
{
struct weston_output * o = obj ;
struct weston_log_subscription * sub = ctx - > subscription ;
struct weston_output * output = obj ;
struct weston_timeline_subscription_object * sub_obj ;
struct weston_timeline_subscription * tl_sub ;
if ( check_series ( ctx , & o - > timeline ) ) {
fprintf ( ctx - > out , " { \" id \" :%u, "
" \" type \" : \" weston_output \" , \" name \" : " ,
o - > timeline . id ) ;
fprint_quoted_string ( ctx - > out , o - > name ) ;
fprintf ( ctx - > out , " } \n " ) ;
}
tl_sub = weston_log_subscription_get_data ( sub ) ;
sub_obj = weston_timeline_subscription_output_ensure ( tl_sub , output ) ;
emit_weston_output_print_id ( sub , sub_obj , output - > name ) ;
fprintf ( ctx - > cur , " \" wo \" :%u " , o - > timeline . id ) ;
assert ( sub_obj - > id ! = 0 ) ;
fprintf ( ctx - > cur , " \" wo \" :%u " , sub_obj - > id ) ;
return 1 ;
}
static void
check_weston_surface_description ( struct timeline_emit_context * ctx ,
struct weston_surface * s )
check_weston_surface_description ( struct weston_log_subscription * sub ,
struct weston_surface * s ,
struct weston_timeline_subscription * tm_sub ,
struct weston_timeline_subscription_object * sub_obj )
{
struct weston_surface * mains ;
char d [ 512 ] ;
char mainstr [ 32 ] ;
if ( ! check_series ( ctx , & s - > timeline ) )
if ( ! weston_timeline_check_object_refresh ( sub_obj ) )
return ;
mains = weston_surface_get_main_surface ( s ) ;
if ( mains ! = s ) {
check_weston_surface_description ( ctx , mains ) ;
if ( snprintf ( mainstr , sizeof ( mainstr ) ,
" , \" main_surface \" :%u " , mains - > timeline . id ) < 0 )
struct weston_timeline_subscription_object * new_sub_obj ;
new_sub_obj = weston_timeline_subscription_surface_ensure ( tm_sub , mains ) ;
check_weston_surface_description ( sub , mains , tm_sub , new_sub_obj ) ;
if ( snprintf ( mainstr , sizeof ( mainstr ) , " , \" main_surface \" :%u " ,
new_sub_obj - > id ) < 0 )
mainstr [ 0 ] = ' \0 ' ;
} else {
mainstr [ 0 ] = ' \0 ' ;
@ -125,19 +263,27 @@ check_weston_surface_description(struct timeline_emit_context *ctx,
if ( ! s - > get_label | | s - > get_label ( s , d , sizeof ( d ) ) < 0 )
d [ 0 ] = ' \0 ' ;
fprintf ( ctx - > out , " { \" id \" :%u, "
" \" type \" : \" weston_surface \" , \" desc \" : " , s - > timeline . id ) ;
fprint_quoted_string ( ctx - > out , d [ 0 ] ? d : NULL ) ;
fprintf ( ctx - > out , " %s } \n " , mainstr ) ;
weston_log_subscription_printf ( sub , " { \" id \" :%u, "
" \" type \" : \" weston_surface \" , \" desc \" : " ,
sub_obj - > id ) ;
fprint_quoted_string ( sub , d [ 0 ] ? d : NULL ) ;
weston_log_subscription_printf ( sub , " %s } \n " , mainstr ) ;
}
static int
emit_weston_surface ( struct timeline_emit_context * ctx , void * obj )
{
struct weston_surface * s = obj ;
struct weston_log_subscription * sub = ctx - > subscription ;
struct weston_surface * surface = obj ;
struct weston_timeline_subscription_object * sub_obj ;
struct weston_timeline_subscription * tl_sub ;
tl_sub = weston_log_subscription_get_data ( sub ) ;
sub_obj = weston_timeline_subscription_surface_ensure ( tl_sub , surface ) ;
check_weston_surface_description ( sub , surface , tl_sub , sub_obj ) ;
check_weston_surface_description ( ctx , s ) ;
fprintf ( ctx - > cur , " \" ws \" :%u " , s - > timeline . id ) ;
assert ( sub_obj - > id ! = 0 ) ;
fprintf ( ctx - > cur , " \" ws \" :%u " , sub_obj - > id ) ;
return 1 ;
}
@ -214,7 +360,7 @@ weston_timeline_point(const char *name, ...)
if ( ferror ( ctx . cur ) ) {
weston_log ( " Timeline error in constructing entry, closing. \n " ) ;
} else {
f printf( ctx . out , " %s " , buf ) ;
weston_log_subscription_ printf( ctx . subscription , " %s " , buf ) ;
}
fclose ( ctx . cur ) ;