⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alsasequencer.java

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
		}	}	/*	  This method has to be synchronized because it is called	  from sendMessageTick() as well as from loadSequenceToNative().	*/	private synchronized void enqueueMessage(MidiMessage message, long lTick)	{		m_playbackAlsaMidiOut.enqueueMessage(message, lTick);	}	/**	Put a message into the queue.		This is Claus-Dieter's special method: it puts the message to		the ALSA queue for delivery at the specified time.		The time has to be given in ticks according to the resolution		of the currently active Sequence. For this method to work,		the Sequencer has to be started. The message is delivered		the same way as messages from a Sequence, i.e. to all		registered Transmitters. If the current queue position (as		returned by getTickPosition()) is		already behind the desired schedule time, the message is		ignored.		@param message the MidiMessage to put into the queue.		@param lTick the desired schedule time in ticks.	*/	public void sendMessageTick(MidiMessage message, long lTick)	{		enqueueMessage(message, lTick);	}	private void startQueue()	{		controlQueue(AlsaSeq.SND_SEQ_EVENT_START);	}	private void continueQueue()	{		controlQueue(AlsaSeq.SND_SEQ_EVENT_CONTINUE);	}	private void stopQueue()	{		controlQueue(AlsaSeq.SND_SEQ_EVENT_STOP);	}	private void controlQueue(int nType)	{		int	nSourcePort = getPlaybackPort();		int	nQueue = getQueue();		sendQueueControlEvent(			nType,			AlsaSeq.SND_SEQ_TIME_STAMP_REAL | AlsaSeq.SND_SEQ_TIME_MODE_REL,			0,			AlsaSeq.SND_SEQ_QUEUE_DIRECT,			0L,			nSourcePort,			AlsaSeq.SND_SEQ_CLIENT_SYSTEM,			AlsaSeq.SND_SEQ_PORT_SYSTEM_TIMER,			nQueue, 0, 0);	}	/**	Send a real time START  event to the subscribers immediately.	 */	private void sendStartEvent()	{		sendRealtimeEvent(AlsaSeq.SND_SEQ_EVENT_START);	}	/**	Send a real time STOP  event to the subscribers immediately.	 */	private void sendStopEvent()	{		sendRealtimeEvent(AlsaSeq.SND_SEQ_EVENT_STOP);	}	private void sendRealtimeEvent(int nType)	{		sendQueueControlEvent(			nType,			AlsaSeq.SND_SEQ_TIME_STAMP_REAL | AlsaSeq.SND_SEQ_TIME_MODE_REL,			0,				// tag			AlsaSeq.SND_SEQ_QUEUE_DIRECT,	// queue			0L,				// time			getPlaybackPort(),			// source			AlsaSeq.SND_SEQ_ADDRESS_SUBSCRIBERS,	// dest client			AlsaSeq.SND_SEQ_ADDRESS_UNKNOWN,	// dest port			0, 0, 0);	}	// NOTE: also used for setting position and start/stop RT	private void sendQueueControlEvent(		int nType, int nFlags, int nTag, int nQueue, long lTime,		int nSourcePort, int nDestClient, int nDestPort,		int nControlQueue, int nControlValue, long lControlTime)	{		m_queueControlEvent.setCommon(nType, nFlags, nTag, nQueue, lTime,					      0, nSourcePort, nDestClient, nDestPort);		m_queueControlEvent.setQueueControl(nControlQueue, nControlValue, lControlTime);		getPlaybackAlsaSeq().eventOutputDirect(m_queueControlEvent);	}	private void sendAllNotesOffEvent(int nChannel)	{		int	nSourcePort = getPlaybackPort();		m_allNotesOffEvent.setCommon(			AlsaSeq.SND_SEQ_EVENT_CONTROLLER,			AlsaSeq.SND_SEQ_TIME_STAMP_REAL | AlsaSeq.SND_SEQ_TIME_MODE_REL,			0,				// tag			AlsaSeq.SND_SEQ_QUEUE_DIRECT,	// queue			0L,				// time			0, nSourcePort,			// source			AlsaSeq.SND_SEQ_ADDRESS_SUBSCRIBERS,	// dest client			AlsaSeq.SND_SEQ_ADDRESS_UNKNOWN);	// dest port		m_allNotesOffEvent.setControl(nChannel, 0x78, 0);		getPlaybackAlsaSeq().eventOutputDirect(m_allNotesOffEvent);	}	private void sendAllNotesOff()	{		// TODO: check if [0..15] or [1..16]		for (int nChannel = 0; nChannel < 16; nChannel++)		{			sendAllNotesOffEvent(nChannel);		}	}	/**	Receive a correctely timestamped event.		This method expects that the timestamp is in ticks,		appropriate for the Sequence currently running.	*/	private void receiveTimestamped(MidiMessage message, long lTimestamp)	{		if (isRecording())		{			// TODO: this is hacky; should implement correct track mapping			Track	track = m_track;			MidiEvent	event = new MidiEvent(message, lTimestamp);			track.add(event);		}		// TODO: entering an event into the sequence	}	/**	Receive an event from a Receiver.	 	This method is called by AlsaSequencer.AlsaSequencerReceiver		on receipt of a MidiMessage.	*/	protected void receive(MidiMessage message, long lTimestamp)	{		lTimestamp = getTickPosition();		receiveTimestamped(message, lTimestamp);	}	///////////////////////////////////////////////////	public Receiver getReceiver()		throws	MidiUnavailableException	{		return new AlsaSequencerReceiver();	}	public Transmitter getTransmitter()		throws	MidiUnavailableException	{		return new AlsaSequencerTransmitter();	}/////////////////// INNER CLASSES //////////////////////////////////////	private class PlaybackAlsaMidiInListener		implements AlsaMidiIn.AlsaMidiInListener	{		public void dequeueEvent(MidiMessage message, long lTimestamp)		{			if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.PlaybackAlsaMidiInListener.dequeueEvent(): begin"); }			if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.PlaybackAlsaMidiInListener.dequeueEvent(): message: " + message); }			if (message instanceof MetaMessage)			{				MetaMessage	metaMessage = (MetaMessage) message;				if (metaMessage.getType() == 0x51)	// set tempo				{					byte[]	abData = metaMessage.getData();					int	nTempo = MidiUtils.getUnsignedInteger(abData[0]) * 65536 +						MidiUtils.getUnsignedInteger(abData[1]) * 256 +						MidiUtils.getUnsignedInteger(abData[2]);					setTempoInMPQ((float) nTempo);				}			}			// passes events to the receivers			sendImpl(message, -1L);			// calls control and meta listeners			notifyListeners(message);			if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.PlaybackAlsaMidiInListener.dequeueEvent(): end"); }		}	}	private class RecordingAlsaMidiInListener		implements AlsaMidiIn.AlsaMidiInListener	{		public void dequeueEvent(MidiMessage message, long lTimestamp)		{			if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.RecordingAlsaMidiInListener.dequeueEvent(): begin"); }			if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.RecordingAlsaMidiInListener.dequeueEvent(): message: " + message); }			AlsaSequencer.this.receiveTimestamped(message, lTimestamp);			if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.RecordingAlsaMidiInListener.dequeueEvent(): end"); }		}	}	private class AlsaSequencerReceiver		extends		TReceiver		implements	AlsaReceiver	{		public AlsaSequencerReceiver()		{			super();		}		/**	Subscribe to the passed port.		 *	This establishes a subscription in the ALSA sequencer		 *	so that the device this Receiver belongs to receives		 *	event from the client:port passed as parameters.		 *		 *	@return true if subscription was established,		 *		false otherwise		 */		public boolean subscribeTo(int nClient, int nPort)		{			try			{				AlsaSeqPortSubscribe	portSubscribe = new AlsaSeqPortSubscribe();				portSubscribe.setSender(nClient, nPort);				portSubscribe.setDest(AlsaSequencer.this.getRecordingClient(), AlsaSequencer.this.getRecordingPort());				portSubscribe.setQueue(AlsaSequencer.this.getQueue());				portSubscribe.setExclusive(false);				portSubscribe.setTimeUpdate(true);				portSubscribe.setTimeReal(false);				AlsaSequencer.this.getRecordingAlsaSeq().subscribePort(portSubscribe);				portSubscribe.free();				return true;			}			catch (RuntimeException e)			{				if (TDebug.TraceAllExceptions) { TDebug.out(e); }				return false;			}		}	}	private class AlsaSequencerTransmitter		extends		TTransmitter	{		private boolean		m_bReceiverSubscribed;		public AlsaSequencerTransmitter()		{			super();			m_bReceiverSubscribed = false;		}		public void setReceiver(Receiver receiver)		{			super.setReceiver(receiver);			/*			 *	Try to establish a subscription of the Receiver			 *	to the ALSA seqencer client of the device this			 *	Transmitter belongs to.			 */			if (receiver instanceof AlsaReceiver)			{				// TDebug.out("AlsaSequencer.AlsaSequencerTransmitter.setReceiver(): trying to establish subscription");				m_bReceiverSubscribed = ((AlsaReceiver) receiver).subscribeTo(getPlaybackClient(), getPlaybackPort());				// TODO: similar subscription for the sequencer's own midi in listener!!				// this is necessary because sync messages are sent via the recording port				m_bReceiverSubscribed = ((AlsaReceiver) receiver).subscribeTo(getRecordingClient(), getRecordingPort());				// TDebug.out("AlsaSequencer.AlsaSequencerTransmitter.setReceiver(): subscription established: " + m_bReceiverSubscribed);			}		}		public void send(MidiMessage message, long lTimeStamp)		{			/*			 *	Send message via Java methods only if no			 *	subscription was established. If there is a			 *	subscription, the message is routed inside of			 *	the ALSA sequencer.			 */			if (! m_bReceiverSubscribed)			{				super.send(message, lTimeStamp);			}		}		public void close()		{			super.close();			// TODO: remove subscription		}	}	private class LoaderThread		extends	Thread	{		private long	m_lLoadingPosition;		public void run()		{			if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.run(): begin"); }			while (isOpen())			{				do				{					synchronized (this)					{						try						{							this.wait();						}						catch (InterruptedException e)						{							if (TDebug.TraceAllExceptions) { TDebug.out(e); }						}					}				}				while (! isRunning());				loadSequenceToNative();			}			if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.run(): end"); }		}		private void loadSequenceToNative()		{			if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.loadSequenceToNative(): begin"); }			Sequence	sequence = getSequence();			Track[]	aTracks = sequence.getTracks();			int[]	anTrackPositions = new int[aTracks.length];			for (int i = 0; i < aTracks.length; i++)			{				anTrackPositions[i] = 0;			}			// this is used to get a useful tick value for the end of track message			m_lLoadingPosition = 0;			while (isRunning())			{				boolean		bTrackPresent = false;				long		lBestTick = Long.MAX_VALUE;				int		nBestTrack = -1;				for (int nTrack = 0; nTrack < aTracks.length; nTrack++)				{					if (anTrackPositions[nTrack] < aTracks[nTrack].size())					{						bTrackPresent = true;						MidiEvent	event = aTracks[nTrack].get(anTrackPositions[nTrack]);						long		lTick = event.getTick();						if (lTick < lBestTick)						{							lBestTick = lTick;							nBestTrack = nTrack;						}					}				}				if (!bTrackPresent)				{					/*	No more events; send						end-of-track event.					*/					MetaMessage	metaMessage = new MetaMessage();					try					{						metaMessage.setMessage(0x2F, new byte[0], 0);					}					catch (InvalidMidiDataException e)					{						if (TDebug.TraceAllExceptions) { TDebug.out(e); }					}					if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.loadSequenceToNative(): sending End of Track message with tick " + (m_lLoadingPosition + 1)); }					enqueueMessage(metaMessage, m_lLoadingPosition + 1);					// leave the while (isRunning())-loop					break;				}				/**	The normal case: deliver the event					found to be the next.				*/				MidiEvent	event = aTracks[nBestTrack].get(anTrackPositions[nBestTrack]);				anTrackPositions[nBestTrack]++;				MidiMessage	message = event.getMessage();				long		lTick = event.getTick();				m_lLoadingPosition = Math.max(m_lLoadingPosition, lTick);				if (message instanceof MetaMessage && ((MetaMessage) message).getType() == 0x2F)				{					if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.loadSequenceToNative(): ignoring End of Track message with tick " + lTick); }				}				else				{					if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.loadSequenceToNative(): enqueueing event with tick " + lTick); }					enqueueMessage(message, lTick);				}			}			if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.loadSequenceToNative(): end"); }		}	}	// TODO: start/stop; on/off	private class MasterSynchronizer		extends	Thread	{		public void run()		{			if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.MasterSynchronizer.run(): begin"); }			while (isOpen())			{				do				{					synchronized (this)					{						try						{							this.wait();						}						catch (InterruptedException e)						{							if (TDebug.TraceAllExceptions) { TDebug.out(e); }						}					}				}				while (! isRunning());				double	dTickMin = getTickPosition();				double	dTickMax = getSequence().getTickLength();				double	dTickStep = getSequence().getResolution() / 24.0;				if (TDebug.TraceSequencer) { TDebug.out("MasterSynchronizer.run(): tick step: " + dTickStep); }				double	dTick = dTickMin;				// TODO: ... && getS.Mode().equals(...)				while (dTick < dTickMax && isRunning())				{					long	lTick = Math.round(dTick);					if (TDebug.TraceSequencer) { TDebug.out("MasterSynchronizer.run(): sending clock event with tick " + lTick); }					m_clockEvent.setTimestamp(lTick);					getRecordingAlsaSeq().eventOutput(m_clockEvent);					getRecordingAlsaSeq().drainOutput();					dTick += dTickStep;				}			}			if (TDebug.TraceSequencer) { TDebug.out("AlsaSequencer.MasterSynchronizer.run(): end"); }		}	}}/*** AlsaSequencer.java ***/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -