Statistics
| Branch: | Revision:

chunker-player / chunker_player / chunker_player.c @ 74564eb3

History | View | Annotate | Download (16.9 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

    
21
#define MANDATORY_PARAMS 3
22
#define OPTIONAL_PARAMS 1
23

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

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

    
47
void sigproc()
48
{
49
        printf("you have pressed ctrl-c, terminating...\n");
50
        quit = 1;
51
}
52

    
53
static void print_usage(int argc, char *argv[])
54
{
55
  fprintf (stderr,
56
    "\nUsage:%s [options]\n"
57
    "\n"
58
    "Mandatory options:\n"
59
    "\t[-q q_thresh]: playout queue size\n"
60
    "\t[-c ChannelName]: channel name (from channels.conf)\n"
61
    "\t[-p port]: player http port\n\n"
62
    "Other options:\n"
63
    "\t[-t]: log traces (WARNING: old traces will be deleted).\n"
64
    "\t[-s mode]: silent mode (mode=1 no user gui and no audio, mode=2 audio only, mode=3 only gui and no P2P).\n\n"
65
    "=======================================================\n", argv[0]
66
    );
67
}
68

    
69
int main(int argc, char *argv[])
70
{
71
        srand ( time(NULL) );
72
        // some initializations
73
        SilentMode = 0;
74
        queue_filling_threshold = 0;
75
        quit = 0;
76
        QueueFillingMode=1;
77
        LogTraces = 0;
78

    
79
#ifndef __WIN32__
80
        static pid_t fork_pid = -1;
81
        P2PProcessHandle=&fork_pid;
82
#else
83
        static PROCESS_INFORMATION ProcessInfo;
84
        ZeroMemory( &ProcessInfo, sizeof(ProcessInfo) );
85
        P2PProcessHandle=&ProcessInfo;
86
#endif
87

    
88
        NChannels = 0;
89
        SelectedChannel = -1;
90
        char firstChannelName[255];
91
        int firstChannelIndex;
92
        
93
        memset((void*)Channels, 0, (MAX_CHANNELS_NUM*sizeof(SChannel)));
94

    
95
#ifdef HTTPIO
96
        HttpPort = -1;
97
#endif
98
#ifdef TCPIO
99
        TcpPort = -1;
100
#endif
101
        struct MHD_Daemon *daemon = NULL;
102
        SDL_Event event;
103
        OverlayMutex = SDL_CreateMutex();
104
        int mandatories = 0;
105
        
106
        char c;
107
        while ((c = getopt (argc, argv, "q:c:p:s:t")) != -1)
108
        {
109
                switch (c) {
110
                        case 0: //for long options
111
                                break;
112
                        case 'q':
113
                                sscanf(optarg, "%d", &queue_filling_threshold);
114
                                mandatories++;
115
                                break;
116
                        case 'c':
117
                                sprintf(firstChannelName, "%s", optarg);
118
                                mandatories++;
119
                                break;
120
                        case 'p':
121
#ifdef HTTPIO
122
                                sscanf(optarg, "%d", &HttpPort);
123
#endif
124
#ifdef TCPIO
125
                                sscanf(optarg, "%d", &TcpPort);
126
#endif
127
                                mandatories++;
128
                                break;
129
                        case 's':
130
                                sscanf(optarg, "%d", &SilentMode);
131
                                break;
132
                        case 't':
133
                                DELETE_DIR("traces");
134
                                CREATE_DIR("traces");
135
                                LogTraces = 1;
136
                                break;
137
                        default:
138
                                print_usage(argc, argv);
139
                                return -1;
140
                }
141
        }
142
        if(mandatories < MANDATORY_PARAMS)
143
        {
144
                print_usage(argc, argv);
145
                return -1;
146
        }
147

    
148
#ifdef EMULATE_CHUNK_LOSS
149
        ScheduledChunkLosses = NULL;
150
        cfg_opt_t scheduled_chunk_loss_opts[] =
151
        {
152
                CFG_INT("Time", 0, CFGF_NONE),
153
                CFG_INT("Value", 0, CFGF_NONE),
154
                CFG_INT("MinValue", 0, CFGF_NONE),
155
                CFG_INT("MaxValue", 0, CFGF_NONE),
156
                CFG_INT("Burstiness", 0, CFGF_NONE),
157
                CFG_END()
158
        };
159
        cfg_opt_t opts[] =
160
        {
161
                CFG_SEC("ScheduledChunkLoss", scheduled_chunk_loss_opts, CFGF_MULTI),
162
                CFG_END()
163
        };
164
        cfg_t *cfg, *cfg_sched;
165
        cfg = cfg_init(opts, CFGF_NONE);
166
        if(!cfg_parse(cfg, "_chunklossrate.conf") == CFG_PARSE_ERROR)
167
        {
168
                NScheduledChunkLosses = cfg_size(cfg, "ScheduledChunkLoss");
169
                if(NScheduledChunkLosses > 0)
170
                        ScheduledChunkLosses = (SChunkLoss*)malloc((NScheduledChunkLosses)*sizeof(SChunkLoss));
171
                
172
                int j;
173
                for(j = 0; j < cfg_size(cfg, "ScheduledChunkLoss"); j++)
174
                {
175
                        cfg_sched = cfg_getnsec(cfg, "ScheduledChunkLoss", j);
176
                        ScheduledChunkLosses[j].Time = cfg_getint(cfg_sched, "Time");
177
                        ScheduledChunkLosses[j].Value = cfg_getint(cfg_sched, "Value");
178
                        ScheduledChunkLosses[j].Burstiness = cfg_getint(cfg_sched, "Burstiness");
179
                        
180
                        // -1 means random value between min and max
181
                        if(ScheduledChunkLosses[j].Value == -1)
182
                        {
183
                                ScheduledChunkLosses[j].MinValue = cfg_getint(cfg_sched, "MinValue");
184
                                ScheduledChunkLosses[j].MaxValue = cfg_getint(cfg_sched, "MaxValue");
185
                        }
186
                }
187
                cfg_free(cfg);
188
                CurrChunkLossIndex = -1;
189
                
190
                for(j=0; j < NScheduledChunkLosses; j++)
191
                {
192
                        printf("ScheduledChunkLosses[%d].Time = %ld\n", j, ScheduledChunkLosses[j].Time);
193
                        printf("ScheduledChunkLosses[%d].Value = %d\n", j, ScheduledChunkLosses[j].Value);
194
                        printf("ScheduledChunkLosses[%d].Burstiness = %d\n", j, ScheduledChunkLosses[j].Burstiness);
195
                }
196
        }
197
#endif
198

    
199
#ifdef HTTPIO
200
        //this thread fetches chunks from the network by listening to the following path, port
201
        daemon = (struct MHD_Daemon*)initChunkPuller(UL_DEFAULT_EXTERNALPLAYER_PATH, HttpPort);
202
        if(daemon == NULL)
203
        {
204
                printf("CANNOT START MICROHTTPD SERVICE, EXITING...\n");
205
                exit(2);
206
        }
207
#endif
208
#ifdef TCPIO
209
        int fd = initChunkPuller(TcpPort);
210
        if(! (fd > 0))
211
        {
212
                printf("CANNOT START TCP PULLER...\n");
213
                exit(2);
214
        }
215
#endif
216

    
217
        if(!SilentMode)
218
        {
219
                if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
220
                        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
221
                        return -1;
222
                }
223
        }
224
        else
225
        {
226
                if(SDL_Init(SDL_INIT_TIMER)) {
227
                        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
228
                        return -1;
229
                }
230
        }
231
        
232
        if(ParseConf())
233
        {
234
                printf("ERROR: Cannot parse configuration file, exit...\n");
235
                exit(1);
236
        }
237
        
238
        firstChannelIndex = -1;
239
        int it;
240
        for(it = 0; it < NChannels; it++)
241
        {
242
                if(!strcmp(Channels[it].Title, firstChannelName))
243
                {
244
                        firstChannelIndex = it;
245
                        break;
246
                }
247
        }
248
        
249
        if(firstChannelIndex < 0)
250
        {
251
                printf("Cannot find the specified channel (%s) into the configuration file (channels.conf), exiting\n", firstChannelName);
252
                exit(0);
253
        }
254
        
255
        if(ChunkerPlayerGUI_Init())
256
        {
257
                printf("ERROR: Cannot init player gui, exit...\n");
258
                exit(1);
259
        }
260
        
261
        SelectedChannel = firstChannelIndex;
262

    
263
        SwitchChannel(&(Channels[SelectedChannel]));
264

    
265
        // Wait for user input
266
        while(!quit) {
267
                if(QueueFillingMode) {
268
                        SDL_WM_SetCaption("Filling buffer...", NULL);
269

    
270
                        if(ChunkerPlayerCore_AudioEnded())
271
                                ChunkerPlayerCore_ResetAVQueues();
272

    
273
#ifdef DEBUG_QUEUE
274
                        //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);
275
#endif
276
                }
277
                else
278
                        SDL_WM_SetCaption("NAPA-Wine Player", NULL);
279

    
280
                //listen for key and mouse
281
                while(SDL_PollEvent(&event)) {
282
                        switch(event.type) {
283
                                case SDL_QUIT:
284
                                        quit=1;
285
                                break;
286
                                case SDL_VIDEORESIZE:
287
                                        if(SilentMode)
288
                                                break;
289
                                        // printf("\tSDL_VIDEORESIZE event received!! \n");
290
                                        if(!FullscreenMode)
291
                                                ChunkerPlayerGUI_HandleResize(event.resize.w, event.resize.h);
292
                                        else
293
                                                ChunkerPlayerGUI_HandleResize(FullscreenWidth, FullscreenHeight);
294
                                break;
295
                                case SDL_ACTIVEEVENT:
296
                                        if(SilentMode)
297
                                                break;
298
                                                
299
                                        // if the window was iconified or restored
300
                                        if(event.active.state & SDL_APPACTIVE)
301
                                        {
302
                                                //If the application is being reactivated
303
                                                if( event.active.gain != 0 )
304
                                                {
305
                                                        ChunkerPlayerGUI_HandleGetFocus();
306
                                                }
307
                                        }
308

    
309
                                        //If something happened to the keyboard focus
310
                                        else if( event.active.state & SDL_APPINPUTFOCUS )
311
                                        {
312
                                                //If the application gained keyboard focus
313
                                                if( event.active.gain != 0 )
314
                                                {
315
                                                        ChunkerPlayerGUI_HandleGetFocus();
316
                                                }
317
                                        }
318
                                        //If something happened to the mouse focus
319
                                        else if( event.active.state & SDL_APPMOUSEFOCUS )
320
                                        {
321
                                                //If the application gained mouse focus
322
                                                if( event.active.gain != 0 )
323
                                                {
324
                                                        ChunkerPlayerGUI_HandleGetFocus();
325
                                                }
326
                                        }
327
                                        break;
328
                                case SDL_MOUSEMOTION:
329
                                        if(SilentMode)
330
                                                break;
331
                                                
332
                                        ChunkerPlayerGUI_HandleMouseMotion(event.motion.x, event.motion.y);
333
                                break;
334
                                case SDL_MOUSEBUTTONUP:
335
                                        if(SilentMode)
336
                                                break;
337
                                                
338
                                        if( event.button.button != SDL_BUTTON_LEFT )
339
                                                break;
340

    
341
                                        ChunkerPlayerGUI_HandleLButton(event.motion.x, event.motion.y);
342
                                break;
343
                        }
344
                        ChunkerPlayerGUI_HandleKey();
345
                }
346
                usleep(120000);
347
        }
348

    
349
        KILL_PROCESS(P2PProcessHandle);
350

    
351
        //TERMINATE
352
        ChunkerPlayerCore_Stop();
353
        if(YUVOverlay != NULL)
354
                SDL_FreeYUVOverlay(YUVOverlay);
355
        
356
        ChunkerPlayerGUI_Close();
357
        SDL_DestroyMutex(OverlayMutex);
358
        SDL_Quit();
359
        
360
#ifdef HTTPIO
361
        finalizeChunkPuller(daemon);
362
#endif
363
#ifdef TCPIO
364
        finalizeChunkPuller();
365
#endif
366
        
367
#ifdef EMULATE_CHUNK_LOSS
368
        if(ScheduledChunkLosses)
369
                free(ScheduledChunkLosses);
370
#endif
371
        return 0;
372
}
373

    
374
int cb_validate_conffile(cfg_t *cfg)
375
{
376
        char LaunchString[255];
377
        cfg_t *cfg_greet;
378
        
379
        if(cfg_size(cfg, "Channel") == 0)
380
        {
381
                cfg_error(cfg, "no \"Channel\" section found");
382
                return -1;
383
        }
384
        
385
        printf("\t%d Channel setions found\n", cfg_size(cfg, "Channel"));
386
        
387
        int j;
388
        for(j = 0; j < cfg_size(cfg, "Channel"); j++)
389
        {
390
                cfg_greet = cfg_getnsec(cfg, "Channel", j);
391
                sprintf(LaunchString, "%s", cfg_getstr(cfg_greet, "LaunchString"));
392
                if(!(strlen(LaunchString) > 0))
393
                {
394
                        cfg_error(cfg, "invalid LaunchString for Channel[%d]", j);
395
                        return -1;
396
                }
397
                printf("\tChannel[%d].LaunchString = %s\n", j, LaunchString);
398
                printf("\tChannel[%d].AudioChannels = %ld\n", j, cfg_getint(cfg_greet, "AudioChannels"));
399
                printf("\tChannel[%d].SampleRate = %ld\n", j, cfg_getint(cfg_greet, "SampleRate"));
400
                printf("\tChannel[%d].Width = %ld\n", j, cfg_getint(cfg_greet, "Width"));
401
                printf("\tChannel[%d].Height = %ld\n", j, cfg_getint(cfg_greet, "Height"));
402
                printf("\tChannel[%d].Bitrate = %ld\n", j, cfg_getint(cfg_greet, "Bitrate"));
403
                printf("\tChannel[%d].Ratio = %s\n", j, cfg_getstr(cfg_greet, "Ratio"));
404
        }
405
    return 0;
406
}
407

    
408
int ParseConf()
409
{
410
        int j;
411
        
412
        // PARSING CONF FILE
413
        cfg_opt_t channel_opts[] =
414
        {
415
                CFG_STR("Title", "", CFGF_NONE),
416
                CFG_STR("LaunchString", "", CFGF_NONE),
417
                CFG_INT("AudioChannels", 2, CFGF_NONE),
418
                CFG_INT("SampleRate", 48000, CFGF_NONE),
419
                CFG_INT("Width", 176, CFGF_NONE),
420
                CFG_INT("Height", 144, CFGF_NONE),
421
                CFG_INT("Bitrate", 0, CFGF_NONE),
422
                
423
                // for some reason libconfuse parsing for floating point does not work in windows
424
                //~ CFG_FLOAT("Ratio", 1.22, CFGF_NONE),
425
                CFG_STR("Ratio", "1.22", CFGF_NONE),
426
                CFG_END()
427
        };
428
        cfg_opt_t opts[] =
429
        {
430
                CFG_SEC("Channel", channel_opts, CFGF_TITLE | CFGF_MULTI),
431
                CFG_END()
432
        };
433
        cfg_t *cfg, *cfg_channel;
434
        cfg = cfg_init(opts, CFGF_NONE);
435
        if(cfg_parse(cfg, DEFAULT_CONF_FILENAME) == CFG_PARSE_ERROR)
436
        {
437
                printf("Error while parsing configuration file, exiting...\n");
438
                cb_validate_conffile(cfg);
439
                return 1;
440
        }
441
        
442
        if(cfg_parse(cfg, DEFAULT_CONF_FILENAME) == CFG_FILE_ERROR)
443
        {
444
                printf("Error trying parsing configuration file. '%s' file couldn't be opened for reading\n", DEFAULT_CONF_FILENAME);
445
                return 1;
446
        }
447
        
448
        FILE * tmp_file;
449
        if(tmp_file = fopen(DEFAULT_PEEREXECNAME_FILENAME, "r")) {
450
                if(fscanf(tmp_file, "%s", StreamerFilename) != 1) {
451
                        printf("Wrong format of conf file %s containing peer application exec name. Assuming default: %s.\n\n", DEFAULT_PEEREXECNAME_FILENAME, DEFAULT_PEER_EXEC_NAME);
452
                }
453
                fclose(tmp_file);
454
        }
455
        else {
456
                printf("Could not find conf file %s containing peer application exec name. Exiting.\n\n", DEFAULT_PEEREXECNAME_FILENAME);
457
                exit(1);
458
        }
459
        if(tmp_file = fopen(StreamerFilename, "r"))
460
    {
461
        fclose(tmp_file);
462
    }
463
    else
464
        {
465
                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);
466
                exit(1);
467
        }
