maemo-ui/src/mmyth_epg_grid_widget.c
author rosfran
Wed Dec 06 00:10:35 2006 +0000 (2006-12-06)
branchtrunk
changeset 199 4bed4ce6b681
child 208 c3c073032757
permissions -rw-r--r--
[svn r200] Put a GThreadPool, for a better memory usage.
renatofilho@20
     1
#include <gtk/gtksignal.h>
renatofilho@20
     2
#include <gdk/gdkevents.h>
renatofilho@20
     3
#include <gdk/gdkkeysyms.h>
renatofilho@20
     4
renatofilho@20
     5
#include "mmyth_uicommon.h"
renatofilho@20
     6
#include "mmyth_epg_grid_widget.h"
renatofilho@20
     7
renatofilho@20
     8
#include "gmyth_util.h" 
renatofilho@20
     9
#include "gmyth_epg.h"
renatofilho@20
    10
renatofilho@20
    11
#define PIXELS_HOUR 105
renatofilho@20
    12
#define PROGRAM_SEPARATION 2
renatofilho@20
    13
renatofilho@20
    14
enum {
renatofilho@20
    15
  SELECTION_UPDATED_SIGNAL,
renatofilho@20
    16
  LAST_SIGNAL
renatofilho@20
    17
};
renatofilho@20
    18
renatofilho@20
    19
struct _MMythEpgGridWidgetPrivate {
renatofilho@20
    20
    /* private widget components */
renatofilho@20
    21
    GtkWidget *epg_channels_vbox;
renatofilho@20
    22
    GtkWidget *epg_programs_vbox;
renatofilho@20
    23
 
renatofilho@20
    24
    GHashTable *service_model_hash;
renatofilho@20
    25
    
renatofilho@20
    26
    /* guidegrid attributes */
renatofilho@20
    27
    gboolean show_favorites;
renatofilho@20
    28
    gint current_start_channel_id;
renatofilho@20
    29
    
renatofilho@20
    30
    time_t current_start_time;
renatofilho@20
    31
    time_t current_end_time;
renatofilho@20
    32
renatofilho@20
    33
    guint selected_channel_index;
renatofilho@20
    34
    
renatofilho@20
    35
    /* GList of ProgramInfo for each Channel */
renatofilho@20
    36
    GList * program_list[MAX_DISPLAY_CHANS];
renatofilho@20
    37
    GList * channel_list;
renatofilho@20
    38
    
renatofilho@20
    39
    GMythEPG *mmyth_epg;
renatofilho@20
    40
    
renatofilho@20
    41
    gint DISPLAY_CHANS;
renatofilho@20
    42
};
renatofilho@20
    43
renatofilho@20
    44
static void mmyth_epg_grid_widget_class_init          (MMythEpgGridWidgetClass *klass);
renatofilho@20
    45
static void mmyth_epg_grid_widget_init                (MMythEpgGridWidget *object);
renatofilho@20
    46
static void mmyth_epg_grid_widget_private_init        (MMythEpgGridWidgetPrivate *private);
renatofilho@20
    47
static void mmyth_epg_grid_widget_mount_services      (MMythEpgGridWidget *object, 
renatofilho@20
    48
                                                       int start_time, int end_time);
renatofilho@20
    49
static void mmyth_epg_grid_widget_mount_header        (MMythEpgGridWidget *object);
renatofilho@20
    50
static void mmyth_epg_grid_widget_clicked             (GtkWidget* widget, 
renatofilho@20
    51
                                                       GdkEventExpose *event, 
renatofilho@20
    52
                                                       gpointer data);
renatofilho@20
    53
static GtkWidget *create_event_box_lbl                (gchar *str, int width, 
renatofilho@20
    54
                                                       const GdkColor *bg_color, 
renatofilho@20
    55
                                                       const GdkColor *fg_color);
renatofilho@20
    56
renatofilho@20
    57
static void mmyth_epg_grid_widget_fill_programinfos(MMythEpgGridWidgetPrivate *private);
renatofilho@20
    58
static void mmyth_epg_grid_widget_fill_program_row_infos(
renatofilho@20
    59
                    MMythEpgGridWidgetPrivate *private, 
renatofilho@20
    60
                    unsigned int chanNum, unsigned int row);
renatofilho@20
    61
renatofilho@20
    62
static gint mmyth_epg_grid_widget_signals[LAST_SIGNAL] = { 0 };
renatofilho@20
    63
renatofilho@20
    64
G_DEFINE_TYPE(MMythEpgGridWidget, mmyth_epg_grid_widget, GTK_TYPE_EVENT_BOX)
renatofilho@20
    65
    
renatofilho@20
    66
static void
renatofilho@20
    67
