How to play a .MIDI file in a new thread in Java? - java

I am remaking part of a game in Java, and I need to know how to play the MIDI sound files. Preferably it would not involve importing any external libraries. It must also be runnable in a new thread, so that I can stack the individual sounds over the background song.
Thanks for your thoughts and time.

This code plays two MIDI tracks at the same time (the 2nd sequence starts as soon as the 1st dialog is dismissed). No threads are explicitly created, but I imagine it would work much the same if they were wrapped in a Thread object.
import java.net.URL;
import java.util.Locale;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.midi.Transmitter;
import javax.swing.JOptionPane;
import org.apache.commons.lang.StringUtils;
class PlayMidi {
public static boolean useExternalSynth = false;
public static void main(String[] args) throws Exception {
MidiDevice receivingDevice = getReceivingDevice();
receivingDevice.open();
URL url1 = new URL("http://pscode.org/media/EverLove.mid");
Sequence sequence1 = MidiSystem.getSequence(url1);
Sequencer sequencer1 = MidiSystem.getSequencer(false);
Transmitter tx1 = sequencer1.getTransmitter();
Receiver rx1 = receivingDevice.getReceiver();
tx1.setReceiver(rx1);
sequencer1.open();
sequencer1.setSequence(sequence1);
URL url2 = new URL("http://pscode.org/media/AftrMdnt.mid");
Sequence sequence2 = MidiSystem.getSequence(url2);
Sequencer sequencer2 = MidiSystem.getSequencer(false);
Transmitter tx2 = sequencer2.getTransmitter();
Receiver rx2 = receivingDevice.getReceiver();
tx2.setReceiver(rx2);
sequencer2.open();
sequencer2.setSequence(sequence2);
sequencer1.start();
JOptionPane.showMessageDialog(null, "Everlasting Love");
sequencer2.start();
JOptionPane.showMessageDialog(null, "After Midnight");
}
private static MidiDevice getReceivingDevice()
throws MidiUnavailableException {
for (MidiDevice.Info mdi: MidiSystem.getMidiDeviceInfo()) {
MidiDevice dev = MidiSystem.getMidiDevice(mdi);
if (dev.getMaxReceivers() != 0) {
String lcName =
StringUtils.defaultString(mdi.getName())
.toLowerCase(Locale.ENGLISH);
if (lcName.contains(useExternalSynth? "usb": "java")) {
return dev;
}
}
}
return null;
}
}

Related

How to use a string from another method

I am trying to make a plugin where when a certain block in the GUI is clicked, a command is run. The problem is, I have to transfer a string from one method to another. I don't have very much java knowledge, so if someone could teach me how to do this, I would very much appreciate it.
P.S. The string I am trying to use is called custompermscommand.
Code:
package me.eliminiquated.yugengrant;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
public class Grant implements CommandExecutor, Listener {
#Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (command.getName().equals("grant")){
if (sender instanceof Player){
Player player = (Player) sender;
if (player.hasPermission("yugen.grant")){
if (args.length == 1){
player.sendMessage("Incorrect Usage! </grant (username)>");
}else if (args.length == 2){
Inventory gui = Bukkit.createInventory(player, 27, ChatColor.DARK_GREEN+"Grant Menu");
ItemStack custom = new ItemStack(Material.ORANGE_GLAZED_TERRACOTTA);
ItemStack playerranks = new ItemStack(Material.LAPIS_BLOCK);
ItemStack staffpositions = new ItemStack(Material.REDSTONE_BLOCK);
ItemMeta custommeta = custom.getItemMeta();
ItemMeta playerranksmeta = playerranks.getItemMeta();
ItemMeta staffpositionsmeta = staffpositions.getItemMeta();
custommeta.setDisplayName(ChatColor.GOLD+"Custom");
ArrayList<String> custom_lore = new ArrayList<>();
custom_lore.add(ChatColor.GRAY+""+ChatColor.ITALIC+"Coming soon");
custommeta.setLore(custom_lore);
custom.setItemMeta(custommeta);
playerranksmeta.setDisplayName(ChatColor.AQUA+"Player Ranks");
playerranks.setItemMeta(playerranksmeta);
staffpositionsmeta.setDisplayName(ChatColor.RED+"Staff Positions");
staffpositions.setItemMeta(staffpositionsmeta);
gui.setItem(10, custom);
gui.setItem(12, playerranks);
gui.setItem(14, staffpositions);
player.openInventory(gui);
String custompermscommand = "grantcustomperms "+args[0]+"";
}else{
player.sendMessage("Incorrect Usage! </grant (username)>");
}
}else{
player.sendMessage(ChatColor.RED+"You do not have permission to execute this command!");
}
}
}else{
System.out.println("You must be a player to execute this command");
}
return false;
}
#EventHandler
public void onInventoryClick(InventoryClickEvent event){
Player player = (Player) event.getWhoClicked();
if (event.getClickedInventory().getTitle().equalsIgnoreCase(ChatColor.DARK_GREEN+"Grant Menu")){
if (event.getCurrentItem().getType() == Material.ORANGE_GLAZED_TERRACOTTA){
Bukkit.dispatchCommand(player, custompermscommand);
}
}
}
}
For anyone that wants to do this themselves, this is the answer:
First, declare the variable as public outside of the methods:
Example:
public String command;
Next, edit the string inside of the method that you want to grab the string from:
Example:
command = args[0];
Finally, you are able to call this string in whatever method you want:
Example:
Bukkit.dispatchCommand(player, command);

