feat: custom option setter
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
@@ -216,7 +216,7 @@ pub trait PtpDeserialize: Sized {
|
|||||||
fn try_read_ptp<R: Read>(cur: &mut R) -> io::Result<Self>;
|
fn try_read_ptp<R: Read>(cur: &mut R) -> io::Result<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_ptp {
|
macro_rules! impl_ptp_ser {
|
||||||
($ty:ty, $read_fn:ident, $write_fn:ident) => {
|
($ty:ty, $read_fn:ident, $write_fn:ident) => {
|
||||||
impl PtpSerialize for $ty {
|
impl PtpSerialize for $ty {
|
||||||
fn try_into_ptp(&self) -> io::Result<Vec<u8>> {
|
fn try_into_ptp(&self) -> io::Result<Vec<u8>> {
|
||||||
@@ -229,7 +229,11 @@ macro_rules! impl_ptp {
|
|||||||
buf.$write_fn(self)
|
buf.$write_fn(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_ptp_de {
|
||||||
|
($ty:ty, $read_fn:ident, $write_fn:ident) => {
|
||||||
impl PtpDeserialize for $ty {
|
impl PtpDeserialize for $ty {
|
||||||
fn try_from_ptp(buf: &[u8]) -> io::Result<Self> {
|
fn try_from_ptp(buf: &[u8]) -> io::Result<Self> {
|
||||||
let mut cur = Cursor::new(buf);
|
let mut cur = Cursor::new(buf);
|
||||||
@@ -245,20 +249,38 @@ macro_rules! impl_ptp {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_ptp!(u8, read_ptp_u8, write_ptp_u8);
|
impl_ptp_ser!(u8, read_ptp_u8, write_ptp_u8);
|
||||||
impl_ptp!(i8, read_ptp_i8, write_ptp_i8);
|
impl_ptp_de!(u8, read_ptp_u8, write_ptp_u8);
|
||||||
impl_ptp!(u16, read_ptp_u16, write_ptp_u16);
|
impl_ptp_ser!(i8, read_ptp_i8, write_ptp_i8);
|
||||||
impl_ptp!(i16, read_ptp_i16, write_ptp_i16);
|
impl_ptp_de!(i8, read_ptp_i8, write_ptp_i8);
|
||||||
impl_ptp!(u32, read_ptp_u32, write_ptp_u32);
|
impl_ptp_ser!(u16, read_ptp_u16, write_ptp_u16);
|
||||||
impl_ptp!(i32, read_ptp_i32, write_ptp_i32);
|
impl_ptp_de!(u16, read_ptp_u16, write_ptp_u16);
|
||||||
impl_ptp!(u64, read_ptp_u64, write_ptp_u64);
|
impl_ptp_ser!(i16, read_ptp_i16, write_ptp_i16);
|
||||||
impl_ptp!(i64, read_ptp_i64, write_ptp_i64);
|
impl_ptp_de!(i16, read_ptp_i16, write_ptp_i16);
|
||||||
impl_ptp!(String, read_ptp_str, write_ptp_str);
|
impl_ptp_ser!(u32, read_ptp_u32, write_ptp_u32);
|
||||||
impl_ptp!(Vec<u8>, read_ptp_u8_vec, write_ptp_u8_vec);
|
impl_ptp_de!(u32, read_ptp_u32, write_ptp_u32);
|
||||||
impl_ptp!(Vec<i8>, read_ptp_i8_vec, write_ptp_i8_vec);
|
impl_ptp_ser!(i32, read_ptp_i32, write_ptp_i32);
|
||||||
impl_ptp!(Vec<u16>, read_ptp_u16_vec, write_ptp_u16_vec);
|
impl_ptp_de!(i32, read_ptp_i32, write_ptp_i32);
|
||||||
impl_ptp!(Vec<i16>, read_ptp_i16_vec, write_ptp_i16_vec);
|
impl_ptp_ser!(u64, read_ptp_u64, write_ptp_u64);
|
||||||
impl_ptp!(Vec<u32>, read_ptp_u32_vec, write_ptp_u32_vec);
|
impl_ptp_de!(u64, read_ptp_u64, write_ptp_u64);
|
||||||
impl_ptp!(Vec<i32>, read_ptp_i32_vec, write_ptp_i32_vec);
|
impl_ptp_ser!(i64, read_ptp_i64, write_ptp_i64);
|
||||||
impl_ptp!(Vec<u64>, read_ptp_u64_vec, write_ptp_u64_vec);
|
impl_ptp_de!(i64, read_ptp_i64, write_ptp_i64);
|
||||||
impl_ptp!(Vec<i64>, read_ptp_i64_vec, write_ptp_i64_vec);
|
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);
|
||||||
|
@@ -11,10 +11,10 @@ use ptp::{
|
|||||||
Ptp,
|
Ptp,
|
||||||
hex::{
|
hex::{
|
||||||
CommandCode, DevicePropCode, FujiClarity, FujiColor, FujiColorChromeEffect,
|
CommandCode, DevicePropCode, FujiClarity, FujiColor, FujiColorChromeEffect,
|
||||||
FujiColorChromeFXBlue, FujiCustomSetting, FujiDynamicRange, FujiFilmSimulation,
|
FujiColorChromeFXBlue, FujiCustomSetting, FujiCustomSettingName, FujiDynamicRange,
|
||||||
FujiGrainEffect, FujiHighISONR, FujiHighlightTone, FujiImageQuality, FujiImageSize,
|
FujiDynamicRangePriority, FujiFilmSimulation, FujiGrainEffect, FujiHighISONR,
|
||||||
FujiShadowTone, FujiSharpness, FujiStillDynamicRangePriority, FujiWhiteBalance,
|
FujiHighlightTone, FujiImageQuality, FujiImageSize, FujiShadowTone, FujiSharpness,
|
||||||
FujiWhiteBalanceShift, FujiWhiteBalanceTemperature, UsbMode,
|
FujiWhiteBalance, FujiWhiteBalanceShift, FujiWhiteBalanceTemperature, UsbMode,
|
||||||
},
|
},
|
||||||
structs::DeviceInfo,
|
structs::DeviceInfo,
|
||||||
};
|
};
|
||||||
@@ -158,81 +158,172 @@ impl Camera {
|
|||||||
self.r#impl.set_custom_setting_slot(&mut self.ptp, slot)
|
self.r#impl.set_custom_setting_slot(&mut self.ptp, slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_custom_setting_name(&mut self) -> anyhow::Result<String> {
|
pub fn get_custom_setting_name(&mut self) -> anyhow::Result<FujiCustomSettingName> {
|
||||||
self.r#impl.get_custom_setting_name(&mut self.ptp)
|
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> {
|
pub fn get_image_size(&mut self) -> anyhow::Result<FujiImageSize> {
|
||||||
self.r#impl.get_image_size(&mut self.ptp)
|
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> {
|
pub fn get_image_quality(&mut self) -> anyhow::Result<FujiImageQuality> {
|
||||||
self.r#impl.get_image_quality(&mut self.ptp)
|
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> {
|
pub fn get_dynamic_range(&mut self) -> anyhow::Result<FujiDynamicRange> {
|
||||||
self.r#impl.get_dynamic_range(&mut self.ptp)
|
self.r#impl.get_dynamic_range(&mut self.ptp)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_dynamic_range_priority(&mut self) -> anyhow::Result<FujiStillDynamicRangePriority> {
|
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)
|
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> {
|
pub fn get_film_simulation(&mut self) -> anyhow::Result<FujiFilmSimulation> {
|
||||||
self.r#impl.get_film_simulation(&mut self.ptp)
|
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> {
|
pub fn get_grain_effect(&mut self) -> anyhow::Result<FujiGrainEffect> {
|
||||||
self.r#impl.get_grain_effect(&mut self.ptp)
|
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> {
|
pub fn get_white_balance(&mut self) -> anyhow::Result<FujiWhiteBalance> {
|
||||||
self.r#impl.get_white_balance(&mut self.ptp)
|
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> {
|
pub fn get_high_iso_nr(&mut self) -> anyhow::Result<FujiHighISONR> {
|
||||||
self.r#impl.get_high_iso_nr(&mut self.ptp)
|
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> {
|
pub fn get_highlight_tone(&mut self) -> anyhow::Result<FujiHighlightTone> {
|
||||||
self.r#impl.get_highlight_tone(&mut self.ptp)
|
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> {
|
pub fn get_shadow_tone(&mut self) -> anyhow::Result<FujiShadowTone> {
|
||||||
self.r#impl.get_shadow_tone(&mut self.ptp)
|
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> {
|
pub fn get_color(&mut self) -> anyhow::Result<FujiColor> {
|
||||||
self.r#impl.get_color(&mut self.ptp)
|
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> {
|
pub fn get_sharpness(&mut self) -> anyhow::Result<FujiSharpness> {
|
||||||
self.r#impl.get_sharpness(&mut self.ptp)
|
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> {
|
pub fn get_clarity(&mut self) -> anyhow::Result<FujiClarity> {
|
||||||
self.r#impl.get_clarity(&mut self.ptp)
|
self.r#impl.get_clarity(&mut self.ptp)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_wb_shift_red(&mut self) -> anyhow::Result<FujiWhiteBalanceShift> {
|
pub fn set_clarity(&mut self, value: FujiClarity) -> anyhow::Result<()> {
|
||||||
self.r#impl.get_wb_shift_red(&mut self.ptp)
|
self.r#impl.set_clarity(&mut self.ptp, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_wb_shift_blue(&mut self) -> anyhow::Result<FujiWhiteBalanceShift> {
|
pub fn get_white_balance_shift_red(&mut self) -> anyhow::Result<FujiWhiteBalanceShift> {
|
||||||
self.r#impl.get_wb_shift_blue(&mut self.ptp)
|
self.r#impl.get_white_balance_shift_red(&mut self.ptp)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_wb_temperature(&mut self) -> anyhow::Result<FujiWhiteBalanceTemperature> {
|
pub fn set_white_balance_shift_red(
|
||||||
self.r#impl.get_wb_temperature(&mut self.ptp)
|
&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> {
|
pub fn get_color_chrome_effect(&mut self) -> anyhow::Result<FujiColorChromeEffect> {
|
||||||
self.r#impl.get_color_chrome_effect(&mut self.ptp)
|
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> {
|
pub fn get_color_chrome_fx_blue(&mut self) -> anyhow::Result<FujiColorChromeFXBlue> {
|
||||||
self.r#impl.get_color_chrome_fx_blue(&mut self.ptp)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Camera {
|
impl Drop for Camera {
|
||||||
@@ -370,10 +461,16 @@ pub trait CameraImpl<P: rusb::UsbContext> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_custom_setting_name(&self, ptp: &mut Ptp) -> anyhow::Result<String> {
|
fn get_custom_setting_name(&self, ptp: &mut Ptp) -> anyhow::Result<FujiCustomSettingName> {
|
||||||
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingName)?;
|
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingName)?;
|
||||||
let name = String::try_from_ptp(&bytes)?;
|
let result = FujiCustomSettingName::try_from_ptp(&bytes)?;
|
||||||
Ok(name)
|
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> {
|
fn get_image_size(&self, ptp: &mut Ptp) -> anyhow::Result<FujiImageSize> {
|
||||||
@@ -382,30 +479,70 @@ pub trait CameraImpl<P: rusb::UsbContext> {
|
|||||||
Ok(result)
|
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> {
|
fn get_image_quality(&self, ptp: &mut Ptp) -> anyhow::Result<FujiImageQuality> {
|
||||||
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingImageQuality)?;
|
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingImageQuality)?;
|
||||||
let result = FujiImageQuality::try_from_ptp(&bytes)?;
|
let result = FujiImageQuality::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
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> {
|
fn get_dynamic_range(&self, ptp: &mut Ptp) -> anyhow::Result<FujiDynamicRange> {
|
||||||
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingDynamicRange)?;
|
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingDynamicRange)?;
|
||||||
let result = FujiDynamicRange::try_from_ptp(&bytes)?;
|
let result = FujiDynamicRange::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
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(
|
fn get_dynamic_range_priority(
|
||||||
&self,
|
&self,
|
||||||
ptp: &mut Ptp,
|
ptp: &mut Ptp,
|
||||||
) -> anyhow::Result<FujiStillDynamicRangePriority> {
|
) -> anyhow::Result<FujiDynamicRangePriority> {
|
||||||
let bytes = self.get_prop_value(
|
let bytes = self.get_prop_value(
|
||||||
ptp,
|
ptp,
|
||||||
DevicePropCode::FujiStillCustomSettingDynamicRangePriority,
|
DevicePropCode::FujiStillCustomSettingDynamicRangePriority,
|
||||||
)?;
|
)?;
|
||||||
let result = FujiStillDynamicRangePriority::try_from_ptp(&bytes)?;
|
let result = FujiDynamicRangePriority::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
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> {
|
fn get_film_simulation(&self, ptp: &mut Ptp) -> anyhow::Result<FujiFilmSimulation> {
|
||||||
let bytes =
|
let bytes =
|
||||||
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingFilmSimulation)?;
|
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingFilmSimulation)?;
|
||||||
@@ -413,24 +550,60 @@ pub trait CameraImpl<P: rusb::UsbContext> {
|
|||||||
Ok(result)
|
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> {
|
fn get_grain_effect(&self, ptp: &mut Ptp) -> anyhow::Result<FujiGrainEffect> {
|
||||||
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingGrainEffect)?;
|
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingGrainEffect)?;
|
||||||
let result = FujiGrainEffect::try_from_ptp(&bytes)?;
|
let result = FujiGrainEffect::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
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> {
|
fn get_white_balance(&self, ptp: &mut Ptp) -> anyhow::Result<FujiWhiteBalance> {
|
||||||
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingWhiteBalance)?;
|
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingWhiteBalance)?;
|
||||||
let result = FujiWhiteBalance::try_from_ptp(&bytes)?;
|
let result = FujiWhiteBalance::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
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> {
|
fn get_high_iso_nr(&self, ptp: &mut Ptp) -> anyhow::Result<FujiHighISONR> {
|
||||||
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingHighISONR)?;
|
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingHighISONR)?;
|
||||||
let result = FujiHighISONR::try_from_ptp(&bytes)?;
|
let result = FujiHighISONR::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
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> {
|
fn get_highlight_tone(&self, ptp: &mut Ptp) -> anyhow::Result<FujiHighlightTone> {
|
||||||
let bytes =
|
let bytes =
|
||||||
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingHighlightTone)?;
|
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingHighlightTone)?;
|
||||||
@@ -438,45 +611,118 @@ pub trait CameraImpl<P: rusb::UsbContext> {
|
|||||||
Ok(result)
|
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> {
|
fn get_shadow_tone(&self, ptp: &mut Ptp) -> anyhow::Result<FujiShadowTone> {
|
||||||
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingShadowTone)?;
|
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingShadowTone)?;
|
||||||
let result = FujiShadowTone::try_from_ptp(&bytes)?;
|
let result = FujiShadowTone::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
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> {
|
fn get_color(&self, ptp: &mut Ptp) -> anyhow::Result<FujiColor> {
|
||||||
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingColor)?;
|
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingColor)?;
|
||||||
let result = FujiColor::try_from_ptp(&bytes)?;
|
let result = FujiColor::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
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> {
|
fn get_sharpness(&self, ptp: &mut Ptp) -> anyhow::Result<FujiSharpness> {
|
||||||
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingSharpness)?;
|
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingSharpness)?;
|
||||||
let result = FujiSharpness::try_from_ptp(&bytes)?;
|
let result = FujiSharpness::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
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> {
|
fn get_clarity(&self, ptp: &mut Ptp) -> anyhow::Result<FujiClarity> {
|
||||||
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingClarity)?;
|
let bytes = self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingClarity)?;
|
||||||
let result = FujiClarity::try_from_ptp(&bytes)?;
|
let result = FujiClarity::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_wb_shift_red(&self, ptp: &mut Ptp) -> anyhow::Result<FujiWhiteBalanceShift> {
|
fn set_clarity(&self, ptp: &mut Ptp, value: FujiClarity) -> anyhow::Result<()> {
|
||||||
let bytes =
|
let bytes = value.try_into_ptp()?;
|
||||||
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingWhiteBalanceRed)?;
|
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)?;
|
let result = FujiWhiteBalanceShift::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_wb_shift_blue(&self, ptp: &mut Ptp) -> anyhow::Result<FujiWhiteBalanceShift> {
|
fn set_white_balance_shift_red(
|
||||||
let bytes =
|
&self,
|
||||||
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingWhiteBalanceBlue)?;
|
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)?;
|
let result = FujiWhiteBalanceShift::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_wb_temperature(&self, ptp: &mut Ptp) -> anyhow::Result<FujiWhiteBalanceTemperature> {
|
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(
|
let bytes = self.get_prop_value(
|
||||||
ptp,
|
ptp,
|
||||||
DevicePropCode::FujiStillCustomSettingWhiteBalanceTemperature,
|
DevicePropCode::FujiStillCustomSettingWhiteBalanceTemperature,
|
||||||
@@ -485,6 +731,20 @@ pub trait CameraImpl<P: rusb::UsbContext> {
|
|||||||
Ok(result)
|
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> {
|
fn get_color_chrome_effect(&self, ptp: &mut Ptp) -> anyhow::Result<FujiColorChromeEffect> {
|
||||||
let bytes =
|
let bytes =
|
||||||
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingColorChromeEffect)?;
|
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingColorChromeEffect)?;
|
||||||
@@ -492,10 +752,38 @@ pub trait CameraImpl<P: rusb::UsbContext> {
|
|||||||
Ok(result)
|
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> {
|
fn get_color_chrome_fx_blue(&self, ptp: &mut Ptp) -> anyhow::Result<FujiColorChromeFXBlue> {
|
||||||
let bytes =
|
let bytes =
|
||||||
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingColorChromeFXBlue)?;
|
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingColorChromeFXBlue)?;
|
||||||
let result = FujiColorChromeFXBlue::try_from_ptp(&bytes)?;
|
let result = FujiColorChromeFXBlue::try_from_ptp(&bytes)?;
|
||||||
Ok(result)
|
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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
io::{self, Cursor},
|
io::{self, Cursor},
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -146,8 +147,8 @@ pub enum DevicePropCode {
|
|||||||
FujiStillCustomSettingColorChromeFXBlue = 0xD197,
|
FujiStillCustomSettingColorChromeFXBlue = 0xD197,
|
||||||
// TODO: 0xD198 All 1s
|
// TODO: 0xD198 All 1s
|
||||||
FujiStillCustomSettingWhiteBalance = 0xD199,
|
FujiStillCustomSettingWhiteBalance = 0xD199,
|
||||||
FujiStillCustomSettingWhiteBalanceRed = 0xD19A,
|
FujiStillCustomSettingWhiteBalanceShiftRed = 0xD19A,
|
||||||
FujiStillCustomSettingWhiteBalanceBlue = 0xD19B,
|
FujiStillCustomSettingWhiteBalanceShiftBlue = 0xD19B,
|
||||||
FujiStillCustomSettingWhiteBalanceTemperature = 0xD19C,
|
FujiStillCustomSettingWhiteBalanceTemperature = 0xD19C,
|
||||||
FujiStillCustomSettingHighlightTone = 0xD19D,
|
FujiStillCustomSettingHighlightTone = 0xD19D,
|
||||||
FujiStillCustomSettingShadowTone = 0xD19E,
|
FujiStillCustomSettingShadowTone = 0xD19E,
|
||||||
@@ -181,7 +182,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{}", best_score);
|
println!("{best_score}");
|
||||||
if best_score <= SIMILARITY_THRESHOLD {
|
if best_score <= SIMILARITY_THRESHOLD {
|
||||||
best_match
|
best_match
|
||||||
} else {
|
} else {
|
||||||
@@ -231,7 +232,7 @@ impl Serialize for FujiCustomSetting {
|
|||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
serializer.serialize_u16(*self as u16)
|
serializer.serialize_u16((*self).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,6 +257,52 @@ impl FromStr for FujiCustomSetting {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, PtpSerialize, PtpDeserialize)]
|
||||||
|
pub struct FujiCustomSettingName(String);
|
||||||
|
|
||||||
|
impl FujiCustomSettingName {
|
||||||
|
pub const MAX_LEN: usize = 25;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for FujiCustomSettingName {
|
||||||
|
type Target = String;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for FujiCustomSettingName {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<String> for FujiCustomSettingName {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
fn try_from(value: String) -> Result<Self, anyhow::Error> {
|
||||||
|
if value.len() > Self::MAX_LEN {
|
||||||
|
bail!("Value '{}' exceeds max length of {}", value, Self::MAX_LEN);
|
||||||
|
}
|
||||||
|
Ok(Self(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for FujiCustomSettingName {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
fn from_str(s: &str) -> Result<Self, anyhow::Error> {
|
||||||
|
if s.len() > Self::MAX_LEN {
|
||||||
|
bail!("Value '{}' exceeds max length of {}", s, Self::MAX_LEN);
|
||||||
|
}
|
||||||
|
Ok(Self(s.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for FujiCustomSettingName {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
@@ -329,8 +376,8 @@ impl FromStr for FujiImageSize {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let resolution_input = s.replace(' ', "x").replace("by", "x");
|
let input = s.replace(' ', "x").replace("by", "x");
|
||||||
if let Some((w_str, h_str)) = resolution_input.split_once('x')
|
if let Some((w_str, h_str)) = input.split_once('x')
|
||||||
&& let (Ok(w), Ok(h)) = (w_str.trim().parse::<u32>(), h_str.trim().parse::<u32>())
|
&& let (Ok(w), Ok(h)) = (w_str.trim().parse::<u32>(), h_str.trim().parse::<u32>())
|
||||||
{
|
{
|
||||||
match (w, h) {
|
match (w, h) {
|
||||||
@@ -489,14 +536,14 @@ impl FromStr for FujiDynamicRange {
|
|||||||
PtpDeserialize,
|
PtpDeserialize,
|
||||||
EnumIter,
|
EnumIter,
|
||||||
)]
|
)]
|
||||||
pub enum FujiStillDynamicRangePriority {
|
pub enum FujiDynamicRangePriority {
|
||||||
Auto = 0x8000,
|
Auto = 0x8000,
|
||||||
Strong = 0x2,
|
Strong = 0x2,
|
||||||
Weak = 0x1,
|
Weak = 0x1,
|
||||||
Off = 0x0,
|
Off = 0x0,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for FujiStillDynamicRangePriority {
|
impl fmt::Display for FujiDynamicRangePriority {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Auto => write!(f, "Auto"),
|
Self::Auto => write!(f, "Auto"),
|
||||||
@@ -507,7 +554,7 @@ impl fmt::Display for FujiStillDynamicRangePriority {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for FujiStillDynamicRangePriority {
|
impl FromStr for FujiDynamicRangePriority {
|
||||||
type Err = anyhow::Error;
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> anyhow::Result<Self> {
|
fn from_str(s: &str) -> anyhow::Result<Self> {
|
||||||
@@ -705,10 +752,10 @@ impl FromStr for FujiGrainEffect {
|
|||||||
.replace(['+', '-', ',', ' '].as_ref(), "");
|
.replace(['+', '-', ',', ' '].as_ref(), "");
|
||||||
|
|
||||||
match input.as_str() {
|
match input.as_str() {
|
||||||
"stronglarge" => return Ok(Self::StrongLarge),
|
"stronglarge" | "largestrong" => return Ok(Self::StrongLarge),
|
||||||
"weaklarge" => return Ok(Self::WeakLarge),
|
"weaklarge" | "largeweak" => return Ok(Self::WeakLarge),
|
||||||
"strongsmall" => return Ok(Self::StrongSmall),
|
"strongsmall" | "smallstrong" => return Ok(Self::StrongSmall),
|
||||||
"weaksmall" => return Ok(Self::WeakSmall),
|
"weaksmall" | "smallweak" => return Ok(Self::WeakSmall),
|
||||||
"off" => return Ok(Self::Off),
|
"off" => return Ok(Self::Off),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -999,10 +1046,22 @@ macro_rules! define_fuji_i16 {
|
|||||||
pub struct $name(i16);
|
pub struct $name(i16);
|
||||||
|
|
||||||
impl $name {
|
impl $name {
|
||||||
pub const MIN: i16 = $min;
|
pub const MIN: f32 = $min;
|
||||||
pub const MAX: i16 = $max;
|
pub const MAX: f32 = $max;
|
||||||
pub const STEP: i16 = $step;
|
pub const STEP: f32 = $step;
|
||||||
pub const SCALE: f32 = $scale;
|
|
||||||
|
pub const SCALE: f32 = $scale as f32;
|
||||||
|
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
pub const RAW_MIN: i16 = ($min * $scale as f32) as i16;
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
pub const RAW_MAX: i16 = ($max * $scale as f32) as i16;
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
pub const RAW_STEP: i16 = ($step * $scale as f32) as i16;
|
||||||
|
|
||||||
|
pub const unsafe fn new_unchecked(value: i16) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Deref for $name {
|
impl std::ops::Deref for $name {
|
||||||
@@ -1022,12 +1081,12 @@ macro_rules! define_fuji_i16 {
|
|||||||
type Error = anyhow::Error;
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
fn try_from(value: i16) -> anyhow::Result<Self> {
|
fn try_from(value: i16) -> anyhow::Result<Self> {
|
||||||
if !(Self::MIN..=Self::MAX).contains(&value) {
|
if !(Self::RAW_MIN..=Self::RAW_MAX).contains(&value) {
|
||||||
anyhow::bail!("Value {} is out of range", value);
|
anyhow::bail!("Value {} is out of range", value);
|
||||||
}
|
}
|
||||||
#[allow(clippy::modulo_one)]
|
#[allow(clippy::modulo_one)]
|
||||||
if (value - Self::MIN) % Self::STEP != 0 {
|
if (value - Self::RAW_MIN) % Self::RAW_STEP != 0 {
|
||||||
anyhow::bail!("Value {} is not aligned to step {}", value, Self::STEP);
|
anyhow::bail!("Value {} is not aligned to step {}", value, Self::RAW_STEP);
|
||||||
}
|
}
|
||||||
Ok(Self(value))
|
Ok(Self(value))
|
||||||
}
|
}
|
||||||
@@ -1035,18 +1094,8 @@ macro_rules! define_fuji_i16 {
|
|||||||
|
|
||||||
impl std::fmt::Display for $name {
|
impl std::fmt::Display for $name {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
if (Self::SCALE - 1.0).abs() < f32::EPSILON {
|
let value = (f32::from(self.0) / Self::SCALE);
|
||||||
write!(f, "{}", self.0)
|
write!(f, "{}", value)
|
||||||
} else {
|
|
||||||
let val = f32::from(self.0) * Self::SCALE;
|
|
||||||
if val.fract().abs() < f32::EPSILON {
|
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
|
||||||
let val = val as i32;
|
|
||||||
write!(f, "{}", val as i32)
|
|
||||||
} else {
|
|
||||||
write!(f, "{:.1}", val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1061,9 +1110,18 @@ macro_rules! define_fuji_i16 {
|
|||||||
.parse::<f32>()
|
.parse::<f32>()
|
||||||
.with_context(|| format!("Invalid numeric value '{s}'"))?;
|
.with_context(|| format!("Invalid numeric value '{s}'"))?;
|
||||||
|
|
||||||
|
if !(Self::MIN..=Self::MAX).contains(&input) {
|
||||||
|
anyhow::bail!("Value {} is out of range", input);
|
||||||
|
}
|
||||||
|
#[allow(clippy::modulo_one)]
|
||||||
|
if (input - Self::MIN) % Self::STEP != 0.0 {
|
||||||
|
anyhow::bail!("Value {} is not aligned to step {}", input, Self::STEP);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
let raw = (input / Self::SCALE).round() as i16;
|
let raw = (input * Self::SCALE).round() as i16;
|
||||||
Self::try_from(raw)
|
|
||||||
|
unsafe { Ok(Self::new_unchecked(raw)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1072,24 +1130,20 @@ macro_rules! define_fuji_i16 {
|
|||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
{
|
{
|
||||||
let val = f32::from(self.0) * Self::SCALE;
|
let val = f32::from(self.0) / Self::SCALE;
|
||||||
if (val.fract().abs() < f32::EPSILON) {
|
serializer.serialize_f32(val)
|
||||||
serializer.serialize_i32(val as i32)
|
|
||||||
} else {
|
|
||||||
serializer.serialize_f32(val)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
define_fuji_i16!(FujiWhiteBalanceShift, -9, 9, 1, 1.0);
|
define_fuji_i16!(FujiWhiteBalanceShift, -9.0, 9.0, 1.0, 1i16);
|
||||||
define_fuji_i16!(FujiWhiteBalanceTemperature, 2500, 10000, 10, 1.0);
|
define_fuji_i16!(FujiWhiteBalanceTemperature, 2500.0, 10000.0, 10.0, 1i16);
|
||||||
define_fuji_i16!(FujiHighlightTone, -40, 20, 5, 0.1);
|
define_fuji_i16!(FujiHighlightTone, -2.0, 4.0, 0.5, 10i16);
|
||||||
define_fuji_i16!(FujiShadowTone, -20, 40, 5, 0.1);
|
define_fuji_i16!(FujiShadowTone, -2.0, 4.0, 0.5, 10i16);
|
||||||
define_fuji_i16!(FujiColor, -40, 40, 10, 0.1);
|
define_fuji_i16!(FujiColor, -4.0, 4.0, 1.0, 10i16);
|
||||||
define_fuji_i16!(FujiSharpness, -40, 40, 10, 0.1);
|
define_fuji_i16!(FujiSharpness, -4.0, 4.0, 1.0, 10i16);
|
||||||
define_fuji_i16!(FujiClarity, -50, 50, 10, 0.1);
|
define_fuji_i16!(FujiClarity, -5.0, 5.0, 1.0, 10i16);
|
||||||
|
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@@ -1,87 +1,87 @@
|
|||||||
use clap::Args;
|
use clap::Args;
|
||||||
|
|
||||||
use crate::camera::ptp::hex::{
|
use crate::camera::ptp::hex::{
|
||||||
FujiClarity, FujiColor, FujiColorChromeEffect, FujiColorChromeFXBlue, FujiDynamicRange,
|
FujiClarity, FujiColor, FujiColorChromeEffect, FujiColorChromeFXBlue, FujiCustomSettingName,
|
||||||
FujiFilmSimulation, FujiGrainEffect, FujiHighISONR, FujiHighlightTone, FujiImageQuality,
|
FujiDynamicRange, FujiDynamicRangePriority, FujiFilmSimulation, FujiGrainEffect, FujiHighISONR,
|
||||||
FujiImageSize, FujiShadowTone, FujiSharpness, FujiStillDynamicRangePriority, FujiWhiteBalance,
|
FujiHighlightTone, FujiImageQuality, FujiImageSize, FujiShadowTone, FujiSharpness,
|
||||||
FujiWhiteBalanceShift, FujiWhiteBalanceTemperature,
|
FujiWhiteBalance, FujiWhiteBalanceShift, FujiWhiteBalanceTemperature,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Args, Debug)]
|
#[derive(Args, Debug)]
|
||||||
pub struct FilmSimulationOptions {
|
pub struct FilmSimulationOptions {
|
||||||
/// The name of the slot
|
/// The name of the slot
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub name: Option<String>,
|
pub name: Option<FujiCustomSettingName>,
|
||||||
|
|
||||||
/// The Fujifilm film simulation to use
|
/// The Fujifilm film simulation to use
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub simulation: Option<FujiFilmSimulation>,
|
pub simulation: Option<FujiFilmSimulation>,
|
||||||
|
|
||||||
/// The output image resolution
|
/// The output image resolution
|
||||||
#[clap(long, alias = "size")]
|
#[clap(long)]
|
||||||
pub resolution: Option<FujiImageSize>,
|
pub size: Option<FujiImageSize>,
|
||||||
|
|
||||||
/// The output image quality (JPEG compression level)
|
/// The output image quality (JPEG compression level)
|
||||||
#[clap(long, value_parser)]
|
#[clap(long)]
|
||||||
pub quality: Option<FujiImageQuality>,
|
pub quality: Option<FujiImageQuality>,
|
||||||
|
|
||||||
/// Highlight Tone
|
/// Highlight Tone
|
||||||
#[clap(long, value_parser)]
|
#[clap(long, allow_hyphen_values(true))]
|
||||||
pub highlights: Option<FujiHighlightTone>,
|
pub highlight: Option<FujiHighlightTone>,
|
||||||
|
|
||||||
/// Shadow Tone
|
/// Shadow Tone
|
||||||
#[clap(long, value_parser)]
|
#[clap(long, allow_hyphen_values(true))]
|
||||||
pub shadows: Option<FujiShadowTone>,
|
pub shadow: Option<FujiShadowTone>,
|
||||||
|
|
||||||
/// Color
|
/// Color
|
||||||
#[clap(long, value_parser)]
|
#[clap(long, allow_hyphen_values(true))]
|
||||||
pub color: Option<FujiColor>,
|
pub color: Option<FujiColor>,
|
||||||
|
|
||||||
/// Sharpness
|
/// Sharpness
|
||||||
#[clap(long, value_parser)]
|
#[clap(long, allow_hyphen_values(true))]
|
||||||
pub sharpness: Option<FujiSharpness>,
|
pub sharpness: Option<FujiSharpness>,
|
||||||
|
|
||||||
/// Clarity
|
/// Clarity
|
||||||
#[clap(long, value_parser)]
|
#[clap(long, allow_hyphen_values(true))]
|
||||||
pub clarity: Option<FujiClarity>,
|
pub clarity: Option<FujiClarity>,
|
||||||
|
|
||||||
/// White Balance
|
/// White Balance
|
||||||
#[clap(long, value_parser)]
|
#[clap(long)]
|
||||||
pub white_balance: Option<FujiWhiteBalance>,
|
pub white_balance: Option<FujiWhiteBalance>,
|
||||||
|
|
||||||
/// White Balance Shift Red
|
/// White Balance Shift Red
|
||||||
#[clap(long, value_parser)]
|
#[clap(long, allow_hyphen_values(true))]
|
||||||
pub white_balance_shift_red: Option<FujiWhiteBalanceShift>,
|
pub white_balance_shift_red: Option<FujiWhiteBalanceShift>,
|
||||||
|
|
||||||
/// White Balance Shift Blue
|
/// White Balance Shift Blue
|
||||||
#[clap(long, value_parser)]
|
#[clap(long, allow_hyphen_values(true))]
|
||||||
pub white_balance_shift_blue: Option<FujiWhiteBalanceShift>,
|
pub white_balance_shift_blue: Option<FujiWhiteBalanceShift>,
|
||||||
|
|
||||||
/// White Balance Temperature (Only used if WB is set to 'Temperature')
|
/// White Balance Temperature (Only used if WB is set to 'Temperature')
|
||||||
#[clap(long, value_parser)]
|
#[clap(long)]
|
||||||
pub white_balance_temperature: Option<FujiWhiteBalanceTemperature>,
|
pub white_balance_temperature: Option<FujiWhiteBalanceTemperature>,
|
||||||
|
|
||||||
/// Dynamic Range
|
/// Dynamic Range
|
||||||
#[clap(long, value_parser)]
|
#[clap(long)]
|
||||||
pub dynamic_range: Option<FujiDynamicRange>,
|
pub dynamic_range: Option<FujiDynamicRange>,
|
||||||
|
|
||||||
/// Dynamic Range Priority
|
/// Dynamic Range Priority
|
||||||
#[clap(long, value_parser)]
|
#[clap(long)]
|
||||||
pub dynamic_ranga_priority: Option<FujiStillDynamicRangePriority>,
|
pub dynamic_range_priority: Option<FujiDynamicRangePriority>,
|
||||||
|
|
||||||
/// High ISO Noise Reduction
|
/// High ISO Noise Reduction
|
||||||
#[clap(long, value_parser)]
|
#[clap(long, allow_hyphen_values(true))]
|
||||||
pub noise_reduction: Option<FujiHighISONR>,
|
pub noise_reduction: Option<FujiHighISONR>,
|
||||||
|
|
||||||
/// Grain Effect
|
/// Grain Effect
|
||||||
#[clap(long, value_parser)]
|
#[clap(long)]
|
||||||
pub grain: Option<FujiGrainEffect>,
|
pub grain: Option<FujiGrainEffect>,
|
||||||
|
|
||||||
/// Color Chrome Effect
|
/// Color Chrome Effect
|
||||||
#[clap(long, value_parser)]
|
#[clap(long)]
|
||||||
pub color_chrome_effect: Option<FujiColorChromeEffect>,
|
pub color_chrome_effect: Option<FujiColorChromeEffect>,
|
||||||
|
|
||||||
/// Color Chrome FX Blue
|
/// Color Chrome FX Blue
|
||||||
#[clap(long, value_parser)]
|
#[clap(long)]
|
||||||
pub color_chrome_fx_blue: Option<FujiColorChromeFXBlue>,
|
pub color_chrome_fx_blue: Option<FujiColorChromeFXBlue>,
|
||||||
}
|
}
|
||||||
|
@@ -3,9 +3,9 @@ use std::fmt;
|
|||||||
use crate::{
|
use crate::{
|
||||||
camera::ptp::hex::{
|
camera::ptp::hex::{
|
||||||
FujiClarity, FujiColor, FujiColorChromeEffect, FujiColorChromeFXBlue, FujiCustomSetting,
|
FujiClarity, FujiColor, FujiColorChromeEffect, FujiColorChromeFXBlue, FujiCustomSetting,
|
||||||
FujiDynamicRange, FujiFilmSimulation, FujiGrainEffect, FujiHighISONR, FujiHighlightTone,
|
FujiCustomSettingName, FujiDynamicRange, FujiDynamicRangePriority, FujiFilmSimulation,
|
||||||
FujiImageQuality, FujiImageSize, FujiShadowTone, FujiSharpness,
|
FujiGrainEffect, FujiHighISONR, FujiHighlightTone, FujiImageQuality, FujiImageSize,
|
||||||
FujiStillDynamicRangePriority, FujiWhiteBalance, FujiWhiteBalanceShift,
|
FujiShadowTone, FujiSharpness, FujiWhiteBalance, FujiWhiteBalanceShift,
|
||||||
FujiWhiteBalanceTemperature,
|
FujiWhiteBalanceTemperature,
|
||||||
},
|
},
|
||||||
usb,
|
usb,
|
||||||
@@ -16,6 +16,7 @@ use super::common::{
|
|||||||
film::FilmSimulationOptions,
|
film::FilmSimulationOptions,
|
||||||
};
|
};
|
||||||
use clap::Subcommand;
|
use clap::Subcommand;
|
||||||
|
use log::warn;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ pub enum SimulationCmd {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CustomSettingRepr {
|
pub struct CustomSettingRepr {
|
||||||
pub slot: FujiCustomSetting,
|
pub slot: FujiCustomSetting,
|
||||||
pub name: String,
|
pub name: FujiCustomSettingName,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_list(json: bool, device_id: Option<&str>) -> anyhow::Result<()> {
|
fn handle_list(json: bool, device_id: Option<&str>) -> anyhow::Result<()> {
|
||||||
@@ -97,12 +98,12 @@ fn handle_list(json: bool, device_id: Option<&str>) -> anyhow::Result<()> {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct FilmSimulationRepr {
|
pub struct FilmSimulationRepr {
|
||||||
pub slot: FujiCustomSetting,
|
pub slot: FujiCustomSetting,
|
||||||
pub name: String,
|
pub name: FujiCustomSettingName,
|
||||||
pub simulation: FujiFilmSimulation,
|
pub simulation: FujiFilmSimulation,
|
||||||
pub resolution: FujiImageSize,
|
pub size: FujiImageSize,
|
||||||
pub quality: FujiImageQuality,
|
pub quality: FujiImageQuality,
|
||||||
pub highlights: FujiHighlightTone,
|
pub highlight: FujiHighlightTone,
|
||||||
pub shadows: FujiShadowTone,
|
pub shadow: FujiShadowTone,
|
||||||
pub color: FujiColor,
|
pub color: FujiColor,
|
||||||
pub sharpness: FujiSharpness,
|
pub sharpness: FujiSharpness,
|
||||||
pub clarity: FujiClarity,
|
pub clarity: FujiClarity,
|
||||||
@@ -111,7 +112,7 @@ pub struct FilmSimulationRepr {
|
|||||||
pub white_balance_shift_blue: FujiWhiteBalanceShift,
|
pub white_balance_shift_blue: FujiWhiteBalanceShift,
|
||||||
pub white_balance_temperature: FujiWhiteBalanceTemperature,
|
pub white_balance_temperature: FujiWhiteBalanceTemperature,
|
||||||
pub dynamic_range: FujiDynamicRange,
|
pub dynamic_range: FujiDynamicRange,
|
||||||
pub dynamic_range_priority: FujiStillDynamicRangePriority,
|
pub dynamic_range_priority: FujiDynamicRangePriority,
|
||||||
pub noise_reduction: FujiHighISONR,
|
pub noise_reduction: FujiHighISONR,
|
||||||
pub grain: FujiGrainEffect,
|
pub grain: FujiGrainEffect,
|
||||||
pub color_chrome_effect: FujiColorChromeEffect,
|
pub color_chrome_effect: FujiColorChromeEffect,
|
||||||
@@ -123,10 +124,10 @@ impl fmt::Display for FilmSimulationRepr {
|
|||||||
writeln!(f, "Slot: {}", self.slot)?;
|
writeln!(f, "Slot: {}", self.slot)?;
|
||||||
writeln!(f, "Name: {}", self.name)?;
|
writeln!(f, "Name: {}", self.name)?;
|
||||||
writeln!(f, "Simulation: {}", self.simulation)?;
|
writeln!(f, "Simulation: {}", self.simulation)?;
|
||||||
writeln!(f, "Resolution: {}", self.resolution)?;
|
writeln!(f, "Size: {}", self.size)?;
|
||||||
writeln!(f, "Quality: {}", self.quality)?;
|
writeln!(f, "Quality: {}", self.quality)?;
|
||||||
writeln!(f, "Highlights: {}", self.highlights)?;
|
writeln!(f, "Highlights: {}", self.highlight)?;
|
||||||
writeln!(f, "Shadows: {}", self.shadows)?;
|
writeln!(f, "Shadows: {}", self.shadow)?;
|
||||||
writeln!(f, "Color: {}", self.color)?;
|
writeln!(f, "Color: {}", self.color)?;
|
||||||
writeln!(f, "Sharpness: {}", self.sharpness)?;
|
writeln!(f, "Sharpness: {}", self.sharpness)?;
|
||||||
writeln!(f, "Clarity: {}", self.clarity)?;
|
writeln!(f, "Clarity: {}", self.clarity)?;
|
||||||
@@ -136,7 +137,11 @@ impl fmt::Display for FilmSimulationRepr {
|
|||||||
"White Balance Shift (R/B): {} / {}",
|
"White Balance Shift (R/B): {} / {}",
|
||||||
self.white_balance_shift_red, self.white_balance_shift_blue
|
self.white_balance_shift_red, self.white_balance_shift_blue
|
||||||
)?;
|
)?;
|
||||||
writeln!(f, "White Balance Temperature: {}K", self.white_balance_temperature)?;
|
writeln!(
|
||||||
|
f,
|
||||||
|
"White Balance Temperature: {}K",
|
||||||
|
self.white_balance_temperature
|
||||||
|
)?;
|
||||||
writeln!(f, "Dynamic Range: {}", self.dynamic_range)?;
|
writeln!(f, "Dynamic Range: {}", self.dynamic_range)?;
|
||||||
writeln!(f, "Dynamic Range Priority: {}", self.dynamic_range_priority)?;
|
writeln!(f, "Dynamic Range Priority: {}", self.dynamic_range_priority)?;
|
||||||
writeln!(f, "Noise Reduction: {}", self.noise_reduction)?;
|
writeln!(f, "Noise Reduction: {}", self.noise_reduction)?;
|
||||||
@@ -154,17 +159,17 @@ fn handle_get(json: bool, device_id: Option<&str>, slot: FujiCustomSetting) -> a
|
|||||||
slot,
|
slot,
|
||||||
name: camera.get_custom_setting_name()?,
|
name: camera.get_custom_setting_name()?,
|
||||||
simulation: camera.get_film_simulation()?,
|
simulation: camera.get_film_simulation()?,
|
||||||
resolution: camera.get_image_size()?,
|
size: camera.get_image_size()?,
|
||||||
quality: camera.get_image_quality()?,
|
quality: camera.get_image_quality()?,
|
||||||
highlights: camera.get_highlight_tone()?,
|
highlight: camera.get_highlight_tone()?,
|
||||||
shadows: camera.get_shadow_tone()?,
|
shadow: camera.get_shadow_tone()?,
|
||||||
color: camera.get_color()?,
|
color: camera.get_color()?,
|
||||||
sharpness: camera.get_sharpness()?,
|
sharpness: camera.get_sharpness()?,
|
||||||
clarity: camera.get_clarity()?,
|
clarity: camera.get_clarity()?,
|
||||||
white_balance: camera.get_white_balance()?,
|
white_balance: camera.get_white_balance()?,
|
||||||
white_balance_shift_red: camera.get_wb_shift_red()?,
|
white_balance_shift_red: camera.get_white_balance_shift_red()?,
|
||||||
white_balance_shift_blue: camera.get_wb_shift_blue()?,
|
white_balance_shift_blue: camera.get_white_balance_shift_blue()?,
|
||||||
white_balance_temperature: camera.get_wb_temperature()?,
|
white_balance_temperature: camera.get_white_balance_temperature()?,
|
||||||
dynamic_range: camera.get_dynamic_range()?,
|
dynamic_range: camera.get_dynamic_range()?,
|
||||||
dynamic_range_priority: camera.get_dynamic_range_priority()?,
|
dynamic_range_priority: camera.get_dynamic_range_priority()?,
|
||||||
noise_reduction: camera.get_high_iso_nr()?,
|
noise_reduction: camera.get_high_iso_nr()?,
|
||||||
@@ -183,11 +188,118 @@ fn handle_get(json: bool, device_id: Option<&str>, slot: FujiCustomSetting) -> a
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_set(
|
fn handle_set(
|
||||||
_device_id: Option<&str>,
|
device_id: Option<&str>,
|
||||||
_slot: FujiCustomSetting,
|
slot: FujiCustomSetting,
|
||||||
_opts: &FilmSimulationOptions,
|
options: &FilmSimulationOptions,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
todo!();
|
let mut camera = usb::get_camera(device_id)?;
|
||||||
|
camera.set_active_custom_setting(slot)?;
|
||||||
|
|
||||||
|
// General
|
||||||
|
if let Some(name) = &options.name {
|
||||||
|
camera.set_custom_setting_name(name)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(size) = &options.size {
|
||||||
|
camera.set_image_size(*size)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(quality) = &options.quality {
|
||||||
|
camera.set_image_quality(*quality)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Style
|
||||||
|
if let Some(simulation) = &options.simulation {
|
||||||
|
camera.set_film_simulation(*simulation)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(color) = &options.color {
|
||||||
|
camera.set_color(*color)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(sharpness) = &options.sharpness {
|
||||||
|
camera.set_sharpness(*sharpness)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(clarity) = &options.clarity {
|
||||||
|
camera.set_clarity(*clarity)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(noise_reduction) = &options.noise_reduction {
|
||||||
|
camera.set_high_iso_nr(*noise_reduction)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(grain) = &options.grain {
|
||||||
|
camera.set_grain_effect(*grain)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(color_chrome_effect) = &options.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)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// White Balance
|
||||||
|
let white_balance = match &options.white_balance {
|
||||||
|
Some(white_balance) => {
|
||||||
|
camera.set_white_balance(*white_balance)?;
|
||||||
|
white_balance
|
||||||
|
}
|
||||||
|
None => &camera.get_white_balance()?,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(temperature) = &options.white_balance_temperature {
|
||||||
|
if *white_balance != FujiWhiteBalance::Temperature {
|
||||||
|
warn!("White Balance mode is not set to 'Temperature', refusing to set temperature")
|
||||||
|
} else {
|
||||||
|
camera.set_white_balance_temperature(*temperature)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(shift_red) = &options.white_balance_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)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exposure
|
||||||
|
let dynamic_range_priority = match &options.dynamic_range_priority {
|
||||||
|
Some(dynamic_range_priority) => {
|
||||||
|
camera.set_dynamic_range_priority(*dynamic_range_priority)?;
|
||||||
|
dynamic_range_priority
|
||||||
|
}
|
||||||
|
None => &camera.get_dynamic_range_priority()?,
|
||||||
|
};
|
||||||
|
|
||||||
|
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")
|
||||||
|
} else {
|
||||||
|
camera.set_dynamic_range(*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")
|
||||||
|
} else {
|
||||||
|
camera.set_highlight_tone(*highlights)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(shadows) = &options.shadow {
|
||||||
|
if *dynamic_range_priority != FujiDynamicRangePriority::Off {
|
||||||
|
warn!("Dynamic Range Priority is enabled, refusing to set shadow tone")
|
||||||
|
} else {
|
||||||
|
camera.set_shadow_tone(*shadows)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_export(
|
fn handle_export(
|
||||||
|
@@ -14,7 +14,13 @@ pub fn init(verbose: u8) -> anyhow::Result<()> {
|
|||||||
_ => LevelFilter::Trace,
|
_ => LevelFilter::Trace,
|
||||||
};
|
};
|
||||||
|
|
||||||
let encoder = Box::new(PatternEncoder::new("{d} {h({l})} {M}::{L} - {m}{n}"));
|
let pattern = if verbose > 0 {
|
||||||
|
"{d} {h({l})} {M}::{L} - {m}{n}"
|
||||||
|
} else {
|
||||||
|
"{h({l})} - {m}{n}"
|
||||||
|
};
|
||||||
|
|
||||||
|
let encoder = Box::new(PatternEncoder::new(pattern));
|
||||||
|
|
||||||
let console = ConsoleAppender::builder()
|
let console = ConsoleAppender::builder()
|
||||||
.encoder(encoder)
|
.encoder(encoder)
|
||||||
|
Reference in New Issue
Block a user