This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** \file | |
* PTP handlers to extend Magic Lantern to the USB port. | |
* | |
* These handlers are registered to allow Magic Lantern to interact with | |
* a PTP client on the USB port. | |
*/ | |
#include "dryos.h" | |
#include "ptp.h" | |
#include "ptp-extra.h" | |
#include "tasks.h" | |
#include "menu.h" | |
#include "raw.h" | |
#include "bmp.h" | |
#include "property.h" | |
#include "module.h" | |
#include "lens.h" | |
#include "shoot.h" | |
#include "version.h" | |
#include "chdk-dng.h" | |
#include "powersave.h" | |
static PROP_INT(PROP_ISO, prop_iso); | |
static PROP_INT(PROP_SHUTTER, prop_shutter); | |
static void* my_single_frame; | |
static int get_a_frame = 0; | |
static void* get_lv() | |
{ | |
// See also silent_pic_take_fullres(int interactive) | |
force_liveview(); | |
raw_lv_request(); | |
msleep(50); | |
raw_lv_release(); | |
msleep(50); | |
raw_update_params(); | |
return &raw_info; | |
} | |
static int getBuffers(struct memSuite * hSuite) | |
{ | |
struct memChunk * hChunk = (void*) GetFirstChunkFromSuite(hSuite); | |
void* ptr = (void*) GetMemoryAddressOfMemoryChunk(hChunk); | |
while (1) | |
{ | |
void* ptr0 = (void*) GetMemoryAddressOfMemoryChunk(hChunk); | |
int size = GetSizeOfMemoryChunk(hChunk); | |
int used = ptr - ptr0; | |
int remain = size - used; | |
//~ printf("remain: %x\n", remain); | |
/* the EDMAC might write a bit more than that, | |
* so we'll use a small safety margin (2 extra lines) */ | |
if (remain < raw_info.frame_size + 2 * raw_info.pitch) | |
{ | |
/* move to next chunk */ | |
hChunk = GetNextMemoryChunk(hSuite, hChunk); | |
if (!hChunk) | |
{ | |
//~ printf("no more memory\n"); | |
break; | |
} | |
ptr = (void*) GetMemoryAddressOfMemoryChunk(hChunk); | |
//~ printf("next chunk: %x %x\n", hChunk, ptr); | |
continue; | |
} | |
else /* alright, a new frame fits here */ | |
{ | |
//~ printf("FRAME %d: hSuite=%x hChunk=%x ptr=%x\n", count, hSuite, hChunk, ptr); | |
my_single_frame = ptr; | |
return 0; | |
/*ptr = ptr + raw_info.frame_size; | |
if (count >= SP_BUFFER_SIZE) | |
{ | |
//~ printf("we have lots of RAM, lol\n"); | |
break; | |
} | |
*/ | |
} | |
} | |
return 1; | |
} | |
static void fill_uint32(char* data, uint32_t value) { | |
uint8_t* d = (uint8_t*)data; | |
*d = value & 0xFF; value >>= 8; d++; | |
*d = value & 0xFF; value >>= 8; d++; | |
*d = value & 0xFF; value >>= 8; d++; | |
*d = value & 0xFF; | |
} | |
PTP_HANDLER( PTP_EXTRA_CODE, 0 ) | |
{ | |
struct ptp_msg msg = { | |
.id = PTP_RC_OK, | |
.session = session, | |
.transaction = transaction, | |
.param_count = 4, | |
.param = { 1, 2, 0xdeadbeef, 3 }, | |
}; | |
// handle command | |
char* mydata = NULL; | |
size_t thumbnail_size = 0; | |
char* rawadr = NULL; | |
struct memSuite * hSuite1 = NULL; | |
switch ( param1 ) | |
{ | |
case PTP_EXTRA_HelloWorld: | |
msg.param_count = 2; | |
msg.param[0] = PTP_EXTRA_VERSION_MAJOR; | |
msg.param[1] = PTP_EXTRA_VERSION_MINOR; | |
break; | |
case PTP_EXTRA_TakePicture: | |
#if defined(CONFIG_EOSM) | |
call("Release"); | |
#endif | |
msg.param_count = 1; | |
msg.param[0] = 0; | |
break; | |
case PTP_EXTRA_GetLV: | |
hSuite1 = srm_malloc_suite(1); | |
if(!hSuite1) | |
{ | |
msg.id = PTP_RC_GeneralError; | |
msg.param[0] = 0; | |
} | |
int raw_flag = 1; | |
raw_lv_request(); | |
if (!raw_update_params()) | |
{ | |
msg.id = PTP_RC_GeneralError; | |
msg.param[0] = 1; | |
goto cleanup; | |
} | |
if(getBuffers(hSuite1)) | |
{ | |
msg.id = PTP_RC_GeneralError; | |
msg.param[0] = 2; | |
goto cleanup; | |
} | |
memset(my_single_frame, 0, raw_info.frame_size); | |
struct raw_info local_raw_info = raw_info; | |
get_a_frame = 1; | |
int loop_ctr = 0; | |
while(get_a_frame == 1) | |
{ | |
loop_ctr++; | |
msleep(20); | |
if (!lv) | |
{ | |
get_a_frame = 0; | |
break; | |
} | |
} | |
if(get_a_frame != 2) | |
{ | |
msg.id = PTP_RC_GeneralError; | |
msg.param[0] = 3; | |
get_a_frame = 0; | |
goto cleanup; | |
} | |
raw_lv_release(); raw_flag = 0; | |
//raw_force_aspect_ratio_1to1(); | |
// | |
local_raw_info.buffer = my_single_frame; | |
msg.param[0] = local_raw_info.jpeg.width; | |
msg.param[1] = local_raw_info.jpeg.height; | |
create_dng_header(&local_raw_info); | |
create_thumbnail(&local_raw_info); | |
thumbnail_size = dng_th_width*dng_th_height*3; | |
mydata = malloc(dng_header_buf_size + thumbnail_size + local_raw_info.frame_size ); | |
memcpy(mydata,dng_header_buf,dng_header_buf_size); | |
memcpy(mydata + dng_header_buf_size, thumbnail_buf,thumbnail_size); | |
rawadr = (void*) local_raw_info.buffer; | |
reverse_bytes_order(rawadr, local_raw_info.frame_size); | |
memcpy(mydata + dng_header_buf_size + thumbnail_size, rawadr, local_raw_info.frame_size); | |
srm_free_suite(hSuite1); | |
my_single_frame = NULL; | |
send_ptp_data(context, mydata, dng_header_buf_size + thumbnail_size + local_raw_info.frame_size); | |
free(mydata); | |
free_dng_header(); | |
redraw(); | |
cleanup: | |
if (raw_flag) | |
raw_lv_release(); | |
break; | |
/* | |
case PTP_EXTRA_GetLVFull: | |
prop_iso = lens_info.raw_iso; | |
if (shooting_mode != SHOOTMODE_M || (prop_iso == 0 || prop_shutter == 0)) | |
{ | |
msg.param_count = 1; | |
msg.param[0] = 1; | |
break; | |
} | |
if (!lv && !LV_PAUSED && gui_state != GUISTATE_QR) force_liveview(); | |
PauseLiveView(); | |
//gui_uilock(UILOCK_EVERYTHING); | |
//clrscr(); | |
vram_clear_lv(); | |
display_off(); | |
//struct JobClass * copy_job = 0; | |
//void* copy_buf = 0; | |
struct JobClass * job = (void*) call("FA_CreateTestImage"); | |
lens_info.job_state = 1; | |
info_led_on(); | |
//int t0 = get_ms_clock_value(); | |
call("FA_CaptureTestImage", job); | |
//int t1 = get_ms_clock_value(); | |
//int capture_time = t1 - t0; | |
info_led_off(); | |
lens_info.job_state = 0; | |
call("FA_DeleteTestImage", job); | |
msg.param[0] = raw_info.jpeg.width; | |
msg.param[1] = raw_info.jpeg.height; | |
create_dng_header(&raw_info); | |
create_thumbnail(&raw_info); | |
mydata = malloc(dng_header_buf_size + dng_th_width*dng_th_height*3 + raw_info.frame_size ); | |
memcpy(mydata,dng_header_buf,dng_header_buf_size); | |
size_t thumbnail_size = dng_th_width*dng_th_height*3; | |
memcpy(mydata + dng_header_buf_size, thumbnail_buf,thumbnail_size); | |
rawadr = (void*) raw_info.buffer; | |
reverse_bytes_order(rawadr, raw_info.frame_size); | |
memcpy(mydata + dng_header_buf_size + thumbnail_size, rawadr, raw_info.frame_size); | |
send_ptp_data(context, mydata, dng_header_buf_size + thumbnail_size + raw_info.frame_size); | |
free(mydata); | |
free_dng_header(); | |
break; | |
*/ | |
default: | |
msg.id = PTP_RC_ParameterNotSupported; | |
break; | |
} | |
context->send_resp( | |
context->handle, | |
&msg | |
); | |
return 0; | |
} | |
unsigned int get_single_frame(unsigned int ctx) | |
{ | |
if(get_a_frame != 1) | |
return 0; | |
if(my_single_frame == 0) | |
return 0; | |
raw_lv_redirect_edmac(my_single_frame); | |
get_a_frame=2; | |
return 0; | |
/* | |
if (!sp_running) return 0; | |
if (!sp_buffer_count) { sp_running = 0; return 0; }; | |
if (!raw_lv_settings_still_valid()) { sp_running = 0; return 0; } | |
if (silent_pic_mode == SILENT_PIC_MODE_SLITSCAN) | |
{ | |
silent_pic_raw_slitscan_vsync(); | |
return 0; | |
} | |
// are we done? | |
if ((sp_num_frames >= sp_min_frames && !get_halfshutter_pressed()) || sp_num_frames >= sp_max_frames) | |
{ | |
sp_running = 0; | |
return 0; | |
} | |
int next_slot = sp_num_frames % sp_buffer_count; | |
if (silent_pic_mode == SILENT_PIC_MODE_BEST_FOCUS) | |
{ | |
next_slot = silent_pic_raw_choose_next_slot(); | |
} | |
// Reprogram the raw EDMAC to output the data in our buffer (ptr) | |
raw_lv_redirect_edmac(sp_frames[next_slot % sp_buffer_count]); | |
sp_num_frames++; | |
bmp_printf(FONT_MED, 0, 60, "Capturing frame %d...", sp_num_frames); | |
return 0; | |
*/ | |
} | |
MODULE_CBRS_START() | |
MODULE_CBR(CBR_VSYNC, get_single_frame, 0) | |
MODULE_CBRS_END() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello natschil,
I would like to use your ML PTP extension for capturing silencing pictures via libgphoto2 for astrophotography.
Could you please upload also your ptp-extra.h?
Have you managed to make it work with libgphoto2 or libptp2?
Regards