java value recieved from client-server program used in another program

My project looks like: I have a bike speedometer attached to simple bike and connected to Raspberry Pi, which is connected over ethernet cable to laptop.
What I want to do is: Raspberry measure the speed of bike wheel and send this value over ethernet cable to laptop. Laptop now uses recieved value and speed up a video, which is played in VLC.
I have working java program on RPi to measure speed of a wheel, I have a working client (on laptop)-server (on RPi) java program to send values from RPi to laptop, and I have a working java program to control speed of video playing in VLC on laptop.
But my problem is, that I don't know how to use values, recieved from RPi over client-server program, in my program, which control speed of video, playing in VLC.
Down are my codes for client and to control speed of video.
Client code:
package player;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class client {
public static int inputPlayer = 0;
public static void main(String[] args) throws UnknownHostException, IOException {
String accept;
int input;
DataInputStream inC = null;
Scanner sc1 = null;
Socket s = null;
try {
s = new Socket ("169.254.218.194", 1342);
Scanner sc = new Scanner (System.in);
System.out.println("Accept connection!");
accept = sc.next();
PrintStream p = new PrintStream (s.getOutputStream());
p.println(accept);
//inC = new DataInputStream(s.getInputStream());
}
catch (Exception e) {
e.printStackTrace();
}
while (true) {
sc1 = new Scanner (s.getInputStream());
input = sc1.nextInt();
if (input > 0) {
inputPlayer = input;
}
System.out.println("I" + input);
//System.out.println("IP" + inputPlayer);
}
}
public int getInputPlayer () {
return this.inputPlayer;
}
}
Player code:
package player;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Scanner;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.discovery.NativeDiscovery;
public class Player {
private final JFrame frame;
private final EmbeddedMediaPlayerComponent mediaPlayerComponent;
public static void main(final String[] args) {
new NativeDiscovery().discover();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Player(args);
}
});
}
public Player(String[] args) {
frame = new JFrame("My First Media Player");
frame.setBounds(100, 100, 600, 400);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
mediaPlayerComponent.release();
System.exit(0);
}
});
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout());
mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
contentPane.add(mediaPlayerComponent, BorderLayout.CENTER);
Scanner in = new Scanner (System.in);
frame.setContentPane(contentPane);
frame.setVisible(true);
mediaPlayerComponent.getMediaPlayer().playMedia("file:URL");
mediaPlayerComponent.getMediaPlayer().skip(1000);
client c = new client();
float i = c.getInputPlayer();
while (true) {
//float i = in.nextFloat();
//System.out.println(i);
mediaPlayerComponent.getMediaPlayer().setRate(i);
}
}
}
Everything I want to do is to use variable inputPlayer from client class as variable i in Player class.
As I have done, Eclipse return me error: "[000000001ade9eb0] core input error: input control fifo overflow, trashing type=2"
Thanks for your help.
Jan
There are several problems here:
the code in the client class (btw, class names should begin with uppercase) is never run. You've put all the code in that class in a main method, which only gets executed if you run the application by choosing that class. Essentially, you have two separate applications here. Even if you were to run them at the same time, it wouldn't help you since one would not have direct access to instances of classes in the other.
i is set only once and never updated inside the loop
you could turn that main method of the client class into an ordinary method, but even then you can't have two while(true) loops run at the same time if they are on the same thread.
If handling thread is a bit much for you at this stage, you could try simply combining both classes in one. One loop would scan for incoming data and set the players speed as it came. This might or might not work, depending on how the player itself is implemented, but you could give it a try.

