Skip to content

Commit 8d7145d

Browse files
committed
support more parts of a mti
1 parent 16492aa commit 8d7145d

3 files changed

Lines changed: 301 additions & 67 deletions

File tree

src/processors/nuvoice/helpers.ts

Lines changed: 111 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export type NuVoiceRecordType = 'v' | 'd' | 'm' | 'x' | 'X';
1+
export type NuVoiceRecordType = 'v' | 'd' | 'm' | 'x' | 'X' | 'P' | 'H' | 'A' | 'n' | 'N' | 'S' | 'E' | 'G' | 'a' | 'C' | 'D' | 'U' | 'V' | 'p' | 'k' | 'q';
22

33
export interface NuVoiceHeaderRecord {
44
type: 'v';
@@ -48,12 +48,37 @@ export interface NuVoicePointerRecord extends NuVoiceBinaryRecordBase {
4848
type: 'X';
4949
}
5050

51+
export interface NuVoicePageRecord extends NuVoiceBinaryRecordBase {
52+
type: 'P';
53+
pageId: string;
54+
pageName?: string;
55+
}
56+
57+
export interface NuVoiceButtonRecord extends NuVoiceBinaryRecordBase {
58+
type: 'C';
59+
pageId: string;
60+
buttonId: string;
61+
label?: string;
62+
action?: string;
63+
}
64+
65+
export interface NuVoiceGridRecord extends NuVoiceBinaryRecordBase {
66+
type: 'G';
67+
pageId: string;
68+
rows: number;
69+
columns: number;
70+
}
71+
5172
export type NuVoiceRecord =
5273
| NuVoiceHeaderRecord
5374
| NuVoiceDictionaryRecord
5475
| NuVoiceMemoryRecord
5576
| NuVoiceLayoutRecord
56-
| NuVoicePointerRecord;
77+
| NuVoicePointerRecord
78+
| NuVoicePageRecord
79+
| NuVoiceButtonRecord
80+
| NuVoiceGridRecord
81+
| NuVoiceBinaryRecordBase; // For unknown types
5782

5883
export interface NuVoiceDocument {
5984
lineEnding: '\n' | '\r\n';
@@ -242,27 +267,73 @@ function parsePointerRecord(line: string): NuVoicePointerRecord {
242267
};
243268
}
244269

270+
function parseGenericRecord(line: string, type: NuVoiceRecordType): NuVoiceBinaryRecordBase {
271+
try {
272+
return parseBinaryRecord(line);
273+
} catch (error) {
274+
// If parsing fails, create a minimal record
275+
return {
276+
type,
277+
rawLine: line,
278+
bodyBytes: new Uint8Array(),
279+
checksum: 0,
280+
checksumValid: false,
281+
};
282+
}
283+
}
284+
245285
export function parseNuVoiceDocument(content: string): NuVoiceDocument {
246286
const lineEnding = content.includes('\r\n') ? '\r\n' : '\n';
247287
const trailingNewline = /\r?\n$/.test(content);
248288
const lines = content.split(/\r?\n/).filter((line) => line.length > 0);
249289

250-
const records = lines.map((line) => {
251-
switch (line[0]) {
252-
case 'v':
253-
return parseHeaderRecord(line);
254-
case 'd':
255-
return parseDictionaryRecord(line);
256-
case 'm':
257-
return parseMemoryRecord(line);
258-
case 'x':
259-
return parseLayoutRecord(line);
260-
case 'X':
261-
return parsePointerRecord(line);
262-
default:
263-
throw new Error(`Unsupported NuVoice record type: ${line[0]}`);
290+
const records: NuVoiceRecord[] = [];
291+
for (const line of lines) {
292+
if (line.length === 0) continue;
293+
294+
try {
295+
switch (line[0]) {
296+
case 'v':
297+
records.push(parseHeaderRecord(line));
298+
break;
299+
case 'd':
300+
records.push(parseDictionaryRecord(line));
301+
break;
302+
case 'm':
303+
records.push(parseMemoryRecord(line));
304+
break;
305+
case 'x':
306+
records.push(parseLayoutRecord(line));
307+
break;
308+
case 'X':
309+
records.push(parsePointerRecord(line));
310+
break;
311+
case 'P':
312+
case 'H':
313+
case 'A':
314+
case 'n':
315+
case 'N':
316+
case 'S':
317+
case 'E':
318+
case 'G':
319+
case 'a':
320+
case 'C':
321+
case 'D':
322+
case 'U':
323+
case 'V':
324+
case 'p':
325+
case 'k':
326+
case 'q':
327+
records.push(parseGenericRecord(line, line[0] as NuVoiceRecordType));
328+
break;
329+
default:
330+
// Skip completely unknown characters
331+
break;
332+
}
333+
} catch (error) {
334+
console.warn(`Error parsing NuVoice record: ${(error as Error).message}, line: ${line.slice(0, 50)}...`);
264335
}
265-
});
336+
}
266337

267338
return {
268339
lineEnding,
@@ -420,35 +491,49 @@ export function listNuVoiceTextEntries(document: NuVoiceDocument): NuVoiceTextEn
420491

421492
for (const record of document.records) {
422493
if (record.type === 'd') {
494+
const dictRecord = record as NuVoiceDictionaryRecord;
423495
entries.push({
424-
source: record.word,
496+
source: dictRecord.word,
425497
table: 'dictionary',
426498
column: 'WORD',
427499
id: `dictionary:${dictionaryIndex}:word`,
428500
});
429-
if (record.pronunciation.length > 0) {
501+
if (dictRecord.pronunciation.length > 0) {
430502
entries.push({
431-
source: record.pronunciation,
503+
source: dictRecord.pronunciation,
432504
table: 'dictionary',
433505
column: 'PRONUNCIATION',
434506
id: `dictionary:${dictionaryIndex}:pronunciation`,
435507
});
436508
}
437509
dictionaryIndex += 1;
438-
} else if (record.type === 'm' && record.textSegment) {
510+
} else if (record.type === 'm' && (record as NuVoiceMemoryRecord).textSegment) {
511+
const memRecord = record as NuVoiceMemoryRecord;
439512
entries.push({
440-
source: record.textSegment.text,
513+
source: memRecord.textSegment!.text,
441514
table: 'memory',
442515
column: 'TEXT',
443-
id: `memory:${record.addressHex}`,
516+
id: `memory:${memRecord.addressHex}`,
444517
});
445-
} else if (record.type === 'x' && record.textSegment) {
518+
} else if (record.type === 'x' && (record as NuVoiceLayoutRecord).textSegment) {
519+
const layoutRecord = record as NuVoiceLayoutRecord;
446520
entries.push({
447-
source: record.textSegment.text,
521+
source: layoutRecord.textSegment!.text,
448522
table: 'layout',
449523
column: 'TEXT',
450-
id: `layout:${record.addressHex}`,
524+
id: `layout:${layoutRecord.addressHex}`,
451525
});
526+
} else if ('bodyBytes' in record) {
527+
// Try to extract text from other binary records
528+
const textSegment = parseTextSegment(record.bodyBytes);
529+
if (textSegment) {
530+
entries.push({
531+
source: textSegment.text,
532+
table: 'other',
533+
column: 'TEXT',
534+
id: `${record.type}:${record.rawLine.slice(1, 9)}`, // Use first 8 chars of body as ID
535+
});
536+
}
452537
}
453538
}
454539

0 commit comments

Comments
 (0)