diff --git a/adb.go b/adb.go index dd1ab2e..b97c616 100644 --- a/adb.go +++ b/adb.go @@ -42,6 +42,7 @@ type ConnOptions struct { // // This will return a Device struct, which can be used to call other methods. // If the connection fails or cannot complete on time, Connect will return an error. +// TODO func Connect(ctx context.Context, opts ConnOptions) (Device, error) { if opts.Port == 0 { opts.Port = 5555 diff --git a/capture.go b/capture.go index 9a9ca23..7807c2f 100644 --- a/capture.go +++ b/capture.go @@ -17,8 +17,34 @@ import ( // Instead of using Shell, please consider submitting a PR with the functionality // you require. +type SeqType int + +const ( + SeqSwipe SeqType = iota + SeqTap + SeqSleep +) + +type TapSequenceImporter struct { + Events []SequenceImporter + Resolution Resolution +} + +type SequenceImporter struct { + Duration time.Duration + Type SeqType + X int + Y int + X1 int + Y1 int + X2 int + Y2 int + Start time.Time + End time.Time +} type SequenceSleep struct { Duration time.Duration + Type SeqType } func (s SequenceSleep) Play(d Device, ctx context.Context) error { @@ -44,6 +70,7 @@ type SequenceTap struct { Y int Start time.Time End time.Time + Type SeqType } func (s SequenceTap) Play(d Device, ctx context.Context) error { @@ -69,6 +96,7 @@ type SequenceSwipe struct { Y2 int Start time.Time End time.Time + Type SeqType } func (s SequenceSwipe) Play(d Device, ctx context.Context) error { @@ -248,6 +276,7 @@ func insertSleeps(inputs []Input) []Input { curr := input.EndTime() var sleep SequenceSleep sleep.Duration = curr.Sub(prev) + sleep.Type = SeqSleep sleepingInputs = append(sleepingInputs, sleep) } sleepingInputs = append(sleepingInputs, input) @@ -320,6 +349,7 @@ func (e eventSet) ToInput() (Input, error) { swipe.Y2 = int(endy) swipe.Start = e[0].TimeStamp swipe.End = e[len(e)-1].TimeStamp + swipe.Type = SeqSwipe return swipe, err } diff --git a/examples/tapRecorder/go.mod b/examples/tapRecorder/go.mod index a20c10d..e91a407 100644 --- a/examples/tapRecorder/go.mod +++ b/examples/tapRecorder/go.mod @@ -1,3 +1,9 @@ module github.com/taigrr/adb/examples/tapRecorder go 1.19 + +replace github.com/taigrr/adb => ../.. + +require github.com/taigrr/adb v0.0.0-20220803063720-bd9524431495 + +require github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect diff --git a/examples/tapRecorder/go.sum b/examples/tapRecorder/go.sum new file mode 100644 index 0000000..0be9157 --- /dev/null +++ b/examples/tapRecorder/go.sum @@ -0,0 +1,2 @@ +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= diff --git a/examples/tapRecorder/main.go b/examples/tapRecorder/main.go index 6855f4d..70bec96 100644 --- a/examples/tapRecorder/main.go +++ b/examples/tapRecorder/main.go @@ -1,23 +1,34 @@ package main import ( + "bytes" "context" + "encoding/json" + "flag" "fmt" - "time" + "os" + "os/signal" + "syscall" "github.com/taigrr/adb" ) -var command string - -func init() { - // TODO allow for any input to be used as the command - command = "ls" -} +var ( + command string + file string +) func main() { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) - defer cancel() + flag.StringVar(&command, "command", "rec", "rec or play") + flag.StringVar(&file, "file", "taps.json", "Name of the file to save taps to or to play from") + flag.Parse() + sigChan := make(chan os.Signal) + ctx, cancel := context.WithCancel(context.Background()) + go func() { + <-sigChan + cancel() + }() + signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) devs, err := adb.Devices(ctx) if err != nil { fmt.Printf("Error enumerating devices: %v\n", err) @@ -33,13 +44,79 @@ func main() { // // handle error here // fmt.Printf("Error: %v\n", err) //} - fmt.Printf("Begin tapping on device %s now...\n", dev.SerialNo) - t, err := dev.CaptureSequence(ctx) - if err != nil { - fmt.Printf("Error capturing sequence: %v\n", err) - return + switch command { + case "rec": + fmt.Println("Recording taps now. Hit ctrl+c to stop.") + t, err := dev.CaptureSequence(ctx) + if err != nil { + fmt.Printf("Error capturing sequence: %v\n", err) + return + } + b, _ := json.Marshal(t) + f, err := os.Create(file) + if err != nil { + fmt.Printf("Error creating tap file %s: %v", file, err) + return + } + defer f.Close() + f.Write(b) + case "play": + fmt.Println("Replaying taps now. Hit ctrl+c to stop.") + f, err := os.Open(file) + if err != nil { + fmt.Printf("Error opening tap file %s: %v", file, err) + return + } + defer f.Close() + var j map[string]interface{} + var t adb.TapSequence + var b bytes.Buffer + b.ReadFrom(f) + err = json.Unmarshal(b.Bytes(), &j) + if err != nil { + fmt.Printf("Error parsing tap file %s: %v", file, err) + return + } + if events, ok := j["Events"]; ok { + if sliceEvent, ok := events.([]interface{}); ok { + for _, e := range sliceEvent { + if mapEvent, ok := e.(map[string]interface{}); ok { + if eventType, ok := mapEvent["Type"]; ok { + if et, ok := eventType.(float64); ok { + switch int(et) { + case int(adb.SeqSleep): + t.Events = append(t.Events, adb.SequenceSleep{}) + case int(adb.SeqSwipe): + t.Events = append(t.Events, adb.SequenceSwipe{}) + case int(adb.SeqTap): + t.Events = append(t.Events, adb.SequenceTap{}) + } + } else { + fmt.Printf("Could not parse %v (%T) into JSON! 1\n", eventType, eventType) + } + } else { + fmt.Println("Could not parse JSON! 2") + } + } else { + fmt.Println("Could not parse JSON! 3") + } + } + } else { + fmt.Println("Could not parse JSON! 4") + } + } else { + fmt.Println("Could not parse JSON! 5") + } + dev.ReplayTapSequence(ctx, t) + err = json.Unmarshal(b.Bytes(), &t) + if err != nil { + fmt.Printf("struct: %v\n",t) + fmt.Printf("bytes: %v\n",b.String()) + fmt.Printf("Error parsing tap file %s: %v", file, err) + return + } + + default: } - fmt.Println("Sequence captured, replaying now...") - dev.ReplayTapSequence(context.TODO(), t) } }