468
        
469
        for(j = 0; j < cfg_size(cfg, "Channel"); j++)
470
        {
471
                cfg_channel = cfg_getnsec(cfg, "Channel", j);
472
                sprintf(Channels[j].Title, "%s", cfg_title(cfg_channel));
473
                strcpy(Channels[j].LaunchString, cfg_getstr(cfg_channel, "LaunchString"));
474
                Channels[j].Width = cfg_getint(cfg_channel, "Width");
475
                Channels[j].Height = cfg_getint(cfg_channel, "Height");
476
                Channels[j].AudioChannels = cfg_getint(cfg_channel, "AudioChannels");
477
                Channels[j].SampleRate = cfg_getint(cfg_channel, "SampleRate");
478
                Channels[j].Ratio = strtof(cfg_getstr(cfg_channel, "Ratio"), 0);
479
                Channels[j].Bitrate = cfg_getint(cfg_channel, "Bitrate");
480
                
481
                Channels[j].Index = j+1;
482
                NChannels++;
483
        }
484
        cfg_free(cfg);
485

    
486
        return 0;
487
}
488

    
489
int ReTune(SChannel* channel)
490
{        
491
        if(ChunkerPlayerCore_IsRunning())
492
                ChunkerPlayerCore_Pause();
493
        
494
        //reset quality info
495
        channel->startTime = time(NULL);
496
        
497
        ChunkerPlayerCore_Play();
498
        
499
        return 0;
500
}
501

    
502
int SwitchChannel(SChannel* channel)
503
{
504
        int i=0;
505
#ifdef RESTORE_SCREEN_ON_ZAPPING
506
        int was_fullscreen = FullscreenMode;
507
        int old_width = window_width, old_height = window_height;
508
#endif
509
        
510
        if(ChunkerPlayerCore_IsRunning())
511
                ChunkerPlayerCore_Stop();
512

    
513
    KILL_PROCESS(P2PProcessHandle);
514
        remove("NetworkID");
515
        
516
        ratio = channel->Ratio;
517
        ChunkerPlayerGUI_SetChannelTitle(channel->Title);
518
        ChunkerPlayerGUI_ForceResize(channel->Width, channel->Height);
519
        
520
        int w=0, h=0;
521
        ChunkerPlayerGUI_AspectRatioResize((float)channel->Ratio, channel->Width, channel->Height, &w, &h);
522
        ChunkerPlayerCore_SetupOverlay(w, h);
523
        //ChunkerPlayerGUI_SetupOverlayRect(channel);
524
        
525
        if(ChunkerPlayerCore_InitCodecs(channel->Width, channel->Height, channel->SampleRate, channel->AudioChannels) < 0)
526
        {
527
                printf("ERROR, COULD NOT INITIALIZE CODECS\n");
528
                exit(2);
529
        }
530
        
531
        //reset quality info
532
        channel->startTime = time(NULL);
533
        channel->instant_score = 0.0;
534
        channel->average_score = 0.0;
535
        channel->history_index = 0;
536
        for(i=0; i<CHANNEL_SCORE_HISTORY_SIZE; i++)
537
                channel->score_history[i] = -1;
538
        sprintf(channel->quality, "EVALUATING...");
539
        
540
        if(SilentMode != 3) //mode 3 is for GUI only, no P2P peer process
541
        {
542
                char argv0[255], parameters_string[511];
543
                sprintf(argv0, "%s", StreamerFilename);
544

    
545
#ifdef HTTPIO
546
                sprintf(parameters_string, "%s %s %s %d %s %s %d", "-C", channel->Title, "-P", (HttpPort+channel->Index), channel->LaunchString, "-F", HttpPort);
547
#endif
548

    
549
#ifdef TCPIO
550
                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);
551
#endif
552

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

    
555
#ifndef __WIN32__
556
                char* parameters_vector[255];
557
                parameters_vector[0] = argv0;
558
                
559
                // split parameters and count them
560
                int par_count=1;
561
                char* pch = strtok (parameters_string, " ");
562
                while (pch != NULL)
563
                {
564
                        if(par_count > 255) break;
565
                        // printf ("\tpch=%s\n",pch);
566
                        parameters_vector[par_count] = (char*) malloc(sizeof(char)*(strlen(pch)+1));
567
                        strcpy(parameters_vector[par_count], pch);
568
                        pch = strtok (NULL, " ");
569
                        par_count++;
570
                }
571
                parameters_vector[par_count] = NULL;
572

    
573
                int d;
574
                int stdoutS, stderrS;
575
                FILE* stream;
576
                stream = fopen("/dev/null", "a+");
577
                d = fileno(stream);
578

    
579
                // create backup descriptors for the current stdout and stderr devices
580
                stdoutS = dup(STDOUT_FILENO);
581
                stderrS = dup(STDERR_FILENO);
582
                
583
                // redirect child output to /dev/null
584
                dup2(d, STDOUT_FILENO);
585
                dup2(d, STDERR_FILENO);
586

    
587
                int pid = fork();
588
                if(pid == 0)
589
                {
590
                        execv(argv0, parameters_vector);
591
                        printf("ERROR, COULD NOT LAUNCH OFFERSTREAMER\n");
592
                        exit(2);
593
                }
594
                else
595
                        *((pid_t*)P2PProcessHandle) = pid;
596
                
597
                // restore backup descriptors in the parent process
598
                dup2(stdoutS, STDOUT_FILENO);
599
                dup2(stderrS, STDERR_FILENO);
600
                
601
                for(i=1; i<par_count; i++)
602
                        free(parameters_vector[i]);
603
                        
604
                fclose(stream);
605

    
606
#ifdef RESTORE_SCREEN_ON_ZAPPING
607
                if(was_fullscreen)
608
                        ChunkerPlayerGUI_ToggleFullscreen();
609
                else
610
                {
611
                        ChunkerPlayerGUI_HandleResize(old_width, old_height);
612
                }
613
#endif
614
        
615
#else
616

    
617
                STARTUPINFO sti;
618
                SECURITY_ATTRIBUTES sats = { 0 };
619
                DWORD writ, excode, read, available;
620
                int ret = 0;
621

    
622
                //set SECURITY_ATTRIBUTES struct fields
623
                sats.nLength = sizeof(sats);
624
                sats.bInheritHandle = TRUE;
625
                sats.lpSecurityDescriptor = NULL;
626

    
627
                ZeroMemory( &sti, sizeof(sti) );
628
                sti.cb = sizeof(sti);
629
                ZeroMemory( P2PProcessHandle, sizeof(PROCESS_INFORMATION) );
630

    
631
                char buffer[512];
632
                sprintf(buffer, "%s %s", argv0, parameters_string);
633

    
634
                if(!CreateProcess(NULL,
635
                  buffer,
636
                  &sats,
637
                  &sats,
638
                  TRUE,
639
                  0,
640
                  NULL,
641
                  NULL,
642
                  &sti,
643
                  P2PProcessHandle))
644
                {
645
                        printf("Unable to generate process \n");
646
                        return -1;
647
                }
648
#endif
649

    
650
        }
