chore: macros

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2025-10-19 12:56:54 +01:00
parent 8120690caa
commit b9dec53c0d
6 changed files with 173 additions and 615 deletions

7
Cargo.lock generated
View File

@@ -242,6 +242,7 @@ dependencies = [
"log",
"log4rs",
"num_enum",
"paste",
"ptp_cursor",
"ptp_macro",
"rusb",
@@ -502,6 +503,12 @@ dependencies = [
"windows-link",
]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pkg-config"
version = "0.3.32"

View File

@@ -28,3 +28,4 @@ ptp_macro = { path = "crates/ptp/macro" }
ptp_cursor = { path = "crates/ptp/cursor" }
strum = { version = "0.27.2", features = ["strum_macros"] }
strum_macros = "0.27.2"
paste = "1.0.15"

View File

@@ -216,7 +216,7 @@ pub trait PtpDeserialize: Sized {
fn try_read_ptp<R: Read>(cur: &mut R) -> io::Result<Self>;
}
macro_rules! impl_ptp_ser {
macro_rules! ptp_ser {
($ty:ty, $read_fn:ident, $write_fn:ident) => {
impl PtpSerialize for $ty {
fn try_into_ptp(&self) -> io::Result<Vec<u8>> {
@@ -232,7 +232,7 @@ macro_rules! impl_ptp_ser {
};
}
macro_rules! impl_ptp_de {
macro_rules! ptp_de {
($ty:ty, $read_fn:ident, $write_fn:ident) => {
impl PtpDeserialize for $ty {
fn try_from_ptp(buf: &[u8]) -> io::Result<Self> {
@@ -249,38 +249,38 @@ macro_rules! impl_ptp_de {
};
}
impl_ptp_ser!(u8, read_ptp_u8, write_ptp_u8);
impl_ptp_de!(u8, read_ptp_u8, write_ptp_u8);
impl_ptp_ser!(i8, read_ptp_i8, write_ptp_i8);
impl_ptp_de!(i8, read_ptp_i8, write_ptp_i8);
impl_ptp_ser!(u16, read_ptp_u16, write_ptp_u16);
impl_ptp_de!(u16, read_ptp_u16, write_ptp_u16);
impl_ptp_ser!(i16, read_ptp_i16, write_ptp_i16);
impl_ptp_de!(i16, read_ptp_i16, write_ptp_i16);
impl_ptp_ser!(u32, read_ptp_u32, write_ptp_u32);
impl_ptp_de!(u32, read_ptp_u32, write_ptp_u32);
impl_ptp_ser!(i32, read_ptp_i32, write_ptp_i32);
impl_ptp_de!(i32, read_ptp_i32, write_ptp_i32);
impl_ptp_ser!(u64, read_ptp_u64, write_ptp_u64);
impl_ptp_de!(u64, read_ptp_u64, write_ptp_u64);
impl_ptp_ser!(i64, read_ptp_i64, write_ptp_i64);
impl_ptp_de!(i64, read_ptp_i64, write_ptp_i64);
impl_ptp_ser!(&str, read_ptp_str, write_ptp_str);
impl_ptp_ser!(String, read_ptp_str, write_ptp_str);
impl_ptp_de!(String, read_ptp_str, write_ptp_str);
impl_ptp_ser!(Vec<u8>, read_ptp_u8_vec, write_ptp_u8_vec);
impl_ptp_de!(Vec<u8>, read_ptp_u8_vec, write_ptp_u8_vec);
impl_ptp_ser!(Vec<i8>, read_ptp_i8_vec, write_ptp_i8_vec);
impl_ptp_de!(Vec<i8>, read_ptp_i8_vec, write_ptp_i8_vec);
impl_ptp_ser!(Vec<u16>, read_ptp_u16_vec, write_ptp_u16_vec);
impl_ptp_de!(Vec<u16>, read_ptp_u16_vec, write_ptp_u16_vec);
impl_ptp_ser!(Vec<i16>, read_ptp_i16_vec, write_ptp_i16_vec);
impl_ptp_de!(Vec<i16>, read_ptp_i16_vec, write_ptp_i16_vec);
impl_ptp_ser!(Vec<u32>, read_ptp_u32_vec, write_ptp_u32_vec);
impl_ptp_de!(Vec<u32>, read_ptp_u32_vec, write_ptp_u32_vec);
impl_ptp_ser!(Vec<i32>, read_ptp_i32_vec, write_ptp_i32_vec);
impl_ptp_de!(Vec<i32>, read_ptp_i32_vec, write_ptp_i32_vec);
impl_ptp_ser!(Vec<u64>, read_ptp_u64_vec, write_ptp_u64_vec);
impl_ptp_de!(Vec<u64>, read_ptp_u64_vec, write_ptp_u64_vec);
impl_ptp_ser!(Vec<i64>, read_ptp_i64_vec, write_ptp_i64_vec);
impl_ptp_de!(Vec<i64>, read_ptp_i64_vec, write_ptp_i64_vec);
ptp_ser!(u8, read_ptp_u8, write_ptp_u8);
ptp_de!(u8, read_ptp_u8, write_ptp_u8);
ptp_ser!(i8, read_ptp_i8, write_ptp_i8);
ptp_de!(i8, read_ptp_i8, write_ptp_i8);
ptp_ser!(u16, read_ptp_u16, write_ptp_u16);
ptp_de!(u16, read_ptp_u16, write_ptp_u16);
ptp_ser!(i16, read_ptp_i16, write_ptp_i16);
ptp_de!(i16, read_ptp_i16, write_ptp_i16);
ptp_ser!(u32, read_ptp_u32, write_ptp_u32);
ptp_de!(u32, read_ptp_u32, write_ptp_u32);
ptp_ser!(i32, read_ptp_i32, write_ptp_i32);
ptp_de!(i32, read_ptp_i32, write_ptp_i32);
ptp_ser!(u64, read_ptp_u64, write_ptp_u64);
ptp_de!(u64, read_ptp_u64, write_ptp_u64);
ptp_ser!(i64, read_ptp_i64, write_ptp_i64);
ptp_de!(i64, read_ptp_i64, write_ptp_i64);
ptp_ser!(&str, read_ptp_str, write_ptp_str);
ptp_ser!(String, read_ptp_str, write_ptp_str);
ptp_de!(String, read_ptp_str, write_ptp_str);
ptp_ser!(Vec<u8>, read_ptp_u8_vec, write_ptp_u8_vec);
ptp_de!(Vec<u8>, read_ptp_u8_vec, write_ptp_u8_vec);
ptp_ser!(Vec<i8>, read_ptp_i8_vec, write_ptp_i8_vec);
ptp_de!(Vec<i8>, read_ptp_i8_vec, write_ptp_i8_vec);
ptp_ser!(Vec<u16>, read_ptp_u16_vec, write_ptp_u16_vec);
ptp_de!(Vec<u16>, read_ptp_u16_vec, write_ptp_u16_vec);
ptp_ser!(Vec<i16>, read_ptp_i16_vec, write_ptp_i16_vec);
ptp_de!(Vec<i16>, read_ptp_i16_vec, write_ptp_i16_vec);
ptp_ser!(Vec<u32>, read_ptp_u32_vec, write_ptp_u32_vec);
ptp_de!(Vec<u32>, read_ptp_u32_vec, write_ptp_u32_vec);
ptp_ser!(Vec<i32>, read_ptp_i32_vec, write_ptp_i32_vec);
ptp_de!(Vec<i32>, read_ptp_i32_vec, write_ptp_i32_vec);
ptp_ser!(Vec<u64>, read_ptp_u64_vec, write_ptp_u64_vec);
ptp_de!(Vec<u64>, read_ptp_u64_vec, write_ptp_u64_vec);
ptp_ser!(Vec<i64>, read_ptp_i64_vec, write_ptp_i64_vec);
ptp_de!(Vec<i64>, read_ptp_i64_vec, write_ptp_i64_vec);

View File

@@ -27,8 +27,26 @@ use crate::usb::find_endpoint;
const SESSION: u32 = 1;
pub struct Camera {
r#impl: Box<dyn CameraImpl<GlobalContext>>,
ptp: Ptp,
pub r#impl: Box<dyn CameraImpl<GlobalContext>>,
pub ptp: Ptp,
}
macro_rules! camera_custom_settings {
($( $name:ident : $type:ty => $code:expr ),+ $(,)?) => {
$(
paste::paste! {
#[allow(dead_code)]
pub fn [<get_ $name>](&mut self) -> anyhow::Result<$type> {
self.r#impl.[<get_ $name>](&mut self.ptp)
}
#[allow(dead_code)]
pub fn [<set_ $name>](&mut self, value: &$type) -> anyhow::Result<()> {
self.r#impl.[<set_ $name>](&mut self.ptp, value)
}
}
)+
};
}
impl Camera {
@@ -88,183 +106,28 @@ impl Camera {
self.r#impl.import_backup(&mut self.ptp, backup)
}
pub fn set_active_custom_setting(&mut self, slot: FujiCustomSetting) -> anyhow::Result<()> {
self.r#impl.set_custom_setting_slot(&mut self.ptp, slot)
}
pub fn get_custom_setting_name(&mut self) -> anyhow::Result<FujiCustomSettingName> {
self.r#impl.get_custom_setting_name(&mut self.ptp)
}
pub fn set_custom_setting_name(&mut self, value: &str) -> anyhow::Result<()> {
self.r#impl.set_custom_setting_name(&mut self.ptp, value)
}
pub fn get_image_size(&mut self) -> anyhow::Result<FujiImageSize> {
self.r#impl.get_image_size(&mut self.ptp)
}
pub fn set_image_size(&mut self, value: FujiImageSize) -> anyhow::Result<()> {
self.r#impl.set_image_size(&mut self.ptp, value)
}
pub fn get_image_quality(&mut self) -> anyhow::Result<FujiImageQuality> {
self.r#impl.get_image_quality(&mut self.ptp)
}
pub fn set_image_quality(&mut self, value: FujiImageQuality) -> anyhow::Result<()> {
self.r#impl.set_image_quality(&mut self.ptp, value)
}
pub fn get_dynamic_range(&mut self) -> anyhow::Result<FujiDynamicRange> {
self.r#impl.get_dynamic_range(&mut self.ptp)
}
pub fn set_dynamic_range(&mut self, value: FujiDynamicRange) -> anyhow::Result<()> {
self.r#impl.set_dynamic_range(&mut self.ptp, value)
}
pub fn get_dynamic_range_priority(&mut self) -> anyhow::Result<FujiDynamicRangePriority> {
self.r#impl.get_dynamic_range_priority(&mut self.ptp)
}
pub fn set_dynamic_range_priority(
&mut self,
value: FujiDynamicRangePriority,
) -> anyhow::Result<()> {
self.r#impl.set_dynamic_range_priority(&mut self.ptp, value)
}
pub fn get_film_simulation(&mut self) -> anyhow::Result<FujiFilmSimulation> {
self.r#impl.get_film_simulation(&mut self.ptp)
}
pub fn set_film_simulation(&mut self, value: FujiFilmSimulation) -> anyhow::Result<()> {
self.r#impl.set_film_simulation(&mut self.ptp, value)
}
pub fn get_grain_effect(&mut self) -> anyhow::Result<FujiGrainEffect> {
self.r#impl.get_grain_effect(&mut self.ptp)
}
pub fn set_grain_effect(&mut self, value: FujiGrainEffect) -> anyhow::Result<()> {
self.r#impl.set_grain_effect(&mut self.ptp, value)
}
pub fn get_white_balance(&mut self) -> anyhow::Result<FujiWhiteBalance> {
self.r#impl.get_white_balance(&mut self.ptp)
}
pub fn set_white_balance(&mut self, value: FujiWhiteBalance) -> anyhow::Result<()> {
self.r#impl.set_white_balance(&mut self.ptp, value)
}
pub fn get_high_iso_nr(&mut self) -> anyhow::Result<FujiHighISONR> {
self.r#impl.get_high_iso_nr(&mut self.ptp)
}
pub fn set_high_iso_nr(&mut self, value: FujiHighISONR) -> anyhow::Result<()> {
self.r#impl.set_high_iso_nr(&mut self.ptp, value)
}
pub fn get_highlight_tone(&mut self) -> anyhow::Result<FujiHighlightTone> {
self.r#impl.get_highlight_tone(&mut self.ptp)
}
pub fn set_highlight_tone(&mut self, value: FujiHighlightTone) -> anyhow::Result<()> {
self.r#impl.set_highlight_tone(&mut self.ptp, value)
}
pub fn get_shadow_tone(&mut self) -> anyhow::Result<FujiShadowTone> {
self.r#impl.get_shadow_tone(&mut self.ptp)
}
pub fn set_shadow_tone(&mut self, value: FujiShadowTone) -> anyhow::Result<()> {
self.r#impl.set_shadow_tone(&mut self.ptp, value)
}
pub fn get_color(&mut self) -> anyhow::Result<FujiColor> {
self.r#impl.get_color(&mut self.ptp)
}
pub fn set_color(&mut self, value: FujiColor) -> anyhow::Result<()> {
self.r#impl.set_color(&mut self.ptp, value)
}
pub fn get_sharpness(&mut self) -> anyhow::Result<FujiSharpness> {
self.r#impl.get_sharpness(&mut self.ptp)
}
pub fn set_sharpness(&mut self, value: FujiSharpness) -> anyhow::Result<()> {
self.r#impl.set_sharpness(&mut self.ptp, value)
}
pub fn get_clarity(&mut self) -> anyhow::Result<FujiClarity> {
self.r#impl.get_clarity(&mut self.ptp)
}
pub fn set_clarity(&mut self, value: FujiClarity) -> anyhow::Result<()> {
self.r#impl.set_clarity(&mut self.ptp, value)
}
pub fn get_white_balance_shift_red(&mut self) -> anyhow::Result<FujiWhiteBalanceShift> {
self.r#impl.get_white_balance_shift_red(&mut self.ptp)
}
pub fn set_white_balance_shift_red(
&mut self,
value: FujiWhiteBalanceShift,
) -> anyhow::Result<()> {
self.r#impl
.set_white_balance_shift_red(&mut self.ptp, value)
}
pub fn get_white_balance_shift_blue(&mut self) -> anyhow::Result<FujiWhiteBalanceShift> {
self.r#impl.get_white_balance_shift_blue(&mut self.ptp)
}
pub fn set_white_balance_shift_blue(
&mut self,
value: FujiWhiteBalanceShift,
) -> anyhow::Result<()> {
self.r#impl
.set_white_balance_shift_blue(&mut self.ptp, value)
}
pub fn get_white_balance_temperature(&mut self) -> anyhow::Result<FujiWhiteBalanceTemperature> {
self.r#impl.get_white_balance_temperature(&mut self.ptp)
}
pub fn set_white_balance_temperature(
&mut self,
value: FujiWhiteBalanceTemperature,
) -> anyhow::Result<()> {
self.r#impl
.set_white_balance_temperature(&mut self.ptp, value)
}
pub fn get_color_chrome_effect(&mut self) -> anyhow::Result<FujiColorChromeEffect> {
self.r#impl.get_color_chrome_effect(&mut self.ptp)
}
pub fn set_color_chrome_effect(&mut self, value: FujiColorChromeEffect) -> anyhow::Result<()> {
self.r#impl.set_color_chrome_effect(&mut self.ptp, value)
}
pub fn get_color_chrome_fx_blue(&mut self) -> anyhow::Result<FujiColorChromeFXBlue> {
self.r#impl.get_color_chrome_fx_blue(&mut self.ptp)
}
pub fn set_color_chrome_fx_blue(&mut self, value: FujiColorChromeFXBlue) -> anyhow::Result<()> {
self.r#impl.set_color_chrome_fx_blue(&mut self.ptp, value)
}
pub fn get_smooth_skin_effect(&mut self) -> anyhow::Result<FujiSmoothSkinEffect> {
self.r#impl.get_smooth_skin_effect(&mut self.ptp)
}
pub fn set_smooth_skin_effect(&mut self, value: FujiSmoothSkinEffect) -> anyhow::Result<()> {
self.r#impl.set_smooth_skin_effect(&mut self.ptp, value)
camera_custom_settings! {
active_custom_setting: FujiCustomSetting => DevicePropCode::FujiStillCustomSetting,
custom_setting_name: FujiCustomSettingName => DevicePropCode::FujiStillCustomSettingName,
image_size: FujiImageSize => DevicePropCode::FujiStillCustomSettingImageSize,
image_quality: FujiImageQuality => DevicePropCode::FujiStillCustomSettingImageQuality,
dynamic_range: FujiDynamicRange => DevicePropCode::FujiStillCustomSettingDynamicRange,
dynamic_range_priority: FujiDynamicRangePriority => DevicePropCode::FujiStillCustomSettingDynamicRangePriority,
film_simulation: FujiFilmSimulation => DevicePropCode::FujiStillCustomSettingFilmSimulation,
grain_effect: FujiGrainEffect => DevicePropCode::FujiStillCustomSettingGrainEffect,
white_balance: FujiWhiteBalance => DevicePropCode::FujiStillCustomSettingWhiteBalance,
high_iso_nr: FujiHighISONR => DevicePropCode::FujiStillCustomSettingHighISONR,
highlight_tone: FujiHighlightTone => DevicePropCode::FujiStillCustomSettingHighlightTone,
shadow_tone: FujiShadowTone => DevicePropCode::FujiStillCustomSettingShadowTone,
color: FujiColor => DevicePropCode::FujiStillCustomSettingColor,
sharpness: FujiSharpness => DevicePropCode::FujiStillCustomSettingSharpness,
clarity: FujiClarity => DevicePropCode::FujiStillCustomSettingClarity,
white_balance_shift_red: FujiWhiteBalanceShift => DevicePropCode::FujiStillCustomSettingWhiteBalanceShiftRed,
white_balance_shift_blue: FujiWhiteBalanceShift => DevicePropCode::FujiStillCustomSettingWhiteBalanceShiftBlue,
white_balance_temperature: FujiWhiteBalanceTemperature => DevicePropCode::FujiStillCustomSettingWhiteBalanceTemperature,
color_chrome_effect: FujiColorChromeEffect => DevicePropCode::FujiStillCustomSettingColorChromeEffect,
color_chrome_fx_blue: FujiColorChromeFXBlue => DevicePropCode::FujiStillCustomSettingColorChromeFXBlue,
smooth_skin_effect: FujiSmoothSkinEffect => DevicePropCode::FujiStillCustomSettingSmoothSkinEffect,
}
}
@@ -348,6 +211,28 @@ impl TryFrom<&rusb::Device<GlobalContext>> for Camera {
}
}
macro_rules! camera_impl_custom_settings {
($( $name:ident : $type:ty => $code:expr ),+ $(,)?) => {
$(
paste::paste! {
#[allow(dead_code)]
fn [<get_ $name>](&self, ptp: &mut Ptp) -> anyhow::Result<$type> {
let bytes = self.get_prop_value(ptp, $code)?;
let result = <$type>::try_from_ptp(&bytes)?;
Ok(result)
}
#[allow(dead_code)]
fn [<set_ $name>](&self, ptp: &mut Ptp, value: &$type) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(ptp, $code, &bytes)?;
Ok(())
}
}
)+
};
}
pub trait CameraImpl<P: rusb::UsbContext> {
fn supported_camera(&self) -> &'static SupportedCamera<P>;
@@ -460,363 +345,27 @@ pub trait CameraImpl<P: rusb::UsbContext> {
Ok(())
}
fn set_custom_setting_slot(
&self,
ptp: &mut Ptp,
slot: FujiCustomSetting,
) -> anyhow::Result<()> {
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSetting,
&slot.try_into_ptp()?,
)?;
Ok(())
}
fn get_custom_setting_name(&self, ptp: &mut Ptp) -> anyhow::Result<FujiCustomSettingName> {
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingName)?;
let result = FujiCustomSettingName::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_custom_setting_name(&self, ptp: &mut Ptp, value: &str) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(ptp, DevicePropCode::FujiStillCustomSettingName, &bytes)?;
Ok(())
}
fn get_image_size(&self, ptp: &mut Ptp) -> anyhow::Result<FujiImageSize> {
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingImageSize)?;
let result = FujiImageSize::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_image_size(&self, ptp: &mut Ptp, value: FujiImageSize) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(ptp, DevicePropCode::FujiStillCustomSettingImageSize, &bytes)?;
Ok(())
}
fn get_image_quality(&self, ptp: &mut Ptp) -> anyhow::Result<FujiImageQuality> {
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingImageQuality)?;
let result = FujiImageQuality::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_image_quality(&self, ptp: &mut Ptp, value: FujiImageQuality) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingImageQuality,
&bytes,
)?;
Ok(())
}
fn get_dynamic_range(&self, ptp: &mut Ptp) -> anyhow::Result<FujiDynamicRange> {
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingDynamicRange)?;
let result = FujiDynamicRange::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_dynamic_range(&self, ptp: &mut Ptp, value: FujiDynamicRange) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingDynamicRange,
&bytes,
)?;
Ok(())
}
fn get_dynamic_range_priority(
&self,
ptp: &mut Ptp,
) -> anyhow::Result<FujiDynamicRangePriority> {
let bytes = self.get_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingDynamicRangePriority,
)?;
let result = FujiDynamicRangePriority::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_dynamic_range_priority(
&self,
ptp: &mut Ptp,
value: FujiDynamicRangePriority,
) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingDynamicRangePriority,
&bytes,
)?;
Ok(())
}
fn get_film_simulation(&self, ptp: &mut Ptp) -> anyhow::Result<FujiFilmSimulation> {
let bytes =
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingFilmSimulation)?;
let result = FujiFilmSimulation::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_film_simulation(&self, ptp: &mut Ptp, value: FujiFilmSimulation) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingFilmSimulation,
&bytes,
)?;
Ok(())
}
fn get_grain_effect(&self, ptp: &mut Ptp) -> anyhow::Result<FujiGrainEffect> {
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingGrainEffect)?;
let result = FujiGrainEffect::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_grain_effect(&self, ptp: &mut Ptp, value: FujiGrainEffect) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingGrainEffect,
&bytes,
)?;
Ok(())
}
fn get_white_balance(&self, ptp: &mut Ptp) -> anyhow::Result<FujiWhiteBalance> {
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingWhiteBalance)?;
let result = FujiWhiteBalance::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_white_balance(&self, ptp: &mut Ptp, value: FujiWhiteBalance) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingWhiteBalance,
&bytes,
)?;
Ok(())
}
fn get_high_iso_nr(&self, ptp: &mut Ptp) -> anyhow::Result<FujiHighISONR> {
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingHighISONR)?;
let result = FujiHighISONR::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_high_iso_nr(&self, ptp: &mut Ptp, value: FujiHighISONR) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(ptp, DevicePropCode::FujiStillCustomSettingHighISONR, &bytes)?;
Ok(())
}
fn get_highlight_tone(&self, ptp: &mut Ptp) -> anyhow::Result<FujiHighlightTone> {
let bytes =
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingHighlightTone)?;
let result = FujiHighlightTone::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_highlight_tone(&self, ptp: &mut Ptp, value: FujiHighlightTone) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingHighlightTone,
&bytes,
)?;
Ok(())
}
fn get_shadow_tone(&self, ptp: &mut Ptp) -> anyhow::Result<FujiShadowTone> {
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingShadowTone)?;
let result = FujiShadowTone::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_shadow_tone(&self, ptp: &mut Ptp, value: FujiShadowTone) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingShadowTone,
&bytes,
)?;
Ok(())
}
fn get_color(&self, ptp: &mut Ptp) -> anyhow::Result<FujiColor> {
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingColor)?;
let result = FujiColor::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_color(&self, ptp: &mut Ptp, value: FujiColor) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(ptp, DevicePropCode::FujiStillCustomSettingColor, &bytes)?;
Ok(())
}
fn get_sharpness(&self, ptp: &mut Ptp) -> anyhow::Result<FujiSharpness> {
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingSharpness)?;
let result = FujiSharpness::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_sharpness(&self, ptp: &mut Ptp, value: FujiSharpness) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(ptp, DevicePropCode::FujiStillCustomSettingSharpness, &bytes)?;
Ok(())
}
fn get_clarity(&self, ptp: &mut Ptp) -> anyhow::Result<FujiClarity> {
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingClarity)?;
let result = FujiClarity::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_clarity(&self, ptp: &mut Ptp, value: FujiClarity) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(ptp, DevicePropCode::FujiStillCustomSettingClarity, &bytes)?;
Ok(())
}
fn get_white_balance_shift_red(&self, ptp: &mut Ptp) -> anyhow::Result<FujiWhiteBalanceShift> {
let bytes = self.get_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingWhiteBalanceShiftRed,
)?;
let result = FujiWhiteBalanceShift::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_white_balance_shift_red(
&self,
ptp: &mut Ptp,
value: FujiWhiteBalanceShift,
) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingWhiteBalanceShiftRed,
&bytes,
)?;
Ok(())
}
fn get_white_balance_shift_blue(&self, ptp: &mut Ptp) -> anyhow::Result<FujiWhiteBalanceShift> {
let bytes = self.get_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingWhiteBalanceShiftBlue,
)?;
let result = FujiWhiteBalanceShift::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_white_balance_shift_blue(
&self,
ptp: &mut Ptp,
value: FujiWhiteBalanceShift,
) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingWhiteBalanceShiftBlue,
&bytes,
)?;
Ok(())
}
fn get_white_balance_temperature(
&self,
ptp: &mut Ptp,
) -> anyhow::Result<FujiWhiteBalanceTemperature> {
let bytes = self.get_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingWhiteBalanceTemperature,
)?;
let result = FujiWhiteBalanceTemperature::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_white_balance_temperature(
&self,
ptp: &mut Ptp,
value: FujiWhiteBalanceTemperature,
) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingWhiteBalanceTemperature,
&bytes,
)?;
Ok(())
}
fn get_color_chrome_effect(&self, ptp: &mut Ptp) -> anyhow::Result<FujiColorChromeEffect> {
let bytes =
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingColorChromeEffect)?;
let result = FujiColorChromeEffect::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_color_chrome_effect(
&self,
ptp: &mut Ptp,
value: FujiColorChromeEffect,
) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingColorChromeEffect,
&bytes,
)?;
Ok(())
}
fn get_color_chrome_fx_blue(&self, ptp: &mut Ptp) -> anyhow::Result<FujiColorChromeFXBlue> {
let bytes =
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingColorChromeFXBlue)?;
let result = FujiColorChromeFXBlue::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_color_chrome_fx_blue(
&self,
ptp: &mut Ptp,
value: FujiColorChromeFXBlue,
) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingColorChromeFXBlue,
&bytes,
)?;
Ok(())
}
fn get_smooth_skin_effect(&self, ptp: &mut Ptp) -> anyhow::Result<FujiSmoothSkinEffect> {
let bytes =
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingSmoothSkinEffect)?;
let result = FujiSmoothSkinEffect::try_from_ptp(&bytes)?;
Ok(result)
}
fn set_smooth_skin_effect(
&self,
ptp: &mut Ptp,
value: FujiSmoothSkinEffect,
) -> anyhow::Result<()> {
let bytes = value.try_into_ptp()?;
self.set_prop_value(
ptp,
DevicePropCode::FujiStillCustomSettingSmoothSkinEffect,
&bytes,
)?;
Ok(())
camera_impl_custom_settings! {
active_custom_setting: FujiCustomSetting => DevicePropCode::FujiStillCustomSetting,
custom_setting_name: FujiCustomSettingName => DevicePropCode::FujiStillCustomSettingName,
image_size: FujiImageSize => DevicePropCode::FujiStillCustomSettingImageSize,
image_quality: FujiImageQuality => DevicePropCode::FujiStillCustomSettingImageQuality,
dynamic_range: FujiDynamicRange => DevicePropCode::FujiStillCustomSettingDynamicRange,
dynamic_range_priority: FujiDynamicRangePriority => DevicePropCode::FujiStillCustomSettingDynamicRangePriority,
film_simulation: FujiFilmSimulation => DevicePropCode::FujiStillCustomSettingFilmSimulation,
grain_effect: FujiGrainEffect => DevicePropCode::FujiStillCustomSettingGrainEffect,
white_balance: FujiWhiteBalance => DevicePropCode::FujiStillCustomSettingWhiteBalance,
high_iso_nr: FujiHighISONR => DevicePropCode::FujiStillCustomSettingHighISONR,
highlight_tone: FujiHighlightTone => DevicePropCode::FujiStillCustomSettingHighlightTone,
shadow_tone: FujiShadowTone => DevicePropCode::FujiStillCustomSettingShadowTone,
color: FujiColor => DevicePropCode::FujiStillCustomSettingColor,
sharpness: FujiSharpness => DevicePropCode::FujiStillCustomSettingSharpness,
clarity: FujiClarity => DevicePropCode::FujiStillCustomSettingClarity,
white_balance_shift_red: FujiWhiteBalanceShift => DevicePropCode::FujiStillCustomSettingWhiteBalanceShiftRed,
white_balance_shift_blue: FujiWhiteBalanceShift => DevicePropCode::FujiStillCustomSettingWhiteBalanceShiftBlue,
white_balance_temperature: FujiWhiteBalanceTemperature => DevicePropCode::FujiStillCustomSettingWhiteBalanceTemperature,
color_chrome_effect: FujiColorChromeEffect => DevicePropCode::FujiStillCustomSettingColorChromeEffect,
color_chrome_fx_blue: FujiColorChromeFXBlue => DevicePropCode::FujiStillCustomSettingColorChromeFXBlue,
smooth_skin_effect: FujiSmoothSkinEffect => DevicePropCode::FujiStillCustomSettingSmoothSkinEffect,
}
}

