diff --git a/jam-ui/src/components/client/JKSessionBackingTrack.js b/jam-ui/src/components/client/JKSessionBackingTrack.js
new file mode 100644
index 000000000..330082cfd
--- /dev/null
+++ b/jam-ui/src/components/client/JKSessionBackingTrack.js
@@ -0,0 +1,177 @@
+import React, { useState, useEffect } from 'react';
+import { useMixersContext } from '../../context/MixersContext';
+import { useJamClient } from '../../context/JamClientContext';
+import usePanHelpers from '../../hooks/usePanHelpers';
+import SessionTrackVU from './SessionTrackVU';
+import SessionTrackGain from './SessionTrackGain';
+import TrackDiagnostics from './TrackDiagnostics';
+import JKSessionPanModal from './JKSessionPanModal';
+import { UncontrolledTooltip } from 'reactstrap';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faTimes } from '@fortawesome/free-solid-svg-icons';
+import './JKSessionMyTrack.css';
+
+const JKSessionBackingTrack = ({
+ backingTrack,
+ mixers,
+ onClose
+}) => {
+ const mixerHelper = useMixersContext();
+ const jamClient = useJamClient();
+ const { convertPanToPercent } = usePanHelpers();
+ const [pan, setPan] = useState(0);
+ const [showMenu, setShowMenu] = useState(false);
+ const [showPanModal, setShowPanModal] = useState(false);
+
+ console.log('JKSessionBackingTrack backingTrack:', backingTrack);
+
+ useEffect(() => {
+ if (mixers?.mixer) {
+ setPan(mixers.mixer.pan || 0);
+ }
+ }, [mixers]);
+
+ const trackClasses = `session-track backing-track has-mixer`;
+
+ const panStyle = {
+ transform: `rotate(${pan}deg)`,
+ WebkitTransform: `rotate(${pan}deg)`
+ };
+
+ const handleClose = () => {
+ console.log('JKSessionBackingTrack: Close clicked');
+ if (onClose) {
+ onClose();
+ }
+ };
+
+ const getFileName = (backingTrack) => {
+ if (!backingTrack) return 'Unknown File';
+
+ // Extract filename from path or use provided name
+ if (backingTrack.shortFilename) {
+ return backingTrack.shortFilename;
+ }
+ if (backingTrack.filename) {
+ return backingTrack.filename.split('/').pop().split('\\').pop();
+ }
+ return 'Audio File';
+ };
+
+ return (
+
+
+
+ {/* Backing Track Header with Close Icon */}
+
+
+ {/* File Name - centered where user name would be */}
+
+ {getFileName(backingTrack)}
+
+
+ {/* Instrument Icon */}
+
+

+
+
+ {/* Controls */}
+
+
+
+
+
+
+
+
+
setShowMenu(!showMenu)}>
+ ...
+
+ {showMenu && (
+
+
{
+ setShowPanModal(true);
+ setShowMenu(false);
+ }}
+ >
+ Pan...
+
+
+ )}
+
+
+
+
+
+
+
+ {/* Pan Modal */}
+ {showPanModal && (
+
setShowPanModal(false)}
+ mixers={mixers}
+ />
+ )}
+
+ );
+};
+
+export default JKSessionBackingTrack;
\ No newline at end of file
diff --git a/jam-ui/src/components/client/JKSessionMyTrack.js b/jam-ui/src/components/client/JKSessionMyTrack.js
index 50a77e2e7..7503fb22d 100644
--- a/jam-ui/src/components/client/JKSessionMyTrack.js
+++ b/jam-ui/src/components/client/JKSessionMyTrack.js
@@ -45,7 +45,7 @@ const JKSessionMyTrack = ({
const [showProfilePanel, setShowProfilePanel] = useState(false);
const [profileUser, setProfileUser] = useState(null);
- console.log('JKSessionMyTrack instrumentIcon:', instrumentIcon);
+ //console.log('JKSessionMyTrack instrumentIcon:', instrumentIcon);
useEffect(() => {
if (mixers?.mixer) {
diff --git a/jam-ui/src/components/client/JKSessionScreen.js b/jam-ui/src/components/client/JKSessionScreen.js
index ae412fcc4..fee5c7e43 100644
--- a/jam-ui/src/components/client/JKSessionScreen.js
+++ b/jam-ui/src/components/client/JKSessionScreen.js
@@ -41,6 +41,7 @@ import JKSessionJamTrackStems from './JKSessionJamTrackStems.js';
import JKSessionOpenMenu from './JKSessionOpenMenu.js';
import WindowPortal from '../common/WindowPortal.js';
import JKSessionBackingTrackPlayer from './JKSessionBackingTrackPlayer.js';
+import JKSessionBackingTrack from './JKSessionBackingTrack.js';
import JKPopupMediaControls from '../popups/JKPopupMediaControls.js';
import { SESSION_PRIVACY_MAP } from '../../helpers/globals.js';
import { toast } from 'react-toastify';
@@ -84,7 +85,7 @@ const JKSessionScreen = () => {
const { globalObject, metronomeState, closeMetronome, resetMetronome } = useGlobalContext();
const { getCurrentRecordingState, reset: resetRecordingState, currentlyRecording } = useRecordingHelpers();
const { SessionPageEnter } = useSessionUtils();
- const { mediaSummary, openBackingTrack, openMetronome, loadJamTrack } = useMediaContext();
+ const { mediaSummary, openBackingTrack, openMetronome, loadJamTrack, closeMedia } = useMediaContext();
// Use the session model hook
const sessionModel = useSessionModel(app, server, null); // sessionScreen is null for now
@@ -140,6 +141,12 @@ const JKSessionScreen = () => {
setBackingTrackData(null);
}, []);
+ // Stable callback for backing track close in main screen
+ const handleBackingTrackMainClose = useCallback(() => {
+ console.log('JKSessionScreen: Backing Track main screen close requested');
+ closeMedia();
+ }, [closeMedia]);
+
//state for media controls popup
const [showMediaControlsPopup, setShowMediaControlsPopup] = useState(false);
const [mediaControlsOpened, setMediaControlsOpened] = useState(false);
@@ -997,6 +1004,20 @@ const JKSessionScreen = () => {
>
)}
+ {/* Backing Track Section */}
+ {mixerHelper.backingTracks && mixerHelper.backingTracks.length > 0 && (
+ <>
+
+
+
+
+ >
+ )}
+
{/* Connection Status Alerts */}
@@ -1269,4 +1290,3 @@ const JKSessionScreen = () => {
}
export default memo(JKSessionScreen)
-