001/* Copyright (C) Cross The Road Electronics 2024 */ 002/* 003 * Software License Agreement 004 * 005 * Copyright (C) Cross The Road Electronics. All rights 006 * reserved. 007 * 008 * Cross The Road Electronics (CTRE) licenses to you the right to 009 * use, publish, and distribute copies of CRF (Cross The Road) firmware files (*.crf) and Software 010 * API Libraries ONLY when in use with Cross The Road Electronics hardware products. 011 * 012 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT 013 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT 014 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A 015 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL 016 * CROSS THE ROAD ELECTRONICS BE LIABLE FOR ANY INCIDENTAL, SPECIAL, 017 * INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF 018 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS 019 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE 020 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER 021 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT 022 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE 023 */ 024package com.ctre.phoenix.music; 025 026import com.ctre.phoenix.ErrorCode; 027import com.ctre.phoenix.motorcontrol.can.TalonFX; 028import java.util.Collection; 029 030/** 031 * An Orchestra is used to play music through Talon FX motor controllers. 032 * It uses a "Chirp" (.chrp) music file that can be generated using Phoenix Tuner. 033 * 034 * Chirp files are generated from standard MIDI files. 035 * Each Talon FX can only play a single track within the music file. 036 * For multi-track files, multiple Talon FXs are needed. 037 * ie, The first track will be played through the first Talon FX added, 038 * the second track will be played through the second Talon FX added, etc. 039 * 040 * Any Chirp file located in the src/main/deploy directory of your FRC project 041 * will automatically be copied to the roboRIO on code deploy. 042 * 043 * To use the Orchestra: 044 * - Add the Talon FXs to be used as instruments 045 * - Load the Chirp file to be played using the loadMusic routine. 046 * Both of these can also be done in the Orchestra constructor. 047 * 048 * Once ready, the Orchestra can be controlled using standard 049 * play/pause/stop routines. 050 * 051 * New music files can be loaded at any time. 052 * 053 * The robot must be enabled to play music. 054 * 055 * Calling set on any of the TalonFX instruments while the orchestra is 056 * playing will pause the orchestra. 057 */ 058public class Orchestra { 059 private long m_handle; 060 061 /** 062 * Constructor for an Orchestra Object. 063 * Call AddInstrument after this to add the instruments. 064 */ 065 public Orchestra() { 066 m_handle = OrchestraJNI.JNI_new_Orchestra(); 067 } 068 /** 069 * Constructor for an Orchestra Object. 070 * @param instruments 071 * A collection of TalonFX's that will be used as instruments 072 * inside the orchestra. 073 */ 074 public Orchestra(Collection<TalonFX> instruments) { 075 this(); 076 077 for(TalonFX instrument : instruments) { 078 addInstrument(instrument); 079 } 080 } 081 /** 082 * Constructor for an Orchestra Object 083 * @param instruments 084 * A collection of TalonFX's that will be used as instruments 085 * inside the orchestra. 086 * @param filePath 087 * The path to the music file to immediately load into 088 * the orchestra. 089 */ 090 public Orchestra(Collection<TalonFX> instruments, String filePath) { 091 this(instruments); 092 093 loadMusic(filePath); 094 } 095 096 /** 097 * Loads a Chirp file at the specified file path. 098 * 099 * If the Chirp file is inside your "src/main/deploy" directory 100 * this file will be automatically deployed to a default directory in 101 * the RoboRIO when you deploy code. For these files, the name and file 102 * extension is sufficient. 103 * 104 * Use Tuner to create a Chirp file. 105 * @param filePath 106 * The path to the Chirp File. 107 * @return Error Code generated by function. 0 indicates no error. 108 */ 109 public ErrorCode loadMusic(String filePath) { 110 int retval = OrchestraJNI.JNI_LoadMusic(m_handle, filePath); 111 return ErrorCode.valueOf(retval); 112 } 113 114 /** 115 * Plays the music file that's loaded. 116 * If the player is paused, this will resume. 117 * This will also resume a song if the orchestra was interrupted. 118 * @return Error Code generated by function. 0 indicates no error. 119 */ 120 public ErrorCode play() { 121 int retval = OrchestraJNI.JNI_Play(m_handle); 122 return ErrorCode.valueOf(retval); 123 } 124 125 /** 126 * Stops the music file that's loaded. 127 * This resets the current position in the track to the start. 128 * @return Error Code generated by function. 0 indicates no error. 129 */ 130 public ErrorCode stop() { 131 int retval = OrchestraJNI.JNI_Stop(m_handle); 132 return ErrorCode.valueOf(retval); 133 } 134 135 /** 136 * Pauses the music file that's loaded. 137 * This saves the current position in the track, so it can be resumed later. 138 * Pausing while stopped is an invalid request. 139 * @return Error Code generated by function. 0 indicates no error. 140 */ 141 public ErrorCode pause() { 142 int retval = OrchestraJNI.JNI_Pause(m_handle); 143 return ErrorCode.valueOf(retval); 144 } 145 146 /** 147 * Returns whether the current track is actively playing or not 148 * @return True if playing, false otherwise 149 */ 150 public boolean isPlaying() { 151 return OrchestraJNI.JNI_IsPlaying(m_handle); 152 } 153 154 /** 155 * @return The current timestamp of the music file (playing or paused) in milliseconds. 156 * The timestamp will reset to zero whenever loadMusic() or stop() is called. 157 * If isPlaying() returns false, this routine can be used to determine if music is stopped or paused. 158 */ 159 public int getCurrentTime() { 160 return OrchestraJNI.JNI_GetCurrentTime(m_handle); 161 } 162 163 /** 164 * Clears all instruments in the orchestra. 165 * @return Error Code generated by function. 0 indicates no error. 166 */ 167 public ErrorCode clearInstruments() { 168 int retval = OrchestraJNI.JNI_ClearInstruments(m_handle); 169 return ErrorCode.valueOf(retval); 170 } 171 172 /** 173 * Adds another instrument to the orchestra. 174 * @param instrument 175 * TalonFX to add to orchestra 176 * @return Error Code generated by function. 0 indicates no error. 177 */ 178 public ErrorCode addInstrument(TalonFX instrument) { 179 int retval = OrchestraJNI.JNI_AddInstrument(m_handle, instrument.getHandle()); 180 return ErrorCode.valueOf(retval); 181 } 182}