예제 #1
0
int main( int i_argc, char **pp_argv )
{
    const char *psz_network_name = "DVBlast - http://www.videolan.org/projects/dvblast.html";
    const char *psz_provider_name = NULL;
    char *psz_dup_config = NULL;
    struct sched_param param;
    int i_error;
    int c;
    int b_enable_syslog = 0;
    struct ev_signal sigint_watcher, sigterm_watcher, sighup_watcher;
    struct ev_timer quit_watcher;

    print_fh = stdout;

    if ( i_argc == 1 )
        usage();

    /*
     * The only short options left are: 489
     * Use them wisely.
     */
    static const struct option long_options[] =
    {
        { "config-file",     required_argument, NULL, 'c' },
        { "remote-socket",   required_argument, NULL, 'r' },
        { "ttl",             required_argument, NULL, 't' },
        { "rtp-output",      required_argument, NULL, 'o' },
        { "priority",        required_argument, NULL, 'i' },
        { "adapter",         required_argument, NULL, 'a' },
        { "frontend-number", required_argument, NULL, 'n' },
        { "delsys",          required_argument, NULL, '5' },
				{ "dvb-plp-id",      required_argument, NULL, '9' },
        { "frequency",       required_argument, NULL, 'f' },
        { "fec-inner",       required_argument, NULL, 'F' },
        { "rolloff",         required_argument, NULL, 'R' },
        { "symbol-rate",     required_argument, NULL, 's' },
        { "diseqc",          required_argument, NULL, 'S' },
        { "uncommitted",     required_argument, NULL, 'k' },
        { "voltage",         required_argument, NULL, 'v' },
        { "force-pulse",     no_argument,       NULL, 'p' },
        { "bandwidth",       required_argument, NULL, 'b' },
        { "inversion",       required_argument, NULL, 'I' },
        { "modulation",      required_argument, NULL, 'm' },
        { "pilot",           required_argument, NULL, 'P' },
        { "multistream-id",  required_argument, NULL, '1' },
        { "fec-lp",          required_argument, NULL, 'K' },
        { "guard",           required_argument, NULL, 'G' },
        { "hierarchy",       required_argument, NULL, 'H' },
        { "transmission",    required_argument, NULL, 'X' },
        { "lock-timeout",    required_argument, NULL, 'O' },
        { "budget-mode",     no_argument,       NULL, 'u' },
        { "select-pmts",     no_argument,       NULL, 'w' },
        { "udp",             no_argument,       NULL, 'U' },
        { "unique-ts-id",    no_argument,       NULL, 'T' },
        { "latency",         required_argument, NULL, 'L' },
        { "retention",       required_argument, NULL, 'E' },
        { "duplicate",       required_argument, NULL, 'd' },
        { "passthrough",     no_argument,       NULL, '3' },
        { "rtp-input",       required_argument, NULL, 'D' },
        { "asi-adapter",     required_argument, NULL, 'A' },
        { "any-type",        no_argument,       NULL, 'z' },
        { "dvb-compliance",  no_argument,       NULL, 'C' },
        { "emm-passthrough", no_argument,       NULL, 'W' },
        { "ecm-passthrough", no_argument,       NULL, 'Y' },
        { "epg-passthrough", no_argument,       NULL, 'e' },
        { "network-name",    no_argument,       NULL, 'M' },
        { "network-id",      no_argument,       NULL, 'N' },
        { "system-charset",  required_argument, NULL, 'j' },
        { "dvb-charset",     required_argument, NULL, 'J' },
        { "provider-name",   required_argument, NULL, 'B' },
        { "logger",          no_argument,       NULL, 'l' },
        { "logger-ident",    required_argument, NULL, 'g' },
        { "print",           required_argument, NULL, 'x' },
        { "quit-timeout",    required_argument, NULL, 'Q' },
        { "print-period",    required_argument, NULL, '6' },
        { "es-timeout",      required_argument, NULL, '7' },
        { "quiet",           no_argument,       NULL, 'q' },
        { "help",            no_argument,       NULL, 'h' },
        { "version",         no_argument,       NULL, 'V' },
        { "mrtg-file",       required_argument, NULL, 'Z' },
        { "ca-number",       required_argument, NULL, 'y' },
        { "pidmap",          required_argument, NULL, '0' },
        { "dvr-buf-size",    required_argument, NULL, '2' },
        { 0, 0, 0, 0 }
    };

    while ( (c = getopt_long(i_argc, pp_argv, "q::c:r:t:o:i:a:n:5:f:F:R:s:S:k:v:pb:I:m:P:K:G:H:X:O:uwUTL:E:d:3D:A:lg:zCWYeM:N:j:J:B:x:Q:6:7:hVZ:y:0:1:2:9:", long_options, NULL)) != -1 )
    {
        switch ( c )
        {
        case 'q':
            if ( optarg )
            {
                if ( *optarg == 'q' )  /* e.g. -qqq */
                {
                    i_verbose--;
                    while ( *optarg == 'q' )
                    {
                        i_verbose--;
                        optarg++;
                    }
                }
                else
                {
                    i_verbose -= atoi( optarg );  /* e.g. -q2 */
                }
            }
            else
            {
                i_verbose--;  /* -q */
            }
            break;

        case 'c':
            psz_conf_file = optarg;
            /*
             * When configuration file is used it is reasonable to assume that
             * services may be added/removed. If b_select_pmts is not set dvblast
             * is unable to start streaming newly added services in the config.
             */
            b_select_pmts = 1;
            break;

        case 'r':
            psz_srv_socket = optarg;
            break;

        case 't':
            i_ttl_global = strtol( optarg, NULL, 0 );
            break;

        case 'o':
        {
            struct in_addr maddr;
            if ( !inet_aton( optarg, &maddr ) )
                usage();
            memcpy( pi_ssrc_global, &maddr.s_addr, 4 * sizeof(uint8_t) );
            break;
        }

        case 'i':
            i_priority = strtol( optarg, NULL, 0 );
            break;

        case 'a':
            i_adapter = strtol( optarg, NULL, 0 );
            break;

        case 'n':
            i_fenum = strtol( optarg, NULL, 0 );
            break;

        case 'y':
            i_canum = strtol( optarg, NULL, 0 );
            break;

        case '5':
            psz_delsys = optarg;
            break;
				case '9':
           dvb_plp_id = strtol( optarg, NULL, 0 );
           break;
        case 'f':
            if (optarg && optarg[0] != '-')
                i_frequency = strtol( optarg, NULL, 0 );
            if ( pf_Open != NULL )
                usage();
#ifdef HAVE_DVB_SUPPORT
            pf_Open = dvb_Open;
            pf_Reset = dvb_Reset;
            pf_SetFilter = dvb_SetFilter;
            pf_UnsetFilter = dvb_UnsetFilter;
#else
            msg_Err( NULL, "DVBlast is compiled without DVB support.");
            exit(1);
#endif
            break;

        case 'F':
            i_fec = strtol( optarg, NULL, 0 );
            break;

        case 'R':
            i_rolloff = strtol( optarg, NULL, 0 );
            break;

        case 's':
            i_srate = strtol( optarg, NULL, 0 );
            break;

        case 'S':
            i_satnum = strtol( optarg, NULL, 16 );
            break;

        case 'k':
            i_uncommitted = strtol( optarg, NULL, 16 );
            break;

        case 'v':
            i_voltage = strtol( optarg, NULL, 0 );
            break;

        case 'p':
            b_tone = 1;
            break;

        case 'b':
            i_bandwidth = strtol( optarg, NULL, 0 );
            break;

        case 'I':
            i_inversion = strtol( optarg, NULL, 0 );
            break;

        case 'm':
            psz_modulation = optarg;
            break;

        case 'P':
            i_pilot = strtol( optarg, NULL, 0 );
            break;

        case '1':
            i_mis = strtol( optarg, NULL, 0 );
            break;

        case 'K':
            i_fec_lp = strtol( optarg, NULL, 0 );
            break;

        case 'G':
            i_guard = strtol( optarg, NULL, 0 );
            break;

        case 'X':
            i_transmission = strtol( optarg, NULL, 0 );
            break;

        case 'O':
            i_frontend_timeout_duration = strtoll( optarg, NULL, 0 ) * 1000;
            break;

        case 'H':
            i_hierarchy = strtol( optarg, NULL, 0 );
            break;

        case 'u':
            b_budget_mode = 1;
            break;

        case 'w':
            b_select_pmts = !b_select_pmts;
            break;

        case 'U':
            b_udp_global = true;
            break;

        case 'L':
            i_latency_global = strtoll( optarg, NULL, 0 ) * 1000;
            break;

        case 'E':
            i_retention_global = strtoll( optarg, NULL, 0 ) * 1000;
            break;

        case 'd':
            psz_dup_config = optarg;
            break;

        case '3':
            b_passthrough = true;
            print_fh = stderr;
            break;

        case 'D':
            psz_udp_src = optarg;
            if ( pf_Open != NULL )
                usage();
            pf_Open = udp_Open;
            pf_Reset = udp_Reset;
            pf_SetFilter = udp_SetFilter;
            pf_UnsetFilter = udp_UnsetFilter;
            break;

        case 'A':
#ifdef HAVE_ASI_SUPPORT
            if ( pf_Open != NULL )
                usage();
            if ( strncmp(optarg, "deltacast:", 10) == 0)
            {
#ifdef HAVE_ASI_DELTACAST_SUPPORT
                i_asi_adapter = strtol( optarg+10, NULL, 0 );
                pf_Open = asi_deltacast_Open;
                pf_Reset = asi_deltacast_Reset;
                pf_SetFilter = asi_deltacast_SetFilter;
                pf_UnsetFilter = asi_deltacast_UnsetFilter;
#else
                msg_Err( NULL, "DVBlast is compiled without Deltacast ASI support.");
                exit(1);
#endif
            }
            else
            {
                i_asi_adapter = strtol( optarg, NULL, 0 );
                pf_Open = asi_Open;
                pf_Reset = asi_Reset;
                pf_SetFilter = asi_SetFilter;
                pf_UnsetFilter = asi_UnsetFilter;
            }
#else
            msg_Err( NULL, "DVBlast is compiled without ASI support.");
            exit(1);
#endif
            break;

        case 'z':
            b_any_type = 1;
            break;

        case 'C':
            b_dvb_global = true;
            break;

        case 'W':
            b_enable_emm = true;
            break;

        case 'Y':
            b_enable_ecm = true;
            break;
 
        case 'e':
            b_epg_global = true;
            break;

        case 'M':
            psz_network_name = optarg;
            break;

        case 'N':
            i_network_id = strtoul( optarg, NULL, 0 );
            break;

        case 'T':
            b_random_tsid = 1;
            break;

        case 'j':
            psz_native_charset = optarg;
            break;

        case 'J':
            psz_dvb_charset = optarg;
            break;

        case 'B':
            psz_provider_name = optarg;
            break;

        case 'l':
            b_enable_syslog = 1;
            break;

        case 'g':
            psz_syslog_ident = optarg;
            break;

        case 'x':
            b_print_enabled = true;
            if ( !strcmp(optarg, "text") )
                i_print_type = PRINT_TEXT;
            else if ( !strcmp(optarg, "xml") )
                i_print_type = PRINT_XML;
            else
            {
                b_print_enabled = false;
                msg_Warn( NULL, "unrecognized print type %s", optarg );
            }
            break;

        case 'Q':
            i_quit_timeout_duration = strtoll( optarg, NULL, 0 ) * 1000;
            break;

        case '6':
            i_print_period = strtoll( optarg, NULL, 0 ) * 1000;
            break;

        case '7':
            i_es_timeout = strtoll( optarg, NULL, 0 ) * 1000;
            break;

        case 'V':
            DisplayVersion();
            exit(0);
            break;

        case 'Z':
            psz_mrtg_file = optarg;
            break;

        case '0': {
            /* We expect a comma separated list of numbers.
               Put them into the pi_newpids array as they appear */
            char *str1;
            char *saveptr = NULL;
            char *tok = NULL;
            int i, i_newpid;
            for (i = 0, str1 = optarg; i < N_MAP_PIDS; i++, str1 = NULL)
            {
                tok = strtok_r(str1, ",", &saveptr);
                if ( !tok )
                    break;
                i_newpid = strtoul(tok, NULL, 0);
                if ( !i_newpid ) {
                     msg_Err( NULL, "Invalid pidmap string" );
                     usage();
                }
                pi_newpids[i] = i_newpid;
            }
            b_do_remap = true;
            break;
        }
#ifdef HAVE_DVB_SUPPORT
        case '2':
            i_dvr_buffer_size = strtol( optarg, NULL, 0 );
            if (!i_dvr_buffer_size)
                usage();	// it exits
            /* roundup to packet size */
            i_dvr_buffer_size += TS_SIZE - 1;
            i_dvr_buffer_size /= TS_SIZE;
            i_dvr_buffer_size *= TS_SIZE;
            break;
#endif
        case 'h':
        default:
            usage();
        }
    }
    if ( optind < i_argc || pf_Open == NULL )
        usage();

    if ( b_enable_syslog )
        msg_Connect( psz_syslog_ident ? psz_syslog_ident : pp_argv[0] );

    if ( b_print_enabled )
    {
        /* Make std* line-buffered */
        setvbuf(print_fh, NULL, _IOLBF, 0);
    }

    if ( i_verbose )
        DisplayVersion();

    msg_Warn( NULL, "restarting" );

    switch (i_print_type) 
    {
        case PRINT_XML:
            fprintf(print_fh, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
            fprintf(print_fh, "<TS>\n");
            break;
        default:
            break;
    }

    if ( b_udp_global )
    {
        msg_Warn( NULL, "raw UDP output is deprecated.  Please consider using RTP." );
        msg_Warn( NULL, "for DVB-IP compliance you should use RTP." );
    }

    if ( b_epg_global && !b_dvb_global )
    {
        msg_Dbg( NULL, "turning on DVB compliance, required by EPG information" );
        b_dvb_global = true;
    }

    if ((event_loop = ev_default_loop(0)) == NULL)
    {
        msg_Err( NULL, "unable to initialize libev" );
        exit(EXIT_FAILURE);
    }

    memset( &output_dup, 0, sizeof(output_dup) );
    if ( psz_dup_config != NULL )
    {
        output_config_t config;

        config_Defaults( &config );
        if ( !config_ParseHost( &config, psz_dup_config ) )
            msg_Err( NULL, "Invalid target address for -d switch" );
        else
        {
            output_Init( &output_dup, &config );
            output_Change( &output_dup, &config );
        }

        config_Free( &config );
    }

    config_strdvb( &network_name, psz_network_name );
    config_strdvb( &provider_name, psz_provider_name );

    /* Set signal handlers */
    signal_watcher_init(&sigint_watcher, event_loop, sighandler, SIGINT);
    signal_watcher_init(&sigterm_watcher, event_loop, sighandler, SIGTERM);
    signal_watcher_init(&sighup_watcher, event_loop, sighandler, SIGHUP);

    srand( time(NULL) * getpid() );

    demux_Open();

    // init the mrtg logfile
    mrtgInit(psz_mrtg_file);

    if ( i_priority > 0 )
    {
        memset( &param, 0, sizeof(struct sched_param) );
        param.sched_priority = i_priority;
        if ( (i_error = pthread_setschedparam( pthread_self(), SCHED_RR,
                                               &param )) )
        {
            msg_Warn( NULL, "couldn't set thread priority: %s",
                      strerror(i_error) );
        }
    }

    config_ReadFile();

    if ( psz_srv_socket != NULL )
        comm_Open();

    if ( i_quit_timeout_duration )
    {
        ev_timer_init(&quit_watcher, quit_cb,
                      i_quit_timeout_duration / 1000000., 0);
        ev_timer_start(event_loop, &quit_watcher);
    }

    outputs_Init();

    ev_run(event_loop, 0);

    mrtgClose();
    outputs_Close( i_nb_outputs );
    demux_Close();
    dvb_string_clean( &network_name );
    dvb_string_clean( &provider_name );
    if ( conf_iconv != (iconv_t)-1 )
        iconv_close( conf_iconv );

    switch (i_print_type)
    {
    case PRINT_XML:
        fprintf(print_fh, "</TS>\n");
        break;
    default:
        break;
    }

    if ( b_enable_syslog )
        msg_Disconnect();

    comm_Close();
    block_Vacuum();

    return EXIT_SUCCESS;
}
예제 #2
0
파일: dvblast.c 프로젝트: deanzhang/dvblast
int main( int i_argc, char **pp_argv )
{
    const char *psz_network_name = "DVBlast - http://www.videolan.org/projects/dvblast.html";
    char *p_network_name_tmp = NULL;
    size_t i_network_name_tmp_size;
    char *psz_dup_config = NULL;
    mtime_t i_poll_timeout = MAX_POLL_TIMEOUT;
    struct sched_param param;
    int i_error;
    int c;
    struct sigaction sa;
    sigset_t set;

    int b_enable_syslog = 0;

    if ( i_argc == 1 )
        usage();

    /*
     * The only short options left are: ky0123456789
     * Use them wisely.
     */
    static const struct option long_options[] =
    {
        { "config-file",     required_argument, NULL, 'c' },
        { "remote-socket",   required_argument, NULL, 'r' },
        { "ttl",             required_argument, NULL, 't' },
        { "rtp-output",      required_argument, NULL, 'o' },
        { "priority",        required_argument, NULL, 'i' },
        { "adapter",         required_argument, NULL, 'a' },
        { "frontend-number", required_argument, NULL, 'n' },
        { "frequency",       required_argument, NULL, 'f' },
        { "fec-inner",       required_argument, NULL, 'F' },
        { "rolloff",         required_argument, NULL, 'R' },
        { "symbol-rate",     required_argument, NULL, 's' },
        { "diseqc",          required_argument, NULL, 'S' },
        { "voltage",         required_argument, NULL, 'v' },
        { "force-pulse",     no_argument,       NULL, 'p' },
        { "bandwidth",       required_argument, NULL, 'b' },
        { "inversion",       required_argument, NULL, 'I' },
        { "modulation",      required_argument, NULL, 'm' },
        { "pilot",           required_argument, NULL, 'P' },
        { "fec-lp",          required_argument, NULL, 'K' },
        { "guard",           required_argument, NULL, 'G' },
        { "hierarchy",       required_argument, NULL, 'H' },
        { "transmission",    required_argument, NULL, 'X' },
        { "lock-timeout",    required_argument, NULL, 'O' },
        { "budget-mode",     no_argument,       NULL, 'u' },
        { "select-pmts",     no_argument,       NULL, 'w' },
        { "udp",             no_argument,       NULL, 'U' },
        { "unique-ts-id",    no_argument,       NULL, 'T' },
        { "latency",         required_argument, NULL, 'L' },
        { "retention",       required_argument, NULL, 'E' },
        { "duplicate",       required_argument, NULL, 'd' },
        { "rtp-input",       required_argument, NULL, 'D' },
        { "asi-adapter",     required_argument, NULL, 'A' },
        { "any-type",        no_argument,       NULL, 'z' },
        { "dvb-compliance",  no_argument,       NULL, 'C' },
        { "emm-passthrough", no_argument,       NULL, 'W' },
        { "ecm-passthrough", no_argument,       NULL, 'Y' },
        { "epg-passthrough", no_argument,       NULL, 'e' },
        { "network-name",    no_argument,       NULL, 'M' },
        { "network-id",      no_argument,       NULL, 'N' },
        { "system-charset",  required_argument, NULL, 'j' },
        { "dvb-charset",     required_argument, NULL, 'J' },
        { "provider-name",   required_argument, NULL, 'B' },
        { "logger",          no_argument,       NULL, 'l' },
        { "logger-ident",    required_argument, NULL, 'g' },
        { "print",           required_argument, NULL, 'x' },
        { "quit-timeout",    required_argument, NULL, 'Q' },
        { "quiet",           no_argument,       NULL, 'q' },
        { "help",            no_argument,       NULL, 'h' },
        { "version",         no_argument,       NULL, 'V' },
        { "mrtg-file",       required_argument, NULL, 'Z' },
        { 0, 0, 0, 0 }
    };

    while ( (c = getopt_long(i_argc, pp_argv, "q::c:r:t:o:i:a:n:f:F:R:s:S:v:pb:I:m:P:K:G:H:X:O:uwUTL:E:d:D:A:lg:zCWYeM:N:j:J:B:x:Q:hVZ:", long_options, NULL)) != -1 )
    {
        switch ( c )
        {
        case 'q':
            if ( optarg )
            {
                if ( *optarg == 'q' )  /* e.g. -qqq */
                {
                    i_verbose--;
                    while ( *optarg == 'q' )
                    {
                        i_verbose--;
                        optarg++;
                    }
                }
                else
                {
                    i_verbose -= atoi( optarg );  /* e.g. -q2 */
                }
            }
            else
            {
                i_verbose--;  /* -q */
            }
            break;

        case 'c':
            psz_conf_file = optarg;
            break;

        case 'r':
            psz_srv_socket = optarg;
            break;

        case 't':
            i_ttl_global = strtol( optarg, NULL, 0 );
            break;

        case 'o':
        {
            struct in_addr maddr;
            if ( !inet_aton( optarg, &maddr ) )
                usage();
            memcpy( pi_ssrc_global, &maddr.s_addr, 4 * sizeof(uint8_t) );
            break;
        }

        case 'i':
            i_priority = strtol( optarg, NULL, 0 );
            break;

        case 'a':
            i_adapter = strtol( optarg, NULL, 0 );
            break;

        case 'n':
            i_fenum = strtol( optarg, NULL, 0 );
            break;

        case 'f':
            i_frequency = strtol( optarg, NULL, 0 );
            if ( pf_Open != NULL )
                usage();
            pf_Open = dvb_Open;
            pf_Read = dvb_Read;
            pf_Reset = dvb_Reset;
            pf_SetFilter = dvb_SetFilter;
            pf_UnsetFilter = dvb_UnsetFilter;
            break;

        case 'F':
            i_fec = strtol( optarg, NULL, 0 );
            break;

        case 'R':
            i_rolloff = strtol( optarg, NULL, 0 );
            break;

        case 's':
            i_srate = strtol( optarg, NULL, 0 );
            break;

        case 'S':
            i_satnum = strtol( optarg, NULL, 16 );
            break;

        case 'v':
            i_voltage = strtol( optarg, NULL, 0 );
            break;

        case 'p':
            b_tone = 1;
            break;

        case 'b':
            i_bandwidth = strtol( optarg, NULL, 0 );
            break;

        case 'I':
            i_inversion = strtol( optarg, NULL, 0 );
            break;

        case 'm':
            psz_modulation = optarg;
            break;

        case 'P':
            i_pilot = strtol( optarg, NULL, 0 );
            break;

        case 'K':
            i_fec_lp = strtol( optarg, NULL, 0 );
            break;

        case 'G':
            i_guard = strtol( optarg, NULL, 0 );
            break;

        case 'X':
            i_transmission = strtol( optarg, NULL, 0 );
            break;

        case 'O':
            i_frontend_timeout_duration = strtoll( optarg, NULL, 0 ) * 1000;
            break;

        case 'H':
            i_hierarchy = strtol( optarg, NULL, 0 );
            break;

        case 'u':
            b_budget_mode = 1;
            break;

        case 'w':
            b_select_pmts = 1;
            break;

        case 'U':
            b_udp_global = true;
            break;

        case 'L':
            i_latency_global = strtoll( optarg, NULL, 0 ) * 1000;
            break;

        case 'E':
            i_retention_global = strtoll( optarg, NULL, 0 ) * 1000;
            break;

        case 'd':
            psz_dup_config = optarg;
            break;

        case 'D':
            psz_udp_src = optarg;
            if ( pf_Open != NULL )
                usage();
            pf_Open = udp_Open;
            pf_Read = udp_Read;
            pf_Reset = udp_Reset;
            pf_SetFilter = udp_SetFilter;
            pf_UnsetFilter = udp_UnsetFilter;
            break;

        case 'A':
            i_asi_adapter = strtol( optarg, NULL, 0 );
            if ( pf_Open != NULL )
                usage();
            pf_Open = asi_Open;
            pf_Read = asi_Read;
            pf_Reset = asi_Reset;
            pf_SetFilter = asi_SetFilter;
            pf_UnsetFilter = asi_UnsetFilter;
            break;

        case 'z':
            b_any_type = 1;
            break;

        case 'C':
            b_dvb_global = true;
            break;

        case 'W':
            b_enable_emm = true;
            break;

        case 'Y':
            b_enable_ecm = true;
            b_dvb_global = true;
            break;
 
        case 'e':
            b_epg_global = true;
            break;

        case 'M':
            psz_network_name = optarg;
            break;

        case 'N':
            i_network_id = strtoul( optarg, NULL, 0 );
            break;

        case 'T':
            b_random_tsid = 1;
            break;

        case 'j':
            psz_native_charset = optarg;
            break;

        case 'J':
            psz_dvb_charset = optarg;
            break;

        case 'B':
            psz_provider_name = optarg;
            break;

        case 'l':
            b_enable_syslog = 1;
            break;

        case 'g':
            psz_syslog_ident = optarg;
            break;

        case 'x':
            if ( !strcmp(optarg, "text") )
                i_print_type = PRINT_TEXT;
            else if ( !strcmp(optarg, "xml") )
                i_print_type = PRINT_XML;
            else
                msg_Warn( NULL, "unrecognized print type %s", optarg );
            /* Make stdout line-buffered */
            setvbuf(stdout, NULL, _IOLBF, 0);
            break;

        case 'Q':
            i_quit_timeout_duration = strtoll( optarg, NULL, 0 ) * 1000;
            break;

        case 'V':
            DisplayVersion();
            exit(0);
            break;

        case 'Z':
            psz_mrtg_file = optarg;
            break;

        case 'h':
        default:
            usage();
        }
    }
    if ( optind < i_argc || pf_Open == NULL )
        usage();

    if ( b_enable_syslog )
        msg_Connect( psz_syslog_ident ? psz_syslog_ident : pp_argv[0] );

    if ( i_verbose )
        DisplayVersion();

    msg_Warn( NULL, "restarting" );
    switch (i_print_type) 
    {
        case PRINT_XML:
            printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
            printf("<TS>\n");
            break;
        default:
            break;
    }

    if ( b_udp_global )
    {
        msg_Warn( NULL, "raw UDP output is deprecated.  Please consider using RTP." );
        msg_Warn( NULL, "for DVB-IP compliance you should use RTP." );
    }

    if ( b_epg_global && !b_dvb_global )
    {
        msg_Dbg( NULL, "turning on DVB compliance, required by EPG information" );
        b_dvb_global = true;
    }

    memset( &output_dup, 0, sizeof(output_dup) );
    if ( psz_dup_config != NULL )
    {
        output_config_t config;

        config_Defaults( &config );
        if ( !config_ParseHost( &config, psz_dup_config ) )
            msg_Err( NULL, "Invalid target address for -d switch" );
        else
        {
            output_Init( &output_dup, &config );
            output_Change( &output_dup, &config );
        }

        config_Free( &config );
    }

    if ( strcasecmp( psz_native_charset, psz_dvb_charset ) )
    {
#ifdef HAVE_ICONV
        iconv_t iconv_system = iconv_open( psz_dvb_charset,
                                           psz_native_charset );
        if ( iconv_system != (iconv_t)-1 )
        {
            size_t i = strlen( psz_network_name );
            char *p, *psz_string;
            i_network_name_tmp_size = i * 6;
            p = psz_string = malloc(i_network_name_tmp_size);
            if ( iconv( iconv_system, (char **)&psz_network_name, &i, &p,
                        &i_network_name_tmp_size ) == -1 )
                free( psz_string );
            else
            {
                p_network_name_tmp = psz_string;
                i_network_name_tmp_size = p - psz_string;
            }
            iconv_close( iconv_system );
        }
#else
        msg_Warn( NULL,
                  "unable to convert from %s to %s (iconv is not available)",
                  psz_native_charset, psz_dvb_charset );
#endif
    }
    if ( p_network_name_tmp == NULL )
    {
        p_network_name_tmp = strdup(psz_network_name);
        i_network_name_tmp_size = strlen(psz_network_name);
    }
    p_network_name = dvb_string_set( (uint8_t *)p_network_name_tmp,
                                     i_network_name_tmp_size, psz_dvb_charset,
                                     &i_network_name_size );
    free( p_network_name_tmp );

    /* Set signal handlers */
    memset( &sa, 0, sizeof(struct sigaction) );
    sa.sa_handler = SigHandler;
    sigfillset( &set );

    if ( sigaction( SIGHUP, &sa, NULL ) == -1 || sigaction( SIGINT, &sa, NULL ) == -1 )
    {
        msg_Err( NULL, "couldn't set signal handler: %s", strerror(errno) );
        exit(EXIT_FAILURE);
    }

    srand( time(NULL) * getpid() );

    demux_Open();

    // init the mrtg logfile
    mrtgInit(psz_mrtg_file);

    if ( i_priority > 0 )
    {
        memset( &param, 0, sizeof(struct sched_param) );
        param.sched_priority = i_priority;
        if ( (i_error = pthread_setschedparam( pthread_self(), SCHED_RR,
                                               &param )) )
        {
            msg_Warn( NULL, "couldn't set thread priority: %s",
                      strerror(i_error) );
        }
    }

    config_ReadFile( psz_conf_file );

    if ( psz_srv_socket != NULL )
        comm_Open();

    for ( ; ; )
    {
        block_t *p_ts;

        if ( b_exit_now )
        {
            msg_Info( NULL, "Shutdown was requested." );
            break;
        }

        if ( b_conf_reload )
        {
            b_conf_reload = 0;
            msg_Info( NULL, "Configuration reload was requested." );
            config_ReadFile( psz_conf_file );
        }

        if ( i_quit_timeout && i_quit_timeout <= i_wallclock )
        {
            switch (i_print_type)
            {
            case PRINT_XML:
                printf("</TS>\n");
                break;
            default:
                break;
            }
            exit(EXIT_SUCCESS);
        }

        p_ts = pf_Read( i_poll_timeout );
        if ( p_ts != NULL )
        {
            mrtgAnalyse(p_ts);
            demux_Run( p_ts );
        }
        i_poll_timeout = output_Send();
        if ( i_poll_timeout == -1 || i_poll_timeout > MAX_POLL_TIMEOUT )
            i_poll_timeout = MAX_POLL_TIMEOUT;
    }

    mrtgClose();
    outputs_Close( i_nb_outputs );
    demux_Close();
    free( p_network_name );

    if ( b_enable_syslog )
        msg_Disconnect();

    if ( psz_srv_socket && i_comm_fd > -1 )
        unlink( psz_srv_socket );

    return EXIT_SUCCESS;
}