mmyth_epg_grid_widget_class_init (MMythEpgGridWidgetClass *klass)
renatofilho@20
    68
{
renatofilho@20
    69
  g_type_class_add_private (klass, sizeof (MMythEpgGridWidgetPrivate));
renatofilho@20
    70
  
renatofilho@20
    71
  mmyth_epg_grid_widget_signals[SELECTION_UPDATED_SIGNAL] = g_signal_new (
renatofilho@20
    72
                     "selection_updated",
renatofilho@20
    73
					 G_TYPE_FROM_CLASS(klass), 
renatofilho@20
    74
					 G_SIGNAL_RUN_FIRST,
renatofilho@20
    75
					 0,
renatofilho@20
    76
                     NULL,
renatofilho@20
    77
                     NULL,
renatofilho@20
    78
					 g_cclosure_marshal_VOID__POINTER, 
renatofilho@20
    79
                     G_TYPE_NONE, 
renatofilho@20
    80
                     1,
renatofilho@20
    81
                     G_TYPE_POINTER);
renatofilho@20
    82
}
renatofilho@20
    83
renatofilho@20
    84
static void 
renatofilho@20
    85
mmyth_epg_grid_widget_private_init (MMythEpgGridWidgetPrivate *private)
renatofilho@20
    86
{
renatofilho@20
    87
    time_t cur_time;
renatofilho@20
    88
    
renatofilho@20
    89
    g_return_if_fail(private != NULL);     
renatofilho@20
    90
renatofilho@20
    91
    private->epg_channels_vbox   = NULL;
renatofilho@20
    92
    private->epg_programs_vbox   = NULL;
renatofilho@20
    93
    private->service_model_hash  = NULL;
renatofilho@20
    94
renatofilho@20
    95
    private->show_favorites = FALSE;
renatofilho@20
    96
    private->current_start_channel_id = -1;
renatofilho@20
    97
renatofilho@20
    98
    /* Selected the first diplayable channel initially */
renatofilho@20
    99
    private->selected_channel_index = 0;
renatofilho@20
   100
        
renatofilho@20
   101
    /* TODO fix the current start/end time */
renatofilho@20
   102
    private->current_start_time = time(&cur_time);
renatofilho@20
   103
    private->current_end_time = time(&cur_time) + 10800;   
renatofilho@20
   104
    
renatofilho@20
   105
    private->DISPLAY_CHANS = MAX_DISPLAY_CHANS;
renatofilho@20
   106
    
renatofilho@20
   107
    // TODO: Close the epg and unref it in dispose call
renatofilho@20
   108
    private->mmyth_epg = gmyth_epg_new ();
renatofilho@20
   109
    if (!gmyth_epg_connect (private->mmyth_epg)) {
renatofilho@20
   110
    	g_warning ("[%s] Could not connect mysql handler to db", __FUNCTION__);
renatofilho@20
   111
    	g_object_unref (private->mmyth_epg);
renatofilho@20
   112
    	private->mmyth_epg = NULL;
renatofilho@20
   113
    }
renatofilho@20
   114
}
renatofilho@20
   115
renatofilho@20
   116
static void
renatofilho@20
   117
mmyth_epg_grid_widget_init (MMythEpgGridWidget *mmyth_epg_grid_widget)
renatofilho@20
   118
{
renatofilho@20
   119
    MMythEpgGridWidgetPrivate *private = 
renatofilho@20
   120
        MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget);
renatofilho@20
   121
    
renatofilho@20
   122
    /* init private fields */
renatofilho@20
   123
    mmyth_epg_grid_widget_private_init(private);
renatofilho@20
   124
renatofilho@20
   125
    mmyth_epg_grid_widget->epg_view_model      = NULL;
renatofilho@20
   126
    mmyth_epg_grid_widget->selected_grid_item  = NULL;
renatofilho@20
   127
renatofilho@20
   128
    GtkWidget *epg_event_box = GTK_WIDGET(mmyth_epg_grid_widget);
renatofilho@20
   129
    gtk_widget_modify_bg(epg_event_box, GTK_STATE_NORMAL, &main_bg_color);
renatofilho@20
   130
    gtk_widget_set_size_request (epg_event_box, 0, 125);
renatofilho@20
   131
    
renatofilho@20
   132
    GtkWidget *epg_main_hbox = gtk_hbox_new (FALSE, 10);
renatofilho@20
   133
    gtk_container_set_border_width(GTK_CONTAINER (epg_main_hbox), 10);
renatofilho@20
   134
    
renatofilho@20
   135
    gtk_container_add (GTK_CONTAINER (epg_event_box),
renatofilho@20
   136
                       epg_main_hbox);
renatofilho@20
   137
		        
renatofilho@20
   138
    /* channels vbox */
renatofilho@20
   139
    GtkWidget *epg_channels_vbox = gtk_vbox_new (FALSE, 3); 
renatofilho@20
   140
    private->epg_channels_vbox = epg_channels_vbox; 
renatofilho@20
   141
renatofilho@20
   142
    /* programs vbox */
renatofilho@20
   143
    GtkWidget *epg_programs_vbox = gtk_vbox_new (FALSE, 3);
renatofilho@20
   144
    private->epg_programs_vbox = epg_programs_vbox;
renatofilho@20
   145
    
renatofilho@20
   146
    /* packing start */
renatofilho@20
   147
    gtk_box_pack_start (GTK_BOX (epg_main_hbox),
renatofilho@20
   148
	                epg_channels_vbox, FALSE, FALSE, 0);
renatofilho@20
   149
    gtk_box_pack_start (GTK_BOX (epg_main_hbox),
renatofilho@20
   150
                        epg_programs_vbox, FALSE, FALSE, 0);
