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