Statistics
| Branch: | Revision:

chunker-player / chunker_player / chunker_player.c @ 0cd6b05d

History | View | Annotate | Download (17.7 KB)

1
/*
2
 *  Copyright (c) 2009-2011 Carmelo Daniele, Dario Marchese, Diego Reforgiato, Giuseppe Tropea
3
 *  developed for the Napa-Wine EU project. See www.napa-wine.eu
4
 *
5
 *  This is free software; see lgpl-2.1.txt
6
 */
7

    
8
#include <stdio.h>
9
#include <unistd.h>
10
#include <SDL.h>
11
#include <SDL_mutex.h>
12
#include "player_defines.h"
13
#include <confuse.h>
14
#include "http_default_urls.h"
15
#include "player_defines.h"
16
#include "chunker_player.h"
17
#include "player_gui.h"
18
#include <time.h>
19
#include <getopt.h>
20
#include <napa_log.h>
21

    
22
#define MANDATORY_PARAMS 3
23
#define OPTIONAL_PARAMS 1
24

    
25
#ifdef _WIN32
26
#include <windows.h>
27
#endif
28

    
29
int ReadALine(FILE* fp, char* Output, int MaxOutputSize)
30
{
31
    int i=0;
32
    int c;
33
    do
34
    {
35
        c=getc(fp);
36
        if(c=='\r' || c=='\n' || c==EOF)
37
        {
38
            Output[i]=0;
39
            return i;
40
        }
41
        Output[i++]=c;
42
    }
43
    while(c!=EOF);
44
    
45
    return -1;
46
}
47

    
48
void CheckForRepoAddress(char* Param)
49
{
50
    char* pch;
51
    if(strncasecmp(Param,"repo_address=",13)==0)
52
    {
53
        pch=strtok(Param+13,",");
54
        strncpy(RepoAddress,pch,2048);
55
    }
56
}
57

    
58
void sigproc()
59
{
60
        printf("you have pressed ctrl-c, terminating...\n");
61
        quit = 1;
62
}
63

    
64
static void print_usage(int argc, char *argv[])
65
{
66
  fprintf (stderr,
67
    "\nUsage:%s [options]\n"
68
    "\n"
69
    "Mandatory options:\n"
70
    "\t[-q q_thresh]: playout queue size\n"
71
    "\t[-c ChannelName]: channel name (from channels.conf)\n"
72
    "\t[-p port]: player http port\n\n"
73
    "Other options:\n"
74
    "\t[-t]: log traces (WARNING: old traces will be deleted).\n"
75
    "\t[-s mode]: silent mode (no GUI) (mode=1 audio ON, mode=2 audio OFF, mode=3 audio OFF; P2P OFF).\n\n"
76
    "=======================================================\n", argv[0]
77
    );
78
}
79

    
80
int main(int argc, char *argv[])
81
{
82
        srand ( time(NULL) );
83
        // some initializations
84
        SilentMode = 0;
85
        queue_filling_threshold = 0;
86
        quit = 0;
87
        QueueFillingMode=1;
88
        LogTraces = 0;
89
        repoclient=NULL;
90
        LastTimeRepoPublish.tv_sec=0;
91
        LastTimeRepoPublish.tv_usec=0;
92
        
93
        napaInitLog(LOG_DEBUG, NULL, NULL);
94
    repInit("");
95

    
96
        
97
#ifndef __WIN32__
98
        static pid_t fork_pid = -1;
99
        P2PProcessHandle=&fork_pid;
100
#else
101
        static PROCESS_INFORMATION ProcessInfo;
102
        ZeroMemory( &ProcessInfo, sizeof(ProcessInfo) );
103
        P2PProcessHandle=&ProcessInfo;
104
#endif
105

    
106
        NChannels = 0;
107
        SelectedChannel = -1;
108
        char firstChannelName[255];
109
        int firstChannelIndex;
110
        
111
        memset((void*)Channels, 0, (MAX_CHANNELS_NUM*sizeof(SChannel)));
112

    
113
#ifdef HTTPIO
114
        HttpPort = -1;
115
#endif
116
#ifdef TCPIO
117
        TcpPort = -1;
118
#endif
119
        struct MHD_Daemon *daemon = NULL;
120
        SDL_Event event;
121
        OverlayMutex = SDL_CreateMutex();
122
        int mandatories = 0;
123
        
124
        char c;
125
        while ((c = getopt (argc, argv, "q:c:p:s:t")) != -1)
126
        {
127
                switch (c) {
128
                        case 0: //for long options
129
                                break;
130
                        case 'q':
131
                                sscanf(optarg, "%d", &queue_filling_threshold);
132
                                mandatories++;
133
                                break;
134
                        case 'c':
135
                                sprintf(firstChannelName, "%s", optarg);
136
                                mandatories++;
137
                                break;
138
                        case 'p':
139
#ifdef HTTPIO
140
                                sscanf(optarg, "%d", &HttpPort);
141
#endif
142
#ifdef TCPIO
143
                                sscanf(optarg, "%d", &TcpPort);
144
#endif
145
                                mandatories++;
146
                                break;
147
                        case 's':
148
                                sscanf(optarg, "%d", &SilentMode);
149
                                break;
150
                        case 't':
151
                                DELETE_DIR("traces");
152
                                CREATE_DIR("traces");
153
                                LogTraces = 1;
154
                                break;
155
                        default:
156
                                print_usage(argc, argv);
157
                                return -1;
158
                }
159
        }
160
        if(mandatories < MANDATORY_PARAMS)
161
        {
162
                print_usage(argc, argv);
163
                return -1;
164
        }
165

    
166
#ifdef EMULATE_CHUNK_LOSS
167
        ScheduledChunkLosses = NULL;
168
        cfg_opt_t scheduled_chunk_loss_opts[] =
169
        {
170
                CFG_INT("Time", 0, CFGF_NONE),
171
                CFG_INT("Value", 0, CFGF_NONE),
172
                CFG_INT("MinValue", 0, CFGF_NONE),
173
                CFG_INT("MaxValue", 0, CFGF_NONE),
174
                CFG_INT("Burstiness", 0, CFGF_NONE),
175
                CFG_END()
176
        };
177
        cfg_opt_t opts[] =
178
        {
179
                CFG_SEC("ScheduledChunkLoss", scheduled_chunk_loss_opts, CFGF_MULTI),
180
                CFG_END()
181
        };
182
        cfg_t *cfg, *cfg_sched;
183
        cfg = cfg_init(opts, CFGF_NONE);
184
        if(!cfg_parse(cfg, "_chunklossrate.conf") == CFG_PARSE_ERROR)
185
        {
186
                NScheduledChunkLosses = cfg_size(cfg, "ScheduledChunkLoss");
187
                if(NScheduledChunkLosses > 0)
188
                        ScheduledChunkLosses = (SChunkLoss*)malloc((NScheduledChunkLosses)*sizeof(SChunkLoss));
189
                
190
                int j;
191
                for(j = 0; j < cfg_size(cfg, "ScheduledChunkLoss"); j++)
192
                {
193
                        cfg_sched = cfg_getnsec(cfg, "ScheduledChunkLoss", j);
194
                        ScheduledChunkLosses[j].Time = cfg_getint(cfg_sched, "Time");
195
                        ScheduledChunkLosses[j].Value = cfg_getint(cfg_sched, "Value");
196
                        ScheduledChunkLosses[j].Burstiness = cfg_getint(cfg_sched, "Burstiness");
197
                        
198
                        // -1 means random value between min and max
199
                        if(ScheduledChunkLosses[j].Value == -1)
200
                        {
201
                                ScheduledChunkLosses[j].MinValue = cfg_getint(cfg_sched, "MinValue");
202
                                ScheduledChunkLosses[j].MaxValue = cfg_getint(cfg_sched, "MaxValue");
203
                        }
204
                }
205
                cfg_free(cfg);
206
                CurrChunkLossIndex = -1;
207
                
208
                for(j=0; j < NScheduledChunkLosses; j++)
209
                {
210
                        printf("ScheduledChunkLosses[%d].Time = %ld\n", j, ScheduledChunkLosses[j].Time);
211
                        printf("ScheduledChunkLosses[%d].Value = %d\n", j, ScheduledChunkLosses[j].Value);
212
                        printf("ScheduledChunkLosses[%d].Burstiness = %d\n", j, ScheduledChunkLosses[j].Burstiness);
213
                }
214
        }
215
#endif
216

    
217
#ifdef HTTPIO
218
        //this thread fetches chunks from the network by listening to the following path, port
219
        daemon = (struct MHD_Daemon*)initChunkPuller(UL_DEFAULT_EXTERNALPLAYER_PATH, HttpPort);
220
        if(daemon == NULL)
221
        {
222
                printf("CANNOT START MICROHTTPD SERVICE, EXITING...\n");
223
                exit(2);
224
        }
225
#endif
226
#ifdef TCPIO
227
        int fd = initChunkPuller(TcpPort);
228
        if(! (fd > 0))
229
        {
230
                printf("CANNOT START TCP PULLER...\n");
231
                exit(2);
232
        }
233
#endif
234

    
235
        if(SilentMode == 0)
236
        {
237
                if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
238
                        fprintf(stderr, "Could not initialize SDL audio/video or timer - %s\n", SDL_GetError());
239
                        return -1;
240
                }
241
        }
