001/* 002 * Copyright (C) Cross The Road Electronics. All rights reserved. 003 * License information can be found in CTRE_LICENSE.txt 004 * For support and suggestions contact support@ctr-electronics.com or file 005 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases 006 */ 007package com.ctre.phoenix6; 008 009import java.util.Collection; 010 011import com.ctre.phoenix6.hardware.ParentDevice; 012import com.ctre.phoenix6.jni.OrchestraJNI; 013 014/** 015 * Orchestra is used to play music through devices. It uses a "Chirp" (.chrp) music 016 * file that can be generated using Phoenix Tuner. Chirp files are generated from 017 * standard MIDI files. 018 * <p> 019 * Any Chirp file located in the src/main/deploy directory of your FRC project will 020 * automatically be copied to the roboRIO on code deploy. 021 * <p> 022 * The robot must be enabled to play music. Additionally, devices playing in Orchestra 023 * will not run any other control requests while Orchestra is running. Users can 024 * {@link #pause} or {@link #stop} the Orchestra to re-enable device control. 025 * <p> 026 * Each device can only play a single track within the music file. For multi-track 027 * files, multiple devices are needed. Devices can be added with an explicit track 028 * number. Otherwise, the first track will be played through the first Talon FX added, 029 * the second track will be played through the second Talon FX added, etc. 030 * <p> 031 * To use Orchestra: 032 * <ul> 033 * <li> Add the Talon FXs to be used as instruments using {@link #addInstrument}. 034 * <li> Load the Chirp file to be played using {@link #loadMusic}. This can also 035 * be done in the Orchestra constructor. 036 * </ul> 037 * Both of these can also be done in the Orchestra constructor. 038 * <p> 039 * Once ready, the Orchestra can be controlled using {@link #play}/{@link #pause}/{@link #stop}. 040 * New music files can be loaded at any time. 041 */ 042public class Orchestra implements AutoCloseable { 043 private OrchestraJNI jni = new OrchestraJNI(); 044 045 /** 046 * Constructor for a new Orchestra. 047 */ 048 public Orchestra() { 049 jni.JNI_Create(); 050 } 051 052 /** 053 * Constructor for a new Orchestra using the given Chirp file. 054 * 055 * @param filepath The path to the music file to immediately load into the orchestra. 056 */ 057 public Orchestra(String filepath) { 058 this(); 059 loadMusic(filepath); 060 } 061 062 /** 063 * Constructor for a new Orchestra using the given instruments. 064 * 065 * @param instruments A collection of devices that will be used as instruments in the orchestra. 066 */ 067 public Orchestra(Collection<ParentDevice> instruments) { 068 this(); 069 for (var instrument : instruments) { 070 addInstrument(instrument); 071 } 072 } 073 074 /** 075 * Constructor for a new Orchestra using the given instruments and Chirp file. 076 * 077 * @param instruments A collection of devices that will be used as instruments in the orchestra. 078 * @param filepath The path to the music file to immediately load into the orchestra. 079 */ 080 public Orchestra(Collection<ParentDevice> instruments, String filepath) { 081 this(); 082 for (var instrument : instruments) { 083 addInstrument(instrument); 084 } 085 loadMusic(filepath); 086 } 087 088 /** 089 * Closes this Orchestra instance. 090 */ 091 @Override 092 public void close() { 093 jni.JNI_Close(); 094 } 095 096 /** 097 * Adds an instrument to the orchestra. 098 * 099 * @param instrument The device to add to the orchestra 100 * @return Status code of adding the device 101 */ 102 public StatusCode addInstrument(ParentDevice instrument) { 103 return StatusCode.valueOf(jni.JNI_AddDevice(instrument.getNetwork(), instrument.getDeviceHash())); 104 } 105 106 /** 107 * Adds an instrument to the orchestra on the given track. 108 * 109 * @param instrument The device to add to the orchestra 110 * @param trackNumber The track number the device should play, starting at 0 111 * @return Status code of adding the device 112 */ 113 public StatusCode addInstrument(ParentDevice instrument, int trackNumber) { 114 return StatusCode.valueOf(jni.JNI_AddDeviceWithTrack(instrument.getNetwork(), instrument.getDeviceHash(), trackNumber)); 115 } 116 117 /** 118 * Clears all instruments in the orchestra. 119 * 120 * @return Status code of clearing all devices 121 */ 122 public StatusCode clearInstruments() { 123 return StatusCode.valueOf(jni.JNI_ClearDevices()); 124 } 125 126 /** 127 * Loads a Chirp file at the specified file path. 128 * <p> 129 * If the Chirp file is inside your "src/main/deploy" directory, it will be 130 * automatically deployed to a default directory on the roboRIO when you 131 * deploy code. For these files, the name and file extension is sufficient. 132 * <p> 133 * A Chirp file can be created from a MIDI file using Phoenix Tuner. 134 * 135 * @param filepath The path to the Chirp file 136 * @return Status code of loading the Chirp file 137 */ 138 public StatusCode loadMusic(String filepath) { 139 return StatusCode.valueOf(jni.JNI_LoadMusic(filepath)); 140 } 141 142 /** 143 * Plays the loaded music file. If the player is paused, this will resume 144 * the orchestra. 145 * 146 * @return Status code of playing the orchestra 147 */ 148 public StatusCode play() { 149 return StatusCode.valueOf(jni.JNI_Play()); 150 } 151 152 /** 153 * Pauses the loaded music file. This saves the current position in the 154 * track so it can be resumed later. 155 * 156 * @return Status code of pausing the orchestra 157 */ 158 public StatusCode pause() { 159 return StatusCode.valueOf(jni.JNI_Pause()); 160 } 161 162 /** 163 * Stops the loaded music file. This resets the current position in the 164 * track to the start. 165 * 166 * @return Status code of stopping the orchestra 167 */ 168 public StatusCode stop() { 169 return StatusCode.valueOf(jni.JNI_Stop()); 170 } 171 172 /** 173 * Gets whether the current track is actively playing. 174 * 175 * @return true if Orchestra is playing the music file 176 */ 177 public boolean isPlaying() { 178 return jni.JNI_IsPlaying(); 179 } 180 181 /** 182 * Gets the current timestamp of the music file. The timestamp will reset 183 * to zero whenever {@link #loadMusic} or {@link #stop} is called. 184 * <p> 185 * If {@link #isPlaying} returns false, this method can be used to determine 186 * if the music is stopped or paused. 187 * 188 * @return The current timestamp of the music file, in seconds 189 */ 190 public double getCurrentTime() { 191 return jni.JNI_GetCurrentTime(); 192 } 193}