# Ubuntu LCD 多媒体终端 **Repository Path**: YOUNGQI-LYQ/ubuntu-lcd-multimedia-terminal ## Basic Information - **Project Name**: Ubuntu LCD 多媒体终端 - **Description**: 一个简易的实训项目。 - **Primary Language**: C/C++ - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-07-06 - **Last Updated**: 2025-07-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 多媒体终端 本项目是一个基于 C/C++ 混合编程,运行于 x86/Ubuntu 环境下的多功能 LCD 屏幕应用。通过直接操作 Linux Framebuffer 和 Input Event 设备,它实现了一个集电子相册(支持缩放/平移)、电子书阅读器(支持TTS语音朗读)、电子琴(支持录音/回放)于一体的交互式多媒体系统,旨在模拟嵌入式设备的底层开发方式。 ## 视频演示 [点击观看视频](https://imgcdn.youngqi.cn/res/video.mp4) ## 目录 - [项目特色](#项目特色) - [技术栈](#技术栈) - [项目架构图](#项目架构图) - [执行流程图](#执行流程图) - [核心逻辑剖析](#核心逻辑剖析) - [Framebuffer 图形渲染](#Framebuffer 图形渲染) - [触摸/输入事件处理](#触摸/输入事件处理) - [语音合成 (TTS) 集成](#语音合成 (TTS) 集成) - [电子琴录音与回放](#电子琴录音与回放) - [应用模块化管理](#应用模块化管理) - [环境部署 (x86/Ubuntu)](#环境部署 (x86/Ubuntu)) - [编译与运行](#编译与运行) - [使用介绍](#使用介绍) - [文件结构](#文件结构) ## 项目特色 - **底层驱动模拟**: 直接通过 `mmap` 内存映射操作 Framebuffer (`/dev/ubuntu_lcd`),通过 `read` 读取输入事件 (`/dev/ubuntu_event`),模拟了嵌入式 Linux 开发中对硬件的底层访问方式。 - **功能复合型应用**: 清晰地分为三大核心模块: - **电子相册**: 支持 `.jpg`/`.bmp` 图片浏览,并实现了**图片缩放与平移**功能。 - **电子书**: 支持 `txt` 文本阅读,并集成了科大讯飞SDK,实现了**TTS语音朗读**功能。 - **电子琴**: 12键模拟钢琴,不仅能弹奏,还支持**实时录音与旋律回放**。 - **动态UI与状态保存**: - 主菜单界面包含**实时时钟**和**相册图片轮播**,提升了界面的动态感。 - 电子书模块能够**自动保存阅读进度**,方便用户下次继续阅读。 - **C/C++ 混合编程**: 主体框架使用 C 语言,同时通过 C++ 桥接文件 (`tts_bridge.cpp`) 封装和调用科大讯飞的 C++ SDK,是混合编程的典型实践。 - **资源整合**: 整合了 `libjpeg` 库、`mpg123` 命令行工具、`iconv` 编码转换库以及 `HZK16`/`ASC16` 点阵字库,构建了功能完善的多媒体支持体系。 ## 技术栈 - **编程语言**: `C` / `C++` (用于桥接TTS SDK) - **操作系统**: `Linux` (在 `Ubuntu` 下开发和测试) - **核心 API**: - `Linux Framebuffer`: 用于图形用户界面的直接渲染。 - `Linux Input Event Subsystem`: 用于接收和解析触摸屏或鼠标的输入事件。 - `POSIX API`: `mmap`, `select`, `open`, `read`, `iconv`, `system` 等。 - **图形与图像**: - `libjpeg`: 用于解码 `JPG` 格式的图片。 - 自定义 `BMP` 解析器与渲染器,支持缩放和平移。 - **音频处理**: - **播放**: `mpg123` 作为外部命令行工具,用于播放 `MP3` 音频文件。 - **语音合成**: `科大讯飞 SparkChain TTS SDK` 用于将文本转换为语音。 - **字体与编码**: - 点阵字库 (`HZK16`, `ASC16`): 用于在中英文界面上显示文本。 - `iconv`: 用于 `GB2312` 到 `UTF-8` 的文本编码转换,以适配TTS SDK的要求。 - **构建系统**: `GNU Make` ## 项目架构图 ```mermaid graph TD subgraph "应用层 (Application Layer)" A[主程序入口
main.c] end subgraph "功能模块 (Feature Modules)" B["电子相册
run_photo_album()"] C["电子书
run_ebook()"] D["电子琴
run_piano()"] end subgraph "服务/逻辑层 (Service/Logic Layer)" E["UI 绘制服务
show_main_menu(), etc."] F["图片列表管理
photo.c (双向链表)"] G["MP3 播放服务
mp3.c"] TTS_Bridge["TTS C++桥接层
tts_bridge.cpp"] end subgraph "驱动/库/SDK层 (Driver, Library & SDK Layer)" H["LCD 驱动封装
lcd.c (Framebuffer)"] I["触摸驱动封装
ts.c (Input Event)"] J["libjpeg 解码库"] K["字体库 (HZK16, ASC16)"] L["mpg123 命令行工具"] SDK["讯飞 TTS SDK (.so)"] ICONV["iconv 编码转换库"] end A --> B A --> C A --> D A --> E B --> F; B --> J; B --> H; B --> I C --> K; C --> H; C --> I; C --> TTS_Bridge; C --> ICONV D --> G; D --> H; D --> I G --> L TTS_Bridge --> SDK ``` ## 执行流程图 ```mermaid flowchart TD Start[开始] --> Init{"1. 初始化
打开 Framebuffer, Input Device
内存映射(mmap)
初始化TTS SDK"}; Init --> Loop["2. 主循环 (while)"]; Loop --> DrawMenu["2.1 绘制/更新主菜单
show_main_menu()"]; DrawMenu --> CheckUpdates{"2.2 定时任务
(非阻塞等待)
- 更新时钟
- 轮播相册预览"}; CheckUpdates --> CheckInput{"2.3 检查触摸输入
select() / get_touch_event()"}; CheckInput -- "无输入" --> Loop; CheckInput -- "有输入" --> ProcessInput; ProcessInput --> Choice{"2.4 根据坐标判断用户选择"}; Choice -- "相册区域" --> RunPhoto["执行 run_photo_album()
(进入相册子循环)"]; Choice -- "电子书区域" --> RunEbook["执行 run_ebook()
(进入电子书子循环)"]; Choice -- "电子琴区域" --> RunPiano["执行 run_piano()
(进入电子琴子循环)"]; Choice -- "退出区域" --> Cleanup{"3. 清理资源
清屏, munmap, close(fd)
反初始化TTS SDK"}; RunPhoto --> Loop; RunEbook --> Loop; RunPiano --> Loop; Cleanup --> End[结束]; ``` ## 核心逻辑剖析 ### Framebuffer 图形渲染 所有图形界面的绘制都通过直接操作 Framebuffer 完成,核心函数封装在 `lcd.c` 中。关键逻辑是:通过 `mmap` 将设备物理显存映射到进程的虚拟地址空间,后续所有绘图操作(画点、画矩形、渲染文字/图片)都简化为对这块内存的直接读写。本项目还实现了带缩放和平移的图像绘制函数 (`draw_jpeg_with_scale`),通过计算缩放后像素与原图像素的映射关系,实现高质量的图像显示。 ### 触摸/输入事件处理 输入处理逻辑封装在 `ts.c` 中。`get_touch_event` 函数通过 `read` 读取 `struct input_event`,并设计了一个小型状态机:它等待一个 `EV_ABS` 类型的 X 坐标事件,然后等待一个 Y 坐标事件,两者都收到后才认为是一次有效的触摸,并返回坐标。这种方式不依赖 `EV_SYN` 同步信号,增强了对不同输入设备的兼容性。主循环则使用 `select` 实现对触摸事件的非阻塞监听,允许在等待用户操作的同时执行其他任务(如更新时钟)。 ### 语音合成 (TTS) 集成 这是电子书模块的一大亮点,实现了 C 与 C++ SDK 的协同工作: 1. **获取文本**: 当用户点击“听书”按钮,程序首先从当前页的文本内容中提取字符串(GB2312编码)。 2. **编码转换**: 由于讯飞SDK要求UTF-8编码,程序调用 `iconv` 库函数,将提取的 GB2312 字符串转换为 UTF-8 格式。 3. **调用C++桥接层**: C代码(`main.c`)调用 `tts_bridge.cpp`中通过 `extern "C"` 暴露的 `text_to_speech_c` 函数。 4. **SDK交互**: `tts_bridge.cpp` 内的C++代码负责调用讯飞 SparkChain C++ SDK,发起语音合成请求,并将合成的音频流(MP3格式)写入本地文件 (`./res/audio/tts_output.mp3`)。 5. **播放音频**: 合成成功后,主程序通过 `system()` 命令调用 `mpg123` 在后台播放该音频文件。 ### 电子琴录音与回放 电子琴模块通过一个精巧的状态机 (`P_IDLE`, `P_RECORDING`, `P_PLAYBACK`) 和数据结构 `struct NoteEvent` 实现录音与回放功能。 - **录音**: 当进入 `P_RECORDING` 状态,每次按下琴键,程序会记录两样东西:被按下的**琴键索引** (`key_index`) 和距离上一次按键的**时间间隔**(`delay_us`,通过高精度时钟 `get_time_in_us()` 获取)。这些信息被存入 `recorded_song` 数组中。 - **回放**: 当进入 `P_PLAYBACK` 状态,程序会遍历 `recorded_song` 数组。对于每个音符,它会先等待 `delay_us` 微秒,然后播放对应 `key_index` 的音效,从而精准复现原始弹奏的节奏和音高。 ### 应用模块化管理 `main.c` 充当顶层调度器。`main` 函数的主循环负责绘制主菜单并等待用户输入。获取触摸坐标后,通过 `if-else` 判断坐标区域,调用相应的功能模块函数(如 `run_photo_album()`)。每个功能模块是一个独立的子循环,处理该模块内的所有交互,直到用户点击“返回”,函数返回,控制权交还给 `main` 函数,再次显示主菜单。 ## 环境部署 (x86/Ubuntu) 1. **安装基础依赖** ```bash sudo apt-get update sudo apt-get install build-essential libjpeg-dev mpg123 ``` - `build-essential`: 提供 `gcc`, `g++` 和 `make`。 - `libjpeg-dev`: 用于解码 JPG 图片。 - `mpg123`: 用于播放 MP3 音频。 2. **配置讯飞TTS SDK** 本项目需要科大讯飞的Linux版SparkChain SDK。 - 前往讯飞开放平台下载SDK。 - 将解压后的 `libs` 和 `include` 文件夹内容,放入您项目的一个指定目录,例如 `sdk/`。Makefile需要正确配置头文件和库文件的搜索路径。 3. **配置模拟设备节点 (如果需要)** 代码中使用了 `/dev/ubuntu_lcd` 和 `/dev/ubuntu_event` 作为设备路径。您需要创建符号链接将其指向 x86 平台对应的真实设备。 - **Framebuffer**: ```bash # 将 /dev/ubuntu_lcd 链接到 /dev/fb0 sudo ln -s /dev/fb0 /dev/ubuntu_lcd ``` - **Input Event**: ```bash # 首先用 `cat /proc/bus/input/devices` 找到你的鼠标设备号 (eventX) # 然后将 /dev/ubuntu_event 链接到该设备 sudo ln -s /dev/input/eventX /dev/ubuntu_event ``` ## 编译与运行 1. **配置 Makefile** 确保 `Makefile` 中的编译和链接选项正确: - `CC` 应设为 `gcc`,`CXX` 设为 `g++`。 - `INCLUDE_PATH` 应包含 `-I./inc -I./sdk/include`。 - `LDFLAGS` 应包含 `-L./sdk/libs -lSparkChain -ljpeg` 等链接选项。 2. **编译** 在项目根目录下执行: ```bash make ``` 该命令会分别编译 C 和 C++ 源文件,并最终链接成一个名为 `main` 的可执行文件。 3. **运行** 确保终端位于项目根目录,然后以超级用户权限运行(因为需要访问设备文件): ```bash sudo ./main ``` ## 使用介绍 程序启动后,会显示主菜单。所有操作均通过鼠标点击(模拟触摸)完成。 - **主菜单** - **电子相册**: 点击进入。 - **电子书**: 点击进入。 - **电子琴**: 点击进入。 - **右下角“退出”按钮**: 退出程序。 - **电子相册模块** - **右侧控制栏**: `上一张`/`下一张`, `放大`/`缩小`, `上`/`下`/`左`/`右`平移, `返回`。 - **电子书模块** - **右侧控制栏**: `上`/`下`翻页, `上`/`下`换章, **`听书 (TTS)`**, `返回`。 - **电子琴模块** - **琴键区域**: 点击播放对应音效。 - **底部控制栏**: `录制`, `停止录制`, `播放录音`, `返回`。 ## 文件结构 ``` MULTIMEDIA_TERMINAL/ ├── inc/ # 头文件目录 (.h) │ ├── lcd.h # LCD 驱动封装 │ ├── mp3.h # MP3 播放功能封装 │ ├── photo.h # 电子相册模块 (链表结构) │ ├── read.h # 电子书模块 │ ├── ts.h # 触摸驱动封装 │ ├── tts_bridge.h # C++桥接层头文件 │ ├── ASC16.h # ASCII 字体数据 │ └── HZK16.h # 汉字字体数据 ├── res/ # 资源文件目录 │ ├── audio/ # 存放MP3文件 (琴键音效, TTS输出) │ ├── imagefiles/ # 存放图片文件 (UI元素, 相册图片) │ ├── novel/ # 存放TXT格式的电子书文本 │ └── state/ # 存放程序状态文件 (如 ebook_state.txt) ├── src/ # 源文件目录 │ ├── main.c # 主程序入口与模块调度 │ ├── lcd.c # LCD 驱动实现 │ ├── mp3.c # MP3 播放功能实现 │ ├── photo.c # 电子相册功能实现 (链表操作) │ ├── read.c # 电子书功能实现 (文本渲染) │ ├── ts.c # 触摸驱动实现 │ └── tts_bridge.cpp # TTS 功能的 C++ 桥接实现 ├── sdk/ # (需手动创建) 存放第三方SDK │ ├── include/ # 存放SDK头文件 │ └── libs/ # 存放SDK库文件 (.so) ├── .gitignore # Git 忽略文件配置 ├── Makefile # 编译脚本 └── main # (编译后生成) 最终可执行文件 ```