@@ -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) } ;
@@ -44,26 +117,35 @@ fn main(argc: usize, argv: *const *const u8) {
44117
45118 let file = args[ 1 ] ;
46119
47- let img_data;
48- let img_width;
49- let img_height;
120+ let mut dir_fd = 3 ;
121+ let mut idx = 0 ;
122+ let mut files = Vec :: new ( ) ;
123+
124+ let mut img_data;
125+ let mut img_width;
126+ let mut img_height;
127+
128+ let mut last_idx = idx;
50129
51130 if file. ends_with ( "qoi" ) {
131+ files. push ( file. to_owned ( ) ) ;
52132 let Ok ( file) = ulib:: sys:: openat ( 3 , file. as_bytes ( ) , 0 , 0 ) else {
53133 println ! ( "Error opening file {}" , file) ;
54134 ulib:: sys:: exit ( 1 ) ;
55135 } ;
56-
57- let img = read_all ( file) ;
58- let ( header, data) = gfx:: format:: qoi:: read_qoi_header ( & img) . unwrap ( ) ;
59- let width = header. width as usize ;
60- let height = header. height as usize ;
61- let mut output = alloc:: vec![ 0u32 ; width * height] ;
62- gfx:: format:: qoi:: decode_qoi ( & header, data, & mut output, width) ;
63-
64- img_width = width;
65- img_height = height;
66- img_data = output;
136+ ( img_width, img_height, img_data) = load_image ( file) ;
137+ } else if let Ok ( dir) = ulib:: sys:: openat ( 3 , alloc:: format!( "{file}/" ) . as_bytes ( ) , 0 , 0 ) {
138+ files = list_dir ( dir) ;
139+ files. retain ( |f| f. ends_with ( "qoi" ) ) ;
140+ files. sort ( ) ;
141+ println ! ( "Loaded files: {:?}" , files) ;
142+ dir_fd = dir;
143+
144+ let Ok ( file) = ulib:: sys:: openat ( dir_fd, files[ 0 ] . as_bytes ( ) , 0 , 0 ) else {
145+ println ! ( "Error opening file {}" , file) ;
146+ ulib:: sys:: exit ( 1 ) ;
147+ } ;
148+ ( img_width, img_height, img_data) = load_image ( file) ;
67149 } else {
68150 println ! ( "Unknown file format, exiting." ) ;
69151 ulib:: sys:: exit ( 1 ) ;
@@ -84,11 +166,29 @@ fn main(argc: usize, argv: *const *const u8) {
84166 proto:: EventKind :: INPUT => {
85167 use proto:: EventData ;
86168 let data = proto:: InputEvent :: parse ( & ev) . expect ( "TODO" ) ;
87- if data. kind == proto:: InputEvent :: KIND_KEY {
169+ if data. kind == proto:: InputEvent :: KIND_KEY && data . data1 == 1 {
88170 match proto:: ScanCode ( data. data2 ) {
89171 proto:: ScanCode :: ESCAPE | proto:: ScanCode :: Q => {
90172 break ' outer;
91173 }
174+ proto:: ScanCode :: RIGHT => {
175+ idx = ( idx + 1 ) % files. len ( ) ;
176+ }
177+ proto:: ScanCode :: LEFT => {
178+ idx = ( idx + files. len ( ) - 1 ) % files. len ( ) ;
179+ }
180+ _ => ( ) ,
181+ }
182+ } else if data. kind == proto:: InputEvent :: KIND_MOUSE && data. data1 == 2 {
183+ match data. data4 {
184+ 1 => {
185+ // Mouse1 down
186+ idx = ( idx + 1 ) % files. len ( ) ;
187+ }
188+ 2 => {
189+ // Mouse2 down
190+ idx = ( idx + files. len ( ) - 1 ) % files. len ( ) ;
191+ }
92192 _ => ( ) ,
93193 }
94194 }
@@ -100,9 +200,27 @@ fn main(argc: usize, argv: *const *const u8) {
100200 }
101201 }
102202
203+ idx = idx % files. len ( ) ;
204+ if idx != last_idx {
205+ let start = unsafe { ulib:: sys:: sys_get_time_ms ( ) } ;
206+ if let Ok ( file) = ulib:: sys:: openat ( dir_fd, files[ idx] . as_bytes ( ) , 0 , 0 ) {
207+ drop ( img_data) ;
208+ ( img_width, img_height, img_data) = load_image ( file) ;
209+ let end = unsafe { ulib:: sys:: sys_get_time_ms ( ) } ;
210+ println ! ( "Loading image took {}ms" , end - start) ;
211+ last_idx = idx;
212+ } else {
213+ println ! ( "Error opening file {}" , file) ;
214+ idx = last_idx;
215+ }
216+ }
217+
218+ let x = width. saturating_sub ( img_width) / 2 ;
219+ let y = height. saturating_sub ( img_height) / 2 ;
220+
103221 let fb = buf. video_mem ( ) ;
104222 gfx:: blit_buffer (
105- fb, width, height, row_stride, 0 , 0 , & img_data, img_width, img_height, img_width,
223+ fb, width, height, row_stride, x , y , & img_data, img_width, img_height, img_width,
106224 ) ;
107225
108226 buf. client_to_server_queue ( )
@@ -114,8 +232,6 @@ fn main(argc: usize, argv: *const *const u8) {
114232
115233 // signal(video)? for sync
116234 ulib:: sys:: sem_down ( buf. get_sem_fd ( buf. present_sem ) ) . unwrap ( ) ;
117-
118- unsafe { ulib:: sys:: sys_sleep_ms ( 1000 ) } ;
119235 }
120236
121237 buf. client_to_server_queue ( )
0 commit comments