Skip to content

Commit 12f39d1

Browse files
authored
Merge pull request #122 from alexander-akhmetov/dev/remarkable-paper-pro
Add initial support for Remarkable Paper Pro
2 parents 087878d + f7afec6 commit 12f39d1

28 files changed

+712
-157
lines changed

Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export GOOS ?= linux
2+
export CGO_ENABLED ?= 0
3+
export GOARCH ?= amd64
4+
5+
.PHONY: build-remarkable-2
6+
build-remarkable-2: GOARCH=arm
7+
build-remarkable-2: build
8+
9+
.PHONY: build-remarkable-paper-pro
10+
build-remarkable-paper-pro: GOARCH=arm64
11+
build-remarkable-paper-pro: build
12+
13+
.PHONY: build
14+
build:
15+
@echo "Building for GOOS=${GOOS}, GOARCH=${GOARCH}, CGO_ENABLED=${CGO_ENABLED}"
16+
go build -v -trimpath -ldflags="-s -w" .

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ The goMarkableStream is a lightweight and user-friendly application designed spe
1111

1212
Its primary goal is to enable users to stream their reMarkable tablet screen to a web browser without the need for any hacks or modifications that could void the warranty.
1313

14+
## Device support
15+
16+
- Remarkable 2
17+
- Remarkable Paper Pro (see notes below)
18+
19+
### Remarkable Paper Pro
20+
21+
Remarkable Paper Pro is in initial support. The application is not yet fully tested on this device and some features may not work as expected.
22+
23+
When running on the Remarkable Paper Pro, `RLE_COMPRESSION` environment variable must be set to `false` since it's not supported.
24+
1425
## Version support
1526

1627
- reMarkable with firmware < 3.4 may use goMarkableStream version < 0.8.6
@@ -122,6 +133,9 @@ Configure the application via environment variables:
122133
- `RK_HTTPS`: (True/False, default: `true`) Enable or disable HTTPS.
123134
- `RK_COMPRESSION`: (True/False, default: `false`) Enable or disable compression.
124135
- `RK_DEV_MODE`: (True/False, default: `false`) Enable or disable developer mode.
136+
- `RLE_COMPRESSION`: (True/False, default: `true`) Enable or disable RLE compression.
137+
- `ZSTD_COMPRESSION`: (True/False, default: `false`) Enable or disable ZSTD compression.
138+
- `ZSTD_COMPRESSION_LEVEL`: (Integer, default: `3`) Set the ZSTD compression level.
125139
126140
### Endpoint Configuration
127141
Add query parameters to the URL (`?parameter=value&otherparameter=value`):

client/canvasHandling.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ function resizeVisibleCanvas() {
33
var container = document.getElementById("container");
44

55
if (portrait) {
6-
var aspectRatio = 1404 / 1872;
6+
var aspectRatio = screenHeight / screenWidth;
77
} else {
8-
var aspectRatio = 1872 / 1404;
8+
var aspectRatio = screenWidth / screenHeight;
99
}
1010

1111
var containerWidth = container.offsetWidth;

client/glCanvas.js

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -131,16 +131,25 @@ const programInfo = {
131131
const textureCoordBuffer = gl.createBuffer();
132132
gl.bindBuffer(gl.ARRAY_BUFFER, textureCoordBuffer);
133133

134-
const textureCoordinates = [
135-
// 1.0, 0.0, // Bottom right
136-
// 0.0, 0.0, // Bottom left
137-
// 1.0, 1.0, // Top right
138-
// 0.0, 1.0, // Top left
139-
1.0, 1.0,
140-
0.0, 1.0,
141-
1.0, 0.0,
142-
0.0, 0.0,
143-
];
134+
const textureCoordinates = getTextureCoordinates();
135+
136+
function getTextureCoordinates() {
137+
if (DeviceModel === "Remarkable2") {
138+
return [
139+
1.0, 1.0,
140+
0.0, 1.0,
141+
1.0, 0.0,
142+
0.0, 0.0,
143+
];
144+
} else {
145+
return [
146+
1.0, 0.0,
147+
0.0, 0.0,
148+
1.0, 1.0,
149+
0.0, 1.0,
150+
];
151+
};
152+
};
144153

145154
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates), gl.STATIC_DRAW);
146155

@@ -160,7 +169,7 @@ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
160169
// gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
161170

162171
// Upload the image into the texture.
163-
let imageData = new ImageData(width, height);
172+
let imageData = new ImageData(screenWidth, screenHeight);
164173
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageData);
165174

166175
// Draw the scene
@@ -208,8 +217,12 @@ drawScene(gl, programInfo, positionBuffer, textureCoordBuffer, texture);
208217

209218
// Update texture
210219
function updateTexture(newRawData, shouldRotate, scaleFactor) {
220+
if (useBGRA) {
221+
convertBGRAtoRGBA(newRawData);
222+
};
223+
211224
gl.bindTexture(gl.TEXTURE_2D, texture);
212-
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, newRawData);
225+
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, screenWidth, screenHeight, gl.RGBA, gl.UNSIGNED_BYTE, newRawData);
213226

214227
// Set rotation
215228
const uRotationMatrixLocation = gl.getUniformLocation(shaderProgram, 'uRotationMatrix');
@@ -223,6 +236,14 @@ function updateTexture(newRawData, shouldRotate, scaleFactor) {
223236
drawScene(gl, programInfo, positionBuffer, textureCoordBuffer, texture);
224237
}
225238

