コード例 #1
0
ファイル: servicedvbrecord.cpp プロジェクト: Tron3/enigma2
RESULT eDVBServiceRecord::stop()
{
	if (!m_simulate)
		eDebug("stop recording!");
	if (m_state == stateRecording)
	{
		if (m_record)
			m_record->stop();
		if (m_target_fd >= 0)
		{
			::close(m_target_fd);
			m_target_fd = -1;
		}
		
		saveCutlist();
		
		m_state = statePrepared;
	} else if (!m_simulate)
		eDebug("(was not recording)");
	if (m_state == statePrepared)
	{
		m_record = 0;
		m_state = stateIdle;
	}
	m_event((iRecordableService*)this, evRecordStopped);
	return 0;
}
コード例 #2
0
ファイル: servicexine.cpp プロジェクト: christophecvr/enigma2
RESULT eServiceXine::start()
{
	if (m_state == stError)
		return -1;

	ASSERT(m_state == stIdle);
	ASSERT(stream);

	if (!xine_open(stream, m_filename.c_str()))
	{
		eWarning("xine_open failed!");
		return -1;
	}

	if (!xine_play(stream, 0, 0))
	{
		eWarning("xine_play failed!");
		return -1;
	}

	m_state = stRunning;

	m_event(this, evStart);
	return 0;
}
コード例 #3
0
RESULT eServiceTS::start()
{
	ePtr<eDVBResourceManager> rmgr;
	eDVBResourceManager::getInstance(rmgr);
	eDVBChannel dvbChannel(rmgr, 0);
	if (dvbChannel.getDemux(m_decodedemux, iDVBChannel::capDecode) != 0) {
		eDebug("Cannot allocate decode-demux");
		return -1;
	}
	if (m_decodedemux->getMPEGDecoder(m_decoder, 1) != 0) {
		eDebug("Cannot allocate MPEGDecoder");
		return -1;
	}
	if (m_destfd == -1)
	{
		m_destfd = m_decodedemux->openDVR(O_WRONLY);
		if (m_destfd < 0)
		{
			eDebug("openDVR failed");
			return -1;
		}
	}
	m_decoder->setVideoPID(m_vpid, eDVBVideo::MPEG2);
	m_decoder->setAudioPID(m_apid, eDVBAudio::aMPEG);
	m_streamthread = new eStreamThread();
	CONNECT(m_streamthread->m_event, eServiceTS::recv_event);
	m_decoder->pause();
	if (unpause() != 0) 
		return -1;
	m_event(this, evStart);
	return 0;
}
コード例 #4
0
ファイル: demux.cpp プロジェクト: formiano/enigma2-4.4
RESULT eDVBDemux::flush()
{
	// FIXME: implement flushing the PVR queue here.

	m_event(evtFlush);
	return 0;
}
コード例 #5
0
ファイル: servicedvbrecord.cpp プロジェクト: Tron3/enigma2
void eDVBServiceRecord::gotNewEvent(int /*error*/)
{
	ePtr<eServiceEvent> event_now;
	m_event_handler.getEvent(event_now, 0);

	if (!event_now)
		return;

	int event_id = event_now->getEventId();

	pts_t p;
	
	if (m_record)
	{
		if (m_record->getCurrentPCR(p))
			eDebug("getting PCR failed!");
		else
		{
			m_event_timestamps[event_id] = p;
			eDebug("pcr of eit change: %llx", p);
		}
	}

	if (event_id != m_last_event_id)
		eDebug("[eDVBServiceRecord] now running: %s (%d seconds)", event_now->getEventName().c_str(), event_now->getDuration());
	
	m_last_event_id = event_id;

	m_event((iRecordableService*)this, evNewEventInfo);
}
コード例 #6
0
ファイル: servicehdmi.cpp プロジェクト: BlackHole/enigma2-1
RESULT eServiceHDMIRecord::stop()
{
	if (!m_simulate)
		eDebug("[eServiceHDMIRecord] stop recording!");
	if (m_state == stateRecording)
	{
		if (m_thread)
		{
			m_thread->stop();
			m_thread->stopSaveMetaInformation();
		}
		if (m_target_fd >= 0)
		{
			::close(m_target_fd);
			m_target_fd = -1;
		}

		m_state = statePrepared;
	} else if (!m_simulate)
		eDebug("[eServiceHDMIRecord] (was not recording)");
	if (m_state == statePrepared)
	{
		m_thread = NULL;
		if (eEncoder::getInstance()) eEncoder::getInstance()->freeEncoder(m_encoder_fd);
		m_encoder_fd = -1;
		m_state = stateIdle;
	}
	m_event((iRecordableService*)this, evRecordStopped);
	return 0;
}
コード例 #7
0
ファイル: servicedvd.cpp プロジェクト: undertaker01/stbgui
RESULT eServiceDVD::enableSubtitles(iSubtitleUser *user, SubtitleTrack &track)
{
	eSize size = eSize(720, 576);

	if (m_subtitle_widget) m_subtitle_widget->destroy();
	m_subtitle_widget = user;

	int pid = -1;

	if (track.pid >= 0)
	{
		pid = track.pid - 1;

		ddvd_set_spu(m_ddvdconfig, pid);
		m_event(this, evUser+7);
	}

	eDebug("[eServiceDVD] enableSubtitles %i", pid);

	if (!m_pixmap)
	{
		m_pixmap = new gPixmap(size, 32, 1); /* allocate accel surface (if possible) */
#ifdef DDVD_SUPPORTS_GET_BLIT_DESTINATION
		ddvd_set_lfb_ex(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, size.width(), size.height(), 4, size.width()*4, 1);
#else
		ddvd_set_lfb(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, size.width(), size.height(), 4, size.width()*4);
#warning please update libdreamdvd for fast scaling
#endif
		run(); // start the thread
	}

	return 0;
}
コード例 #8
0
RESULT eServiceMP3::getPlayPosition(pts_t &pts)
{
	if (player && player->playback && !player->playback->isPlaying)
	{
		eDebug("[eServiceMP3::%s] !!!!EOF!!!!", __func__);

		if(m_state == stRunning)
			m_event((iPlayableService*)this, evEOF);

		pts = 0;
		return -1;
	}

	unsigned long long int vpts = 0;

	if (player && player->playback)
		player->playback->Command(player, PLAYBACK_PTS, &vpts);

	if (vpts<=0)
		return -1;

	/* len is in nanoseconds. we have 90 000 pts per second. */
	pts = vpts;
	return 0;
}
コード例 #9
0
ファイル: node_param.hpp プロジェクト: EQ4/psychosynth
    void set (const T& d) {
	{
	    std::unique_lock<std::mutex> lock (m_mutex);
	    m_changed = true;
	    *static_cast<T*>(m_src) = d;
	}
	if (!m_event.empty()) m_event(*this);
    }
