diff --git a/src/album_data.rs b/src/album_data.rs index c2a6c22..617af2c 100644 --- a/src/album_data.rs +++ b/src/album_data.rs @@ -64,7 +64,7 @@ impl BaseAlbumResources { } } - pub fn construct_artwork<'a, T>(self, texture_creator: &'a TextureCreator) -> AlbumResources { + pub fn construct_artwork(self, texture_creator: &TextureCreator) -> AlbumResources { let artwork = texture_creator.load_texture(&self.artwork_file_path).unwrap(); // Should never panic AlbumResources { base_resources: self, diff --git a/src/main.rs b/src/main.rs index 5241e26..c7704d2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ - // FRONT BURNER // TODO: Try sending seperate requests more often to get data on whether it's playing or paused // TODO: temporarily add albums to a new array for reshuffle animation @@ -6,7 +5,6 @@ // TODO: add gradient at the top of album selection view to make buttons more visible // TODO: re-implement variable framerate if necessary - // CRASHES // TODO: Probably panic the whole program when the secondary thread panics // TODO: Fix crash when clicking heart button while nothing's playing @@ -24,30 +22,29 @@ // TODO: Add a way for user to manually clear caches // TODO: Load data directly from cache, then update it when loaded from apple music - use std::collections::HashMap; use std::rc::Rc; -use std::time::{Duration, Instant}; use std::sync::mpsc; -use std::{thread}; +use std::thread; +use std::time::{Duration, Instant}; -use queues::{Queue, IsQueue}; +use queues::{IsQueue, Queue}; use rust_embed::RustEmbed; use sdl2; +use sdl2::event::{Event, WindowEvent}; use sdl2::image::LoadTexture; use sdl2::libc::c_int; use sdl2::mouse::MouseButton; use sdl2::pixels::Color; -use sdl2::event::{Event, WindowEvent}; -use sdl2::rect::{Rect, Point}; -use sdl2::render::{ TextureCreator, Texture, BlendMode }; +use sdl2::rect::{Point, Rect}; +use sdl2::render::{BlendMode, Texture, TextureCreator}; -use sdl2::sys::{SDL_SetWindowHitTest, SDL_Window, SDL_Point, SDL_Rect, SDL_HitTestResult}; +use sdl2::sys::{SDL_HitTestResult, SDL_Point, SDL_Rect, SDL_SetWindowHitTest, SDL_Window}; use std::ffi::c_void; -use rand::thread_rng; use rand::seq::SliceRandom; +use rand::thread_rng; mod player_data; use player_data::PlayerState; @@ -61,7 +58,6 @@ use engine::Button; use crate::album_data::BaseAlbumResources; use crate::player_data::NowPlayingResourceCollection; - #[derive(PartialEq)] enum View { Miniplayer, @@ -71,7 +67,7 @@ enum View { // PRIMARY THREAD: Renders a SDL2 interface for users to interact with the application fn main() { sdl2::hint::set("SDL_VIDEO_ALLOW_SCREENSAVER", "1"); - + // Set up a MPSC channel to send player data between threads let (player_tx, player_rx) = mpsc::channel(); @@ -101,28 +97,34 @@ fn main() { const THUMBNAIL_SIZE_DRAG: u32 = THUMBNAIL_SIZE - THUMBNAIL_SCALE_AMT_DRAG; // Create the window - let mut window = video_subsystem.window("micromusic", WINDOW_WIDTH, WINDOW_HEIGHT) + let mut window = video_subsystem + .window("micromusic", WINDOW_WIDTH, WINDOW_HEIGHT) .position_centered() .allow_highdpi() .borderless() .build() .unwrap(); window.raise(); - + // Make the window draggable fn raw_heap_rect(x: c_int, y: c_int, w: c_int, h: c_int) -> *const SDL_Rect { - Box::into_raw(Box::new(SDL_Rect { x, y, w, h } )) + Box::into_raw(Box::new(SDL_Rect { x, y, w, h })) } - let add = vec![ raw_heap_rect(0, 0, WINDOW_WIDTH as i32, WINDOW_HEIGHT as i32) ]; + let add = vec![raw_heap_rect( + 0, + 0, + WINDOW_WIDTH as i32, + WINDOW_HEIGHT as i32, + )]; let mut sub = vec![]; - + #[repr(C)] struct HitTestData { add: *const *const SDL_Rect, add_len: c_int, sub: *const *const SDL_Rect, - sub_len: c_int + sub_len: c_int, } let mut hit_test_data = HitTestData { add: add.as_ptr(), @@ -130,9 +132,13 @@ fn main() { sub: sub.as_ptr(), sub_len: sub.len() as c_int, }; - - extern "C" { - pub fn hitTest(window: *mut SDL_Window, pt: *const SDL_Point, data: *mut c_void) -> SDL_HitTestResult; + + extern "C" { + pub fn hitTest( + window: *mut SDL_Window, + pt: *const SDL_Point, + data: *mut c_void, + ) -> SDL_HitTestResult; } unsafe { SDL_SetWindowHitTest( @@ -142,13 +148,8 @@ fn main() { ); } - //Create a canvas from the window - let mut canvas = window - .into_canvas() - .present_vsync() - .build() - .unwrap(); + let mut canvas = window.into_canvas().present_vsync().build().unwrap(); // Get the canvas's texture creator let texture_creator = canvas.texture_creator(); @@ -159,7 +160,6 @@ fn main() { canvas.clear(); canvas.present(); - // Create the icon textures and load them into a dictionary // TODO: Maybe move to engine // TODO: Only load files with .png extension (not .DS_Store if it exists) @@ -167,19 +167,27 @@ fn main() { #[folder = "assets/icons/"] struct IconAsset; - fn load_icons<'a, T: 'a>(color_mod: u8, blend_mode: BlendMode, texture_creator: &'a TextureCreator) -> HashMap> { - IconAsset::iter().map(|file_path| { - let mut tex = texture_creator.load_texture_bytes(&IconAsset::get(&file_path).unwrap().data) - .unwrap_or_else(|_| panic!("Unable to load {}", &file_path)); - tex.set_color_mod(color_mod, color_mod, color_mod); - tex.set_blend_mode(blend_mode); - (file_path.to_string(), tex) - }).collect() + fn load_icons<'a, T: 'a>( + color_mod: u8, + blend_mode: BlendMode, + texture_creator: &'a TextureCreator, + ) -> HashMap> { + IconAsset::iter() + .map(|file_path| { + let mut tex = texture_creator + .load_texture_bytes(&IconAsset::get(&file_path).unwrap().data) + .unwrap_or_else(|_| panic!("Unable to load {}", &file_path)); + tex.set_color_mod(color_mod, color_mod, color_mod); + tex.set_blend_mode(blend_mode); + (file_path.to_string(), tex) + }) + .collect() } const ICON_COLOR_MOD_DEFAULT: u8 = 150; const ICON_COLOR_MOD_HOVER: u8 = 255; - let icon_textures_default = load_icons(ICON_COLOR_MOD_DEFAULT, BlendMode::Add, &texture_creator); + let icon_textures_default = + load_icons(ICON_COLOR_MOD_DEFAULT, BlendMode::Add, &texture_creator); let icon_textures_hover = load_icons(ICON_COLOR_MOD_HOVER, BlendMode::Add, &texture_creator); // Create a map of all of the buttons on the screen @@ -187,7 +195,7 @@ fn main() { const A_SIZE: i32 = ARTWORK_SIZE as i32; [ ("album_view", (5, 5)), - ("miniplayer_view", (5, 5)), + ("miniplayer_view", (5, 5)), ("heart_empty", (19, 5)), ("heart_filled", (19, 5)), ("reshuffle", (19, 5)), @@ -199,51 +207,62 @@ fn main() { ("back_track", (A_SIZE / 2 - 6 - 18, A_SIZE - 20)), ] }; - let mut buttons: HashMap<&'static str, Button> = button_data.into_iter() - .map(|b| (b.0, { - let filename = String::from(b.0) + ".png"; - Button::new(b.1.0, b.1.1, - &icon_textures_default[&filename], - &icon_textures_hover[&filename], - &icon_textures_hover[&filename], - ) - })) + let mut buttons: HashMap<&'static str, Button> = button_data + .into_iter() + .map(|b| { + (b.0, { + let filename = String::from(b.0) + ".png"; + Button::new( + b.1 .0, + b.1 .1, + &icon_textures_default[&filename], + &icon_textures_hover[&filename], + &icon_textures_hover[&filename], + ) + }) + }) .collect(); - + // Add the queue box button, which requires a different texture for default and hover states - buttons.insert("queue", Button::new(ARTWORK_SIZE as i32 - 36, ARTWORK_SIZE as i32 - 36, - &icon_textures_default["queue_closed.png"], - &icon_textures_hover["queue_open.png"], - &icon_textures_hover["queue_open.png"], - )); + buttons.insert( + "queue", + Button::new( + ARTWORK_SIZE as i32 - 36, + ARTWORK_SIZE as i32 - 36, + &icon_textures_default["queue_closed.png"], + &icon_textures_hover["queue_open.png"], + &icon_textures_hover["queue_open.png"], + ), + ); let mut queue_button_squash_frame = 0; - + // Spawn a thread to get all album resources from Apple Music let (album_tx, album_rx) = mpsc::channel(); thread::spawn(move || { let base_album_resources = BaseAlbumResources::get_all_from_music(ARTWORK_SIZE * 2 / 3); album_tx.send(base_album_resources).unwrap(); }); - // Data for album select screen (Rc necessary because Queue requires Clone and references will go out of scope) enum ItemState { Default, Dragged, - Freeze { timer: u32}, + Freeze { + timer: u32, + }, Anim { duration: u32, - current: u32, + current: u32, x_curve: Box f32>, - y_curve: Box f32>, + y_curve: Box f32>, scale_curve: Box f32>, }, } - struct AlbumViewItem<'a> { - pub album: Rc>, + struct AlbumViewItem<'a> { + pub album: Rc>, pub x_vel: f32, pub x_pos: f32, - pub state: ItemState + pub state: ItemState, } impl AlbumViewItem<'_> { fn get_target_pos(item_col_i: usize, drag_placeholder_x: Option) -> usize { @@ -278,27 +297,33 @@ fn main() { self.state = ItemState::Default; } } - ItemState::Anim { duration, current, .. } => { + ItemState::Anim { + duration, current, .. + } => { if current < duration { *current += 1; } else { self.state = ItemState::Default; } } - _ => () + _ => (), } } fn get_anim_pos_and_scale(&self) -> Option<([f32; 2], f32)> { - if let ItemState::Anim { - duration, - current, - x_curve, - y_curve, + if let ItemState::Anim { + duration, + current, + x_curve, + y_curve, scale_curve, .. - } = &self.state { + } = &self.state + { let progress = *current as f32 / *duration as f32; - return Some(([x_curve(progress), y_curve(progress)], scale_curve(progress))); + return Some(( + [x_curve(progress), y_curve(progress)], + scale_curve(progress), + )); } else { return None; } @@ -311,9 +336,9 @@ fn main() { let mut drag_placeholder_loc: Option<[usize; 2]> = None; let mut queueing_albums: Vec = Vec::new(); - // State variables for the rendering loop - let mut now_playing_resources: NowPlayingResourceCollection = NowPlayingResourceCollection::build(None, &texture_creator); + let mut now_playing_resources: NowPlayingResourceCollection = + NowPlayingResourceCollection::build(None, &texture_creator); let mut last_snapshot_time = Instant::now(); let mut info_scroll_pos: i32 = 0; const INFO_SPACING: i32 = 50; @@ -326,144 +351,187 @@ fn main() { // This code will run every frame 'running: loop { - // Mouse state - let mouse_state = engine::mouse::MouseState::get_relative_state(&event_pump, canvas.window()); + let mouse_state = + engine::mouse::MouseState::get_relative_state(&event_pump, canvas.window()); let window_input_focus = &canvas.window().window_flags() & 512 == 512; // input focus: 512, mouse focus: 1024 - + // Iterate through the input events - for event in event_pump.poll_iter() { match event { - Event::Quit { .. } => { - break 'running; - }, - Event::MouseButtonDown { x, y, mouse_btn: MouseButton::Left, ..} => { - if Button::get_hovered_from_hash(&buttons, x, y).is_some() { - continue; + for event in event_pump.poll_iter() { + match event { + Event::Quit { .. } => { + break 'running; } - if current_view == View::AlbumSelect && artwork_rect.contains_point(mouse_state.pos()) { - let hovered_album_loc = mouse_state.pos() / I_THUMBNAIL_SIZE; - let target_row = album_view_rows.get_mut(hovered_album_loc.y as usize).unwrap(); - - if !target_row.is_empty() { - let mut target_item = target_row.remove(hovered_album_loc.x as usize); - target_item.state = ItemState::Dragged; - dragged_item_pos = [ - target_item.x_pos + (THUMBNAIL_SCALE_AMT_DRAG / 2) as f32, - (I_THUMBNAIL_SIZE * hovered_album_loc.y) as f32 + (THUMBNAIL_SCALE_AMT_DRAG / 2) as f32 - ]; - dragged_item = Some(target_item); - - target_row.push(AlbumViewItem { - album: album_view_queue.remove().unwrap(), - state: ItemState::Default, - x_pos: ARTWORK_SIZE as f32, - x_vel: 0.0, - }); - } - } - } - Event::MouseButtonUp { x, y, mouse_btn: MouseButton::Left, ..} => { - // Filter loc so that it's none if out of bounds - let loc = drag_placeholder_loc - .filter(|loc| (loc[1]) < 3 && (loc[0]) < 3); - - if let Some(mut u_dragged_item) = dragged_item.take() { - if buttons["queue"].is_hovering(mouse_state.x(), mouse_state.y()) { - // Constants - const START_SCALE: f32 = THUMBNAIL_SIZE_DRAG as f32 / THUMBNAIL_SIZE as f32; - const START_OFFSET: f32 = THUMBNAIL_SIZE_DRAG as f32 / 2.0; - - // The starting x and y positions of the thumbnail - let (x, y) = (dragged_item_pos[0] + START_OFFSET, dragged_item_pos[1] + START_OFFSET); - - // Quadratic data for vertical animation curve - const QUEUE_BUTTON_X: f32 = ARTWORK_SIZE as f32 - 20.0; - const QUEUE_BUTTON_Y: f32 = ARTWORK_SIZE as f32 - 20.0; - const ANIM_ARC_HEIGHT: f32 = 150.0; - - let a = QUEUE_BUTTON_Y - y; - let b = -2.0 * (ANIM_ARC_HEIGHT - y); - let c = ANIM_ARC_HEIGHT - y; - let vertex_t = (-b + (b.powi(2) - 4.0 * a * c).sqrt()) / (2.0 * a); - let scale_y = (y - ANIM_ARC_HEIGHT) / vertex_t.powi(2); - - // Set the dragged item's state to animate - u_dragged_item.state = ItemState::Anim { - duration: 15, - current: 0, - x_curve: Box::new(move |t: f32| x + t * (QUEUE_BUTTON_X - x)), - y_curve: Box::new(move |t: f32| scale_y * (t - vertex_t).powi(2) + ANIM_ARC_HEIGHT), - scale_curve: Box::new(|t: f32| (1.0 - t) * START_SCALE), - }; - queueing_albums.push(u_dragged_item); - - // Freeze the next item in the third row until the animation finishes - album_view_rows[2][2].state = ItemState::Freeze { timer: 25 }; + Event::MouseButtonDown { + x, + y, + mouse_btn: MouseButton::Left, + .. + } => { + if Button::get_hovered_from_hash(&buttons, x, y).is_some() { continue; } - u_dragged_item.state = ItemState::Default; - if let Some(loc) = loc { - u_dragged_item.x_pos = AlbumViewItem::get_target_pos(loc[0], None) as f32; - album_view_rows[loc[1]].insert(loc[0], u_dragged_item); - } else { - album_view_queue.add(u_dragged_item.album).unwrap(); + if current_view == View::AlbumSelect + && artwork_rect.contains_point(mouse_state.pos()) + { + let hovered_album_loc = mouse_state.pos() / I_THUMBNAIL_SIZE; + let target_row = album_view_rows + .get_mut(hovered_album_loc.y as usize) + .unwrap(); + + if !target_row.is_empty() { + let mut target_item = target_row.remove(hovered_album_loc.x as usize); + target_item.state = ItemState::Dragged; + dragged_item_pos = [ + target_item.x_pos + (THUMBNAIL_SCALE_AMT_DRAG / 2) as f32, + (I_THUMBNAIL_SIZE * hovered_album_loc.y) as f32 + + (THUMBNAIL_SCALE_AMT_DRAG / 2) as f32, + ]; + dragged_item = Some(target_item); + + target_row.push(AlbumViewItem { + album: album_view_queue.remove().unwrap(), + state: ItemState::Default, + x_pos: ARTWORK_SIZE as f32, + x_vel: 0.0, + }); + } } - dragged_item = None; - continue; } - - match Button::get_hovered_from_hash(&buttons, x, y) { - Some(button_name) => match button_name { - "heart_empty" => osascript_requests::run_command(JXACommand::Love, player_tx.clone()), - "heart_filled" => osascript_requests::run_command(JXACommand::Unlove, player_tx.clone()), - "album_view" => current_view = View::AlbumSelect, - "miniplayer_view" => current_view = View::Miniplayer, - "play" | "pause" => osascript_requests::run_command(JXACommand::PlayPause, player_tx.clone()), - "back_track" => osascript_requests::run_command(JXACommand::BackTrack, player_tx.clone()), - "next_track" => osascript_requests::run_command(JXACommand::NextTrack, player_tx.clone()), - "minimize" => { - // TODO: temporary border enabling hack no longer necessary in Ventura, remove? - canvas.window_mut().set_bordered(true); - canvas.window_mut().minimize(); - canvas.window_mut().set_bordered(false); + Event::MouseButtonUp { + x, + y, + mouse_btn: MouseButton::Left, + .. + } => { + // Filter loc so that it's none if out of bounds + let loc = drag_placeholder_loc.filter(|loc| (loc[1]) < 3 && (loc[0]) < 3); + + if let Some(mut u_dragged_item) = dragged_item.take() { + if buttons["queue"].is_hovering(mouse_state.x(), mouse_state.y()) { + // Constants + const START_SCALE: f32 = + THUMBNAIL_SIZE_DRAG as f32 / THUMBNAIL_SIZE as f32; + const START_OFFSET: f32 = THUMBNAIL_SIZE_DRAG as f32 / 2.0; + + // The starting x and y positions of the thumbnail + let (x, y) = ( + dragged_item_pos[0] + START_OFFSET, + dragged_item_pos[1] + START_OFFSET, + ); + + // Quadratic data for vertical animation curve + const QUEUE_BUTTON_X: f32 = ARTWORK_SIZE as f32 - 20.0; + const QUEUE_BUTTON_Y: f32 = ARTWORK_SIZE as f32 - 20.0; + const ANIM_ARC_HEIGHT: f32 = 150.0; + + let a = QUEUE_BUTTON_Y - y; + let b = -2.0 * (ANIM_ARC_HEIGHT - y); + let c = ANIM_ARC_HEIGHT - y; + let vertex_t = (-b + (b.powi(2) - 4.0 * a * c).sqrt()) / (2.0 * a); + let scale_y = (y - ANIM_ARC_HEIGHT) / vertex_t.powi(2); + + // Set the dragged item's state to animate + u_dragged_item.state = ItemState::Anim { + duration: 15, + current: 0, + x_curve: Box::new(move |t: f32| x + t * (QUEUE_BUTTON_X - x)), + y_curve: Box::new(move |t: f32| { + scale_y * (t - vertex_t).powi(2) + ANIM_ARC_HEIGHT + }), + scale_curve: Box::new(|t: f32| (1.0 - t) * START_SCALE), + }; + queueing_albums.push(u_dragged_item); + + // Freeze the next item in the third row until the animation finishes + album_view_rows[2][2].state = ItemState::Freeze { timer: 25 }; + continue; + } + u_dragged_item.state = ItemState::Default; + if let Some(loc) = loc { + u_dragged_item.x_pos = + AlbumViewItem::get_target_pos(loc[0], None) as f32; + album_view_rows[loc[1]].insert(loc[0], u_dragged_item); + } else { + album_view_queue.add(u_dragged_item.album).unwrap(); } - "reshuffle" => { - for row in album_view_rows.iter_mut() { - row.drain(..).for_each(|item| { album_view_queue.add(item.album).unwrap(); } ); + dragged_item = None; + continue; + } + + match Button::get_hovered_from_hash(&buttons, x, y) { + Some(button_name) => match button_name { + "heart_empty" => { + osascript_requests::run_command(JXACommand::Love, player_tx.clone()) } - for i in 0..9 { - if let Ok(a) = album_view_queue.remove() { - album_view_rows[i % 3].push(AlbumViewItem { - album: a, - x_pos: AlbumViewItem::get_target_pos(i / 3, None) as f32 + ARTWORK_SIZE as f32, - x_vel: 0.0, - state: ItemState::Freeze { timer: i as u32 % 3 * 3 + i as u32 / 3 } - }) - } else { - break; + "heart_filled" => osascript_requests::run_command( + JXACommand::Unlove, + player_tx.clone(), + ), + "album_view" => current_view = View::AlbumSelect, + "miniplayer_view" => current_view = View::Miniplayer, + "play" | "pause" => osascript_requests::run_command( + JXACommand::PlayPause, + player_tx.clone(), + ), + "back_track" => osascript_requests::run_command( + JXACommand::BackTrack, + player_tx.clone(), + ), + "next_track" => osascript_requests::run_command( + JXACommand::NextTrack, + player_tx.clone(), + ), + "minimize" => { + // TODO: temporary border enabling hack no longer necessary in Ventura, remove? + canvas.window_mut().set_bordered(true); + canvas.window_mut().minimize(); + canvas.window_mut().set_bordered(false); + } + "reshuffle" => { + for row in album_view_rows.iter_mut() { + row.drain(..).for_each(|item| { + album_view_queue.add(item.album).unwrap(); + }); + } + for i in 0..9 { + if let Ok(a) = album_view_queue.remove() { + album_view_rows[i % 3].push(AlbumViewItem { + album: a, + x_pos: AlbumViewItem::get_target_pos(i / 3, None) + as f32 + + ARTWORK_SIZE as f32, + x_vel: 0.0, + state: ItemState::Freeze { + timer: i as u32 % 3 * 3 + i as u32 / 3, + }, + }) + } else { + break; + } } } - } - "close" => { - // osascript_requests::remove_dj_playlist(); - break 'running + "close" => { + // osascript_requests::remove_dj_playlist(); + break 'running; + } + _ => {} + }, + None => (), + } + } + Event::Window { win_event, .. } => { + match win_event { + WindowEvent::Moved { .. } => { + // Update the canvas scale in case the user drags the window to a different monitor + engine::update_canvas_scale(&mut canvas, WINDOW_WIDTH, WINDOW_HEIGHT); } _ => {} } - None => () - } - } - Event::Window { win_event, .. } => { - match win_event { - WindowEvent::Moved {..} => { - // Update the canvas scale in case the user drags the window to a different monitor - engine::update_canvas_scale(&mut canvas, WINDOW_WIDTH, WINDOW_HEIGHT); - }, - _ => {} } + _ => {} } - _ => {} - }} + } // Reset drag_in_progress if the mouse button was just lifted if mouse_state.is_mouse_button_pressed(sdl2::mouse::MouseButton::Left) { @@ -474,7 +542,6 @@ fn main() { window_interaction_in_progress = false; } - // If the now playing channel has new data in it, update the player and track data on this thread if let Ok(response) = player_rx.try_recv() { now_playing_resources.update(response, &texture_creator); @@ -484,20 +551,21 @@ fn main() { // If the base album resources are done loading, create and save their artwork textures if let Ok(response) = album_rx.try_recv() { - let mut album_resources: Vec = response.into_iter() + let mut album_resources: Vec = response + .into_iter() .map(|r| r.construct_artwork(&texture_creator)) .collect(); - + album_resources.shuffle(&mut thread_rng()); - album_resources.into_iter().for_each(|item| { - album_view_queue.add(Rc::new(item)).unwrap(); + album_resources.into_iter().for_each(|item| { + album_view_queue.add(Rc::new(item)).unwrap(); }); for i in 0..9 { if let Ok(a) = album_view_queue.remove() { album_view_rows[i % 3].push(AlbumViewItem { - album: a, - x_pos: AlbumViewItem::get_target_pos(i / 3, None) as f32, + album: a, + x_pos: AlbumViewItem::get_target_pos(i / 3, None) as f32, x_vel: 0.0, state: ItemState::Default, }) @@ -507,7 +575,6 @@ fn main() { } } - // Clear the canvas for drawing canvas.set_draw_color(Color::RGB(0, 0, 0)); canvas.set_blend_mode(BlendMode::None); @@ -518,32 +585,34 @@ fn main() { button.active = false; } - // Per-frame code for the album select screen if current_view == View::AlbumSelect { - // The 3x3 grid coordinates of the album that's currently being hovered over // Casts done individually to prevent negative positions rounding toward 0 let hovered_album_loc: [usize; 2] = [ - (mouse_state.x() as usize) / THUMBNAIL_SIZE as usize, - (mouse_state.y() as usize) / THUMBNAIL_SIZE as usize + (mouse_state.x() as usize) / THUMBNAIL_SIZE as usize, + (mouse_state.y() as usize) / THUMBNAIL_SIZE as usize, ]; drag_placeholder_loc = dragged_item.as_ref().map(|_| hovered_album_loc); // Update the positions of all of the thumbnails and draw them for (row_y, row) in album_view_rows.iter_mut().enumerate() { for (item_x, item) in row.iter_mut().enumerate() { - let drag_placeholder_x = drag_placeholder_loc.filter(|loc| loc[1] == row_y).map(|loc| loc[0]); + let drag_placeholder_x = drag_placeholder_loc + .filter(|loc| loc[1] == row_y) + .map(|loc| loc[0]); let target_x = AlbumViewItem::get_target_pos(item_x, drag_placeholder_x) as f32; item.update(target_x); let thumbnail_rect = Rect::new( item.x_pos as i32, - I_THUMBNAIL_SIZE * row_y as i32, - THUMBNAIL_SIZE, - THUMBNAIL_SIZE + I_THUMBNAIL_SIZE * row_y as i32, + THUMBNAIL_SIZE, + THUMBNAIL_SIZE, ); - canvas.copy(item.album.artwork(), None, thumbnail_rect).unwrap(); + canvas + .copy(item.album.artwork(), None, thumbnail_rect) + .unwrap(); } } @@ -551,19 +620,33 @@ fn main() { if let Some(u_dragged_item) = dragged_item.as_ref() { const DRAG_SPEED_MULTIPLIER: f32 = 0.6; - let target_pos = mouse_state.pos() - Point::new(THUMBNAIL_SIZE_DRAG as i32 / 2, THUMBNAIL_SIZE_DRAG as i32 / 2); - let direction = [target_pos.x() as f32 - dragged_item_pos[0], target_pos.y() as f32 - dragged_item_pos[1]]; - let velocity = [direction[0] * DRAG_SPEED_MULTIPLIER, direction[1] * DRAG_SPEED_MULTIPLIER]; - - dragged_item_pos = [dragged_item_pos[0] + velocity[0], dragged_item_pos[1] + velocity[1]]; + let target_pos = mouse_state.pos() + - Point::new( + THUMBNAIL_SIZE_DRAG as i32 / 2, + THUMBNAIL_SIZE_DRAG as i32 / 2, + ); + let direction = [ + target_pos.x() as f32 - dragged_item_pos[0], + target_pos.y() as f32 - dragged_item_pos[1], + ]; + let velocity = [ + direction[0] * DRAG_SPEED_MULTIPLIER, + direction[1] * DRAG_SPEED_MULTIPLIER, + ]; + + dragged_item_pos = [ + dragged_item_pos[0] + velocity[0], + dragged_item_pos[1] + velocity[1], + ]; let dragged_item_rect = Rect::new( dragged_item_pos[0] as i32, dragged_item_pos[1] as i32, - THUMBNAIL_SIZE_DRAG, + THUMBNAIL_SIZE_DRAG, THUMBNAIL_SIZE_DRAG, ); - canvas.copy(u_dragged_item.album.artwork(), None, dragged_item_rect).unwrap(); - + canvas + .copy(u_dragged_item.album.artwork(), None, dragged_item_rect) + .unwrap(); } else if window_input_focus && window_rect.contains_point(mouse_state.pos()) { // Enlarge the album artwork that the user is hovering over let target_row = album_view_rows.get_mut(hovered_album_loc[1]); @@ -571,42 +654,54 @@ fn main() { if let Some(item) = target_row.and_then(|r| r.get(hovered_album_loc[0])) { if item.x_vel.abs() < 0.1 && matches!(item.state, ItemState::Default) { let thumbnail_rect = Rect::new( - item.x_pos as i32 - THUMBNAIL_SCALE_AMT_HOVER as i32 / 2, - I_THUMBNAIL_SIZE * hovered_album_loc[1] as i32 - THUMBNAIL_SCALE_AMT_HOVER as i32 / 2, - THUMBNAIL_SIZE + THUMBNAIL_SCALE_AMT_HOVER, + item.x_pos as i32 - THUMBNAIL_SCALE_AMT_HOVER as i32 / 2, + I_THUMBNAIL_SIZE * hovered_album_loc[1] as i32 + - THUMBNAIL_SCALE_AMT_HOVER as i32 / 2, + THUMBNAIL_SIZE + THUMBNAIL_SCALE_AMT_HOVER, THUMBNAIL_SIZE + THUMBNAIL_SCALE_AMT_HOVER, ); - canvas.copy(item.album.artwork(), None, thumbnail_rect).unwrap(); + canvas + .copy(item.album.artwork(), None, thumbnail_rect) + .unwrap(); } } } - buttons.get_mut("queue").unwrap().texture_default = &icon_textures_default["queue_closed.png"]; - buttons.get_mut("queue").unwrap().texture_hover = &icon_textures_hover["queue_open.png"]; - buttons.get_mut("queue").unwrap().texture_pressed = &icon_textures_hover["queue_open.png"]; + buttons.get_mut("queue").unwrap().texture_default = + &icon_textures_default["queue_closed.png"]; + buttons.get_mut("queue").unwrap().texture_hover = + &icon_textures_hover["queue_open.png"]; + buttons.get_mut("queue").unwrap().texture_pressed = + &icon_textures_hover["queue_open.png"]; for i in 0..queueing_albums.len() { - buttons.get_mut("queue").unwrap().texture_default = &icon_textures_default["queue_open.png"]; + buttons.get_mut("queue").unwrap().texture_default = + &icon_textures_default["queue_open.png"]; queueing_albums[i].update(0.0); if let Some((pos, scale)) = queueing_albums[i].get_anim_pos_and_scale() { let scale = (THUMBNAIL_SIZE as f32 * scale) as u32; let thumbnail_rect = Rect::new( pos[0] as i32 - scale as i32 / 2, - pos[1] as i32 - scale as i32 / 2, - scale, + pos[1] as i32 - scale as i32 / 2, + scale, scale, ); - canvas.copy(queueing_albums[i].album.artwork(), None, thumbnail_rect).unwrap(); + canvas + .copy(queueing_albums[i].album.artwork(), None, thumbnail_rect) + .unwrap(); } else { queue_button_squash_frame = 2; let album = queueing_albums.remove(i).album; - osascript_requests::queue_album(album.title().to_string(), album.album_artist().to_string()); + osascript_requests::queue_album( + album.title().to_string(), + album.album_artist().to_string(), + ); album_view_queue.add(album).unwrap(); } } buttons.get_mut("minimize").unwrap().active = true; - buttons.get_mut("close").unwrap().active = true; + buttons.get_mut("close").unwrap().active = true; buttons.get_mut("miniplayer_view").unwrap().active = true; buttons.get_mut("reshuffle").unwrap().active = true; @@ -615,125 +710,171 @@ fn main() { // Squash animation for the queue button after an album is queued match queue_button_squash_frame { 2 => { - buttons.get_mut("queue").unwrap().texture_default = &icon_textures_default["queue_squashed_2.png"]; - buttons.get_mut("queue").unwrap().texture_hover = &icon_textures_hover["queue_squashed_2.png"]; - buttons.get_mut("queue").unwrap().texture_pressed = &icon_textures_hover["queue_squashed_2.png"]; + buttons.get_mut("queue").unwrap().texture_default = + &icon_textures_default["queue_squashed_2.png"]; + buttons.get_mut("queue").unwrap().texture_hover = + &icon_textures_hover["queue_squashed_2.png"]; + buttons.get_mut("queue").unwrap().texture_pressed = + &icon_textures_hover["queue_squashed_2.png"]; queue_button_squash_frame -= 1; } 1 => { - buttons.get_mut("queue").unwrap().texture_default = &icon_textures_default["queue_squashed_1.png"]; - buttons.get_mut("queue").unwrap().texture_hover = &icon_textures_hover["queue_squashed_1.png"]; - buttons.get_mut("queue").unwrap().texture_pressed = &icon_textures_hover["queue_squashed_1.png"]; + buttons.get_mut("queue").unwrap().texture_default = + &icon_textures_default["queue_squashed_1.png"]; + buttons.get_mut("queue").unwrap().texture_hover = + &icon_textures_hover["queue_squashed_1.png"]; + buttons.get_mut("queue").unwrap().texture_pressed = + &icon_textures_hover["queue_squashed_1.png"]; queue_button_squash_frame -= 1; } _ => {} } canvas.set_draw_color(Color::BLACK); - canvas.fill_rect(Rect::new(0, ARTWORK_SIZE as i32, ARTWORK_SIZE, INFO_AREA_HEIGHT)).unwrap(); + canvas + .fill_rect(Rect::new( + 0, + ARTWORK_SIZE as i32, + ARTWORK_SIZE, + INFO_AREA_HEIGHT, + )) + .unwrap(); } - // Draw info depending on the received player data let info_tex = now_playing_resources.track_resources.info_texture(); let info_qry = info_tex.query(); let art_tex = now_playing_resources.track_resources.artwork_texture(); - + if now_playing_resources.player_info.state() == PlayerState::Playing { - info_scroll_pos -= 1; + info_scroll_pos -= 1; info_scroll_pos %= info_qry.width as i32 + INFO_SPACING; } //Draw the info text, once normally and once shifted to the right for seamless looping - engine::copy_unscaled(&info_tex, - info_scroll_pos, - (ARTWORK_SIZE + INFO_PADDING) as i32, - &mut canvas - ).unwrap(); - engine::copy_unscaled(&info_tex, - info_scroll_pos + info_qry.width as i32 + INFO_SPACING, - (ARTWORK_SIZE + INFO_PADDING) as i32, - &mut canvas - ).unwrap(); + engine::copy_unscaled( + &info_tex, + info_scroll_pos, + (ARTWORK_SIZE + INFO_PADDING) as i32, + &mut canvas, + ) + .unwrap(); + engine::copy_unscaled( + &info_tex, + info_scroll_pos + info_qry.width as i32 + INFO_SPACING, + (ARTWORK_SIZE + INFO_PADDING) as i32, + &mut canvas, + ) + .unwrap(); if current_view == View::Miniplayer { // Draw the album art - canvas.copy(art_tex, None, Rect::new(0,0, - ARTWORK_SIZE, - ARTWORK_SIZE - )).unwrap(); + canvas + .copy(art_tex, None, Rect::new(0, 0, ARTWORK_SIZE, ARTWORK_SIZE)) + .unwrap(); //Draw an overlay if the user is hovering over the window //TODO: find a way to avoid nesting this if statement inside the last - if window_input_focus && window_rect.contains_point(mouse_state.pos()) || window_interaction_in_progress { + if window_input_focus && window_rect.contains_point(mouse_state.pos()) + || window_interaction_in_progress + { // Darken the cover art canvas.set_blend_mode(BlendMode::Mod); - canvas.set_draw_color(Color::RGB( 120, 120, 120)); - canvas.fill_rect(Rect::new(0, 0, ARTWORK_SIZE, ARTWORK_SIZE)).unwrap(); + canvas.set_draw_color(Color::RGB(120, 120, 120)); + canvas + .fill_rect(Rect::new(0, 0, ARTWORK_SIZE, ARTWORK_SIZE)) + .unwrap(); // Draw a progress bar canvas.set_blend_mode(BlendMode::Add); canvas.set_draw_color(Color::RGB(100, 100, 100)); - let percent_elapsed = (now_playing_resources.player_info.pos() - + if now_playing_resources.player_info.state() == PlayerState::Playing { last_snapshot_time.elapsed().as_secs_f64() } else { 0. }) + let percent_elapsed = (now_playing_resources.player_info.pos() + + if now_playing_resources.player_info.state() == PlayerState::Playing { + last_snapshot_time.elapsed().as_secs_f64() + } else { + 0. + }) / now_playing_resources.track_info.length(); - canvas.draw_line( - Point::new(0, ARTWORK_SIZE as i32 - 1), - Point::new( - (ARTWORK_SIZE as f64 * percent_elapsed) as i32, - ARTWORK_SIZE as i32 - 1 + canvas + .draw_line( + Point::new(0, ARTWORK_SIZE as i32 - 1), + Point::new( + (ARTWORK_SIZE as f64 * percent_elapsed) as i32, + ARTWORK_SIZE as i32 - 1, + ), ) - ).unwrap(); + .unwrap(); // Update button visibility based on new data buttons.get_mut("next_track").unwrap().active = true; buttons.get_mut("back_track").unwrap().active = true; buttons.get_mut("minimize").unwrap().active = true; - buttons.get_mut("close").unwrap().active = true; + buttons.get_mut("close").unwrap().active = true; - buttons.get_mut("heart_empty").unwrap().active = !now_playing_resources.track_info.loved(); - buttons.get_mut("heart_filled").unwrap().active = now_playing_resources.track_info.loved(); + buttons.get_mut("heart_empty").unwrap().active = + !now_playing_resources.track_info.loved(); + buttons.get_mut("heart_filled").unwrap().active = + now_playing_resources.track_info.loved(); buttons.get_mut("album_view").unwrap().active = true; - buttons.get_mut("play").unwrap().active = now_playing_resources.player_info.state() != PlayerState::Playing; - buttons.get_mut("pause").unwrap().active = now_playing_resources.player_info.state() == PlayerState::Playing; + buttons.get_mut("play").unwrap().active = + now_playing_resources.player_info.state() != PlayerState::Playing; + buttons.get_mut("pause").unwrap().active = + now_playing_resources.player_info.state() == PlayerState::Playing; } } // Draw each button and add its rect to the 'sub' vec if it's active, then deactivate every button sub.clear(); - for button in buttons.values() { - button.render(&mut canvas, mouse_state).unwrap(); + for button in buttons.values() { + button.render(&mut canvas, mouse_state).unwrap(); if button.active { - sub.push(raw_heap_rect(button.collision_rect.x, button.collision_rect.y, button.collision_rect.w, button.collision_rect.h)); + sub.push(raw_heap_rect( + button.collision_rect.x, + button.collision_rect.y, + button.collision_rect.w, + button.collision_rect.h, + )); } } if current_view == View::AlbumSelect { if dragged_item.is_some() { - sub.push(raw_heap_rect(0, 0, WINDOW_WIDTH as i32, WINDOW_HEIGHT as i32)); + sub.push(raw_heap_rect( + 0, + 0, + WINDOW_WIDTH as i32, + WINDOW_HEIGHT as i32, + )); } else { - sub.push(raw_heap_rect(0, 0, ARTWORK_SIZE as i32, ARTWORK_SIZE as i32)); + sub.push(raw_heap_rect( + 0, + 0, + ARTWORK_SIZE as i32, + ARTWORK_SIZE as i32, + )); } } hit_test_data.sub_len = sub.len() as c_int; hit_test_data.sub = sub.as_ptr(); - - + //Draw a border canvas.set_blend_mode(BlendMode::Mod); canvas.set_draw_color(Color::RGB(200, 200, 200)); - canvas.draw_rect(Rect::new(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT)).unwrap(); + canvas + .draw_rect(Rect::new(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT)) + .unwrap(); canvas.set_blend_mode(BlendMode::Add); canvas.set_draw_color(Color::RGB(30, 30, 30)); - canvas.draw_rect(Rect::new(1, 1, WINDOW_WIDTH-2, WINDOW_HEIGHT-2)).unwrap(); - + canvas + .draw_rect(Rect::new(1, 1, WINDOW_WIDTH - 2, WINDOW_HEIGHT - 2)) + .unwrap(); + //Present the canvas canvas.present(); thread::sleep(Duration::from_nanos(1_000_000_000u64 / 30)); } } - diff --git a/src/osascript_requests.rs b/src/osascript_requests.rs index f29773d..53d0f40 100644 --- a/src/osascript_requests.rs +++ b/src/osascript_requests.rs @@ -5,8 +5,8 @@ use std::sync::mpsc::Sender; use std::thread; use std::time::Duration; -use crate::player_data::PDOsascriptResponse; use crate::album_data::ADOsascriptResponse; +use crate::player_data::PDOsascriptResponse; type PlayerDataSender = Sender>; @@ -91,11 +91,15 @@ struct GetAlbumDataParams { cached_albums: Vec, } -/// Gets data for the album selection screen. Should only be run one time at the start of the program. +/// Gets data for the album selection screen. Should only be run one time at the start of the program. pub fn get_album_data(album_cache: Vec) -> Vec { const ALBUM_DATA_SCRIPT: &'static str = include_str!("osascript_requests/get_album_data.jxa"); let script = osascript::JavaScript::new(ALBUM_DATA_SCRIPT); - let result: Vec = script.execute_with_params(GetAlbumDataParams { cached_albums: album_cache }).unwrap(); + let result: Vec = script + .execute_with_params(GetAlbumDataParams { + cached_albums: album_cache, + }) + .unwrap(); result } @@ -110,18 +114,30 @@ pub fn queue_album(album: String, album_artist: String) { let script = osascript::JavaScript::new(ALBUM_PLAY_SCRIPT); thread::spawn(move || { - let _: () = script.execute_with_params(PlayAlbumParams { album, album_artist }).unwrap(); + let _: () = script + .execute_with_params(PlayAlbumParams { + album, + album_artist, + }) + .unwrap(); }); } pub fn make_dj_playlist() { - const MAKE_DJ_PLAYLIST_SCRIPT: &'static str = include_str!("osascript_requests/make_dj_playlist.jxa"); + const MAKE_DJ_PLAYLIST_SCRIPT: &'static str = + include_str!("osascript_requests/make_dj_playlist.jxa"); let script = osascript::JavaScript::new(MAKE_DJ_PLAYLIST_SCRIPT); - thread::spawn(move || { let _: () = script.execute().unwrap(); }); + thread::spawn(move || { + let _: () = script.execute().unwrap(); + }); } pub fn remove_dj_playlist() { - const REMOVE_DJ_PLAYLIST_SCRIPT: &'static str = include_str!("osascript_requests/remove_dj_playlist.jxa"); + const REMOVE_DJ_PLAYLIST_SCRIPT: &'static str = + include_str!("osascript_requests/remove_dj_playlist.jxa"); let script = osascript::JavaScript::new(REMOVE_DJ_PLAYLIST_SCRIPT); - thread::spawn(move || { let _: () = script.execute().unwrap(); }); -} \ No newline at end of file + thread::spawn(move || { + let _: () = script.execute().unwrap(); + }); +} + diff --git a/xcode/.rustc_info.json b/xcode/.rustc_info.json new file mode 100644 index 0000000..887291f --- /dev/null +++ b/xcode/.rustc_info.json @@ -0,0 +1 @@ +{"rustc_fingerprint":2593556335313470915,"outputs":{"15729799797837862367":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/breitnw/.rustup/toolchains/stable-aarch64-apple-darwin\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"vh\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""},"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.68.2 (9eb3afe9e 2023-03-27)\nbinary: rustc\ncommit-hash: 9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0\ncommit-date: 2023-03-27\nhost: aarch64-apple-darwin\nrelease: 1.68.2\nLLVM version: 15.0.6\n","stderr":""}},"successes":{}} \ No newline at end of file diff --git a/xcode/Assets.xcassets/AppIcon.appiconset/168421204612031029-1 1.png b/xcode/Assets.xcassets/AppIcon.appiconset/168421204612031029-1 1.png new file mode 100644 index 0000000..82cd72f Binary files /dev/null and b/xcode/Assets.xcassets/AppIcon.appiconset/168421204612031029-1 1.png differ diff --git a/xcode/Assets.xcassets/AppIcon.appiconset/168421204612031029-1.png b/xcode/Assets.xcassets/AppIcon.appiconset/168421204612031029-1.png new file mode 100644 index 0000000..82cd72f Binary files /dev/null and b/xcode/Assets.xcassets/AppIcon.appiconset/168421204612031029-1.png differ diff --git a/xcode/Assets.xcassets/AppIcon.appiconset/168421204612031029-2.png b/xcode/Assets.xcassets/AppIcon.appiconset/168421204612031029-2.png new file mode 100644 index 0000000..13ad05e Binary files /dev/null and b/xcode/Assets.xcassets/AppIcon.appiconset/168421204612031029-2.png differ diff --git a/xcode/Assets.xcassets/AppIcon.appiconset/168421204612031029.png b/xcode/Assets.xcassets/AppIcon.appiconset/168421204612031029.png new file mode 100644 index 0000000..61dc34d Binary files /dev/null and b/xcode/Assets.xcassets/AppIcon.appiconset/168421204612031029.png differ diff --git a/xcode/Assets.xcassets/AppIcon.appiconset/168421208972575398.png b/xcode/Assets.xcassets/AppIcon.appiconset/168421208972575398.png new file mode 100644 index 0000000..a9a7f90 Binary files /dev/null and b/xcode/Assets.xcassets/AppIcon.appiconset/168421208972575398.png differ diff --git a/xcode/Assets.xcassets/AppIcon.appiconset/Contents.json b/xcode/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d3336e1 --- /dev/null +++ b/xcode/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "filename" : "168421204612031029-2.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "filename" : "168421204612031029-1 1.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "filename" : "168421204612031029-1.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "filename" : "168421204612031029.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "filename" : "168421208972575398.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "filename" : "app_256x256x32 1.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "filename" : "app_256x256x32.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "filename" : "app_512x512x32 1.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "filename" : "app_512x512x32.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "filename" : "app_1024x1024x32.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/xcode/Assets.xcassets/AppIcon.appiconset/app_1024x1024x32.png b/xcode/Assets.xcassets/AppIcon.appiconset/app_1024x1024x32.png new file mode 100644 index 0000000..066771a Binary files /dev/null and b/xcode/Assets.xcassets/AppIcon.appiconset/app_1024x1024x32.png differ diff --git a/xcode/Assets.xcassets/AppIcon.appiconset/app_256x256x32 1.png b/xcode/Assets.xcassets/AppIcon.appiconset/app_256x256x32 1.png new file mode 100644 index 0000000..14ca1f1 Binary files /dev/null and b/xcode/Assets.xcassets/AppIcon.appiconset/app_256x256x32 1.png differ diff --git a/xcode/Assets.xcassets/AppIcon.appiconset/app_256x256x32.png b/xcode/Assets.xcassets/AppIcon.appiconset/app_256x256x32.png new file mode 100644 index 0000000..14ca1f1 Binary files /dev/null and b/xcode/Assets.xcassets/AppIcon.appiconset/app_256x256x32.png differ diff --git a/xcode/Assets.xcassets/AppIcon.appiconset/app_512x512x32 1.png b/xcode/Assets.xcassets/AppIcon.appiconset/app_512x512x32 1.png new file mode 100644 index 0000000..9321364 Binary files /dev/null and b/xcode/Assets.xcassets/AppIcon.appiconset/app_512x512x32 1.png differ diff --git a/xcode/Assets.xcassets/AppIcon.appiconset/app_512x512x32.png b/xcode/Assets.xcassets/AppIcon.appiconset/app_512x512x32.png new file mode 100644 index 0000000..9321364 Binary files /dev/null and b/xcode/Assets.xcassets/AppIcon.appiconset/app_512x512x32.png differ diff --git a/xcode/Assets.xcassets/Contents.json b/xcode/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/xcode/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/xcode/Info.plist b/xcode/Info.plist new file mode 100644 index 0000000..97f945f --- /dev/null +++ b/xcode/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2023 Nick Breitling. All rights reserved. + NSPrincipalClass + NSApplication + RustBinaryName + bin/micromusic + + diff --git a/xcode/bin/micromusic b/xcode/bin/micromusic new file mode 100755 index 0000000..aee314e Binary files /dev/null and b/xcode/bin/micromusic differ diff --git a/xcode/build_xcode.sh b/xcode/build_xcode.sh new file mode 100644 index 0000000..54ef0eb --- /dev/null +++ b/xcode/build_xcode.sh @@ -0,0 +1,3 @@ +cargo build --release +mv target/release/micromusic micromusic-xcode/bin/ +dylibbundler -od -b -x micromusic-xcode/bin/micromusic -d micromusic-xcode/libs \ No newline at end of file diff --git a/xcode/libs/libSDL2-2.0.0.dylib b/xcode/libs/libSDL2-2.0.0.dylib new file mode 100644 index 0000000..c0c18dd Binary files /dev/null and b/xcode/libs/libSDL2-2.0.0.dylib differ diff --git a/xcode/libs/libSDL2_image-2.0.0.dylib b/xcode/libs/libSDL2_image-2.0.0.dylib new file mode 100644 index 0000000..7455541 Binary files /dev/null and b/xcode/libs/libSDL2_image-2.0.0.dylib differ diff --git a/xcode/libs/libaom.3.6.1.dylib b/xcode/libs/libaom.3.6.1.dylib new file mode 100644 index 0000000..c0923d4 Binary files /dev/null and b/xcode/libs/libaom.3.6.1.dylib differ diff --git a/xcode/libs/libavif.15.0.1.dylib b/xcode/libs/libavif.15.0.1.dylib new file mode 100644 index 0000000..59691c3 Binary files /dev/null and b/xcode/libs/libavif.15.0.1.dylib differ diff --git a/xcode/libs/libbrotlicommon.1.0.9.dylib b/xcode/libs/libbrotlicommon.1.0.9.dylib new file mode 100644 index 0000000..7d62265 Binary files /dev/null and b/xcode/libs/libbrotlicommon.1.0.9.dylib differ diff --git a/xcode/libs/libbrotlidec.1.0.9.dylib b/xcode/libs/libbrotlidec.1.0.9.dylib new file mode 100644 index 0000000..4e95cf3 Binary files /dev/null and b/xcode/libs/libbrotlidec.1.0.9.dylib differ diff --git a/xcode/libs/libbrotlienc.1.0.9.dylib b/xcode/libs/libbrotlienc.1.0.9.dylib new file mode 100644 index 0000000..7aabf38 Binary files /dev/null and b/xcode/libs/libbrotlienc.1.0.9.dylib differ diff --git a/xcode/libs/libhwy.1.0.4.dylib b/xcode/libs/libhwy.1.0.4.dylib new file mode 100644 index 0000000..78637bb Binary files /dev/null and b/xcode/libs/libhwy.1.0.4.dylib differ diff --git a/xcode/libs/libjpeg.8.2.2.dylib b/xcode/libs/libjpeg.8.2.2.dylib new file mode 100644 index 0000000..a873c8f Binary files /dev/null and b/xcode/libs/libjpeg.8.2.2.dylib differ diff --git a/xcode/libs/libjxl.0.8.1.dylib b/xcode/libs/libjxl.0.8.1.dylib new file mode 100644 index 0000000..66af585 Binary files /dev/null and b/xcode/libs/libjxl.0.8.1.dylib differ diff --git a/xcode/libs/liblcms2.2.dylib b/xcode/libs/liblcms2.2.dylib new file mode 100644 index 0000000..03f0a58 Binary files /dev/null and b/xcode/libs/liblcms2.2.dylib differ diff --git a/xcode/libs/liblzma.5.dylib b/xcode/libs/liblzma.5.dylib new file mode 100644 index 0000000..bce0da7 Binary files /dev/null and b/xcode/libs/liblzma.5.dylib differ diff --git a/xcode/libs/libpng16.16.dylib b/xcode/libs/libpng16.16.dylib new file mode 100644 index 0000000..bf82d0e Binary files /dev/null and b/xcode/libs/libpng16.16.dylib differ diff --git a/xcode/libs/libsharpyuv.0.0.0.dylib b/xcode/libs/libsharpyuv.0.0.0.dylib new file mode 100644 index 0000000..35c2a8d Binary files /dev/null and b/xcode/libs/libsharpyuv.0.0.0.dylib differ diff --git a/xcode/libs/libtiff.6.dylib b/xcode/libs/libtiff.6.dylib new file mode 100644 index 0000000..3fc9531 Binary files /dev/null and b/xcode/libs/libtiff.6.dylib differ diff --git a/xcode/libs/libvmaf.1.dylib b/xcode/libs/libvmaf.1.dylib new file mode 100644 index 0000000..8b999e3 Binary files /dev/null and b/xcode/libs/libvmaf.1.dylib differ diff --git a/xcode/libs/libwebp.7.1.6.dylib b/xcode/libs/libwebp.7.1.6.dylib new file mode 100644 index 0000000..139acf9 Binary files /dev/null and b/xcode/libs/libwebp.7.1.6.dylib differ diff --git a/xcode/libs/libzstd.1.5.5.dylib b/xcode/libs/libzstd.1.5.5.dylib new file mode 100644 index 0000000..c8c1d74 Binary files /dev/null and b/xcode/libs/libzstd.1.5.5.dylib differ diff --git a/xcode/main.swift b/xcode/main.swift new file mode 100644 index 0000000..472adfa --- /dev/null +++ b/xcode/main.swift @@ -0,0 +1,30 @@ +import Cocoa + +func log(_ data: Data) { + if let message = NSString(data: data, encoding: String.Encoding.utf8.rawValue) { + NSLog("%@", message) + } +} + +let task = Process() +let bundle = Bundle.main +let rustBinName = bundle.infoDictionary?["RustBinaryName"] as! String +task.launchPath = bundle.path(forResource: rustBinName, ofType: nil) +task.environment = ["RUST_BACKTRACE": "1"] + +let stdOut = Pipe() +let stdErr = Pipe() + +stdOut.fileHandleForReading.readabilityHandler = { log($0.availableData) } +stdErr.fileHandleForReading.readabilityHandler = { log($0.availableData) } + +task.standardOutput = stdOut +task.standardError = stdErr + +task.terminationHandler = { task in + (task.standardOutput as AnyObject?)?.fileHandleForReading.readabilityHandler = nil + (task.standardError as AnyObject?)?.fileHandleForReading.readabilityHandler = nil +} + +task.launch() +task.waitUntilExit() diff --git a/xcode/micromusic.xcodeproj/project.pbxproj b/xcode/micromusic.xcodeproj/project.pbxproj new file mode 100644 index 0000000..12f0de4 --- /dev/null +++ b/xcode/micromusic.xcodeproj/project.pbxproj @@ -0,0 +1,360 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 53; + objects = { + +/* Begin PBXBuildFile section */ + 8ADFC72B1DD67B670080DCCC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8ADFC72A1DD67B670080DCCC /* Assets.xcassets */; }; + 8ADFC7361DD67B950080DCCC /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8ADFC7351DD67B950080DCCC /* main.swift */; }; + 99A1640C2A1B265600253314 /* bin in Resources */ = {isa = PBXBuildFile; fileRef = 99A1640B2A1B265600253314 /* bin */; }; + 99A164262A1B29E600253314 /* libs in Resources */ = {isa = PBXBuildFile; fileRef = 99A164252A1B29E600253314 /* libs */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 993017972A1B1D0B003B89BE /* Embed Libraries */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Libraries"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 8ADFC7251DD67B670080DCCC /* micromusic.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = micromusic.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 8ADFC72A1DD67B670080DCCC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = SOURCE_ROOT; }; + 8ADFC72F1DD67B670080DCCC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; + 8ADFC7351DD67B950080DCCC /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = SOURCE_ROOT; }; + 99A1640B2A1B265600253314 /* bin */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = bin; sourceTree = SOURCE_ROOT; }; + 99A164252A1B29E600253314 /* libs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = libs; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8ADFC7221DD67B670080DCCC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8ADFC71C1DD67B670080DCCC = { + isa = PBXGroup; + children = ( + 8ADFC72A1DD67B670080DCCC /* Assets.xcassets */, + 8ADFC72F1DD67B670080DCCC /* Info.plist */, + 8ADFC7351DD67B950080DCCC /* main.swift */, + 99A164252A1B29E600253314 /* libs */, + 99A1640B2A1B265600253314 /* bin */, + 8ADFC7261DD67B670080DCCC /* Products */, + 99A164202A1B294500253314 /* Frameworks */, + ); + sourceTree = ""; + }; + 8ADFC7261DD67B670080DCCC /* Products */ = { + isa = PBXGroup; + children = ( + 8ADFC7251DD67B670080DCCC /* micromusic.app */, + ); + name = Products; + sourceTree = ""; + }; + 99A164202A1B294500253314 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8ADFC7241DD67B670080DCCC /* micromusic */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8ADFC7321DD67B670080DCCC /* Build configuration list for PBXNativeTarget "micromusic" */; + buildPhases = ( + 8ADFC7211DD67B670080DCCC /* Sources */, + 8ADFC7221DD67B670080DCCC /* Frameworks */, + 8ADFC7231DD67B670080DCCC /* Resources */, + 993017972A1B1D0B003B89BE /* Embed Libraries */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = micromusic; + productName = RustPack; + productReference = 8ADFC7251DD67B670080DCCC /* micromusic.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8ADFC71D1DD67B670080DCCC /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0800; + LastUpgradeCheck = 1430; + ORGANIZATIONNAME = breitnw; + TargetAttributes = { + 8ADFC7241DD67B670080DCCC = { + CreatedOnToolsVersion = 8.0; + LastSwiftMigration = ""; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 8ADFC7201DD67B670080DCCC /* Build configuration list for PBXProject "micromusic" */; + compatibilityVersion = "Xcode 10.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 8ADFC71C1DD67B670080DCCC; + productRefGroup = 8ADFC7261DD67B670080DCCC /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8ADFC7241DD67B670080DCCC /* micromusic */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8ADFC7231DD67B670080DCCC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 99A1640C2A1B265600253314 /* bin in Resources */, + 99A164262A1B29E600253314 /* libs in Resources */, + 8ADFC72B1DD67B670080DCCC /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8ADFC7211DD67B670080DCCC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8ADFC7361DD67B950080DCCC /* main.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 8ADFC7301DD67B670080DCCC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 8ADFC7311DD67B670080DCCC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 8ADFC7331DD67B670080DCCC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = arm64; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = PPLGT4R3H9; + INFOPLIST_FILE = Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = micromusic; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.music"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/libs", + ); + MACOSX_DEPLOYMENT_TARGET = 12.0; + MARKETING_VERSION = "v0.2.1-beta"; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.breitnw.micromusic; + PRODUCT_NAME = "$(TARGET_NAME)"; + REEXPORTED_LIBRARY_PATHS = ""; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 8ADFC7341DD67B670080DCCC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = arm64; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = PPLGT4R3H9; + INFOPLIST_FILE = Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = micromusic; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.music"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/libs", + ); + MACOSX_DEPLOYMENT_TARGET = 12.0; + MARKETING_VERSION = "v0.2.1-beta"; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.breitnw.micromusic; + PRODUCT_NAME = "$(TARGET_NAME)"; + REEXPORTED_LIBRARY_PATHS = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8ADFC7201DD67B670080DCCC /* Build configuration list for PBXProject "micromusic" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8ADFC7301DD67B670080DCCC /* Debug */, + 8ADFC7311DD67B670080DCCC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8ADFC7321DD67B670080DCCC /* Build configuration list for PBXNativeTarget "micromusic" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8ADFC7331DD67B670080DCCC /* Debug */, + 8ADFC7341DD67B670080DCCC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8ADFC71D1DD67B670080DCCC /* Project object */; +} diff --git a/xcode/micromusic.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/xcode/micromusic.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..bb20687 --- /dev/null +++ b/xcode/micromusic.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/xcode/micromusic.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/xcode/micromusic.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/xcode/micromusic.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/xcode/micromusic.xcodeproj/project.xcworkspace/xcuserdata/breitnw.xcuserdatad/UserInterfaceState.xcuserstate b/xcode/micromusic.xcodeproj/project.xcworkspace/xcuserdata/breitnw.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..e0f6b77 Binary files /dev/null and b/xcode/micromusic.xcodeproj/project.xcworkspace/xcuserdata/breitnw.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/xcode/micromusic.xcodeproj/xcshareddata/xcschemes/micromusic.xcscheme b/xcode/micromusic.xcodeproj/xcshareddata/xcschemes/micromusic.xcscheme new file mode 100644 index 0000000..60363c8 --- /dev/null +++ b/xcode/micromusic.xcodeproj/xcshareddata/xcschemes/micromusic.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xcode/micromusic.xcodeproj/xcuserdata/breitnw.xcuserdatad/xcschemes/xcschememanagement.plist b/xcode/micromusic.xcodeproj/xcuserdata/breitnw.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..0241c9f --- /dev/null +++ b/xcode/micromusic.xcodeproj/xcuserdata/breitnw.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,8 @@ + + + + + SchemeUserState + + +