Linux-DVB-1.01/0000755000000000000000000000000011376355761011657 5ustar rootrootLinux-DVB-1.01/DVB.xs0000644000000000000000000006776311376355662012671 0ustar rootroot#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include #include #define CONST(name) { #name, name } typedef int FE_fd; enum { SCT_PAT = 0x00, SCT_CAT = 0x01, SCT_PMT = 0x02, SCT_TSDT = 0x03, SCT_NIT = 0x40,//TODO SCT_NIT_OTHER = 0x41, SCT_SDT = 0x42, SCT_SDT_OTHER = 0x46, SCT_BAT = 0x4a,//TODO SCT_EIT_PRESENT = 0x4e, SCT_EIT_PRESENT_OTHER = 0x4f, SCT_EIT_SCHEDULE0 = 0x50, SCT_EIT_SCHEDULE15 = 0x5f, SCT_EIT_SCHEDULE_OTHER0 = 0x60, SCT_EIT_SCHEDULE_OTHER15 = 0x6f, SCT_TDT = 0x70, SCT_RST = 0x71, SCT_ST = 0x72, SCT_TOT = 0x73, SCT_RNT = 0x74, SCT_CST = 0x75, SCT_RCT = 0x76, SCT_CIT = 0x77, SCT_MPE = 0x78, SCT_DIT = 0x7e, SCT_SIT = 0x7f, }; enum { DT_network_name = 0x40, DT_service_list = 0x41, DT_satellite_delivery_system = 0x43, DT_cable_delivery_system = 0x44, DT_service = 0x48, DT_country_availability = 0x49, DT_linkage = 0x4a, DT_short_event = 0x4d, DT_extended_event = 0x4e, //NYI DT_component = 0x50, DT_content = 0x54, DT_terrestrial_delivery_system = 0x5A, DT_private_data_specifier = 0x5f, DT_short_smoothing_buffer = 0x61, //NYI DT_scrambling_indicator = 0x65, //NYI DT_PDC = 0x69, }; static const struct consts { const char *name; const long value; } consts [] = { CONST (FE_QPSK), CONST (FE_QAM), CONST (FE_OFDM), CONST (FE_IS_STUPID), CONST (FE_CAN_INVERSION_AUTO), CONST (FE_CAN_FEC_1_2), CONST (FE_CAN_FEC_2_3), CONST (FE_CAN_FEC_3_4), CONST (FE_CAN_FEC_4_5), CONST (FE_CAN_FEC_5_6), CONST (FE_CAN_FEC_6_7), CONST (FE_CAN_FEC_7_8), CONST (FE_CAN_FEC_8_9), CONST (FE_CAN_FEC_AUTO), CONST (FE_CAN_QPSK), CONST (FE_CAN_QAM_16), CONST (FE_CAN_QAM_32), CONST (FE_CAN_QAM_64), CONST (FE_CAN_QAM_128), CONST (FE_CAN_QAM_256), CONST (FE_CAN_QAM_AUTO), CONST (FE_CAN_TRANSMISSION_MODE_AUTO), CONST (FE_CAN_BANDWIDTH_AUTO), CONST (FE_CAN_GUARD_INTERVAL_AUTO), CONST (FE_CAN_HIERARCHY_AUTO), CONST (FE_NEEDS_BENDING), CONST (FE_CAN_RECOVER), CONST (FE_CAN_MUTE_TS), CONST (FE_HAS_SIGNAL), CONST (FE_HAS_CARRIER), CONST (FE_HAS_VITERBI), CONST (FE_HAS_SYNC), CONST (FE_HAS_LOCK), CONST (FE_TIMEDOUT), CONST (FE_REINIT), CONST (INVERSION_OFF), CONST (INVERSION_ON), CONST (INVERSION_AUTO), CONST (FEC_NONE), CONST (FEC_1_2), CONST (FEC_2_3), CONST (FEC_3_4), CONST (FEC_4_5), CONST (FEC_5_6), CONST (FEC_6_7), CONST (FEC_7_8), CONST (FEC_8_9), CONST (FEC_AUTO), CONST (QPSK), CONST (QAM_16), CONST (QAM_32), CONST (QAM_64), CONST (QAM_128), CONST (QAM_256), CONST (QAM_AUTO), CONST (TRANSMISSION_MODE_2K), CONST (TRANSMISSION_MODE_8K), CONST (TRANSMISSION_MODE_AUTO), CONST (BANDWIDTH_8_MHZ), CONST (BANDWIDTH_7_MHZ), CONST (BANDWIDTH_6_MHZ), CONST (BANDWIDTH_AUTO), CONST (GUARD_INTERVAL_1_32), CONST (GUARD_INTERVAL_1_16), CONST (GUARD_INTERVAL_1_8), CONST (GUARD_INTERVAL_1_4), CONST (GUARD_INTERVAL_AUTO), CONST (HIERARCHY_NONE), CONST (HIERARCHY_1), CONST (HIERARCHY_2), CONST (HIERARCHY_4), CONST (HIERARCHY_AUTO), CONST (DMX_OUT_DECODER), CONST (DMX_OUT_TAP), CONST (DMX_OUT_TS_TAP), CONST (DMX_IN_FRONTEND), CONST (DMX_IN_DVR), CONST (DMX_PES_AUDIO0), CONST (DMX_PES_VIDEO0), CONST (DMX_PES_TELETEXT0), CONST (DMX_PES_SUBTITLE0), CONST (DMX_PES_PCR0), CONST (DMX_PES_AUDIO1), CONST (DMX_PES_VIDEO1), CONST (DMX_PES_TELETEXT1), CONST (DMX_PES_SUBTITLE1), CONST (DMX_PES_PCR1), CONST (DMX_PES_AUDIO2), CONST (DMX_PES_VIDEO2), CONST (DMX_PES_TELETEXT2), CONST (DMX_PES_SUBTITLE2), CONST (DMX_PES_PCR2), CONST (DMX_PES_AUDIO3), CONST (DMX_PES_VIDEO3), CONST (DMX_PES_TELETEXT3), CONST (DMX_PES_SUBTITLE3), CONST (DMX_PES_PCR3), CONST (DMX_PES_OTHER), CONST (DMX_PES_AUDIO), CONST (DMX_PES_VIDEO), CONST (DMX_PES_TELETEXT), CONST (DMX_PES_SUBTITLE), CONST (DMX_PES_PCR), //CONST (DMX_SCRAMBLING_EV), //CONST (DMX_FRONTEND_EV), CONST (DMX_CHECK_CRC), CONST (DMX_ONESHOT), CONST (DMX_IMMEDIATE_START), CONST (DMX_KERNEL_CLIENT), CONST (DMX_SOURCE_FRONT0), CONST (DMX_SOURCE_FRONT1), CONST (DMX_SOURCE_FRONT2), CONST (DMX_SOURCE_FRONT3), CONST (DMX_SOURCE_DVR0), CONST (DMX_SOURCE_DVR1), CONST (DMX_SOURCE_DVR2), CONST (DMX_SOURCE_DVR3), //CONST (DMX_SCRAMBLING_OFF), //CONST (DMX_SCRAMBLING_ON), // constants defined by this file CONST (SCT_PAT), CONST (SCT_CAT), CONST (SCT_PMT), CONST (SCT_TSDT), CONST (SCT_NIT), CONST (SCT_NIT_OTHER), CONST (SCT_SDT), CONST (SCT_SDT_OTHER), CONST (SCT_BAT), CONST (SCT_EIT_PRESENT), CONST (SCT_EIT_PRESENT_OTHER), CONST (SCT_EIT_SCHEDULE0), CONST (SCT_EIT_SCHEDULE15), CONST (SCT_EIT_SCHEDULE_OTHER0), CONST (SCT_EIT_SCHEDULE_OTHER15), CONST (SCT_TDT), CONST (SCT_RST), CONST (SCT_ST), CONST (SCT_TOT), CONST (SCT_RNT), CONST (SCT_CST), CONST (SCT_RCT), CONST (SCT_CIT), CONST (SCT_MPE), CONST (SCT_DIT), CONST (SCT_SIT), CONST (DT_network_name), CONST (DT_service_list), CONST (DT_satellite_delivery_system), CONST (DT_cable_delivery_system), CONST (DT_service), CONST (DT_country_availability), CONST (DT_linkage), CONST (DT_short_event), CONST (DT_extended_event), CONST (DT_component), CONST (DT_content), CONST (DT_terrestrial_delivery_system), CONST (DT_private_data_specifier), CONST (DT_short_smoothing_buffer), CONST (DT_scrambling_indicator), CONST (DT_PDC), }; #define HVS_S(hv,struct,member) hv_store (hv, #member, sizeof (#member) - 1, newSVpv (struct.member, 0), 0) #define HVS_I(hv,struct,member) hv_store (hv, #member, sizeof (#member) - 1, newSViv (struct.member), 0) #define HVS(hv,name,sv) hv_store (hv, #name, sizeof (#name) - 1, (sv), 0) static void get_parameters (HV *hv, struct dvb_frontend_parameters *p, fe_type_t type) { HVS_I (hv, (*p), frequency); HVS_I (hv, (*p), inversion); switch (type) { case FE_QPSK: HVS_I (hv, (*p).u.qpsk, symbol_rate); HVS_I (hv, (*p).u.qpsk, fec_inner); break; case FE_QAM: HVS_I (hv, (*p).u.qam, symbol_rate); HVS_I (hv, (*p).u.qam, fec_inner); HVS_I (hv, (*p).u.qam, modulation); break; case FE_OFDM: HVS_I (hv, (*p).u.ofdm, bandwidth); HVS_I (hv, (*p).u.ofdm, code_rate_HP); HVS_I (hv, (*p).u.ofdm, code_rate_LP); HVS_I (hv, (*p).u.ofdm, constellation); HVS_I (hv, (*p).u.ofdm, transmission_mode); break; } } #define HVF_I(hv,struct,member) \ if (v = hv_fetch (hv, #member, sizeof (#member) - 1, 0)) \ struct.member = SvIV (*v); \ else \ croak ("required hash key '%s' not specified", #member); static void set_parameters (HV *hv, struct dvb_frontend_parameters *p, fe_type_t type) { SV **v; HVF_I (hv, (*p), frequency); HVF_I (hv, (*p), inversion); switch (type) { case FE_QPSK: HVF_I (hv, (*p).u.qpsk, symbol_rate); HVF_I (hv, (*p).u.qpsk, fec_inner); break; case FE_QAM: HVF_I (hv, (*p).u.qam, symbol_rate); HVF_I (hv, (*p).u.qam, fec_inner); HVF_I (hv, (*p).u.qam, modulation); break; case FE_OFDM: HVF_I (hv, (*p).u.ofdm, bandwidth); HVF_I (hv, (*p).u.ofdm, code_rate_HP); HVF_I (hv, (*p).u.ofdm, code_rate_LP); HVF_I (hv, (*p).u.ofdm, constellation); HVF_I (hv, (*p).u.ofdm, transmission_mode); break; } } typedef unsigned char u8; static SV *dec_sv; static u8 *dec_data; static long dec_ofs, dec_len8; static U32 dec_field; STRLEN dec_len; #define decode_overflow (dec_ofs > dec_len8) static void decode_set (SV *data) { if (dec_sv) SvREFCNT_dec (dec_sv); dec_sv = newSVsv (data); dec_data = (u8 *)SvPVbyte (dec_sv, dec_len); dec_ofs = 0; dec_len8 = dec_len << 3; } static U32 decode_field (int bits) { u8 *p = dec_data + (dec_ofs >> 3); int frac = 8 - (dec_ofs & 7); dec_ofs += bits; if (decode_overflow) return dec_field = 0; U32 r = *p++; r &= (1UL << frac) - 1; if (bits < frac) r >>= (frac - bits); else { bits -= frac; while (bits >= 8) { r = (r << 8) | *p++; bits -= 8; } if (bits > 0) r = (r << bits) | (*p >> (8 - bits)); } return dec_field = r; } U32 clamp (U32 len) { return len < 4096 && len <= dec_len8 - (dec_ofs >> 3) + 1 /* +1 to detect overflows */ ? len : 0; } /* works on SvPOK strings ONLY */ void safe_sv_chop (SV *sv, STRLEN count) { if ((U32)count >= (U32)SvCUR (sv)) SvCUR_set (sv, 0); else sv_chop (sv, SvPVX (sv) + count); } U32 bcd_to_int (U32 bcd_number) { U32 result = 0; U32 multiplicator = 1; while (bcd_number != 0) { result += (bcd_number & 0x0f) * multiplicator; bcd_number >>= 4; multiplicator *= 10; } return result; } static SV * text2sv (u8 *data, U32 len) { dSP; SV *sv = newSVpvn ((char *)data, clamp (len)); PUSHMARK (SP); XPUSHs (sv); PUTBACK; call_pv ("Linux::DVB::Decode::text", G_VOID); return sv; } #define DEC_I(hv, bits, name) HVS (hv, name, newSViv (decode_field (bits))) #define DEC_T(hv, bytes, name) HVS (hv, name, text2sv (dec_data + (dec_ofs >> 3), clamp (bytes))), dec_ofs += clamp (bytes) << 3 #define DEC_S(hv, bytes, name) HVS (hv, name, newSVpvn ((char *)dec_data + (dec_ofs >> 3), clamp (bytes))), dec_ofs += clamp (bytes) << 3 static AV * decode_descriptors (long end) { AV *av = newAV (); while (dec_ofs < end) { HV *hv = newHV (); U8 type, len, len2; AV *av2; long end, end2; av_push (av, newRV_noinc ((SV *)hv)); DEC_I (hv, 8, type); type = dec_field; len = decode_field (8); end = dec_ofs + (len << 3); if (end > dec_len8) return av; switch (type) { case DT_network_name: DEC_T (hv, (end - dec_ofs) >> 3, network_name); break; case DT_service_list: { AV *services = newAV (); HVS (hv, services, newRV_noinc ((SV *)services)); while (dec_ofs < end) { HV *sv = newHV (); av_push (services, newRV_noinc ((SV *)sv)); DEC_I (sv, 16, service_id); DEC_I (sv, 8, service_type); } } break; case DT_satellite_delivery_system: HVS (hv, frequency, newSVuv (bcd_to_int (decode_field (32)))); HVS (hv, orbital_position, newSVnv (bcd_to_int (decode_field (32)) / 10)); DEC_I (hv, 1, west_east_flag); DEC_I (hv, 2, polarization); DEC_I (hv, 5, modulation); HVS (hv, symbol_rate, newSVuv (bcd_to_int (decode_field (28)))); DEC_I (hv, 4, fec_inner); break; case DT_cable_delivery_system: { I16 qam_modulation = -1; HVS (hv, frequency, newSVuv (bcd_to_int (decode_field (32)))); decode_field (12); // reserved DEC_I (hv, 4, fec_outer); DEC_I (hv, 8, modulation); if (dec_field >= 1 && dec_field <= 5) qam_modulation = 1 << dec_field + 3; HVS (hv, modulation_qam, newSViv (qam_modulation)); HVS (hv, symbol_rate, newSVuv (bcd_to_int (decode_field (28)))); DEC_I (hv, 4, fec_inner); break; } case DT_service: DEC_I (hv, 8, service_type); len2 = decode_field (8); DEC_T (hv, len2, service_provider_name); len2 = decode_field (8); DEC_T (hv, len2, service_name); break; case DT_country_availability: DEC_I (hv, 1, country_availability_flag); decode_field (7); DEC_S (hv, (end - dec_ofs) >> 3, private_data); //while (dec_ofs + 24 <= end) // av_push (av, break; case DT_linkage: DEC_I (hv, 16, transport_stream_id); DEC_I (hv, 16, original_network_id); DEC_I (hv, 16, service_id); DEC_I (hv, 8, linkage_type); if (dec_field == 8) { U32 hot, org; DEC_I (hv, 8, hand_over_type); hot = dec_field; decode_field (3); DEC_I (hv, 1, origin_type); org = dec_field; if (hot > 0x00 && hot < 0x04) DEC_I (hv, 16, network_id); if (org == 0) DEC_I (hv, 16, initial_service_id); } DEC_S (hv, (end - dec_ofs) >> 3, private_data); break; case DT_PDC: decode_field (4); DEC_I (hv, 20, programme_identification_label); break; case DT_component: decode_field (4); DEC_I (hv, 4, stream_content); DEC_I (hv, 8, component_type); DEC_I (hv, 8, component_tag); DEC_S (hv, 3, ISO_639_language_code); DEC_T (hv, (end - dec_ofs) >> 3, text); break; case DT_short_event: DEC_S (hv, 3, ISO_639_language_code); len2 = decode_field (8); DEC_T (hv, len2, event_name); len2 = decode_field (8); DEC_T (hv, len2, text); break; case DT_extended_event: DEC_I (hv, 4, descriptor_number); DEC_I (hv, 4, last_descriptor_number); DEC_S (hv, 3, ISO_639_language_code); len2 = decode_field (8); end2 = dec_ofs + (len2 << 3); av2 = newAV (); HVS (hv, items, newRV_noinc ((SV *)av2)); while (dec_ofs < end2) { AV *av3 = newAV (); len2 = decode_field (8); av_push (av3, text2sv (dec_data + (dec_ofs >> 3), len2)), dec_ofs += len << 3; len2 = decode_field (8); av_push (av3, text2sv (dec_data + (dec_ofs >> 3), len2)), dec_ofs += len << 3; av_push (av2, newRV_noinc ((SV *)av3)); } len2 = decode_field (8); DEC_T (hv, len2, text); break; case DT_content: av2 = newAV (); HVS (hv, items, newRV_noinc ((SV *)av2)); while (dec_ofs < end) { HV *ev = newHV (); DEC_I (ev, 4, content_nibble_level_1); DEC_I (ev, 4, content_nibble_level_2); DEC_I (ev, 4, user_nibble_1); DEC_I (ev, 4, user_nibble_2); av_push (av2, newRV_noinc ((SV *)ev)); } break; case DT_terrestrial_delivery_system: { I8 bandwidth_mhz = -1; HVS (hv, centre_frequency, newSVuv (decode_field (32) * 10)); DEC_I (hv, 3, bandwidth); if (dec_field <= 3) bandwidth_mhz = 8 - dec_field; HVS (hv, bandwidth_mhz, newSViv (bandwidth_mhz)); DEC_I (hv, 1, priority); DEC_I (hv, 1, time_slicing_indicator); DEC_I (hv, 1, mpe_fec_indicator); decode_field (2); // reserved DEC_I (hv, 2, constellation); DEC_I (hv, 3, hierarchy_information); DEC_I (hv, 3, code_rate_hp_stream); DEC_I (hv, 3, code_rate_lp_stream); DEC_I (hv, 2, guard_interval); DEC_I (hv, 2, transmission_mode); DEC_I (hv, 1, other_frequency_use); decode_field (32); } break; case DT_private_data_specifier: DEC_I (hv, 32, private_data_specifier); break; default: //fprintf (stderr, "UNKXXX %x\n", type);//D case 0: case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x8d: case 0x8e: case 0xb2: DEC_S (hv, len, raw_data); break; } dec_ofs = end; // re-sync, in case of problems } return av; } MODULE = Linux::DVB PACKAGE = Linux::DVB PROTOTYPES: DISABLE void _consts () PPCODE: const struct consts *c; for (c = consts; c < consts + sizeof (consts) / sizeof (consts[0]); c++) { XPUSHs (sv_2mortal (newSVpv (c->name, 0))); XPUSHs (sv_2mortal (newSViv (c->value))); } MODULE = Linux::DVB PACKAGE = Linux::DVB::Frontend SV * frontend_info (FE_fd fd) CODE: struct dvb_frontend_info fi; HV *hv; if (ioctl (fd, FE_GET_INFO, &fi) < 0) XSRETURN_UNDEF; hv = newHV (); HVS_S (hv, fi, name); HVS_I (hv, fi, type); HVS_I (hv, fi, type); HVS_I (hv, fi, frequency_min); HVS_I (hv, fi, frequency_max); HVS_I (hv, fi, frequency_stepsize); HVS_I (hv, fi, frequency_tolerance); HVS_I (hv, fi, symbol_rate_min); HVS_I (hv, fi, symbol_rate_max); HVS_I (hv, fi, symbol_rate_tolerance); HVS_I (hv, fi, notifier_delay); HVS_I (hv, fi, caps); RETVAL = (SV *)newRV_noinc ((SV *)hv); OUTPUT: RETVAL long read_status (FE_fd fd) CODE: fe_status_t st; if (ioctl (fd, FE_READ_STATUS, &st) < 0) XSRETURN_UNDEF; RETVAL = st; OUTPUT: RETVAL U32 read_ber (FE_fd fd) CODE: uint32_t ber; if (ioctl (fd, FE_READ_BER, &ber) < 0) XSRETURN_UNDEF; RETVAL = ber; OUTPUT: RETVAL U32 read_snr (FE_fd fd) CODE: uint32_t ber; if (ioctl (fd, FE_READ_SNR, &ber) < 0) XSRETURN_UNDEF; RETVAL = ber; OUTPUT: RETVAL I16 signal_strength (FE_fd fd) CODE: int16_t st; if (ioctl (fd, FE_READ_SIGNAL_STRENGTH, &st) < 0) XSRETURN_UNDEF; RETVAL = st; OUTPUT: RETVAL U32 uncorrected_blocks (FE_fd fd) CODE: uint32_t ubl; if (ioctl (fd, FE_READ_UNCORRECTED_BLOCKS, &ubl) < 0) XSRETURN_UNDEF; RETVAL = ubl; OUTPUT: RETVAL int _set (int fd, SV *parameters, int type) CODE: struct dvb_frontend_parameters p; if (!SvROK (parameters) || SvTYPE (SvRV (parameters)) != SVt_PVHV) croak ("Linux::DVB::Frontend::set requires a hash as argument"); set_parameters ((HV *)SvRV (parameters), &p, type); if (ioctl (fd, FE_SET_FRONTEND, &p) < 0) XSRETURN_UNDEF; RETVAL = 1; OUTPUT: RETVAL SV * _get (int fd, int type) CODE: struct dvb_frontend_parameters p; HV *hv; if (ioctl (fd, FE_GET_FRONTEND, &p) < 0) XSRETURN_UNDEF; hv = newHV (); get_parameters (hv, &p, type); RETVAL = (SV *)newRV_noinc ((SV *)hv); OUTPUT: RETVAL SV * _event (int fd, int type) CODE: struct dvb_frontend_event e; HV *hv; if (ioctl (fd, FE_GET_EVENT, &e) < 0) XSRETURN_UNDEF; hv = newHV (); HVS_I (hv, e, status); get_parameters (hv, &e.parameters, type); RETVAL = (SV *)newRV_noinc ((SV *)hv); OUTPUT: RETVAL int diseqc_reset_overload (FE_fd fd) CODE: RETVAL = !!ioctl (fd, FE_DISEQC_RESET_OVERLOAD); OUTPUT: RETVAL int diseqc_voltage (FE_fd fd, int volts) CODE: RETVAL = !!ioctl (fd, FE_SET_VOLTAGE, volts == 18 ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13); OUTPUT: RETVAL int diseqc_tone (FE_fd fd, int on) CODE: RETVAL = !!ioctl (fd, FE_SET_TONE, on ? SEC_TONE_ON : SEC_TONE_OFF); OUTPUT: RETVAL int diseqc_send_burst (FE_fd fd, int type) CODE: RETVAL = !!ioctl (fd, FE_DISEQC_SEND_BURST, type ? SEC_MINI_B : SEC_MINI_A); OUTPUT: RETVAL int diseqc_cmd (FE_fd fd, SV *command_) CODE: { STRLEN len; char *command = SvPVbyte (command_, len); struct dvb_diseqc_master_cmd cmd; memcpy (cmd.msg, command, len); cmd.msg_len = len; RETVAL = !!ioctl (fd, FE_DISEQC_SEND_MASTER_CMD, &cmd); } OUTPUT: RETVAL SV * diseqc_reply (FE_fd fd, int timeout_ms) CODE: { struct dvb_diseqc_slave_reply rep; rep.timeout = timeout_ms; if (!!ioctl (fd, FE_DISEQC_RECV_SLAVE_REPLY, &rep)) RETVAL = newSVpvn ((char *)rep.msg, rep.msg_len); else RETVAL = &PL_sv_undef; } OUTPUT: RETVAL MODULE = Linux::DVB PACKAGE = Linux::DVB::Demux int _start (int fd) ALIAS: _stop = 1 CODE: if (ioctl (fd, ix ? DMX_STOP : DMX_START, 0) < 0) XSRETURN_UNDEF; RETVAL = 1; OUTPUT: RETVAL int _filter (int fd, U16 pid, SV *filter, SV *mask, U32 timeout = 0, U32 flags = DMX_CHECK_CRC) CODE: struct dmx_sct_filter_params p; STRLEN l; char *s; memset (&p.filter, 0, sizeof (p.filter)); p.pid = pid; s = SvPVbyte (filter, l); if (l > DMX_FILTER_SIZE) l = DMX_FILTER_SIZE; memcpy (p.filter.filter, s, l); s = SvPVbyte (mask , l); if (l > DMX_FILTER_SIZE) l = DMX_FILTER_SIZE; memcpy (p.filter.mask , s, l); p.timeout = timeout; p.flags = flags; if (ioctl (fd, DMX_SET_FILTER, &p) < 0) XSRETURN_UNDEF; RETVAL = 1; OUTPUT: RETVAL int _pes_filter (int fd, U16 pid, long input, long output, long type, U32 flags = 0) CODE: struct dmx_pes_filter_params p; p.pid = pid; p.input = input; p.output = output; p.pes_type = type; p.flags = flags; if (ioctl (fd, DMX_SET_PES_FILTER, &p) < 0) XSRETURN_UNDEF; RETVAL = 1; OUTPUT: RETVAL int _buffer (int fd, unsigned long size) CODE: if (ioctl (fd, DMX_SET_BUFFER_SIZE, size) < 0) XSRETURN_UNDEF; RETVAL = 1; OUTPUT: RETVAL MODULE = Linux::DVB PACKAGE = Linux::DVB::Decode PREFIX = decode_ void decode_set (SV *data) CODE: int decode_len () CODE: RETVAL = (dec_ofs + 7) >> 3; OUTPUT: RETVAL U32 decode_field (int bits) SV * decode_si (SV *stream) CODE: HV *hv = newHV (); int syntax_indicator; U8 table_id; U16 length; long end; decode_set (stream); do { DEC_I (hv, 8, table_id); table_id = dec_field; } while (table_id == 0xff); syntax_indicator = decode_field (1); HVS (hv, section_syntax_indicator, newSViv (syntax_indicator)); decode_field (1); decode_field (2); length = decode_field (12); end = dec_ofs + (length << 3); if (syntax_indicator) { switch (table_id) { case SCT_NIT: case SCT_NIT_OTHER: { U16 descriptor_end_offset; DEC_I (hv, 16, network_id); decode_field (2); // reserved DEC_I (hv, 5, version_number); DEC_I (hv, 1, current_next_indicator); DEC_I (hv, 8, section_number); DEC_I (hv, 8, last_section_number); decode_field (4); // reserved AV *desc; descriptor_end_offset = dec_ofs + (decode_field (12) << 3); desc = decode_descriptors (descriptor_end_offset); HVS (hv,network_descriptors, newRV_noinc ((SV *)desc)); decode_field (4); //reserved decode_field (12); // Skip length, we read until the end AV *events = newAV (); HVS (hv, events, newRV_noinc ((SV *)events)); while (end - dec_ofs > 32) { long dll; HV *ev = newHV (); av_push (events, newRV_noinc ((SV *)ev)); DEC_I (ev, 16, transport_stream_id); DEC_I (ev, 16, original_network_id); decode_field (4); dll = dec_ofs + (decode_field (12) << 3); desc = decode_descriptors (dll); HVS (ev, descriptors, newRV_noinc ((SV *)desc)); } decode_field (32); // skip CRC } break; case SCT_EIT_PRESENT: case SCT_EIT_PRESENT_OTHER: case SCT_EIT_SCHEDULE0...SCT_EIT_SCHEDULE15: //GCC case SCT_EIT_SCHEDULE_OTHER0...SCT_EIT_SCHEDULE_OTHER15: //GCC { DEC_I (hv, 16, service_id); decode_field (2); DEC_I (hv, 5, version_number); DEC_I (hv, 1, current_next_indicator); DEC_I (hv, 8, section_number); DEC_I (hv, 8, last_section_number); DEC_I (hv, 16, transport_stream_id); DEC_I (hv, 16, original_network_id); DEC_I (hv, 8, segment_last_section_number); DEC_I (hv, 8, last_table_id); AV *events = newAV (); HVS (hv, events, newRV_noinc ((SV *)events)); while (end - dec_ofs > 32) { long dll; AV *desc; HV *ev = newHV (); av_push (events, newRV_noinc ((SV *)ev)); DEC_I (ev, 16, event_id); DEC_I (ev, 16, start_time_mjd); DEC_I (ev, 24, start_time_hms); DEC_I (ev, 24, duration); DEC_I (ev, 3, running_status); DEC_I (ev, 1, free_CA_mode); dll = dec_ofs + (decode_field (12) << 3); desc = decode_descriptors (dll); HVS (ev, descriptors, newRV_noinc ((SV *)desc)); } decode_field (32); // skip CRC } break; case SCT_SDT: case SCT_SDT_OTHER: DEC_I (hv, 16, transport_stream_id); decode_field (2); DEC_I (hv, 5, version_number); DEC_I (hv, 1, current_next_indicator); DEC_I (hv, 8, section_number); DEC_I (hv, 8, last_section_number); DEC_I (hv, 16, original_network_id); decode_field (8); AV *services = newAV (); HVS (hv, services, newRV_noinc ((SV *)services)); while (end - dec_ofs > 32) { HV *ev = newHV (); U32 dll; AV *desc; av_push (services, newRV_noinc ((SV *)ev)); DEC_I (ev, 16, service_id); decode_field (6); DEC_I (ev, 1, EIT_schedule_flags); DEC_I (ev, 1, EIT_present_following_flag); DEC_I (ev, 3, running_status); DEC_I (ev, 1, free_CA_mode); dll = dec_ofs + (decode_field (12) << 3); desc = decode_descriptors (dll); HVS (ev, descriptors, newRV_noinc ((SV *)desc)); } decode_field (32); // skip CRC break; default: DEC_S (hv, length, raw_data); break; } if (decode_overflow) { SvREFCNT_dec (hv); safe_sv_chop (stream, (end + 7) >> 3); XSRETURN_UNDEF; } safe_sv_chop (stream, (dec_ofs + 7) >> 3); } else { SvREFCNT_dec (hv); safe_sv_chop (stream, (end + 7) >> 3); XSRETURN_UNDEF; } RETVAL = (SV *)newRV_noinc ((SV *)hv); OUTPUT: RETVAL Linux-DVB-1.01/COPYING0000644000000000000000000000007710324260044012673 0ustar rootrootThis module is licensed under the same terms as perl itself. Linux-DVB-1.01/Changes0000644000000000000000000000211211376355746013151 0ustar rootrootRevision history for Perl extension Linux::DVB 1.01 Mon May 24 03:52:33 CEST 2010 - diseqc_cmd was broken (patch by Damjan Marion). 1.0 Thu Apr 17 06:46:11 CEST 2008 - applied patches and ideas by Mark Buechler to make it compile again with current kernels. - remove fec_inner from QAM. - add support for diseqc ioctls. 0.4 Tue Apr 12 03:02:24 CEST 2005 - incompatibly changed (fixed, improved) datetime decoding functions. 0.3 Mon Apr 11 23:13:42 CEST 2005 - implemented $frontend->set and updated eg/extract-si. - patch by Magnus Schmidt that adds more descriptor decodings. - updated dvbapi document url. - slightly improved documentation. - make decode_si more resistent against protocol errors, by dropping sections with syntax_indicator=0, more robustly skip illegal frames. 0.2 Thu Mar 3 21:10:52 CET 2005 - fix version mismatch. 0.02 Thu Mar 3 18:00:52 CET 2005 - change of contact address. 0.01 Mon Sep 6 08:24:43 CEST 2004 - original version; created by copying Convert-Scalar. Linux-DVB-1.01/DVB.pm0000644000000000000000000003652011376355752012636 0ustar rootroot=head1 NAME Linux::DVB - interface to (some parts of) the Linux DVB API =head1 SYNOPSIS use Linux::DVB; =head1 DESCRIPTION This module provides an interface to the Linux DVB API. It is a straightforward translation of the C API. You should read the Linux DVB API description to make any sense of this module. It can be found here: http://www.linuxtv.org/docs/dvbapi/dvbapi.html All constants from F and F are exported by their C name and by default. Noteworthy differences to the C API: unions and sub-structs are usually translated into flat perl hashes, i.e C becomes C<< $struct->{symbol_rate} >>. Noteworthy limitations of this module include: No interface to the video, audio and net devices. If you need this functionality bug the author. =cut package Linux::DVB; use Fcntl (); BEGIN { $VERSION = '1.01'; @ISA = qw(Exporter); require XSLoader; XSLoader::load __PACKAGE__, $VERSION; require Exporter; my %consts = &_consts; my $consts; while (my ($k, $v) = each %consts) { push @EXPORT, $k; $consts .= "sub $k(){$v}\n"; } eval $consts; } sub new { my ($class, $path, $mode) = @_; my $self = bless { path => $path, mode => $mode }, $class; sysopen $self->{fh}, $path, $mode | &Fcntl::O_NONBLOCK or die "$path: $!"; $self->{fd} = fileno $self->{fh}; $self; } sub fh { $_[0]{fh} } sub fd { $_[0]{fd} } sub blocking { fcntl $_[0]{fh}, &Fcntl::F_SETFL, $_[1] ? 0 : &Fcntl::O_NONBLOCK; } package Linux::DVB::Frontend; @ISA = qw(Linux::DVB); =head1 Linux::DVB::Frontend CLASS =head2 SYNOPSIS my $fe = new Linux::DVB::Frontend $path, $writable; my $fe = new Linux::DVB::Frontend "/dev/dvb/adapter0/frontend0", 1; $fe->fh; # filehandle $fe->fd; # fileno $fe->blocking (0); # or 1 $fe->{name} $fe->{type} $fe->frontend_info->{name} $fe->status & FE_HAS_LOCK print $fe->ber, $fe->snr, $fe->signal_strength, $fe->uncorrected; my $tune = $fe->parameters; $tune->{frequency}; $tune->{symbol_rate}; =over 4 =cut sub new { my ($class, $path, $mode) = @_; my $self = $class->SUPER::new ($path, $mode ? &Fcntl::O_RDWR : &Fcntl::O_RDONLY); %$self = ( %$self, %{ $self->frontend_info } ); $self; } =item $fe->set (parameter => value, ...) Sets frontend parameters. All values are stuffed into the C structure without conversion and passed to FE_SET_FRONTEND. Returns true on success. All modes: frequency => inversion => QPSK frontends: symbol_rate => fec_inner => QAM frontends: symbol_rate => modulation => QFDM frontends: bandwidth => code_rate_HP => code_rate_LP => constellation => transmission_mode => =cut sub set { my ($self) = shift; _set $self->{fd}, { @_ }, $self->{type} } =item $fe->parameters Calls FE_GET_FRONTEND and returns a hash reference that contains the same keys as given to the C method. Example: Data::Dumper::Dumper $fe->get { frequency => 426000000, # 426 Mhz inversion => 0, # INVERSION_OFF symbol_rate => 6900000, # 6.9 MB/s modulation => 3, # QAM_64 } =cut sub parameters { _get ($_[0]{fd}, $_[0]{type}) } sub get { _get ($_[0]{fd}, $_[0]{type}) } # unannounced alias sub event { _event ($_[0]{fd}, $_[0]{type}) } =item $ok = $fe->diseqc_reset_overload If the bus has been automatically powered off due to power overload, this call restores the power to the bus. The call requires read/write access to the device. This call has no effect if the device is manually powered off. Not all DVB adapters support this call. =item $ok = $fe->diseqc_voltage (13|18) Set the DiSEqC voltage to either 13 or 18 volts. =item $ok = $fe->diseqc_tone (1|0) Enables (1) or disables (0) the DiSEqC continuous 22khz tone generation. =item $ok = $fe->diseqc_send_burst (0|1) Sends a 22KHz tone burst of type SEC_MINI_A (0) or SEC_MINI_B (1). =item $ok = $fe->diseqc_cmd ($command) Sends a DiSEqC command ($command is 3 to 6 bytes of binary data). =item $reply = $fe->diseqc_reply ($timeout) Receives a reply to a DiSEqC 2.0 command and returns it as a binary octet string 0..4 bytes in length (or C in the error case). =cut package Linux::DVB::Demux; @ISA = qw(Linux::DVB); =back =head1 Linux::DVB::Demux CLASS =head2 SYNOPSIS my $dmx = new Linux::DVB::Demux "/dev/dvb/adapter0/demux0"; $fe->fh; # filehandle $fe->fd; # fileno $fe->blocking (1); # non-blocking is default $dmx->buffer (16384); $dmx->sct_filter ($pid, "filter", "mask", $timeout=0, $flags=DMX_CHECK_CRC); $dmx->pes_filter ($pid, $input, $output, $type, $flags=0); $dmx->start; $dmx->stop; =over 4 =cut sub new { my ($class, $path) = @_; my $self = $class->SUPER::new ($path, &Fcntl::O_RDWR); $self; } sub start { _start ($_[0]{fd}) } sub stop { _stop ($_[0]{fd}) } sub sct_filter { _filter ($_[0]{fd}, @_[1, 2, 3, 4, 5]) } sub pes_filter { _pes_filter ($_[0]{fd}, @_[1, 2, 3, 4, 5]) } sub buffer { _buffer ($_[0]{fd}, $_[1]) } package Linux::DVB::Decode; =back =head1 Linux::DVB::Decode CLASS =head2 SYNOPSIS $si_decoded_hashref = Linux::DVB::Decode::si $section_data; =over 4 =cut =item $hashref = Linux::DVB::Decode::si $section_data Tries to parse the string inside C<$section_data> as an SI table and return it as a hash reference. Only the first SI table will be returned as hash reference, and the C<$section_data> will be modified in-place by removing the table data. The way to use this function is to append new data to your C<$section_data> and then call C in a loop until it returns C. Please ntoe, however, that the Linux DVB API will return only one table at a time from sysread, so you can safely assume that every sysread will return exactly one (or zero in case of errors) SI table. Here is an example of what to expect: { 'segment_last_section_number' => 112, 'table_id' => 81, 'service_id' => 28129, 'original_network_id' => 1, 'section_syntax_indicator' => 1, 'current_next_indicator' => 1, 'events' => [ { 'running_status' => 0, 'start_time_hms' => 2097152, 'event_id' => 39505, 'free_CA_mode' => 0, 'start_time_mjd' => 53470, 'descriptors' => [ { 'event_name' => 'Nachrichten', 'text' => '', 'ISO_639_language_code' => 'deu', 'type' => 77 }, { 'programme_identification_label' => 337280, 'type' => 105 }, { 'raw_data' => '22:0010.04#00', 'type' => 130 } ], 'duration' => 1280 }, { 'running_status' => 0, 'start_time_hms' => 2098432, 'event_id' => 39506, 'free_CA_mode' => 0, 'start_time_mjd' => 53470, 'descriptors' => [ { 'event_name' => 'SR 1 - Nachtwerk', 'text' => '', 'ISO_639_language_code' => 'deu', 'type' => 77 }, { 'programme_identification_label' => 337285, 'type' => 105 }, { 'raw_data' => '22:0510.04#00', 'type' => 130 } ], 'duration' => 87296 } ], 'last_table_id' => 81, 'section_number' => 112, 'last_section_number' => 176, 'version_number' => 31, 'transport_stream_id' => 1101 } =item $text = Linux::DVB::Decode::text $data Converts text found in DVB si tables into perl text. Only iso-8859-1..-11 and UTF-16 is supported, other encodings (big5 etc. is not. Bug me if you need this). =cut sub text($) { use Encode; for ($_[0]) { s/^([\x01-\x0b])// and $_ = decode sprintf ("iso-8859-%d", 4 + ord $1), $_; # 10 - pardon you??? s/^\x11// and $_ = decode "utf16-be", $_; # 12 ksc5601, DB # 13 db2312, DB # 14 big5(?), DB s/\x8a/\n/g; #s/([\x00-\x09\x0b-\x1f\x80-\x9f])/sprintf "{%02x}", ord $1/ge; s/([\x00-\x09\x0b-\x1f\x80-\x9f])//ge; } } =item %Linux::DVB::Decode::nibble_to_genre A two-level hash mapping genre nibbles to genres, e.g. $Linux::DVB::Decode::nibble_to_genre{7}{6} => 'film/cinema' =cut our %nibble_to_genre = ( 0x1 => { 0x0 => 'Movie/Drama (general)', 0x1 => 'Movie - detective/thriller', 0x2 => 'Movie - adventure/western/war', 0x3 => 'Movie - science fiction/fantasy/horror', 0x4 => 'Movie - comedy', 0x5 => 'Movie - soap/melodrama/folkloric', 0x6 => 'Movie - romance', 0x7 => 'Movie - serious/classical/religious/historical movie/drama', 0x8 => 'Movie - adult movie/drama', }, 0x2 => { 0x0 => 'News/Current Affairs (general)', 0x1 => 'news/weather report', 0x2 => 'news magazine', 0x3 => 'documentary', 0x4 => 'discussion/interview/debate', }, 0x3 => { 0x0 => 'Show/Game Show (general)', 0x1 => 'game show/quiz/contest', 0x2 => 'variety show', 0x3 => 'talk show', }, 0x4 => { 0x0 => 'Sports (general)', 0x1 => 'special events (Olympic Games, World Cup etc.)', 0x2 => 'sports magazines', 0x3 => 'football/soccer', 0x4 => 'tennis/squash', 0x5 => 'team sports (excluding football)', 0x6 => 'athletics', 0x7 => 'motor sport', 0x8 => 'water sport', 0x9 => 'winter sports', 0xA => 'equestrian', 0xB => 'martial sports', }, 0x5 => { 0x0 => 'Childrens/Youth (general)', 0x1 => "pre-school children's programmes", 0x2 => 'entertainment programmes for 6 to 14', 0x3 => 'entertainment programmes for 10 to 16', 0x4 => 'informational/educational/school programmes', 0x5 => 'cartoons/puppets', }, 0x6 => { 0x0 => 'Music/Ballet/Dance (general)', 0x1 => 'rock/pop', 0x2 => 'serious music or classical music', 0x3 => 'folk/traditional music', 0x4 => 'jazz', 0x5 => 'musical/opera', 0x6 => 'ballet', }, 0x7 => { 0x0 => 'Arts/Culture (without music, general)', 0x1 => 'performing arts', 0x2 => 'fine arts', 0x3 => 'religion', 0x4 => 'popular culture/traditional arts', 0x5 => 'literature', 0x6 => 'film/cinema', 0x7 => 'experimental film/video', 0x8 => 'broadcasting/press', 0x9 => 'new media', 0xA => 'arts/culture magazines', 0xB => 'fashion', }, 0x8 => { 0x0 => 'Social/Policical/Economics (general)', 0x1 => 'magazines/reports/documentary', 0x2 => 'economics/social advisory', 0x3 => 'remarkable people', }, 0x9 => { 0x0 => 'Education/Science/Factual (general)', 0x1 => 'nature/animals/environment', 0x2 => 'technology/natural sciences', 0x3 => 'medicine/physiology/psychology', 0x4 => 'foreign countries/expeditions', 0x5 => 'social/spiritual sciences', 0x6 => 'further education', 0x7 => 'languages', }, 0xA => { 0x0 => 'Leisure/Hobbies (general)', 0x1 => 'tourism/travel', 0x2 => 'handicraft', 0x3 => 'motoring', 0x4 => 'fitness & health', 0x5 => 'cooking', 0x6 => 'advertizement/shopping', 0x7 => 'gardening', }, 0xB => { 0x0 => '(original language)', 0x1 => '(black & white)', 0x2 => '(unpublished)', 0x3 => '(live broadcast)', }, ); =item ($sec,$min,$hour) = Linux::DVB::Decode::time $hms =item ($mday,$mon,$year) = Linux::DVB::Decode::date $mjd =item ($sec,$min,$hour,$mday,$mon,$year) = Linux::DVB::Decode::datetime $mjd, $hms =item $sec = Linux::DVB::Decode::time_linear $hms =item $sec = Linux::DVB::Decode::datetime_linear $mjd, $hms Break down a "DVB time" (modified julian date + bcd encoded seconds) into it's components (non-C<_linear>) or into a seconds count (C<_linear> variants) since the epoch (C) or the start of the day (C). The format of the returns value of the date and datetime functions is I compatible with C. Use the C<_linear> functions instead. Example: my $time = Linux::DVB::Decode::datetime_linear $mjd, $hms printf "Starts at %s\n", POSIX::strftime "%Y-%m-%d %H:%M:%S", localtime $time; =cut sub time($) { my ($time) = @_; # Time is in UTC, 24 bit, every nibble one digit in BCD from right to left my $hour = sprintf "%02x", ($time >> 16) & 0xFF; my $minute = sprintf "%02x", ($time >> 8) & 0xFF; my $second = sprintf "%02x", ($time ) & 0xFF; ($second, $minute, $hour) } sub date($) { my ($mjd) = @_; # Date is given in Modified Julian Date # Decoding routines taken from ANNEX C, ETSI EN 300 468 (DVB SI) my $y_ = int (($mjd - 15078.2) / 365.25); my $m_ = int (($mjd - 14956.1 - int ($y_ * 365.25)) / 30.6001); my $day = $mjd - 14956 - int ($y_ * 365.25) - int ($m_ * 30.6001); my $k = $m_ == 14 or $m_ == 15 ? 1 : 0; my $year = $y_ + $k + 1900; my $month = $m_ - 1 - $k * 12; ($day, $month, $year) } sub datetime($$) { (Linux::DVB::Decode::time $_[1], date $_[0]) } sub time_linear($) { my ($s, $m, $h) = Linux::DVB::Decode::time $_[0]; (($h * 60) + $m * 60) + $s } sub datetime_linear($$) { my ($sec, $min, $hour, $mday, $mon, $year) = Linux::DVB::Decode::datetime $_[0], $_[1]; require Time::Local; Time::Local::timegm ($sec, $min, $hour, $mday, $mon - 1, $year) } =back =head1 AUTHORS Marc Lehmann , http://home.schmorp.de/ Magnus Schmidt, eMail at http://www.27b-6.de/email.php =cut 1 Linux-DVB-1.01/MANIFEST0000644000000000000000000000023511376355761013010 0ustar rootrootREADME Changes MANIFEST COPYING Makefile.PL DVB.pm DVB.xs typemap t/00_load.t META.yml Module meta-data (added by MakeMaker) Linux-DVB-1.01/t/0000755000000000000000000000000011376355761012122 5ustar rootrootLinux-DVB-1.01/t/00_load.t0000644000000000000000000000017010211641032013473 0ustar rootrootBEGIN { $| = 1; print "1..1\n"; } END {print "not ok 1\n" unless $loaded;} use Linux::DVB; $loaded = 1; print "ok 1\n"; Linux-DVB-1.01/typemap0000644000000000000000000000033210435144173013243 0ustar rootrootFE_fd T_FE_FD INPUT T_FE_FD if (sv_derived_from ($arg, \"Linux::DVB::Frontend\")) $var = ($type) SvIV (*hv_fetch ((HV*)SvRV ($arg), \"fd\", 2, 1)); else croak (\"$var is not of type Linux::DVB::Frontend\") Linux-DVB-1.01/README0000644000000000000000000002233011376355761012537 0ustar rootrootNAME Linux::DVB - interface to (some parts of) the Linux DVB API SYNOPSIS use Linux::DVB; DESCRIPTION This module provides an interface to the Linux DVB API. It is a straightforward translation of the C API. You should read the Linux DVB API description to make any sense of this module. It can be found here: http://www.linuxtv.org/docs/dvbapi/dvbapi.html All constants from frontend.h and demux.h are exported by their C name and by default. Noteworthy differences to the C API: unions and sub-structs are usually translated into flat perl hashes, i.e "struct.u.qam.symbol_rate" becomes "$struct->{symbol_rate}". Noteworthy limitations of this module include: No interface to the video, audio and net devices. If you need this functionality bug the author. Linux::DVB::Frontend CLASS SYNOPSIS my $fe = new Linux::DVB::Frontend $path, $writable; my $fe = new Linux::DVB::Frontend "/dev/dvb/adapter0/frontend0", 1; $fe->fh; # filehandle $fe->fd; # fileno $fe->blocking (0); # or 1 $fe->{name} $fe->{type} $fe->frontend_info->{name} $fe->status & FE_HAS_LOCK print $fe->ber, $fe->snr, $fe->signal_strength, $fe->uncorrected; my $tune = $fe->parameters; $tune->{frequency}; $tune->{symbol_rate}; $fe->set (parameter => value, ...) Sets frontend parameters. All values are stuffed into the "dvb_frontend_parameters" structure without conversion and passed to FE_SET_FRONTEND. Returns true on success. All modes: frequency => inversion => QPSK frontends: symbol_rate => fec_inner => QAM frontends: symbol_rate => modulation => QFDM frontends: bandwidth => code_rate_HP => code_rate_LP => constellation => transmission_mode => $fe->parameters Calls FE_GET_FRONTEND and returns a hash reference that contains the same keys as given to the "set" method. Example: Data::Dumper::Dumper $fe->get { frequency => 426000000, # 426 Mhz inversion => 0, # INVERSION_OFF symbol_rate => 6900000, # 6.9 MB/s modulation => 3, # QAM_64 } $ok = $fe->diseqc_reset_overload If the bus has been automatically powered off due to power overload, this call restores the power to the bus. The call requires read/write access to the device. This call has no effect if the device is manually powered off. Not all DVB adapters support this call. $ok = $fe->diseqc_voltage (13|18) Set the DiSEqC voltage to either 13 or 18 volts. $ok = $fe->diseqc_tone (1|0) Enables (1) or disables (0) the DiSEqC continuous 22khz tone generation. $ok = $fe->diseqc_send_burst (0|1) Sends a 22KHz tone burst of type SEC_MINI_A (0) or SEC_MINI_B (1). $ok = $fe->diseqc_cmd ($command) Sends a DiSEqC command ($command is 3 to 6 bytes of binary data). $reply = $fe->diseqc_reply ($timeout) Receives a reply to a DiSEqC 2.0 command and returns it as a binary octet string 0..4 bytes in length (or "undef" in the error case). Linux::DVB::Demux CLASS SYNOPSIS my $dmx = new Linux::DVB::Demux "/dev/dvb/adapter0/demux0"; $fe->fh; # filehandle $fe->fd; # fileno $fe->blocking (1); # non-blocking is default $dmx->buffer (16384); $dmx->sct_filter ($pid, "filter", "mask", $timeout=0, $flags=DMX_CHECK_CRC); $dmx->pes_filter ($pid, $input, $output, $type, $flags=0); $dmx->start; $dmx->stop; Linux::DVB::Decode CLASS SYNOPSIS $si_decoded_hashref = Linux::DVB::Decode::si $section_data; $hashref = Linux::DVB::Decode::si $section_data Tries to parse the string inside $section_data as an SI table and return it as a hash reference. Only the first SI table will be returned as hash reference, and the $section_data will be modified in-place by removing the table data. The way to use this function is to append new data to your $section_data and then call "Linux::DVB::Decode::si" in a loop until it returns "undef". Please ntoe, however, that the Linux DVB API will return only one table at a time from sysread, so you can safely assume that every sysread will return exactly one (or zero in case of errors) SI table. Here is an example of what to expect: { 'segment_last_section_number' => 112, 'table_id' => 81, 'service_id' => 28129, 'original_network_id' => 1, 'section_syntax_indicator' => 1, 'current_next_indicator' => 1, 'events' => [ { 'running_status' => 0, 'start_time_hms' => 2097152, 'event_id' => 39505, 'free_CA_mode' => 0, 'start_time_mjd' => 53470, 'descriptors' => [ { 'event_name' => 'Nachrichten', 'text' => '', 'ISO_639_language_code' => 'deu', 'type' => 77 }, { 'programme_identification_label' => 337280, 'type' => 105 }, { 'raw_data' => '22:0010.04#00', 'type' => 130 } ], 'duration' => 1280 }, { 'running_status' => 0, 'start_time_hms' => 2098432, 'event_id' => 39506, 'free_CA_mode' => 0, 'start_time_mjd' => 53470, 'descriptors' => [ { 'event_name' => 'SR 1 - Nachtwerk', 'text' => '', 'ISO_639_language_code' => 'deu', 'type' => 77 }, { 'programme_identification_label' => 337285, 'type' => 105 }, { 'raw_data' => '22:0510.04#00', 'type' => 130 } ], 'duration' => 87296 } ], 'last_table_id' => 81, 'section_number' => 112, 'last_section_number' => 176, 'version_number' => 31, 'transport_stream_id' => 1101 } $text = Linux::DVB::Decode::text $data Converts text found in DVB si tables into perl text. Only iso-8859-1..-11 and UTF-16 is supported, other encodings (big5 etc. is not. Bug me if you need this). %Linux::DVB::Decode::nibble_to_genre A two-level hash mapping genre nibbles to genres, e.g. $Linux::DVB::Decode::nibble_to_genre{7}{6} => 'film/cinema' ($sec,$min,$hour) = Linux::DVB::Decode::time $hms ($mday,$mon,$year) = Linux::DVB::Decode::date $mjd ($sec,$min,$hour,$mday,$mon,$year) = Linux::DVB::Decode::datetime $mjd, $hms $sec = Linux::DVB::Decode::time_linear $hms $sec = Linux::DVB::Decode::datetime_linear $mjd, $hms Break down a "DVB time" (modified julian date + bcd encoded seconds) into it's components (non-"_linear") or into a seconds count ("_linear" variants) since the epoch ("datetime_linear") or the start of the day ("time_linear"). The format of the returns value of the date and datetime functions is *not* compatible with "Time::Local". Use the "_linear" functions instead. Example: my $time = Linux::DVB::Decode::datetime_linear $mjd, $hms printf "Starts at %s\n", POSIX::strftime "%Y-%m-%d %H:%M:%S", localtime $time; AUTHORS Marc Lehmann , http://home.schmorp.de/ Magnus Schmidt, eMail at http://www.27b-6.de/email.php Linux-DVB-1.01/Makefile.PL0000644000000000000000000000053511225724104013614 0ustar rootrootuse ExtUtils::MakeMaker; use 5.006; WriteMakefile( dist => { PREOP => 'pod2text DVB.pm | tee README >$(DISTVNAME)/README; chmod -R u=rwX,go=rX . ;', COMPRESS => 'gzip -9v', SUFFIX => '.gz', }, INC => "-I/usr/src/linux/include", NAME => "Linux::DVB", VERSION_FROM => "DVB.pm", ); Linux-DVB-1.01/META.yml0000644000000000000000000000072611376355761013135 0ustar rootroot--- #YAML:1.0 name: Linux-DVB version: 1.01 abstract: ~ author: [] license: unknown distribution_type: module configure_requires: ExtUtils::MakeMaker: 0 build_requires: ExtUtils::MakeMaker: 0 requires: {} no_index: directory: - t - inc generated_by: ExtUtils::MakeMaker version 6.55_02 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4