242
        else if(SilentMode == 1)
243
        {
244
                if(SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
245
                        fprintf(stderr, "Could not initialize SDL audio or timer - %s\n", SDL_GetError());
246
                        return -1;
247
                }
248
        }
249
        else
250
        {
251
                if(SDL_Init(SDL_INIT_TIMER)) {
252
                        fprintf(stderr, "Could not initialize SDL timer - %s\n", SDL_GetError());
253
                        return -1;
254
                }
255
        }
256
        
257
        if(ParseConf())
258
        {
259
                printf("ERROR: Cannot parse configuration file, exit...\n");
260
                exit(1);
261
        }
262
        
263
        firstChannelIndex = -1;
264
        int it;
265
        for(it = 0; it < NChannels; it++)
266
        {
267
                if(!strcmp(Channels[it].Title, firstChannelName))
268
                {
269
                        firstChannelIndex = it;
270
                        break;
271
                }
272
        }
273
        
274
        if(firstChannelIndex < 0)
275
        {
276
                printf("Cannot find the specified channel (%s) into the configuration file (channels.conf), exiting\n", firstChannelName);
277
                exit(0);
278
        }
279
        
280
        if(ChunkerPlayerGUI_Init())
281
        {
282
                printf("ERROR: Cannot init player gui, exit...\n");
283
                exit(1);
284
        }