renatofilho@20
   151
renatofilho@20
   152
    /* table header (first line) */  
renatofilho@20
   153
    mmyth_epg_grid_widget_mount_header(mmyth_epg_grid_widget);                 
renatofilho@20
   154
    
renatofilho@20
   155
    /* service programs */ 
renatofilho@20
   156
    /* mount service programs with current time */
renatofilho@20
   157
    mmyth_epg_grid_widget_mount_services(mmyth_epg_grid_widget, 
renatofilho@20
   158
                                         private->current_start_time,
renatofilho@20
   159
                                         private->current_end_time);                                           
renatofilho@20
   160
}
renatofilho@20
   161
renatofilho@20
   162
GtkWidget*
renatofilho@20
   163
mmyth_epg_grid_widget_new ()
renatofilho@20
   164
{
renatofilho@20
   165
  return GTK_WIDGET ( gtk_type_new (mmyth_epg_grid_widget_get_type ()));
renatofilho@20
   166
}
renatofilho@20
   167
renatofilho@20
   168
static void
renatofilho@20
   169
mmyth_epg_grid_widget_mount_services(MMythEpgGridWidget *mmyth_epg_grid_widget, 
renatofilho@20
   170
                                     int start_time, int end_time)
renatofilho@20
   171
{
renatofilho@20
   172
    GList *proglist;
renatofilho@20
   173
    GList *channel_list = NULL;
renatofilho@20
   174
    GMythChannelInfo *channel_info;
renatofilho@20
   175
renatofilho@20
   176
    int chanid;
renatofilho@20
   177
    MMythEpgGridWidgetPrivate *private = 
renatofilho@20
   178
        MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget);
renatofilho@20
   179
	
renatofilho@20
   180
	// update view_model
renatofilho@20
   181
	/* FIXME shallow free or recursive? */
renatofilho@20
   182
	if(mmyth_epg_grid_widget->epg_view_model != NULL) {
renatofilho@20
   183
		g_list_free(mmyth_epg_grid_widget->epg_view_model);
renatofilho@20
   184
		mmyth_epg_grid_widget->epg_view_model = NULL;
renatofilho@20
   185
	}
renatofilho@20
   186
	
renatofilho@20
   187
	if(private->service_model_hash != NULL) {
renatofilho@20
   188
		g_hash_table_destroy(private->service_model_hash);
renatofilho@20
   189
	}
renatofilho@20
   190
renatofilho@20
   191
	private->service_model_hash = g_hash_table_new(NULL, NULL);
renatofilho@20
   192
renatofilho@20
   193
    /* fill program infos from db */
renatofilho@20
   194
    mmyth_epg_grid_widget_fill_programinfos(private);
renatofilho@20
   195
    
renatofilho@20
   196
    channel_list = private->channel_list;
renatofilho@20
   197
 
renatofilho@20
   198
    /* for each channel get_programs() */
