Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Albin #4

Merged
merged 3 commits into from
Apr 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions client/src/components/AudioOutput.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,38 @@
import React from "react";
// In the AudioOutput component
import React, { useEffect, useRef } from "react";

function AudioOutput() {
return <></>;
function AudioOutput({ currentAudioMessage }) {
const audioRef = useRef(null);

useEffect(() => {
if (currentAudioMessage) {
console.log(
"Creating blob with ArrayBuffer of size:",
currentAudioMessage.audio.byteLength
);
const blob = new Blob([currentAudioMessage.audio], { type: "audio/mp3" });
const url = URL.createObjectURL(blob);
console.log("Blob URL:", url); // Check the generated URL
audioRef.current.src = url;
audioRef.current
.play()
.catch((err) => console.error("Error playing audio:", err));

return () => {
console.log("Revoking URL:", url);
URL.revokeObjectURL(url);
};
}
}, [currentAudioMessage]);

return (
<audio
ref={audioRef}
controls
autoPlay
onLoadedData={() => console.log("Audio loaded")}
/>
);
}

export default AudioOutput;
15 changes: 12 additions & 3 deletions client/src/components/Contact.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import React from "react";
function Contact() {
return (
<div className="wrapper">
<div className="text-container" style={{ justifyContent: "center" }}>
<div
className="text-container"
style={{ justifyContent: "center" }}
>
<h4>
The project is an initiative by art & design
<br /> collective Nonhuman Nonsense developed in
Expand All @@ -18,11 +21,17 @@ function Contact() {
@nonhuman-nonsense
</a>
<br />
<a className="link" href="https://nonhuman-nonsense.com">
<a
className="link"
href="https://nonhuman-nonsense.com"
>
nonhuman-nonsense.com
</a>
<br />
<a className="link" href="mailto:hello@nonhuman-nonsense.com">
<a
className="link"
href="mailto:hello@nonhuman-nonsense.com"
>
hello@nonhuman-nonsense.com
</a>
</h4>
Expand Down
25 changes: 18 additions & 7 deletions client/src/components/Council.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ function Council({ options }) {
const [activeOverlay, setActiveOverlay] = useState("");
const { width: screenWidth } = useWindowSize();
const [conversation, setConversation] = useState([]); // State to store conversation updates
const [audioMessages, setAudioMessages] = useState([]); // To store multiple ArrayBuffers
const socketRef = useRef(null); // Using useRef to persist socket instance

const foodsContainerStyle = {
Expand All @@ -33,26 +34,33 @@ function Council({ options }) {
useEffect(() => {
socketRef.current = io();

// Send initial data to start the conversation
let promptsAndOptions = {
options: {
...globalOptions,
humanName: humanName,
humanName,
raiseHandPrompt: false,
neverMindPrompt: false,
},
name: "New room",
topic: topic,
topic,
characters: foods,
};

socketRef.current.emit("start_conversation", promptsAndOptions);

// Listen for conversation updates
// Listen for conversation text updates
socketRef.current.on("conversation_update", (message) => {
setConversation((prev) => [...prev, message]); // Update conversation state
setConversation((prev) => [...prev, message]);
});

// Listen for audio updates
socketRef.current.on("audio_update", (audioMessage) => {
setAudioMessages((prevAudioMessages) => [
...prevAudioMessages,
audioMessage,
]);
});

// Cleanup on component unmount
return () => {
socketRef.current.disconnect();
};
Expand Down Expand Up @@ -108,7 +116,10 @@ function Council({ options }) {
className="text-container"
style={{ justifyContent: "end" }}
>
<Output conversation={conversation} />
<Output
conversation={conversation}
audioMessages={audioMessages}
/>
</div>
)}
<div style={foodsContainerStyle}>
Expand Down
92 changes: 46 additions & 46 deletions client/src/components/Output.jsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,75 @@
import React, { useState, useEffect } from "react";
import TextOutput from "./TextOutput";
import AudioOutput from "./AudioOutput";
import ConversationControls from "./ConversationControls";

function Output({ conversation }) {
function Output({ conversation, audioMessages }) {
const [currentMessageIndex, setCurrentMessageIndex] = useState(0);
const [currentSnippetIndex, setCurrentSnippetIndex] = useState(0);
const [currentMessageTextSnippet, setCurrentMessageTextSnippet] =
useState("");
const [initialize, setInitialize] = useState(true); // Flag to control initialization
const [isPaused, setIsPaused] = useState(false);

// Function to calculate the display time based on text length
const calculateDisplayTime = (text) => Math.max(3, text.length * 0.05);
useEffect(() => {
console.log("Audio buffers length:", audioMessages.length);
console.log("Current audio buffer index:", currentMessageIndex);
}, [audioMessages, currentMessageIndex]);

function handlePauseResume() {
if (!isPaused) {
console.log("Pausing");
} else {
console.log("Resuming");
}
useEffect(() => {
if (conversation.length > 0 && !isPaused) {
const snippets =
conversation[currentMessageIndex].text.split(/(?<=\.\s)/);
if (snippets.length > currentSnippetIndex) {
setCurrentMessageTextSnippet(snippets[currentSnippetIndex]);
const timeout = setTimeout(() => {
if (currentSnippetIndex < snippets.length - 1) {
setCurrentSnippetIndex(currentSnippetIndex + 1);
} else if (currentMessageIndex < conversation.length - 1) {
setCurrentMessageIndex(currentMessageIndex + 1);
setCurrentSnippetIndex(0);
}
}, calculateDisplayTime(snippets[currentSnippetIndex]) * 1000);

setIsPaused(!isPaused);
}
return () => clearTimeout(timeout); // Cleanup timeout on unmount or dependency change
}
}
}, [currentMessageIndex, currentSnippetIndex, conversation, isPaused]); // Include isPaused in dependencies

function handleSkipForward() {
// TODO: See if last message before skipping forward
const calculateDisplayTime = (text) => Math.max(3, text.length * 0.065);

console.log("Skipping forward");
function handlePauseResume() {
setIsPaused(!isPaused); // Toggle pause state
}

useEffect(() => {
if (initialize && conversation.length > 0) {
setCurrentMessageIndex(0);
setCurrentSnippetIndex(0);
setInitialize(false); // Reset initialization flag after first setup
}
}, [conversation, initialize]);

useEffect(() => {
const processSnippets = () => {
if (conversation.length > currentMessageIndex) {
const snippets =
conversation[currentMessageIndex].text.split(/(?<=\.\s)/);
if (snippets.length > currentSnippetIndex) {
setCurrentMessageTextSnippet(snippets[currentSnippetIndex]);
const timeout = setTimeout(() => {
if (currentSnippetIndex < snippets.length - 1) {
setCurrentSnippetIndex(currentSnippetIndex + 1);
} else if (currentMessageIndex < conversation.length - 1) {
setCurrentMessageIndex(currentMessageIndex + 1);
setCurrentSnippetIndex(0);
}
}, calculateDisplayTime(snippets[currentSnippetIndex]) * 1000);
return () => clearTimeout(timeout);
}
function handleSkipForward() {
if (conversation.length > currentMessageIndex) {
const snippets =
conversation[currentMessageIndex].text.split(/(?<=\.\s)/);
if (currentSnippetIndex < snippets.length - 1) {
// Move to the next snippet within the same message
setCurrentSnippetIndex(currentSnippetIndex + 1);
} else if (currentMessageIndex < conversation.length - 1) {
// Move to the first snippet of the next message
setCurrentMessageIndex(currentMessageIndex + 1);
setCurrentSnippetIndex(0);
}
};

processSnippets();
}, [currentMessageIndex, currentSnippetIndex, conversation]);
}
}

return (
<div>
<div style={{ textAlign: "center", width: "75%" }}>
<h2>
Speaker:{" "}
{conversation.length > 0
? conversation[currentMessageIndex].speaker
: ""}
</h2>
<TextOutput currentMessageTextSnippet={currentMessageTextSnippet} />
<AudioOutput />
<AudioOutput
currentAudioMessage={audioMessages.find(
(a) => a.message_index == currentMessageIndex
)}
/>
<ConversationControls
isPaused={isPaused}
onPauseResume={handlePauseResume}
Expand Down