diff --git a/.gitignore b/.gitignore index 129d522..0c5b04d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ build/bin node_modules frontend/dist +.data/* +!.data/*.ps1 \ No newline at end of file diff --git a/README.md b/README.md index 7c22430..7fb0825 100644 --- a/README.md +++ b/README.md @@ -24,3 +24,13 @@ A 'simple' application for reading and visualizing the bitrate of media files. - [ ] Confirmation Dialogs - [ ] Localization - [ ] Logging & Log Viewer +- [ ] Stream Merging or Splitting +- [ ] GIF, Audio, Video support + +## Usage Flow + +1. Drop file +2. Select streams manually or using preset buttons + +- Drag and drop with editable stream names +- Presets reorganize streams smartly (All Together, Separate Video/Audio, All Separate, Separate Main Streams, Main Streams Only) diff --git a/app.go b/app.go index af53038..33c9c4e 100644 --- a/app.go +++ b/app.go @@ -3,24 +3,57 @@ package main import ( "context" "fmt" + + "github.com/wailsapp/wails/v2/pkg/runtime" + "gopkg.in/vansante/go-ffprobe.v2" ) // App struct type App struct { - ctx context.Context + ctx context.Context + files []File } // NewApp creates a new App application struct func NewApp() *App { - return &App{} + return &App{ + files: []File{}, + } } // startup is called when the app starts. The context is saved // so we can call the runtime methods func (a *App) startup(ctx context.Context) { + runtime.OnFileDrop(ctx, func(x, y int, paths []string) { + a.OnFileDrop(x, y, paths) + }) + a.ctx = ctx } +func (a *App) shutdown(ctx context.Context) { + runtime.OnFileDropOff(ctx) +} + +func (a *App) GetStream(path string) { +} + +func (a *App) OnFileDrop(x, y int, paths []string) { + runtime.LogPrint(a.ctx, fmt.Sprintf("OnFileDrop: %v", paths)) + + for _, path := range paths { + probe, err := ffprobe.ProbeURL(a.ctx, path) + if err != nil { + runtime.LogPrint(a.ctx, fmt.Sprintf("Error: %v", err)) + continue + } + + for _, stream := range probe.Streams { + runtime.LogPrint(a.ctx, fmt.Sprintf("Stream: %v", stream)) + } + } +} + // Greet returns a greeting for the given name func (a *App) Greet(name string) string { return fmt.Sprintf("Hello %s, It's show time!", name) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index a3599f9..6bc0b8d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,368 +1,139 @@ -import { useState } from "react"; -import "./App.css"; -import { Greet } from "../wailsjs/go/main/App.js"; import { ResponsiveLine } from "@nivo/line"; +import { useEffect, useMemo } from "react"; +import { OnFileDrop, OnFileDropOff } from "../wailsjs/runtime/runtime.js"; +import "./App.css"; import { formatBytes } from "./lib/format.js"; +type Frame = { + id: string; + data: { x: string | number; y: number }[]; +}; + function App() { - const [resultText, setResultText] = useState( - "Please enter your name below 👇" - ); - const [name, setName] = useState(""); - const updateName = (e: any) => setName(e.target.value); - const updateResultText = (result: string) => setResultText(result); + useEffect(() => { + OnFileDrop((_x, _y, paths) => {}, true); + return () => OnFileDropOff(); + }, []); - const data = [ - { - id: "japan", - data: [ - { - x: "plane", - y: 99, - }, - { - x: "helicopter", - y: 80, - }, - { - x: "boat", - y: 60, - }, - { - x: "train", - y: 179, - }, - { - x: "subway", - y: 102, - }, - { - x: "bus", - y: 68, - }, - { - x: "car", - y: 200, - }, - { - x: "moto", - y: 38, - }, - { - x: "bicycle", - y: 32, - }, - { - x: "horse", - y: 84, - }, - { - x: "skateboard", - y: 93, - }, - { - x: "others", - y: 206, - }, - ], - }, - { - id: "france", - data: [ - { - x: "plane", - y: 227, - }, - { - x: "helicopter", - y: 278, - }, - { - x: "boat", - y: 241, - }, - { - x: "train", - y: 104, - }, - { - x: "subway", - y: 140, - }, - { - x: "bus", - y: 16, - }, - { - x: "car", - y: 21, - }, - { - x: "moto", - y: 135, - }, - { - x: "bicycle", - y: 158, - }, - { - x: "horse", - y: 41, - }, - { - x: "skateboard", - y: 20, - }, - { - x: "others", - y: 172, - }, - ], - }, - { - id: "us", - data: [ - { - x: "plane", - y: 54, - }, - { - x: "helicopter", - y: 59, - }, - { - x: "boat", - y: 165, - }, - { - x: "train", - y: 213, - }, - { - x: "subway", - y: 79, - }, - { - x: "bus", - y: 248, - }, - { - x: "car", - y: 184, - }, - { - x: "moto", - y: 251, - }, - { - x: "bicycle", - y: 122, - }, - { - x: "horse", - y: 12, - }, - { - x: "skateboard", - y: 269, - }, - { - x: "others", - y: 101, - }, - ], - }, - { - id: "germany", - data: [ - { - x: "plane", - y: 177, - }, - { - x: "helicopter", - y: 249, - }, - { - x: "boat", - y: 37, - }, - { - x: "train", - y: 173, - }, - { - x: "subway", - y: 145, - }, - { - x: "bus", - y: 283, - }, - { - x: "car", - y: 50, - }, - { - x: "moto", - y: 231, - }, - { - x: "bicycle", - y: 100, - }, - { - x: "horse", - y: 226, - }, - { - x: "skateboard", - y: 5, - }, - { - x: "others", - y: 139, - }, - ], - }, - { - id: "norway", - data: [ - { - x: "plane", - y: 234, - }, - { - x: "helicopter", - y: 38, - }, - { - x: "boat", - y: 254, - }, - { - x: "train", - y: 228, - }, - { - x: "subway", - y: 106, - }, - { - x: "bus", - y: 213, - }, - { - x: "car", - y: 289, - }, - { - x: "moto", - y: 116, - }, - { - x: "bicycle", - y: 272, - }, - { - x: "horse", - y: 50, - }, - { - x: "skateboard", - y: 263, - }, - { - x: "others", - y: 196, - }, - ], - }, - ]; + const data: Frame[] = []; + // const data: Frame[] = useMemo(() => + // // Array.from({ length: 4 }, (_, i) => { + // // const d = Math.random(); + // // const g = Math.random(); + // // return { + // // id: `file-${i}`, + // // data: Array.from({ length: 500 }, (_, j) => { + // // if (Math.random() < 0.5) return null; + // // return { + // // x: j, + // // y: Math.random() * 256 * d + (1 - g) * 1024, + // // }; + // // }).filter((i) => i !== null), + // // }; + // // }), + // [] + // ); - function greet() { - Greet(name).then(updateResultText); - } + console.log(data); - return ( -
- formatBytes(v * 1024 * 53), + }} + pointSize={10} + colors={[ + "#3e8faf", + "#c4a7e7", + "#f5c276", + "#EA9B96", + "#EB7092", + "#9CCFD8", + ]} + // pointColor={{ modifiers: [["brighter", 1100]] }} + pointBorderWidth={0} + pointBorderColor={{ from: "seriesColor" }} + pointLabelYOffset={-12} + enableSlices={"x"} + enableTouchCrosshair={true} + useMesh={true} + legends={[ + { + anchor: "bottom-right", + direction: "column", + translateX: 100, + itemWidth: 80, + itemHeight: 22, + symbolShape: "circle", + }, + ]} + /> + ); - domain: { - line: { - stroke: "rgb(252, 191, 212)", - strokeWidth: 0.5, - strokeOpacity: 0.5, - }, - }, - }, - text: { - fill: "#6e6a86", - }, - }} - axisBottom={{ legend: "transportation", legendOffset: 36 }} - axisLeft={{ - legend: "count", - legendOffset: -40, - format: (v) => formatBytes(v * 1024 * 53), - }} - pointSize={10} - colors={[ - "#3e8faf", - "#c4a7e7", - "#f5c276", - "#EA9B96", - "#EB7092", - "#9CCFD8", - ]} - // pointColor={{ modifiers: [["brighter", 1100]] }} - pointBorderWidth={0} - pointBorderColor={{ from: "seriesColor" }} - pointLabelYOffset={-12} - enableSlices={"x"} - enableTouchCrosshair={true} - useMesh={true} - legends={[ - { - anchor: "bottom-right", - direction: "column", - translateX: 100, - itemWidth: 80, - itemHeight: 22, - symbolShape: "circle", - }, - ]} - /> + return ( +
+
+
+
+ Drag and Drop to Add +
+
+
+ {graph}
); } diff --git a/frontend/src/style.css b/frontend/src/style.css index 50fdebb..b302805 100644 --- a/frontend/src/style.css +++ b/frontend/src/style.css @@ -27,3 +27,16 @@ body { height: 100vh; text-align: center; } + +#drop-target { + pointer-events: none; + opacity: 0; + background-color: rgb(0, 0, 0, 0.5) !important; +} + +.wails-drop-target-active { + #drop-target { + pointer-events: auto; + opacity: 1; + } +} diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 02a3bb9..6bba93b 100644 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -1,4 +1,8 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT +export function GetStream(arg1:string):Promise; + export function Greet(arg1:string):Promise; + +export function OnFileDrop(arg1:number,arg2:number,arg3:Array):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index c71ae77..0296205 100644 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -2,6 +2,14 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT +export function GetStream(arg1) { + return window['go']['main']['App']['GetStream'](arg1); +} + export function Greet(arg1) { return window['go']['main']['App']['Greet'](arg1); } + +export function OnFileDrop(arg1, arg2, arg3) { + return window['go']['main']['App']['OnFileDrop'](arg1, arg2, arg3); +} diff --git a/go.mod b/go.mod index eadd9c9..f5c5ebd 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,10 @@ module byteme go 1.23 -require github.com/wailsapp/wails/v2 v2.10.1 +require ( + github.com/wailsapp/wails/v2 v2.10.1 + gopkg.in/vansante/go-ffprobe.v2 v2.2.1 +) require ( github.com/bep/debounce v1.2.1 // indirect diff --git a/go.sum b/go.sum index 0ad6722..0838917 100644 --- a/go.sum +++ b/go.sum @@ -75,5 +75,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/vansante/go-ffprobe.v2 v2.2.1 h1:sFV08OT1eZ1yroLCZVClIVd9YySgCh9eGjBWO0oRayI= +gopkg.in/vansante/go-ffprobe.v2 v2.2.1/go.mod h1:qF0AlAjk7Nqzqf3y333Ly+KxN3cKF2JqA3JT5ZheUGE= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index f698735..6c8098e 100644 --- a/main.go +++ b/main.go @@ -20,11 +20,16 @@ func main() { Title: "byteme", Width: 1024, Height: 768, + AssetServer: &assetserver.Options{ Assets: assets, }, + DragAndDrop: &options.DragAndDrop{ + EnableFileDrop: true, + }, BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, OnStartup: app.startup, + OnShutdown: app.shutdown, Bind: []interface{}{ app, }, diff --git a/probe.go b/probe.go new file mode 100644 index 0000000..77aa650 --- /dev/null +++ b/probe.go @@ -0,0 +1,18 @@ +package main + +type Frame struct { + Key string + Bytes uint32 +} + +type File struct { + Path string + Data []Frame +} + +func NewFile(path string) File { + return File{ + Path: path, + Data: []Frame{}, + } +}