Example #1
0
/** @brief Reads the program map table
 *
 * It's used to get the differents "useful" pids of the channel
 * @param pmt the pmt packet
 * @param channel the associated channel
 */
int autoconf_read_pmt(mumudvb_ts_packet_t *pmt, mumudvb_channel_t *channel, char *card_base_path, int tuner, uint8_t *asked_pid, uint8_t *number_chan_asked_pid,fds_t *fds)
{
	int section_len, descr_section_len, i,j;
	int pid;
	int pid_type;
	int found=0;
	pmt_t *header;
	pmt_info_t *descr_header;

	int program_info_length;
	int channel_update;

	//For channel update
	int temp_pids[MAX_PIDS];
	int temp_pids_type[MAX_PIDS];
	char temp_pids_language[MAX_PIDS][4];
	//For channel update
	int temp_num_pids=0;

	pid_type=0;

	section_len=pmt->len_full;
	header=(pmt_t *)pmt->data_full;

	if(header->table_id!=0x02)
	{
		log_message( log_module,  MSG_INFO,"Packet PID %d for channel \"%s\" is not a PMT PID. We remove the pmt pid for this channel\n", pmt->pid, channel->name);
		channel->pmt_pid=0; /** @todo : put a threshold, */
		return 1;
	}

	//We check if this PMT belongs to the current channel. (Only works with autoconfiguration full for the moment because it stores the service_id)
	if(channel->service_id && (channel->service_id != HILO(header->program_number)) )
	{
		log_message( log_module,  MSG_DETAIL,"The PMT %d does not belongs to channel \"%s\"\n", pmt->pid, channel->name);
		return 1;
	}

	/*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table
  sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable
  and shall be the next table to become valid.*/
	if(header->current_next_indicator == 0)
	{
		log_message( log_module, MSG_DEBUG,"The current_next_indicator is set to 0, this PMT is not valid for the current stream\n");
		return 1;
	}


	log_message( log_module,  MSG_DEBUG,"PMT (PID %d) read for autoconfiguration of channel \"%s\"\n", pmt->pid, channel->name);

	channel_update=channel->num_pids>1?1:0;
	if(channel_update)
	{
		// Update
		log_message( log_module,  MSG_INFO,"Channel %s update\n",channel->name);
		temp_pids[0]=pmt->pid;
		temp_num_pids++;
#ifdef ENABLE_CAM_SUPPORT
		// Reset of the CA SYS saved for the chanel
		for (i=0; i<32; i++)
			channel->ca_sys_id[i]=0;
#endif
	}

	program_info_length=HILO(header->program_info_length); //program_info_length
	char language[4]="";
	int pos=0;

	//we read the different descriptors included in the pmt
	//for more information see ITU-T Rec. H.222.0 | ISO/IEC 13818 table 2-34
	for (i=program_info_length+PMT_LEN; i<=section_len-(PMT_INFO_LEN+4); i+=descr_section_len+PMT_INFO_LEN)
	{
		//we parse the part after the descriptors
		//we map the descriptor header
		descr_header=(pmt_info_t *)(pmt->data_full+i);
		//We get the length of the descriptor
		descr_section_len=HILO(descr_header->ES_info_length);        //ES_info_length

		// Default language value if not found
		snprintf(language,4,"%s","---");
		// Default, no position found
		pos=0;

		pid=HILO(descr_header->elementary_PID);
		//Depending of the stream type we'll take or not this pid
		switch(descr_header->stream_type)
		{
		case 0x01:
			pid_type=PID_VIDEO_MPEG1;
			log_message( log_module,  MSG_DEBUG,"  Video MPEG1 \tpid %d\n",pid);
			break;
		case 0x02:
			pid_type=PID_VIDEO_MPEG2;
			log_message( log_module,  MSG_DEBUG,"  Video MPEG2 \tpid %d\n",pid);
			break;
		case 0x10: /* ISO/IEC 14496-2 Visual - MPEG4 video */
			pid_type=PID_VIDEO_MPEG4_ASP;
			log_message( log_module,  MSG_DEBUG,"  Video MPEG4-ASP \tpid %d\n",pid);
			break;
		case 0x1b: /* AVC video stream as defined in ITU-T Rec. H.264 | ISO/IEC 14496-10 Video */
			pid_type=PID_VIDEO_MPEG4_AVC;
			log_message( log_module,  MSG_DEBUG,"  Video MPEG4-AVC \tpid %d\n",pid);
			break;
		case 0x03:
			pid_type=PID_AUDIO_MPEG1;
			log_message( log_module,  MSG_DEBUG,"  Audio MPEG1 \tpid %d\n",pid);
			break;
		case 0x04:
			pid_type=PID_AUDIO_MPEG2;
			log_message( log_module,  MSG_DEBUG,"  Audio MPEG2 \tpid %d\n",pid);
			break;
		case 0x11: /* ISO/IEC 14496-3 Audio with the LATM transport syntax as defined in ISO/IEC 14496-3 */
			pid_type=PID_AUDIO_AAC_LATM;
			log_message( log_module,  MSG_DEBUG,"  Audio AAC-LATM \tpid %d\n",pid);
			break;
		case 0x0f: /* ISO/IEC 13818-7 Audio with ADTS transport syntax - usually AAC */
			pid_type=PID_AUDIO_AAC_ADTS;
			log_message( log_module,  MSG_DEBUG,"  Audio AAC-ADTS \tpid %d\n",pid);
			break;
		case 0x81: /* Audio per ATSC A/53B [2] Annex B */
			pid_type=PID_AUDIO_ATSC;
			log_message( log_module,  MSG_DEBUG,"  Audio ATSC A/53B \tpid %d\n",pid);
			break;



		case 0x06: /* Descriptor defined in EN 300 468 */
			if(descr_section_len) //If we have an accociated descriptor, we'll search inforation in it
			{
				if(pmt_find_descriptor(0x45,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  VBI Data \tpid %d\n",pid);
					pid_type=PID_EXTRA_VBIDATA;
				}else if(pmt_find_descriptor(0x46,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  VBI Teletext \tpid %d\n",pid);
					pid_type=PID_EXTRA_VBITELETEXT;
				}else if(pmt_find_descriptor(0x56,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  Teletext \tpid %d\n",pid);
					pid_type=PID_EXTRA_TELETEXT;
				}else if(pmt_find_descriptor(0x59,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, &pos)){
					log_message( log_module,  MSG_DEBUG,"  Subtitling \tpid %d\n",pid);
					pid_type=PID_EXTRA_SUBTITLE;
					char * lng=(char *)(pmt->data_full+i+PMT_INFO_LEN+pos+2);
					language[0]=lng[0];
					language[1]=lng[1];
					language[2]=lng[2];
					language[3]=0;
				}else if(pmt_find_descriptor(0x6a,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  AC3 (audio) \tpid %d\n",pid);
					pid_type=PID_AUDIO_AC3;
				}else if(pmt_find_descriptor(0x7a,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  Enhanced AC3 (audio) \tpid %d\n",pid);
					pid_type=PID_AUDIO_EAC3;
				}else if(pmt_find_descriptor(0x7b,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  DTS (audio) \tpid %d\n",pid);
					pid_type=PID_AUDIO_DTS;
				}else if(pmt_find_descriptor(0x7c,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  AAC (audio) \tpid %d\n",pid);
					pid_type=PID_AUDIO_AAC;
				}else
				{
					log_message( log_module,  MSG_DEBUG,"Unknown descriptor see EN 300 468 v1.9.1 table 12, pid %d descriptor tags : ", pid);
					pmt_print_descriptor_tags(pmt->data_full+i+PMT_INFO_LEN,descr_section_len);
					log_message( log_module,  MSG_DEBUG,"\n");
					continue;
				}
			}
			else
			{
				log_message( log_module,  MSG_DEBUG,"PMT read : stream type 0x06 without descriptor\n");
				continue;
			}
			break;

			//Now, the list of what we drop
		case 0x05:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : 0x05, ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private_sections \n",pid);
			continue;
			//Digital Storage Medium Command and Control (DSM-CC) cf H.222.0 | ISO/IEC 13818-1 annex B
		case 0x0a:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : 0x0A ISO/IEC 13818-6 type A (DSM-CC)\n",pid);
			continue;
		case 0x0b:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : 0x0B ISO/IEC 13818-6 type B (DSM-CC)\n",pid);
			continue;
		case 0x0c:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : 0x0C ISO/IEC 13818-6 type C (DSM-CC)\n",pid);
			continue;
		case 0x0D:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : ISO/IEC 13818-6 type D",pid);
			continue;
		case 0x0E:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : ITU-T Rec. H.222.0 | ISO/IEC 13818-1 auxiliary",pid);
			continue;
		case 0x12:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in PES packets",pid);
			continue;
		case 0x13:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in ISO/IEC 14496_sections",pid);
			continue;
		case 0x14:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : ISO/IEC 13818-6 Synchronized Download Protocol",pid);
			continue;
		case 0x15:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : Metadata carried in PES packets",pid);
			continue;
		case 0x16:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : Metadata carried in metadata_sections",pid);
			continue;
		case 0x17:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : Metadata carried in ISO/IEC 13818-6 Data Carousel",pid);
			continue;
		case 0x18:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : Metadata carried in ISO/IEC 13818-6 Object Carousel",pid);
			continue;
		case 0x19:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : Metadata carried in ISO/IEC 13818-6 Synchronized Download Protocol",pid);
			continue;
		case 0x1A:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : IPMP stream (defined in ISO/IEC 13818-11, MPEG-2 IPMP)",pid);
			continue;
		case 0x7F:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : IPMP stream",pid);
			continue;
		default:
			if(descr_header->stream_type >= 0x1C && descr_header->stream_type <= 0x7E)
				log_message( log_module,  MSG_DEBUG, "Dropped pid %d, stream type : 0x%02x : ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved",pid,descr_header->stream_type);
			else if(descr_header->stream_type >= 0x80)
				log_message( log_module,  MSG_DEBUG, "Dropped pid %d, stream type : 0x%02x : User Private",pid,descr_header->stream_type);
			else
				log_message( log_module,  MSG_INFO, "!!!!Unknown stream type : 0x%02x, PID : %d cf ITU-T Rec. H.222.0 | ISO/IEC 13818\n",descr_header->stream_type,pid);
			continue;
		}

		//We keep this pid

		// We try to find a 0x0a (ISO639) descriptor to have language information about the stream
		pos=0;
		if(pmt_find_descriptor(0x0a,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, &pos)){
			char * lng=(char *)(pmt->data_full+i+PMT_INFO_LEN+pos+2);
			language[0]=lng[0];
			language[1]=lng[1];
			language[2]=lng[2];
			language[3]=0;
		}
		log_message( log_module,  MSG_DEBUG,"  PID Language Code = %s\n",language);

		//For cam debugging purposes, we look if we can find a ca descriptor to display ca system ids
		if(descr_section_len)
		{
			int pos;
			int casysid;
			pos=0;
			while(pmt_find_descriptor(0x09,pmt->data_full+i+PMT_INFO_LEN,descr_section_len,&pos))
			{
				descr_ca_t *ca_descriptor;
				ca_descriptor=(descr_ca_t *)(pmt->data_full+i+PMT_INFO_LEN+pos);
				casysid=0;
				while(casysid<32 && channel->ca_sys_id[casysid] && channel->ca_sys_id[casysid]!=HILO(ca_descriptor->CA_type) )
					casysid++;
				if(casysid<32 && !channel->ca_sys_id[casysid])
				{
					channel->ca_sys_id[casysid]=HILO(ca_descriptor->CA_type);
					log_message( log_module,  MSG_DETAIL,"Ca system id 0x%04x : %s\n", HILO(ca_descriptor->CA_type), ca_sys_id_to_str(HILO(ca_descriptor->CA_type)));//we display it with the description
				}
				if(casysid==32)
					log_message( log_module,  MSG_WARN,"Too much Ca system id line %d file %s\n", __LINE__,__FILE__);
				pos+=ca_descriptor->descriptor_length+2;
			}
		}

		if(channel_update)
		{
			temp_pids[temp_num_pids]=pid;
			temp_pids_type[temp_num_pids]=pid_type;
			snprintf(temp_pids_language[temp_num_pids],4,"%s",language);
			temp_num_pids++;
			if (temp_num_pids >= MAX_PIDS)
			{
				log_message( log_module,  MSG_ERROR,
						"Too many PIDs : %d\n",
						temp_num_pids);
				temp_num_pids--;
			}
		}
		else
		{
			channel->pids[channel->num_pids]=pid;
			channel->pids_type[channel->num_pids]=pid_type;
			snprintf(channel->pids_language[channel->num_pids],4,"%s",language);
			channel->num_pids++;
		}
	}

	/**************************
	 * PCR PID
	 **************************/

	channel->pcr_pid=HILO(header->PCR_PID); //The PCR pid.
	//we check if it's not already included (ie the pcr is carried with the video)
	found=0;
	for(i=0;i<channel->num_pids;i++)
	{
		if((channel_update && temp_pids[i]==channel->pcr_pid) || (!channel_update && channel->pids[i]==channel->pcr_pid))
			found=1;
	}
	if(!found)
	{
		if(channel_update)
		{
			temp_pids[temp_num_pids]=channel->pcr_pid;
			temp_pids_type[temp_num_pids]=PID_PCR;
			snprintf(temp_pids_language[temp_num_pids],4,"%s","---");
			temp_num_pids++;
		}
		else
		{
			channel->pids[channel->num_pids]=channel->pcr_pid;
			channel->pids_type[channel->num_pids]=PID_PCR;
			snprintf(channel->pids_language[channel->num_pids],4,"%s","---");
			channel->num_pids++;
		}
	}
	log_message( log_module,  MSG_DEBUG, "PCR pid %d\n",channel->pcr_pid);

	/**************************
	 * PCR PID - END
	 **************************/
	//We store the PMT version useful to check for updates
	channel->pmt_version=header->version_number;

	/**************************
	 * Channel update
	 **************************/
	//If it's a channel update we will have to update the filters
	if(channel_update)
	{
		log_message( log_module,  MSG_DEBUG,"Channel update new number of pids %d old %d we check for changes\n", temp_num_pids, channel->num_pids);

		//We search for added pids
		for(i=0;i<temp_num_pids;i++)
		{
			found=0;
			for(j=0;j<channel->num_pids;j++)
			{
				if(channel->pids[j]==temp_pids[i])
					found=1;
			}
			if(!found)
			{
				log_message( log_module,  MSG_DETAIL, "Update : pid %d added \n",temp_pids[i]);
				//If the pid is not on the list we add it for the filters
				if(asked_pid[temp_pids[i]]==PID_NOT_ASKED)
					asked_pid[temp_pids[i]]=PID_ASKED;

				number_chan_asked_pid[temp_pids[i]]++;
				channel->pids[channel->num_pids]=temp_pids[i];
				channel->pids_type[channel->num_pids]=temp_pids_type[i];
				snprintf(channel->pids_language[channel->num_pids],4,"%s",temp_pids_language[i]);
				channel->num_pids++;

				log_message( log_module, MSG_DETAIL,"Add the new filters\n");
				// we open the file descriptors
				if (create_card_fd (card_base_path, tuner, asked_pid, fds) < 0)
				{
					log_message( log_module, MSG_ERROR,"CANNOT open the new descriptors. Some channels will probably not work\n");
					//return; //FIXME : what do we do here ?
				}
				//open the new filters
				set_filters(asked_pid, fds);

			}
		}
		//We search for suppressed pids
		for(i=0;i<channel->num_pids;i++)
		{
			found=0;
			for(j=0;j<temp_num_pids;j++)
			{
				if(channel->pids[i]==temp_pids[j])
					found=1;
			}
			if(!found)
			{
				log_message( log_module,  MSG_DETAIL, "Update : pid %d supressed \n",channel->pids[i]);

				//We check the number of channels on wich this pid is registered, if 0 it's strange we warn
				if((channel->pids[i]>MAX_MANDATORY_PID_NUMBER )&& (number_chan_asked_pid[channel->pids[i]]))
				{
					//We decrease the number of channels with this pid
					number_chan_asked_pid[channel->pids[i]]--;
					//If no channel need this pid anymore, we remove the filter (closing the file descriptor remove the filter associated)
					if(number_chan_asked_pid[channel->pids[i]]==0)
					{
						log_message( log_module,  MSG_DEBUG, "Update : pid %d does not belong to any channel anymore, we close the filter \n",channel->pids[i]);
						close(fds->fd_demuxer[channel->pids[i]]);
						fds->fd_demuxer[channel->pids[i]]=0;
						asked_pid[channel->pids[i]]=PID_NOT_ASKED;
					}
				}
				else
					log_message( log_module,  MSG_WARN, "Update : We tried to suppress pid %d in a strange way, please contact if you can reproduce\n",channel->pids[i]);
				//We remove the pid from this channel by swapping with the last one and decreasing the pid number
				channel->pids[i]=channel->pids[channel->num_pids-1];
				channel->num_pids--;
				i--; //we wan to check the pid just moved so we force the loop to reaxamine pid i

			}
		}
		log_message( log_module,  MSG_DETAIL, "        pids : \n");/**@todo Generate a strind and call log_message after, in syslog it generates one line per pid : use the toolbox unicast*/
		int ipid;
		for (ipid = 0; ipid < channel->num_pids; ipid++)
			log_message( log_module,  MSG_DETAIL, "              %d (%s) \n", channel->pids[ipid], pid_type_to_str(channel->pids_type[ipid]));

	}
	/** @todo : update generated conf file*/
	/**************************
	 * Channel update END
	 **************************/
	/*************************
	 * Language template
	 **************************/
	found =0;
	int len=MAX_NAME_LEN;
	for(i=0;i<channel->num_pids && !found;i++)
	{
		if(channel->pids_language[i][0]!='-')
		{
			log_message( log_module,  MSG_FLOOD, "Primary language for channel: %s",channel->pids_language[i]);
			mumu_string_replace(channel->name,&len,0,"%lang",channel->pids_language[i]);
			found=1; //we exit the loop
		}
	}
	//If we don't find a lang we replace by our "usual" ---
	if(!found)
		mumu_string_replace(channel->name,&len,0,"%lang",channel->pids_language[0]);
	/*************************
	 * Language template END
	 **************************/

	log_message( log_module,  MSG_DEBUG,"Number of pids after autoconf %d\n", channel->num_pids);
	return 0;
}
Example #2
0
/** @brief : List the DVB cards of the system and their capabilities
 * 
 */
void list_dvb_cards ()
{
  DIR *dvb_dir;
  log_message( log_module, MSG_INFO,"==================================");
  log_message( log_module, MSG_INFO,"        DVB CARDS LISTING\n");
  log_message( log_module, MSG_INFO,"==================================");

  dvb_dir = opendir ("/dev/dvb/");
  if (dvb_dir == NULL)
  {
    log_message( log_module,  MSG_ERROR, "Cannot open /dev/dvb : %s\n", strerror (errno));
    return;
  }

  int card_number;
  int num_cards;
  int cards[256];
  num_cards=0;
  struct dirent *d_adapter;
  while ((d_adapter=readdir(dvb_dir))!=NULL)
  {
    if(strlen(d_adapter->d_name)<8)
      continue;
    if(strncmp(d_adapter->d_name,"adapter",7))
      continue;
    card_number= atoi(d_adapter->d_name+7);
    log_message( log_module,  MSG_DEBUG, "found adapter %d\n", card_number);
    cards[num_cards]=card_number;
    num_cards++;
    if(num_cards==256)
    {
      log_message( log_module, MSG_ERROR, "Wow You have a system with more than 256 DVB cards, Please Contact me :D\n");
      return;
    }
  }
  closedir(dvb_dir);

  //Basic card sorting (O(N^2))
  int i,j,old_card;
  old_card=-1;
  DIR *adapter_dir;
  /** The path of the card */
  char card_dev_path[256];
  int tuner_number;
  struct dirent *d_tuner;
  for(i=0;i<num_cards;i++)
  {
    card_number=-1;
    for(j=0;j<num_cards;j++)
	if((card_number<=old_card)||((cards[j]>old_card) && (cards[j]<card_number)))
	  card_number=cards[j];
	old_card=card_number;

    strncpy(card_dev_path,DVB_DEV_PATH,256);
    char number[10];
    sprintf(number,"%d",card_number);
    int l=sizeof(card_dev_path);
    mumu_string_replace(card_dev_path,&l,0,"%card",number);
    adapter_dir = opendir (card_dev_path);
    if (adapter_dir == NULL)
    {
      log_message( log_module,  MSG_ERROR, "Cannot open %s : %s\n", card_dev_path, strerror (errno));
      return;
    }
    while ((d_tuner=readdir(adapter_dir))!=NULL)
    {
      if(strlen(d_tuner->d_name)<(strlen(FRONTEND_DEV_NAME)+1))
        continue;
      if(strncmp(d_tuner->d_name,FRONTEND_DEV_NAME,strlen(FRONTEND_DEV_NAME)))
        continue;
      tuner_number= atoi(d_tuner->d_name+strlen(FRONTEND_DEV_NAME));
      log_message( log_module,  MSG_DEBUG, "\tCard %d found Frontend %d\n", card_number, tuner_number);
      /** show the current tuner */
      show_card_capabilities( card_number , tuner_number);
    }
    closedir(adapter_dir);
  }
}
Example #3
0
/** @brief : List the capabilities of one card
 * 
 * 
 */
void show_card_capabilities( int card, int tuner )
{
  int frontend_fd;
  int i_ret;
  int display_sr;
  int frequency_factor;
  /** The path of the card */
  char card_dev_path[256];
  strncpy(card_dev_path,DVB_DEV_PATH,256);
  char number[10];
  sprintf(number,"%d",card);
  int l=sizeof(card_dev_path);
  mumu_string_replace(card_dev_path,&l,0,"%card",number);
  //Open the frontend
  if(!open_fe (&frontend_fd, card_dev_path, tuner,0)) // we open the card readonly so we can get the capabilities event when used
    return;

  //get frontend info
  struct dvb_frontend_info fe_info;
  if ( (i_ret = ioctl(frontend_fd,FE_GET_INFO, &fe_info) < 0)){
    log_message( log_module,  MSG_ERROR, "FE_GET_INFO: %s \n", strerror(errno));
    return;
  }
  log_message( log_module,  MSG_INFO, "=========== Card %d - Tuner %d ===========\n", card, tuner);
  log_message( log_module,  MSG_INFO, " Frontend : %s\n", fe_info.name);
  display_sr=0;
  switch(fe_info.type)
  {
    case FE_OFDM:
      log_message( log_module,  MSG_INFO, " Terrestrial (DVB-T) card\n");
      break;
    case FE_QPSK:
      log_message( log_module,  MSG_INFO, " Satellite (DVB-S) card\n");
      display_sr=1;
      break;
    case FE_QAM:
      log_message( log_module,  MSG_INFO, " Cable (DVB-C) card\n");
      display_sr=1;
      break;
    case FE_ATSC:
      log_message( log_module,  MSG_INFO, " ATSC card\n");
      break;
  }
  if(fe_info.type==FE_QPSK)
    frequency_factor=1000;
  else
    frequency_factor=1;
  if (frequency_factor!=0)
    log_message( log_module,  MSG_INFO, " Frequency: %d kHz to %d kHz\n",(int) fe_info.frequency_min/1000*frequency_factor,(int) fe_info.frequency_max/1000*frequency_factor);
  else
    log_message( log_module,  MSG_WARN, " frequency_factor=0\n");
  if(display_sr)
    log_message( log_module,  MSG_INFO, " Symbol rate: %d k symbols/s to %d k symbols/s \n", (int)fe_info.symbol_rate_min/1000, (int)fe_info.symbol_rate_max/1000);

  log_message( log_module,  MSG_DETAIL, " == Card capabilities ==");
  log_message( log_module,  MSG_DEBUG, "caps 0x%x\n",fe_info.caps);
  frontend_cap_t caps[]={
    {0x1,"FE_CAN_INVERSION_AUTO"},
    {0x2,"FE_CAN_FEC_1_2"},
    {0x4,"FE_CAN_FEC_2_3"},
    {0x8,"FE_CAN_FEC_3_4"},
    {0x10,"FE_CAN_FEC_4_5"},
    {0x20,"FE_CAN_FEC_5_6"},
    {0x40,"FE_CAN_FEC_6_7"},
    {0x80,"FE_CAN_FEC_7_8"},
    {0x100,"FE_CAN_FEC_8_9"},
    {0x200,"FE_CAN_FEC_AUTO"},
    {0x400,"FE_CAN_QPSK"},
    {0x800,"FE_CAN_QAM_16"},
    {0x1000,"FE_CAN_QAM_32"},
    {0x2000,"FE_CAN_QAM_64"},
    {0x4000,"FE_CAN_QAM_128"},
    {0x8000,"FE_CAN_QAM_256"},
    {0x10000,"FE_CAN_QAM_AUTO"},
    {0x20000,"FE_CAN_TRANSMISSION_MODE_AUTO"},
    {0x40000,"FE_CAN_BANDWIDTH_AUTO"},
    {0x80000,"FE_CAN_GUARD_INTERVAL_AUTO"},
    {0x100000,"FE_CAN_HIERARCHY_AUTO"},
    {0x200000,"FE_CAN_8VSB"},
    {0x400000,"FE_CAN_16VSB"},
    {0x800000,"FE_HAS_EXTENDED_CAPS /* We need more bitspace for newer APIs, indicate this. */"},
    {0x10000000,"FE_CAN_2G_MODULATION /* frontend supports '2nd generation modulation' (DVB-S2) */"},
    {0x20000000,"FE_NEEDS_BENDING /* not supported anymore */"},
    {0x40000000,"FE_CAN_RECOVER /* frontend can recover from a cable unplug automatically */"},
    {0x80000000,"FE_CAN_MUTE_TS /* frontend can stop spurious TS data output */"},
  };
  int numcaps=28;
  int i;
  for(i=0;i<numcaps;i++)
    if(fe_info.caps & caps[i].flag)
      log_message( log_module,  MSG_DETAIL, "%s\n", caps[i].descr);
  close (frontend_fd);

  log_message( log_module,  MSG_INFO, "\n");

}
Example #4
0
/** @brief This function is called when a new packet is there and the autoconf is not finished*/
int autoconf_new_packet(int pid, unsigned char *ts_packet, autoconf_parameters_t *autoconf_vars, fds_t *fds, mumudvb_chan_and_pids_t *chan_and_pids, tuning_parameters_t *tuneparams, multicast_parameters_t *multicast_vars,  unicast_parameters_t *unicast_vars, int server_id)
{
  int iRet=0;
  if(autoconf_vars->autoconfiguration==AUTOCONF_MODE_FULL) //Full autoconfiguration, we search the channels and their names
  {
    if(pid==0) //PAT : contains the services identifiers and the PMT PID for each service
    {
      if(get_ts_packet(ts_packet,autoconf_vars->autoconf_temp_pat))
      {
        if(autoconf_read_pat(autoconf_vars))
        {
          log_message( log_module, MSG_DEBUG,"It seems that we have finished to get the services list\n");
          //we finish full autoconfiguration
          iRet = autoconf_finish_full(chan_and_pids, autoconf_vars, multicast_vars, tuneparams, fds, unicast_vars, server_id);
        }
      }
    }
    else if(pid==17) //SDT : contains the names of the services
    {
      if(get_ts_packet(ts_packet,autoconf_vars->autoconf_temp_sdt))
      {
        autoconf_read_sdt(autoconf_vars->autoconf_temp_sdt->data_full,autoconf_vars->autoconf_temp_sdt->len_full,autoconf_vars->services);
      }
    }
    else if(pid==PSIP_PID && tuneparams->fe_type==FE_ATSC) //PSIP : contains the names of the services
    {
      if(get_ts_packet(ts_packet,autoconf_vars->autoconf_temp_psip))
      {
        autoconf_read_psip(autoconf_vars);
      }
    }
  }
  else if(autoconf_vars->autoconfiguration==AUTOCONF_MODE_PIDS) //We have the channels and their PMT, we search the other pids
  {
    int curr_channel;
    for(curr_channel=0;curr_channel<MAX_CHANNELS;curr_channel++)
    {
      if((!chan_and_pids->channels[curr_channel].autoconfigurated) &&(chan_and_pids->channels[curr_channel].pmt_pid==pid)&& pid)
      {
        if(get_ts_packet(ts_packet,chan_and_pids->channels[curr_channel].pmt_packet))
	{
	  //Now we have the PMT, we parse it
          if(autoconf_read_pmt(chan_and_pids->channels[curr_channel].pmt_packet, &chan_and_pids->channels[curr_channel], tuneparams->card_dev_path, tuneparams->tuner, chan_and_pids->asked_pid, chan_and_pids->number_chan_asked_pid, fds)==0)
          {
            log_pids(log_module,&chan_and_pids->channels[curr_channel],curr_channel);

            chan_and_pids->channels[curr_channel].autoconfigurated=1;

            //We parse the NIT before finishing autoconfiguration
	      autoconf_vars->autoconfiguration=AUTOCONF_MODE_NIT;
            for (curr_channel = 0; curr_channel < chan_and_pids->number_of_channels; curr_channel++)
              if(!chan_and_pids->channels[curr_channel].autoconfigurated)
                autoconf_vars->autoconfiguration=AUTOCONF_MODE_PIDS;  //not finished we continue

            //if it's finished, we open the new descriptors and add the new filters
            if(autoconf_vars->autoconfiguration!=AUTOCONF_MODE_PIDS)
            {
              autoconf_set_channel_filt(tuneparams->card_dev_path, tuneparams->tuner, chan_and_pids, fds);
              //We free autoconf memory
              autoconf_freeing(autoconf_vars);
	      if(autoconf_vars->autoconfiguration==AUTOCONF_MODE_NIT)
		log_message( log_module, MSG_DETAIL,"We search for the NIT\n");
              else
                autoconf_definite_end(tuneparams->card, tuneparams->tuner, chan_and_pids, multicast_vars, unicast_vars);
            }
          }
        }
      }
    }
  }
  else if(autoconf_vars->autoconfiguration==AUTOCONF_MODE_NIT) //We search the NIT
  {
    if(pid==16) //NIT : Network Information Table
    {
      if(get_ts_packet(ts_packet,autoconf_vars->autoconf_temp_nit))
      {
	log_message( log_module, MSG_FLOOD,"New NIT\n");
        if(autoconf_read_nit(autoconf_vars, chan_and_pids->channels, chan_and_pids->number_of_channels)==0)
	{
	  autoconf_vars->autoconfiguration=0;
          int curr_channel;
          char lcn[4];
          int len=MAX_NAME_LEN;
          for(curr_channel=0;curr_channel<MAX_CHANNELS;curr_channel++)
          {
            if(chan_and_pids->channels[curr_channel].logical_channel_number)
            {
              sprintf(lcn,"%03d",chan_and_pids->channels[curr_channel].logical_channel_number);
              mumu_string_replace(chan_and_pids->channels[curr_channel].name,&len,0,"%lcn",lcn);
              sprintf(lcn,"%02d",chan_and_pids->channels[curr_channel].logical_channel_number);
              mumu_string_replace(chan_and_pids->channels[curr_channel].name,&len,0,"%2lcn",lcn);
            }
            else
            {
              mumu_string_replace(chan_and_pids->channels[curr_channel].name,&len,0,"%lcn","");
              mumu_string_replace(chan_and_pids->channels[curr_channel].name,&len,0,"%2lcn","");
            }
          }
	  free(autoconf_vars->autoconf_temp_nit);
	  autoconf_vars->autoconf_temp_nit=NULL;
          autoconf_definite_end(tuneparams->card, tuneparams->tuner, chan_and_pids, multicast_vars, unicast_vars);
	}
      }
    }
  }
  return Interrupted;
}
Example #5
0
/** @brief Convert the chained list of services into channels
 *
 * This function is called when We've got all the services, we now fill the channels structure
 * After that we go in AUTOCONF_MODE_PIDS to get audio and video pids
 * @param parameters The autoconf parameters
 * @param channels Chained list of channels
 * @param port The mulicast port
 * @param card The card number for the ip address
 * @param unicast_vars The unicast parameters
 * @param fds The file descriptors (for filters and unicast)
 */
int autoconf_services_to_channels(autoconf_parameters_t parameters, mumudvb_channel_t *channels, int port, int card, int tuner, unicast_parameters_t *unicast_vars, multicast_parameters_t *multicast_vars, int server_id)
{

  mumudvb_service_t *actual_service;
  int channel_number=0;
  int found_in_service_id_list;
  int unicast_port_per_channel;
  char tempstring[256];
  actual_service=parameters.services;
  unicast_port_per_channel=strlen(parameters.autoconf_unicast_port)?1:0;

  do
  {
    if(parameters.autoconf_scrambled && actual_service->free_ca_mode)
        log_message( log_module, MSG_DETAIL,"Service scrambled. Name \"%s\"\n", actual_service->name);

    //If there is a service_id list we look if we find it (option autoconf_sid_list)
    if(parameters.num_service_id)
    {
      int actual_service_id;
      found_in_service_id_list=0;
      for(actual_service_id=0;actual_service_id<parameters.num_service_id && !found_in_service_id_list;actual_service_id++)
      {
        if(parameters.service_id_list[actual_service_id]==actual_service->id)
        {
          found_in_service_id_list=1;
          log_message( log_module, MSG_DEBUG,"Service found in the service_id list. Name \"%s\"\n", actual_service->name);
        }
      }
    }
    else //No ts id list so it is found
      found_in_service_id_list=1;

    if(!parameters.autoconf_scrambled && actual_service->free_ca_mode)
      log_message( log_module, MSG_DETAIL,"Service scrambled, no CAM support and no autoconf_scrambled, we skip. Name \"%s\"\n", actual_service->name);
    else if(!actual_service->pmt_pid)
      log_message( log_module, MSG_DETAIL,"Service without a PMT pid, we skip. Name \"%s\"\n", actual_service->name);
    else if(!found_in_service_id_list)
      log_message( log_module, MSG_DETAIL,"Service NOT in the service_id list, we skip. Name \"%s\", id %d\n", actual_service->name, actual_service->id);
    else //service is ok, we make it a channel
    {
      //Cf EN 300 468 v1.9.1 Table 81
      if((actual_service->type==0x01||
          actual_service->type==0x11||
          actual_service->type==0x16||
          actual_service->type==0x19)||
          ((actual_service->type==0x02||
          actual_service->type==0x0a)&&parameters.autoconf_radios))
      {
        log_message( log_module, MSG_DETAIL,"We convert a new service into a channel, sid %d pmt_pid %d name \"%s\" \n",
			  actual_service->id, actual_service->pmt_pid, actual_service->name);
        display_service_type(actual_service->type, MSG_DETAIL, log_module);

        channels[channel_number].channel_type=actual_service->type;
        channels[channel_number].num_packet = 0;
        channels[channel_number].num_scrambled_packets = 0;
        channels[channel_number].scrambled_channel = 0;
        channels[channel_number].streamed_channel = 1;
        channels[channel_number].nb_bytes=0;
        channels[channel_number].pids[0]=actual_service->pmt_pid;
        channels[channel_number].pids_type[0]=PID_PMT;
        channels[channel_number].num_pids=1;
        snprintf(channels[channel_number].pids_language[0],4,"%s","---");
        if(strlen(parameters.name_template))
        {
          strcpy(channels[channel_number].name,parameters.name_template);
          int len=MAX_NAME_LEN;
          char number[10];
          mumu_string_replace(channels[channel_number].name,&len,0,"%name",actual_service->name);
          sprintf(number,"%d",channel_number+1);
          mumu_string_replace(channels[channel_number].name,&len,0,"%number",number);
          //put LCN here
        }
        else
          strcpy(channels[channel_number].name,actual_service->name);
        if(multicast_vars->multicast)
        {
          char number[10];
          char ip[80];
          int len=80;
          if(strlen(parameters.autoconf_multicast_port))
          {
            strcpy(tempstring,parameters.autoconf_multicast_port);
            sprintf(number,"%d",channel_number);
            mumu_string_replace(tempstring,&len,0,"%number",number);
            sprintf(number,"%d",card);
            mumu_string_replace(tempstring,&len,0,"%card",number);
            sprintf(number,"%d",tuner);
            mumu_string_replace(tempstring,&len,0,"%tuner",number);
            sprintf(number,"%d",server_id);
            mumu_string_replace(tempstring,&len,0,"%server",number);
            channels[channel_number].portOut=string_comput(tempstring);
          }
          else
          {
            channels[channel_number].portOut=port;//do here the job for evaluating the string
          }
	  if(multicast_vars->multicast_ipv4)
	    {
	      strcpy(ip,parameters.autoconf_ip4);
	      sprintf(number,"%d",channel_number);
	      mumu_string_replace(ip,&len,0,"%number",number);
	      sprintf(number,"%d",card);
	      mumu_string_replace(ip,&len,0,"%card",number);
	      sprintf(number,"%d",tuner);
	      mumu_string_replace(ip,&len,0,"%tuner",number);
	      sprintf(number,"%d",server_id);
	      mumu_string_replace(ip,&len,0,"%server",number);
	      strcpy(channels[channel_number].ip4Out,ip);
	      log_message( log_module, MSG_DEBUG,"Channel IPv4 : \"%s\" port : %d\n",channels[channel_number].ip4Out,channels[channel_number].portOut);
	    }
	  if(multicast_vars->multicast_ipv6)
	    {
	      strcpy(ip,parameters.autoconf_ip6);
	      sprintf(number,"%d",channel_number);
	      mumu_string_replace(ip,&len,0,"%number",number);
	      sprintf(number,"%d",card);
	      mumu_string_replace(ip,&len,0,"%card",number);
	      sprintf(number,"%d",tuner);
	      mumu_string_replace(ip,&len,0,"%tuner",number);
	      sprintf(number,"%d",server_id);
	      mumu_string_replace(ip,&len,0,"%server",number);
	      strcpy(channels[channel_number].ip6Out,ip);
	      log_message( log_module, MSG_DEBUG,"Channel IPv6 : \"%s\" port : %d\n",channels[channel_number].ip6Out,channels[channel_number].portOut);
	    }	  
        }

        //This is a scrambled channel, we will have to ask the cam for descrambling it
        if(parameters.autoconf_scrambled && actual_service->free_ca_mode)
          channels[channel_number].need_cam_ask=CAM_NEED_ASK;

        //We store the PMT and the service id in the channel
        channels[channel_number].pmt_pid=actual_service->pmt_pid;
        channels[channel_number].service_id=actual_service->id;
        init_rtp_header(&channels[channel_number]); //We init the rtp header in all cases

        if(channels[channel_number].pmt_packet==NULL)
        {
          channels[channel_number].pmt_packet=malloc(sizeof(mumudvb_ts_packet_t));
          if(channels[channel_number].pmt_packet==NULL)
          {
            log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__);
            Interrupted=ERROR_MEMORY<<8;
            return -1;
          }
          memset (channels[channel_number].pmt_packet, 0, sizeof( mumudvb_ts_packet_t));//we clear it
          pthread_mutex_init(&channels[channel_number].pmt_packet->packetmutex,NULL);
        }
#ifdef ENABLE_CAM_SUPPORT
        //We allocate the packet for storing the PMT for CAM purposes
        if(channels[channel_number].cam_pmt_packet==NULL)
        {
          channels[channel_number].cam_pmt_packet=malloc(sizeof(mumudvb_ts_packet_t));
          if(channels[channel_number].cam_pmt_packet==NULL)
          {
            log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__);
            Interrupted=ERROR_MEMORY<<8;
            return -1;
          }
          memset (channels[channel_number].cam_pmt_packet, 0, sizeof( mumudvb_ts_packet_t));//we clear it
          pthread_mutex_init(&channels[channel_number].cam_pmt_packet->packetmutex,NULL);
        }
#endif
        //We update the unicast port, the connection will be created in autoconf_finish_full
        if(unicast_port_per_channel && unicast_vars->unicast)
        {
          strcpy(tempstring,parameters.autoconf_unicast_port);
          int len;len=256;
          char number[10];
          sprintf(number,"%d",channel_number);
          mumu_string_replace(tempstring,&len,0,"%number",number);
          sprintf(number,"%d",card);
          mumu_string_replace(tempstring,&len,0,"%card",number);
          sprintf(number,"%d",tuner);
          mumu_string_replace(tempstring,&len,0,"%tuner",number);
          sprintf(number,"%d",server_id);
          mumu_string_replace(tempstring,&len,0,"%server",number);
          channels[channel_number].unicast_port=string_comput(tempstring);
          log_message( log_module, MSG_DEBUG,"Channel (direct) unicast port  %d\n",channels[channel_number].unicast_port);
        }
#ifdef ENABLE_TRANSCODING
        //We copy the common transcode options to the new channel
        transcode_copy_options(&global_transcode_opt,&channels[channel_number].transcode_options);
        transcode_options_apply_templates(&channels[channel_number].transcode_options,card,tuner,server_id,channel_number);
#endif
        channel_number++;
      }
      else if(actual_service->type==0x02||actual_service->type==0x0a) //service_type digital radio sound service
        log_message( log_module, MSG_DETAIL,"Service type digital radio sound service, no autoconfigure. (if you want add autoconf_radios=1 to your configuration file) Name \"%s\"\n",actual_service->name);
      else if(actual_service->type!=0) //0 is an empty service
      {
        //We show the service type
        log_message( log_module, MSG_DETAIL,"No autoconfigure due to service type : %s. Name \"%s\"\n",service_type_to_str(actual_service->type),actual_service->name);
      }
    }
    actual_service=actual_service->next;
  }
  while(actual_service && channel_number<MAX_CHANNELS);

  if(channel_number==MAX_CHANNELS)
    log_message( log_module, MSG_WARN,"Warning : We reached the maximum channel number, we drop other possible channels !\n");

  return channel_number;
}
Example #6
0
/**
 * @brief Print a log message
 *
 * @param log_module : the name of the part of MuMuDVB which send the message
 * @param type : message type MSG_*
 * @param psz_format : the message in the printf format
*/
void log_message( char* log_module, int type,
                    const char *psz_format, ... )
{
  va_list args;
  int priority=0;
  char *tempchar;
  int message_size;
  mumu_string_t log_string;
  log_string.string=NULL;
  log_string.length=0;

  /*****************************************/
  //if the log header is not initialised
  // we do it
  /*****************************************/

  if(log_params.log_header==NULL)
  {
    log_params.log_header=malloc((strlen(DEFAULT_LOG_HEADER)+1)*sizeof(char));
    if(log_params.log_header==NULL)
    {
      if (log_params.log_type == LOGGING_FILE)
        fprintf( log_params.log_file,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__);
      else if (log_params.log_type == LOGGING_SYSLOG)
        syslog (MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__);
      else
        fprintf( stderr,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__);
      va_end( args );
      Interrupted=ERROR_MEMORY<<8;
      return;
    }
    sprintf(log_params.log_header,"%s",DEFAULT_LOG_HEADER);

  }
  /*****************************************/
  //We apply the templates to the header
  /*****************************************/
  mumu_string_append(&log_string, "%s",log_params.log_header);
  log_string.string=mumu_string_replace(log_string.string,&log_string.length,1,"%priority",priorities(type));
  if(log_module!=NULL)
    log_string.string=mumu_string_replace(log_string.string,&log_string.length,1,"%module",log_module);
  else
    log_string.string=mumu_string_replace(log_string.string,&log_string.length,1,"%module","");

  char timestring[40];
  time_t actual_time;
  actual_time=time(NULL);
  sprintf(timestring,"%jd", (intmax_t)actual_time);
  log_string.string=mumu_string_replace(log_string.string,&log_string.length,1,"%timeepoch",timestring);
  asctime_r(localtime(&actual_time),timestring);
  timestring[strlen(timestring)-1]='\0'; //In order to remove the final '\n' but by asctime
  log_string.string=mumu_string_replace(log_string.string,&log_string.length,1,"%date",timestring);

  char pidstring[10];
  sprintf (pidstring, "%d", getpid ());
  log_string.string=mumu_string_replace(log_string.string,&log_string.length,1,"%pid",pidstring);


  /*****************************************/
  //We append the log message
  /*****************************************/
  //The length returned by mumu_string_replace is the allocated length not the string length
  //If we want mumu_string_append to work we need to update the length to the string length
  log_string.length=strlen(log_string.string);
  va_start( args, psz_format );
  message_size=vsnprintf(NULL, 0, psz_format, args);
  va_end( args );
  tempchar=malloc((message_size+1)*sizeof(char));
  if(tempchar==NULL)
  {
    if (log_params.log_type == LOGGING_FILE)
      fprintf( log_params.log_file,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__);
    else if (log_params.log_type == LOGGING_SYSLOG)
      syslog (MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__);
    else
      fprintf( stderr,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__);
    va_end( args );
    Interrupted=ERROR_MEMORY<<8;
    return;
  }

  va_start( args, psz_format );
  vsprintf(tempchar, psz_format, args );
  va_end( args );
  //If there is no \n at the end of the message we add it
  char terminator='\0';
  if(tempchar[strlen(tempchar)-1] != '\n')
    terminator='\n';
  mumu_string_append(&log_string,"%s%c",tempchar,terminator);
  free(tempchar);

  /*****************************************/
  //We "display" the log message
  /*****************************************/
  if(type<log_params.verbosity)
    {
      if ( log_params.log_type & LOGGING_FILE)
	fprintf(log_params.log_file,"%s",log_string.string);
      if((log_params.log_type & LOGGING_SYSLOG) && (log_params.syslog_initialised))
	{
	  //what is the priority ?
	  switch(type)
	    {
	    case MSG_ERROR:
	      priority|=LOG_ERR;
	      break;
	    case MSG_WARN:
	      priority|=LOG_WARNING;
	      break;
	    case MSG_INFO:
	      priority|=LOG_INFO;
	      break;
	    case MSG_DETAIL:
	      priority|=LOG_NOTICE;
	    break;
	    case MSG_DEBUG:
	    case MSG_FLOOD:
	      priority|=LOG_DEBUG;
	      break;
            default:
              priority=LOG_USER;
	    }
	  syslog (priority,"%s",log_string.string);
	}
	if((log_params.log_type == LOGGING_UNDEFINED) ||
          (log_params.log_type & LOGGING_CONSOLE) ||
          ((log_params.log_type & LOGGING_SYSLOG) && (log_params.syslog_initialised==0)))
          fprintf(stderr,"%s",log_string.string);
    }
  mumu_free_string(&log_string);

}