285
        
286
        SelectedChannel = firstChannelIndex;
287

    
288
        SwitchChannel(&(Channels[SelectedChannel]));
289

    
290
        // Wait for user input
291
        while(!quit) {
292
                if(QueueFillingMode) {
293
                        SDL_WM_SetCaption("Filling buffer...", NULL);
294

    
295
                        if(ChunkerPlayerCore_AudioEnded())
296
                                ChunkerPlayerCore_ResetAVQueues();
297

    
298
#ifdef DEBUG_QUEUE
299
                        //printf("QUEUE: MAIN audio:%d video:%d audiolastframe:%d videolastframe:%d\n", audioq.nb_packets, videoq.nb_packets, audioq.last_frame_extracted, videoq.last_frame_extracted);
300
#endif
301
                }
302
                else
303
                        SDL_WM_SetCaption("NAPA-Wine Player", NULL);
304

    
305
                //listen for key and mouse
306
                while(SDL_PollEvent(&event)) {
307
                        switch(event.type) {
308
                                case SDL_QUIT:
309
                                        quit=1;
310
                                break;
311
                                case SDL_VIDEORESIZE:
312
                                        if(SilentMode)
313
                                                break;
314
                                        // printf("\tSDL_VIDEORESIZE event received!! \n");
315
                                        if(!FullscreenMode)
316
                                                ChunkerPlayerGUI_HandleResize(event.resize.w, event.resize.h);
317
                                        else
318
                                                ChunkerPlayerGUI_HandleResize(FullscreenWidth, FullscreenHeight);
319
                                break;
320
                                case SDL_ACTIVEEVENT:
321
                                        if(SilentMode)
322
                                                break;
323
                                                
324
                                        // if the window was iconified or restored
325
                                        if(event.active.state & SDL_APPACTIVE)
326
                                        {
327
                                                //If the application is being reactivated
328
                                                if( event.active.gain != 0 )
329
                                                {
330
                                                        ChunkerPlayerGUI_HandleGetFocus();
331
                                                }
332
                                        }
333

    
334
                                        //If something happened to the keyboard focus
335
                                        else if( event.active.state & SDL_APPINPUTFOCUS )
336
                                        {
337
                                                //If the application gained keyboard focus
338
                                                if( event.active.gain != 0 )
339
                                                {
340
                                                        ChunkerPlayerGUI_HandleGetFocus();
341
                                                }
342
                                        }
343
                                        //If something happened to the mouse focus
344
                                        else if( event.active.state & SDL_APPMOUSEFOCUS )
345
                                        {
346
                                                //If the application gained mouse focus
347
                                                if( event.active.gain != 0 )
348
                                                {
349
                                                        ChunkerPlayerGUI_HandleGetFocus();
350
                                                }
351
                                        }
352
                                        break;
353
                                case SDL_MOUSEMOTION:
354
                                        if(SilentMode)
355
                                                break;
356
                                                
357
                                        ChunkerPlayerGUI_HandleMouseMotion(event.motion.x, event.motion.y);
358
                                break;
359
                                case SDL_MOUSEBUTTONUP:
360
                                        if(SilentMode)
361
                                                break;
362
                                                
363
                                        if( event.button.button != SDL_BUTTON_LEFT )
364
                                                break;
365

    
366
                                        ChunkerPlayerGUI_HandleLButton(event.motion.x, event.motion.y);
367
                                break;
368
                        }
369
                        ChunkerPlayerGUI_HandleKey();
370
                }
371
                usleep(120000);
372
        }