renatofilho@20
   199
    for (chanid=0; channel_list &&
renatofilho@20
   200
                   chanid < private->DISPLAY_CHANS; chanid++) {
renatofilho@20
   201
        proglist = (GList *) private->program_list[chanid];        
renatofilho@20
   202
    
renatofilho@20
   203
        channel_info = (GMythChannelInfo *) channel_list->data;
renatofilho@20
   204
        channel_list = g_list_next(channel_list);        
renatofilho@20
   205
renatofilho@20
   206
        /* Service Title*/
renatofilho@20
   207
        GString *name = NULL;
renatofilho@20
   208
        if (channel_info->channel_name)
renatofilho@20
   209
        	name = g_string_new (channel_info->channel_name->str);
renatofilho@20
   210
		
renatofilho@20
   211
		GdkColor title_bg_color;
renatofilho@20
   212
		title_bg_color.red = 5000;
renatofilho@20
   213
		title_bg_color.green = 9000;
renatofilho@20
   214
		title_bg_color.blue = 40000;        
renatofilho@20
   215
		
renatofilho@20
   216
		GdkColor title_fg_color;
renatofilho@20
   217
		title_fg_color.red = 60000;
renatofilho@20
   218
		title_fg_color.green = 60000;
renatofilho@20
   219
		title_fg_color.blue = 60000;        
renatofilho@20
   220
		
renatofilho@20
   221
		GtkWidget *event_box_channel = create_event_box_lbl(
renatofilho@20
   222
                                                        name->str, 90, 
renatofilho@20
   223
									                    &title_bg_color, 
renatofilho@20
   224
									                    &title_fg_color);
renatofilho@20
   225
renatofilho@20
   226
        gtk_box_pack_start (GTK_BOX (private->epg_channels_vbox),
renatofilho@20
   227
		                    event_box_channel, FALSE, FALSE, 0);
renatofilho@20
   228
renatofilho@20
   229
  		GtkWidget *epg_line_hbox = gtk_hbox_new (FALSE, 0);      
renatofilho@20
   230
renatofilho@20
   231
	    GdkColor bg_color;
renatofilho@20
   232
	    bg_color.red = 5000;
renatofilho@20
   233
	    bg_color.green = 30000;
renatofilho@20
   234
	    bg_color.blue = 60000;        
renatofilho@20
   235
	
renatofilho@20
   236
	    GdkColor fg_color;
renatofilho@20
   237
	    fg_color.red = 60000;
renatofilho@20
   238
	    fg_color.green = 60000;
renatofilho@20
   239
	    fg_color.blue = 60000;        
renatofilho@20
   240
		
renatofilho@20
   241
		/* Content parsing */
renatofilho@20
   242
        GList *epg_grid_list = NULL;
renatofilho@20
   243
renatofilho@20
   244
        GMythProgramInfo *proginfo;
renatofilho@20
   245
        int pixel_count = 0;
renatofilho@20
   246
        for (; proglist; proglist = proglist->next) {
renatofilho@20
   247
            proginfo = (GMythProgramInfo *) proglist->data;
renatofilho@20
   248
            
renatofilho@20
   249
            GString *content_name = proginfo->title;
renatofilho@20
   250
                    
renatofilho@20
   251
       	    int initial_time, last_time, duration;
renatofilho@20
   252
renatofilho@20
   253
            int schedule_start_time = proginfo->startts;
renatofilho@20
   254
            int schedule_end_time   = proginfo->endts;
renatofilho@20
   255
renatofilho@20
   256
	        initial_time = 
renatofilho@20
   257
                (schedule_start_time < start_time) ? start_time : schedule_start_time;
renatofilho@20
   258
            last_time = (schedule_end_time > end_time) ? end_time : schedule_end_time;
renatofilho@20
   259
	        duration = last_time - initial_time;
renatofilho@20
   260
		    
renatofilho@20
   261
            // Verify program time 
renatofilho@20
   262
            #if 0
renatofilho@20
   263
			    g_debug ("ServiceID: %d, ScheduleID: %d\n", service->id, schedule->id);
renatofilho@20
   264
                fprintf (stderr, "program time\nfrom = %d, to = %d\n", 
renatofilho@20
   265
                         schedule->validFrom, schedule->validTo); 
renatofilho@20
   266
                
renatofilho@20
   267
                struct tm loctime;
renatofilho@20
   268
    
renatofilho@20
   269
                /* Convert it to local time representation. */
renatofilho@20
   270
                if (localtime_r((time_t *)&schedule->validFrom, &loctime) == NULL) {
renatofilho@20
   271
                    g_warning ("localtime_r error in mmyth_epg_grid_widget!\n");
renatofilho@20
   272
                    return NULL;
renatofilho@20
   273
                }            
renatofilho@20
   274
                fprintf (stderr, asctime (&loctime)); 
renatofilho@20
   275
                
renatofilho@20
   276
                if (localtime_r((time_t *)&schedule->validTo, &loctime) == NULL) {
renatofilho@20
   277
                    g_warning ("localtime_r error in mmyth_epg_grid_widget!\n");
renatofilho@20
   278
                    return NULL;
renatofilho@20
   279
                } 
renatofilho@20
   280
                fprintf (stderr, asctime (&loctime)); 
renatofilho@20
   281
            #endif
renatofilho@20
   282
    		
renatofilho@20
   283
    	    /* fprintf(stderr, "duration = %d\n", duration); */
renatofilho@20
   284
    	    double duration_hour = duration / (double) 3600.0;
renatofilho@20
   285
    	    /* fprintf(stderr, "duration_hour = %lf\n", duration_hour); */
renatofilho@20
   286
    		
renatofilho@20
   287
            int size = PIXELS_HOUR * duration_hour;
renatofilho@20
   288
                
renatofilho@20
   289
            /* complete hour */
renatofilho@20
   290
            /* FIXME: UGLY WRONG HACK TO ALIGN PROGRAM TIME!!!*/
renatofilho@20
   291
            if(last_time%3600 != 0) {
renatofilho@20
   292
                size -= PROGRAM_SEPARATION;                
renatofilho@20
   293
            }
renatofilho@20
   294
            if(initial_time%3600 != 0) {
renatofilho@20
   295
                size -= PROGRAM_SEPARATION;                
renatofilho@20
   296
            }
renatofilho@20
   297
renatofilho@20
   298
            pixel_count += size + PROGRAM_SEPARATION;
renatofilho@20
   299
	        GtkWidget *event_box = create_event_box_lbl(content_name->str, 
renatofilho@20
   300
							  size, &bg_color, 
renatofilho@20
   301
							  &fg_color);
renatofilho@20
   302
							  gtk_widget_add_events(event_box, 
renatofilho@20
   303
							  GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
renatofilho@20
   304
            
renatofilho@20
   305
            /* create EpgGridItem */
renatofilho@20
   306
            EpgGridItem *epg_grid_item = g_new(EpgGridItem, 1);
renatofilho@20
   307
            epg_grid_item->proginfo  = proginfo;
renatofilho@20
   308
            epg_grid_item->event_box = event_box;
renatofilho@20
   309
            epg_grid_item->object    = mmyth_epg_grid_widget;
renatofilho@20
   310
            
renatofilho@20
   311
            epg_grid_list = g_list_prepend(epg_grid_list, (gpointer) epg_grid_item);                                   		                        
renatofilho@20
   312
renatofilho@20
   313
     	    gtk_box_pack_start (GTK_BOX (epg_line_hbox),
renatofilho@20
   314
	                            event_box, FALSE, FALSE, PROGRAM_SEPARATION);
renatofilho@20
   315
	                                 
renatofilho@20
   316
   	        g_signal_connect (G_OBJECT (event_box), "button-press-event",
renatofilho@20
   317
		                      G_CALLBACK (mmyth_epg_grid_widget_clicked), 
renatofilho@20
   318
                              (gpointer*) epg_grid_list);
renatofilho@20
   319
        }
renatofilho@20
   320
#if 0
renatofilho@20
   321
        printf("chaind = %d!!!!" chanid);fflush(stdout);
renatofilho@20
   322
#endif        
renatofilho@20
   323
renatofilho@20
   324
        if(!epg_grid_list) {
renatofilho@20
   325
            /* No programs for current channel */
renatofilho@20
   326
            /* FIXME: size HARDCODED */
renatofilho@20
   327
            GtkWidget *event_box = create_event_box_lbl("No program list available",
renatofilho@20
   328
                              PIXELS_HOUR * 3, &bg_color,
renatofilho@20
   329
                              &fg_color);
renatofilho@20
   330
                              gtk_widget_add_events(event_box,
renatofilho@20
   331
                              GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
renatofilho@20
   332
renatofilho@20
   333
            /* create EpgGridItem */
renatofilho@20
   334
            EpgGridItem *epg_grid_item = g_new(EpgGridItem, 1);
renatofilho@20
   335
            epg_grid_item->proginfo  = NULL;
renatofilho@20
   336
            epg_grid_item->event_box = event_box;
renatofilho@20
   337
            epg_grid_item->object    = mmyth_epg_grid_widget;
renatofilho@20
   338
renatofilho@20
   339
            epg_grid_list = g_list_prepend(epg_grid_list, (gpointer) epg_grid_item);
renatofilho@20
   340
            
renatofilho@20
   341
            gtk_box_pack_start (GTK_BOX (epg_line_hbox),
renatofilho@20
   342
	                            event_box, FALSE, FALSE, PROGRAM_SEPARATION);            	
renatofilho@20
   343
	                                 
renatofilho@20
   344
   	        g_signal_connect (G_OBJECT (event_box), "button-press-event",
renatofilho@20
   345
		                      G_CALLBACK (mmyth_epg_grid_widget_clicked),
renatofilho@20
   346
                              (gpointer*) epg_grid_list);
renatofilho@20
   347
        }
renatofilho@20
   348
renatofilho@20
   349
        epg_grid_list = g_list_reverse(epg_grid_list);
renatofilho@20
   350
        mmyth_epg_grid_widget->epg_view_model = 
renatofilho@20
   351
              g_list_append(mmyth_epg_grid_widget->epg_view_model, epg_grid_list);
renatofilho@20
   352
        
renatofilho@20
   353
	    gtk_box_pack_start (GTK_BOX (private->epg_programs_vbox),
renatofilho@20
   354
	                        epg_line_hbox, FALSE, FALSE,  0);                    		    		
renatofilho@20
   355
    }
renatofilho@20
   356
}
renatofilho@20
   357
renatofilho@20
   358
static void
renatofilho@20
   359
mmyth_epg_grid_widget_mount_header(MMythEpgGridWidget *mmyth_epg_grid_widget)
renatofilho@20
   360
{	          	    
renatofilho@20
   361
    MMythEpgGridWidgetPrivate *private = 
renatofilho@20
   362
        MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget);
renatofilho@20
   363
    
renatofilho@20
   364
    struct tm hour_tm;
renatofilho@20
   365
    const gchar name_title[] = "Today";    
renatofilho@20
   366
    GtkWidget * lbl_title = gtk_label_new(name_title);
renatofilho@20
   367
renatofilho@20
   368
    gtk_misc_set_alignment (GTK_MISC(lbl_title), 0.0, 0.5);
renatofilho@20
   369
    
renatofilho@20
   370
    gtk_box_pack_start (GTK_BOX (private->epg_channels_vbox),
renatofilho@20
   371
                        lbl_title, FALSE, FALSE, 0);
renatofilho@20
   372
renatofilho@20
   373
	/* hours title line */
renatofilho@20
   374
    GtkWidget *epg_programs_hours_hbox = gtk_hbox_new (TRUE, 0); 
renatofilho@20
   375
renatofilho@20
   376
    if (localtime_r((time_t *)&private->current_start_time, &hour_tm) == NULL) {
renatofilho@20
   377
        g_warning ("localtime_r error in mmyth_epg_grid_widget!\n");
renatofilho@20
   378
        return NULL;
renatofilho@20
   379
    }    
renatofilho@20
   380
renatofilho@20
   381
    if (hour_tm.tm_min>30) {
renatofilho@20
   382
        hour_tm.tm_min = 30;
renatofilho@20
   383
    } else if (hour_tm.tm_min>0) {
renatofilho@20
   384
        hour_tm.tm_min = 0;
renatofilho@20
   385
    }
renatofilho@20
   386
        
renatofilho@20
   387
    gchar hour1_str[10];
renatofilho@20
   388
    strftime(hour1_str, 8, "%H:%M", &hour_tm);
renatofilho@20
   389
    GtkWidget * lbl_hour1 = gtk_label_new(hour1_str);
renatofilho@20
   390
    gtk_misc_set_alignment (GTK_MISC(lbl_hour1), 0.0, 0.5);    
renatofilho@20
   391
	
renatofilho@20
   392
    hour_tm.tm_hour++;
renatofilho@20
   393
    gchar hour2_str[10];    
renatofilho@20
   394
    strftime(hour2_str, 8, "%H:%M", &hour_tm);
renatofilho@20
   395
    GtkWidget * lbl_hour2 = gtk_label_new(hour2_str);
renatofilho@20
   396
    gtk_misc_set_alignment (GTK_MISC(lbl_hour2), 0.0, 0.5);        
renatofilho@20
   397
renatofilho@20
   398
    hour_tm.tm_hour++;
renatofilho@20
   399
	gchar hour3_str[10];    
renatofilho@20
   400
    strftime(hour3_str, 8, "%H:%M", &hour_tm);
renatofilho@20
   401
    GtkWidget * lbl_hour3 = gtk_label_new(hour3_str);
renatofilho@20
   402
    gtk_misc_set_alignment (GTK_MISC(lbl_hour3), 0.0, 0.5);        
renatofilho@20
   403
    
renatofilho@20
   404
    gtk_box_pack_start (GTK_BOX (epg_programs_hours_hbox),
renatofilho@20
   405
                        lbl_hour1, TRUE, TRUE, 0);                    
renatofilho@20
   406
    gtk_box_pack_start (GTK_BOX (epg_programs_hours_hbox),
renatofilho@20
   407
                        lbl_hour2, TRUE, TRUE, 0);                    
renatofilho@20
   408
    gtk_box_pack_start (GTK_BOX (epg_programs_hours_hbox),
renatofilho@20
   409
                        lbl_hour3, TRUE, TRUE, 0); 
renatofilho@20
   410
 
renatofilho@20
   411
    gtk_box_pack_start (GTK_BOX (private->epg_programs_vbox),
renatofilho@20
   412
                        epg_programs_hours_hbox, FALSE, FALSE, 0);                        
renatofilho@20
   413
}
renatofilho@20
   414
