-
Notifications
You must be signed in to change notification settings - Fork 8
feat: adding screencapture settings method #153
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,8 @@ | ||
| package devices | ||
|
|
||
| import ( | ||
| "encoding/binary" | ||
| "encoding/json" | ||
| "context" | ||
| "errors" | ||
| "fmt" | ||
|
|
@@ -10,6 +12,7 @@ | |
| "os/signal" | ||
| "strconv" | ||
| "strings" | ||
| "sync" | ||
| "syscall" | ||
| "time" | ||
|
|
||
|
|
@@ -45,9 +48,11 @@ | |
| DeviceName string `json:"DeviceName"` | ||
| OSVersion string `json:"Version"` | ||
|
|
||
| tunnelManager *ios.TunnelManager | ||
| wdaClient *wda.WdaClient | ||
| mjpegClient *mjpeg.WdaMjpegClient | ||
| tunnelManager *ios.TunnelManager | ||
| wdaClient *wda.WdaClient | ||
| mjpegClient *mjpeg.WdaMjpegClient | ||
| screenCaptureConn net.Conn | ||
| screenCaptureConnLock sync.Mutex | ||
| } | ||
|
|
||
| func (d IOSDevice) ID() string { | ||
|
|
@@ -713,6 +718,11 @@ | |
| return fmt.Errorf("failed to connect to stream port: %w", err) | ||
| } | ||
|
|
||
| // store connection for configuration updates | ||
| d.screenCaptureConnLock.Lock() | ||
| d.screenCaptureConn = conn | ||
| d.screenCaptureConnLock.Unlock() | ||
|
|
||
| // setup signal handling for Ctrl+C | ||
| sigChan := make(chan os.Signal, 1) | ||
| signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) | ||
|
|
@@ -722,7 +732,12 @@ | |
|
|
||
| // stream data in a goroutine | ||
| go func() { | ||
| defer conn.Close() | ||
| defer func() { | ||
| conn.Close() | ||
| d.screenCaptureConnLock.Lock() | ||
| d.screenCaptureConn = nil | ||
| d.screenCaptureConnLock.Unlock() | ||
| }() | ||
|
Comment on lines
+735
to
+740
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, check if the file exists and look at the specified lines
git ls-files | grep -E "devices/ios\.go"Repository: mobile-next/mobilecli Length of output: 79 🏁 Script executed: # Read the file around the specified lines (735-740)
if [ -f "devices/ios.go" ]; then
wc -l devices/ios.go
sed -n '730,745p' devices/ios.go
fiRepository: mobile-next/mobilecli Length of output: 469 🏁 Script executed: # Check if linter configuration exists
git ls-files | grep -E "(\.golangci|\.eslintrc|linter|lint)" | head -20Repository: mobile-next/mobilecli Length of output: 78 🏁 Script executed: # Search for utils.Verbose function
find . -type f -name "*.go" | head -20 | xargs grep -l "func.*Verbose\|utils.Verbose" 2>/dev/null | head -5Repository: mobile-next/mobilecli Length of output: 84 🏁 Script executed: # Check for any errcheck configuration
grep -r "errcheck" . --include="*.yml" --include="*.yaml" --include="*.toml" --include="*.cfg" 2>/dev/null | head -10Repository: mobile-next/mobilecli Length of output: 158 🏁 Script executed: # Get exact lines 735-740
sed -n '735,740p' devices/ios.goRepository: mobile-next/mobilecli Length of output: 208 🏁 Script executed: # Check the golangci.yml errcheck configuration
cat .golangci.yml | grep -A 5 "errcheck:"Repository: mobile-next/mobilecli Length of output: 156 🏁 Script executed: # Find utils package and Verbose function
find . -type f -name "*.go" -path "*/utils/*" | head -10Repository: mobile-next/mobilecli Length of output: 270 🏁 Script executed: # Search for utils.Verbose function definition
rg "func.*Verbose" --type go -A 2Repository: mobile-next/mobilecli Length of output: 423 🏁 Script executed: # Check what type conn is by looking at context around the defer
sed -n '715,740p' devices/ios.goRepository: mobile-next/mobilecli Length of output: 817 🏁 Script executed: # Search for Close() error handling patterns in Go files
rg "Close\(\)" --type go -A 1 -B 1 | head -50Repository: mobile-next/mobilecli Length of output: 1492 🏁 Script executed: # Look for conn.Close() specifically
rg "conn\.Close\(\)" --type go -A 1 -B 1Repository: mobile-next/mobilecli Length of output: 303 🏁 Script executed: # Check how errors are handled in defer blocks
rg "defer.*Close" --type go -A 2 | head -60Repository: mobile-next/mobilecli Length of output: 2134 🏁 Script executed: # Check project conventions for handling errors in defer
rg "_.*:=" --type go | grep -i close | head -20Repository: mobile-next/mobilecli Length of output: 47 Fix conn.Close() error handling to match project conventions. Line 736 ignores the error from 🔧 Suggested fix defer func() {
- conn.Close()
+ _ = conn.Close()
d.screenCaptureConnLock.Lock()
d.screenCaptureConn = nil
d.screenCaptureConnLock.Unlock()
}()Additionally, line 762 has an identical unhandled 🧰 Tools🪛 GitHub Check: lint[failure] 736-736: 🤖 Prompt for AI Agents |
||
| buffer := make([]byte, 65536) | ||
| for { | ||
| n, err := conn.Read(buffer) | ||
|
|
@@ -748,7 +763,7 @@ | |
| // wait for either signal or stream completion | ||
| select { | ||
| case <-sigChan: | ||
| conn.Close() | ||
| utils.Verbose("stream closed by user") | ||
| return nil | ||
| case err := <-done: | ||
|
|
@@ -775,6 +790,68 @@ | |
| return d.mjpegClient.StartScreenCapture(config.Format, config.OnData) | ||
| } | ||
|
|
||
| // SendScreenCaptureConfiguration sends encoder configuration updates to the device over the TCP stream. | ||
| // | ||
| // This method sends a length-prefixed JSON-RPC message to update the H.264 encoder | ||
| // bitrate and optionally frame rate dynamically without restarting the stream. | ||
| // | ||
| // Parameters: | ||
| // - bitrate: Target bitrate in bits per second (100000 - 8000000) | ||
| // - frameRate: Optional target frame rate (nil to keep current, 1-60 if provided) | ||
| // | ||
| // The message format is: | ||
| // [4-byte big-endian length][JSON-RPC payload] | ||
| // | ||
| // Returns an error if: | ||
| // - Screen capture is not active | ||
| // - JSON marshaling fails | ||
| // - TCP write fails | ||
| func (d *IOSDevice) SendScreenCaptureConfiguration(bitrate int, frameRate *int) error { | ||
| // Check if screen capture is active (TCP connection exists) | ||
| d.screenCaptureConnLock.Lock() | ||
| conn := d.screenCaptureConn | ||
| d.screenCaptureConnLock.Unlock() | ||
|
|
||
| if conn == nil { | ||
| return fmt.Errorf("screen capture not active, start screencapture first") | ||
| } | ||
|
|
||
| // Build JSON-RPC request | ||
| request := map[string]interface{}{ | ||
| "jsonrpc": "2.0", | ||
| "method": "screencapture.setConfiguration", | ||
| "params": map[string]interface{}{ | ||
| "bitrate": bitrate, | ||
| "frameRate": frameRate, | ||
| }, | ||
| "id": 1, | ||
| } | ||
|
|
||
| jsonData, err := json.Marshal(request) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to marshal request: %w", err) | ||
| } | ||
|
|
||
| // Prepend 4-byte length (big-endian) | ||
| length := uint32(len(jsonData)) | ||
| lengthBytes := make([]byte, 4) | ||
| binary.BigEndian.PutUint32(lengthBytes, length) | ||
|
|
||
| // Send: [4-byte length][JSON payload] | ||
| message := append(lengthBytes, jsonData...) | ||
|
|
||
| d.screenCaptureConnLock.Lock() | ||
| _, err = conn.Write(message) | ||
| d.screenCaptureConnLock.Unlock() | ||
|
|
||
| if err != nil { | ||
| return fmt.Errorf("failed to send configuration: %w", err) | ||
| } | ||
|
|
||
| utils.Verbose("Sent screen capture configuration: bitrate=%d bps, frameRate=%v", bitrate, frameRate) | ||
| return nil | ||
| } | ||
|
|
||
| func (d IOSDevice) DumpSource() ([]ScreenElement, error) { | ||
| return d.wdaClient.GetSourceElements() | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.