@@ -7,6 +7,9 @@ extern crate display_client;
77#[ macro_use]
88extern crate ulib;
99
10+ use alloc:: borrow:: ToOwned ;
11+ use alloc:: string:: String ;
12+ use alloc:: vec:: Vec ;
1013use display_client:: proto;
1114
1215use ulib:: sys:: FileDesc ;
@@ -32,6 +35,76 @@ fn read_all(fd: FileDesc) -> alloc::vec::Vec<u8> {
3235 out
3336}
3437
38+ fn load_image ( file : u32 ) -> ( usize , usize , Vec < u32 > ) {
39+ let img = read_all ( file) ;
40+ let ( header, data) = gfx:: format:: qoi:: read_qoi_header ( & img) . unwrap ( ) ;
41+ let width = header. width as usize ;
42+ let height = header. height as usize ;
43+ let mut output = alloc:: vec![ 0u32 ; width * height] ;
44+ gfx:: format:: qoi:: decode_qoi ( & header, data, & mut output, width) ;
45+
46+ ( width, height, output)
47+ }
48+
49+ fn list_dir ( dir : u32 ) -> Vec < String > {
50+ let mut cookie = 0 ;
51+ let mut data_backing = [ 0u64 ; 8192 / 8 ] ;
52+ let data = cast_slice ( & mut data_backing) ;
53+
54+ fn cast_slice < ' a > ( s : & ' a mut [ u64 ] ) -> & ' a mut [ u8 ] {
55+ unsafe {
56+ core:: slice:: from_raw_parts_mut ( s. as_mut_ptr ( ) . cast :: < u8 > ( ) , s. len ( ) * size_of :: < u64 > ( ) )
57+ }
58+ }
59+
60+ #[ repr( C ) ]
61+ #[ derive( Copy , Clone , Debug ) ]
62+ pub struct DirEntry {
63+ pub inode : u64 ,
64+ pub next_entry_cookie : u64 ,
65+ pub rec_len : u16 ,
66+ pub name_len : u16 ,
67+ pub file_type : u8 ,
68+ pub name : [ u8 ; 3 ] ,
69+ // Name is an arbitrary size array; the record is always padded with
70+ // 0 bytes such that rec_len is a multiple of 8 bytes.
71+ }
72+
73+ let mut filenames = Vec :: new ( ) ;
74+
75+ ' outer: loop {
76+ match ulib:: sys:: pread ( dir, data, cookie) {
77+ Err ( e) => {
78+ println ! ( "Error reading dir: {e}" ) ;
79+ ulib:: sys:: exit ( 1 ) ;
80+ }
81+ Ok ( 0 ) => break ,
82+ Ok ( len) => {
83+ let mut i = 0 ;
84+ while i < len as usize {
85+ let slice = & data[ i..] ;
86+ assert ! ( slice. len( ) >= size_of:: <DirEntry >( ) ) ;
87+ let entry = unsafe { * slice. as_ptr ( ) . cast :: < DirEntry > ( ) } ;
88+
89+ let name_off = core:: mem:: offset_of!( DirEntry , name) ;
90+ let name = & slice[ name_off..] [ ..entry. name_len as usize ] ;
91+
92+ let name = core:: str:: from_utf8 ( name) . unwrap ( ) ;
93+ filenames. push ( name. to_owned ( ) ) ;
94+
95+ i += entry. rec_len as usize ;
96+ cookie = entry. next_entry_cookie ;
97+ }
98+ if cookie == 0 {
99+ break ' outer;
100+ }
101+ }
102+ }
103+ }
104+
105+ filenames
106+ }
107+
35108#[ no_mangle]
36109fn main ( argc : usize , argv : * const * const u8 ) {
37110 let argv_array = unsafe { core:: slice:: from_raw_parts ( argv, argc) } ;
@@ -42,26 +115,35 @@ fn main(argc: usize, argv: *const *const u8) {
42115
43116 let file = args[ 1 ] ;
44117
45- let img_data;
46- let img_width;
47- let img_height;
118+ let mut dir_fd = 3 ;
119+ let mut idx = 0 ;
120+ let mut files = Vec :: new ( ) ;
121+
122+ let mut img_data;
123+ let mut img_width;
124+ let mut img_height;
125+
126+ let mut last_idx = idx;
48127
49128 if file. ends_with ( "qoi" ) {
129+ files. push ( file. to_owned ( ) ) ;
50130 let Ok ( file) = ulib:: sys:: openat ( 3 , file. as_bytes ( ) , 0 , 0 ) else {
51131 println ! ( "Error opening file {}" , file) ;
52132 ulib:: sys:: exit ( 1 ) ;
53133 } ;
54-
55- let img = read_all ( file) ;
56- let ( header, data) = gfx:: format:: qoi:: read_qoi_header ( & img) . unwrap ( ) ;
57- let width = header. width as usize ;
58- let height = header. height as usize ;
59- let mut output = alloc:: vec![ 0u32 ; width * height] ;
60- gfx:: format:: qoi:: decode_qoi ( & header, data, & mut output, width) ;
61-
62- img_width = width;
63- img_height = height;
64- img_data = output;
134+ ( img_width, img_height, img_data) = load_image ( file) ;
135+ } else if let Ok ( dir) = ulib:: sys:: openat ( 3 , alloc:: format!( "{file}/" ) . as_bytes ( ) , 0 , 0 ) {
136+ files = list_dir ( dir) ;
137+ files. retain ( |f| f. ends_with ( "qoi" ) ) ;
138+ files. sort ( ) ;
139+ println ! ( "Loaded files: {:?}" , files) ;
140+ dir_fd = dir;
141+
142+ let Ok ( file) = ulib:: sys:: openat ( dir_fd, files[ 0 ] . as_bytes ( ) , 0 , 0 ) else {
143+ println ! ( "Error opening file {}" , file) ;
144+ ulib:: sys:: exit ( 1 ) ;
145+ } ;
146+ ( img_width, img_height, img_data) = load_image ( file) ;
65147 } else {
66148 println ! ( "Unknown file format, exiting." ) ;
67149 ulib:: sys:: exit ( 1 ) ;
@@ -82,30 +164,66 @@ fn main(argc: usize, argv: *const *const u8) {
82164 proto:: EventKind :: INPUT => {
83165 use proto:: EventData ;
84166 let data = proto:: InputEvent :: parse ( & ev) . expect ( "TODO" ) ;
85- if data. kind == proto:: InputEvent :: KIND_KEY {
167+ if data. kind == proto:: InputEvent :: KIND_KEY && data . data1 == 1 {
86168 match proto:: ScanCode ( data. data2 ) {
87169 proto:: ScanCode :: ESCAPE | proto:: ScanCode :: Q => {
88170 break ' outer;
89171 } ,
172+ proto:: ScanCode :: RIGHT => {
173+ idx = ( idx + 1 ) % files. len ( ) ;
174+ } ,
175+ proto:: ScanCode :: LEFT => {
176+ idx = ( idx + files. len ( ) - 1 ) % files. len ( ) ;
177+ } ,
90178 _ => ( ) ,
91179 }
180+ } else if data. kind == proto:: InputEvent :: KIND_MOUSE && data. data1 == 2 {
181+ match data. data4 {
182+ 1 => {
183+ // Mouse1 down
184+ idx = ( idx + 1 ) % files. len ( ) ;
185+ } ,
186+ 2 => {
187+ // Mouse2 down
188+ idx = ( idx + files. len ( ) - 1 ) % files. len ( ) ;
189+ } ,
190+ _ => ( ) ,
191+ }
192+ }
92193 }
93- }
94194 proto:: EventKind :: REQUEST_CLOSE => {
95195 break ' outer;
96196 }
97197 _ => ( ) ,
98198 }
99199 }
100200
201+ idx = idx % files. len ( ) ;
202+ if idx != last_idx {
203+ let start = unsafe { ulib:: sys:: sys_get_time_ms ( ) } ;
204+ if let Ok ( file) = ulib:: sys:: openat ( dir_fd, files[ idx] . as_bytes ( ) , 0 , 0 ) {
205+ drop ( img_data) ;
206+ ( img_width, img_height, img_data) = load_image ( file) ;
207+ let end = unsafe { ulib:: sys:: sys_get_time_ms ( ) } ;
208+ println ! ( "Loading image took {}ms" , end - start) ;
209+ last_idx = idx;
210+ } else {
211+ println ! ( "Error opening file {}" , file) ;
212+ idx = last_idx;
213+ }
214+ }
215+
216+ let x = width. saturating_sub ( img_width) / 2 ;
217+ let y = height. saturating_sub ( img_height) / 2 ;
218+
101219 let fb = buf. video_mem ( ) ;
102220 gfx:: blit_buffer (
103221 fb,
104222 width,
105223 height,
106224 row_stride,
107- 0 ,
108- 0 ,
225+ x ,
226+ y ,
109227 & img_data,
110228 img_width,
111229 img_height,
@@ -121,8 +239,6 @@ fn main(argc: usize, argv: *const *const u8) {
121239
122240 // signal(video)? for sync
123241 ulib:: sys:: sem_down ( buf. get_sem_fd ( buf. present_sem ) ) . unwrap ( ) ;
124-
125- unsafe { ulib:: sys:: sys_sleep_ms ( 1000 ) } ;
126242 }
127243
128244 buf. client_to_server_queue ( )
0 commit comments