View File

@@ -1095,7 +1095,7 @@ impl FromStr for FujiHighISONR {
}
}
macro_rules! define_fuji_i16 {
macro_rules! fuji_i16 {
($name:ident, $min:expr, $max:expr, $step:expr, $scale:literal) => {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PtpSerialize, PtpDeserialize)]
pub struct $name(i16);
@@ -1192,13 +1192,13 @@ macro_rules! define_fuji_i16 {
};
}
define_fuji_i16!(FujiWhiteBalanceShift, -9.0, 9.0, 1.0, 1i16);
define_fuji_i16!(FujiWhiteBalanceTemperature, 2500.0, 10000.0, 10.0, 1i16);
define_fuji_i16!(FujiHighlightTone, -2.0, 4.0, 0.5, 10i16);
define_fuji_i16!(FujiShadowTone, -2.0, 4.0, 0.5, 10i16);
define_fuji_i16!(FujiColor, -4.0, 4.0, 1.0, 10i16);
define_fuji_i16!(FujiSharpness, -4.0, 4.0, 1.0, 10i16);
define_fuji_i16!(FujiClarity, -5.0, 5.0, 1.0, 10i16);
fuji_i16!(FujiWhiteBalanceShift, -9.0, 9.0, 1.0, 1i16);
fuji_i16!(FujiWhiteBalanceTemperature, 2500.0, 10000.0, 10.0, 1i16);
fuji_i16!(FujiHighlightTone, -2.0, 4.0, 0.5, 10i16);
fuji_i16!(FujiShadowTone, -2.0, 4.0, 0.5, 10i16);
fuji_i16!(FujiColor, -4.0, 4.0, 1.0, 10i16);
fuji_i16!(FujiSharpness, -4.0, 4.0, 1.0, 10i16);
fuji_i16!(FujiClarity, -5.0, 5.0, 1.0, 10i16);
#[repr(u16)]
#[derive(