239+
function convertBGRAtoRGBA(data) {
240+
for (let i = 0; i < data.length; i += 4) {
241+
const b = data[i]; // Blue
242+
data[i] = data[i + 2]; // Swap Red and Blue
243+
data[i + 2] = b;
244+
}
245+
}
246+
226247
// Call `updateTexture` with new data whenever you need to update the image
227248

228249
// Let's create a function that resizes the canvas element.
@@ -243,9 +264,8 @@ function resizeGLCanvas(canvas) {
243264
}
244265

245266
function updateLaserPosition(x, y) {
246-
247-
laserX = x / 1872 * gl.canvas.width;
248-
laserY = gl.canvas.height - (y / 1404 * gl.canvas.height);
267+
laserX = x / screenWidth * gl.canvas.width;
268+
laserY = gl.canvas.height - (y / screenHeight * gl.canvas.height);
249269

250270
drawScene(gl, programInfo, positionBuffer, textureCoordBuffer, texture);
251271
}

client/index.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@
55
<link rel="icon" type="image/x-icon" href="favicon.ico">
66
<!-- Including the CSS stylesheet -->
77
<link rel="stylesheet" href="style.css">
8+
<script>
9+
const screenWidth = {{ .ScreenWidth }};
10+
const screenHeight = {{ .ScreenHeight }};
11+
const MaxXValue = {{ .MaxXValue }};
12+
const MaxYValue = {{ .MaxYValue }};
13+
const UseRLE = {{ .UseRLE }};
14+
const DeviceModel = {{ .DeviceModel }};
15+
</script>
816
</head>
917
<body>
1018
<div id="menuContainer">

client/main.js

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1-
const width = 1872;
2-
const height = 1404;
3-
4-
const rawCanvas = new OffscreenCanvas(width, height); // Define width and height as needed
1+
const rawCanvas = new OffscreenCanvas(screenWidth, screenHeight); // Define width and height as needed
52
let portrait = getQueryParam('portrait');
63
portrait = portrait !== null ? portrait === 'true' : false;
7-
let flip = getQueryParam('flip');
8-
flip = flip !== null ? flip === 'true' : false;
4+
5+
defaultFlip = true;
6+
// If this is the Paper Pro, we don't need to flip the image.
7+
if (DeviceModel === 'RemarkablePaperPro') {
8+
defaultFlip = false;
9+
}
10+
let flip = getBoolQueryParam('flip', defaultFlip);
11+
912
let withColor = getQueryParam('color', 'true');
1013
withColor = withColor !== null ? withColor === 'true' : true;
1114
let rate = parseInt(getQueryParamOrDefault('rate', '200'), 10);
1215

16+
// Remarkable Paper Pro uses BGRA format.
17+
let useBGRA = false;
18+
if (DeviceModel === 'RemarkablePaperPro') {
19+
useBGRA = true;
20+
};
1321

1422
//let portrait = false;
1523
// Get the 'present' parameter from the URL
@@ -29,12 +37,22 @@ function getQueryParamOrDefault(param, defaultValue) {
2937
const value = urlParams.get(param);
3038
return value !== null ? value : defaultValue;
3139
}
32-
//let imageData = ctx.createImageData(width, height); // width and height of your canvas
40+
41+
//let imageData = ctx.createImageData(screenWidth, screenHeight); // width and height of your canvas
3342
function getQueryParam(name) {
3443
const urlParams = new URLSearchParams(window.location.search);
3544
return urlParams.get(name);
3645
}
3746

47+
function getBoolQueryParam(param, defaultValue = false) {
48+
value = getQueryParam(param);
49+
50+
if (value === null) {
51+
return defaultValue;
52+
}
53+
54+
return value === 'true';
55+
}
3856

3957
window.onload = function() {
4058
// Function to get the value of a query parameter by name

client/worker_event_processing.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ let portrait;
55
let draw;
66
let latestX;
77
let latestY;
8-
const MAX_X_VALUE = 15725;
9-
const MAX_Y_VALUE = 20966;
8+
let maxXValue;
9+
let maxYValue;
1010

1111
onmessage = (event) => {
1212
const data = event.data;
@@ -17,6 +17,8 @@ onmessage = (event) => {
1717
width = event.data.width;
1818
eventURL = event.data.eventURL;
1919
portrait = event.data.portrait;
20+
maxXValue = event.data.maxXValue;
21+
maxYValue = event.data.maxYValue;
2022
initiateEventsListener();
2123
break;
2224
case 'portrait':
@@ -50,16 +52,16 @@ async function initiateEventsListener() {
5052
// Code 3: Update and draw laser pointer
5153
if (portrait) {
5254
if (message.Code === 1) { // Horizontal position
53-
latestX = scaleValue(message.Value, MAX_X_VALUE, width);
55+
latestX = scaleValue(message.Value, maxXValue, width);
5456
} else if (message.Code === 0) { // Vertical position
55-
latestY = height - scaleValue(message.Value, MAX_Y_VALUE, height);
57+
latestY = height - scaleValue(message.Value, maxYValue, height);
5658
}
5759
} else {
5860
// wrong
5961
if (message.Code === 1) { // Horizontal position
60-
latestY = scaleValue(message.Value, MAX_X_VALUE, height);
62+
latestY = scaleValue(message.Value, maxYValue, height);
6163
} else if (message.Code === 0) { // Vertical position
62-
latestX = scaleValue(message.Value, MAX_Y_VALUE, width);
64+
latestX = scaleValue(message.Value, maxXValue, width);
6365
}
6466
}
6567
if (draw) {

0 commit comments

Comments
 (0)