コード例 #10
0
ファイル: servicewebts.cpp プロジェクト: henrylicious/test
void eServiceWebTS::recv_event(int evt)
{
	eDebug("eServiceWebTS::recv_event: %d", evt);
	switch (evt) {
	case eStreamThreadWeb::evtEOS:
		m_decodedemux->flush();
		m_event((iPlayableService*)this, evEOF);
		break;
	case eStreamThreadWeb::evtReadError:
	case eStreamThreadWeb::evtWriteError:
		m_decoder->pause();
		m_event((iPlayableService*)this, evEOF);
		break;
	case eStreamThreadWeb::evtSOS:
		m_event((iPlayableService*)this, evSOF);
		break;
	case eStreamThreadWeb::evtStreamInfo:
		if (VPID != 0 && PID_SET == 0 && APID != 0)
		{
			PID_SET = 1;
			m_decodedemux->flush();
			if (H264)
				m_decoder->setVideoPID(VPID, eDVBVideo::MPEG4_H264);
			else
				m_decoder->setVideoPID(VPID, eDVBVideo::MPEG2);
			m_decoder->setAudioPID(APID, eDVBAudio::aMPEG);
			m_decoder->pause();
			m_event(this, evStart);
			m_decoder->play();

		}
		bool wasnull = !m_audioInfo;
		m_streamthread->getAudioInfo(m_audioInfo);
		//if (m_audioInfo)
		//	eDebug("[ServiceWebTS] %d audiostreams found", m_audioInfo->audioStreams.size());
		if (m_audioInfo && wasnull) {
			eDebug("[ServiceWebTS] %d audiostreams found", m_audioInfo->audioStreams.size());
			int sel = getCurrentTrack();
			if (sel < 0)
				selectTrack(0);
			else if (m_audioInfo->audioStreams[sel].type != eDVBAudio::aMPEG)
				selectTrack(sel);
		}
		break;
	}
}
コード例 #11
0
ファイル: servicedvbrecord.cpp プロジェクト: TitanNit/tdt
RESULT eDVBServiceRecord::start(bool simulate)
{
	m_simulate = simulate;
	m_want_record = 1;
		/* when tune wasn't yet successfully, doRecord stays in "prepared"-state which is fine. */
	m_event((iRecordableService*)this, evStart);
	return doRecord();
}
コード例 #12
0
ファイル: servicemp3record.cpp プロジェクト: Open-Plus/opgui
RESULT eServiceMP3Record::start(bool simulate)
{
	m_simulate = simulate;
	m_event((iRecordableService*)this, evStart);
	if (simulate)
		return 0;
	return doRecord();
}
コード例 #13
0
ファイル: servicehdmi.cpp プロジェクト: BlackHole/enigma2-1
int eServiceHDMIRecord::doRecord()
{
	int err = doPrepare();
	if (err)
	{
		m_error = errTuneFailed;
		m_event((iRecordableService*)this, evRecordFailed);
		return err;
	}

	if (!m_thread && !m_simulate)
	{
		eDebug("[eServiceHDMIRecord] Recording to %s...", m_filename.c_str());
		::remove(m_filename.c_str());
		int fd = ::open(m_filename.c_str(), O_WRONLY | O_CREAT | O_LARGEFILE | O_CLOEXEC, 0666);
		if (fd < 0)
		{
			eDebug("[eServiceHDMIRecord] can't open recording file: %m");
			m_error = errOpenRecordFile;
			m_event((iRecordableService*)this, evRecordFailed);
			return errOpenRecordFile;
		}

		m_thread = new eDVBRecordFileThread(188, 20);
		m_thread->setTargetFD(fd);

		m_target_fd = fd;
	}

	eDebug("[eServiceHDMIRecord] start recording...");

	if (m_state != stateRecording)
	{
		if (m_thread && m_encoder_fd >= 0)
		{
			m_thread->startSaveMetaInformation(m_filename);
			m_thread->start(m_encoder_fd);
		}
		m_state = stateRecording;
	}

	m_error = 0;
	m_event((iRecordableService*)this, evRecordRunning);
	return 0;
}
コード例 #14
0
ファイル: core.cpp プロジェクト: Adga52/enigma2
void eNavigation::serviceEvent(iPlayableService* service, int event)
{
	if (m_runningService && service != m_runningService)
	{
		eDebug("nav: event %d for other service", event);
		return;
	}
	m_event(event);
}
コード例 #15
0
ファイル: demux.cpp プロジェクト: pizzelnet/enigma2-1
void eDVBTSRecorder::filepushEvent(int event)
{
	switch (event)
	{
	case eFilePushThread::evtWriteError:
		m_event(eventWriteError);
		break;
	}
}
コード例 #16
0
void eServiceMP3::gotThreadMessage(const int &msg)
{
	switch(msg)
	{
	case 1: // thread stopped
		eDebug("[eServiceMP3::%s] issuing eof...", __func__);
		m_event(this, evEOF);
		break;
	}
}
コード例 #17
0
ファイル: servicedvd.cpp プロジェクト: Caught/openpliPC
void eServiceDVD::gotThreadMessage(const int &msg)
{
	switch(msg)
	{
	case 1: // thread stopped
		m_state = stStopped;
		m_event(this, evStopped);
		break;
	}
}
コード例 #18
0
ファイル: servicehdmi.cpp プロジェクト: BlackHole/enigma2-1
RESULT eServiceHDMI::start()
{
	m_decoder = new eTSMPEGDecoder(NULL, m_decoder_index);
	m_decoder->setVideoPID(1, 0);
	if (!m_noaudio)
		m_decoder->setAudioPID(1, 0);
	m_decoder->play();
	m_event(this, evStart);
	return 0;
}
コード例 #19
0
ファイル: servicedvbrecord.cpp プロジェクト: Tron3/enigma2
void eDVBServiceRecord::serviceEvent(int event)
{
	eDebug("RECORD service event %d", event);
	switch (event)
	{
	case eDVBServicePMTHandler::eventTuned:
	{
		eDebug("tuned..");
		m_tuned = 1;

			/* start feeding EIT updates */
		ePtr<iDVBDemux> m_demux;
		if (!m_service_handler.getDataDemux(m_demux))
		{
			eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_ref;
			int sid = ref.getParentServiceID().get();
			if (!sid)
				sid = ref.getServiceID().get();
			if ( ref.getParentTransportStreamID().get() &&
				ref.getParentTransportStreamID() != ref.getTransportStreamID() )
				m_event_handler.startOther(m_demux, sid);
			else
				m_event_handler.start(m_demux, sid);
		}

		if (m_state == stateRecording && m_want_record)
			doRecord();
		m_event((iRecordableService*)this, evTunedIn);
		break;
	}
	case eDVBServicePMTHandler::eventTuneFailed:
	{
		eDebug("record failed to tune");
		m_event((iRecordableService*)this, evTuneFailed);
		break;
	}
	case eDVBServicePMTHandler::eventNewProgramInfo:
	{
		if (m_state == stateIdle)
			doPrepare();
		else if (m_want_record) /* doRecord can be called from Prepared and Recording state */
			doRecord();
		m_event((iRecordableService*)this, evNewProgramInfo);
		break;
	}
	case eDVBServicePMTHandler::eventMisconfiguration:
		m_error = errMisconfiguration;
		m_event((iRecordableService*)this, evTuneFailed);
		break;
	case eDVBServicePMTHandler::eventNoResources:
		m_error = errNoResources;
		m_event((iRecordableService*)this, evTuneFailed);
		break;
	case eDVBServicePMTHandler::eventStopped:
		/* recording data source has stopped, stop recording */
		stop();
		m_event((iRecordableService*)this, evRecordAborted);
		break;
	}
}
コード例 #20
0
ファイル: servicedvbrecord.cpp プロジェクト: TitanNit/tdt
void eDVBServiceRecord::recordEvent(int event)
{
	switch (event)
	{
	case iDVBTSRecorder::eventWriteError:
		eWarning("[eDVBServiceRecord] record write error");
		stop();
		m_event((iRecordableService*)this, evRecordWriteError);
		return;
	default:
		eDebug("unhandled record event %d", event);
	}
}
コード例 #21
0
ファイル: servicemp3record.cpp プロジェクト: Open-Plus/opgui
int eServiceMP3Record::doRecord()
{
	int err = doPrepare();
	if (err)
	{
		m_error = errMisconfiguration;
		m_event((iRecordableService*)this, evRecordFailed);
		return err;
	}

	if (gst_element_set_state(m_recording_pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE)
	{
		eDebug("[eMP3ServiceRecord] doRecord error cannot set pipeline to state_playing");
		m_error = errMisconfiguration;
		m_event((iRecordableService*)this, evRecordFailed);
		return -1;
	}

	m_state = stateRecording;
	m_error = 0;
	m_event((iRecordableService*)this, evRecordRunning);
	return 0;
}
コード例 #22
0
void eServiceMP3::updateEpgCacheNowNext()
{
	bool update = false;
	ePtr<eServiceEvent> next = 0;
	ePtr<eServiceEvent> ptr = 0;
	eServiceReference ref(m_ref);
	ref.type = eServiceFactoryMP3::id;
	ref.path.clear();

	if (eEPGCache::getInstance() && eEPGCache::getInstance()->lookupEventTime(ref, -1, ptr) >= 0)
	{
		ePtr<eServiceEvent> current = m_event_now;
		if (!current || !ptr || current->getEventId() != ptr->getEventId())
		{
			update = true;
			m_event_now = ptr;
			time_t next_time = ptr->getBeginTime() + ptr->getDuration();
			if (eEPGCache::getInstance()->lookupEventTime(ref, next_time, ptr) >= 0)
			{
				next = ptr;
				m_event_next = ptr;
			}
		}
	}

	int refreshtime = 60;

	if (!next)
	{
		next = m_event_next;
	}

	if (next)
	{
		time_t now = eDVBLocalTimeHandler::getInstance()->nowTime();
		refreshtime = (int)(next->getBeginTime() - now) + 3;

		if (refreshtime <= 0 || refreshtime > 60)
		{
			refreshtime = 60;
		}
	}

	m_nownext_timer->startLongTimer(refreshtime);

	if (update)
	{
		m_event((iPlayableService*)this, evUpdatedEventInfo);
	}
}
コード例 #23
0
ファイル: servicemp3.cpp プロジェクト: TELE-TWIN/enigma2pc-1
RESULT eServiceMP3::start()
{
//	ASSERT(m_state == stIdle); openpliPC

	m_state = stRunning;
	/*if (m_gst_playbin) openpliPC
	{
		eDebug("eServiceMP3::starting pipeline");
		gst_element_set_state (m_gst_playbin, GST_STATE_PLAYING);
	}*/

	m_event(this, evStart);

	return 0;
}
コード例 #24
0
ファイル: servicemp3.cpp プロジェクト: ambrosa/test
RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple)
{
	ePyObject entry;
	int tuplesize = PyTuple_Size(tuple);
	int pid;

	if (!PyTuple_Check(tuple))
		goto error_out;
	if (tuplesize < 1)
		goto error_out;
	entry = PyTuple_GET_ITEM(tuple, 1);
	if (!PyInt_Check(entry))
		goto error_out;
	pid = PyInt_AsLong(entry);

	if (m_currentSubtitleStream != pid)
	{
		g_object_set (G_OBJECT (m_gst_playbin), "current-text", -1, NULL);
		m_subtitle_pages.clear();
		m_prev_decoder_time = -1;
		m_decoder_time_valid_state = 0;
		m_currentSubtitleStream = pid;
		g_object_set (G_OBJECT (m_gst_playbin), "current-text", m_currentSubtitleStream, NULL);

		m_subtitle_widget = 0;
		m_subtitle_widget = new eSubtitleWidget(parent);
		m_subtitle_widget->resize(parent->size()); /* full size */

		eDebug ("eServiceMP3::switched to subtitle stream %i", m_currentSubtitleStream);

		m_event((iPlayableService*)this, evUpdatedInfo);

#ifdef GSTREAMER_SUBTITLE_SYNC_MODE_BUG
		/* 
		 * when we're running the subsink in sync=false mode, 
		 * we have to force a seek, before the new subtitle stream will start
		 */
		seekRelative(-1, 90000);
#endif
	}

	return 0;

error_out:
	eDebug("eServiceMP3::enableSubtitles needs a tuple as 2nd argument!\n"
		"for gst subtitles (2, subtitle_stream_count, subtitle_type)");
	return -1;
}
コード例 #25
0
ファイル: servicedvd.cpp プロジェクト: Caught/openpliPC
RESULT eServiceDVD::enableSubtitles(eWidget *parent, ePyObject tuple)
{
	delete m_subtitle_widget;
	eSize size = eSize(720, 576);

	m_subtitle_widget = new eSubtitleWidget(parent);
	m_subtitle_widget->resize(parent->size());

	int pid = -1;

	if ( tuple != Py_None )
	{		
		ePyObject entry;
		int tuplesize = PyTuple_Size(tuple);
		if (!PyTuple_Check(tuple))
			goto error_out;
		if (tuplesize < 1)
			goto error_out;
		entry = PyTuple_GET_ITEM(tuple, 1);
		if (!PyInt_Check(entry))
			goto error_out;
		pid = PyInt_AsLong(entry)-1;

		ddvd_set_spu(m_ddvdconfig, pid);
		m_event(this, evUser+7);
	}
	eDebug("eServiceDVD::enableSubtitles %i", pid);

	if (!m_pixmap)
	{
		m_pixmap = new gPixmap(size, 32, 1); /* allocate accel surface (if possible) */
#ifdef DDVD_SUPPORTS_GET_BLIT_DESTINATION
		ddvd_set_lfb_ex(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, size.width(), size.height(), 4, size.width()*4, 1);
#else
		ddvd_set_lfb(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, size.width(), size.height(), 4, size.width()*4);
#warning please update libdreamdvd for fast scaling
#endif
		run(); // start the thread
	}

	m_subtitle_widget->setZPosition(-1);
	m_subtitle_widget->show();

	return 0;

error_out:
	return -1;
}
コード例 #26
0
ファイル: core.cpp プロジェクト: Adga52/enigma2
RESULT eNavigation::stopService(void)
{
		/* check if there is a running service... */
	if (!m_runningService)
		return 1;

	ePtr<iPlayableService> tmp = m_runningService;
	m_runningService=0;
	tmp->stop();

	/* send stop event */
	m_event(iPlayableService::evEnd);

		/* kill service. */
	m_service_event_conn = 0;
	return 0;
}
コード例 #27
0
ファイル: servicemp3record.cpp プロジェクト: Open-Plus/opgui
RESULT eServiceMP3Record::stop()
{
	if (!m_simulate)
		eDebug("[eMP3ServiceRecord] stop recording");
	if (m_state == stateRecording)
	{
		gst_element_set_state(m_recording_pipeline, GST_STATE_NULL);
		m_state = statePrepared;
	} else if (!m_simulate)
		eDebug("[eMP3ServiceRecord] stop was not recording");
	if (m_state == statePrepared)
	{
		if (m_streamingsrc_timeout)
			m_streamingsrc_timeout->stop();
		m_state = stateIdle;
	}
	m_event((iRecordableService*)this, evRecordStopped);
	return 0;
}
コード例 #28
0
/* cuesheet CVR */
void eServiceMP3::loadCuesheet()
{
	if (!m_cuesheet_loaded)
	{
		eDebug("[eServiceMP3::%s] loading cuesheet", __func__);
		m_cuesheet_loaded = true;
	}

	std::string filename = m_ref.path + ".cuts";

	m_cue_entries.clear();

	FILE *f = fopen(filename.c_str(), "rb");

	if (f)
	{
		while (1)
		{
			unsigned long long where;
			unsigned int what;

			if (!fread(&where, sizeof(where), 1, f))
				break;
			if (!fread(&what, sizeof(what), 1, f))
				break;

			where = be64toh(where);
			what = ntohl(what);

			if (what > 3)
				break;

			m_cue_entries.insert(cueEntry(where, what));
		}
		fclose(f);
		eDebug("[eServiceMP3::%s] cuts file has %zd entries", __func__, m_cue_entries.size());
	} else
		eDebug("[eServiceMP3::%s] cutfile not found!", __func__);

	m_cuesheet_changed = 0;
	m_event((iPlayableService*)this, evCuesheetChanged);
}
コード例 #29
0
RESULT eServiceTS::start()
{
	ePtr<eDVBResourceManager> rmgr;
	eDVBResourceManager::getInstance(rmgr);
	// FIXMEE hardcoded chid... this only works for one eServiceWebTS
	eDVBChannelID chid;
	chid.dvbnamespace = eDVBNamespace(0);
	chid.transport_stream_id = eTransportStreamID(0);
	chid.original_network_id = eOriginalNetworkID(0);
	chid.pvr_source = "/eServiceTS";
	if (rmgr->allocateChannel(chid, m_channel)) {
		eDebug("Cannot allocate pvr channel");
		return -1;
	}
	if (m_channel->getDemux(m_decodedemux, iDVBChannel::capDecode) != 0) {
		eDebug("Cannot allocate decode-demux");
		return -1;
	}
	if (m_decodedemux->getMPEGDecoder(m_decoder, 1) != 0) {
		eDebug("Cannot allocate MPEGDecoder");
		return -1;
	}
	if (m_destfd == -1)
	{
		m_destfd = m_decodedemux->openDVR(O_WRONLY);
		if (m_destfd < 0)
		{
			eDebug("openDVR failed");
			return -1;
		}
	}
	m_decoder->setVideoPID(m_vpid, eDVBVideo::MPEG2);
	m_decoder->setAudioPID(m_apid, eDVBAudio::aMPEG);
	m_streamthread = new eStreamThread();
	CONNECT(m_streamthread->m_event, eServiceTS::recv_event);
	m_decoder->pause();
	if (unpause() != 0) 
		return -1;
	m_event(this, evStart);
	return 0;
}
コード例 #30
0
/* cuesheet CVR */
void eServiceMP3::setCutList(ePyObject list)
{
	if (!PyList_Check(list))
		return;
	int size = PyList_Size(list);
	int i;

	m_cue_entries.clear();

	for (i=0; i<size; ++i)
	{
		ePyObject tuple = PyList_GET_ITEM(list, i);
		if (!PyTuple_Check(tuple))
		{
			eDebug("[eServiceMP3::%s] non-tuple in cutlist", __func__);
			continue;
		}
		if (PyTuple_Size(tuple) != 2)
		{
			eDebug("[eServiceMP3::%s] cutlist entries need to be a 2-tuple", __func__);
			continue;
		}
		ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
		if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
		{
			eDebug("[eServiceMP3::%s] cutlist entries need to be (pts, type)-tuples (%d %d)", __func__, PyLong_Check(ppts), PyInt_Check(ptype));
			continue;
		}
		pts_t pts = PyLong_AsLongLong(ppts);
		int type = PyInt_AsLong(ptype);
		m_cue_entries.insert(cueEntry(pts, type));
		eDebug("[eServiceMP3::%s] adding %08llx, %d", __func__, pts, type);
	}
	m_cuesheet_changed = 1;
	m_event((iPlayableService*)this, evCuesheetChanged);
}