renatofilho@20
   415
/******************************************************************************
renatofilho@20
   416
 *              INTERNAL CALLBACKS FOR STATE CHANGE                           *
renatofilho@20
   417
 *****************************************************************************/
renatofilho@20
   418
static void 
renatofilho@20
   419
mmyth_epg_grid_widget_deselect_service(MMythEpgGridWidget *mmyth_epg_grid_widget)
renatofilho@20
   420
{
renatofilho@20
   421
	EpgGridItem *epg_grid_item;
renatofilho@20
   422
	
renatofilho@20
   423
  	/* deselect*/
renatofilho@20
   424
    if(mmyth_epg_grid_widget->selected_grid_item != NULL) {
renatofilho@20
   425
    	epg_grid_item = 
renatofilho@20
   426
            (EpgGridItem*) mmyth_epg_grid_widget->selected_grid_item->data;
renatofilho@20
   427
    	gtk_widget_set_state(GTK_WIDGET(epg_grid_item->event_box), GTK_STATE_NORMAL);
renatofilho@20
   428
    }            
renatofilho@20
   429
}
renatofilho@20
   430
renatofilho@20
   431
static void 
renatofilho@20
   432
mmyth_epg_grid_widget_clicked (GtkWidget* widget, 
renatofilho@20
   433
                               GdkEventExpose *event, gpointer data)