651
        // Read the Network ID
652
        int Error=true;
653
        char Line1[255], Line2[255];
654
        while(Error)
655
        {
656
            FILE* fp=fopen("NetworkID","r");
657
            if(fp)
658
            {
659
                if(ReadALine(fp,Line1,255)!=-1)
660
                    if(ReadALine(fp,Line2,255)!=-1)
661
                    {
662
                        if(strcmp(Line2,"IDEnd")==0)
663
                        {
664
                            strcpy(NetworkID,Line1);
665
                            Error=false;
666
                        }
667
                    }
668
                fclose(fp);
669
            }
670
            if(Error) usleep(100000);
671
        }
672
        
673
        printf("NetworkID = %s\n",NetworkID);
674
        
675
        ChunkerPlayerCore_Play();
676
        ChunkerPlayerGUI_ChannelSwitched();
677
        return 0;
678
}
679

    
680
void ZapDown()
681
{
682
        SelectedChannel = ((SelectedChannel+1) %NChannels);
683
        SwitchChannel(&(Channels[SelectedChannel]));
684
}
685

    
686
void ZapUp()
687
{
688
        SelectedChannel--;
689
        if(SelectedChannel < 0)
690
                SelectedChannel = NChannels-1;
691

    
692
        SwitchChannel(&(Channels[SelectedChannel]));
693
}
694

    
695
int enqueueBlock(const uint8_t *block, const int block_size)
696
{
697
        return ChunkerPlayerCore_EnqueueBlocks(block, block_size);
698
}