GCM Notification is not working sometimes in Playframework(Play Java)

I am writing code for GCM notification to send to my android app using the registered id with GCM Server and project API key. Sometimes it's not sending any notification and it's only working for some API keys, but not for others.
I am posting sample code here. I have searched the internet but I got only play Scala. But I need for play Java. I am using playframework with Java.
Is there any alternative code in Playframework?
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import play.Logger;
import com.google.android.gcm.server.Message;
import com.google.android.gcm.server.MulticastResult;
import com.google.android.gcm.server.Result;
import com.google.android.gcm.server.Sender;
public class GcmNotification {
public static boolean sendNotification(String notification, String regId) {
// api key
final Sender sender = new Sender("AIzaSyCQAE7VyFHreppcOkv7aXGk8JOxy4Osxdgvx");
Result result = null;
final Message message = new Message.Builder().timeToLive(30)
.delayWhileIdle(true)
.addData("date", new Date().getTime() + "")
.addData("message", notification).build();
final List<String> regids = new ArrayList<String>();
regids.add(regId);
Logger.info("entered2 : " + regids.size());
try {
result = sender.send(message, regids, 1);
} catch (final IOException e) {
e.printStackTrace();
}
return true;
}
}

Cannot change boolean value in method

I've got a little problem. I'm playing mp3 using Java sound sampled and I want to stop playing when I click the button. So I came up with something like this:
package sk.umb.osadnici.Client.Core.getterImages;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine.Info;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.FloatControl;
import javazoom.jl.player.advanced.AdvancedPlayer;
import static javax.sound.sampled.AudioSystem.getAudioInputStream;
import static javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED;
public class GetterForBGMusic {
private SourceDataLine line;
private URL url;
public URL bgUrl, bgUUUrl;
private boolean canPlay = true;
public void runMusic() {
final GetterForBGMusic player = new GetterForBGMusic();
player.play();
}
public void play() {
URL inTTT = getClass().getResource("../sounds/bgMusic.mp3");
try (AudioInputStream in = getAudioInputStream(inTTT)) {
AudioFormat outFormat = getOutFormat(in.getFormat());
Info info = new Info(SourceDataLine.class, outFormat);
try (SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info)) {
if (line != null) {
System.out.println(canPlay);
line.open(outFormat);
line.start();
stream(getAudioInputStream(outFormat, in), line);
line.drain();
line.stop();
}
}
} catch (UnsupportedAudioFileException
| LineUnavailableException
| IOException e) {
throw new IllegalStateException(e);
}
}
private AudioFormat getOutFormat(AudioFormat inFormat) {
final int ch = inFormat.getChannels();
final float rate = inFormat.getSampleRate();
return new AudioFormat(PCM_SIGNED, rate, 16, ch, ch * 2, rate, false);
}
private void stream(AudioInputStream in, SourceDataLine line)
throws IOException {
while (true) {
System.out.println(this.getCanPlay());
}
}
public void setCanPlay(boolean play) {
this.canPlay = play;
}
public boolean getCanPlay() {
return canPlay;
}
private void booleanValue() {
while (true)
System.out.println(canPlay);
}
}
Im using this code, if i call booleanValue method in constructor, everything is fine. but if call this method inside stream there is no change after value change.
Or can someone tell me how to stop this: http://odoepner.wordpress.com/2013/07/19/play-mp3-or-ogg-using-javax-sound-sampled-mp3spi-vorbisspi/
Your program is single-threaded, which means that it executes the sequence of "commands" you programmed from top to bottom.
For example, in this example
setCanPlay(true);
play(); //your for loop
setCanPlay(false);
the setCanPlay(false) instruction will only execute once the for loop has finished executing.
What you need is to have the for loop running in the background, and to be able to modify canPlay while the for loop is running. That's called multi-threading and you should lookup the classes Runnable, Task and Service in the java api doc to learn how to implement it.
You would end up with something like this:
setCanPlay(true);
play(); //your for loop, launched in another thread.
setCanPlay(false); // Executed while the for loop is running
That would start and end the playing instantly.
Multithreading is the only way to stop an executing program (from the outside).

