~ubuntu-branches/ubuntu/saucy/vdr-plugin-live/saucy-proposed

« back to all changes in this revision

Viewing changes to pages/multischedule.ecpp

  • Committer: Package Import Robot
  • Author(s): Tobias Grimm
  • Date: 2012-01-15 10:22:53 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20120115102253-hixwx4gbcpyhtt2m
Tags: 0.2.0+git20120114-1
* New Upstream Snapshot (commit d2a85a6) (Closes: #654879)
* Dropped 02_timers_colon patch - fixed upstream
* Dropped 04_tntnet-2.0.patch - fixed upstream
* Dropped 01_ipv6.patch - fixed upstream
* Dropped 03_live-0.2.0-fix-INCLUDES.patch - fixed upstream
* Build-depend on libpcre3-dev
* Updated debian/copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<%pre>
 
2
#include <list>
 
3
#include <vdr/plugin.h>
 
4
#include <vdr/channels.h>
 
5
#include <vdr/epg.h>
 
6
#include <vdr/config.h>
 
7
#include <vdr/device.h>
 
8
#include "exception.h"
 
9
#include "livefeatures.h"
 
10
#include "setup.h"
 
11
#include "tools.h"
 
12
#include "timers.h"
 
13
#include "epg_events.h"
 
14
#include "i18n.h"
 
15
 
 
16
using namespace std;
 
17
using namespace vdrlive;
 
18
 
 
19
struct SchedEntry {
 
20
        string title;
 
21
        string short_description;
 
22
        string description;
 
23
        string description_trunc;
 
24
        string start;
 
25
        string end;
 
26
        string day;
 
27
        string epgid;
 
28
        bool truncated;
 
29
        bool has_timer;
 
30
        int start_row;
 
31
        int row_count;
 
32
};
 
33
 
 
34
        std::string channel_groups_setting;
 
35
        std::vector<std::string> channel_groups_names;
 
36
        std::vector< std::vector<int> > channel_groups_numbers;
 
37
        std::vector<std::string> times_names;
 
38
        std::vector<time_t>      times_start;
 
39
</%pre>
 
40
<%args>
 
41
        int channel = -1;
 
42
        unsigned int time_para = 0;
 
43
</%args>
 
44
<%session scope="global">
 
45
bool logged_in(false);
 
46
</%session>
 
47
<%request scope="page">
 
48
        unsigned int channel_group=0;
 
49
        unsigned int time_selected=0;
 
50
</%request>
 
51
<%include>page_init.eh</%include>
 
52
<%cpp>
 
53
if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 
54
pageTitle = tr("MultiSchedule");
 
55
 
 
56
        ReadLock channelsLock( Channels );
 
57
        if ( !channelsLock )
 
58
                throw HtmlError( tr("Couldn't aquire access to channels, please try again later.") );
 
59
 
 
60
#define MAX_CHANNELS 10 
 
61
#define MAX_DAYS 3
 
62
#define MAX_HOURS 8
 
63
#define MINUTES_PER_ROW 5
 
64
#define CHARACTERS_PER_ROW 30
 
65
 
 
66
    if ( ( channel_groups_setting.compare(LiveSetup().GetChannelGroups()) != 0 ) || ( channel_groups_numbers.size() == 0 ) )
 
67
    {
 
68
        // build the groups of channels to display
 
69
        std::string channelGroups=LiveSetup().GetChannelGroups();
 
70
        if ( channelGroups.empty() )
 
71
        {
 
72
            // setup default channel groups
 
73
           int lastChannel = LiveSetup().GetLastChannel();
 
74
           if ( lastChannel == 0 )
 
75
               lastChannel = Channels.MaxNumber();
 
76
           std::stringstream groups;
 
77
           int i = 0;
 
78
           for (cChannel *channel = Channels.First(); channel && (channel->Number() <= lastChannel); channel = Channels.Next(channel))
 
79
           {
 
80
               if (channel->GroupSep())
 
81
                   continue;
 
82
               groups << channel->Number();
 
83
               if ( (++i % 5) == 0 )
 
84
                   groups << ";";
 
85
               else
 
86
                   groups << ",";
 
87
           }
 
88
           channelGroups = groups.str();
 
89
           LiveSetup().SetChannelGroups( channelGroups );
 
90
        }
 
91
        channel_groups_names.clear();
 
92
        channel_groups_numbers.clear();
 
93
        channel_groups_setting = channelGroups;
 
94
        size_t groupSep;
 
95
        std::string thisGroup = "";
 
96
        while ( ! channelGroups.empty() )
 
97
        {
 
98
            groupSep = channelGroups.find(';');
 
99
            thisGroup = channelGroups.substr(0, groupSep );
 
100
            if ( groupSep != channelGroups.npos )
 
101
                channelGroups.erase(0, groupSep+1 );
 
102
            else
 
103
                channelGroups="";
 
104
 
 
105
            int cur_group_count=0;
 
106
            channel_groups_names.push_back( std::string() );
 
107
            channel_groups_numbers.push_back( std::vector<int>() );
 
108
            while ( !thisGroup.empty() )
 
109
            {
 
110
                std::string thisChannel;
 
111
                try {
 
112
                    if ( cur_group_count != 0 )
 
113
                        channel_groups_names.back() += std::string( " - " );
 
114
                    size_t channelSep = thisGroup.find(',');
 
115
                    thisChannel = thisGroup.substr(0, channelSep );
 
116
                    if ( channelSep != thisGroup.npos )
 
117
                        thisGroup.erase( 0, channelSep+1 );
 
118
                    else 
 
119
                        thisGroup = "";
 
120
                    int channel_no = lexical_cast< int > (thisChannel);
 
121
                    cChannel* Channel = Channels.GetByNumber( channel_no );
 
122
                    if ( !Channel )
 
123
                    {
 
124
                        esyslog("Live: could not find channel no '%s'.", thisChannel.c_str() );
 
125
                        continue;
 
126
                    }
 
127
                    channel_groups_names.back() += std::string( Channel->Name() );
 
128
                    channel_groups_numbers.back().push_back( Channel->Number() );
 
129
                    cur_group_count++;
 
130
                    if ( cur_group_count>=MAX_CHANNELS )
 
131
                    {
 
132
                        // start new group if group gets too large
 
133
                        cur_group_count=0;
 
134
                        channel_groups_names.push_back( std::string() );
 
135
                        channel_groups_numbers.push_back( std::vector<int>() );
 
136
                    }
 
137
                }
 
138
                catch ( const bad_lexical_cast & )
 
139
                {
 
140
                    esyslog("Live: could not convert '%s' into a channel number", thisChannel.c_str());
 
141
                    continue;
 
142
                }
 
143
            }
 
144
        }
 
145
    }
 
146
        if ( channel < 0 ) {
 
147
                if (cDevice::CurrentChannel()) {
 
148
            // find group corresponding to current channel
 
149
            int curGroup =0;
 
150
                        int curChannel = cDevice::CurrentChannel();
 
151
            for ( std::vector< std::vector<int> >::iterator grIt = channel_groups_numbers.begin();
 
152
                  grIt != channel_groups_numbers.end() && channel < 0; ++grIt, ++curGroup )
 
153
            {
 
154
                for ( std::vector<int>::iterator chIt = (*grIt).begin();
 
155
                       chIt != (*grIt).end() && channel < 0; ++ chIt )
 
156
                {
 
157
                    if ( *chIt == curChannel )
 
158
                        channel_group = channel = curGroup;
 
159
                }
 
160
            }
 
161
            // if nothing is found, fall back to group 0
 
162
            if ( channel < 0 )
 
163
                channel = 0;
 
164
                }
 
165
                else {
 
166
            channel_group = channel;
 
167
                }
 
168
        }
 
169
 
 
170
        if ( channel >= (int)channel_groups_numbers.size() )
 
171
          channel = 0;
 
172
        channel_group = channel;
 
173
{
 
174
    // build time list
 
175
    times_names.clear();
 
176
    times_start.clear();
 
177
    
 
178
    // calculate time of midnight (localtime) and convert back to GMT
 
179
    time_t now = (time(NULL)/3600)*3600;
 
180
    time_t now_local = time(NULL);
 
181
    struct tm tm_r;
 
182
    if ( localtime_r( &now_local, &tm_r ) == 0 ) {
 
183
        ostringstream builder;
 
184
        builder << "cannot represent timestamp " << now_local << " as local time";
 
185
        throw runtime_error( builder.str() );
 
186
    }
 
187
    tm_r.tm_hour=0;
 
188
    tm_r.tm_min=0;
 
189
    tm_r.tm_sec=0;
 
190
    time_t midnight = mktime( &tm_r );
 
191
 
 
192
    // add four 8h steps per day to the time list
 
193
    for (int i=0; i<4*MAX_DAYS ; i++ )
 
194
    {
 
195
        times_start.push_back( midnight + MAX_HOURS*3600*i );
 
196
    }
 
197
    vector< string > parts = StringSplit( LiveSetup().GetTimes(), ';' );
 
198
    vector< time_t > offsets;
 
199
    vector< string >::const_iterator part = parts.begin();
 
200
    for ( ; part != parts.end(); ++part ) 
 
201
    {
 
202
        try {
 
203
            unsigned int sep = (*part).find(':');
 
204
            std::string hour = (*part).substr(0, sep );
 
205
            if ( sep == (*part).npos )
 
206
            {
 
207
                esyslog("Live: Error parsing time '%s'", (*part).c_str() );
 
208
                continue;
 
209
            }
 
210
            std::string min = (*part).substr(sep+1, (*part).npos );
 
211
            offsets.push_back( lexical_cast<time_t>( hour )*60*60 + lexical_cast<time_t>( min ) *60 );
 
212
        }
 
213
        catch ( const bad_lexical_cast & ) {
 
214
            esyslog("Live: Error parsing time '%s'", part->c_str() );
 
215
        };
 
216
    };
 
217
    // add the time of the favourites to the time list
 
218
    for (int i=0; i< MAX_DAYS ; i++ )
 
219
    {
 
220
        vector< time_t >::const_iterator offset = offsets.begin();
 
221
        for ( ; offset != offsets.end(); ++offset ) 
 
222
        {
 
223
            times_start.push_back( midnight + 24*3600*i + *offset );
 
224
        }
 
225
    }
 
226
    // add now
 
227
    times_start.push_back( now );
 
228
    // sort the times
 
229
    std::sort( times_start.begin(), times_start.end() );
 
230
    // delete every time which has already passed
 
231
    while ( *times_start.begin()< now )
 
232
        times_start.erase(times_start.begin() );
 
233
 
 
234
    // build the corresponding names
 
235
    for ( vector< time_t >::const_iterator start = times_start.begin();
 
236
          start != times_start.end(); ++start ) 
 
237
    {
 
238
        times_names.push_back(FormatDateTime( tr("%A, %x"), *start)
 
239
                              +std::string(" ")+ FormatDateTime( tr("%I:%M %p"), *start) );
 
240
    }
 
241
    // the first time is now
 
242
    times_names[0]=tr("Now");
 
243
 
 
244
    if ( time_para >= times_names.size() )
 
245
        time_para = times_names.size()-1;
 
246
    time_selected=time_para;
 
247
}
 
248
</%cpp>
 
249
<& pageelems.doc_type &>
 
250
<html>
 
251
        <head>
 
252
                <title>VDR Live - <$ pageTitle $></title>
 
253
                <& pageelems.stylesheets &>
 
254
                <& pageelems.ajax_js &>
 
255
        </head>
 
256
        <body>
 
257
                <& pageelems.logo &>
 
258
                <& menu active=("multischedule") component=("multischedule.channel_selection") &>
 
259
                <div class="inhalt">
 
260
<%cpp>
 
261
        cSchedulesLock schedulesLock;
 
262
        cSchedules const* schedules = cSchedules::Schedules( schedulesLock );
 
263
       
 
264
        time_t now = time(NULL);
 
265
        if ( time_para >= times_start.size() )
 
266
            time_para = times_start.size()-1;
 
267
        time_t sched_start = (times_start[ time_para ]/300)*300; 
 
268
        time_t max_hours;
 
269
        try {
 
270
          max_hours = lexical_cast<time_t>( LiveSetup().GetScheduleDuration() );
 
271
        }
 
272
        catch ( const bad_lexical_cast & )
 
273
        {
 
274
          esyslog("Live: could not convert '%s' into a schedule duration", LiveSetup().GetScheduleDuration().c_str());
 
275
          max_hours = 8;
 
276
        };
 
277
        if (max_hours > 48)
 
278
            max_hours = 48;
 
279
 
 
280
        time_t sched_end = sched_start + 60 * 60 * max_hours;
 
281
        int sched_end_row = ( sched_end - sched_start ) / 60 / MINUTES_PER_ROW;
 
282
        std::list<SchedEntry> table[MAX_CHANNELS];
 
283
        std::vector<std::string> channel_names(channel_groups_numbers[ channel ].size() );
 
284
        std::vector<tChannelID> channel_IDs(channel_groups_numbers[ channel ].size() );
 
285
        if ( channel >= (int)channel_groups_numbers.size() )
 
286
          channel = channel_groups_numbers.size()-1;
 
287
        //for ( int chan = 0; chan<MAX_CHANNELS; chan++)
 
288
        for ( unsigned int j = 0; j<channel_groups_numbers[ channel ].size(); j++)
 
289
        {
 
290
          int prev_row = -1;
 
291
 
 
292
 
 
293
          int chan = channel_groups_numbers[ channel ][ j ];
 
294
 
 
295
          cChannel* Channel = Channels.GetByNumber( chan );
 
296
          if ( ! Channel )
 
297
            continue;
 
298
          if ( Channel->GroupSep() || Channel->Name() == '\0' )
 
299
            continue;
 
300
          channel_names[ j ] = Channel->Name();
 
301
          channel_IDs[ j ] = Channel->GetChannelID();
 
302
 
 
303
          cSchedule const* Schedule = schedules->GetSchedule( Channel );
 
304
          if ( ! Schedule )
 
305
            continue;
 
306
          for (const cEvent *Event = Schedule->Events()->First(); Event; 
 
307
               Event = Schedule->Events()->Next(Event) ) 
 
308
          {
 
309
            if (Event->EndTime() <= sched_start )
 
310
              continue;
 
311
            if (Event->StartTime() >= sched_end )
 
312
              continue;
 
313
 
 
314
            EpgInfoPtr epgEvent = EpgEvents::CreateEpgInfo(Channel, Event);
 
315
            if ( prev_row < 0 && Event->StartTime() > sched_start + MINUTES_PER_ROW )
 
316
            {
 
317
              // insert dummy event at start
 
318
              table[ j ].push_back( SchedEntry() );
 
319
              SchedEntry &en=table[ j ].back();
 
320
              int event_start_row = (Event->StartTime() - sched_start) / 60 / MINUTES_PER_ROW;
 
321
              en.start_row = 0;
 
322
              en.row_count = event_start_row;
 
323
              // no title and no start time = dummy event
 
324
              en.title = "";
 
325
              en.start = "";
 
326
              prev_row = en.start_row + en.row_count;
 
327
            }
 
328
            table[ j ].push_back( SchedEntry() );
 
329
            SchedEntry &en=table[j].back();
 
330
 
 
331
            en.title = epgEvent->Title();
 
332
            en.short_description = epgEvent->ShortDescr();
 
333
            en.description = epgEvent->LongDescr();
 
334
            en.start = epgEvent->StartTime(tr("%I:%M %p"));
 
335
            en.end = epgEvent->EndTime(tr("%I:%M %p"));
 
336
            en.day = epgEvent->StartTime(tr("%A, %b %d %Y"));
 
337
            en.epgid = EpgEvents::EncodeDomId(Channel->GetChannelID(), Event->EventID());
 
338
            en.has_timer = LiveTimerManager().GetTimer(Event->EventID(), Channel->GetChannelID() ) != 0;
 
339
 
 
340
            en.start_row = prev_row > 0 ? prev_row : 0;
 
341
            int end_time = Schedule->Events()->Next(Event) ? 
 
342
              Schedule->Events()->Next(Event)->StartTime() :
 
343
              Event->EndTime();
 
344
            if (end_time > sched_end)
 
345
                end_time = sched_end;
 
346
            int next_event_start_row = (end_time - sched_start) / 60 / MINUTES_PER_ROW;
 
347
            en.row_count = next_event_start_row - en.start_row;
 
348
            if ( en.row_count < 1 )
 
349
              en.row_count = 1;
 
350
            prev_row = en.start_row + en.row_count;
 
351
 
 
352
            // truncate description if too long
 
353
            en.truncated=false;
 
354
            en.description_trunc=StringWordTruncate( en.description,
 
355
                                                     CHARACTERS_PER_ROW*(en.row_count-2),
 
356
                                                     en.truncated );
 
357
 
 
358
 
 
359
 
 
360
          };
 
361
          if ( table[ j ].begin() == table[ j ].end() )
 
362
          {
 
363
            // no entries... create a single dummy entry       
 
364
            table[ j ].push_back( SchedEntry() );
 
365
            SchedEntry &en=table[ j ].back();
 
366
            en.start_row = 0;
 
367
            en.row_count = sched_end_row;
 
368
            // no title and no start time = dummy event
 
369
            en.title = "";
 
370
            en.start = "";
 
371
          }
 
372
        }
 
373
</%cpp>
 
374
                <table class="mschedule" cellspacing="0" cellpadding="0">
 
375
<%cpp>
 
376
</%cpp>
 
377
               <tr class=" topaligned ">
 
378
               <td > <div class="boxheader"> <div><div><$ tr("Time") $></div></div> </div></td>
 
379
               <td class="time spacer"> &nbsp; </td>
 
380
<%cpp>
 
381
                for ( unsigned int channel = 0; channel< channel_names.size() ; channel++)
 
382
                {
 
383
</%cpp>
 
384
               <td> <div class="boxheader"> <div> <div><$ channel_names[channel] $> <# reply.sout() automatically escapes special characters to html entities #>
 
385
            <& pageelems.ajax_action_href action="switch_channel" tip=(tr("Switch to this channel.")) param=(channel_IDs[channel]) image="zap.png" alt="" &>
 
386
            <& pageelems.vlc_stream_channel channelId=(channel_IDs[channel]) &>
 
387
            </div></div> </div></td>
 
388
               <td class="time spacer"> &nbsp; </td>
 
389
<%cpp>
 
390
                }
 
391
</%cpp>
 
392
               </tr>
 
393
<%cpp>
 
394
                bool odd=true;
 
395
                std::list<SchedEntry>::iterator  cur_event[ MAX_CHANNELS ];
 
396
                for (int i=0;i<MAX_CHANNELS;i++)
 
397
                        cur_event[i]=table[i].begin();
 
398
                for (int row = 0 ; row < sched_end_row; row++ )
 
399
                {
 
400
                       int minutes= ( (sched_start +  row * 60 * MINUTES_PER_ROW ) % 3600 ) / 60;
 
401
                       string row_class;
 
402
                       if ( minutes < MINUTES_PER_ROW )
 
403
                       {
 
404
                         // full hour, swap odd/even
 
405
                         odd = !odd;
 
406
                       };
 
407
                       if (  (sched_start +  row * 60 * MINUTES_PER_ROW ) <= now &&
 
408
                             (sched_start +  (row+1) * 60 * MINUTES_PER_ROW ) > now )
 
409
                       {
 
410
                         row_class +=" current_row ";
 
411
                       }
 
412
                       row_class += odd ? " odd " : " even ";
 
413
 
 
414
</%cpp>
 
415
                       <tr>
 
416
                       <td class=" time leftcol rightcol <$ row_class $>">
 
417
<%cpp>
 
418
                        if (  minutes < MINUTES_PER_ROW )
 
419
                        {
 
420
</%cpp>
 
421
                       <$ FormatDateTime( tr("%I:%M %p"), sched_start +  row * 60 * MINUTES_PER_ROW )  $>
 
422
<%cpp>
 
423
                        }
 
424
                        else
 
425
                        {
 
426
</%cpp>
 
427
                         &nbsp;
 
428
<%cpp>
 
429
                        }       
 
430
</%cpp>
 
431
                       </td>
 
432
<%cpp>
 
433
                        for ( unsigned int channel = 0; channel< channel_names.size() ; channel++)
 
434
                        {
 
435
                                // output spacer column
 
436
</%cpp>
 
437
                                <td class = " time spacer " > &nbsp; </td>
 
438
<%cpp>
 
439
                                if ( cur_event[channel] == table[channel].end() 
 
440
                                     || cur_event[channel]->start_row != row )
 
441
                                  // no new event in this channel, skip it
 
442
                                  continue;
 
443
                                
 
444
                                SchedEntry &en=*cur_event[channel];
 
445
                                if (en.title.empty() && en.start.empty() )
 
446
                                {
 
447
                                  // empty dummy event
 
448
</%cpp>
 
449
                        <td class="event topaligned leftcol rightcol" rowspan="<$ en.row_count $>">
 
450
                        </td>
 
451
<%cpp>
 
452
                                  ++cur_event[channel];
 
453
                                  continue;
 
454
                                        
 
455
                                }
 
456
                                // output an event cell
 
457
</%cpp>
 
458
                        <td class="event topaligned leftcol rightcol <$ en.has_timer ? "has_timer" : "" $>" rowspan="<$ en.row_count $>">
 
459
                        <div class=" content1 " >
 
460
                        <div class=" tools1 " >
 
461
                          <& pageelems.event_timer epgid=(en.epgid) &>
 
462
<%cpp>
 
463
                           if (LiveFeatures<features::epgsearch>().Recent() ) { 
 
464
</%cpp>
 
465
                          <a href="searchresults.html?searchplain=<$ StringUrlEncode(en.title) $>"><img src="<$ LiveSetup().GetThemedLink("img", "search.png") $>" alt="" <& tooltip.hint text=(tr("Search for repeats.")) &>></img></a>
 
466
<%cpp> 
 
467
                           } else { 
 
468
                             </%cpp><img src="img/transparent.png" width="16" height="16"><%cpp> 
 
469
                           }
 
470
</%cpp>
 
471
                          <& pageelems.imdb_info_href title=(en.title) &>
 
472
                         </div><div class= "start withmargin"><$ en.start $></div>
 
473
                          <div class="title withmargin"><a <& tooltip.hint text=(StringEscapeAndBreak(tr("Click to view details."))) &><& tooltip.display domId=en.epgid &>><$ en.title $></a></div>
 
474
<%cpp>
 
475
                         if ( en.row_count>2 && !en.short_description.empty() ) 
 
476
                         {
 
477
</%cpp>
 
478
                          <div class="short withmargin"><$ en.short_description.empty() ? "&nbsp;" : en.short_description $></div>
 
479
<%cpp>
 
480
                         }
 
481
                         if ( en.row_count>3 && ! en.description_trunc.empty() )
 
482
                         {
 
483
</%cpp>
 
484
                          <div class="description withmargin"><$en.description_trunc$>...
 
485
<%cpp>
 
486
                           if ( en.truncated )
 
487
                           {
 
488
</%cpp>
 
489
                           <a <& tooltip.hint text=(StringEscapeAndBreak(tr("Click to view details."))) &><& tooltip.display domId=en.epgid &>> <$ tr("more") $></a>
 
490
<%cpp>
 
491
                           }
 
492
</%cpp>
 
493
                           </div>
 
494
<%cpp>
 
495
                         }
 
496
</%cpp>
 
497
                          </div></div>
 
498
                          </td>
 
499
<%cpp>
 
500
                          // move to next event for this channel
 
501
                          ++cur_event[channel];
 
502
                        }
 
503
</%cpp>
 
504
                       </tr>
 
505
<%cpp>
 
506
                }
 
507
</%cpp>
 
508
                        <tr>
 
509
<%cpp>
 
510
                        for ( unsigned int channel = 0; channel <= channel_names.size() ; channel++)
 
511
                        {
 
512
</%cpp>
 
513
                        <td class = " event leftcol rightcol bottomrow " > &nbsp; </td>
 
514
                        <td class = " time spacer " > &nbsp; </td>
 
515
<%cpp>
 
516
                        }
 
517
</%cpp>
 
518
                        </tr>
 
519
                        </table>
 
520
                </div>
 
521
        </body>
 
522
</html>
 
523
<%include>page_exit.eh</%include>
 
524
 
 
525
<%def channel_selection>
 
526
<form action="multischedule.html" method="get" id="channels">
 
527
   <span>
 
528
     <label for="channel"><$ tr("Channel") $>:&nbsp;<span class="bold"></span></label>
 
529
     <select name="channel" id="channel"  onchange="document.forms.channels.submit()" >
 
530
%       for ( unsigned int i = 0; i < channel_groups_names.size(); ++i ) {
 
531
%
 
532
                <option value="<$ i $>"
 
533
%                      if ( i == channel_group )
 
534
%                      {
 
535
                        selected="selected"
 
536
%                      }
 
537
                        ><$ channel_groups_names[i] $></option>
 
538
%       }
 
539
     </select>
 
540
     <label for="time_para"><$ tr("Time") $>:&nbsp;<span class="bold"></span></label>
 
541
     <select name="time_para" id="time_para"  onchange="document.forms.channels.submit()" >
 
542
%       for ( unsigned int i = 0; i < times_names.size(); ++i ) {
 
543
%
 
544
                <option value="<$ i $>"
 
545
%                      if ( i == time_selected )
 
546
%                      {
 
547
                        selected="selected"
 
548
%                      }
 
549
                        ><$ times_names[i] $></option>
 
550
%       }
 
551
     </select>
 
552
% //     <& pageelems.ajax_action_href action="switch_channel" tip=(tr("Switch to this channel.")) param=(Channel->GetChannelID()) image="zap.png" alt="" &>
 
553
% //     <& pageelems.vlc_stream_channel channelId=(Channel->GetChannelID()) &>
 
554
   </span>
 
555
</form>
 
556
</%def>