This is a JAVA PROGRAM: In this program, we make several extensions to our syste
ID: 3871488 • Letter: T
Question
This is a JAVA PROGRAM:
In this program, we make several extensions to our system:
>Add specialized toString() to Receiver.java and Transmitter.java
>Add a three message queue to the Receiver.java
>Define a logger to stdout for logging events
>Add JUnit unit testing for Transmitter.java, Receiver.java, Message.java
Transmitter.java modifications:
Modify Transmitter such that:
>one can connect a PrintLogger to it
>it send log entries to the connected PrintLogger (if any) for any actions that cause state changes and when sending a message
>it has a meaningful toString()
More specifically, the following methods should be added or modified to Transmitter:
>void addLog(PrintLogger printLogger) shall add a PrintLogger to the Transmitter.
>String toString() shall return a string consisting of “Transmitter(address)”.
>update other methods to add meaningful logging for any actions that cause state changes and when sending a message.
Receiver.java modifications:
Modify Receiver such that:
>one can connect a PrintLogger to it
>it send log entries to the connected PrintLogger (if any) for any actions that cause state changes
>it has a meaningful toString()
More specifically, the following methods should be added or modified to Receiver:
>void addLog(PrintLogger printLogger) shall add a PrintLogger to the Receiver.
>String toString() shall return a string consisting of “Receiver(address)”.
>update other methods to add meaningful logging for any actions that cause state changes.
Create a PrintLogger class:
>An I/O class for conditionally outputting strings to stdout. PrintLogger implements a concept of a level where nothing will print if the level of the request does not equal or exceed the level at which the printLogger is operating at.
--Constructor:
PrintLogger(int logLevel)
--Commands:
void setLogLevel(int newLogLevel);
where
>newLogLevel is the level that must be met or exceeded when the logger is asked to log (print) something
void log(int level, String logEntry);
where
>level is a value noting the type of the information where common values are given in the table below
>logEntry is a text to be part of the printed log
which prints a string to stdout if level is active. The printing routine will add a newline to the logEntry.
SO FAR THIS IS WHAT I GOT FOR: Message.java, Transmitter.java, and Receiver.java. I need to modify Transmitter.java and Receiver.java as mention above with those requirements. Then this TestP3.java is the main class (It will connected message.java, transmitter.java, and receiver.java).
This is the code for Message.java:
public class Message {
private String message;
private String contentType = "text/plain";
private String source ="unset";
private String destination = "unset";
private static int count = 0;
private int messageUID= 10000;
public Message() {
this.message = "";
messageUID = messageUID + count;
count++;
}
public Message(String content) {
this.message = content;
messageUID = messageUID + count;
count++;
}
public long getUID() {
return messageUID;
}
public String getSource() {
return source;
}
public String getDestination() {
return destination;
}
@Override
public String toString() {
return message;
}
public String getType() {
return contentType;
}
public String dump() {
String lineSeparator = System.getProperty("line.separator");
return "UID: "+ messageUID+" " + "Source: "+ source+ " " + "Destination: " + destination + lineSeparator +
"ContentType:" +" "+ contentType + lineSeparator +
"Message:" + lineSeparator +
">>"+message+"<<";
}
public void setContent(String text) {
this.message = text;
}
public void setSource(String address) {
source = address;
}
public void setDestination(String address) {
destination = address;
}
}
This is the code so far for Receiver.java (but need to modify):
public class Receiver {
private String address;
private Message message;
private boolean status = false;
public Receiver() {
this.address = "unknown";
this.message = null;
}
public Receiver(String address) {
this.address = address;
}
public String getAddress() {
return address;
}
public boolean overrun() {
return status;
}
public boolean available(){
return (message != null);
}
public void deliver(Message message){
if ( this.message != null){
status = true;
}
this.message = message;
}
public Message getMessage(){
Message m = message;
message = null;
return m;
}
public void reset() {
message = null;
status = false;
}
}
This is the code so far for Transmitter.java (but need to modify):
public class Transmitter {
private Receiver linkReceiver = null;
private String address;
public Transmitter(){
this.address = "unknown";
}
public Transmitter(String address) {
this.address = address;
}
public String getAddress() {
return address;
}
public void connect(Receiver receiver) {
this.linkReceiver = receiver;
}
public void send(Message message) {
if ( linkReceiver != null) {
message.setDestination( linkReceiver.getAddress());
message.setSource(address);
linkReceiver.deliver(message);
}
}
public void disconnect(){
linkReceiver = null;
}
}
This is the code for TestP3.java (this is the main class and connect message, receiver and transmitter):
public class TestP3 {
public static void main(String[] args) {
PrintLogger logger = new PrintLogger();
Transmitter t1 = new Transmitter("tx");
//t1.addLog(logger);
Receiver r1 = new Receiver("rx");
//r1.addLog(logger);
Message m1 = new Message();
Message m2 = new Message("m2 contents");
Message m3 = new Message("m3 contents");
// check Messages (left to guarantee start at 10000)
passFail(m1.getUID() == 10000, "test1");
for (int i = 0; i < 2; i++ ) {
if ( i == 1 ) {
logger.setLogLevel(PrintLogger.ERROR);
System.out.println("Second pass, log only errors ********");
}
/*
*
* UID: nnnnn Source: sourceaddr destination: destaddr
* ContentType: text/plain
* Message:
* Text of message
*
*/
String lineSeparator = System.getProperty("line.separator");
String messageDump
= "UID: 10001 Source: unset Destination: unset" + lineSeparator
+ "ContentType: text/plain" + lineSeparator
+ "Message:" + lineSeparator
+ ">>m2 contents<<";
String mDump = m2.dump();
if ( i == 0 ) {
passFail(mDump.equals(messageDump), "test2");
}
// send before connecting a transmitter
t1.send(m3);
// connect r1 to t1 and send a message
t1.connect(r1);
t1.send(m2);
Message m = r1.getMessage();
messageDump
= "UID: 10001 Source: tx Destination: rx" + lineSeparator
+ "ContentType: text/plain" + lineSeparator
+ "Message:" + lineSeparator
+ ">>m2 contents<<";
mDump = m.dump();
passFail(mDump.equals(messageDump), "test3");
// check overrun behavior followed by reset
t1.send(m2);
t1.send(m3);
t1.send(m3);
t1.send(m3);
passFail(r1.overrun(), "test4");
r1.reset();
passFail(!r1.overrun(), "test5");
passFail(r1.getMessage() == null, "test6");
t1.disconnect();
}
}
// Helper function to print results of test
private static void passFail(boolean test, String name) {
System.out.println("Test " + name + (test ? " passes" : " fails"));
}
}
After run TestP3.java, this should be the expected output:
Test test1 passes
Test test2 passes
Transmitter(tx): no connected receiver.
Transmitter(tx): connected receiver: Receiver(rx)
Receiver(rx): delivery of message: m2 contents
Transmitter(tx): sending message to Receiver(rx)
Transmitter(tx): delivering message: m2 contents
Receiver(rx): retrieving message: m2 contents
Test test3 passes
Receiver(rx): delivery of message: m2 contents
Transmitter(tx): sending message to Receiver(rx)
Transmitter(tx): delivering message: m2 contents
Receiver(rx): delivery of message: m3 contents
Transmitter(tx): sending message to Receiver(rx)
Transmitter(tx): delivering message: m3 contents
Receiver(rx): delivery of message: m3 contents
Transmitter(tx): sending message to Receiver(rx)
Transmitter(tx): delivering message: m3 contents
Receiver(rx): overrun caused by delivery of message: m3 contents
Transmitter(tx): sending message to Receiver(rx)
Transmitter(tx): delivering message: m3 contents
Test test4 passes
Receiver(rx): reseting
Test test5 passes
Receiver(rx): attempt to get non-existent message
Test test6 passes
Transmitter(tx): Receiver(rx) disconnected.
Second pass, log only errors ********
Transmitter(tx): no connected receiver.
Test test3 passes
Receiver(rx): overrun caused by delivery of message: m3 contents
Test test4 passes
Test test5 passes
Receiver(rx): attempt to get non-existent message
Test test6 passes
Explanation / Answer
public MidiSimple( String theDeviceName , Receiver theReceiver ) {
MidiDevice.Info[] aInfos = MidiSystem.getMidiDeviceInfo();
for ( int i = 0; i < aInfos.length; i++ ) {
try {
MidiDevice device = MidiSystem.getMidiDevice( aInfos[ i ] );
boolean bAllowsInput = ( device.getMaxTransmitters() != 0 );
boolean bAllowsOutput = ( device.getMaxReceivers() != 0 );
System.out.println( "" + i + " " + ( bAllowsInput ? "IN " : " " ) + ( bAllowsOutput ? "OUT " : " " ) + aInfos[ i ].getName() + ", " + aInfos[ i ].getVendor() + ", "
+ aInfos[ i ].getVersion() + ", " + aInfos[ i ].getDescription() );
}
catch ( MidiUnavailableException e ) {
// device is obviously not available...
// out(e);
}
}
try {
MidiDevice device;
device = MidiSystem.getMidiDevice( getMidiDeviceInfo( theDeviceName, false ) );
device.open();
Transmitter conTrans = device.getTransmitter();
conTrans.setReceiver( theReceiver );
}
catch ( MidiUnavailableException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NullPointerException e) {
System.out.println("No Midi device ( "+theDeviceName+" ) is available.");
}
}
private boolean loadInputDevices() {
MidiDevice device = null;
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
boolean deviceLoaded = false;
for (int i = 0; i < infos.length; i++) {
System.out.println(i + ": " + infos[i].getName());
try {
device = MidiSystem.getMidiDevice(infos[i]);
System.out.println(" " + i + " class: " + device.getClass().getName());
System.out.println(" " + i + " receivers: " + device.getMaxReceivers());
System.out.println(" " + i + " transmitters: " + device.getMaxTransmitters());
if (device.getClass().getName().equalsIgnoreCase("com.sun.media.sound.MidiInDevice")) {
System.out.println("MIDI In Found!");
if (!device.isOpen() && device.getMaxTransmitters() != 0) {
device.open();
openDevices.addLast(device);
Transmitter t = device.getTransmitter();
transmitters.addLast(t);
t.setReceiver(this);
deviceLoaded = true;
}
}
device = null;
}
catch (MidiUnavailableException e) {
System.out.println("Error loading device " + i + " " + e);
}
}
return deviceLoaded;
}
private static synchronized String getDefaultProvider(Class typeClass) {
if (!SourceDataLine.class.equals(typeClass)
&& !TargetDataLine.class.equals(typeClass)
&& !Clip.class.equals(typeClass)
&& !Port.class.equals(typeClass)
&& !Receiver.class.equals(typeClass)
&& !Transmitter.class.equals(typeClass)
&& !Synthesizer.class.equals(typeClass)
&& !Sequencer.class.equals(typeClass)) {
return null;
}
String value;
String propertyName = typeClass.getName();
value = JSSecurityManager.getProperty(propertyName);
if (value == null) {
value = getProperties().getProperty(propertyName);
}
if ("".equals(value)) {
value = null;
}
return value;
}
public TMidiDevice(MidiDevice.Info info,
boolean bUseTransmitter,
boolean bUseReceiver)
{
m_info = info;
m_bUseTransmitter = bUseTransmitter;
m_bUseReceiver = bUseReceiver;
m_bDeviceOpen = false;
m_receivers = new ArrayList<Receiver>();
m_transmitters = new ArrayList<Transmitter>();
}
@Override public final void execute ( final INotification notification )
{
MidiProxy midiProxy = ( MidiProxy ) getFacade ( ).retrieveProxy ( MidiProxy.NAME );
MidiDevice.Info midiDeviceInfo = getMIDIDeviceInfo ( notification, midiProxy );
if ( midiDeviceInfo == null )
{
return;
}
try
{
/** Get the MIDI device. */
MidiDevice midiDevice = MidiSystem.getMidiDevice ( midiDeviceInfo );
System.out.println ( "OpenMidiDeviceCommand - MIDI device: " + midiDeviceInfo.getDescription ( ) + ", notification: " + notification.getName ( ) );
if ( notification.getName ( ) == SeqNotifications.OPEN_MIDI_IN_DEVICE )
{
/** Set the MIDI IN device. */
midiProxy.setMidiInDevice ( midiDevice );
midiProxy.setMidiInDeviceInfo ( midiDeviceInfo );
/** Close previous transmitter if it is open. */
Transmitter transmitter = midiProxy.getClockTransmitter ( );
if ( transmitter != null )
{
transmitter.close ( );
}
transmitter = midiProxy.getNoteTransmitter ( );
if ( transmitter != null )
{
transmitter.close ( );
}
/** Open the new transmitter. */
midiProxy.setClockTransmitter ( midiDevice.getTransmitter ( ) );
midiProxy.setNoteTransmitter ( midiDevice.getTransmitter ( ) );
/** Store device name in preferences. */
EPGPreferences.put ( EPGPreferences.MIDI_IN_DEVICE, midiDevice.getDeviceInfo ( ).getName ( ) );
sendNotification ( SeqNotifications.MIDI_IN_DEVICE_OPENED, midiDeviceInfo );
}
else if ( notification.getName ( ) == SeqNotifications.OPEN_MIDI_OUT_DEVICE )
{
/** Set the MIDI OUT device. */
midiProxy.setMidiOutDevice ( midiDevice );
midiProxy.setMidiOutDeviceInfo ( midiDeviceInfo );
/** Close previous receiver if it is open. */
Receiver receiver = midiProxy.getReceiver ( );
if ( receiver != null )
{
receiver.close ( );
}
/** Open the new receiver. */
midiProxy.setReceiver ( midiDevice.getReceiver ( ) );
/** Store device name in preferences. */
EPGPreferences.put ( EPGPreferences.MIDI_OUT_DEVICE, midiDevice.getDeviceInfo ( ).getName ( ) );
sendNotification ( SeqNotifications.MIDI_OUT_DEVICE_OPENED, midiDeviceInfo );
}
/** Open the device. */
if ( !midiDevice.isOpen ( ) )
{
try
{
midiDevice.open ( );
}
catch ( MidiUnavailableException exception )
{
System.out.println ( "OpenMidiDeviceCommand exception - MIDI device can't be opened: " + exception.getMessage ( ) );
}
}
}
catch ( MidiUnavailableException exception )
{
System.out.println ( "OpenMidiDeviceCommand exception - MIDI device unavailable: " + exception.getMessage ( ) );
}
}
public void play() throws MidiUnavailableException,
InvalidMidiDataException {
final Sequencer sequencer;
final Synthesizer synthesizer;
/*
* Now, we need a Sequencer to play the sequence. Here, we simply
* request the default sequencer without an implicitly connected
* synthesizer
*/
sequencer = MidiSystem.getSequencer(false);
/*
* The Sequencer is still a dead object. We have to open() it to become
* live. This is necessary to allocate some ressources in the native
* part.
*/
sequencer.open();
/*
* Next step is to tell the Sequencer which Sequence it has to play. In
* this case, we set it as the Sequence object created above.
*/
sequencer.setSequence(sequence);
/*
* We try to get the default synthesizer, open() it and chain it to the
* sequencer with a Transmitter-Receiver pair.
*/
synthesizer = MidiSystem.getSynthesizer();
synthesizer.open();
final Receiver synthReceiver = synthesizer.getReceiver();
final Transmitter seqTransmitter = sequencer.getTransmitter();
seqTransmitter.setReceiver(synthReceiver);
/*
* To free system resources, it is recommended to close the synthesizer
* and sequencer properly. To accomplish this, we register a Listener to
* the Sequencer. It is called when there are "meta" events. Meta event
* 47 is end of track. Thanks to Espen Riskedal for finding this trick.
*/
sequencer.addMetaEventListener(new MetaEventListener() {
public void meta(final MetaMessage event) {
if (event.getType() == 47) {
sequencer.close();
if (synthesizer != null) {
synthesizer.close();
}
}
}
});
/*
* Now, we can start over.
*/
sequencer.start();
}
import javax.sound.midi.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
public class Main {
public static Receiver synthRcvr = new CustomReceiver();
public static Transmitter seqTrans;
public static Synthesizer synth;
public static void main(String[] args) {
try {
sequencer = MidiSystem.getSequencer();
sequence = MidiSystem.getSequence(new File("test.midi"));
Sequencer sequencer = MidiSystem.getSequencer();
seqTrans = sequencer.getTransmitter();
seqTrans.setReceiver(synthRcvr);
sequencer.open();
sequencer.setSequence(sequence);
sequencer.start();
} catch (IOException | MidiUnavailableException | InvalidMidiDataException e) {
System.out.println(e);
}
}
import javax.sound.midi.MidiMessage;
import javax.sound.midi.Receiver;
public class CustomReceiver implements Receiver {
public CustomReceiver() {
}
@Override
public void send(MidiMessage message, long timeStamp) {
// Process midi messages here
}
@Override
public void close() {
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.