renatofilho@20
   434
{           
renatofilho@20
   435
    g_return_if_fail(data != NULL);
renatofilho@20
   436
renatofilho@20
   437
    GList *epg_grid_item_list = (GList *) data;
renatofilho@20
   438
    EpgGridItem *epg_grid_item = (EpgGridItem *) epg_grid_item_list->data;
renatofilho@20
   439
renatofilho@20
   440
    /* update the selected service */
renatofilho@20
   441
    mmyth_epg_grid_widget_update_service( epg_grid_item->object, (GList*) data );       
renatofilho@20
   442
}
renatofilho@20
   443
renatofilho@20
   444
void
renatofilho@20
   445
mmyth_epg_grid_widget_update_service(MMythEpgGridWidget * object,
renatofilho@20
   446
                                     GList *selected_grid_list)
renatofilho@20
   447
{
renatofilho@20
   448
    g_return_if_fail(object != NULL);
renatofilho@20
   449
    g_return_if_fail(selected_grid_list != NULL);
renatofilho@20
   450
		
renatofilho@20
   451
	EpgGridItem *epg_grid_item = (EpgGridItem *) selected_grid_list->data;
renatofilho@20
   452
renatofilho@20
   453
    mmyth_epg_grid_widget_deselect_service(epg_grid_item->object);
renatofilho@20
   454
renatofilho@20
   455
    /* updating current selected schedule_item and schedule_list*/
renatofilho@20
   456
    object->selected_grid_item = selected_grid_list;
renatofilho@20
   457
    
renatofilho@20
   458
    /* set state of the event box */
renatofilho@20
   459
    gtk_widget_set_state(GTK_WIDGET(epg_grid_item->event_box), GTK_STATE_SELECTED);
renatofilho@20
   460
    /* emit update signal for listeners */
renatofilho@20
   461
    g_signal_emit(object, 
renatofilho@20
   462
                  mmyth_epg_grid_widget_signals[SELECTION_UPDATED_SIGNAL],
renatofilho@20
   463
                  0,
renatofilho@20
   464
                  (gpointer) epg_grid_item);
renatofilho@20
   465
}
renatofilho@20
   466
renatofilho@20
   467
static GtkWidget * 
renatofilho@20
   468
create_event_box_lbl(gchar *str, int width, const GdkColor *bg_color, 
renatofilho@20
   469
                     const GdkColor *fg_color) 
renatofilho@20
   470
{
renatofilho@20
   471
    GtkWidget *event_box = gtk_event_box_new();
renatofilho@20
   472
	GtkWidget *lbl = gtk_label_new(str);
renatofilho@20
   473
    gtk_label_set_ellipsize(GTK_LABEL(lbl), PANGO_ELLIPSIZE_END);
renatofilho@20
   474
renatofilho@20
   475
    gtk_widget_modify_bg(event_box, GTK_STATE_NORMAL, bg_color);    
renatofilho@20
   476
    gtk_widget_modify_fg(lbl, GTK_STATE_NORMAL, fg_color);    
renatofilho@20
   477
    
renatofilho@20
   478
    /* selected colors are const*/
renatofilho@20
   479
    GdkColor selected_bg_color;
renatofilho@20
   480
    selected_bg_color.red = 100;
renatofilho@20
   481
    selected_bg_color.green = 40000;
renatofilho@20
   482
    selected_bg_color.blue = 100;        
renatofilho@20
   483
renatofilho@20
   484
    GdkColor selected_fg_color;
renatofilho@20
   485
    selected_fg_color.red = 100;
renatofilho@20
   486
    selected_fg_color.green = 100;
renatofilho@20
   487
    selected_fg_color.blue = 100;        
renatofilho@20
   488
            
renatofilho@20
   489
    gtk_widget_modify_bg(event_box, GTK_STATE_SELECTED, &selected_bg_color);    
renatofilho@20
   490
    gtk_widget_modify_fg(lbl, GTK_STATE_SELECTED, &selected_fg_color);    
renatofilho@20
   491
    
renatofilho@20
   492
    gtk_misc_set_alignment (GTK_MISC(lbl), 0.0, 0.5);    
renatofilho@20
   493
	gtk_container_add (GTK_CONTAINER (event_box),
renatofilho@20
   494
                       lbl);
renatofilho@20
   495
	gtk_widget_set_size_request(event_box, width, -1);
renatofilho@20
   496
	                       
renatofilho@20
   497
    return event_box;
renatofilho@20
   498
}
renatofilho@20
   499
renatofilho@20
   500
/******************************************************************************
renatofilho@20
   501
 *                            METHODS                                         *
renatofilho@20
   502
 *****************************************************************************/
renatofilho@20
   503
renatofilho@20
   504
/* Callback for hardware keys */
renatofilho@20
   505
gboolean
renatofilho@20
   506
mmyth_epg_grid_widget_key_press (MMythEpgGridWidget * object, 
renatofilho@20
   507
                                 GtkWidget * widget, GdkEventKey * event)
renatofilho@20
   508
{
renatofilho@20
   509
    MMythEpgGridWidgetPrivate *private = 
renatofilho@20
   510
        MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(object);
renatofilho@20
   511
  
renatofilho@20
   512
    EpgGridItem *epg_grid_item;
renatofilho@20
   513
    GList *tmp;
renatofilho@20
   514
    
renatofilho@20
   515
    /* List of selected_grid_item */
renatofilho@20
   516
    GList *selected_view_model;
renatofilho@20
   517
    
renatofilho@20
   518
    gint channel_index;
renatofilho@20
   519
    
renatofilho@20
   520
	if(object->selected_grid_item == NULL) {
renatofilho@20
   521
        g_warning ("No program selected");
renatofilho@20
   522
	    return FALSE;
renatofilho@20
   523
	} 
renatofilho@20
   524
    
renatofilho@20
   525
    epg_grid_item = (EpgGridItem*) object->selected_grid_item->data;    
renatofilho@20
   526
    
renatofilho@20
   527
    channel_index = private->selected_channel_index;
renatofilho@20
   528
    
renatofilho@20
   529
    switch (event->keyval) {
renatofilho@20
   530
        case GDK_Up:        
renatofilho@20
   531
            selected_view_model = g_list_nth( object->epg_view_model, channel_index - 1 );
renatofilho@20
   532
            if(selected_view_model != NULL) {
renatofilho@20
   533
                private->selected_channel_index = channel_index - 1;
renatofilho@20
   534
   	            tmp = (GList *) selected_view_model->data;               
renatofilho@20
   535
                /* TODO: select a better centralized item 
renatofilho@20
   536
                   currently is picking the 1st or last item */
renatofilho@20
   537
                if(g_list_next(object->selected_grid_item) == NULL &&
renatofilho@20
   538
                   g_list_previous(object->selected_grid_item) != NULL) {
renatofilho@20
   539
                    /* in this case the new selected will be the last */ 
renatofilho@20
   540
                    tmp = g_list_last(tmp);
renatofilho@20
   541
                }
renatofilho@20
   542
renatofilho@20
   543
	            /* update the selected service */
renatofilho@20
   544
                mmyth_epg_grid_widget_update_service( object, tmp );
renatofilho@20
   545
            }    
renatofilho@20
   546
        return TRUE;         
renatofilho@20
   547
        case GDK_Down:
renatofilho@20
   548
            selected_view_model = g_list_nth( object->epg_view_model, channel_index + 1 );            
renatofilho@20
   549
            if(selected_view_model != NULL) {   	            
renatofilho@20
   550
                private->selected_channel_index = channel_index + 1;
renatofilho@20
   551
   	            tmp = (GList *) selected_view_model->data;
renatofilho@20
   552
                /* TODO: select a better centralized item 
renatofilho@20
   553
                   currently is picking the 1st or last item */
renatofilho@20
   554
                if(g_list_next(object->selected_grid_item) == NULL &&
renatofilho@20
   555
                   g_list_previous(object->selected_grid_item) != NULL) {
renatofilho@20
   556
                    /* in this case the new selected will be the last */ 
renatofilho@20
   557
                    tmp = g_list_last(tmp);
renatofilho@20
   558
                }
renatofilho@20
   559
renatofilho@20
   560
	            /* update the selected service */
renatofilho@20
   561
                mmyth_epg_grid_widget_update_service( object, tmp );
renatofilho@20
   562
            }
renatofilho@20
   563
        return TRUE;        
renatofilho@20
   564
        case GDK_Left:    
renatofilho@20
   565
            tmp = g_list_previous( object->selected_grid_item );
renatofilho@20
   566
            if(tmp != NULL) {
renatofilho@20
   567
	            /* update the selected service */
renatofilho@20
   568
                mmyth_epg_grid_widget_update_service( object, tmp );
renatofilho@20
   569
            }
renatofilho@20
   570
        return TRUE;        
renatofilho@20
   571
        case GDK_Right:
renatofilho@20
   572
            tmp = g_list_next( object->selected_grid_item );
renatofilho@20
   573
            if(tmp != NULL) {
renatofilho@20
   574
	            /* update the selected service */
renatofilho@20
   575
                mmyth_epg_grid_widget_update_service( object, tmp );
renatofilho@20
   576
            }
renatofilho@20
   577
        return TRUE;        
renatofilho@20
   578
	    default:
renatofilho@20
   579
	    return TRUE;
renatofilho@20
   580
    }
renatofilho@20
   581
    
renatofilho@20
   582
    return FALSE;
renatofilho@20
   583
}
renatofilho@20
   584
renatofilho@20
   585
static void 
renatofilho@20
   586
mmyth_epg_grid_widget_fill_programinfos (MMythEpgGridWidgetPrivate *private)
renatofilho@20
   587
{
renatofilho@20
   588
    GList *channels_list = NULL;
renatofilho@20
   589
    int y;
renatofilho@20
   590
renatofilho@20
   591
    if ((private->mmyth_epg != NULL) &&
renatofilho@20
   592
	   	(gmyth_epg_get_channel_list (private->mmyth_epg, &channels_list) < 0 )) {
renatofilho@20
   593
			private->channel_list = NULL;
renatofilho@20
   594
			return;
renatofilho@20
   595
    }
renatofilho@20
   596
    
renatofilho@20
   597
    private->channel_list = channels_list;
renatofilho@20
   598
    
renatofilho@20
   599
    for (y = 0; y < private->DISPLAY_CHANS && channels_list; y++) {
renatofilho@20
   600
        GMythChannelInfo *channel_info = (GMythChannelInfo *) channels_list->data;
renatofilho@20
   601
renatofilho@20
   602
        mmyth_epg_grid_widget_fill_program_row_infos(
renatofilho@20
   603
                            private, channel_info->channel_ID, y);
renatofilho@20
   604
renatofilho@20
   605
        channels_list = g_list_next (channels_list);
renatofilho@20
   606
    }
renatofilho@20
   607
}
renatofilho@20
   608
renatofilho@20
   609
static void 
renatofilho@20
   610
mmyth_epg_grid_widget_fill_program_row_infos(MMythEpgGridWidgetPrivate *private,
renatofilho@20
   611
                                             guint chanNum, guint row)
renatofilho@20
   612
{    
renatofilho@20
   613
    gint res =  gmyth_epg_get_program_list (private->mmyth_epg,
renatofilho@20
   614
    					&(private->program_list[row]),
renatofilho@20
   615
                        chanNum, private->current_start_time, 
renatofilho@20
   616
                        private->current_end_time);
renatofilho@20
   617
                        
renatofilho@20
   618
    if (res < 0) {
renatofilho@20
   619
    	g_warning ("[%s] Error while retrieving epg programs", __FUNCTION__);
renatofilho@20
   620
    }
renatofilho@20
   621
}
renatofilho@20
   622