NPE using QBOVendorService

I am trying to query vendors using the QBOVendorService but having no luck.
I am creating the service as follows:
QBOVendorService vService = QBServiceFactory.getService(context, QBOVendorService.class);
where the context is a valid PlatformSessionContext. I know the platform session context is good since I can get information about the user with it. When I try
vService.addVendor(context, vendor);
I end up with a NPE like my vService is null. Shouldn't I get an error initializing the QBOVendorService if it fails? Is there a good place to find more examples for using this since the intuit developer forums have been shut down?
I'm sharing a sample code snippet. Replace your OAuth tokens and relamId. It should work fine.
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import com.intuit.ds.qb.QBIdType;
import com.intuit.ds.qb.QBVendor;
import com.intuit.ds.qb.QBVendorQuery;
import com.intuit.ds.qb.QBVendorService;
import com.intuit.ds.qb.QBInvalidContextException;
import com.intuit.ds.qb.QBObjectFactory;
import com.intuit.ds.qb.QBServiceFactory;
import com.intuit.ds.qb.impl.QBRecordCountImpl;
import com.intuit.ds.qb.qbd.QBDRecordCountService;
import com.intuit.ds.qb.qbd.QBDServiceFactory;
import com.intuit.platform.client.PlatformSessionContext;
import com.intuit.platform.client.PlatformServiceType;
import com.intuit.platform.client.security.OAuthCredentials;
import com.intuit.ds.qb.QBSyncStatusRequest;
import com.intuit.ds.qb.QBSyncStatusRequestService;
import com.intuit.ds.qb.QBSyncStatusResponse;
import com.intuit.sb.cdm.NgIdSet;
import com.intuit.sb.cdm.ObjectName;
import org.slf4j.Logger;
// QBD API Docs - https://developer.intuit.com/docs/0025_quickbooksapi/0050_data_services/v2/0500_quickbooks_windows/0600_object_reference/vendor
// QBO API Docs - https://developer.intuit.com/docs/0025_quickbooksapi/0050_data_services/v2/0400_quickbooks_online/vendor
// JavaDocs - http://developer-static.intuit.com/SDKDocs/QBV2Doc/ipp-java-devkit-2.0.10-SNAPSHOT-javadoc/
public class CodegenStubVendorall {
final PlatformSessionContext context;
public CodegenStubVendorall(PlatformSessionContext context) {
this.context = context;
}
public void testAdd() {
final List<QBVendor> entityList = new ArrayList<QBVendor>();
try {
QBVendorService service = QBServiceFactory.getService(context, QBVendorService.class);
//Your Code
//Use Vendor POJO for creating Vendor
}
} catch (QBInvalidContextException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
PlatformSessionContext context = getPlatformContext();
CodegenStubVendorall testObj = new CodegenStubVendorall(context);
testObj.testAdd();
}
public static PlatformSessionContext getPlatformContext() {
String accesstoken = "rplce_your_application_token";
String accessstokensecret = "rplce_your_application_token";
String appToken = "rplce_your_application_token";
String oauth_consumer_key = "rplce_your_application_token";
String oauth_consumer_secret = "rplce_your_application_token";
String realmID = "123456";
String dataSource = "QBO";
PlatformServiceType serviceType;
if (dataSource.equalsIgnoreCase("QBO")) {
serviceType = PlatformServiceType.QBO;
} else {
serviceType = PlatformServiceType.QBD;
}
final OAuthCredentials oauthcredentials = new OAuthCredentials(
oauth_consumer_key, oauth_consumer_secret, accesstoken,
accessstokensecret);
final PlatformSessionContext context = new PlatformSessionContext(
oauthcredentials, appToken, serviceType, realmID);
return context;
}
}
You can try to use ApiExplorer tool to verify your OAuth tokens and to check the create Vendor API endpoint.
Link - https://developer.intuit.com/apiexplorer?apiname=V2QBO
Please let me know how it goes.
Thanks

Categories

Resources