373

    
374
        KILL_PROCESS(P2PProcessHandle);
375

    
376
        //TERMINATE
377
        ChunkerPlayerCore_Stop();
378
        if(YUVOverlay != NULL)
379
                SDL_FreeYUVOverlay(YUVOverlay);
380
        
381
        ChunkerPlayerGUI_Close();
382
        SDL_DestroyMutex(OverlayMutex);
383
        SDL_Quit();
384
        
385
#ifdef HTTPIO
386
        finalizeChunkPuller(daemon);
387
#endif
388
#ifdef TCPIO
389
        finalizeChunkPuller();
390
#endif
391
        
392
#ifdef EMULATE_CHUNK_LOSS
393
        if(ScheduledChunkLosses)
394
                free(ScheduledChunkLosses);
395
#endif
396
        return 0;
397
}
398

    
399
int cb_validate_conffile(cfg_t *cfg)
400
{
401
        char LaunchString[255];
402
        cfg_t *cfg_greet;
403
        
404
        if(cfg_size(cfg, "Channel") == 0)
405
        {
406
                cfg_error(cfg, "no \"Channel\" section found");
407
                return -1;
408
        }
409
        
410
        printf("\t%d Channel setions found\n", cfg_size(cfg, "Channel"));
411
        
412
        int j;
413
        for(j = 0; j < cfg_size(cfg, "Channel"); j++)
414
        {
415
                cfg_greet = cfg_getnsec(cfg, "Channel", j);
416
                sprintf(LaunchString, "%s", cfg_getstr(cfg_greet, "LaunchString"));
417
                if(!(strlen(LaunchString) > 0))
418
                {
419
                        cfg_error(cfg, "invalid LaunchString for Channel[%d]", j);
420
                        return -1;
421
                }
422
                printf("\tChannel[%d].LaunchString = %s\n", j, LaunchString);
423
                printf("\tChannel[%d].AudioChannels = %ld\n", j, cfg_getint(cfg_greet, "AudioChannels"));
424
                printf("\tChannel[%d].SampleRate = %ld\n", j, cfg_getint(cfg_greet, "SampleRate"));
425
                printf("\tChannel[%d].Width = %ld\n", j, cfg_getint(cfg_greet, "Width"));
426
                printf("\tChannel[%d].Height = %ld\n", j, cfg_getint(cfg_greet, "Height"));
427
                printf("\tChannel[%d].Bitrate = %ld\n", j, cfg_getint(cfg_greet, "Bitrate"));
428
                printf("\tChannel[%d].Ratio = %s\n", j, cfg_getstr(cfg_greet, "Ratio"));
429
        }
430
    return 0;
431
}
432

    
433
int ParseConf()
434
{
435
        int j;
436
        
437
        // PARSING CONF FILE
438
        cfg_opt_t channel_opts[] =
439
        {
440
                CFG_STR("Title", "", CFGF_NONE),
441
                CFG_STR("LaunchString", "", CFGF_NONE),
442
                CFG_INT("AudioChannels", 2, CFGF_NONE),
443
                CFG_INT("SampleRate", 48000, CFGF_NONE),
444
                CFG_INT("Width", 176, CFGF_NONE),
445
                CFG_INT("Height", 144, CFGF_NONE),
446
                CFG_INT("Bitrate", 0, CFGF_NONE),
447
                
448
                // for some reason libconfuse parsing for floating point does not work in windows
449
                //~ CFG_FLOAT("Ratio", 1.22, CFGF_NONE),
450
                CFG_STR("Ratio", "1.22", CFGF_NONE),
451
                CFG_END()
452
        };
453
        cfg_opt_t opts[] =
454
        {
455
                CFG_SEC("Channel", channel_opts, CFGF_TITLE | CFGF_MULTI),
456
                CFG_END()
457
        };
458
        cfg_t *cfg, *cfg_channel;
459
        cfg = cfg_init(opts, CFGF_NONE);
460
        if(cfg_parse(cfg, DEFAULT_CONF_FILENAME) == CFG_PARSE_ERROR)
461
        {
462
                printf("Error while parsing configuration file, exiting...\n");
463
                cb_validate_conffile(cfg);
464
                return 1;
465
        }
466
        
467
        if(cfg_parse(cfg, DEFAULT_CONF_FILENAME) == CFG_FILE_ERROR)
468
        {
469
                printf("Error trying parsing configuration file. '%s' file couldn't be opened for reading\n", DEFAULT_CONF_FILENAME);
470
                return 1;
471
        }
472
        
473
        FILE * tmp_file;
474
        if(tmp_file = fopen(DEFAULT_PEEREXECNAME_FILENAME, "r")) {
475
                if(fscanf(tmp_file, "%s", StreamerFilename) != 1) {
476
                        printf("Wrong format of conf file %s containing peer application exec name. Assuming default: %s.\n\n", DEFAULT_PEEREXECNAME_FILENAME, DEFAULT_PEER_EXEC_NAME);
477
                }
478
                fclose(tmp_file);
479
        }
480
        else {
481
                printf("Could not find conf file %s containing peer application exec name. Exiting.\n\n", DEFAULT_PEEREXECNAME_FILENAME);
482
                exit(1);
483
        }
484
        if(tmp_file = fopen(StreamerFilename, "r"))
485
    {
486
        fclose(tmp_file);
487
    }
488
    else
489
        {
490
                printf("Could not find peer application (named '%s') into the current folder, please copy or link it into the player folder, then retry\n\n", StreamerFilename);
491
                exit(1);
492
        }
493
        
494
        for(j = 0; j < cfg_size(cfg, "Channel"); j++)
495
        {
496
                cfg_channel = cfg_getnsec(cfg, "Channel", j);
497
                sprintf(Channels[j].Title, "%s", cfg_title(cfg_channel));
498
                strcpy(Channels[j].LaunchString, cfg_getstr(cfg_channel, "LaunchString"));
499
                Channels[j].Width = cfg_getint(cfg_channel, "Width");
500
                Channels[j].Height = cfg_getint(cfg_channel, "Height");
501
                Channels[j].AudioChannels = cfg_getint(cfg_channel, "AudioChannels");
502
                Channels[j].SampleRate = cfg_getint(cfg_channel, "SampleRate");
503
                Channels[j].Ratio = strtof(cfg_getstr(cfg_channel, "Ratio"), 0);
504
                Channels[j].Bitrate = cfg_getint(cfg_channel, "Bitrate");
505
                
506
                Channels[j].Index = j+1;
507
                NChannels++;
508
        }
509
        cfg_free(cfg);
510

    
511
        return 0;
512
}
513

    
514
int ReTune(SChannel* channel)
515
{        
516
        if(ChunkerPlayerCore_IsRunning())
517
                ChunkerPlayerCore_Pause();
518
        
519
        //reset quality info
520
        channel->startTime = time(NULL);
521
        
522
        ChunkerPlayerCore_Play();
523
        
524
        return 0;
525
}
526

    
527
int SwitchChannel(SChannel* channel)
528
{
529
        int i=0;
530
#ifdef RESTORE_SCREEN_ON_ZAPPING
531
        int was_fullscreen = FullscreenMode;
532
        int old_width = window_width, old_height = window_height;
533
#endif
534
        
535
        if(ChunkerPlayerCore_IsRunning())
536
                ChunkerPlayerCore_Stop();
537

    
538
    KILL_PROCESS(P2PProcessHandle);
539
        remove("NetworkID");
540
        
541
        ratio = channel->Ratio;
542
        ChunkerPlayerGUI_SetChannelTitle(channel->Title);
543
        ChunkerPlayerGUI_ForceResize(channel->Width, channel->Height);
544
        
545
        int w=0, h=0;
546
        ChunkerPlayerGUI_AspectRatioResize((float)channel->Ratio, channel->Width, channel->Height, &w, &h);
547
        ChunkerPlayerCore_SetupOverlay(w, h);
548
        //ChunkerPlayerGUI_SetupOverlayRect(channel);
549
        
550
        if(ChunkerPlayerCore_InitCodecs(channel->Width, channel->Height, channel->SampleRate, channel->AudioChannels) < 0)
551
        {
552
                printf("ERROR, COULD NOT INITIALIZE CODECS\n");
553
                exit(2);
554
        }
555
        
556
        //reset quality info
557
        channel->startTime = time(NULL);
558
        channel->instant_score = 0.0;
559
        channel->average_score = 0.0;
560
        channel->history_index = 0;
561
        for(i=0; i<CHANNEL_SCORE_HISTORY_SIZE; i++)
562
                channel->score_history[i] = -1;
563
        sprintf(channel->quality, "EVALUATING...");
564
        
565
        if(SilentMode != 3) //mode 3 is without P2P peer process
566
        {
567
                char argv0[255], parameters_string[511];
568
                sprintf(argv0, "%s", StreamerFilename);
569

    
570
#ifdef HTTPIO
571
                sprintf(parameters_string, "%s %s %s %d %s %s %d", "-C", channel->Title, "-P", (HttpPort+channel->Index), channel->LaunchString, "-F", HttpPort);
572
#endif
573

    
574
#ifdef TCPIO
575
                sprintf(parameters_string, "%s %s %s %d %s %s 127.0.0.1:%d", "-C", channel->Title, "-P", (TcpPort+channel->Index), channel->LaunchString, "-F", TcpPort);
576
#endif
577

    
578
                printf("OFFERSTREAMER LAUNCH STRING: %s %s\n", argv0, parameters_string);
579

    
580

    
581
                char* parameters_vector[255];
582
                parameters_vector[0] = argv0;
583
                
584
                // split parameters and count them
585
                int par_count=1;
586
                char* pch = strtok (parameters_string, " ");
587
                while (pch != NULL)
588
                {
589
                        if(par_count > 255) break;
590
                        // printf ("\tpch=%s\n",pch);
591
                        parameters_vector[par_count] = (char*) malloc(sizeof(char)*(strlen(pch)+1));
592
                        strcpy(parameters_vector[par_count], pch);
593
                        // Find repo_address
594
                        CheckForRepoAddress(parameters_vector[par_count]);
595
                        pch = strtok (NULL, " ");
596
                        par_count++;
597
                }
598
                parameters_vector[par_count] = NULL;
599
                
600
#ifndef __WIN32__
601
                int d;
602
                int stdoutS, stderrS;
603
                FILE* stream;
604
                stream = fopen("/dev/null", "a+");
605
                d = fileno(stream);
606

    
607
                // create backup descriptors for the current stdout and stderr devices
608
                stdoutS = dup(STDOUT_FILENO);
609
                stderrS = dup(STDERR_FILENO);
610
                
611
                // redirect child output to /dev/null
612
                dup2(d, STDOUT_FILENO);
613
                dup2(d, STDERR_FILENO);
614

    
615
                int pid = fork();
616
                if(pid == 0)
617
                {
618
                        execv(argv0, parameters_vector);
619
                        printf("ERROR, COULD NOT LAUNCH OFFERSTREAMER\n");
620
                        exit(2);
621
                }
622
                else
623
                        *((pid_t*)P2PProcessHandle) = pid;
624
                
625
                // restore backup descriptors in the parent process
626
                dup2(stdoutS, STDOUT_FILENO);
627
                dup2(stderrS, STDERR_FILENO);
628
                
629
                for(i=1; i<par_count; i++)
630
                        free(parameters_vector[i]);
631
                        
632
                fclose(stream);
633

    
634
#ifdef RESTORE_SCREEN_ON_ZAPPING
635
                if(was_fullscreen)
636
                        ChunkerPlayerGUI_ToggleFullscreen();
637
                else
638
                {
639
                        ChunkerPlayerGUI_HandleResize(old_width, old_height);
640
                }
641
#endif
642
        
643
#else
644

    
645
                STARTUPINFO sti;
646
                SECURITY_ATTRIBUTES sats = { 0 };
647
                DWORD writ, excode, read, available;
648
                int ret = 0;
649

    
650
                //set SECURITY_ATTRIBUTES struct fields
651
                sats.nLength = sizeof(sats);
652
                sats.bInheritHandle = TRUE;
653
                sats.lpSecurityDescriptor = NULL;
654

    
655
                ZeroMemory( &sti, sizeof(sti) );
656
                sti.cb = sizeof(sti);
657
                ZeroMemory( P2PProcessHandle, sizeof(PROCESS_INFORMATION) );
658

    
659
                char buffer[512];
660
                sprintf(buffer, "%s %s", argv0, parameters_string);
661

    
662
                if(!CreateProcess(NULL,
663
                  buffer,
664
                  &sats,
665
                  &sats,
666
                  TRUE,
667
                  0,
668
                  NULL,
669
                  NULL,
670
                  &sti,
671
                  P2PProcessHandle))
672
                {
673
                        printf("Unable to generate process \n");
674
                        return -1;
675
                }
676
#endif
677

    
678
        // Open Repository
679
        if(repoclient) repClose(repoclient);
680
        repoclient=NULL;
681
            
682
            repoclient = repOpen(RepoAddress,0);
683
            //if (repoclient == NULL) fatal("Unable to initialize repoclient");
684
        }
685
        // Read the Network ID
686
        int Error=true;
687
        char Line1[255], Line2[255];
688
        while(Error)
689
        {
690
            FILE* fp=fopen("NetworkID","r");
691
            if(fp)
692
            {
693
                if(ReadALine(fp,Line1,255)!=-1)
694
                    if(ReadALine(fp,Line2,255)!=-1)
695
                    {
696
                        if(strcmp(Line2,"IDEnd")==0)
697
                        {
698
                            strcpy(NetworkID,Line1);
699
                            Error=false;
700
                        }
701
                    }
702
                fclose(fp);
703
            }
704
            if(Error) usleep(100000);
705
        }
706
        
707
        printf("NetworkID = %s\n",NetworkID);
708
        
709
        ChunkerPlayerCore_Play();
710
        ChunkerPlayerGUI_ChannelSwitched();
711
        return 0;
712
}
713

    
714
void ZapDown()
715
{
716
        SelectedChannel = ((SelectedChannel+1) %NChannels);
717
        SwitchChannel(&(Channels[SelectedChannel]));
718
}
719

    
720
void ZapUp()
721
{
722
        SelectedChannel--;
723
        if(SelectedChannel < 0)
724
                SelectedChannel = NChannels-1;
725

    
726
        SwitchChannel(&(Channels[SelectedChannel]));
727
}
728

    
729
int enqueueBlock(const uint8_t *block, const int block_size)
730
{
731
        return ChunkerPlayerCore_EnqueueBlocks(block, block_size);
732
}