integrated launch terminal into launcher with option to show it
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
package launcher
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"turtlesilicon/pkg/paths" // Corrected import path
|
||||
"turtlesilicon/pkg/utils" // Corrected import path
|
||||
@@ -15,6 +19,87 @@ import (
|
||||
var EnableMetalHud = true // Default to enabled
|
||||
var CustomEnvVars = "" // Custom environment variables
|
||||
|
||||
// Terminal state management
|
||||
var (
|
||||
currentGameProcess *exec.Cmd
|
||||
isGameRunning bool
|
||||
gameMutex sync.Mutex
|
||||
)
|
||||
|
||||
// runGameIntegrated runs the game with integrated terminal output
|
||||
func runGameIntegrated(parentWindow fyne.Window, shellCmd string) error {
|
||||
gameMutex.Lock()
|
||||
defer gameMutex.Unlock()
|
||||
|
||||
if isGameRunning {
|
||||
return fmt.Errorf("game is already running")
|
||||
}
|
||||
|
||||
isGameRunning = true
|
||||
|
||||
// Parse the shell command to extract components
|
||||
// The shellCmd format is: cd <path> && <envVars> <rosettaExec> <wineloader> <wowExe>
|
||||
log.Printf("Parsing shell command: %s", shellCmd)
|
||||
|
||||
// Create the command without context cancellation
|
||||
cmd := exec.Command("sh", "-c", shellCmd)
|
||||
|
||||
// Set up stdout and stderr pipes
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
isGameRunning = false
|
||||
return err
|
||||
}
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
isGameRunning = false
|
||||
return err
|
||||
}
|
||||
|
||||
currentGameProcess = cmd
|
||||
|
||||
// Start the process
|
||||
if err := cmd.Start(); err != nil {
|
||||
isGameRunning = false
|
||||
return err
|
||||
}
|
||||
|
||||
// Monitor output in goroutines
|
||||
go func() {
|
||||
scanner := bufio.NewScanner(stdout)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
log.Printf("GAME STDOUT: %s", line)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
scanner := bufio.NewScanner(stderr)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
log.Printf("GAME STDERR: %s", line)
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for the process to complete in a goroutine
|
||||
go func() {
|
||||
defer func() {
|
||||
gameMutex.Lock()
|
||||
isGameRunning = false
|
||||
currentGameProcess = nil
|
||||
gameMutex.Unlock()
|
||||
}()
|
||||
|
||||
if err := cmd.Wait(); err != nil {
|
||||
log.Printf("Game process ended with error: %v", err)
|
||||
} else {
|
||||
log.Println("Game process ended successfully")
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func LaunchGame(myWindow fyne.Window) {
|
||||
log.Println("Launch Game button clicked")
|
||||
|
||||
@@ -36,6 +121,15 @@ func LaunchGame(myWindow fyne.Window) {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if game is already running
|
||||
gameMutex.Lock()
|
||||
if isGameRunning {
|
||||
gameMutex.Unlock()
|
||||
dialog.ShowInformation("Game Already Running", "The game is already running.", myWindow)
|
||||
return
|
||||
}
|
||||
gameMutex.Unlock()
|
||||
|
||||
log.Println("Preparing to launch TurtleSilicon...")
|
||||
|
||||
rosettaInTurtlePath := filepath.Join(paths.TurtlewowPath, "rosettax87")
|
||||
@@ -82,6 +176,11 @@ func LaunchGame(myWindow fyne.Window) {
|
||||
utils.QuotePathForShell(wineloader2Path),
|
||||
utils.QuotePathForShell(wowExePath))
|
||||
|
||||
// Check user preference for terminal display
|
||||
prefs, _ := utils.LoadPrefs()
|
||||
|
||||
if prefs.ShowTerminalNormally {
|
||||
// Use the old method with external Terminal.app
|
||||
escapedShellCmd := utils.EscapeStringForAppleScript(shellCmd)
|
||||
cmd2Script := fmt.Sprintf("tell application \"Terminal\" to do script \"%s\"", escapedShellCmd)
|
||||
|
||||
@@ -91,4 +190,39 @@ func LaunchGame(myWindow fyne.Window) {
|
||||
}
|
||||
|
||||
log.Println("Launch command executed. Check the new terminal window.")
|
||||
} else {
|
||||
// Use integrated terminal
|
||||
log.Printf("Shell command for integrated terminal: %s", shellCmd)
|
||||
log.Println("Executing WoW launch command with integrated terminal...")
|
||||
if err := runGameIntegrated(myWindow, shellCmd); err != nil {
|
||||
dialog.ShowError(fmt.Errorf("failed to launch game: %v", err), myWindow)
|
||||
return
|
||||
}
|
||||
log.Println("Game launched with integrated terminal. Check the application logs for output.")
|
||||
}
|
||||
}
|
||||
|
||||
// IsGameRunning returns true if the game is currently running
|
||||
func IsGameRunning() bool {
|
||||
gameMutex.Lock()
|
||||
defer gameMutex.Unlock()
|
||||
return isGameRunning
|
||||
}
|
||||
|
||||
// StopGame forcefully stops the running game
|
||||
func StopGame() error {
|
||||
gameMutex.Lock()
|
||||
defer gameMutex.Unlock()
|
||||
|
||||
if !isGameRunning || currentGameProcess == nil {
|
||||
return fmt.Errorf("no game process is running")
|
||||
}
|
||||
|
||||
// Try to terminate gracefully first
|
||||
if err := currentGameProcess.Process.Signal(os.Interrupt); err != nil {
|
||||
// If that fails, force kill
|
||||
return currentGameProcess.Process.Kill()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
14
pkg/ui/ui.go
14
pkg/ui/ui.go
@@ -35,6 +35,7 @@ var (
|
||||
startServiceButton *widget.Button
|
||||
stopServiceButton *widget.Button
|
||||
metalHudCheckbox *widget.Check
|
||||
showTerminalCheckbox *widget.Check
|
||||
envVarsEntry *widget.Entry
|
||||
pulsingActive = false
|
||||
)
|
||||
@@ -267,6 +268,15 @@ func CreateUI(myWindow fyne.Window) fyne.CanvasObject {
|
||||
})
|
||||
metalHudCheckbox.SetChecked(launcher.EnableMetalHud)
|
||||
|
||||
showTerminalCheckbox = widget.NewCheck("Show Terminal", func(checked bool) {
|
||||
// Save to preferences
|
||||
prefs, _ := utils.LoadPrefs()
|
||||
prefs.ShowTerminalNormally = checked
|
||||
utils.SavePrefs(prefs)
|
||||
log.Printf("Show terminal normally: %v", checked)
|
||||
})
|
||||
showTerminalCheckbox.SetChecked(prefs.ShowTerminalNormally)
|
||||
|
||||
// Load environment variables from preferences
|
||||
if prefs.EnvironmentVariables != "" {
|
||||
launcher.CustomEnvVars = prefs.EnvironmentVariables
|
||||
@@ -356,7 +366,11 @@ func CreateUI(myWindow fyne.Window) fyne.CanvasObject {
|
||||
logoContainer,
|
||||
pathSelectionForm,
|
||||
patchOperationsLayout,
|
||||
container.NewHBox(
|
||||
metalHudCheckbox,
|
||||
showTerminalCheckbox,
|
||||
),
|
||||
widget.NewSeparator(),
|
||||
widget.NewLabel("Environment Variables:"),
|
||||
envVarsEntry,
|
||||
container.NewPadded(launchButton),
|
||||
|
@@ -12,6 +12,7 @@ type UserPrefs struct {
|
||||
CrossOverPath string `json:"crossover_path"`
|
||||
EnvironmentVariables string `json:"environment_variables"`
|
||||
SaveSudoPassword bool `json:"save_sudo_password"`
|
||||
ShowTerminalNormally bool `json:"show_terminal_normally"`
|
||||
}
|
||||
|
||||
func getPrefsPath() (string, error) {
|
||||
|
Reference in New Issue
Block a user