View File

@@ -81,7 +81,7 @@ fn handle_list(json: bool, device_id: Option<&str>) -> anyhow::Result<()> {
let mut slots = Vec::new();
for slot in FujiCustomSetting::iter() {
camera.set_active_custom_setting(slot)?;
camera.set_active_custom_setting(&slot)?;
let name = camera.get_custom_setting_name()?;
slots.push(CustomSettingRepr { slot, name });
}
@@ -157,7 +157,7 @@ impl fmt::Display for FilmSimulationRepr {
fn handle_get(json: bool, device_id: Option<&str>, slot: FujiCustomSetting) -> anyhow::Result<()> {
let mut camera = usb::get_camera(device_id)?;
camera.set_active_custom_setting(slot)?;
camera.set_active_custom_setting(&slot)?;
let repr = FilmSimulationRepr {
name: camera.get_custom_setting_name()?,
@@ -191,14 +191,15 @@ fn handle_get(json: bool, device_id: Option<&str>, slot: FujiCustomSetting) -> a
Ok(())
}
#[allow(clippy::cognitive_complexity)]
fn handle_set(
device_id: Option<&str>,
slot: FujiCustomSetting,
name: Option<FujiCustomSettingName>,
options: FilmSimulationOptions,
name: Option<&FujiCustomSettingName>,
options: &FilmSimulationOptions,
) -> anyhow::Result<()> {
let mut camera = usb::get_camera(device_id)?;
camera.set_active_custom_setting(slot)?;
camera.set_active_custom_setting(&slot)?;
// General
if let Some(name) = &name {
@@ -206,53 +207,53 @@ fn handle_set(
}
if let Some(size) = &options.size {
camera.set_image_size(*size)?;
camera.set_image_size(size)?;
}
if let Some(quality) = &options.quality {
camera.set_image_quality(*quality)?;
camera.set_image_quality(quality)?;
}
// Style
if let Some(simulation) = &options.simulation {
camera.set_film_simulation(*simulation)?;
camera.set_film_simulation(simulation)?;
}
if let Some(color) = &options.color {
camera.set_color(*color)?;
camera.set_color(color)?;
}
if let Some(sharpness) = &options.sharpness {
camera.set_sharpness(*sharpness)?;
camera.set_sharpness(sharpness)?;
}
if let Some(clarity) = &options.clarity {
camera.set_clarity(*clarity)?;
camera.set_clarity(clarity)?;
}
if let Some(noise_reduction) = &options.noise_reduction {
camera.set_high_iso_nr(*noise_reduction)?;
camera.set_high_iso_nr(noise_reduction)?;
}
if let Some(grain) = &options.grain {
camera.set_grain_effect(*grain)?;
camera.set_grain_effect(grain)?;
}
if let Some(color_chrome_effect) = &options.color_chrome_effect {
camera.set_color_chrome_effect(*color_chrome_effect)?;
camera.set_color_chrome_effect(color_chrome_effect)?;
}
if let Some(color_chrome_fx_blue) = &options.color_chrome_fx_blue {
camera.set_color_chrome_fx_blue(*color_chrome_fx_blue)?;
camera.set_color_chrome_fx_blue(color_chrome_fx_blue)?;
}
if let Some(smooth_skin_effect) = &options.smooth_skin_effect {
camera.set_smooth_skin_effect(*smooth_skin_effect)?;
camera.set_smooth_skin_effect(smooth_skin_effect)?;
}
// White Balance
if let Some(white_balance) = &options.white_balance {
camera.set_white_balance(*white_balance)?;
camera.set_white_balance(white_balance)?;
}
if let Some(temperature) = &options.white_balance_temperature {
@@ -262,24 +263,24 @@ fn handle_set(
&camera.get_white_balance()?
};
if *white_balance != FujiWhiteBalance::Temperature {
warn!("White Balance mode is not set to 'Temperature', refusing to set temperature")
if *white_balance == FujiWhiteBalance::Temperature {
camera.set_white_balance_temperature(temperature)?;
} else {
camera.set_white_balance_temperature(*temperature)?;
warn!("White Balance mode is not set to 'Temperature', refusing to set temperature");
}
}
if let Some(shift_red) = &options.white_balance_shift_red {
camera.set_white_balance_shift_red(*shift_red)?;
camera.set_white_balance_shift_red(shift_red)?;
}
if let Some(shift_blue) = &options.white_balance_shift_blue {
camera.set_white_balance_shift_blue(*shift_blue)?;
camera.set_white_balance_shift_blue(shift_blue)?;
}
// Exposure
if let Some(dynamic_range_priority) = &options.dynamic_range_priority {
camera.set_dynamic_range_priority(*dynamic_range_priority)?;
camera.set_dynamic_range_priority(dynamic_range_priority)?;
}
if options.dynamic_range.is_some() || options.highlight.is_some() || options.shadow.is_some() {
@@ -291,26 +292,26 @@ fn handle_set(
};
if let Some(dynamic_range) = &options.dynamic_range {
if *dynamic_range_priority != FujiDynamicRangePriority::Off {
warn!("Dynamic Range Priority is enabled, refusing to set dynamic range")
if *dynamic_range_priority == FujiDynamicRangePriority::Off {
camera.set_dynamic_range(dynamic_range)?;
} else {
camera.set_dynamic_range(*dynamic_range)?;
warn!("Dynamic Range Priority is enabled, refusing to set dynamic range");
}
}
if let Some(highlights) = &options.highlight {
if *dynamic_range_priority != FujiDynamicRangePriority::Off {
warn!("Dynamic Range Priority is enabled, refusing to set highlight tone")
if *dynamic_range_priority == FujiDynamicRangePriority::Off {
camera.set_highlight_tone(highlights)?;
} else {
camera.set_highlight_tone(*highlights)?;
warn!("Dynamic Range Priority is enabled, refusing to set highlight tone");
}
}
if let Some(shadows) = &options.shadow {
if *dynamic_range_priority != FujiDynamicRangePriority::Off {
warn!("Dynamic Range Priority is enabled, refusing to set shadow tone")
if *dynamic_range_priority == FujiDynamicRangePriority::Off {
camera.set_shadow_tone(shadows)?;
} else {
camera.set_shadow_tone(*shadows)?;
warn!("Dynamic Range Priority is enabled, refusing to set shadow tone");
}
}
}
@@ -342,7 +343,7 @@ pub fn handle(cmd: SimulationCmd, json: bool, device_id: Option<&str>) -> anyhow
slot,
name,
film_simulation_options,
} => handle_set(device_id, slot, name, film_simulation_options),
} => handle_set(device_id, slot, name.as_ref(), &film_simulation_options),
SimulationCmd::Export { slot, output_file } => handle_export(device_id, slot, &output_file),
SimulationCmd::Import { slot, input_file } => handle_import(device_id, slot, &input_file),
}