From 944df748445e616b8055d0d718fd09747db70632 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Sun, 26 May 2019 21:41:24 +0200 Subject: initial lumix build https://github.com/gphoto/libgphoto2/issues/409 --- camlibs/Makefile.am | 1 + camlibs/lumix/Makefile-files | 12 + camlibs/lumix/README.lumix | 1 + camlibs/lumix/lumix.c | 957 +++++++++++++++++++++++ configure.ac | 1 + libgphoto2_port/gphoto2/gphoto2-port-info-list.h | 3 +- libgphoto2_port/ptpip/ptpip.c | 12 + 7 files changed, 986 insertions(+), 1 deletion(-) create mode 100644 camlibs/lumix/Makefile-files create mode 100644 camlibs/lumix/README.lumix create mode 100644 camlibs/lumix/lumix.c diff --git a/camlibs/Makefile.am b/camlibs/Makefile.am index e9fec2b2b..53f210d85 100644 --- a/camlibs/Makefile.am +++ b/camlibs/Makefile.am @@ -87,6 +87,7 @@ include kodak/Makefile-files include konica/Makefile-files include largan/lmini/Makefile-files include lg_gsm/Makefile-files +include lumix/Makefile-files include mars/Makefile-files include minolta/dimagev/Makefile-files include minolta/Makefile-files diff --git a/camlibs/lumix/Makefile-files b/camlibs/lumix/Makefile-files new file mode 100644 index 000000000..a975d6dc1 --- /dev/null +++ b/camlibs/lumix/Makefile-files @@ -0,0 +1,12 @@ +# -*- Makefile -*- + +EXTRA_DIST += lumix/README.lumix lumix/ChangeLog + +noinst_DATA += lumix/README.lumix +EXTRA_LTLIBRARIES += lumix.la + +lumix_la_SOURCES = lumix/lumix.c +lumix_la_CFLAGS = $(AM_CFLAGS) $(NO_UNUSED_CFLAGS) $(CFLAGS) +lumix_la_LDFLAGS = $(camlib_ldflags) +lumix_la_DEPENDENCIES = $(camlib_dependencies) +lumix_la_LIBADD = $(camlib_libadd) diff --git a/camlibs/lumix/README.lumix b/camlibs/lumix/README.lumix new file mode 100644 index 000000000..aebb3d775 --- /dev/null +++ b/camlibs/lumix/README.lumix @@ -0,0 +1 @@ +This is a small Lumix WIFI library. diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c new file mode 100644 index 000000000..72cf09a41 --- /dev/null +++ b/camlibs/lumix/lumix.c @@ -0,0 +1,957 @@ +/** \file lumix.c + * + * \author Copyright 2019 Marcus Meissner + * + * \par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * \par + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * \par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + */ +#include "config.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +#include +#include + +#define GP_MODULE "lumix" + +#define CHECK(result) \ +{ \ + int res = (result); \ + \ + if (res < 0) { \ + gp_log (GP_LOG_DEBUG, "lumix", "Operation failed in %s (%i)!", __FUNCTION__, res); \ + return (res); \ + } \ +} + + +#ifdef ENABLE_NLS +# include +# undef _ +/** +* This define is the string translation macro used in +* libgphoto2. It will resolve to a dcgettext() function call and +* does both the translation itself and also marks up the string +* for the collector (xgettext). +*/ +# define _(String) dgettext (GETTEXT_PACKAGE, String) +# ifdef gettext_noop +/** +* This is the noop translation macro, which does not translate the +* string, but marks it up for the extraction of translatable strings. +*/ +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define _(String) (String) +# define N_(String) (String) +#endif + +char* NUMPIX = "cam.cgi?mode=get_content_info"; +char* RECMODE = "cam.cgi?mode=camcmd&value=recmode"; +char* PLAYMODE = "cam.cgi?mode=camcmd&value=playmode"; +char* SHUTTERSTART = "cam.cgi?mode=camcmd&value=capture"; +char* SHUTTERSTOP = "cam.cgi?mode=camcmd&value=capture_cancel"; +char* SETAPERTURE = "cam.cgi?mode=setsetting&type=focal&value="; +char* QUALITY = "cam.cgi?mode=setsetting&type=quality&value="; +char* CDS_Control = ":60606/Server0/CDS_control"; +char* STARTSTREAM = "cam.cgi?mode=startstream&value=49199"; +char* CAMERAIP = "192.168.1.24"; //placeholder until there is a better way to discover the IP from the network and via PTPIP +int buflen = 10000; +static char Buffer[10000-1]; +int ReadoutMode = 0; // this should be picked up from the settings.... 0-> JPG; 1->RAW; 2 -> Thumbnails +char* cameraShutterSpeed = "B"; // //placeholder to store the value of the shutterspeed set in camera; "B" is for bulb. +int captureDuration = 10; //placeholder to store the value of the bulb shot this should be taken as input. note that my primary goal is in fact to perform bulb captures. but this should be extended for sure to take Shutter Speed capture as set in camera + +struct _CameraPrivateLibrary { + /* all private data */ +}; + + +static int +camera_exit (Camera *camera, GPContext *context) +{ + return GP_OK; +} + +int camera_config_get (Camera *camera, CameraWidget **window, GPContext *context); + +static int +camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) +{ + return GP_OK; +} + + +static int +camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) +{ + return GP_OK; +} + + +int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context); + +static int camera_about (Camera *camera, CameraText *about, GPContext *context); + + +/** + * Put a file onto the camera. + * + * This function is a CameraFilesystem method. + */ +int +put_file_func (CameraFilesystem *fs, const char *folder, const char *name, + CameraFileType type, CameraFile *file, void *data, GPContext *context); +int +put_file_func (CameraFilesystem *fs, const char *folder, const char *name, + CameraFileType type, CameraFile *file, void *data, GPContext *context) +{ + /*Camera *camera = data;*/ + + /* + * Upload the file to the camera. Use gp_file_get_data_and_size, etc + */ + + return GP_OK; +} + + +/** + * Delete a file from the camera. + * + * This function is a CameraFilesystem method. + */ +int +delete_file_func (CameraFilesystem *fs, const char *folder, + const char *filename, void *data, GPContext *context); +int +delete_file_func (CameraFilesystem *fs, const char *folder, + const char *filename, void *data, GPContext *context) +{ + /*Camera *camera = data;*/ + + /* Delete the file from the camera. */ + + return GP_OK; +} + + +/** + * Delete all files from the camera. + * + * This function is a CameraFilesystem method. + */ +int +delete_all_func (CameraFilesystem *fs, const char *folder, void *data, + GPContext *context); +int +delete_all_func (CameraFilesystem *fs, const char *folder, void *data, + GPContext *context) +{ + /*Camera *camera = data;*/ + + /* + * Delete all files in the given folder. If your camera doesn't have + * such a functionality, just don't implement this function. + */ + + return GP_OK; +} + + +/** + * Get the file info here and write it to space provided by caller. + * + * \param info Space provided by caller in which file info is written. + * + * This function is a CameraFilesystem method. + */ +int +get_info_func (CameraFilesystem *fs, const char *folder, const char *filename, + CameraFileInfo *info, void *data, GPContext *context); +int +get_info_func (CameraFilesystem *fs, const char *folder, const char *filename, + CameraFileInfo *info, void *data, GPContext *context) +{ + /*Camera *camera = data;*/ + + return GP_OK; +} + + +/** + * FIXME. + * + * This function is a CameraFilesystem method. + */ +int +set_info_func (CameraFilesystem *fs, const char *folder, const char *file, + CameraFileInfo info, void *data, GPContext *context); +int +set_info_func (CameraFilesystem *fs, const char *folder, const char *file, + CameraFileInfo info, void *data, GPContext *context) +{ + /*Camera *camera = data;*/ + + /* Set the file info here from */ + + return GP_OK; +} + + +/** + * List available folders in the specified folder. + * + * This function is a CameraFilesystem method. + */ +int +folder_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, + void *data, GPContext *context); +int +folder_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, + void *data, GPContext *context) +{ + /*Camera *camera = data;*/ + + /* List your folders here */ + + return GP_OK; +} + + +/** + * List available files in the specified folder. + * + * This function is a CameraFilesystem method. + */ +int +file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, + void *data, GPContext *context); +int +file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, + void *data, GPContext *context) +{ + /*Camera *camera = data;*/ + + /* List your files here */ + + return GP_OK; +} + +/** + * Get information on all available storages in the camera. + * + * This function is a CameraFilesystem method. + */ +int +storage_info_func (CameraFilesystem *fs, + CameraStorageInformation **storageinformations, + int *nrofstorageinformations, void *data, + GPContext *context); +int +storage_info_func (CameraFilesystem *fs, + CameraStorageInformation **storageinformations, + int *nrofstorageinformations, void *data, + GPContext *context) +{ + /*Camera *camera = data;*/ + + /* List your storages here */ + + return GP_ERROR_NOT_SUPPORTED; +} + +/*@}*/ + + +/**********************************************************************/ +/** + * @name camlib API functions + * + * @{ + */ +/**********************************************************************/ + + +int +camera_id (CameraText *id) +{ + strcpy(id->text, "Lumix Wifi"); + + return GP_OK; +} + +/*size_t read_callback(char *buffer, size_t size, size_t nitems, void *userdata);*/ + +static size_t +read_callback(void *ptr, size_t size, size_t nmemb, void *stream) { + curl_off_t nread; + /* in real-world cases, this would probably get this data differently + as this fread() stuff is exactly what the library already would do + by default internally */ + size_t retcode = fread(ptr, size, nmemb, stream); + nread = (curl_off_t)retcode; + return retcode; +} + +static char* loadCmd (Camera *camera,char* cmd) { + CURL *curl; + CURLcode res; + int stream = strcmp (cmd, STARTSTREAM); + char URL[100]; + //xmlDoc *doc = NULL; + //xmlNode *root_element = NULL; + + curl = curl_easy_init(); + + snprintf( URL,100, "http://%s/cam.cgi%s",CAMERAIP, cmd); + curl_easy_setopt(curl, CURLOPT_URL, URL); + //curl_easy_setopt(curl, CURLOPT_READ, URL); + if (!stream) { + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); + curl_easy_setopt(curl, CURLOPT_READDATA, camera); + } + res = curl_easy_perform(curl); + if(res != CURLE_OK) { + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + return NULL; + } else { + /* read the XML that is now in Buffer*/ + } + curl_easy_cleanup(curl); + if (!stream) { + return Buffer; + } else { + return NULL; + } // TO DO the idea would be to return the socket to the actual video stream here.... +} + + +static void switchToRecMode(Camera *camera) { + loadCmd(camera,"?mode=camcmd&value=recmode"); +} + +static void Set_ISO(Camera *camera,const char * ISOValue) { + char buf[200]; + sprintf(buf, "?mode==setsetting&type=iso&value=%s",ISOValue); + loadCmd(camera,buf); +} + +static void Set_Speed(Camera *camera,const char* SpeedValue) { + char buf[200]; + sprintf(buf, "?mode=setsetting&type=shtrspeed&value=%s",SpeedValue); + loadCmd(camera,buf); +} + +static void startStream(Camera *camera) { + loadCmd(camera,"?mode=startstream&value=49199"); +} + +static void shotPicture(Camera *camera) { + loadCmd(camera,"?mode=camcmd&value=capture"); +} + +static void stopCapture(Camera *camera) { + loadCmd(camera,"?mode=camcmd&value=capture_cancel"); +} + +static void startMovie(Camera *camera) { + loadCmd(camera,"?mode=camcmd&value=video_recstart"); +} + +static void stopMovie(Camera *camera) { + loadCmd(camera,"?mode=camcmd&value=video_recstop"); +} + +static void zoomIn(Camera *camera) { + loadCmd(camera,"?mode=camcmd&value=tele-fast"); +} + +static void zoomOut(Camera *camera) { + loadCmd(camera,"?mode=camcmd&value=wide-fast"); +} + +static void zoomStop(Camera *camera) { + loadCmd(camera,"?mode=camcmd&value=zoomstop"); +} + +static void focusIn(Camera *camera) { + loadCmd(camera,"?mode=camctrl&type=focus&value=tele-fast"); +} + +static void focusOut(Camera *camera) { + loadCmd(camera,"?mode=camctrl&type=focus&value=wide-fast"); +} + +/* + +this is the XML sample to be parsed by the function below NumberPix() + +ok341372342 + + +*/ +static char* NumberPix(Camera *camera) { + xmlChar *key; + xmlDocPtr doc = xmlParseDoc((unsigned char*)loadCmd(camera,NUMPIX)); + xmlNodePtr cur = NULL; + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + fprintf(stderr,"empty document\n"); + xmlFreeDoc(doc); + return NULL; + } + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"content_number"))){ + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + return (char*) key; + } + cur = cur->next; + } + return ""; +} + +/*utility function to creat a SOAP envelope for the lumix cam */ +static char* +SoapEnvelop(int start, int num){ + static char Envelop[500]; + snprintf(Envelop,500, "0BrowseDirectChildren* %d %dLumixLink2.0",start,num); + + return Envelop; +} + +/* + * retrieves the XML doc with the last num pictures avail in the camera. + */ +static char* GetPix(Camera *camera,int num) { + loadCmd(camera,PLAYMODE); + int Start = 0; + long NumPix = strtol(NumberPix(camera), NULL, 10); + char* SoapMsg = SoapEnvelop((NumPix - num)> 0?(NumPix - num):0, num); + CURL *curl; + curl = curl_easy_init(); + CURLcode res; + struct curl_slist *list = NULL; + + list = curl_slist_append(list, "soapaction"); + list = curl_slist_append(list, "Content-Type: text/xml; charset=\"utf-8\""); + list = curl_slist_append(list, "urn:schemas-upnp-org:service:ContentDirectory:1#Browse:"); + + char URL[1000]; + snprintf( URL,1000, "http://%s/cam.cgi%s",CAMERAIP, CDS_Control); + curl_easy_setopt(curl, CURLOPT_URL, URL); + //curl_easy_setopt(curl, CURLOPT_READ, URL); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); + curl_easy_setopt(curl, CURLOPT_READDATA, Buffer); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, SoapMsg); + res = curl_easy_perform(curl); + if(res != CURLE_OK) { + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + } + else { + /* read the XML that is now in Buffer*/ + + } + curl_easy_cleanup(curl); + return Buffer; + +} + +/** +* Get the full configuration tree of the camera. +* +* This function is a method of the Camera object. +* TO DO - - i started to include some items to set the quality (raw and raw+jpg) as well as dictionary for ISO and shutter speed +* mostly every thing is still to do +*/ +int camera_config_get (Camera *camera, CameraWidget **window, GPContext *context); +int +camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) +{ + return GP_OK; +} + +static int +waitBulb(Camera *camera, long Duration ) { + sleep(Duration * 1000); // Sleep for the duration to simulate exposure, if this is in Bulb mode + loadCmd(camera,SHUTTERSTOP); + return TRUE; +} + +static size_t dl_write(void *buffer, size_t size, size_t nmemb, void *stream) +{ + return fwrite(buffer, size, nmemb, (FILE*)stream); +} + + + +/* + +below are 2 samples of XML files to be parsed one in case of a JPG/Thumb retrieve the other for RAW + +case JPG/Thumb + + +- +- +- +- +- +- +103-0516 +WRITABLE +object.item.imageItem +http://192.168.1.26:50001/DO1030516.JPG +http://192.168.1.26:50001/DT1030516.JPG +http://192.168.1.26:50001/DL1030516.JPG +http://192.168.1.26:50001/DO1030516.RW2 + + + +1 +343 +1 + + + + +case RAW: + +- +- +- +- +- +- +103-0517 +WRITABLE +object.item.imageItem +http://192.168.1.26:50001/DO1030517.RAW +http://192.168.1.26:50001/DT1030517.JPG +http://192.168.1.26:50001/DL1030517.JPG + + + +1 +344 +1 + + + + +*/ +static char* ReadImageFromCamera(Camera *camera) { + xmlDocPtr Pictures =xmlParseDoc((xmlChar*)GetPix(camera,1)); //the XML with all the results from the camea + xmlNodePtr PictureList = NULL; //the list of picture items extratec + xmlNode *Picture, *cur; //a singlepicture item + cur = xmlDocGetRootElement(Pictures); + char *Images[250]; //the array of the urls in the camera + long nRead[250]; + int j = -1; + int SendStatus = -1; + int length = 0; + + PictureList = xmlFirstElementChild(xmlFirstElementChild(xmlFirstElementChild(xmlFirstElementChild(Pictures->last))))->children ;//items + //xmlFirstElementChild + //PictureList = Pictures.LastChild.FirstChild.FirstChild.FirstChild.FirstChild.ChildNodes 'items + + loadCmd(camera,PLAYMODE); // 'making sure the camera is in Playmode + + Picture = PictureList->xmlChildrenNode; + while (Picture != NULL) { + // if ((!xmlStrcmp(cur->name, (const xmlChar *)"content_number"))){ + // key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + // return (char*) key; + // } + + // Else 'JPG or Thumbnails + char* lookuptag; + int lookupNum; + char* xmlimageName; + + if (ReadoutMode == 0) { + lookuptag = "DO" ;//full JPG + lookupNum = 3; + xmlimageName = (char*)Picture->children->next->next->name; + } else { + lookuptag = "DL" ; //large thumbnail + lookupNum = 5; + xmlimageName = (char*)Picture->children->next->next->next->next->name; + } + + + if ((strstr(xmlimageName,"JPG")&& strstr(xmlimageName, lookuptag))||strstr(xmlimageName,"RAW")) { + // If Picture.ChildNodes(lookupNum).InnerText.Contains(".JPG") And Picture.ChildNodes(lookupNum).InnerText.Contains(lookuptag) Then + j = j + 1; + Images[j] = strdup(xmlimageName); + nRead[j] = 0; + CURL* imageUrl; + imageUrl = curl_easy_init(); + CURLcode res; + double bytesread = 0; + FILE* imageFile; + char filename[100]; + char* tempPath = "C:\\"; + long http_response; + int ret_val=0; + + while (ret_val!=2) { + snprintf(filename,100,"%s%s",tempPath,Images[j][strlen(Images[j])- 13]); + imageFile = fopen(filename,"ab"); + GP_DEBUG("reading stream %s position %ld", Images[j], nRead[j]); + + curl_easy_setopt(imageUrl, CURLOPT_URL, Images[j]); + curl_easy_setopt(imageUrl,CURLOPT_TCP_KEEPALIVE,1L); + curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPIDLE, 120L); + curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPINTVL, 60L); + curl_easy_setopt(imageUrl, CURLOPT_WRITEFUNCTION, dl_write); + //curl_easy_setopt(imageUrl, CURLOPT_PROGRESSFUNCTION, dl_progress); + //curl_easy_setopt(imageUrl, CURLOPT_NOPROGRESS, 0); + + if (nRead[j]) { + curl_easy_setopt(imageUrl, CURLOPT_RESUME_FROM, nRead[j]); + GetPix(camera,1);//'if the file not found happened then this trick is to get the camera in a readmode again and making sure it remembers the filename + GP_DEBUG("continuing the read where it stopped %s position %ld", Images[j], nRead[j]); + } + curl_easy_setopt(imageUrl, CURLOPT_WRITEDATA, imageFile); + + res = curl_easy_perform(imageUrl); + if(res != CURLE_OK) { + double x; + curl_easy_getinfo(imageUrl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &x); + nRead[j] = x; + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + GP_DEBUG("error in reading stream %s position %ld", Images[j], nRead[j]); + + curl_easy_getinfo(imageUrl, CURLINFO_RESPONSE_CODE, &http_response); + + GP_DEBUG("CURLINFO_RESPONSE_CODE:%ld\n", http_response); + } else { + GP_DEBUG("read the whole file"); + ret_val=2; + } + } + curl_easy_cleanup(imageUrl); + fclose(imageFile); + return strdup(filename); + } + Picture = Picture->next; + } + return NULL; +} + + +/** +* Capture an image and tell libgphoto2 where to find it by filling +* out the path. +* +* This function is a method of the Camera object. +*/ +int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context); +int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context){ + loadCmd(camera,"capture"); //we should really multithread so as to not block while waiting + if (!strcmp(cameraShutterSpeed, "B")) { + waitBulb(camera,captureDuration);//trying captureDuration sec to start before we know how to make a bulb capture of x sec .... + } + path = ReadImageFromCamera(camera); + return GP_OK; +} + + + +/** +* Fill out the summary with textual information about the current +* state of the camera (like pictures taken, etc.). +* +* This function is a method of the Camera object. +*/ +static int +camera_summary (Camera *camera, CameraText *summary, GPContext *context) +{ + return GP_OK; +} + + +/** +* Return the camera drivers manual. +* If you would like to tell the user some information about how +* to use the camera or the driver, this is the place to do. +* +* This function is a method of the Camera object. +*/ +static int camera_manual (Camera *camera, CameraText *manual, GPContext *context) { + return GP_OK; +} + + +/** +* Return "About" content as textual description. +* Will be translated. +* +* This function is a method of the Camera object. +*/ +int camera_about (Camera *camera, CameraText *about, GPContext *context); +int camera_about (Camera *camera, CameraText *about, GPContext *context) { + strcpy (about->text, _("Library Name\n" + "Robert Hasson \n" + "Connects to Lumix Cameras over Wifi.\n" + "using the http GET commands.")); + return GP_OK; +} + +/*@}*/ + + +/**********************************************************************/ +/** +* @name CameraFilesystem member functions +* +* @{ +*/ +/**********************************************************************/ + + +/** +* Get the file from the camera. +* +* This function is a CameraFilesystem method. +*/ +int +get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,CameraFileType type, CameraFile *file, void *data, GPContext *context); +int get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, CameraFileType type, CameraFile *file, void *data, GPContext *context) +{ + Camera *camera = data; + + /* + * Get the file from the camera. Use gp_file_set_mime_type, + * gp_file_set_data_and_size, etc. + */ + + if (type == GP_FILE_TYPE_PREVIEW) { + + loadCmd (camera,STARTSTREAM); + //need to do stuff here to get the UDP stream back from the camera as per other + //("http://" & CameraIP.Text & "/cam.cgi?mode=setsetting&type=liveviewsize&value=vga" + /* + ' UDP-Protokoll einstellen + Winsock1.Close 'Winsock1 ->Microsoft Winsock control in VB + Winsock1.Protocol = sckUDPProtocol + ' Port, der überwacht werden soll + nPort = 49199 + ' Eigene IP ermitteln + sOwnIP = Winsock1.LocalIP + + ' Port an die IP "binden" +Winsock1.Bind nPort, sOwnIP + +'geht nur im 'recmode' +txtStatus.Text = Inet1.OpenURL("http://" & CameraIP.Text & "/cam.cgi?mode=camcmd&value=recmode") 'Inet1 ->Microsoft Inet control + +txtStatus.Text = Inet1.OpenURL("http://" & CameraIP.Text & "/cam.cgi?mode=startstream&value=49199") + +Timer1.Enabled = True 'damit der Datenfluß nicht abbricht + +txtStatus.Text = Inet1.OpenURL("http://" & CameraIP.Text & "/cam.cgi?mode=setsetting_ &type=liveviewsize&value=vga") + +... + +Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) +Dim sData As String +Dim bArray As Variant + +On Error Resume Next + +'im Stream werden ganze Bilder übertragen 'Header ist 167 Byte, Rest - JPG +'Das JPEG-Bild beginnt also bei Byte 168 (Lumix GX7) + +Winsock1.GetData sData, vbString + +sData = Mid(sData, 168) + +bArray = sData + +ImageBox1.ReadBinary2 bArray 'ImageBox1 ist the csxImage OCX + +End Sub + +Private Sub Timer1_Timer() +Dim dummy As Variant + +If CameraIP.Text > "" Then + +If Not Inet2.StillExecuting Then +dummy = Inet2.OpenURL("http://" & CameraIP.Text & "/cam.cgi?mode=startstream_ &value=49199") +'Inet2 ->Microsoft Inet control +End If + +End If + +End Sub +*/ +struct sockaddr_in address; +int sock = 0, valread; +struct sockaddr_in serv_addr; +char *hello = "Hello from client"; +char buffer[1024] = {0}; +if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) +{ +printf("\n Socket creation error \n"); +return -1; +} + +memset(&serv_addr, '0', sizeof(serv_addr)); + +serv_addr.sin_family = AF_INET; +serv_addr.sin_port = htons(49199); + +// Convert IPv4 and IPv6 addresses from text to binary form +if(inet_pton(AF_INET, CAMERAIP, &serv_addr.sin_addr)<=0) +{ +printf("\nInvalid address/ Address not supported \n"); +return -1; +} + +if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) +{ +printf("\nConnection Failed \n"); +return -1; +} +valread = read( sock , buffer, 1024); +printf("%s\n",buffer ); +return 0; + + + +} +return GP_OK; +} + + +/** +* Fill list with abilities of the cameras supported by this camlib. +* +* For each camera, fill a CameraAbilities structure with data about +* that camera and append it to the list. +* +* The job of this function is basically to extract data from a +* camlib specific database and insert it into the libgphoto2 camera +* database. Due to redundant data and other issues, we may decide to +* revise that database mechanism and replace it by something more +* flexible and efficient. +* +* This is a camlib API function. +*/ +int camera_abilities (CameraAbilitiesList *list) { +CameraAbilities a; + +memset(&a, 0, sizeof(a)); +strcpy(a.model, "Panasonic:LumixGSeries"); +a.status = GP_DRIVER_STATUS_EXPERIMENTAL; +a.port = GP_PORT_PTPIP; +a.speed[0] = 0; +a.operations = GP_CAPTURE_IMAGE| GP_OPERATION_CAPTURE_VIDEO| GP_OPERATION_CONFIG; +a.file_operations = GP_FILE_OPERATION_PREVIEW ; +/* it should be possible to browse and DL images the files using the ReadImageFromCamera() function but for now lets keep it simple*/ +a.folder_operations = GP_FOLDER_OPERATION_NONE; +gp_abilities_list_append(list, a); + +return GP_OK; +} + +/** +* All filesystem accessor functions. +* +* This should contain all filesystem accessor functions +* available in the camera library. Non-present fields +* are NULL. +* +*/ +CameraFilesystemFuncs fsfuncs = { +// .file_list_func = file_list_func, +// .folder_list_func = folder_list_func, +// .get_info_func = get_info_func, +// .set_info_func = set_info_func, +.get_file_func = get_file_func, // maybe this works for liveview preview +// .del_file_func = delete_file_func, +// .put_file_func = put_file_func, +// .delete_all_func = delete_all_func, +// .storage_info_func = storage_info_func +}; + +/** +* Initialize a Camera object. +* +* Sets up all the proper object function pointers, initialize camlib +* internal data structures, and probably establish a connection to +* the camera. +* +* This is a camlib API function. +*/ +int +camera_init (Camera *camera, GPContext *context) +{ + GPPortInfo info; + char *xpath; + int ret; + + /* First, set up all the function pointers */ + camera->functions->exit = camera_exit; + camera->functions->get_config = camera_config_get; + camera->functions->set_config = camera_config_set; + camera->functions->capture = camera_capture; + camera->functions->capture_preview = camera_capture_preview; + camera->functions->summary = camera_summary; + camera->functions->manual = camera_manual; + camera->functions->about = camera_about; + + curl_global_init(CURL_GLOBAL_ALL); + + ret = gp_port_get_info (camera->port, &info); + if (ret != GP_OK) { + GP_LOG_E ("Failed to get port info?"); + return ret; + } + gp_port_info_get_path (info, &xpath); + /* xpath now contains tcp:192.168.1.1 */ + + gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera); + + if (loadCmd(camera,PLAYMODE)) + return GP_OK; + else + return GP_ERROR_IO; +} diff --git a/configure.ac b/configure.ac index e6820a1d3..fc4966f69 100644 --- a/configure.ac +++ b/configure.ac @@ -504,6 +504,7 @@ GP_CAMLIB([konica],[outdated])dnl GP_CAMLIB([konica_qm150],[outdated])dnl GP_CAMLIB([largan],[outdated])dnl GP_CAMLIB([lg_gsm],[outdated])dnl +GP_CAMLIB([lumix])dnl GP_CAMLIB([mars])dnl GP_CAMLIB([dimagev])dnl GP_CAMLIB([mustek],[outdated])dnl diff --git a/libgphoto2_port/gphoto2/gphoto2-port-info-list.h b/libgphoto2_port/gphoto2/gphoto2-port-info-list.h index d611b8157..eec6ceabe 100644 --- a/libgphoto2_port/gphoto2/gphoto2-port-info-list.h +++ b/libgphoto2_port/gphoto2/gphoto2-port-info-list.h @@ -38,7 +38,8 @@ typedef enum { GP_PORT_DISK = 1 << 3, /**< \brief Disk / local mountpoint port. */ GP_PORT_PTPIP = 1 << 4, /**< \brief PTP/IP port. */ GP_PORT_USB_DISK_DIRECT = 1 << 5, /**< \brief Direct IO to an usb mass storage device. */ - GP_PORT_USB_SCSI = 1 << 6 /**< \brief USB Mass Storage raw SCSI port. */ + GP_PORT_USB_SCSI = 1 << 6, /**< \brief USB Mass Storage raw SCSI port. */ + GP_PORT_TCP = 1 << 7 /**< \brief generic TCP port. */ } GPPortType; /** diff --git a/libgphoto2_port/ptpip/ptpip.c b/libgphoto2_port/ptpip/ptpip.c index 3b60d8a37..225419a9d 100644 --- a/libgphoto2_port/ptpip/ptpip.c +++ b/libgphoto2_port/ptpip/ptpip.c @@ -185,6 +185,18 @@ gp_port_library_list (GPPortInfoList *list) gp_port_info_set_path (info, "^ptpip:"); gp_port_info_list_append (list, info); /* do not check return */ + gp_port_info_new (&info); + gp_port_info_set_type (info, GP_PORT_TCP); + gp_port_info_set_name (info, _("TCP Connection")); + gp_port_info_set_path (info, "tcp:"); + CHECK (gp_port_info_list_append (list, info)); + + /* Generic matcher so you can pass any IP address */ + gp_port_info_new (&info); + gp_port_info_set_type (info, GP_PORT_TCP); + gp_port_info_set_name (info, ""); + gp_port_info_set_path (info, "^tcp:"); + gp_port_info_list_append (list, info); /* do not check return */ #ifdef HAVE_MDNS_BONJOUR ret = DNSServiceBrowse ( &sd, -- cgit v1.2.1 From 84d25b3d53929f245dae21ea28474a04a5705d2e Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Sun, 26 May 2019 21:43:14 +0200 Subject: change to por tTCP --- camlibs/lumix/lumix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 72cf09a41..319122850 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -881,7 +881,7 @@ CameraAbilities a; memset(&a, 0, sizeof(a)); strcpy(a.model, "Panasonic:LumixGSeries"); a.status = GP_DRIVER_STATUS_EXPERIMENTAL; -a.port = GP_PORT_PTPIP; +a.port = GP_PORT_TCP; a.speed[0] = 0; a.operations = GP_CAPTURE_IMAGE| GP_OPERATION_CAPTURE_VIDEO| GP_OPERATION_CONFIG; a.file_operations = GP_FILE_OPERATION_PREVIEW ; -- cgit v1.2.1 From 7e2dea634f1b546a62a2872e01d9f752688156d8 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Mon, 27 May 2019 07:36:56 +0200 Subject: make it link --- camlibs/lumix/Makefile-files | 2 +- camlibs/lumix/lumix.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/camlibs/lumix/Makefile-files b/camlibs/lumix/Makefile-files index a975d6dc1..abc00f041 100644 --- a/camlibs/lumix/Makefile-files +++ b/camlibs/lumix/Makefile-files @@ -9,4 +9,4 @@ lumix_la_SOURCES = lumix/lumix.c lumix_la_CFLAGS = $(AM_CFLAGS) $(NO_UNUSED_CFLAGS) $(CFLAGS) lumix_la_LDFLAGS = $(camlib_ldflags) lumix_la_DEPENDENCIES = $(camlib_dependencies) -lumix_la_LIBADD = $(camlib_libadd) +lumix_la_LIBADD = $(camlib_libadd) -lcurl -lxml2 diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 319122850..63d15b833 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -1,5 +1,6 @@ /** \file lumix.c * + * \author Copyright 2019 Robert Hasson * \author Copyright 2019 Marcus Meissner * * \par -- cgit v1.2.1 From 2a53dd177798678a08e72433f3d7bfb2a0af86ed Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Mon, 27 May 2019 08:03:35 +0200 Subject: use cameraip from port --- camlibs/lumix/lumix.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 63d15b833..10d6d327e 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -331,10 +331,15 @@ static char* loadCmd (Camera *camera,char* cmd) { char URL[100]; //xmlDoc *doc = NULL; //xmlNode *root_element = NULL; + GPPortInfo info; + char *xpath; curl = curl_easy_init(); - snprintf( URL,100, "http://%s/cam.cgi%s",CAMERAIP, cmd); + gp_port_get_info (camera->port, &info); + gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ + snprintf( URL,100, "http://%s/cam.cgi%s", xpath+4, cmd); + GP_LOG_D("cam url is %s", URL); curl_easy_setopt(curl, CURLOPT_URL, URL); //curl_easy_setopt(curl, CURLOPT_READ, URL); if (!stream) { @@ -446,8 +451,8 @@ static char* NumberPix(Camera *camera) { /*utility function to creat a SOAP envelope for the lumix cam */ static char* SoapEnvelop(int start, int num){ - static char Envelop[500]; - snprintf(Envelop,500, "0BrowseDirectChildren* %d %dLumixLink2.0",start,num); + static char Envelop[1000]; + snprintf(Envelop,1000, "0BrowseDirectChildren* %d %dLumixLink2.0",start,num); return Envelop; } @@ -464,13 +469,18 @@ static char* GetPix(Camera *camera,int num) { curl = curl_easy_init(); CURLcode res; struct curl_slist *list = NULL; + GPPortInfo info; + char *xpath; list = curl_slist_append(list, "soapaction"); list = curl_slist_append(list, "Content-Type: text/xml; charset=\"utf-8\""); list = curl_slist_append(list, "urn:schemas-upnp-org:service:ContentDirectory:1#Browse:"); char URL[1000]; - snprintf( URL,1000, "http://%s/cam.cgi%s",CAMERAIP, CDS_Control); + gp_port_get_info (camera->port, &info); + gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ + snprintf( URL,1000, "http://%s/cam.cgi%s",xpath+4, CDS_Control); + GP_LOG_D("camera url is %s", URL); curl_easy_setopt(curl, CURLOPT_URL, URL); //curl_easy_setopt(curl, CURLOPT_READ, URL); curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); -- cgit v1.2.1 From 1e34cedae000de6d7a6df61c5aa381d9b21c2459 Mon Sep 17 00:00:00 2001 From: Robert Hasson Date: Fri, 7 Jun 2019 11:26:03 +0200 Subject: updates from Robert --- camlibs/lumix/lumix.c | 401 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 258 insertions(+), 143 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 10d6d327e..8c26ad8f8 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -29,6 +29,10 @@ #include #include #include +#include +#include +#include + #include #include @@ -39,6 +43,7 @@ #include #include + #define GP_MODULE "lumix" #define CHECK(result) \ @@ -87,8 +92,8 @@ char* CDS_Control = ":60606/Server0/CDS_control"; char* STARTSTREAM = "cam.cgi?mode=startstream&value=49199"; char* CAMERAIP = "192.168.1.24"; //placeholder until there is a better way to discover the IP from the network and via PTPIP int buflen = 10000; -static char Buffer[10000-1]; -int ReadoutMode = 0; // this should be picked up from the settings.... 0-> JPG; 1->RAW; 2 -> Thumbnails +char Buffer[10000-1]; +int ReadoutMode = 2; // this should be picked up from the settings.... 0-> JPG; 1->RAW; 2 -> Thumbnails char* cameraShutterSpeed = "B"; // //placeholder to store the value of the shutterspeed set in camera; "B" is for bulb. int captureDuration = 10; //placeholder to store the value of the bulb shot this should be taken as input. note that my primary goal is in fact to perform bulb captures. but this should be extended for sure to take Shutter Speed capture as set in camera @@ -119,7 +124,7 @@ camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) } -int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context); +//int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context); static int camera_about (Camera *camera, CameraText *about, GPContext *context); @@ -311,41 +316,96 @@ camera_id (CameraText *id) return GP_OK; } -/*size_t read_callback(char *buffer, size_t size, size_t nitems, void *userdata);*/ +size_t read_data(void *ptr, size_t size, size_t nmeb, void *stream); + +size_t read_data(void *ptr, size_t size, size_t nmeb, void *stream) +{ + return fread(ptr,size,nmeb,stream); +} + +char *replaceWord(const char *s, const char *oldW, + const char *newW) +{ + char *result; + int i, cnt = 0; + int newWlen = strlen(newW); + int oldWlen = strlen(oldW); + + // Counting the number of times old word + // occur in the string + for (i = 0; s[i] != '\0'; i++) + { + if (strstr(&s[i], oldW) == &s[i]) + { + cnt++; + + // Jumping to index after the old word. + i += oldWlen - 1; + } + } + + // Making new string of enough length + result = (char *)malloc(i + cnt * (newWlen - oldWlen) + 1); + + i = 0; + while (*s) + { + // compare the substring with the result + if (strstr(s, oldW) == s) + { + strcpy(&result[i], newW); + i += newWlen; + s += oldWlen; + } + else + result[i++] = *s++; + } + + result[i] = '\0'; + return result; +} + + +size_t write_callback(char *contents, size_t size, size_t nmemb, void *userp); + +size_t write_callback(char *contents, size_t size, size_t nmemb, void *userp) +{ -static size_t -read_callback(void *ptr, size_t size, size_t nmemb, void *stream) { - curl_off_t nread; - /* in real-world cases, this would probably get this data differently - as this fread() stuff is exactly what the library already would do - by default internally */ - size_t retcode = fread(ptr, size, nmemb, stream); - nread = (curl_off_t)retcode; - return retcode; + size_t realsize = size * nmemb; + if (Buffer[0]=='\0') { + memcpy(Buffer,contents,realsize); + } + else { + memcpy(strchr(Buffer,'\0'),contents,realsize); + } + + return realsize; + } -static char* loadCmd (Camera *camera,char* cmd) { - CURL *curl; + +char* loadCmd (Camera *camera,char* cmd) { + CURL *curl; CURLcode res; int stream = strcmp (cmd, STARTSTREAM); char URL[100]; - //xmlDoc *doc = NULL; - //xmlNode *root_element = NULL; + GPPortInfo info; char *xpath; - + curl = curl_easy_init(); - + memset(Buffer,'\0',buflen-1); gp_port_get_info (camera->port, &info); gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ - snprintf( URL,100, "http://%s/cam.cgi%s", xpath+4, cmd); + snprintf( URL,100, "http://%s/%s", xpath+4, cmd); GP_LOG_D("cam url is %s", URL); curl_easy_setopt(curl, CURLOPT_URL, URL); - //curl_easy_setopt(curl, CURLOPT_READ, URL); - if (!stream) { - curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); - curl_easy_setopt(curl, CURLOPT_READDATA, camera); + + if (stream!=0) { + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, Buffer); } + res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", @@ -355,10 +415,17 @@ static char* loadCmd (Camera *camera,char* cmd) { /* read the XML that is now in Buffer*/ } curl_easy_cleanup(curl); - if (!stream) { + + + if (stream != 0) { + if (strcmp(cmd,PLAYMODE)==0) { + } return Buffer; + + } else { return NULL; + } // TO DO the idea would be to return the socket to the actual video stream here.... } @@ -379,6 +446,13 @@ static void Set_Speed(Camera *camera,const char* SpeedValue) { loadCmd(camera,buf); } +static void Set_quality(Camera *camera,const char* Quality) { + char buf[200]; + sprintf(buf,"%s%s", QUALITY,Quality); + loadCmd(camera,buf); +} + + static void startStream(Camera *camera) { loadCmd(camera,"?mode=startstream&value=49199"); } @@ -427,11 +501,27 @@ this is the XML sample to be parsed by the function below NumberPix() */ -static char* NumberPix(Camera *camera) { - xmlChar *key; - xmlDocPtr doc = xmlParseDoc((unsigned char*)loadCmd(camera,NUMPIX)); +int strend(const char *s, const char *t) +{ + size_t ls = strlen(s); // find length of s + size_t lt = strlen(t); // find length of t + if (ls >= lt) // check if t can fit in s + { + // point s to where t should start and compare the strings from there + return (0 == memcmp(t, s + (ls - lt), lt)); + } + return 0; // t was longer than s +} + + +char* NumberPix(Camera *camera) { + xmlChar *keyz ; + char *temp = loadCmd(camera,NUMPIX); + xmlDocPtr doc = xmlParseDoc((unsigned char*) temp); xmlNodePtr cur = NULL; cur = xmlDocGetRootElement(doc); +// GP_LOG_D("NumberPix Decode current root node is %s \n", doc); + if (cur == NULL) { fprintf(stderr,"empty document\n"); xmlFreeDoc(doc); @@ -439,20 +529,21 @@ static char* NumberPix(Camera *camera) { } cur = cur->xmlChildrenNode; while (cur != NULL) { + // GP_LOG_D("NumberPix Decode current node is %s \n", (char*)cur); if ((!xmlStrcmp(cur->name, (const xmlChar *)"content_number"))){ - key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - return (char*) key; - } + keyz = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } cur = cur->next; } - return ""; + GP_LOG_D("NumberPix Found is %s \n", (char *) keyz); + return strdup((char *) keyz); } /*utility function to creat a SOAP envelope for the lumix cam */ static char* SoapEnvelop(int start, int num){ static char Envelop[1000]; - snprintf(Envelop,1000, "0BrowseDirectChildren* %d %dLumixLink2.0",start,num); + snprintf(Envelop,1000, "0BrowseDirectChildren*%d%dLumixLink2.0",start,num); return Envelop; } @@ -464,7 +555,11 @@ static char* GetPix(Camera *camera,int num) { loadCmd(camera,PLAYMODE); int Start = 0; long NumPix = strtol(NumberPix(camera), NULL, 10); + //GP_LOG_D("NumPix is %d \n", NumPix); + char* SoapMsg = SoapEnvelop((NumPix - num)> 0?(NumPix - num):0, num); + //GP_LOG_D("SoapMsg is %s \n", SoapMsg); + CURL *curl; curl = curl_easy_init(); CURLcode res; @@ -472,33 +567,39 @@ static char* GetPix(Camera *camera,int num) { GPPortInfo info; char *xpath; - list = curl_slist_append(list, "soapaction"); + list = curl_slist_append(list, "SOAPaction: urn:schemas-upnp-org:service:ContentDirectory:1#Browse"); list = curl_slist_append(list, "Content-Type: text/xml; charset=\"utf-8\""); - list = curl_slist_append(list, "urn:schemas-upnp-org:service:ContentDirectory:1#Browse:"); - + list = curl_slist_append(list, "Accept: text/xml"); + char URL[1000]; + memset(Buffer,'\0',buflen-1); gp_port_get_info (camera->port, &info); gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ - snprintf( URL,1000, "http://%s/cam.cgi%s",xpath+4, CDS_Control); - GP_LOG_D("camera url is %s", URL); + snprintf( URL,1000, "http://%s%s",xpath+4, CDS_Control); curl_easy_setopt(curl, CURLOPT_URL, URL); - //curl_easy_setopt(curl, CURLOPT_READ, URL); - curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); - curl_easy_setopt(curl, CURLOPT_READDATA, Buffer); + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + + curl_easy_setopt(curl, CURLOPT_WRITEDATA, Buffer); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); + curl_easy_setopt(curl, CURLOPT_POST,1); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) strlen(SoapMsg)); + + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, SoapMsg); + GP_LOG_D("camera url is %s", URL); + res = curl_easy_perform(curl); if(res != CURLE_OK) { - fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); } else { - /* read the XML that is now in Buffer*/ - - } + /* read the XML that is now in Buffer*/ + strcpy(Buffer,replaceWord(replaceWord(replaceWord(replaceWord(replaceWord(Buffer,"&", "&"),"'", "'"), """, "\""), "<", "<"),">", ">")); + } curl_easy_cleanup(curl); return Buffer; - } /** @@ -517,7 +618,7 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) static int waitBulb(Camera *camera, long Duration ) { - sleep(Duration * 1000); // Sleep for the duration to simulate exposure, if this is in Bulb mode + sleep(Duration); // Sleep for the duration to simulate exposure, if this is in Bulb mode loadCmd(camera,SHUTTERSTOP); return TRUE; } @@ -527,7 +628,39 @@ static size_t dl_write(void *buffer, size_t size, size_t nmemb, void *stream) return fwrite(buffer, size, nmemb, (FILE*)stream); } +char* processNode(xmlTextReaderPtr reader) { + + char* ret =""; + char* lookupImgtag=""; + + switch (ReadoutMode) { + case 0 : //'jpg + lookupImgtag = "CAM_RAW_JPG"; + break; + case 1 :// 'raw + lookupImgtag = "CAM_RAW"; + break; + case 2 ://'thumb + lookupImgtag = "CAM_LRGTN"; + break; + } + const xmlChar *name, *value; + + name = xmlTextReaderConstName(reader); + if (name == NULL) + name = BAD_CAST "--"; + if (xmlTextReaderNodeType(reader) == 1) { // Element + while (xmlTextReaderMoveToNextAttribute(reader)){ + if (strend(xmlTextReaderConstValue(reader),lookupImgtag)) { + xmlTextReaderRead(reader); + ret = xmlTextReaderConstValue(reader); + printf("the image file is %s\n" ,ret); + } + } + } + return ret; +} /* @@ -584,105 +717,86 @@ case RAW: */ -static char* ReadImageFromCamera(Camera *camera) { - xmlDocPtr Pictures =xmlParseDoc((xmlChar*)GetPix(camera,1)); //the XML with all the results from the camea - xmlNodePtr PictureList = NULL; //the list of picture items extratec - xmlNode *Picture, *cur; //a singlepicture item - cur = xmlDocGetRootElement(Pictures); - char *Images[250]; //the array of the urls in the camera - long nRead[250]; - int j = -1; +static CameraFilePath * ReadImageFromCamera(Camera *camera) { + char *Images; //the array of the urls in the camera + long nRead; int SendStatus = -1; int length = 0; - PictureList = xmlFirstElementChild(xmlFirstElementChild(xmlFirstElementChild(xmlFirstElementChild(Pictures->last))))->children ;//items - //xmlFirstElementChild - //PictureList = Pictures.LastChild.FirstChild.FirstChild.FirstChild.FirstChild.ChildNodes 'items - loadCmd(camera,PLAYMODE); // 'making sure the camera is in Playmode + char* xmlimageName; + xmlDocPtr doc; /* the resulting document tree */ + int ret; + LIBXML_TEST_VERSION + + char* imageURL=""; + xmlTextReaderPtr reader; + reader = xmlReaderForDoc(GetPix(camera,1), NULL,"noname.xml", + XML_PARSE_DTDATTR | /* default DTD attributes */ + XML_PARSE_NOENT); + ret = xmlTextReaderRead(reader); + while (ret == 1) { + imageURL =processNode(reader); + if (imageURL !="") + break; + ret = xmlTextReaderRead(reader); + } - Picture = PictureList->xmlChildrenNode; - while (Picture != NULL) { - // if ((!xmlStrcmp(cur->name, (const xmlChar *)"content_number"))){ - // key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - // return (char*) key; - // } - - // Else 'JPG or Thumbnails - char* lookuptag; - int lookupNum; - char* xmlimageName; - - if (ReadoutMode == 0) { - lookuptag = "DO" ;//full JPG - lookupNum = 3; - xmlimageName = (char*)Picture->children->next->next->name; - } else { - lookuptag = "DL" ; //large thumbnail - lookupNum = 5; - xmlimageName = (char*)Picture->children->next->next->next->next->name; + GP_DEBUG("the image URL is %s\n",imageURL); + Images = strdup(imageURL); + nRead = 0; + CURL* imageUrl; + imageUrl = curl_easy_init(); + CURLcode res; + double bytesread = 0; + FILE* imageFile; + char filename[100]; + char* tempPath = "./"; + long http_response; + int ret_val=0; + memset(Buffer,'\0',buflen-1); + while (ret_val!=2) { + snprintf(filename,100,"%s%s",tempPath,&Images[strlen(Images)- 13]); + imageFile = fopen(filename,"ab"); + GP_DEBUG("reading stream %s position %ld", Images, nRead); + + curl_easy_setopt(imageUrl, CURLOPT_URL, Images); + //curl_easy_setopt(imageUrl,CURLOPT_TCP_KEEPALIVE,1L); + //curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPIDLE, 120L); + //curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPINTVL, 60L); + //curl_easy_setopt(imageUrl, CURLOPT_WRITEFUNCTION, dl_write); + + if (nRead) { + curl_easy_setopt(imageUrl, CURLOPT_RESUME_FROM, nRead); + GetPix(camera,1);//'if the file not found happened then this trick is to get the camera in a readmode again and making sure it remembers the filename + GP_DEBUG("continuing the read where it stopped %s position %ld", Images, nRead); } + curl_easy_setopt(imageUrl, CURLOPT_WRITEDATA, imageFile); + res = curl_easy_perform(imageUrl); - if ((strstr(xmlimageName,"JPG")&& strstr(xmlimageName, lookuptag))||strstr(xmlimageName,"RAW")) { - // If Picture.ChildNodes(lookupNum).InnerText.Contains(".JPG") And Picture.ChildNodes(lookupNum).InnerText.Contains(lookuptag) Then - j = j + 1; - Images[j] = strdup(xmlimageName); - nRead[j] = 0; - CURL* imageUrl; - imageUrl = curl_easy_init(); - CURLcode res; - double bytesread = 0; - FILE* imageFile; - char filename[100]; - char* tempPath = "C:\\"; - long http_response; - int ret_val=0; - - while (ret_val!=2) { - snprintf(filename,100,"%s%s",tempPath,Images[j][strlen(Images[j])- 13]); - imageFile = fopen(filename,"ab"); - GP_DEBUG("reading stream %s position %ld", Images[j], nRead[j]); - - curl_easy_setopt(imageUrl, CURLOPT_URL, Images[j]); - curl_easy_setopt(imageUrl,CURLOPT_TCP_KEEPALIVE,1L); - curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPIDLE, 120L); - curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPINTVL, 60L); - curl_easy_setopt(imageUrl, CURLOPT_WRITEFUNCTION, dl_write); - //curl_easy_setopt(imageUrl, CURLOPT_PROGRESSFUNCTION, dl_progress); - //curl_easy_setopt(imageUrl, CURLOPT_NOPROGRESS, 0); - - if (nRead[j]) { - curl_easy_setopt(imageUrl, CURLOPT_RESUME_FROM, nRead[j]); - GetPix(camera,1);//'if the file not found happened then this trick is to get the camera in a readmode again and making sure it remembers the filename - GP_DEBUG("continuing the read where it stopped %s position %ld", Images[j], nRead[j]); - } - curl_easy_setopt(imageUrl, CURLOPT_WRITEDATA, imageFile); - - res = curl_easy_perform(imageUrl); - if(res != CURLE_OK) { - double x; - curl_easy_getinfo(imageUrl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &x); - nRead[j] = x; - fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); - GP_DEBUG("error in reading stream %s position %ld", Images[j], nRead[j]); - - curl_easy_getinfo(imageUrl, CURLINFO_RESPONSE_CODE, &http_response); - - GP_DEBUG("CURLINFO_RESPONSE_CODE:%ld\n", http_response); - } else { - GP_DEBUG("read the whole file"); - ret_val=2; - } - } - curl_easy_cleanup(imageUrl); - fclose(imageFile); - return strdup(filename); + if(res != CURLE_OK) { + + //double x; + //curl_easy_getinfo(imageUrl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &x); + //nRead = x; + fseek(imageFile, 0, SEEK_END); // seek to end of file + nRead= ftell(imageFile); // get current file pointer + + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + GP_DEBUG("error in reading stream %s position %ld", Images, nRead); + curl_easy_getinfo(imageUrl, CURLINFO_RESPONSE_CODE, &http_response); + GP_DEBUG("CURLINFO_RESPONSE_CODE:%ld\n", http_response); + } else { + GP_DEBUG("read the whole file"); + ret_val=2; } - Picture = Picture->next; } - return NULL; + curl_easy_cleanup(imageUrl); + fclose(imageFile); + return (CameraFilePath *) strdup(filename); + } @@ -694,11 +808,12 @@ static char* ReadImageFromCamera(Camera *camera) { */ int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context); int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context){ - loadCmd(camera,"capture"); //we should really multithread so as to not block while waiting - if (!strcmp(cameraShutterSpeed, "B")) { + loadCmd(camera,SHUTTERSTART); //we should really multithread so as to not block while waiting + sleep(4); + if (strcmp(cameraShutterSpeed, "B")!=0) { waitBulb(camera,captureDuration);//trying captureDuration sec to start before we know how to make a bulb capture of x sec .... } - path = ReadImageFromCamera(camera); + path = ReadImageFromCamera(camera); return GP_OK; } @@ -866,7 +981,6 @@ printf("%s\n",buffer ); return 0; - } return GP_OK; } @@ -961,8 +1075,9 @@ camera_init (Camera *camera, GPContext *context) gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera); - if (loadCmd(camera,PLAYMODE)) + if (loadCmd(camera,RECMODE)!= NULL){ + Set_quality(camera,"raw_fine"); return GP_OK; - else + } else return GP_ERROR_IO; } -- cgit v1.2.1 From 41dda378cacaea6bea2098b170989ed67c8facbd Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Tue, 25 Jun 2019 12:54:13 +0200 Subject: current state of work - better buffer handling - some more XML decoding in picture info retrieval --- camlibs/lumix/lumix.c | 320 +++++++++++++++++++++++++++++--------------------- 1 file changed, 189 insertions(+), 131 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 8c26ad8f8..b37a499b1 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -91,12 +91,17 @@ char* QUALITY = "cam.cgi?mode=setsetting&type=quality&value="; char* CDS_Control = ":60606/Server0/CDS_control"; char* STARTSTREAM = "cam.cgi?mode=startstream&value=49199"; char* CAMERAIP = "192.168.1.24"; //placeholder until there is a better way to discover the IP from the network and via PTPIP -int buflen = 10000; -char Buffer[10000-1]; int ReadoutMode = 2; // this should be picked up from the settings.... 0-> JPG; 1->RAW; 2 -> Thumbnails char* cameraShutterSpeed = "B"; // //placeholder to store the value of the shutterspeed set in camera; "B" is for bulb. int captureDuration = 10; //placeholder to store the value of the bulb shot this should be taken as input. note that my primary goal is in fact to perform bulb captures. but this should be extended for sure to take Shutter Speed capture as set in camera +static int NumberPix(Camera *camera); + +typedef struct { + char *data; + size_t size; +} LumixMemoryBuffer; + struct _CameraPrivateLibrary { /* all private data */ }; @@ -214,15 +219,7 @@ get_info_func (CameraFilesystem *fs, const char *folder, const char *filename, } -/** - * FIXME. - * - * This function is a CameraFilesystem method. - */ -int -set_info_func (CameraFilesystem *fs, const char *folder, const char *file, - CameraFileInfo info, void *data, GPContext *context); -int +static int set_info_func (CameraFilesystem *fs, const char *folder, const char *file, CameraFileInfo info, void *data, GPContext *context) { @@ -234,22 +231,12 @@ set_info_func (CameraFilesystem *fs, const char *folder, const char *file, } -/** - * List available folders in the specified folder. - * - * This function is a CameraFilesystem method. - */ -int -folder_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, - void *data, GPContext *context); -int +static int folder_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, void *data, GPContext *context) { /*Camera *camera = data;*/ - - /* List your folders here */ - + /* currently no folders exposed */ return GP_OK; } @@ -266,9 +253,9 @@ int file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, void *data, GPContext *context) { - /*Camera *camera = data;*/ + Camera *camera = data; - /* List your files here */ + int numpix = NumberPix(camera); return GP_OK; } @@ -316,14 +303,7 @@ camera_id (CameraText *id) return GP_OK; } -size_t read_data(void *ptr, size_t size, size_t nmeb, void *stream); - -size_t read_data(void *ptr, size_t size, size_t nmeb, void *stream) -{ - return fread(ptr,size,nmeb,stream); -} - -char *replaceWord(const char *s, const char *oldW, +static char *replaceWord(const char *s, const char *oldW, const char *newW) { char *result; @@ -365,71 +345,69 @@ char *replaceWord(const char *s, const char *oldW, return result; } - -size_t write_callback(char *contents, size_t size, size_t nmemb, void *userp); - -size_t write_callback(char *contents, size_t size, size_t nmemb, void *userp) +static size_t +write_callback(char *contents, size_t size, size_t nmemb, void *userp) { + size_t realsize = size * nmemb; + size_t oldsize; + LumixMemoryBuffer *lmb = userp; - size_t realsize = size * nmemb; - if (Buffer[0]=='\0') { - memcpy(Buffer,contents,realsize); - } - else { - memcpy(strchr(Buffer,'\0'),contents,realsize); - } - + oldsize = lmb->size; + lmb->data = realloc(lmb->data, lmb->size+realsize); + lmb->size += realsize; + + gp_log (GP_LOG_DATA, "read from camera", contents, realsize); + + memcpy(lmb->data+oldsize,contents,realsize); return realsize; - } -char* loadCmd (Camera *camera,char* cmd) { +static char* loadCmd (Camera *camera,char* cmd) { CURL *curl; CURLcode res; int stream = strcmp (cmd, STARTSTREAM); char URL[100]; - GPPortInfo info; char *xpath; + LumixMemoryBuffer lmb; curl = curl_easy_init(); - memset(Buffer,'\0',buflen-1); gp_port_get_info (camera->port, &info); gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ snprintf( URL,100, "http://%s/%s", xpath+4, cmd); GP_LOG_D("cam url is %s", URL); + curl_easy_setopt(curl, CURLOPT_URL, URL); - - if (stream!=0) { + + if (stream!=0) { + lmb.size = 0; + lmb.data = malloc(0); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, Buffer); - } + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &lmb); + } res = curl_easy_perform(curl); if(res != CURLE_OK) { - fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); return NULL; } else { /* read the XML that is now in Buffer*/ + GP_LOG_D("result %s\n", lmb.data); + + /* ok */ } curl_easy_cleanup(curl); - if (stream != 0) { if (strcmp(cmd,PLAYMODE)==0) { } - return Buffer; - - + return lmb.data; } else { return NULL; - } // TO DO the idea would be to return the socket to the actual video stream here.... } - static void switchToRecMode(Camera *camera) { loadCmd(camera,"?mode=camcmd&value=recmode"); } @@ -501,7 +479,8 @@ this is the XML sample to be parsed by the function below NumberPix() */ -int strend(const char *s, const char *t) +static int +strend(const char *s, const char *t) { size_t ls = strlen(s); // find length of s size_t lt = strlen(t); // find length of t @@ -513,30 +492,34 @@ int strend(const char *s, const char *t) return 0; // t was longer than s } +static int +NumberPix(Camera *camera) { + xmlChar *keyz = NULL; -char* NumberPix(Camera *camera) { - xmlChar *keyz ; char *temp = loadCmd(camera,NUMPIX); xmlDocPtr doc = xmlParseDoc((unsigned char*) temp); xmlNodePtr cur = NULL; cur = xmlDocGetRootElement(doc); -// GP_LOG_D("NumberPix Decode current root node is %s \n", doc); + /*GP_LOG_D("NumberPix Decode current root node is %s \n", doc); */ if (cur == NULL) { fprintf(stderr,"empty document\n"); xmlFreeDoc(doc); - return NULL; + return GP_ERROR; } cur = cur->xmlChildrenNode; while (cur != NULL) { - // GP_LOG_D("NumberPix Decode current node is %s \n", (char*)cur); - if ((!xmlStrcmp(cur->name, (const xmlChar *)"content_number"))){ + /*GP_LOG_D("NumberPix Decode current node is %s \n", (char*)cur);*/ + if ((!xmlStrcmp(cur->name, (const xmlChar *)"content_number"))) { keyz = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - } + break; + } cur = cur->next; } + if (!keyz) + return GP_ERROR; GP_LOG_D("NumberPix Found is %s \n", (char *) keyz); - return strdup((char *) keyz); + return strtol((char*)keyz, NULL, 10); } /*utility function to creat a SOAP envelope for the lumix cam */ @@ -548,14 +531,48 @@ SoapEnvelop(int start, int num){ return Envelop; } +static int +traverse_tree (int depth, xmlNodePtr node) +{ + xmlNodePtr next; + xmlChar *xchar; + int n; + char *xx; + + + if (!node) return 0; + xx = malloc (depth * 4 + 1); + memset (xx, ' ', depth*4); + xx[depth*4] = 0; + + n = xmlChildElementCount (node); + + next = node; + do { + fprintf(stderr,"%snode %s\n", xx,next->name); + fprintf(stderr,"%selements %d\n", xx,n); + xchar = xmlNodeGetContent (next); + fprintf(stderr,"%scontent %s\n", xx,xchar); + traverse_tree (depth+1,xmlFirstElementChild (next)); + } while ((next = xmlNextElementSibling (next))); + free (xx); + return 1; +} + + /* * retrieves the XML doc with the last num pictures avail in the camera. */ static char* GetPix(Camera *camera,int num) { loadCmd(camera,PLAYMODE); int Start = 0; - long NumPix = strtol(NumberPix(camera), NULL, 10); + long NumPix = NumberPix(camera); //GP_LOG_D("NumPix is %d \n", NumPix); + xmlDocPtr docin; + xmlNodePtr docroot, output, next; + xmlChar *xchar; + + if (NumPix < GP_OK) return NULL; char* SoapMsg = SoapEnvelop((NumPix - num)> 0?(NumPix - num):0, num); //GP_LOG_D("SoapMsg is %s \n", SoapMsg); @@ -566,25 +583,28 @@ static char* GetPix(Camera *camera,int num) { struct curl_slist *list = NULL; GPPortInfo info; char *xpath; + LumixMemoryBuffer lmb; list = curl_slist_append(list, "SOAPaction: urn:schemas-upnp-org:service:ContentDirectory:1#Browse"); list = curl_slist_append(list, "Content-Type: text/xml; charset=\"utf-8\""); list = curl_slist_append(list, "Accept: text/xml"); char URL[1000]; - memset(Buffer,'\0',buflen-1); gp_port_get_info (camera->port, &info); gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ snprintf( URL,1000, "http://%s%s",xpath+4, CDS_Control); curl_easy_setopt(curl, CURLOPT_URL, URL); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, Buffer); + lmb.size = 0; + lmb.data = malloc(0); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &lmb); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); curl_easy_setopt(curl, CURLOPT_POST,1); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) strlen(SoapMsg)); - + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, SoapMsg); GP_LOG_D("camera url is %s", URL); @@ -593,13 +613,63 @@ static char* GetPix(Camera *camera,int num) { if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); - } - else { - /* read the XML that is now in Buffer*/ - strcpy(Buffer,replaceWord(replaceWord(replaceWord(replaceWord(replaceWord(Buffer,"&", "&"),"'", "'"), """, "\""), "<", "<"),">", ">")); - } + curl_easy_cleanup(curl); + return NULL; + } + docin = xmlReadMemory (lmb.data, lmb.size, "http://gphoto.org/", "utf-8", 0); + if (!docin) return NULL; + docroot = xmlDocGetRootElement (docin); + if (!docroot) { + xmlFreeDoc (docin); + return NULL; + } + if (strcmp((char*)docroot->name,"Envelope")) { + GP_LOG_E("root node is '%s', expected 'Envelope'", docroot->name); + xmlFreeDoc (docin); + return NULL; + } + output = xmlFirstElementChild (docroot); + if (strcmp((char*)output->name,"Body")) { + GP_LOG_E("second level node is %s, expected Body", docroot->name); + xmlFreeDoc (docin); + return NULL; + } + output = xmlFirstElementChild (output); + if (strcmp((char*)output->name,"BrowseResponse")) { + GP_LOG_E("third level node is %s, expected BrowseResponse", docroot->name); + xmlFreeDoc (docin); + return NULL; + } + output = xmlFirstElementChild (output); + if (strcmp((char*)output->name,"Result")) { + GP_LOG_E("fourth level node is %s, expected Result", docroot->name); + xmlFreeDoc (docin); + return NULL; + } + xchar = xmlNodeGetContent (output); + GP_LOG_D("content of %s is %s", output->name, xchar); +/* + + + + 103-0822 + WRITABLE + object.item.imageItem + + http://192.168.54.1:50001/DO1030822.JPG + + + http://192.168.54.1:50001/DT1030822.JPG + + + http://192.168.54.1:50001/DL1030822.JPG + + + + +*/ curl_easy_cleanup(curl); - return Buffer; + return strdup((char*)xchar); } /** @@ -628,11 +698,10 @@ static size_t dl_write(void *buffer, size_t size, size_t nmemb, void *stream) return fwrite(buffer, size, nmemb, (FILE*)stream); } -char* processNode(xmlTextReaderPtr reader) { - +static char* processNode(xmlTextReaderPtr reader) { char* ret =""; char* lookupImgtag=""; - + switch (ReadoutMode) { case 0 : //'jpg lookupImgtag = "CAM_RAW_JPG"; @@ -643,21 +712,22 @@ char* processNode(xmlTextReaderPtr reader) { case 2 ://'thumb lookupImgtag = "CAM_LRGTN"; break; - } + } const xmlChar *name, *value; name = xmlTextReaderConstName(reader); if (name == NULL) name = BAD_CAST "--"; - if (xmlTextReaderNodeType(reader) == 1) { // Element - while (xmlTextReaderMoveToNextAttribute(reader)){ - if (strend(xmlTextReaderConstValue(reader),lookupImgtag)) { - xmlTextReaderRead(reader); - ret = xmlTextReaderConstValue(reader); - printf("the image file is %s\n" ,ret); - } + + if (xmlTextReaderNodeType(reader) == 1) { // Element + while (xmlTextReaderMoveToNextAttribute(reader)) { + if (strend(xmlTextReaderConstValue(reader),lookupImgtag)) { + xmlTextReaderRead(reader); + ret = xmlTextReaderConstValue(reader); + printf("the image file is %s\n" ,ret); } + } } return ret; } @@ -718,12 +788,12 @@ case RAW: */ static CameraFilePath * ReadImageFromCamera(Camera *camera) { - char *Images; //the array of the urls in the camera - long nRead; + char *Images; //the array of the urls in the camera + long nRead; int SendStatus = -1; int length = 0; - loadCmd(camera,PLAYMODE); // 'making sure the camera is in Playmode + loadCmd(camera,PLAYMODE); // 'making sure the camera is in Playmode char* xmlimageName; xmlDocPtr doc; /* the resulting document tree */ int ret; @@ -736,9 +806,9 @@ static CameraFilePath * ReadImageFromCamera(Camera *camera) { XML_PARSE_NOENT); ret = xmlTextReaderRead(reader); while (ret == 1) { - imageURL =processNode(reader); - if (imageURL !="") - break; + imageURL = processNode(reader); + if (strlen(imageURL)) + break; ret = xmlTextReaderRead(reader); } @@ -754,7 +824,6 @@ static CameraFilePath * ReadImageFromCamera(Camera *camera) { char* tempPath = "./"; long http_response; int ret_val=0; - memset(Buffer,'\0',buflen-1); while (ret_val!=2) { snprintf(filename,100,"%s%s",tempPath,&Images[strlen(Images)- 13]); imageFile = fopen(filename,"ab"); @@ -796,7 +865,6 @@ static CameraFilePath * ReadImageFromCamera(Camera *camera) { curl_easy_cleanup(imageUrl); fclose(imageFile); return (CameraFilePath *) strdup(filename); - } @@ -986,35 +1054,19 @@ return GP_OK; } -/** -* Fill list with abilities of the cameras supported by this camlib. -* -* For each camera, fill a CameraAbilities structure with data about -* that camera and append it to the list. -* -* The job of this function is basically to extract data from a -* camlib specific database and insert it into the libgphoto2 camera -* database. Due to redundant data and other issues, we may decide to -* revise that database mechanism and replace it by something more -* flexible and efficient. -* -* This is a camlib API function. -*/ int camera_abilities (CameraAbilitiesList *list) { -CameraAbilities a; - -memset(&a, 0, sizeof(a)); -strcpy(a.model, "Panasonic:LumixGSeries"); -a.status = GP_DRIVER_STATUS_EXPERIMENTAL; -a.port = GP_PORT_TCP; -a.speed[0] = 0; -a.operations = GP_CAPTURE_IMAGE| GP_OPERATION_CAPTURE_VIDEO| GP_OPERATION_CONFIG; -a.file_operations = GP_FILE_OPERATION_PREVIEW ; -/* it should be possible to browse and DL images the files using the ReadImageFromCamera() function but for now lets keep it simple*/ -a.folder_operations = GP_FOLDER_OPERATION_NONE; -gp_abilities_list_append(list, a); - -return GP_OK; + CameraAbilities a; + + memset(&a, 0, sizeof(a)); + strcpy(a.model, "Panasonic:LumixGSeries"); + a.status = GP_DRIVER_STATUS_EXPERIMENTAL; + a.port = GP_PORT_TCP; + a.speed[0] = 0; + a.operations = GP_CAPTURE_IMAGE| GP_OPERATION_CAPTURE_VIDEO| GP_OPERATION_CONFIG; + a.file_operations = GP_FILE_OPERATION_PREVIEW ; + /* it should be possible to browse and DL images the files using the ReadImageFromCamera() function but for now lets keep it simple*/ + a.folder_operations = GP_FOLDER_OPERATION_NONE; + return gp_abilities_list_append(list, a); } /** @@ -1026,8 +1078,8 @@ return GP_OK; * */ CameraFilesystemFuncs fsfuncs = { -// .file_list_func = file_list_func, -// .folder_list_func = folder_list_func, + .file_list_func = file_list_func, + .folder_list_func = folder_list_func, // .get_info_func = get_info_func, // .set_info_func = set_info_func, .get_file_func = get_file_func, // maybe this works for liveview preview @@ -1075,8 +1127,14 @@ camera_init (Camera *camera, GPContext *context) gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera); - if (loadCmd(camera,RECMODE)!= NULL){ + if (loadCmd(camera,RECMODE)!= NULL) { Set_quality(camera,"raw_fine"); + + loadCmd(camera,PLAYMODE); // 'making sure the camera is in Playmode + + NumberPix(camera); + GetPix(camera,651); + return GP_OK; } else return GP_ERROR_IO; -- cgit v1.2.1 From 42c1e7170bddca6e07e407c08ea030f8bd288f33 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Tue, 25 Jun 2019 15:00:06 +0200 Subject: more decoding of images rewrote the image download function to work via memory and not with files --- camlibs/lumix/lumix.c | 205 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 144 insertions(+), 61 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index b37a499b1..da74d77e2 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -102,8 +102,17 @@ typedef struct { size_t size; } LumixMemoryBuffer; +typedef struct { + char *url_large; + char *url_medium; + char *url_thumb; +} LumixPicture; + struct _CameraPrivateLibrary { /* all private data */ + + int numpics; + LumixPicture *pics; }; @@ -356,7 +365,7 @@ write_callback(char *contents, size_t size, size_t nmemb, void *userp) lmb->data = realloc(lmb->data, lmb->size+realsize); lmb->size += realsize; - gp_log (GP_LOG_DATA, "read from camera", contents, realsize); + GP_LOG_DATA(contents, realsize, "lumix read from url"); memcpy(lmb->data+oldsize,contents,realsize); return realsize; @@ -563,39 +572,40 @@ traverse_tree (int depth, xmlNodePtr node) /* * retrieves the XML doc with the last num pictures avail in the camera. */ -static char* GetPix(Camera *camera,int num) { +static char* +GetPix(Camera *camera,int num) { + long NumPix; + xmlDocPtr docin, docin2; + xmlNodePtr docroot, docroot2, output, next; + xmlChar *xchar; + char* SoapMsg; + CURL *curl; + CURLcode res; + struct curl_slist *list = NULL; + GPPortInfo info; + char *xpath; + LumixMemoryBuffer lmb; + char URL[1000]; + loadCmd(camera,PLAYMODE); - int Start = 0; - long NumPix = NumberPix(camera); + NumPix = NumberPix(camera); //GP_LOG_D("NumPix is %d \n", NumPix); - xmlDocPtr docin; - xmlNodePtr docroot, output, next; - xmlChar *xchar; - if (NumPix < GP_OK) return NULL; - char* SoapMsg = SoapEnvelop((NumPix - num)> 0?(NumPix - num):0, num); + SoapMsg = SoapEnvelop((NumPix - num)> 0?(NumPix - num):0, num); //GP_LOG_D("SoapMsg is %s \n", SoapMsg); - CURL *curl; curl = curl_easy_init(); - CURLcode res; - struct curl_slist *list = NULL; - GPPortInfo info; - char *xpath; - LumixMemoryBuffer lmb; list = curl_slist_append(list, "SOAPaction: urn:schemas-upnp-org:service:ContentDirectory:1#Browse"); list = curl_slist_append(list, "Content-Type: text/xml; charset=\"utf-8\""); list = curl_slist_append(list, "Accept: text/xml"); - char URL[1000]; gp_port_get_info (camera->port, &info); gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ - snprintf( URL,1000, "http://%s%s",xpath+4, CDS_Control); + snprintf( URL, 1000, "http://%s%s",xpath+4, CDS_Control); curl_easy_setopt(curl, CURLOPT_URL, URL); - - + lmb.size = 0; lmb.data = malloc(0); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); @@ -605,9 +615,10 @@ static char* GetPix(Camera *camera,int num) { curl_easy_setopt(curl, CURLOPT_POST,1); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) strlen(SoapMsg)); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, SoapMsg); + GP_LOG_D("camera url is %s", URL); + GP_LOG_D("posting %s", SoapMsg); res = curl_easy_perform(curl); if(res != CURLE_OK) { @@ -616,6 +627,8 @@ static char* GetPix(Camera *camera,int num) { curl_easy_cleanup(curl); return NULL; } + curl_easy_cleanup(curl); + docin = xmlReadMemory (lmb.data, lmb.size, "http://gphoto.org/", "utf-8", 0); if (!docin) return NULL; docroot = xmlDocGetRootElement (docin); @@ -668,7 +681,29 @@ static char* GetPix(Camera *camera,int num) { */ - curl_easy_cleanup(curl); + docin2 = xmlReadMemory ((char*)xchar, strlen((char*)xchar), "http://gphoto.org/", "utf-8", 0); + if (!docin2) return NULL; + docroot2 = xmlDocGetRootElement (docin2); + if (!docroot) { + xmlFreeDoc (docin2); + return NULL; + } + if (strcmp((char*)docroot2->name,"DIDL-Lite")) { + GP_LOG_E("expected DIDL-Lite, got %s", docroot->name); + xmlFreeDoc (docin2); + return NULL; + } + output = xmlFirstElementChild (docroot2); + if (strcmp((char*)output->name,"item")) { + GP_LOG_E("expected item, got %s", output->name); + xmlFreeDoc (docin2); + return NULL; + } + next = output; + do { + GP_LOG_D("got %s", next->name); + } while ((next = xmlNextElementSibling (next))); + return strdup((char*)xchar); } @@ -787,11 +822,70 @@ case RAW: */ -static CameraFilePath * ReadImageFromCamera(Camera *camera) { - char *Images; //the array of the urls in the camera - long nRead; - int SendStatus = -1; - int length = 0; +static int +add_objectid_and_upload (Camera *camera, CameraFilePath *path, GPContext *context, char *ximage, size_t size) { + int ret; + CameraFile *file = NULL; + CameraFileInfo info; + + ret = gp_file_new(&file); + if (ret!=GP_OK) return ret; + gp_file_set_mtime (file, time(NULL)); + strcpy(info.file.type, GP_MIME_JPEG); + + GP_LOG_D ("setting size"); + ret = gp_file_set_data_and_size(file, ximage, size); + if (ret != GP_OK) { + gp_file_free (file); + return ret; + } + GP_LOG_D ("append to fs"); + ret = gp_filesystem_append(camera->fs, path->folder, path->name, context); + if (ret != GP_OK) { + gp_file_free (file); + return ret; + } + GP_LOG_D ("adding filedata to fs"); + ret = gp_filesystem_set_file_noop(camera->fs, path->folder, path->name, GP_FILE_TYPE_NORMAL, file, context); + if (ret != GP_OK) { + gp_file_free (file); + return ret; + } + + /* We have now handed over the file, disclaim responsibility by unref. */ + gp_file_unref (file); + + /* we also get the fs info for free, so just set it */ + info.file.fields = GP_FILE_INFO_TYPE | + /*GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT |*/ + GP_FILE_INFO_SIZE /*| GP_FILE_INFO_MTIME */ ; + strcpy(info.file.type, GP_MIME_JPEG); + + info.preview.fields = 0; /* so far none */ +/* + info.file.width = oi->ImagePixWidth; + info.file.height = oi->ImagePixHeight; + info.file.size = oi->ObjectCompressedSize; + info.file.mtime = time(NULL); + + info.preview.fields = GP_FILE_INFO_TYPE | + GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT | + GP_FILE_INFO_SIZE; + strcpy_mime (info.preview.type, params->deviceinfo.VendorExtensionID, oi->ThumbFormat); + info.preview.width = oi->ThumbPixWidth; + info.preview.height = oi->ThumbPixHeight; + info.preview.size = oi->ThumbCompressedSize; +*/ + + GP_LOG_D ("setting fileinfo in fs"); + return gp_filesystem_set_info_noop(camera->fs, path->folder, path->name, info, context); +} + +static int +ReadImageFromCamera(Camera *camera, CameraFilePath *path, GPContext *context) { + char *image; + long nRead; + LumixMemoryBuffer lmb; loadCmd(camera,PLAYMODE); // 'making sure the camera is in Playmode char* xmlimageName; @@ -801,9 +895,7 @@ static CameraFilePath * ReadImageFromCamera(Camera *camera) { char* imageURL=""; xmlTextReaderPtr reader; - reader = xmlReaderForDoc(GetPix(camera,1), NULL,"noname.xml", - XML_PARSE_DTDATTR | /* default DTD attributes */ - XML_PARSE_NOENT); + reader = xmlReaderForDoc(GetPix(camera,1), NULL,"noname.xml", XML_PARSE_DTDATTR | /* default DTD attributes */ XML_PARSE_NOENT); ret = xmlTextReaderRead(reader); while (ret == 1) { imageURL = processNode(reader); @@ -813,48 +905,40 @@ static CameraFilePath * ReadImageFromCamera(Camera *camera) { } GP_DEBUG("the image URL is %s\n",imageURL); - Images = strdup(imageURL); + image = strdup(imageURL); nRead = 0; CURL* imageUrl; imageUrl = curl_easy_init(); CURLcode res; double bytesread = 0; - FILE* imageFile; char filename[100]; - char* tempPath = "./"; long http_response; int ret_val=0; + + while (ret_val!=2) { - snprintf(filename,100,"%s%s",tempPath,&Images[strlen(Images)- 13]); - imageFile = fopen(filename,"ab"); - GP_DEBUG("reading stream %s position %ld", Images, nRead); + GP_DEBUG("reading stream %s position %ld", image, nRead); - curl_easy_setopt(imageUrl, CURLOPT_URL, Images); + curl_easy_setopt(imageUrl, CURLOPT_URL, image); //curl_easy_setopt(imageUrl,CURLOPT_TCP_KEEPALIVE,1L); //curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPIDLE, 120L); //curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPINTVL, 60L); - //curl_easy_setopt(imageUrl, CURLOPT_WRITEFUNCTION, dl_write); if (nRead) { curl_easy_setopt(imageUrl, CURLOPT_RESUME_FROM, nRead); GetPix(camera,1);//'if the file not found happened then this trick is to get the camera in a readmode again and making sure it remembers the filename - GP_DEBUG("continuing the read where it stopped %s position %ld", Images, nRead); + GP_DEBUG("continuing the read where it stopped %s position %ld", image, nRead); } - curl_easy_setopt(imageUrl, CURLOPT_WRITEDATA, imageFile); + lmb.size = 0; + lmb.data = malloc(0); + curl_easy_setopt(imageUrl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(imageUrl, CURLOPT_WRITEDATA, &lmb); res = curl_easy_perform(imageUrl); - if(res != CURLE_OK) { - - //double x; - //curl_easy_getinfo(imageUrl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &x); - //nRead = x; - fseek(imageFile, 0, SEEK_END); // seek to end of file - nRead= ftell(imageFile); // get current file pointer - - fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); - GP_DEBUG("error in reading stream %s position %ld", Images, nRead); + if (res != CURLE_OK) { + GP_LOG_E("curl_easy_perform() failed: %s", curl_easy_strerror(res)); + GP_DEBUG("error in reading stream %s position %ld", image, nRead); curl_easy_getinfo(imageUrl, CURLINFO_RESPONSE_CODE, &http_response); GP_DEBUG("CURLINFO_RESPONSE_CODE:%ld\n", http_response); } else { @@ -863,8 +947,9 @@ static CameraFilePath * ReadImageFromCamera(Camera *camera) { } } curl_easy_cleanup(imageUrl); - fclose(imageFile); - return (CameraFilePath *) strdup(filename); + strcpy(path->name, strrchr(image,'/')+1); + strcpy(path->folder, "/"); + return add_objectid_and_upload (camera, path, context, lmb.data, lmb.size); } @@ -881,12 +966,9 @@ int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path if (strcmp(cameraShutterSpeed, "B")!=0) { waitBulb(camera,captureDuration);//trying captureDuration sec to start before we know how to make a bulb capture of x sec .... } - path = ReadImageFromCamera(camera); - return GP_OK; + return ReadImageFromCamera(camera, path, context); } - - /** * Fill out the summary with textual information about the current * state of the camera (like pictures taken, etc.). @@ -1060,9 +1142,8 @@ int camera_abilities (CameraAbilitiesList *list) { memset(&a, 0, sizeof(a)); strcpy(a.model, "Panasonic:LumixGSeries"); a.status = GP_DRIVER_STATUS_EXPERIMENTAL; - a.port = GP_PORT_TCP; - a.speed[0] = 0; - a.operations = GP_CAPTURE_IMAGE| GP_OPERATION_CAPTURE_VIDEO| GP_OPERATION_CONFIG; + a.port = GP_PORT_TCP; + a.operations = GP_CAPTURE_IMAGE| GP_OPERATION_CAPTURE_VIDEO | GP_OPERATION_CONFIG; a.file_operations = GP_FILE_OPERATION_PREVIEW ; /* it should be possible to browse and DL images the files using the ReadImageFromCamera() function but for now lets keep it simple*/ a.folder_operations = GP_FOLDER_OPERATION_NONE; @@ -1128,12 +1209,14 @@ camera_init (Camera *camera, GPContext *context) gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera); if (loadCmd(camera,RECMODE)!= NULL) { + int numpix; + Set_quality(camera,"raw_fine"); loadCmd(camera,PLAYMODE); // 'making sure the camera is in Playmode - NumberPix(camera); - GetPix(camera,651); + numpix = NumberPix(camera); + GetPix(camera,numpix); return GP_OK; } else -- cgit v1.2.1 From 9a5f7cdac95b382d3867b1d831dc111e871bc37c Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Tue, 25 Jun 2019 16:33:59 +0200 Subject: more work on directory reading --- camlibs/lumix/lumix.c | 138 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 120 insertions(+), 18 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index da74d77e2..6dc12e151 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -103,6 +103,7 @@ typedef struct { } LumixMemoryBuffer; typedef struct { + char *id; char *url_large; char *url_medium; char *url_thumb; @@ -372,15 +373,16 @@ write_callback(char *contents, size_t size, size_t nmemb, void *userp) } -static char* loadCmd (Camera *camera,char* cmd) { - CURL *curl; - CURLcode res; - int stream = strcmp (cmd, STARTSTREAM); - char URL[100]; +static char* +loadCmd (Camera *camera,char* cmd) { + CURL *curl; + CURLcode res; + int stream = strcmp (cmd, STARTSTREAM); + char URL[100]; GPPortInfo info; - char *xpath; + char *xpath; LumixMemoryBuffer lmb; - + curl = curl_easy_init(); gp_port_get_info (camera->port, &info); gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ @@ -504,6 +506,7 @@ strend(const char *s, const char *t) static int NumberPix(Camera *camera) { xmlChar *keyz = NULL; + int numpics = 0; char *temp = loadCmd(camera,NUMPIX); xmlDocPtr doc = xmlParseDoc((unsigned char*) temp); @@ -525,10 +528,15 @@ NumberPix(Camera *camera) { } cur = cur->next; } - if (!keyz) + if (!keyz) { + xmlFreeDoc(doc); return GP_ERROR; + } GP_LOG_D("NumberPix Found is %s \n", (char *) keyz); - return strtol((char*)keyz, NULL, 10); + numpics = strtol((char*)keyz, NULL, 10); + + xmlFreeDoc(doc); + return numpics; } /*utility function to creat a SOAP envelope for the lumix cam */ @@ -592,15 +600,21 @@ GetPix(Camera *camera,int num) { //GP_LOG_D("NumPix is %d \n", NumPix); if (NumPix < GP_OK) return NULL; + if (camera->pl->numpics < NumPix) { + camera->pl->pics = realloc(camera->pl->pics,NumPix * sizeof(camera->pl->pics[0])); + memset(camera->pl->pics+camera->pl->numpics, 0, NumPix * sizeof(camera->pl->pics[0])); + camera->pl->numpics = NumPix; + } + SoapMsg = SoapEnvelop((NumPix - num)> 0?(NumPix - num):0, num); //GP_LOG_D("SoapMsg is %s \n", SoapMsg); - + curl = curl_easy_init(); list = curl_slist_append(list, "SOAPaction: urn:schemas-upnp-org:service:ContentDirectory:1#Browse"); list = curl_slist_append(list, "Content-Type: text/xml; charset=\"utf-8\""); list = curl_slist_append(list, "Accept: text/xml"); - + gp_port_get_info (camera->port, &info); gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ snprintf( URL, 1000, "http://%s%s",xpath+4, CDS_Control); @@ -619,7 +633,7 @@ GetPix(Camera *camera,int num) { GP_LOG_D("camera url is %s", URL); GP_LOG_D("posting %s", SoapMsg); - + res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", @@ -699,9 +713,95 @@ GetPix(Camera *camera,int num) { xmlFreeDoc (docin2); return NULL; } +/* + + 103-0822 + WRITABLE + object.item.imageItem + + http://192.168.54.1:50001/DO1030822.JPG + + + http://192.168.54.1:50001/DT1030822.JPG + + + http://192.168.54.1:50001/DL1030822.JPG + + +*/ next = output; do { + char *id = NULL; + int i; + xmlNode *child; + xmlAttr *attr = next->properties; + GP_LOG_D("got %s", next->name); + + while (attr) { + GP_LOG_D("\t attribute %s", attr->name); + GP_LOG_D("\t attribute content %s", xmlNodeGetContent(attr->children)); + + if (!strcmp((char*)attr->name, "id")) { + id = (char*)xmlNodeGetContent(attr->children); + break; + } + attr = attr->next; + } + /* look if we have the id */ + for (i=0;ipl->numpics;i++) + if (camera->pl->pics[i].id && !strcmp(camera->pl->pics[i].id, id)) + break; + if (ipl->numpics) { + GP_LOG_D("already read id %s, is element %d\n", id, i); + continue; + } + for (i=0;ipl->numpics;i++) + if (!camera->pl->pics[i].id) + break; + if (i==camera->pl->numpics) { + GP_LOG_D("no free slot found for id %s\n", id); + continue; + } + camera->pl->pics[i].id = strdup(id); + child = next->children; + + /* + + http://192.168.54.1:50001/DL1030822.JPG + + */ + while (child) { + xmlAttr *attr; + xmlChar *attrcontent; + + if (strcmp((char*)child->name,"res")) { + GP_LOG_D("skipping %s", child->name); + child = child->next; + continue; + } + attr = child->properties; + + if (strcmp((char*)attr->name,"protocolInfo")) { + GP_LOG_D("expected attribute protocolInfo, got %s", attr->name); + } + attrcontent = xmlNodeGetContent(attr->children); + GP_LOG_D("\t\tattribute content is %s", attrcontent); + + GP_LOG_D("\t child content %s", xmlNodeGetContent(child)); + + if (strstr((char*)attrcontent,"DLNA.ORG_PN=JPEG_LRG")) { + camera->pl->pics[i].url_large = strdup((char*)xmlNodeGetContent(child)); + } + if (strstr((char*)attrcontent,"DLNA.ORG_PN=JPEG_TN")) { + camera->pl->pics[i].url_medium = strdup((char*)xmlNodeGetContent(child)); + } + if (strstr((char*)attrcontent,"DLNA.ORG_PN=JPEG_MED")) { + camera->pl->pics[i].url_thumb = strdup((char*)xmlNodeGetContent(child)); + } + + child = child->next; + } } while ((next = xmlNextElementSibling (next))); return strdup((char*)xchar); @@ -757,9 +857,9 @@ static char* processNode(xmlTextReaderPtr reader) { if (xmlTextReaderNodeType(reader) == 1) { // Element while (xmlTextReaderMoveToNextAttribute(reader)) { - if (strend(xmlTextReaderConstValue(reader),lookupImgtag)) { + if (strend((char*)xmlTextReaderConstValue(reader),lookupImgtag)) { xmlTextReaderRead(reader); - ret = xmlTextReaderConstValue(reader); + ret = (char*)xmlTextReaderConstValue(reader); printf("the image file is %s\n" ,ret); } } @@ -769,7 +869,7 @@ static char* processNode(xmlTextReaderPtr reader) { /* -below are 2 samples of XML files to be parsed one in case of a JPG/Thumb retrieve the other for RAW +below are 2 samples of XML files to be parsed one in case of a JPG/Thumb retrieve the other for RAW case JPG/Thumb @@ -795,7 +895,7 @@ case JPG/Thumb 1 - + case RAW: @@ -892,10 +992,10 @@ ReadImageFromCamera(Camera *camera, CameraFilePath *path, GPContext *context) { xmlDocPtr doc; /* the resulting document tree */ int ret; LIBXML_TEST_VERSION - + char* imageURL=""; xmlTextReaderPtr reader; - reader = xmlReaderForDoc(GetPix(camera,1), NULL,"noname.xml", XML_PARSE_DTDATTR | /* default DTD attributes */ XML_PARSE_NOENT); + reader = xmlReaderForDoc((xmlChar*)GetPix(camera,1), NULL,"noname.xml", XML_PARSE_DTDATTR | /* default DTD attributes */ XML_PARSE_NOENT); ret = xmlTextReaderRead(reader); while (ret == 1) { imageURL = processNode(reader); @@ -1186,6 +1286,8 @@ camera_init (Camera *camera, GPContext *context) char *xpath; int ret; + camera->pl = calloc(sizeof(CameraPrivateLibrary),1); + /* First, set up all the function pointers */ camera->functions->exit = camera_exit; camera->functions->get_config = camera_config_get; -- cgit v1.2.1 From 85420422a788c04aadca7cd2bcd867bfe3544293 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 26 Jun 2019 12:24:16 +0200 Subject: return first configurations fixed 0 termination of read buffers --- camlibs/lumix/lumix.c | 144 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 129 insertions(+), 15 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 6dc12e151..20e736451 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -84,6 +84,7 @@ char* NUMPIX = "cam.cgi?mode=get_content_info"; char* RECMODE = "cam.cgi?mode=camcmd&value=recmode"; char* PLAYMODE = "cam.cgi?mode=camcmd&value=playmode"; +char* AFMODE = "cam.cgi?mode=camcmd&value=afmode"; char* SHUTTERSTART = "cam.cgi?mode=camcmd&value=capture"; char* SHUTTERSTOP = "cam.cgi?mode=camcmd&value=capture_cancel"; char* SETAPERTURE = "cam.cgi?mode=setsetting&type=focal&value="; @@ -128,6 +129,7 @@ int camera_config_get (Camera *camera, CameraWidget **window, GPContext *context static int camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) { + return GP_OK; } @@ -363,8 +365,10 @@ write_callback(char *contents, size_t size, size_t nmemb, void *userp) LumixMemoryBuffer *lmb = userp; oldsize = lmb->size; - lmb->data = realloc(lmb->data, lmb->size+realsize); + /* 1 additionaly byte for 0x00 */ + lmb->data = realloc(lmb->data, lmb->size+realsize+1); lmb->size += realsize; + lmb->data[lmb->size] = 0x00; GP_LOG_DATA(contents, realsize, "lumix read from url"); @@ -391,12 +395,10 @@ loadCmd (Camera *camera,char* cmd) { curl_easy_setopt(curl, CURLOPT_URL, URL); - if (stream!=0) { - lmb.size = 0; - lmb.data = malloc(0); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &lmb); - } + lmb.size = 0; + lmb.data = malloc(0); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &lmb); res = curl_easy_perform(curl); if(res != CURLE_OK) { @@ -410,13 +412,9 @@ loadCmd (Camera *camera,char* cmd) { } curl_easy_cleanup(curl); - if (stream != 0) { - if (strcmp(cmd,PLAYMODE)==0) { - } - return lmb.data; - } else { - return NULL; - } // TO DO the idea would be to return the socket to the actual video stream here.... + if (strcmp(cmd,PLAYMODE)==0) { + } + return lmb.data; } static void switchToRecMode(Camera *camera) { @@ -429,6 +427,57 @@ static void Set_ISO(Camera *camera,const char * ISOValue) { loadCmd(camera,buf); } +static char* +Get_Clock(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getsetting&type=clock"); +} + +static char* +Get_AFMode(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getsetting&type=afmode"); +} + +static char* +Get_FocusMode(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getsetting&type=focusmode"); +} + +static char* +Get_MFAssist(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getsetting&type=mf_asst"); +} + +static char* +Get_MFAssist_Mag(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getsetting&type=mf_asst_mag"); +} + +static char* +Get_ExTeleConv(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getsetting&type=ex_tele_conv"); +} + +static char* +Get_Capability(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getinfo&type=capability"); +} + +static char* +Get_Lens(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getinfo&type=lens"); +} + +static char* +Get_AllMenu(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getinfo&type=allmenu"); +} + +static char* +Get_CurMenu(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getinfo&type=curmenu"); +} + + static void Set_Speed(Camera *camera,const char* SpeedValue) { char buf[200]; sprintf(buf, "?mode=setsetting&type=shtrspeed&value=%s",SpeedValue); @@ -818,6 +867,71 @@ int camera_config_get (Camera *camera, CameraWidget **window, GPContext *context int camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) { + CameraWidget *widget,*section; + int ret; + + loadCmd (camera, RECMODE); + + gp_widget_new (GP_WIDGET_WINDOW, _("Lumix Configuration"), window); + gp_widget_set_name (*window, "config"); + + gp_widget_new (GP_WIDGET_SECTION, _("Camera Settings"), §ion); + gp_widget_set_name (section, "settings"); + gp_widget_append (*window, section); + + gp_widget_new (GP_WIDGET_TEXT, _("Clock"), &widget); + gp_widget_set_name (widget, "clock"); + gp_widget_set_value (widget, Get_Clock(camera)); + gp_widget_append (section, widget); + + gp_widget_new (GP_WIDGET_TEXT, _("Autofocus Mode"), &widget); + gp_widget_set_name (widget, "afmode"); + gp_widget_set_value (widget, Get_AFMode(camera)); + gp_widget_append (section, widget); + + gp_widget_new (GP_WIDGET_TEXT, _("Focus Mode"), &widget); + gp_widget_set_name (widget, "focusmode"); + gp_widget_set_value (widget, Get_FocusMode(camera)); + gp_widget_append (section, widget); + + gp_widget_new (GP_WIDGET_TEXT, _("MF Assist"), &widget); + gp_widget_set_name (widget, "mf_assist"); + gp_widget_set_value (widget, Get_MFAssist(camera)); + gp_widget_append (section, widget); + + gp_widget_new (GP_WIDGET_TEXT, _("MF Assist Mag"), &widget); + gp_widget_set_name (widget, "mf_assist_mag"); + gp_widget_set_value (widget, Get_MFAssist_Mag(camera)); + gp_widget_append (section, widget); + + gp_widget_new (GP_WIDGET_TEXT, _("Ex Teleconv"), &widget); + gp_widget_set_name (widget, "ex_tele_conv"); + gp_widget_set_value (widget, Get_ExTeleConv(camera)); + gp_widget_append (section, widget); + + gp_widget_new (GP_WIDGET_TEXT, _("Lens"), &widget); + gp_widget_set_name (widget, "lens"); + gp_widget_set_value (widget, Get_Lens(camera)); + gp_widget_append (section, widget); + + gp_widget_new (GP_WIDGET_TEXT, _("Capability"), &widget); + gp_widget_set_name (widget, "capability"); + gp_widget_set_value (widget, Get_Capability(camera)); + gp_widget_append (section, widget); + +#if 0 + /* lots of stuff */ + gp_widget_new (GP_WIDGET_TEXT, _("All Menu"), &widget); + gp_widget_set_name (widget, "allmenu"); + gp_widget_set_value (widget, Get_AllMenu(camera)); + gp_widget_append (section, widget); + + gp_widget_new (GP_WIDGET_TEXT, _("Cur Menu"), &widget); + gp_widget_set_name (widget, "curmenu"); + gp_widget_set_value (widget, Get_CurMenu(camera)); + gp_widget_append (section, widget); +#endif + return GP_OK; } @@ -1310,7 +1424,7 @@ camera_init (Camera *camera, GPContext *context) gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera); - if (loadCmd(camera,RECMODE)!= NULL) { + if (loadCmd(camera,RECMODE) != NULL) { int numpix; Set_quality(camera,"raw_fine"); -- cgit v1.2.1 From 1675e810b56009290faa11b6c2bbf516e719d094 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 26 Jun 2019 12:35:43 +0200 Subject: added shutterspeed config --- camlibs/lumix/lumix.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 20e736451..8279010f2 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -432,6 +432,11 @@ Get_Clock(Camera *camera) { return loadCmd(camera,"cam.cgi?mode=getsetting&type=clock"); } +static char* +Get_ShutterSpeed(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getsetting&type=shtrspeed"); +} + static char* Get_AFMode(Camera *camera) { return loadCmd(camera,"cam.cgi?mode=getsetting&type=afmode"); @@ -884,6 +889,11 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_value (widget, Get_Clock(camera)); gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("Shutterspeed"), &widget); + gp_widget_set_name (widget, "shutterspeed"); + gp_widget_set_value (widget, Get_ShutterSpeed(camera)); + gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("Autofocus Mode"), &widget); gp_widget_set_name (widget, "afmode"); gp_widget_set_value (widget, Get_AFMode(camera)); -- cgit v1.2.1 From 923b9e9480b402f2352c06e06847b50a94673201 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 26 Jun 2019 13:15:29 +0200 Subject: added "focal", which might be aperture? --- camlibs/lumix/lumix.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 8279010f2..3fbfe8424 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -423,7 +423,7 @@ static void switchToRecMode(Camera *camera) { static void Set_ISO(Camera *camera,const char * ISOValue) { char buf[200]; - sprintf(buf, "?mode==setsetting&type=iso&value=%s",ISOValue); + sprintf(buf, "?mode=setsetting&type=iso&value=%s",ISOValue); loadCmd(camera,buf); } @@ -437,6 +437,11 @@ Get_ShutterSpeed(Camera *camera) { return loadCmd(camera,"cam.cgi?mode=getsetting&type=shtrspeed"); } +static char* +Get_Focal(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getsetting&type=focal"); +} + static char* Get_AFMode(Camera *camera) { return loadCmd(camera,"cam.cgi?mode=getsetting&type=afmode"); @@ -894,6 +899,11 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_value (widget, Get_ShutterSpeed(camera)); gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("Focal Length"), &widget); + gp_widget_set_name (widget, "focal"); + gp_widget_set_value (widget, Get_Focal(camera)); + gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("Autofocus Mode"), &widget); gp_widget_set_name (widget, "afmode"); gp_widget_set_value (widget, Get_AFMode(camera)); -- cgit v1.2.1 From 23f1160080a98bbd0dc41706acf3ce9601e54d8e Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 26 Jun 2019 13:19:13 +0200 Subject: focal >= aperture --- camlibs/lumix/lumix.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 3fbfe8424..25895b2ef 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -438,7 +438,7 @@ Get_ShutterSpeed(Camera *camera) { } static char* -Get_Focal(Camera *camera) { +Get_Aperture(Camera *camera) { return loadCmd(camera,"cam.cgi?mode=getsetting&type=focal"); } @@ -899,9 +899,9 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_value (widget, Get_ShutterSpeed(camera)); gp_widget_append (section, widget); - gp_widget_new (GP_WIDGET_TEXT, _("Focal Length"), &widget); - gp_widget_set_name (widget, "focal"); - gp_widget_set_value (widget, Get_Focal(camera)); + gp_widget_new (GP_WIDGET_TEXT, _("Aperture"), &widget); + gp_widget_set_name (widget, "aperture"); + gp_widget_set_value (widget, Get_Aperture(camera)); gp_widget_append (section, widget); gp_widget_new (GP_WIDGET_TEXT, _("Autofocus Mode"), &widget); -- cgit v1.2.1 From 74f3535099aa8957046bef72c446dabc74b44e11 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 26 Jun 2019 13:54:37 +0200 Subject: added iso and quality for get config --- camlibs/lumix/lumix.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 25895b2ef..6e4737209 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -88,7 +88,6 @@ char* AFMODE = "cam.cgi?mode=camcmd&value=afmode"; char* SHUTTERSTART = "cam.cgi?mode=camcmd&value=capture"; char* SHUTTERSTOP = "cam.cgi?mode=camcmd&value=capture_cancel"; char* SETAPERTURE = "cam.cgi?mode=setsetting&type=focal&value="; -char* QUALITY = "cam.cgi?mode=setsetting&type=quality&value="; char* CDS_Control = ":60606/Server0/CDS_control"; char* STARTSTREAM = "cam.cgi?mode=startstream&value=49199"; char* CAMERAIP = "192.168.1.24"; //placeholder until there is a better way to discover the IP from the network and via PTPIP @@ -432,6 +431,11 @@ Get_Clock(Camera *camera) { return loadCmd(camera,"cam.cgi?mode=getsetting&type=clock"); } +static char* +Get_ISO(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getsetting&type=iso"); +} + static char* Get_ShutterSpeed(Camera *camera) { return loadCmd(camera,"cam.cgi?mode=getsetting&type=shtrspeed"); @@ -494,9 +498,15 @@ static void Set_Speed(Camera *camera,const char* SpeedValue) { loadCmd(camera,buf); } -static void Set_quality(Camera *camera,const char* Quality) { +static char* +Get_Quality(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=getsetting&type=quality"); +} + +static void +Set_quality(Camera *camera,const char* Quality) { char buf[200]; - sprintf(buf,"%s%s", QUALITY,Quality); + sprintf(buf,"cam.cgi?mode=setsetting&type=quality&value=%s", Quality); loadCmd(camera,buf); } @@ -899,11 +909,22 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_value (widget, Get_ShutterSpeed(camera)); gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("Quality"), &widget); + gp_widget_set_name (widget, "quality"); + gp_widget_set_value (widget, Get_Quality(camera)); + gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("Aperture"), &widget); gp_widget_set_name (widget, "aperture"); gp_widget_set_value (widget, Get_Aperture(camera)); gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("ISO"), &widget); + gp_widget_set_name (widget, "iso"); + gp_widget_set_value (widget, Get_ISO(camera)); + gp_widget_append (section, widget); + + gp_widget_new (GP_WIDGET_TEXT, _("Autofocus Mode"), &widget); gp_widget_set_name (widget, "afmode"); gp_widget_set_value (widget, Get_AFMode(camera)); @@ -962,12 +983,8 @@ waitBulb(Camera *camera, long Duration ) { return TRUE; } -static size_t dl_write(void *buffer, size_t size, size_t nmemb, void *stream) -{ - return fwrite(buffer, size, nmemb, (FILE*)stream); -} - -static char* processNode(xmlTextReaderPtr reader) { +static char* +processNode(xmlTextReaderPtr reader) { char* ret =""; char* lookupImgtag=""; @@ -1236,7 +1253,7 @@ static int camera_manual (Camera *camera, CameraText *manual, GPContext *context */ int camera_about (Camera *camera, CameraText *about, GPContext *context); int camera_about (Camera *camera, CameraText *about, GPContext *context) { - strcpy (about->text, _("Library Name\n" + strcpy (about->text, _("Lumix WiFi Library\n" "Robert Hasson \n" "Connects to Lumix Cameras over Wifi.\n" "using the http GET commands.")); -- cgit v1.2.1 From c7750565a74471c5ec146bd61d51e48ec3acf460 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 26 Jun 2019 14:18:56 +0200 Subject: autoconf magic for detecting libcurl, added to lumix Makefile-files --- camlibs/lumix/Makefile-files | 4 ++-- configure.ac | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/camlibs/lumix/Makefile-files b/camlibs/lumix/Makefile-files index abc00f041..d15ef34c2 100644 --- a/camlibs/lumix/Makefile-files +++ b/camlibs/lumix/Makefile-files @@ -6,7 +6,7 @@ noinst_DATA += lumix/README.lumix EXTRA_LTLIBRARIES += lumix.la lumix_la_SOURCES = lumix/lumix.c -lumix_la_CFLAGS = $(AM_CFLAGS) $(NO_UNUSED_CFLAGS) $(CFLAGS) +lumix_la_CFLAGS = $(AM_CFLAGS) $(NO_UNUSED_CFLAGS) $(CFLAGS) $(LIBXML2_CFLAGS) $(LIBCURL_CFLAGS) lumix_la_LDFLAGS = $(camlib_ldflags) lumix_la_DEPENDENCIES = $(camlib_dependencies) -lumix_la_LIBADD = $(camlib_libadd) -lcurl -lxml2 +lumix_la_LIBADD = $(camlib_libadd) $(LIBCURL_LIBS) $(LIBXML2_LIBS) diff --git a/configure.ac b/configure.ac index 691ccf27a..d16a89a59 100644 --- a/configure.ac +++ b/configure.ac @@ -282,6 +282,13 @@ GP_CHECK_LIBRARY([LIBXML2],[libxml-2.0],[>= 2.0], ) GP_CONFIG_MSG([XML support for Olympus E series],[${have_LIBXML2}]) +GP_CHECK_LIBRARY([LIBCURL],[libcurl],[>= 7.1], + [curl/curl.h],[curl_easy_init],[],[], + [default-on], + [https://www.curl.org] +) +GP_CONFIG_MSG([CURL support for Lumix Wifi],[${have_LIBCURL}]) + dnl --------------------------------------------------------------------------- dnl check for libgd dnl they call it "gdlib" ... confusing. -- cgit v1.2.1 From d5ca55d432746c7776762991642be7c1ea74a31d Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 26 Jun 2019 14:19:18 +0200 Subject: listing files works, as we got them from GetPix --- camlibs/lumix/lumix.c | 58 +++++++-------------------------------------------- 1 file changed, 8 insertions(+), 50 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 6e4737209..3b5d4c07d 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -257,17 +257,19 @@ folder_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, * * This function is a CameraFilesystem method. */ -int -file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, - void *data, GPContext *context); -int +static int file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, void *data, GPContext *context) { Camera *camera = data; + int i; - int numpix = NumberPix(camera); - + for (i=0;ipl->numpics;i++) { + if (camera->pl->pics[i].url_large) { + char *s = strrchr(camera->pl->pics[i].url_large, '/')+1; + gp_list_append (list, s, NULL); + } + } return GP_OK; } @@ -314,48 +316,6 @@ camera_id (CameraText *id) return GP_OK; } -static char *replaceWord(const char *s, const char *oldW, - const char *newW) -{ - char *result; - int i, cnt = 0; - int newWlen = strlen(newW); - int oldWlen = strlen(oldW); - - // Counting the number of times old word - // occur in the string - for (i = 0; s[i] != '\0'; i++) - { - if (strstr(&s[i], oldW) == &s[i]) - { - cnt++; - - // Jumping to index after the old word. - i += oldWlen - 1; - } - } - - // Making new string of enough length - result = (char *)malloc(i + cnt * (newWlen - oldWlen) + 1); - - i = 0; - while (*s) - { - // compare the substring with the result - if (strstr(s, oldW) == s) - { - strcpy(&result[i], newW); - i += newWlen; - s += oldWlen; - } - else - result[i++] = *s++; - } - - result[i] = '\0'; - return result; -} - static size_t write_callback(char *contents, size_t size, size_t nmemb, void *userp) { @@ -868,11 +828,9 @@ GetPix(Camera *camera,int num) { if (strstr((char*)attrcontent,"DLNA.ORG_PN=JPEG_MED")) { camera->pl->pics[i].url_thumb = strdup((char*)xmlNodeGetContent(child)); } - child = child->next; } } while ((next = xmlNextElementSibling (next))); - return strdup((char*)xchar); } -- cgit v1.2.1 From ae2d7b396ae2fb37cfded5a8c3c41c8825611241 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 26 Jun 2019 14:21:56 +0200 Subject: do a libcurl based run too --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 3e61b5085..9cf6e790b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ env: - EXTRALIBS="gettext" - EXTRALIBS="gettext libusb-dev" - EXTRALIBS="gettext libusb-1.0-0-dev libgd2-xpm-dev" + - EXTRALIBS="gettext libusb-1.0-0-dev libgd2-xpm-dev libcurl-dev" # Note: Keep the sudo commands in .travis.yml - they do not work from # a helper shell script. -- cgit v1.2.1 From f9f73ac12238ff0ed265a51d0d6bafa0430c5524 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 26 Jun 2019 14:59:20 +0200 Subject: implement downloading files, select thumb or normal --- camlibs/lumix/lumix.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 3b5d4c07d..5fa5dd212 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -1096,7 +1096,7 @@ ReadImageFromCamera(Camera *camera, CameraFilePath *path, GPContext *context) { long nRead; LumixMemoryBuffer lmb; - loadCmd(camera,PLAYMODE); // 'making sure the camera is in Playmode + loadCmd(camera,PLAYMODE); // 'making sure the camera is in Playmode char* xmlimageName; xmlDocPtr doc; /* the resulting document tree */ int ret; @@ -1235,12 +1235,83 @@ int camera_about (Camera *camera, CameraText *about, GPContext *context) { * * This function is a CameraFilesystem method. */ -int -get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,CameraFileType type, CameraFile *file, void *data, GPContext *context); -int get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, CameraFileType type, CameraFile *file, void *data, GPContext *context) +static int +get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, CameraFileType type, CameraFile *file, void *data, GPContext *context) { - Camera *camera = data; + Camera *camera = data; + int i; + CURLcode res; + CURL *imageUrl; + double bytesread = 0; + long http_response; + int ret_val = 0; + long nRead; + LumixMemoryBuffer lmb; + const char *url; + + for (i=0;ipl->numpics;i++) { + char *s; + if (!camera->pl->pics[i].url_large) continue; + + s = strrchr(camera->pl->pics[i].url_large,'/')+1; + + if (!strcmp(s,filename)) break; + } + if (i == camera->pl->numpics) /* not found */ + return GP_ERROR; + + url = camera->pl->pics[i].url_large; + switch (type) { + case GP_FILE_TYPE_PREVIEW: + if (camera->pl->pics[i].url_thumb) + url = camera->pl->pics[i].url_thumb; + break; + case GP_FILE_TYPE_NORMAL: + default: + /* just use regular url */ + break; + } + + loadCmd(camera,PLAYMODE); + + imageUrl = curl_easy_init(); + + while (ret_val != 2) { + GP_DEBUG("reading stream %s position %ld", url, nRead); + + curl_easy_setopt(imageUrl, CURLOPT_URL, url); + //curl_easy_setopt(imageUrl,CURLOPT_TCP_KEEPALIVE,1L); + //curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPIDLE, 120L); + //curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPINTVL, 60L); + + if (nRead) { + curl_easy_setopt(imageUrl, CURLOPT_RESUME_FROM, nRead); + GetPix(camera,1);//'if the file not found happened then this trick is to get the camera in a readmode again and making sure it remembers the filename + GP_DEBUG("continuing the read where it stopped %s position %ld", url, nRead); + } + lmb.size = 0; + lmb.data = malloc(0); + curl_easy_setopt(imageUrl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(imageUrl, CURLOPT_WRITEDATA, &lmb); + + res = curl_easy_perform(imageUrl); + + if (res != CURLE_OK) { + GP_LOG_E("curl_easy_perform() failed: %s", curl_easy_strerror(res)); + GP_DEBUG("error in reading stream %s position %ld", url, nRead); + curl_easy_getinfo(imageUrl, CURLINFO_RESPONSE_CODE, &http_response); + GP_DEBUG("CURLINFO_RESPONSE_CODE:%ld\n", http_response); + return GP_ERROR_IO; + } else { + GP_DEBUG("read the whole file"); + ret_val=2; + } + } + curl_easy_cleanup(imageUrl); + return gp_file_set_data_and_size (file, lmb.data, lmb.size); + +#if 0 /* * Get the file from the camera. Use gp_file_set_mime_type, * gp_file_set_data_and_size, etc. @@ -1342,6 +1413,7 @@ return 0; } return GP_OK; +#endif } -- cgit v1.2.1 From fe8f50e83a90aeed88149f8091f252f4e56f5a15 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 26 Jun 2019 15:44:07 +0200 Subject: merge waitBulb into the capture function --- camlibs/lumix/lumix.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 5fa5dd212..3f8652e31 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -934,13 +934,6 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) return GP_OK; } -static int -waitBulb(Camera *camera, long Duration ) { - sleep(Duration); // Sleep for the duration to simulate exposure, if this is in Bulb mode - loadCmd(camera,SHUTTERSTOP); - return TRUE; -} - static char* processNode(xmlTextReaderPtr reader) { char* ret =""; @@ -1171,10 +1164,12 @@ ReadImageFromCamera(Camera *camera, CameraFilePath *path, GPContext *context) { int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context); int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context){ loadCmd(camera,SHUTTERSTART); //we should really multithread so as to not block while waiting - sleep(4); + if (strcmp(cameraShutterSpeed, "B")!=0) { - waitBulb(camera,captureDuration);//trying captureDuration sec to start before we know how to make a bulb capture of x sec .... + sleep(captureDuration); // Sleep for the duration to simulate exposure, if this is in Bulb mode } + + loadCmd(camera,SHUTTERSTOP); return ReadImageFromCamera(camera, path, context); } -- cgit v1.2.1 From 3b31859dd179252b0fc946748181a99f03a6035a Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 26 Jun 2019 17:57:35 +0200 Subject: preview now works. --- camlibs/lumix/lumix.c | 176 +++++++++++++++++++------------------------------- 1 file changed, 67 insertions(+), 109 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 3f8652e31..ab55aa601 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -25,6 +25,7 @@ #include "config.h" #include +#include #include #include #include @@ -96,6 +97,7 @@ char* cameraShutterSpeed = "B"; // //placeholder to store the value of the shutt int captureDuration = 10; //placeholder to store the value of the bulb shot this should be taken as input. note that my primary goal is in fact to perform bulb captures. but this should be extended for sure to take Shutter Speed capture as set in camera static int NumberPix(Camera *camera); +static char* loadCmd (Camera *camera,char* cmd); typedef struct { char *data; @@ -114,6 +116,8 @@ struct _CameraPrivateLibrary { int numpics; LumixPicture *pics; + + int liveview; }; @@ -136,7 +140,67 @@ camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) static int camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) { - return GP_OK; + int sock = 0, valread; + struct sockaddr_in serv_addr; + unsigned char buffer[65536]; + GPPortInfo info; + char *xpath; + int i, start, end, tries; + + loadCmd (camera, RECMODE); + + if (!camera->pl->liveview) { + loadCmd(camera,"cam.cgi?mode=startstream&value=49199"); + camera->pl->liveview = 1; + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + GP_LOG_E("\n Socket creation error \n"); + return GP_ERROR; + } + + gp_port_get_info (camera->port, &info); + gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ + + memset(&serv_addr, 0, sizeof(serv_addr)); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(49199); + serv_addr.sin_addr.s_addr = 0; + + if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + GP_LOG_E("bind Failed: %d", errno); + return GP_ERROR; + } + } else { + /* this reminds the camera we are still doing it */ + loadCmd(camera,"cam.cgi?mode=getstate"); + } + tries = 3; + while (tries--) { + valread = recv ( sock , buffer, sizeof(buffer), 0); + if (valread == -1) { + GP_LOG_E("recv failed: %d", errno); + return GP_ERROR; + } + + GP_LOG_DATA(buffer,valread,"read from udp port"); + + if (valread == 0) + continue; + + start = end = -1; + for (i = 0; iMicrosoft Winsock control in VB - Winsock1.Protocol = sckUDPProtocol - ' Port, der überwacht werden soll - nPort = 49199 - ' Eigene IP ermitteln - sOwnIP = Winsock1.LocalIP - - ' Port an die IP "binden" -Winsock1.Bind nPort, sOwnIP - -'geht nur im 'recmode' -txtStatus.Text = Inet1.OpenURL("http://" & CameraIP.Text & "/cam.cgi?mode=camcmd&value=recmode") 'Inet1 ->Microsoft Inet control - -txtStatus.Text = Inet1.OpenURL("http://" & CameraIP.Text & "/cam.cgi?mode=startstream&value=49199") - -Timer1.Enabled = True 'damit der Datenfluß nicht abbricht - -txtStatus.Text = Inet1.OpenURL("http://" & CameraIP.Text & "/cam.cgi?mode=setsetting_ &type=liveviewsize&value=vga") - -... - -Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) -Dim sData As String -Dim bArray As Variant - -On Error Resume Next - -'im Stream werden ganze Bilder übertragen 'Header ist 167 Byte, Rest - JPG -'Das JPEG-Bild beginnt also bei Byte 168 (Lumix GX7) - -Winsock1.GetData sData, vbString - -sData = Mid(sData, 168) - -bArray = sData - -ImageBox1.ReadBinary2 bArray 'ImageBox1 ist the csxImage OCX - -End Sub - -Private Sub Timer1_Timer() -Dim dummy As Variant - -If CameraIP.Text > "" Then - -If Not Inet2.StillExecuting Then -dummy = Inet2.OpenURL("http://" & CameraIP.Text & "/cam.cgi?mode=startstream_ &value=49199") -'Inet2 ->Microsoft Inet control -End If - -End If - -End Sub -*/ -struct sockaddr_in address; -int sock = 0, valread; -struct sockaddr_in serv_addr; -char *hello = "Hello from client"; -char buffer[1024] = {0}; -if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) -{ -printf("\n Socket creation error \n"); -return -1; -} - -memset(&serv_addr, '0', sizeof(serv_addr)); - -serv_addr.sin_family = AF_INET; -serv_addr.sin_port = htons(49199); - -// Convert IPv4 and IPv6 addresses from text to binary form -if(inet_pton(AF_INET, CAMERAIP, &serv_addr.sin_addr)<=0) -{ -printf("\nInvalid address/ Address not supported \n"); -return -1; -} - -if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) -{ -printf("\nConnection Failed \n"); -return -1; -} -valread = read( sock , buffer, 1024); -printf("%s\n",buffer ); -return 0; - - -} -return GP_OK; -#endif } -- cgit v1.2.1 From dad0a788fcef32e934aad7987d9f202c07b554f6 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Thu, 27 Jun 2019 10:12:31 +0200 Subject: preview now can capture multiple frames --- camlibs/lumix/lumix.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index ab55aa601..e8c78d1d0 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -118,12 +118,17 @@ struct _CameraPrivateLibrary { LumixPicture *pics; int liveview; + int udpsocket; }; static int camera_exit (Camera *camera, GPContext *context) { + if (camera->pl->udpsocket > 0) { + close (camera->pl->udpsocket); + camera->pl->udpsocket = 0; + } return GP_OK; } @@ -140,7 +145,7 @@ camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) static int camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) { - int sock = 0, valread; + int valread; struct sockaddr_in serv_addr; unsigned char buffer[65536]; GPPortInfo info; @@ -152,23 +157,25 @@ camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) if (!camera->pl->liveview) { loadCmd(camera,"cam.cgi?mode=startstream&value=49199"); camera->pl->liveview = 1; - if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - GP_LOG_E("\n Socket creation error \n"); - return GP_ERROR; - } + if (camera->pl->udpsocket <= 0) { + if ((camera->pl->udpsocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + GP_LOG_E("\n Socket creation error \n"); + return GP_ERROR; + } - gp_port_get_info (camera->port, &info); - gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ + gp_port_get_info (camera->port, &info); + gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ - memset(&serv_addr, 0, sizeof(serv_addr)); + memset(&serv_addr, 0, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_port = htons(49199); - serv_addr.sin_addr.s_addr = 0; + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(49199); + serv_addr.sin_addr.s_addr = 0; - if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { - GP_LOG_E("bind Failed: %d", errno); - return GP_ERROR; + if (bind(camera->pl->udpsocket, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + GP_LOG_E("bind Failed: %d", errno); + return GP_ERROR; + } } } else { /* this reminds the camera we are still doing it */ @@ -176,7 +183,7 @@ camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) } tries = 3; while (tries--) { - valread = recv ( sock , buffer, sizeof(buffer), 0); + valread = recv ( camera->pl->udpsocket, buffer, sizeof(buffer), 0); if (valread == -1) { GP_LOG_E("recv failed: %d", errno); return GP_ERROR; @@ -193,7 +200,7 @@ camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) start = i; } if ((buffer[i] == 0xff) && (buffer[i+1] == 0xd9)) { - end = i; + end = i+2; } } //GP_LOG_DATA(buffer+start,end-start,"read from udp port"); -- cgit v1.2.1 From 669ebdcaf9ce82a3ca66db97813348e7b5b42cf5 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Thu, 27 Jun 2019 11:18:24 +0200 Subject: try conditional build of camlib --- camlibs/lumix/Makefile-files | 4 ++++ configure.ac | 2 ++ 2 files changed, 6 insertions(+) diff --git a/camlibs/lumix/Makefile-files b/camlibs/lumix/Makefile-files index d15ef34c2..b037d6158 100644 --- a/camlibs/lumix/Makefile-files +++ b/camlibs/lumix/Makefile-files @@ -3,7 +3,11 @@ EXTRA_DIST += lumix/README.lumix lumix/ChangeLog noinst_DATA += lumix/README.lumix +if BUILD_LUMIX EXTRA_LTLIBRARIES += lumix.la +else +EXTRA_DIST += lumix/lumix.c +endif lumix_la_SOURCES = lumix/lumix.c lumix_la_CFLAGS = $(AM_CFLAGS) $(NO_UNUSED_CFLAGS) $(CFLAGS) $(LIBXML2_CFLAGS) $(LIBCURL_CFLAGS) diff --git a/configure.ac b/configure.ac index d16a89a59..0bcf25a44 100644 --- a/configure.ac +++ b/configure.ac @@ -289,6 +289,8 @@ GP_CHECK_LIBRARY([LIBCURL],[libcurl],[>= 7.1], ) GP_CONFIG_MSG([CURL support for Lumix Wifi],[${have_LIBCURL}]) +AM_CONDITIONAL([BUILD_LUMIX], [test -n "$have_LIBCURL" && test "X$have_LIBCURL" != "Xno" && test -n "$have_LIBXML2" && test "X$have_LIBXML2" != "Xno"]) + dnl --------------------------------------------------------------------------- dnl check for libgd dnl they call it "gdlib" ... confusing. -- cgit v1.2.1 From eb57375a571595510b58b02ab33019366442ad42 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Thu, 27 Jun 2019 14:47:50 +0200 Subject: use specific libcurl4 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9cf6e790b..5affab673 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ env: - EXTRALIBS="gettext" - EXTRALIBS="gettext libusb-dev" - EXTRALIBS="gettext libusb-1.0-0-dev libgd2-xpm-dev" - - EXTRALIBS="gettext libusb-1.0-0-dev libgd2-xpm-dev libcurl-dev" + - EXTRALIBS="gettext libusb-1.0-0-dev libgd2-xpm-dev libcurl4-openssl-dev" # Note: Keep the sudo commands in .travis.yml - they do not work from # a helper shell script. -- cgit v1.2.1 From 577cfbea1efffafed29de299d5012b3d403efd60 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Thu, 27 Jun 2019 14:48:03 +0200 Subject: port TCP is also valid --- libgphoto2_port/test/test-port-list.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libgphoto2_port/test/test-port-list.c b/libgphoto2_port/test/test-port-list.c index 35dd0bbdc..10c3ecdd0 100644 --- a/libgphoto2_port/test/test-port-list.c +++ b/libgphoto2_port/test/test-port-list.c @@ -107,6 +107,7 @@ run_test () case GP_PORT_USB_SCSI: port_type_str = "USBSCSI"; break; case GP_PORT_DISK: port_type_str = "DISK"; break; case GP_PORT_PTPIP: port_type_str = "PTPIP"; break; + case GP_PORT_TCP: port_type_str = "TCP"; break; default: port_type_str = "UNKNOWN"; return 3; break; } printf ("No: %d\n" -- cgit v1.2.1 From 765123322ece305ec0b8b4a7f7bec454fbb7ec6f Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Thu, 27 Jun 2019 14:48:15 +0200 Subject: cleanups --- camlibs/lumix/lumix.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index e8c78d1d0..e58c6c152 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -82,16 +82,12 @@ # define N_(String) (String) #endif -char* NUMPIX = "cam.cgi?mode=get_content_info"; char* RECMODE = "cam.cgi?mode=camcmd&value=recmode"; char* PLAYMODE = "cam.cgi?mode=camcmd&value=playmode"; -char* AFMODE = "cam.cgi?mode=camcmd&value=afmode"; char* SHUTTERSTART = "cam.cgi?mode=camcmd&value=capture"; char* SHUTTERSTOP = "cam.cgi?mode=camcmd&value=capture_cancel"; char* SETAPERTURE = "cam.cgi?mode=setsetting&type=focal&value="; char* CDS_Control = ":60606/Server0/CDS_control"; -char* STARTSTREAM = "cam.cgi?mode=startstream&value=49199"; -char* CAMERAIP = "192.168.1.24"; //placeholder until there is a better way to discover the IP from the network and via PTPIP int ReadoutMode = 2; // this should be picked up from the settings.... 0-> JPG; 1->RAW; 2 -> Thumbnails char* cameraShutterSpeed = "B"; // //placeholder to store the value of the shutterspeed set in camera; "B" is for bulb. int captureDuration = 10; //placeholder to store the value of the bulb shot this should be taken as input. note that my primary goal is in fact to perform bulb captures. but this should be extended for sure to take Shutter Speed capture as set in camera @@ -189,7 +185,7 @@ camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) return GP_ERROR; } - GP_LOG_DATA(buffer,valread,"read from udp port"); + GP_LOG_DATA((char*)buffer,valread,"read from udp port"); if (valread == 0) continue; @@ -205,12 +201,11 @@ camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) } //GP_LOG_DATA(buffer+start,end-start,"read from udp port"); gp_file_set_mime_type (file, GP_MIME_JPEG); - return gp_file_append (file, buffer+start, end-start); + return gp_file_append (file, (char*)buffer+start, end-start); } return GP_ERROR; } - //int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context); static int camera_about (Camera *camera, CameraText *about, GPContext *context); @@ -411,7 +406,6 @@ static char* loadCmd (Camera *camera,char* cmd) { CURL *curl; CURLcode res; - int stream = strcmp (cmd, STARTSTREAM); char URL[100]; GPPortInfo info; char *xpath; @@ -441,9 +435,6 @@ loadCmd (Camera *camera,char* cmd) { /* ok */ } curl_easy_cleanup(curl); - - if (strcmp(cmd,PLAYMODE)==0) { - } return lmb.data; } @@ -602,12 +593,12 @@ strend(const char *s, const char *t) static int NumberPix(Camera *camera) { - xmlChar *keyz = NULL; - int numpics = 0; + xmlChar *keyz = NULL; + int numpics = 0; + char *temp = loadCmd(camera,"cam.cgi?mode=get_content_info"); + xmlDocPtr doc = xmlParseDoc((unsigned char*) temp); + xmlNodePtr cur = NULL; - char *temp = loadCmd(camera,NUMPIX); - xmlDocPtr doc = xmlParseDoc((unsigned char*) temp); - xmlNodePtr cur = NULL; cur = xmlDocGetRootElement(doc); /*GP_LOG_D("NumberPix Decode current root node is %s \n", doc); */ @@ -1009,13 +1000,13 @@ processNode(xmlTextReaderPtr reader) { switch (ReadoutMode) { case 0 : //'jpg - lookupImgtag = "CAM_RAW_JPG"; + lookupImgtag = "CAM_RAW_JPG"; break; case 1 :// 'raw - lookupImgtag = "CAM_RAW"; + lookupImgtag = "CAM_RAW"; break; case 2 ://'thumb - lookupImgtag = "CAM_LRGTN"; + lookupImgtag = "CAM_LRGTN"; break; } -- cgit v1.2.1 From 47c95ec31cc3e98be9d024f98ba6608ee3c5d2c8 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Thu, 27 Jun 2019 15:44:16 +0200 Subject: added tz91.log --- camlibs/lumix/tz91.log | 3861 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3861 insertions(+) create mode 100644 camlibs/lumix/tz91.log diff --git a/camlibs/lumix/tz91.log b/camlibs/lumix/tz91.log new file mode 100644 index 000000000..d80147aa6 --- /dev/null +++ b/camlibs/lumix/tz91.log @@ -0,0 +1,3861 @@ +/config/settings/clock +Label: Clock +Readonly: 0 +Type: TEXT +Current: +err_non_support +END +/config/settings/shutterspeed +Label: Shutterspeed +Readonly: 0 +Type: TEXT +Current: +err_reject +END +/config/settings/quality +Label: Qualität +Readonly: 0 +Type: TEXT +Current: +ok +END +/config/settings/aperture +Label: Blende +Readonly: 0 +Type: TEXT +Current: +ok +END +/config/settings/iso +Label: ISO +Readonly: 0 +Type: TEXT +Current: +ok +END +/config/settings/afmode +Label: Autofokus Modus +Readonly: 0 +Type: TEXT +Current: +err_critical +END +/config/settings/focusmode +Label: Fokusmodus +Readonly: 0 +Type: TEXT +Current: +ok +END +/config/settings/mf_assist +Label: MF Assist +Readonly: 0 +Type: TEXT +Current: +ok +END +/config/settings/mf_assist_mag +Label: MF Assist Mag +Readonly: 0 +Type: TEXT +Current: +err_non_support +END +/config/settings/ex_tele_conv +Label: Ex Teleconv +Readonly: 0 +Type: TEXT +Current: +ok +END +/config/settings/lens +Label: Lens +Readonly: 0 +Type: TEXT +Current: ok,1536/256,882/256,2816/256,-512/256,0,off,720,24,off,128/1024,on +END +/config/settings/capability +Label: Capability +Readonly: 0 +Type: TEXT +Current: ok1.6DC2702tele-normaltele-fastwide-normalwide-fast4kphoto_markingtouch_command_autooneshot_af_enablesetting_play_sort_mode_enableaf_size_change_pinchzoombar_with_partition_focaldistlens_detach_disablenormal_disp_with_zoom_operation_enablegeotag_add_enablepeaking_flag_use_enablemenu_notify_enablecopy_assist_enable1920x1080/25p +END + +Possible queries we sent and replies: + +http://192.168.54.1/cam.cgi?mode=camcmd&value=recmode + + +ok + + +http://192.168.54.1/cam.cgi?mode=setsetting&type=quality&value=raw_fine + + +ok + +http://192.168.54.1/cam.cgi?mode=camcmd&value=playmode + + +ok + +http://192.168.54.1/cam.cgi?mode=get_content_info + + +ok2651651 + + +http://192.168.54.1/cam.cgi?mode=camcmd&value=playmode + + +ok + +http://192.168.54.1/cam.cgi?mode=get_content_info + + +ok2651651 + +http://192.168.54.1:60606/Server0/CDS_control + +0BrowseDirectChildren*0651LumixLink2.0 + + + + + + + 103-0094 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030094.JPG + http://192.168.54.1:50001/DT1030094.JPG + http://192.168.54.1:50001/DL1030094.JPG + + + 103-0095 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030095.JPG + http://192.168.54.1:50001/DT1030095.JPG + http://192.168.54.1:50001/DL1030095.JPG + + + 103-0096 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030096.JPG + http://192.168.54.1:50001/DT1030096.JPG + http://192.168.54.1:50001/DL1030096.JPG + + + 103-0097 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030097.JPG + http://192.168.54.1:50001/DT1030097.JPG + http://192.168.54.1:50001/DL1030097.JPG + + + 103-0098 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030098.JPG + http://192.168.54.1:50001/DT1030098.JPG + http://192.168.54.1:50001/DL1030098.JPG + + + 103-0099 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030099.JPG + http://192.168.54.1:50001/DT1030099.JPG + http://192.168.54.1:50001/DL1030099.JPG + + + 103-0100 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030100.JPG + http://192.168.54.1:50001/DT1030100.JPG + http://192.168.54.1:50001/DL1030100.JPG + + + 103-0102 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030102.JPG + http://192.168.54.1:50001/DT1030102.JPG + http://192.168.54.1:50001/DL1030102.JPG + + + 103-0103 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030103.JPG + http://192.168.54.1:50001/DT1030103.JPG + http://192.168.54.1:50001/DL1030103.JPG + + + 103-0104 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030104.JPG + http://192.168.54.1:50001/DT1030104.JPG + http://192.168.54.1:50001/DL1030104.JPG + + + 103-0105 + WRITABLE + object.item.videoItem.movie + http://192.168.54.1:50001/DO1030105.MP4 + http://192.168.54.1:50001/DT1030105.JPG + http://192.168.54.1:50001/DL1030105.JPG + + + 103-0106 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030106.JPG + http://192.168.54.1:50001/DT1030106.JPG + http://192.168.54.1:50001/DL1030106.JPG + + + 103-0107 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030107.JPG + http://192.168.54.1:50001/DT1030107.JPG + http://192.168.54.1:50001/DL1030107.JPG + + + 103-0108 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030108.JPG + http://192.168.54.1:50001/DT1030108.JPG + http://192.168.54.1:50001/DL1030108.JPG + + + 103-0109 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030109.JPG + http://192.168.54.1:50001/DT1030109.JPG + http://192.168.54.1:50001/DL1030109.JPG + + + 103-0110 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030110.JPG + http://192.168.54.1:50001/DT1030110.JPG + http://192.168.54.1:50001/DL1030110.JPG + + + 103-0111 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030111.JPG + http://192.168.54.1:50001/DT1030111.JPG + http://192.168.54.1:50001/DL1030111.JPG + + + 103-0112 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030112.JPG + http://192.168.54.1:50001/DT1030112.JPG + http://192.168.54.1:50001/DL1030112.JPG + + + 103-0113 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030113.JPG + http://192.168.54.1:50001/DT1030113.JPG + http://192.168.54.1:50001/DL1030113.JPG + + + 103-0114 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030114.JPG + http://192.168.54.1:50001/DT1030114.JPG + http://192.168.54.1:50001/DL1030114.JPG + + + 103-0115 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030115.JPG + http://192.168.54.1:50001/DT1030115.JPG + http://192.168.54.1:50001/DL1030115.JPG + + + 103-0116 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030116.JPG + http://192.168.54.1:50001/DT1030116.JPG + http://192.168.54.1:50001/DL1030116.JPG + + + 103-0117 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030117.JPG + http://192.168.54.1:50001/DT1030117.JPG + http://192.168.54.1:50001/DL1030117.JPG + + + 103-0118 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030118.JPG + http://192.168.54.1:50001/DT1030118.JPG + http://192.168.54.1:50001/DL1030118.JPG + + + 103-0119 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030119.JPG + http://192.168.54.1:50001/DT1030119.JPG + http://192.168.54.1:50001/DL1030119.JPG + + + 103-0120 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030120.JPG + http://192.168.54.1:50001/DT1030120.JPG + http://192.168.54.1:50001/DL1030120.JPG + + + 103-0121 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030121.JPG + http://192.168.54.1:50001/DT1030121.JPG + http://192.168.54.1:50001/DL1030121.JPG + + + 103-0122 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030122.JPG + http://192.168.54.1:50001/DT1030122.JPG + http://192.168.54.1:50001/DL1030122.JPG + + + 103-0123 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030123.JPG + http://192.168.54.1:50001/DT1030123.JPG + http://192.168.54.1:50001/DL1030123.JPG + + + 103-0124 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030124.JPG + http://192.168.54.1:50001/DT1030124.JPG + http://192.168.54.1:50001/DL1030124.JPG + + + 103-0125 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030125.JPG + http://192.168.54.1:50001/DT1030125.JPG + http://192.168.54.1:50001/DL1030125.JPG + + + 103-0126 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030126.JPG + http://192.168.54.1:50001/DT1030126.JPG + http://192.168.54.1:50001/DL1030126.JPG + + + 103-0127 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030127.JPG + http://192.168.54.1:50001/DT1030127.JPG + http://192.168.54.1:50001/DL1030127.JPG + + + 103-0128 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030128.JPG + http://192.168.54.1:50001/DT1030128.JPG + http://192.168.54.1:50001/DL1030128.JPG + + + 103-0129 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030129.JPG + http://192.168.54.1:50001/DT1030129.JPG + http://192.168.54.1:50001/DL1030129.JPG + + + 103-0130 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030130.JPG + http://192.168.54.1:50001/DT1030130.JPG + http://192.168.54.1:50001/DL1030130.JPG + + + 103-0131 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030131.JPG + http://192.168.54.1:50001/DT1030131.JPG + http://192.168.54.1:50001/DL1030131.JPG + + + 103-0132 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030132.JPG + http://192.168.54.1:50001/DT1030132.JPG + http://192.168.54.1:50001/DL1030132.JPG + + + 103-0133 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030133.JPG + http://192.168.54.1:50001/DT1030133.JPG + http://192.168.54.1:50001/DL1030133.JPG + + + 103-0138 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030138.JPG + http://192.168.54.1:50001/DT1030138.JPG + http://192.168.54.1:50001/DL1030138.JPG + + + 103-0139 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030139.JPG + http://192.168.54.1:50001/DT1030139.JPG + http://192.168.54.1:50001/DL1030139.JPG + + + 103-0140 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030140.JPG + http://192.168.54.1:50001/DT1030140.JPG + http://192.168.54.1:50001/DL1030140.JPG + + + 103-0141 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030141.JPG + http://192.168.54.1:50001/DT1030141.JPG + http://192.168.54.1:50001/DL1030141.JPG + + + 103-0142 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030142.JPG + http://192.168.54.1:50001/DT1030142.JPG + http://192.168.54.1:50001/DL1030142.JPG + + + 103-0143 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030143.JPG + http://192.168.54.1:50001/DT1030143.JPG + http://192.168.54.1:50001/DL1030143.JPG + + + 103-0144 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030144.JPG + http://192.168.54.1:50001/DT1030144.JPG + http://192.168.54.1:50001/DL1030144.JPG + + + 103-0145 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030145.JPG + http://192.168.54.1:50001/DT1030145.JPG + http://192.168.54.1:50001/DL1030145.JPG + + + 103-0146 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030146.JPG + http://192.168.54.1:50001/DT1030146.JPG + http://192.168.54.1:50001/DL1030146.JPG + + + 103-0147 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030147.JPG + http://192.168.54.1:50001/DT1030147.JPG + http://192.168.54.1:50001/DL1030147.JPG + + + 103-0148 + WRITABLE + object.item.imageItem + http://192.168.54.1:50001/DO1030148.JPG + http://192.168.54.1:50001/DT1030148.JPG + http://192.168.54.1:50001/DL1030148.JPG + + + + + +http://192.168.54.1/cam.cgi?mode=camcmd&value=recmode + + +ok + +http://192.168.54.1/cam.cgi?mode=getsetting&type=clock + + +err_non_support + +http://192.168.54.1/cam.cgi?mode=getsetting&type=shtrspeed + + +ok + +http://192.168.54.1/cam.cgi?mode=getsetting&type=quality + + +ok + +http://192.168.54.1/cam.cgi?mode=getsetting&type=focal + + +ok + +http://192.168.54.1/cam.cgi?mode=getsetting&type=iso + + +ok + + + +http://192.168.54.1/cam.cgi?mode=getsetting&type=afmode + + +err_critical + +http://192.168.54.1/cam.cgi?mode=getsetting&type=focusmode + + +ok + +http://192.168.54.1/cam.cgi?mode=getsetting&type=mf_asst + + +ok + +http://192.168.54.1/cam.cgi?mode=getsetting&type=mf_asst_mag + + +err_non_support + +http://192.168.54.1/cam.cgi?mode=getsetting&type=ex_tele_conv + + +ok + +http://192.168.54.1/cam.cgi?mode=getinfo&type=lens + +ok,1536/256,882/256,2816/256,-512/256,0,on,720,24,on,128/1024,on + +http://192.168.54.1/cam.cgi?mode=getinfo&type=capability + + + + + ok + 1.6 + + DC2702 + + + tele-normal + tele-fast + wide-normal + wide-fast + 4kphoto_marking + + + touch_command_auto + oneshot_af_enable + setting_play_sort_mode_enable + af_size_change_pinch + zoombar_with_partition_focaldist + lens_detach_disable + normal_disp_with_zoom_operation_enable + geotag_add_enable + peaking_flag_use_enable + menu_notify_enable + copy_assist_enable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1920x1080/25p + + + + + + +http://192.168.54.1/cam.cgi?mode=startstream&value=49199 + + +ok + +http://192.168.54.1/cam.cgi?mode=getstate + + + + ok + + 3/3 + rec + 1325 + write_enable + set + 900 + off + off + off + num + 0 + enable/enable + 0 + off + low + normal + off + off + none + write_enable + unset + off + sd1 + off + -1/0 + no_disp + off + D2.91 + + + +http://192.168.54.1/cam.cgi?mode=getinfo&type=allmenu + + + + ok + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Set connect. dest. + Live Control Settings + Self shot mode + Live Control quality + VGA + QVGA + Lens extension warning + Jump Snap + Playback settings + Application function + Network name + Scene Guide + Sample display + Help + Terms of use + Creative Control + Expressive + Retro + Old Days + High Key + Low Key + Sepia + Monochrome + Dynamic Monochrome + Rough Monochrome + Silky Monochrome + Impressive Art + High Dynamic + Cross Process + Toy Effect + Toy Pop + Bleach Bypass + Miniature Effect + Soft Focus + Fantasy + Star Filter + One Point Color + Sunshine + Scene Guide + Clear Portrait + Silky Skin + Backlit Softness + Clear in Backlight + Relaxing Tone + Sweet Child&apos;s Face + Distinct Scenery + Bright Blue Sky + Romantic Sunset Glow + Vivid Sunset Glow + Glistening Water + Clear Nightscape + Cool Night Sky + Warm Glowing Nightscape + Artistic Nightscape + Glittering Illuminations + Handheld Night Shot + Clear Night Portrait + Soft Image of a Flower + Appetizing Food + Cute Dessert + Freeze Animal Motion + Clear Sports Shot + Monochrome + Photo Style + Standard + Vivid + Natural + Monochrome + Scenery + Portrait + Custom + Filter Settings + No Effect + Aspect Ratio + 4:3 + 3:2 + 16:9 + 1:1 + Picture Size + L 20M + L 17M + L 14.5M + M 10M + EX M 10M + M 9M + EX M 9M + M 8M + EX M 8M + M 7.5M + EX M 7.5M + S 5M + EX S 5M + S 4.5M + EX S 4.5M + S 3.5M + EX S 3.5M + S 2M + EX S 2M + Quality + Fine + Standard + RAW+Fine + RAW+Standard + RAW + Focus Mode + AF + AF Macro + Macro Zoom + MF + AFS/AFF/AFC + AFS + AFF + AFC + Metering Mode + Multi Metering + Center Weighted + Spot + Flash Mode + Auto + iAuto + Auto/Red-Eye + Forced Flash On + Forced On/Red-Eye + Slow Sync. + Slow Sync./Red-Eye + Forced Flash Off + Rec Format + AVCHD + MP4 + Video Rec Quality + AVCHD(1920x1080)60p 28M + AVCHD(1920x1080)50p 28M + AVCHD(1920x1080)60i 17M + AVCHD(1920x1080)50i 17M + AVCHD(1920x1080)30p 24M + AVCHD(1920x1080)25p 24M + MP4(3840x2160)30p 100Mbps + MP4(3840x2160)25p 100Mbps + MP4(1920x1080)60p 28Mbps + MP4(1920x1080)50p 28Mbps + MP4(1920x1080)30p 20Mbps + MP4(1920x1080)25p 20Mbps + MP4(1280x720)30p 10Mbps + MP4(1280x720)25p 10Mbps + Stop Motion Animation + 4K Live Cropping + 40 sec. + 20 sec. + Off + Bracket + Bracket Type + Exposure + WB + Off + Step + 3・1/3 + 3・2/3 + 3・1 + 5・1/3 + 5・2/3 + 5・1 + 7・1/3 + 7・2/3 + 7・1 + Sequence + 0/-/+ + -/0/+ + Single Shot Setting + ONE BY ONE + ONE TAP + Touch Shutter + Touch AE + Aperture/Shutter Speed + Aperture + Shutter Speed + Program Shift + F + SS + Exposure Comp. + -5 + -4 2/3 + -4 1/3 + -4 + -3 2/3 + -3 1/3 + -3 + -2 2/3 + -2 1/3 + -2 + -1 2/3 + -1 1/3 + -1 + -2/3 + -1/3 + 0 + +1/3 + +2/3 + +1 + +1 1/3 + +1 2/3 + +2 + +2 1/3 + +2 2/3 + +3 + +3 1/3 + +3 2/3 + +4 + +4 1/3 + +4 2/3 + +5 + Step + Off + 3・1/3 + 3・2/3 + 3・1 + 5・1/3 + 5・2/3 + 5・1 + 7・1/3 + 7・2/3 + 7・1 + AF Mode + Face/Eye Detection + Tracking + 49-Area + Custom Multi + Vertical Pattern + Horizontal Pattern + Central Pattern + Custom1 + Custom2 + Custom3 + 1-Area + Pinpoint + Sensitivity + i.Auto + i.ISO + 80 + 100 + 125 + 160 + 200 + 250 + 320 + 400 + 500 + 640 + 800 + 1000 + 1250 + 1600 + 2000 + 2500 + 3200 + H.4000 + H.5000 + H.6400 + White Balance + Auto White Balance + Daylight + Cloudy + Shade + Incandescent + Flash + White Set 1 + White Set 2 + White Set 3 + White Set 4 + Color Temperature + Drive Mode + Single + Burst Shooting + H + M + L + 4K PHOTO + 4K Burst + 4K Burst(S/S) + 4K Pre-Burst + Post Focus + Self Timer + 10sec. + 10s / 3pictures + 2sec. + Drive Mode Off + Peaking + Off + Low + High + + + 接続先設定 + リモートビュー設定 + 自分撮りモード + リモートビュー画質 + レンズ飛び出し警告 + ジャンプスナップ + 再生設定 + アプリ機能 + ネットワーク名称 + シーンガイド + サンプル表示 + ヘルプ + 利用規約 + クリエイティブコントロール + ポップ + レトロ + オールドデイズ + ハイキー + ローキー + セピア + モノクローム + ダイナミックモノクローム + ラフモノクローム + シルキーモノクローム + インプレッシブアート + ハイダイナミック + クロスプロセス + トイフォト + トイポップ + ブリーチバイパス + ジオラマ + ソフトフォーカス + ファンタジー + クロスフィルター + ワンポイントカラー + サンシャイン + シーンガイド + 人物をきれいに撮る + 人物の肌をきれいに撮る + 逆光でふんわり撮る + 逆光でしっかり撮る + ほのぼのした雰囲気で撮る + 子どもをかわいく撮る + 風景をきれいに撮る + 青空をさわやかに撮る + 夕焼けを幻想的に撮る + 夕焼けを印象的に撮る + 水面をキラキラ撮る + 夜景をきれいに撮る + 夜空をクールに撮る + 夜景を暖かく撮る + 夜景をアーティスティックに撮る + イルミネーションをキラキラ撮る + 夜景を手持ちで撮る + 夜景をバックに人物をきれいに撮る + 花をふんわり撮る + 料理をおいしそうに撮る + スイーツをかわいく撮る + 動くペットをきちんと撮る + スポーツをきれいに撮る + モノクロで撮る + フォトスタイル + スタンダード + ヴィヴィッド + ナチュラル + モノクローム + 風景 + 人物 + カスタム + フィルター設定 + 効果なし + 画像横縦比 + 記録画素数 + クオリティ + ファイン + スタンダード + RAW+ファイン + RAW+スタンダード + フォーカスモード + AFマクロ + ズームマクロ + 測光モード + マルチ測光 + 中央重点 + スポット + フラッシュモード + オート + iオート + 赤目軽減オート + 強制発光 + 赤目軽減強制発光 + スローシンクロ + 赤目軽減スローシンクロ + 発光禁止 + 記録方式 + 動画画質設定 + コマ撮りアニメ + 4Kライブクロップ + 40秒 + 20秒 + OFF + ブラケット + ブラケット種類 + 露出 + OFF + 補正幅 + ブラケット順序 + 単写時撮影方法 + 一枚ずつ + 一気撮影 + タッチシャッター + タッチAE + 絞り/シャッタースピード + 絞り + シャッタースピード + プログラムシフト + 露出補正 + 補正幅 + OFF + オートフォーカスモード + 顔・瞳認識 + 追尾 + 49点 + カスタムマルチ + + + 中央 + カスタム1 + カスタム2 + カスタム3 + 1点 + ピンポイント + ISO感度 + AUTO + ホワイトバランス + オートホワイトバランス + 晴天 + 曇り + 日陰 + 白熱灯 + フラッシュ + セットモード 1 + セットモード 2 + セットモード 3 + セットモード 4 + 色温度 + ドライブモード + 単写 + 連写 + 4K フォト + 4K連写 + 4K連写(S/S) + 4Kプリ連写 + フォーカスセレクト + セルフタイマー + 10秒 + 10秒/3枚 + 2秒 + ドライブモードOFF + ピーキング + OFF + + + + + Verbindungsz. einst. + Live-Steuer.-Einst. + Selbstaufnahme-Modus + Bildqualität Live-Steuerung + Warn.: Objektivausf. + Sprungschnappschuss + Wiedergabe-Einstell. + Applikationsfunktion + Netzwerkname + Szenen-Guide + Musteranzeige + Hilfe + Nutzungsbedingungen + Kreativmodus + Expressiv + Früher + Low key + Schwarz-Weiß + Dynamisch Monochrom + Grobes Schwarz-Weiß + Weiches Schwarz-Weiß + Impressiv + Hohe Dynamik + Cross-Prozess + Spielzeugeffekt + Bleach-Bypass + Miniatureffekt + Weichzeichnung + Fantasie + Sternfilter + Selektivfarbe + Sonnenschein + Szenen-Guide + Freigestelltes Portrait + Seidige Haut + Gegenlicht weich + Gegenlicht hart + Weicher Farbton + Kindergesicht + Landschaft + Heller blauer Himmel + Sonnenuntergang romantisch + Sonnenuntergang dramatisch + Glitzerndes Wasser + Klare Nachtaufnahme + Kühler Nachthimmel + Warme Nachtlandschaft + Nachtlandschaft verfremdet + Neonlichter + Hand-Nachtaufn. + Nachtportrait + Weiches Bild einer Blume + Appetitliche Speisen + Leckeres Dessert + Bewegung einfrieren + Sportfoto + Monochrom + Bildstil + Lebhaft + Natürlich + Monochrom + Landschaft + Porträt + Individuell + Filter-Einstellungen + Kein Effekt + Bildverhält. + Bildgröße + Qualität + Fein + RAW+Fein + Fokusmodus + AF Makro + Makro Zoom + Messmethode + Mehrfeld-Messung + Mittenbetont + Blitzlicht-Modus + iAutomatik + Auto/Rot-Aug + Forc. Blitzl. Ein + Blitz Ein/Rot-Aug + Langzeitsynchr. + Lz-Sync/Rot-Aug + Forciert Aus + Aufnahmeformat + Video Aufn.-Qual. + Stop-Motion-Animation + 4K Live Schneiden + 40 s + 20 s + Bracketing + Bracketing-Art + Belichtung + Schritt + Sequenz + Einstellung Einzelfoto + EINZELN + EINM. TIP. + Touch-Auslöser + Touch-AE + Blende/Verschlusszeit + Blende + Verschlusszeit + Programm-wechsel + Belichtungsausgleich + Schritt + AF-Modus + Gesichts-/Augenerkennung + Verfolgung + 49-Feld + Multi-Individuell + Vertikales Muster + Horizontales Muster + Zentral Muster + Benutzerspez.1 + Benutzerspez.2 + Benutzerspez.3 + 1-Feld + Punkt + Empfindlichkeit + Weißabgleich + Autom. Weißabgl. + Tageslicht + Wolken + Schatten + Glühlampen + Blitzlicht + Weißabgleich-Einst. 1 + Weißabgleich-Einst. 2 + Weißabgleich-Einst. 3 + Weißabgleich-Einst. 4 + Farbtemperatur + Antriebsmodus + Einzeln + Serienbilder + 4K Foto + 4K-Serienbilder + 4K-Serienbilder (S/S) + Post-Fokus + Selbstausl. + 10 s + 10 s/3 Bilder + 2 s + Antriebsmodus Aus + Focus peaking + Niedrig + Hoch + + + Régl destin. connex. + Rég. commande dynam. + Mode Autoportrait + Qualité comm. dynam. + Aver. objec. déployé + Instantané saut + Réglages de lecture + Fonction d'application + Nom de réseau + Guide scène + Exemple d’affichage + Aide + Conditions d'utilisation + Commande créative + Expressif + Rétro + Ancien temps + Tons clairs + Clair-obscur + Sépia + Monochrome dynamique + Monochrome brut + Monochrome doux + Impressionnisme + Dynamique élevée + Dévelop. Croisé + Effet jouet + Effet jouet vif + Procédé sans blanchiment + Effet miniature + Focus doux + Fantastique + Filtre étoile + Désatura. Partielle + Rayon de soleil + Guide scène + Portrait clair + Peau soyeuse + Douceur rétroéclairée + Clair en rétroéclairage + Ton reposant + Visage d'enfant + Paysage net + Ciel bleu clair + Lueur romantique du couchant + Vif éclat du couchant + Eau scintillante + Paysage nocturne clair + Ciel nocturne froid + Paysage nocturne chaud + Paysage nocturne artistique + Illuminations scintillantes + Prise noct. manu. + Portrait nuit claire + Image douce d'une fleur + Nourriture appétissante + Beau dessert + Animal en mouvement + Photo de sport nette + Style photo + Éclatant + Naturel + Paysage + Personnalisée + Configuration de filtre + Pas d'effet + Format + Format imag + Qualité + Fin + RAW+fin + RAW+standard + Mode de Focus + AF macro + Zoom macro + Mode mesure + Mesure multiple + Centre + Mode de flash + Auto/y. roug. + Flash forcé oui + Forcé/y. roug. + Sync. lente + Synchr lente/yx rouge + Forcé non + Format enregistrement + Vidéo Qualité enr. + Anim image par image + Recadrage 4K Live + 40 s + 20 s + Non + Bracketing + Type de bracketing + Exposition + Non + Palier + Séquence + Réglage vue unique + UNE P. UNE + UNE TOUCHE + Déclen. tact. + AE tactile + Ouverture/Vitesse obtur. + Ouverture + Vitesse obtur. + Changement progr. + Compensation expo + Palier + Non + Mode AF + Détection visage/œil + Suivi + 49-zones + Multiple personnalisé + Motif vertical + Motif horizontal + Motif central + Personnaliser1 + Personnaliser2 + Personnaliser3 + 1-zone + Point precis + Sensibilité + Éq.blancs + Balance de blancs auto + Jour + Nuageux + Fondu + Réglage bal. blancs 1 + Réglage bal. blancs 2 + Réglage bal. blancs 3 + Réglage bal. blancs 4 + Température couleur + Mode d'entraînement + Simple + Prise rafale + PHOTO 4K + Rafale 4K + Rafale 4K (S/S) + Pré-rafale 4K + Post focus + Retardateur + 10 s + 10 s/3 photos + 2 s + Mode d'entraînement non + Focus Peaking + Non + Bas + Élevé + + + Param. dest. conn. + Param. commande dist. + Mode autoportrait + Comm. dist. qual. Image + Avert. extension objectif + Instantané saut + Param. lecture + Fonction de l'application + Nom de réseau + Guide scène + Exemple d’affichage + Aide + Conditions d'utilisation + Commande créative + Expressif + Rétro + Ancien temps + Tons clairs + Clair-obscur + Sépia + Monochrome dynamique + Monochrome brut + Monochrome doux + Impressionnisme + Dynamique élevée + Dévelop. Croisé + Effet jouet + Effet jouet vif + Procédé sans blanchiment + Effet miniature + Focus doux + Fantastique + Filtre étoile + Désatura. Partielle + Rayon de soleil + Guide scène + Portrait clair + Peau soyeuse + Douceur rétroéclairée + Clair en rétroéclairage + Ton reposant + Visage d'enfant + Paysage net + Ciel bleu clair + Lueur romantique du couchant + Vif éclat du couchant + Eau scintillante + Paysage nocturne clair + Ciel nocturne froid + Paysage nocturne chaud + Paysage nocturne artistique + Illuminations scintillantes + Prise noct. manu. + Portrait nuit claire + Image douce d'une fleur + Nourriture appétissante + Beau dessert + Animal en mouvement + Photo de sport nette + Style photo + Éclatant + Naturel + Paysage + Personnalisée + Configuration de filtre + Pas d'effet + Format + Format imag + Qualité + Fin + RAW+fin + RAW+standard + Mode de Focus + AF macro + Zoom macro + Mode mesure + Mesure multiple + Centre + Mode de flash + Auto/y. roug. + Flash forcé oui + Forcé/y. roug. + Sync. lente + Synchr lente/yx rouge + Forcé non + Format enregistrement + Vidéo Qualité enr. + Anim image par image + Recadrage 4K Live + 40 s + 20 s + Non + Bracketing + Type de bracketing + Exposition + Non + Palier + Séquence + Réglage vue unique + UNE P. UNE + UNE TOUCHE + Déclen. tact. + AE tactile + Ouverture/Vitesse obtur. + Ouverture + Vitesse obtur. + Changement progr. + Compensation expo + Palier + Non + Mode AF + Détection visage/œil + Suivi + 49-zones + Multiple personnalisé + Motif vertical + Motif horizontal + Motif central + Personnaliser1 + Personnaliser2 + Personnaliser3 + 1-zone + Point precis + Sensibilité + Éq.blancs + Balance de blancs auto + Jour + Nuageux + Fondu + Réglage bal. blancs 1 + Réglage bal. blancs 2 + Réglage bal. blancs 3 + Réglage bal. blancs 4 + Température couleur + Mode d'entraînement + Simple + Prise rafale + PHOTO 4K + Rafale 4K + Rafale 4K (S/S) + Pré-rafale 4K + Post focus + Retardateur + 10 s + 10 s/3 photos + 2 s + Mode d'entraînement non + Focus Peaking + Non + Bas + Élevé + + + Imposta desti. conn. + Impos. Contr. “live” + Modalità autoscatto + Qualità Cont. “live” + Avvert. esten.obiet. + Istantanea del salto + Impostaz. riproduz. + Funzione applicazione + Nome rete + Guida scene + Visualizzazione di esempio + ? + Termini d'uso + Controllo creativo + Espressivo + Nostalgico + Vecchi tempi + High key + Sottoesposizione + Monocromo + Monocromatica dinamica + Monocromo sgranato + Monocromo vellutato + Opera d'arte + High dynamic + Processo incrociato + Effetto giocattolo + Giocattolo colori vivi + Bleach bypass + Miniature effetto + Messa a fuoco soft + Filtro a stella + Punto colore + Bagliore + Guida scene + Ritratto chiaro + Pelle di seta + Controluce morbido + Controluce chiaro + Tonalità rilassante + Viso dolce di un bambino + Paesaggio definito + Cielo azzurro + Bagliore romantico del tramonto + Bagliore intenso del tramonto + Scintillio dell'acqua + Notturno nitido + Cielo notturno sofisticato + Notturno caldo e vivido + Notturno artistico + Luci sfavillanti + Ripr. nott. a mano + Ritratto notturno chiaro + Immagine delicata di un fiore + Manicaretti + Dessert goloso + Animale in movimento + Eventi sportivi + Monocromatico + Stile foto + Vivida + Naturale + Monocromatica + Panorama + Ritratto + Personalizzato + Impostazioni filtro + Nessun effetto + Formato + Dim. immag. + Qualità + RAW+fine + RAW+standard + Modalità fuoco + AF macro + Zoom macro + Mod. esposim. + Mod. esposim. mult. + Centro pesato + Modalità Flash + Auto/occhi r. + Att. forz. flash + Att.forz./occhi r. + Slow sync. + Sinc. lenta/occhi r. + Disatt.forz.fl. + Formato Rec + Video Qualità reg. + Animaz. Stop Motion + Ritaglio Live 4K + Tipo Bracket + Esposizione + Passo + Sequenza + Impost. scatto singolo + UNA x UNA + UN TOCCO + Scatto touch + AE touch + Apertura/Vel. otturatore + Apertura + Vel. otturatore + Cambio progr. + Compens. Esposiz. + Passo + Modalità AF + Face/eye detection + 49 aree + Personalizzazione multipla + Schema verticale + Schema orizzontale + Schema central + Personalizzato1 + Personalizzato2 + Personalizzato3 + 1 area + Messa a fuoco precisa + Sensibilità + Bil. bianco + Bil. autom. del bianco + Luce diurna + Nuvoloso + Ombra + Incandescenza + Impost. bianco 1 + Impost. bianco 2 + Impost. bianco 3 + Impost. bianco 4 + Temperatura colore + Modalità avanzamento + Sing. + Scatto continuo + FOTO 4K + Scatto a raff. 4K + Scatto a raff. 4K (S/S) + Pre-scatto a raff. 4K + Autoscatto + 10 sec. + 10 s/3immagini + 2 sec. + Modalità avanzamento off + Bassa + Alta + + + Ajustar dest. conex. + Ajustes control vivo + Modo de disparo automático + Calidad control vivo + Aviso ext. objetivo + Instantánea de salto + Ajustes reproducción + Función de aplicación + Nombre de red + Guía escenas + Visualización de muestras + Ayuda + Condiciones de uso + Control creativo + Expresivo + Viejos tiempos + Tonalidad alta + Tonalidad baja + Monocromático + Monocromo dinámico + Monocromático rugoso + Monocromático sedoso + Arte impresionante + Dinámica alta + Proceso cruzado + Efecto cám. juguete + Juguete vívido + Elim. blanqueamiento + Efecto miniatura + Enfoque suave + Fantasía + Filtro de estrellas + Color puntual + Soleado + Guía escenas + Retrato claro + Piel suave + Contraluz suave + Contraluz clara + Tono relajante + Carita de niño + Escenario Distinto + Cielo azul brillante + Atardecer romántico + Atardecer de colores vivos + Agua reluciente + Paisaje nocturno claro + Cielo nocturno frío + Paisaje nocturno cálido + Paisaje nocturno artístico + Luces y resplandores + Foto nocturna manual + Claro retrato nocturno + Suave imagen de una flor + Comida apetecible + Postre atractivo + Movimiento animal congelado + Foto deportiva clara + Monocromática + Fotoestilo + Estándar + Vívido + Monocromo + Paisaje + Retrato + Personalizar + Ajustes de filtro + Sin efecto + Aspecto + Tamaño de imagen + Calidad + Fina + Estándar + RAW+fina + RAW+estándar + Modo enfoque + AF macro + Zoom macro + Modo medición + Medición múltiple + Central + Puntual + Modo de flash + Automático + Aut./ojo rojo + Flash activado + Forzar act./ ojo-rojo + Sinc. lenta + Sincro. lenta /ojo-rojo + Flash desact. + Formato de grabación + Calidad de grab. Video + Anima. Movimiento D. + Recort. 4K tiempo real + 40 s. + 20 s. + Tipo de bracket + Exposición + Paso + Secuencia + Ajuste disparo único + UNO A UNO + UN TOQUE + Disparo Táctil + AE Táctil + Apertura/Velocidad obtur. + Apertura + Velocidad obtur. + Cambio progr. + Comp. de exposición + Paso + Modo AF + Detección de la cara/ojos + Localización + 49 Áreas + Personalizar múltiple + Patrón vertical + Patrón horizontal + Patrón central + Personalizar 1 + Personalizar 2 + Personalizar 3 + 1 Área + Enfoque preciso + Sensibilidad + Balance b. + Bal. del blanco aut. + Luz del día + Nublado + Sombra + Incandescente + Aj. blanco 1 + Aj. blanco 2 + Aj. blanco 3 + Aj. blanco 4 + Temperatura del color + Modo accionamiento + Único + Disparo de ráfaga + Foto 4K + Ráfaga 4K + Ráfaga 4K (S/S) + Pre-ráfaga 4K + Post-enfoque + Autodisparador + 10 s. + 10 s./3 imag. + 2 s. + Modo accionamiento apagado + Contornos máximos + Bajo + Alto + + + 連接目的地設定 + 即時控制設定 + 自拍模式 + 即時控制影像品質 + 鏡頭伸縮警告 + 跳躍快照 + 播放設定 + 應用程式功能 + 網路名稱 + 場景指南 + 簡易顯示 + 說明 + 使用條款 + 創意控制 + 生動 + 復古 + 舊時光 + 明調 + 暗色調 + 復古色 + 單色調 + 動態黑白 + 粗粒單色調 + 絲柔單色調 + 深刻藝術 + 高動態 + 正片負沖 + 玩具攝影效果 + 玩具普普風 + 漂白效果 + 模型效果 + 柔焦 + 夢幻 + 星芒濾鏡 + 焦點色彩 + 陽光 + 場景指南 + 清晰人像 + 柔膚 + 柔和背光 + 清晰背光 + 悠閒色調 + 活潑小孩 + 清晰風景 + 明亮藍天 + 浪漫夕陽 + 鮮明餘暉 + 閃耀水面 + 清晰夜景 + 冷調夜空 + 暖色調夜景 + 藝術夜景 + 閃爍燈光 + 手提式夜拍 + 夜間人像 + 柔和花卉 + 美味佳餚 + 精緻甜點 + 生態攝影 + 運動攝影 + 單色調 + 照片樣式 + 標準 + 鮮明 + 自然 + 單色 + 風景 + 人像 + 自訂 + 濾鏡設定 + 無效果 + 寬高比 + 圖片尺寸 + 畫質 + 精細 + 標準 + RAW+精細 + RAW+標準 + 對焦模式 + 自動對焦 微距 + 近拍特寫 + 測光模式 + 多區測光 + 中央偏重 + 單點 + 閃光模式 + 自動 + 智慧型全自動 + 自動/紅眼降低 + 強制閃光開 + 強制閃光開/紅眼降低 + 慢速同步 + 慢速同步/紅眼降低 + 強制閃光關 + 拍攝格式 + 影片錄影畫質 + 停格動畫 + 4K 即時剪裁 + 40 秒 + 20 秒 + OFF + 包圍 + 包圍方式 + 曝光 + OFF + 調整幅度 + 順序 + 單一鏡頭設定 + 逐一 + 一拍 + 觸碰快門 + 觸控 AE + 光圈/快門速度 + 光圈 + 快門速度 + 程式切換 + 曝光補償 + 調整幅度 + OFF + AF 模式 + 人臉/眼睛偵測 + 追蹤 + 49點 + 自訂多點對焦 + 垂直模式 + 水平模式 + 中央模式 + 使用者設定1 + 使用者設定2 + 使用者設定3 + 1點 + 定位焦點 + 感光度 + i.AUTO + 白平衡 + 自動白平衡 + 晴天 + 陰天 + 陰影 + 日光燈 + 閃光 + 白色設定 1 + 白色設定 2 + 白色設定 3 + 白色設定 4 + 色溫 + 驅動模式 + 單張 + 連拍 + 4K照片 + 4K 連拍 + 4K 連拍(S/S) + 4K 快門前連拍 + 拍攝後對焦 + 自拍計時器 + 10秒鐘 + 10秒/3張 + 2秒鐘 + 驅動模式關閉 + 峰值 + OFF + + + + + 连接目的地设置 + 实时控制设置 + 自拍模式 + 实时控制画质 + 镜头伸出警告 + 跳跃快照 + 回放设置 + 应用程序功能 + 网络名称 + 场景指南 + 样本显示 + 帮助 + 使用条款 + 创意控制 + 富有表现力 + 乡愁怀旧 + 旧时光滤镜 + 高基调 + 暗色调 + 深棕色 + 单色 + 动态单色 + 颗粒单色 + 柔滑单色 + 印象艺术 + 高动态 + 正片负冲 + 玩具相机效果 + 鲜艳玩具相机滤镜 + 漂白效果滤镜 + 微型画效果 + 柔焦 + 幻觉滤镜 + 星光滤镜 + 单点色彩 + 阳光滤镜 + 场景指南 + 清晰肖像 + 柔肤 + 背光柔和 + 背光清晰 + 轻松氛围 + 可爱孩子的脸部 + 独特风景 + 蔚蓝天空 + 浪漫晚霞 + 生动晚霞 + 闪光水面 + 清晰夜景 + 酷炫夜空 + 温暖夜景 + 艺术夜景 + 闪亮灯饰 + 手持夜景拍摄 + 清晰夜间肖像 + 花卉柔焦 + 美味食物 + 可爱甜品 + 移动宠物拍摄 + 清晰运动拍摄 + 单色 + 照片格调 + 标准 + 生动 + 自然 + 单色 + 风景 + 肖像 + 自定义 + 滤镜设置 + 无效果 + 高宽比 + 图像尺寸 + 质量 + 精细 + 标准 + RAW+精细 + RAW+标准 + 聚焦模式 + 自动对焦微距模式 + 微距变焦 + 测光模式 + 多点测光 + 中央重点测光 + 定点 + 闪光模式 + 自动 + 智能自动 + 自动/红眼降低 + 强制闪光开 + 强制闪光开/红眼降低 + 慢速同步 + 慢速同步/红眼降低 + 强制闪光关 + 录像格式 + 影像录制质量 + 定格动画 + 4K 实时裁剪 + 40 秒 + 20 秒 + OFF + 括弧式 + 括弧式类型 + 曝光 + OFF + 调整幅度 + 顺序 + 单拍设置 + 逐一 + 一次轻触 + 触摸快门 + 触摸AE + 光圈/快门速度 + 光圈 + 快门速度 + 程序切换 + 曝光补偿 + 调整幅度 + OFF + AF 模式 + 人脸/眼睛探测 + 追踪 + 49点 + 多种自定义设置 + 垂直样式 + 水平样式 + 中央样式 + 自定义1 + 自定义2 + 自定义3 + 1点 + 精确定点 + 感光度 + i.AUTO + 白平衡 + 自动白平衡 + 晴天 + 阴天 + 阴影 + 白炽灯 + 闪光 + 白色设置 1 + 白色设置 2 + 白色设置 3 + 白色设置 4 + 色温 + 驱动模式 + 单张 + 连拍 + 4K照片 + 4K 连拍 + 4K 连拍(S/S) + 4K 快门前连拍 + 后对焦 + 自拍定时器 + 10秒钟 + 10秒/3张 + 2秒钟 + 驱动模式关闭 + 峰值 + OFF + + + + + Verbind.best. inst. + Inst. livebesturing + Zelfopnamemodus + Beeldkwal. livebest. + Waarsch. lens uitg. + Springsnapshot + Afspeelinstellingen + Toepassingsfunctie + Netwerknaam + Voorbeeldscherm + Gebruiksvoorwaarden + Creatieve opties + Expressief + Vroeger + Overbelichting + Donker + Zwart-wit + Dynamisch zwart/wit + Ruw zwart-wit + Zacht zwart-wit + Expressieve indruk + Hoge dynamiek + Kruisproces + Speelgoedcam.effect + Speelgoedcamera levendig + Bleach bypass + Miniatuureffect + Zachte focus + Fantasie + Sterfilter + Kleuraccent + Zonneschijn + Geprononceerd portret + Zachte huid + Zacht tegenlicht + Scherp tegenlicht + Ontspannen atmosfeer + Kindergezicht + Landschap + Blauwe lucht + Romantische zonsondergang + Levendige zonsondergang + Glinsterend water + Heldere nachtopname + Koele nachtopname + Warme nachtopname + Artistieke nachtopname + Fonkelende verlichting + Nachtop. uit hand + Nachtportret + Bloemen + Gerechten + Desserts + Bewegende dieren + Sport + Monochroom + Fotostijl + Standaard + Levendig + Natuurlijk + Zwart-wit + Landschap + Portret + Voorkeuze + Filterinstellingen + Geen effect + Aspectratio + Fotoresolutie + Kwaliteit + Fijn + Standaard + RAW+fijn + RAW+standaard + Focusfunctie + Macro-AF + Macro zoom + Meetfunctie + Multimeting + Centrale meting + Punt + Flitserfunctie + Intelligent auto + Auto/rode-og + Flitser altijd aan + Gdw. aan/rode-og + Langz. sync. + Lngz. sync./rode-og + Gedwongen uit + Opname-indeling + Video Opn. kwaliteit + Stop-motionanimatie + 4K Live Bijsnijden + Type Bracket + Belichting + Stap + Serie + Single Shot Instelling + AFZONDERLK + ÉÉN TIK + Touch sluiter + Diafragma/Sluitertijd + Diafragma + Sluitertijd + Progr. wisseling + Belichtingscomp. + Stap + AF mode + Gezicht/ogen detecteren + 49-zone + Voorkeur multi + Verticaal patroon + Horizontaal patroon + Cent. patroon + Klant1 + Klant2 + Klant3 + 1-zone + Spot + Gevoeligheid + Witbalans + Auto witbalans + Daglicht + Bewolkt + Schaduw + Halogeen + Flitser + Witinst. 1 + Witinst. 2 + Witinst. 3 + Witinst. 4 + Kleurtemperatuur + Aandrijfstand + Enkel + Burst shooting + 4K-FOTO + 4K-burst + 4K-burst (S/S) + 4K-voorburst + Zelf ontsp. + 10 sec. + 10 s/3beelden + 2 sec. + Aandrijfstand uit + Laag + Hoog + + + Conf. dest. conexão + Conf. Contr. ao Vivo + Modo autoretrato + Qual. Contr. ao Vivo + Aviso extensão lente + Foto de salto + Config. reprodução + Função do aplicativo + Nome da rede + Guia de Cena + Exemplo de exibição + Ajuda + Termos de uso + Controle criativo + Vivas + Velhos tempos + Alto contraste + Tom escuro + Sépia + Monocromático + Monocromático Dinâmico + Monocromático áspero + Monocromático suave + Arte Impressiva + Dinâmica elev. + Processo Cruzado + Efeito brinquedo + Pop brinquedo + Eliminar branqueamento + Efeito miniat. + Focagem Suave + Fantasia + Filtro Estrela + Cor em Um Ponto + Brilho do sol + Guia de Cena + Retrato Nítido + Pele Sedosa + Suavidade Retro-iluminada + Claro c/ Retroiluminação + Tom Relaxante + Rosto de Criança Amável + Cenário Distinto + Céu Azul Brilhante + Iluminação Romântica Pôr-do-Sol + Iluminação Vívida do Pôr-do-Sol + Água com Reflexo + Cena Noturna Nítida + Céu Noturno Agradável + Cena Noturna Quente Iluminada + Cena Noturna Artística + Iluminações Brilhantes + Foto noturna man. + Retrato Noturno Nítido + Imagem Suave de uma Flor + Comida Apetitosa + Sobremesa Atraente + Congelar o Movimento do Animal + Fotografia Nítida Desportiva + Monocromática + Estilo foto + Padrão + Vívido + Monocromático + Cenário + Retrato + Personaliz. + Definições de filtro + Sem efeito + Formato + Tamanho foto + Qualidade + Alto + Padrão + RAW+Alto + RAW+padrão + Modo focagem + AF macro + Zoom macro + Medição + Multi medição + Centralizado + Modo flash + Automático + Aut/olh. verm + Flash forçado + Lig for/olh verm + Sinc lenta + Sinc lent/olh verm + Flash desligado + Formato de gravação + Vídeo Quald. grav. + Animaç. Stop Motion + Recorte ao vivo em 4K + 40 seg. + 20 seg. + OFF + Variável Sequencial + Tipo variable sequence + Exposição + OFF + Passo + Sequência + Defin. disparo único + UM A UM + UM TOQUE + Toque obtur. + AE de toque + Abertura/Vel. obtur. + Abertura + Vel. obtur. + Mudança de programa + Compens. exposição + Passo + OFF + Modo AF + Detectar face/olho + Busca + 49 áreas + Multi Utilizador + Padrão vertical + Padrão horizontal + Padrão central + Personalizado1 + Personalizado2 + Personalizado3 + 1 área + Foco pontual + Sensibilidade + Bal. brancos + Balanço auto brancos + Luz do dia + Nublado + Sombra + Incandescente + Bal. brancos 1 + Bal. brancos 2 + Bal. brancos 3 + Bal. brancos 4 + Temperatura de cor + Modo drive + Única + Cap. contínua + FOTO 4K + Disp. contínuo 4K + Disp. contínuo 4K(S/S) + Pré-Disp. contínuo 4K + Pós-focagem + Temporizador + 10 segundos + 10 seg/3 fotos + 2 segundos + Modo drive off + Realçar contorno + OFF + Baixa + Alta + + + Настройка назн.соед. + Настр.жив.контроля + Режим автосъемки + Кач.из.жив.контроля + Предуп.о выдв.объек. + Снимок прыжка + Настр.воспроизвед. + Функция приложения + Имя сети + Руковод. по созданию сцен + Показ примера + Справка + Соглашен.об использ. + Творческий контроль + Выразительн. + Ретро + Старые времена + Высокотональный + Недоэкспонирование + Сепия + Монохромный + Динамический монохром + Грубый монохромный + Мягкий монохромный + Выраз. искусство + Высокодинамичный + Кросс-процесс + Эффект мыльницы + Ярк.изобр.с эфф.мыльн. + Пропуск отбеливания + Эффект миниатюры + Нерезкое изображение + Фэнтези + Звездный фильтр + Цветовой акцент + Солнечное сияние + Руковод. по созданию сцен + Четкий портрет + Шелковистая кожа + Мягкость подсветки + Четкость на фоне подсветки + Непринужденность + Милое детское лицо + Отчетливый пейзаж + Яркое голубое небо + Романтич. отсветы заката + Яркие отсветы заката + Сверкающая вода + Четкий ночной пейзаж + Прохладное ночное небо + Ярк. и тепл. ночной пейзаж + Худож. ночной пейзаж + Сверкающее освещение + Портат.ноч.снимок + Четкий ночной портрет + Нежное изображение цветка + Аппетитная еда + Соблазнительный десерт + Застывшее в движ. животное + Четкие спортивные снимки + Монохромный + Фото стиль + Стандарт + Яркий + Естественный + Монохром + Пейзаж + Портрет + Ручн.настр. + Настройка фильтров + Нет эффекта + Формат + Разм. кадра + Качество + Выс/качество + Стандарт + RAW+выс/кач. + RAW+стандарт. + Режим фокус. + + АФ макро + Макро зум + Режим замера + Многозон. замер + Центр.взвеш. эксп. + Точечный + Режим вспышки + Авто + Iавто + Авто/кр. гл. + Прин. всп. вкл + Прин вкл/кр гл + Медл. синхронизация + Зам синх/кр гл + Прин. всп выкл + Формат записи + Видео Кач-во зап. + Покадр. анимация + Живое кадриров. 4K + 40 сек. + 20 сек. + Брекетинг + Тип брекетинга + Экспозиция + Шаг + Последов + Настр. для 1 кадра + ПООЧЕРЕД. + 1 КАСАНИЕ + Затвор кас. + АЭ касанием + Диафрагма/Скор. затвора + Диафрагма + Скор. затвора + Смена прогр. + Компенсация экспоз. + Шаг + Режим АФ + Распознавание лиц/глаз + Следящий + 49-зонный + Пользов. мульти + Вертикальный шаблон + Горизонтальный шаблон + Централ. шаблон + Пользов.1 + Пользов.2 + Пользов.3 + 1-зонный + Очень точно + Светочувст. + Бал. бел. + Автом. баланс белого + Дневной свет + Облачно + Тень + Накаливание + Вспышка + Уст. бал. бел. 1 + Уст. бал. бел. 2 + Уст. бал. бел. 3 + Уст. бал. бел. 4 + Цветовая темпер. + Режим съемки + Один сн. + Серийная съемка + 4K ФОТО + Сер.съемка 4K + Сер.съемк 4K (S/S) + Предв. сер.съемка 4K + Пост-фокус + Авт. таймер + 10 сек + 10 сек / 3 изобр. + 2 сек + Режим накопителя выкл + Усиление контуров + Низк. + Высок. + + + 연결 대상 설정 + 라이브 컨트롤 설정 + 셀프 촬영 모드 + 라이브 컨트롤 품질 + 렌즈 돌출 경고 + 점프 스냅 + 재생 설정 + 응용 프로그램 기능 + 네트워크 이름 + 장면 가이드 + 샘플 표시 + 도움말 + 이용 약관 + 크리에이티브 콘트롤 + 생동감 + 복고 + 올드 데이즈 + 하이키 + 로우 키 + 세피아 + 흑백 + 다이내믹 흑백 효과 + 거친 흑백 + 실크 흑백 + 인상적인 아트 + 하이 다이내믹 + 크로스 프로세스 + 장난감 효과 + 토이 팝 + 표백 바이패스 + 미니어처 효과 + 소프트 포커스 + 판타지 + 스타 필터 + 원 포인트 컬러 + 선샤인 + 장면 가이드 + 선명한 인물 사진 + 피부 보정 + 부드러운 역광 + 선명한 역광 + 따뜻한 색조 + 사랑스런 아이 얼굴 + 특색있는 풍경 + 밝은 푸른빛 하늘 + 낭만적인 저녁노을 + 선명한 저녁노을 + 반짝이는 물 + 선명한 야경 + 근사한 밤 하늘 + 따뜻한 느낌의 야경 + 예술적인 야경 + 반짝이는 조명 + 핸드헬드 야경 + 선명한 야경 인물 + 부드러운 꽃 이미지 + 먹음직스러운 음식 + 예쁜 디저트 + 움직이는 동물 촬영 + 선명한 스포츠 샷 + 흑백 사진 + 사진 스타일 + 표준 + 선명 + 내추럴 + 모노크롬 + 풍경 + 인물 + 사용자 모드 + 필터 설정 + 효과 없음 + 화면비율 + 기록화소수 + 화질 + 고화질 + 표준 + RAW+고화질 + RAW+표준 + 초점 모드 + AF 매크로 + 매크로 줌 + 측광모드 + 다중 측광 + 중앙중점측광 + 스포트 + 플래시 모드 + 자동 + i오토 + 자동/적목감소 + 강제발광 + 강제발광/적목 + 슬로우싱크로 + 슬로우 싱크/적목 + 발광금지 + 촬영포맷 + 동영상 화질 + 스톱 모션 애니메이션 + 4K 라이브 크롭핑 + 40초 + 20초 + OFF + 브래킷 + 브래킷 유형 + 노출 + OFF + 조절 단계 + 순서 + 단사 촬영 설정 + 하나씩 + 한 번의 탭 + 터치 셔터 + 터치 AE + 구경 값/셔터 속도 + 구경 값 + 셔터 속도 + 프로그램 시프트 + 노출보정 + 조절 단계 + OFF + AF 모드 + 얼굴/눈인식 + 트래킹 + 49영역 + 사용자 멀티 + 세로 패턴 + 가로 패턴 + 중앙 패턴 + 사용자1 + 사용자2 + 사용자3 + 1영역 + 핀포인트 + ISO감도 + i.AUTO + 화이트 밸런스 + 오토화이트밸런스 + 맑음 + 흐림 + 그늘 + 백열등 + 플래시 + 화이트 설정 1 + 화이트 설정 2 + 화이트 설정 3 + 화이트 설정 4 + 색온도 + 드라이브 모드 + 1매 + 연사 + 4K 포토 + 4K 연사 + 4K 연사(S/S) + 4K 사전 연사 + 포스트 포커스 + 셀프타이머 + 10초 + 10초/3매 + 2초 + 드라이브 모드 꺼짐 + 피킹 + OFF + + + + + + + + +http://192.168.54.1/cam.cgi?mode=getinfo&type=curmenu + + + + ok + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.1 From 231d97ef0717975ced1d46467e4d43816046efed Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Thu, 27 Jun 2019 17:31:50 +0200 Subject: get full directory using incremental read also handle movie and raw files. (download still fails for them for some reason) --- camlibs/lumix/lumix.c | 479 +++++++++++++++++++++++++++++--------------------- 1 file changed, 280 insertions(+), 199 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index e58c6c152..aed4d71b7 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -102,6 +102,8 @@ typedef struct { typedef struct { char *id; + char *url_raw; + char *url_movie; char *url_large; char *url_medium; char *url_thumb; @@ -128,8 +130,6 @@ camera_exit (Camera *camera, GPContext *context) return GP_OK; } -int camera_config_get (Camera *camera, CameraWidget **window, GPContext *context); - static int camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) { @@ -331,9 +331,20 @@ file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, int i; for (i=0;ipl->numpics;i++) { + if (camera->pl->pics[i].url_raw) { + char *s = strrchr(camera->pl->pics[i].url_raw, '/')+1; + gp_list_append (list, s, NULL); + continue; + } if (camera->pl->pics[i].url_large) { char *s = strrchr(camera->pl->pics[i].url_large, '/')+1; gp_list_append (list, s, NULL); + continue; + } + if (camera->pl->pics[i].url_movie) { + char *s = strrchr(camera->pl->pics[i].url_movie, '/')+1; + gp_list_append (list, s, NULL); + continue; } } return GP_OK; @@ -668,12 +679,14 @@ traverse_tree (int depth, xmlNodePtr node) /* * retrieves the XML doc with the last num pictures avail in the camera. */ + static char* -GetPix(Camera *camera,int num) { +GetPixRange(Camera *camera, int start, int num) { long NumPix; + int numreadint; xmlDocPtr docin, docin2; - xmlNodePtr docroot, docroot2, output, next; - xmlChar *xchar; + xmlNodePtr docroot, docroot2, output, output2, next; + xmlChar *xchar, *numread; char* SoapMsg; CURL *curl; CURLcode res; @@ -694,202 +707,250 @@ GetPix(Camera *camera,int num) { camera->pl->numpics = NumPix; } - SoapMsg = SoapEnvelop((NumPix - num)> 0?(NumPix - num):0, num); - //GP_LOG_D("SoapMsg is %s \n", SoapMsg); + while (num > 0) { + SoapMsg = SoapEnvelop(start, num); + //GP_LOG_D("SoapMsg is %s \n", SoapMsg); - curl = curl_easy_init(); + curl = curl_easy_init(); - list = curl_slist_append(list, "SOAPaction: urn:schemas-upnp-org:service:ContentDirectory:1#Browse"); - list = curl_slist_append(list, "Content-Type: text/xml; charset=\"utf-8\""); - list = curl_slist_append(list, "Accept: text/xml"); + list = curl_slist_append(list, "SOAPaction: urn:schemas-upnp-org:service:ContentDirectory:1#Browse"); + list = curl_slist_append(list, "Content-Type: text/xml; charset=\"utf-8\""); + list = curl_slist_append(list, "Accept: text/xml"); - gp_port_get_info (camera->port, &info); - gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ - snprintf( URL, 1000, "http://%s%s",xpath+4, CDS_Control); - curl_easy_setopt(curl, CURLOPT_URL, URL); + gp_port_get_info (camera->port, &info); + gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ + snprintf( URL, 1000, "http://%s%s",xpath+4, CDS_Control); + curl_easy_setopt(curl, CURLOPT_URL, URL); - lmb.size = 0; - lmb.data = malloc(0); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &lmb); + lmb.size = 0; + lmb.data = malloc(0); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &lmb); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); - curl_easy_setopt(curl, CURLOPT_POST,1); - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) strlen(SoapMsg)); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); + curl_easy_setopt(curl, CURLOPT_POST,1); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) strlen(SoapMsg)); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, SoapMsg); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, SoapMsg); - GP_LOG_D("camera url is %s", URL); - GP_LOG_D("posting %s", SoapMsg); + GP_LOG_D("camera url is %s", URL); + GP_LOG_D("posting %s", SoapMsg); - res = curl_easy_perform(curl); - if(res != CURLE_OK) { - fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + res = curl_easy_perform(curl); + if(res != CURLE_OK) { + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + curl_easy_cleanup(curl); + return NULL; + } curl_easy_cleanup(curl); - return NULL; - } - curl_easy_cleanup(curl); - docin = xmlReadMemory (lmb.data, lmb.size, "http://gphoto.org/", "utf-8", 0); - if (!docin) return NULL; - docroot = xmlDocGetRootElement (docin); - if (!docroot) { - xmlFreeDoc (docin); - return NULL; - } - if (strcmp((char*)docroot->name,"Envelope")) { - GP_LOG_E("root node is '%s', expected 'Envelope'", docroot->name); - xmlFreeDoc (docin); - return NULL; - } - output = xmlFirstElementChild (docroot); - if (strcmp((char*)output->name,"Body")) { - GP_LOG_E("second level node is %s, expected Body", docroot->name); - xmlFreeDoc (docin); - return NULL; - } - output = xmlFirstElementChild (output); - if (strcmp((char*)output->name,"BrowseResponse")) { - GP_LOG_E("third level node is %s, expected BrowseResponse", docroot->name); - xmlFreeDoc (docin); - return NULL; - } - output = xmlFirstElementChild (output); - if (strcmp((char*)output->name,"Result")) { - GP_LOG_E("fourth level node is %s, expected Result", docroot->name); - xmlFreeDoc (docin); - return NULL; - } - xchar = xmlNodeGetContent (output); - GP_LOG_D("content of %s is %s", output->name, xchar); -/* - - - - 103-0822 - WRITABLE - object.item.imageItem - - http://192.168.54.1:50001/DO1030822.JPG - - - http://192.168.54.1:50001/DT1030822.JPG - - - http://192.168.54.1:50001/DL1030822.JPG - - - - -*/ - docin2 = xmlReadMemory ((char*)xchar, strlen((char*)xchar), "http://gphoto.org/", "utf-8", 0); - if (!docin2) return NULL; - docroot2 = xmlDocGetRootElement (docin2); - if (!docroot) { - xmlFreeDoc (docin2); - return NULL; - } - if (strcmp((char*)docroot2->name,"DIDL-Lite")) { - GP_LOG_E("expected DIDL-Lite, got %s", docroot->name); - xmlFreeDoc (docin2); - return NULL; - } - output = xmlFirstElementChild (docroot2); - if (strcmp((char*)output->name,"item")) { - GP_LOG_E("expected item, got %s", output->name); - xmlFreeDoc (docin2); - return NULL; - } -/* - - 103-0822 - WRITABLE - object.item.imageItem - - http://192.168.54.1:50001/DO1030822.JPG - - - http://192.168.54.1:50001/DT1030822.JPG - - - http://192.168.54.1:50001/DL1030822.JPG - - -*/ - next = output; - do { - char *id = NULL; - int i; - xmlNode *child; - xmlAttr *attr = next->properties; - - GP_LOG_D("got %s", next->name); - - while (attr) { - GP_LOG_D("\t attribute %s", attr->name); - GP_LOG_D("\t attribute content %s", xmlNodeGetContent(attr->children)); - - if (!strcmp((char*)attr->name, "id")) { - id = (char*)xmlNodeGetContent(attr->children); - break; - } - attr = attr->next; + docin = xmlReadMemory (lmb.data, lmb.size, "http://gphoto.org/", "utf-8", 0); + if (!docin) return NULL; + docroot = xmlDocGetRootElement (docin); + if (!docroot) { + xmlFreeDoc (docin); + return NULL; } - /* look if we have the id */ - for (i=0;ipl->numpics;i++) - if (camera->pl->pics[i].id && !strcmp(camera->pl->pics[i].id, id)) - break; - if (ipl->numpics) { - GP_LOG_D("already read id %s, is element %d\n", id, i); - continue; + if (strcmp((char*)docroot->name,"Envelope")) { + GP_LOG_E("root node is '%s', expected 'Envelope'", docroot->name); + xmlFreeDoc (docin); + return NULL; } - for (i=0;ipl->numpics;i++) - if (!camera->pl->pics[i].id) - break; - if (i==camera->pl->numpics) { - GP_LOG_D("no free slot found for id %s\n", id); - continue; + output = xmlFirstElementChild (docroot); + if (strcmp((char*)output->name,"Body")) { + GP_LOG_E("second level node is %s, expected Body", docroot->name); + xmlFreeDoc (docin); + return NULL; + } + output = xmlFirstElementChild (output); + if (strcmp((char*)output->name,"BrowseResponse")) { + GP_LOG_E("third level node is %s, expected BrowseResponse", docroot->name); + xmlFreeDoc (docin); + return NULL; + } + output = xmlFirstElementChild (output); + if (strcmp((char*)output->name,"Result")) { + GP_LOG_E("fourth level node is %s, expected Result", docroot->name); + xmlFreeDoc (docin); + return NULL; } - camera->pl->pics[i].id = strdup(id); - child = next->children; + xchar = xmlNodeGetContent (output); + GP_LOG_D("content of %s is %s", output->name, xchar); + /* + + + + 103-0822 + WRITABLE + object.item.imageItem + + http://192.168.54.1:50001/DO1030822.JPG + + + http://192.168.54.1:50001/DT1030822.JPG + + + http://192.168.54.1:50001/DL1030822.JPG + + + - /* - - http://192.168.54.1:50001/DL1030822.JPG - */ - while (child) { - xmlAttr *attr; - xmlChar *attrcontent; + docin2 = xmlReadMemory ((char*)xchar, strlen((char*)xchar), "http://gphoto.org/", "utf-8", 0); + if (!docin2) return NULL; + docroot2 = xmlDocGetRootElement (docin2); + if (!docroot) { + xmlFreeDoc (docin2); + return NULL; + } + if (strcmp((char*)docroot2->name,"DIDL-Lite")) { + GP_LOG_E("expected DIDL-Lite, got %s", docroot2->name); + xmlFreeDoc (docin2); + return NULL; + } + output2 = xmlFirstElementChild (docroot2); + if (strcmp((char*)output2->name,"item")) { + GP_LOG_E("expected item, got %s", output2->name); + xmlFreeDoc (docin2); + return NULL; + } + /* + + 103-0822 + WRITABLE + object.item.imageItem + + http://192.168.54.1:50001/DO1030822.JPG + + + http://192.168.54.1:50001/DT1030822.JPG + + + http://192.168.54.1:50001/DL1030822.JPG + + + +we have: +Picture: + http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=00900000000000000000000000000000;PANASONIC.COM_PN=CAM_ORG + http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00900000000000000000000000000000;PANASONIC.COM_PN=CAM_TN + http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00900000000000000000000000000000;PANASONIC.COM_PN=CAM_LRGTN + +Movie: + http-get:*:application/octet-stream:DLNA.ORG_OP=01;PANASONIC.COM_PN=CAM_AVC_MP4_HP_2160_30P_AAC + http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00900000000000000000000000000000;PANASONIC.COM_PN=CAM_TN + content is http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00900000000000000000000000000000;PANASONIC.COM_PN=CAM_LRGTN + +Raw: + http-get:*:application/octet-stream;PANASONIC.COM_PN=CAM_RAW_JPG + http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00900000000000000000000000000000;PANASONIC.COM_PN=CAM_TN + http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=00900000000000000000000000000000;PANASONIC.COM_PN=CAM_LRGTN + http-get:*:application/octet-stream;PANASONIC.COM_PN=CAM_RAW - if (strcmp((char*)child->name,"res")) { - GP_LOG_D("skipping %s", child->name); - child = child->next; + */ + next = output2; + do { + char *id = NULL; + int i; + xmlNode *child; + xmlAttr *attr = next->properties; + + GP_LOG_D("got %s", next->name); + + while (attr) { + GP_LOG_D("\t attribute %s", attr->name); + GP_LOG_D("\t attribute content %s", xmlNodeGetContent(attr->children)); + + if (!strcmp((char*)attr->name, "id")) { + id = (char*)xmlNodeGetContent(attr->children); + break; + } + attr = attr->next; + } + /* look if we have the id */ + for (i=0;ipl->numpics;i++) + if (camera->pl->pics[i].id && !strcmp(camera->pl->pics[i].id, id)) + break; + if (ipl->numpics) { + GP_LOG_D("already read id %s, is element %d\n", id, i); continue; } - attr = child->properties; - - if (strcmp((char*)attr->name,"protocolInfo")) { - GP_LOG_D("expected attribute protocolInfo, got %s", attr->name); + for (i=0;ipl->numpics;i++) + if (!camera->pl->pics[i].id) + break; + if (i==camera->pl->numpics) { + GP_LOG_D("no free slot found for id %s\n", id); + continue; + } + camera->pl->pics[i].id = strdup(id); + child = next->children; + + /* + + http://192.168.54.1:50001/DL1030822.JPG + + */ + while (child) { + xmlAttr *attr; + xmlChar *attrcontent; + + if (strcmp((char*)child->name,"res")) { + GP_LOG_D("skipping %s", child->name); + child = child->next; + continue; + } + attr = child->properties; + + if (strcmp((char*)attr->name,"protocolInfo")) { + GP_LOG_D("expected attribute protocolInfo, got %s", attr->name); + } + attrcontent = xmlNodeGetContent(attr->children); + GP_LOG_D("\t\tattribute content is %s", attrcontent); + + GP_LOG_D("\t child content %s", xmlNodeGetContent(child)); + + /* FIXME: perhaps shorten match? */ + if (strstr((char*)attrcontent,"PANASONIC.COM_PN=CAM_AVC_MP4_HP_2160_30P_AAC")) { + camera->pl->pics[i].url_movie = strdup((char*)xmlNodeGetContent(child)); + } + // http-get:*:application/octet-stream;PANASONIC.COM_PN=CAM_RAW + // but not + // http-get:*:application/octet-stream;PANASONIC.COM_PN=CAM_RAW_JPG + if (strstr((char*)attrcontent,"PANASONIC.COM_PN=CAM_RAW") && + !strstr((char*)attrcontent,"PANASONIC.COM_PN=CAM_RAW_JPG") + ) { + camera->pl->pics[i].url_raw = strdup((char*)xmlNodeGetContent(child)); + } + if (strstr((char*)attrcontent,"PANASONIC.COM_PN=CAM_ORG")) { + camera->pl->pics[i].url_large = strdup((char*)xmlNodeGetContent(child)); + } + if (strstr((char*)attrcontent,"PANASONIC.COM_PN=CAM_LRGTN")) { + camera->pl->pics[i].url_medium = strdup((char*)xmlNodeGetContent(child)); + } + if (strstr((char*)attrcontent,"PANASONIC.COM_PN=CAM_TN")) { + camera->pl->pics[i].url_thumb = strdup((char*)xmlNodeGetContent(child)); + } + child = child->next; } - attrcontent = xmlNodeGetContent(attr->children); - GP_LOG_D("\t\tattribute content is %s", attrcontent); + } while ((next = xmlNextElementSibling (next))); - GP_LOG_D("\t child content %s", xmlNodeGetContent(child)); - if (strstr((char*)attrcontent,"DLNA.ORG_PN=JPEG_LRG")) { - camera->pl->pics[i].url_large = strdup((char*)xmlNodeGetContent(child)); - } - if (strstr((char*)attrcontent,"DLNA.ORG_PN=JPEG_TN")) { - camera->pl->pics[i].url_medium = strdup((char*)xmlNodeGetContent(child)); - } - if (strstr((char*)attrcontent,"DLNA.ORG_PN=JPEG_MED")) { - camera->pl->pics[i].url_thumb = strdup((char*)xmlNodeGetContent(child)); - } - child = child->next; + output = xmlNextElementSibling (output); + if (strcmp((char*)output->name,"NumberReturned")) { + GP_LOG_E("fourth level node is %s, expected NumberReturned", output->name); + xmlFreeDoc (docin); + return NULL; } - } while ((next = xmlNextElementSibling (next))); + numread = xmlNodeGetContent (output); + GP_LOG_D("content of %s is %s", output->name, numread); + + numreadint = 1; + sscanf((char*)numread,"%d", &numreadint); + + start += numreadint; + num -= numreadint; + } return strdup((char*)xchar); } @@ -900,8 +961,7 @@ GetPix(Camera *camera,int num) { * TO DO - - i started to include some items to set the quality (raw and raw+jpg) as well as dictionary for ISO and shutter speed * mostly every thing is still to do */ -int camera_config_get (Camera *camera, CameraWidget **window, GPContext *context); -int +static int camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) { CameraWidget *widget,*section; @@ -972,13 +1032,13 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_value (widget, Get_Lens(camera)); gp_widget_append (section, widget); +#if 0 gp_widget_new (GP_WIDGET_TEXT, _("Capability"), &widget); gp_widget_set_name (widget, "capability"); gp_widget_set_value (widget, Get_Capability(camera)); gp_widget_append (section, widget); -#if 0 - /* lots of stuff */ + /* lots of stuff ... lets see if we can use it */ gp_widget_new (GP_WIDGET_TEXT, _("All Menu"), &widget); gp_widget_set_name (widget, "allmenu"); gp_widget_set_value (widget, Get_AllMenu(camera)); @@ -1147,16 +1207,14 @@ ReadImageFromCamera(Camera *camera, CameraFilePath *path, GPContext *context) { char *image; long nRead; LumixMemoryBuffer lmb; + char *xmlimageName; + xmlDocPtr doc; /* the resulting document tree */ + int ret; + char * imageURL=""; + xmlTextReaderPtr reader; loadCmd(camera,PLAYMODE); // 'making sure the camera is in Playmode - char* xmlimageName; - xmlDocPtr doc; /* the resulting document tree */ - int ret; - LIBXML_TEST_VERSION - - char* imageURL=""; - xmlTextReaderPtr reader; - reader = xmlReaderForDoc((xmlChar*)GetPix(camera,1), NULL,"noname.xml", XML_PARSE_DTDATTR | /* default DTD attributes */ XML_PARSE_NOENT); + reader = xmlReaderForDoc((xmlChar*)GetPixRange(camera,NumberPix(camera)-1,1), NULL,"noname.xml", XML_PARSE_DTDATTR | /* default DTD attributes */ XML_PARSE_NOENT); ret = xmlTextReaderRead(reader); while (ret == 1) { imageURL = processNode(reader); @@ -1185,11 +1243,14 @@ ReadImageFromCamera(Camera *camera, CameraFilePath *path, GPContext *context) { //curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPIDLE, 120L); //curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPINTVL, 60L); +#if 0 + /* FIXME trick wont work anymore with new buffering code -Marcus */ if (nRead) { curl_easy_setopt(imageUrl, CURLOPT_RESUME_FROM, nRead); GetPix(camera,1);//'if the file not found happened then this trick is to get the camera in a readmode again and making sure it remembers the filename GP_DEBUG("continuing the read where it stopped %s position %ld", image, nRead); } +#endif lmb.size = 0; lmb.data = malloc(0); curl_easy_setopt(imageUrl, CURLOPT_WRITEFUNCTION, write_callback); @@ -1305,16 +1366,32 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, C for (i=0;ipl->numpics;i++) { char *s; - if (!camera->pl->pics[i].url_large) continue; - s = strrchr(camera->pl->pics[i].url_large,'/')+1; - - if (!strcmp(s,filename)) break; + if (camera->pl->pics[i].url_movie) { + s = strrchr(camera->pl->pics[i].url_movie,'/')+1; + if (!strcmp(s,filename)) { + url = camera->pl->pics[i].url_movie; + break; + } + } + if (camera->pl->pics[i].url_raw) { + s = strrchr(camera->pl->pics[i].url_raw,'/')+1; + if (!strcmp(s,filename)) { + url = camera->pl->pics[i].url_raw; + break; + } + } + if (camera->pl->pics[i].url_large) { + s = strrchr(camera->pl->pics[i].url_large,'/')+1; + if (!strcmp(s,filename)) { + url = camera->pl->pics[i].url_large; + break; + } + } } if (i == camera->pl->numpics) /* not found */ return GP_ERROR; - url = camera->pl->pics[i].url_large; switch (type) { case GP_FILE_TYPE_PREVIEW: if (camera->pl->pics[i].url_thumb) @@ -1338,11 +1415,14 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, C //curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPIDLE, 120L); //curl_easy_setopt(imageUrl, CURLOPT_TCP_KEEPINTVL, 60L); +#if 1 + /* FIXME trick wont work anymore with new buffering code -Marcus */ if (nRead) { curl_easy_setopt(imageUrl, CURLOPT_RESUME_FROM, nRead); GetPix(camera,1);//'if the file not found happened then this trick is to get the camera in a readmode again and making sure it remembers the filename GP_DEBUG("continuing the read where it stopped %s position %ld", url, nRead); } +#endif lmb.size = 0; lmb.data = malloc(0); curl_easy_setopt(imageUrl, CURLOPT_WRITEFUNCTION, write_callback); @@ -1364,7 +1444,6 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, C curl_easy_cleanup(imageUrl); return gp_file_set_data_and_size (file, lmb.data, lmb.size); - } @@ -1395,7 +1474,7 @@ CameraFilesystemFuncs fsfuncs = { .folder_list_func = folder_list_func, // .get_info_func = get_info_func, // .set_info_func = set_info_func, -.get_file_func = get_file_func, // maybe this works for liveview preview + .get_file_func = get_file_func, // .del_file_func = delete_file_func, // .put_file_func = put_file_func, // .delete_all_func = delete_all_func, @@ -1430,6 +1509,8 @@ camera_init (Camera *camera, GPContext *context) camera->functions->manual = camera_manual; camera->functions->about = camera_about; + LIBXML_TEST_VERSION + curl_global_init(CURL_GLOBAL_ALL); ret = gp_port_get_info (camera->port, &info); @@ -1450,7 +1531,7 @@ camera_init (Camera *camera, GPContext *context) loadCmd(camera,PLAYMODE); // 'making sure the camera is in Playmode numpix = NumberPix(camera); - GetPix(camera,numpix); + GetPixRange(camera,0,numpix); return GP_OK; } else -- cgit v1.2.1 From b6954a99be1308152904e614f3027c4484b5a3cc Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Thu, 27 Jun 2019 17:50:39 +0200 Subject: first try at setting config for zoom --- camlibs/lumix/lumix.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index aed4d71b7..275ea826d 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -130,14 +130,6 @@ camera_exit (Camera *camera, GPContext *context) return GP_OK; } -static int -camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) -{ - - return GP_OK; -} - - static int camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) { @@ -1032,6 +1024,15 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_value (widget, Get_Lens(camera)); gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_RADIO, _("Zoom"), &widget); + gp_widget_set_name (widget, "zoom"); + gp_widget_set_value (widget, "none"); + gp_widget_add_choice (widget, "wide-fast"); + gp_widget_add_choice (widget, "wide-normal"); + gp_widget_add_choice (widget, "tele-normal"); + gp_widget_add_choice (widget, "tele-fast"); + gp_widget_append (section, widget); + #if 0 gp_widget_new (GP_WIDGET_TEXT, _("Capability"), &widget); gp_widget_set_name (widget, "capability"); @@ -1053,6 +1054,26 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) return GP_OK; } +static int +camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) +{ + CameraWidget *widget; + char *val; + + if (gp_widget_get_child_by_label(window, "zoom", &widget) && + gp_widget_changed (widget) + ) { + char buf[30]; + gp_widget_get_value (widget, &val); + + sprintf(buf,"cam.cgi?mode=camcmd&value=%s", val); + loadCmd(camera,buf); + } + return GP_OK; +} + + + static char* processNode(xmlTextReaderPtr reader) { char* ret =""; @@ -1419,7 +1440,7 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, C /* FIXME trick wont work anymore with new buffering code -Marcus */ if (nRead) { curl_easy_setopt(imageUrl, CURLOPT_RESUME_FROM, nRead); - GetPix(camera,1);//'if the file not found happened then this trick is to get the camera in a readmode again and making sure it remembers the filename + GetPixRange(camera,NumberPix(camera)-1,1);//'if the file not found happened then this trick is to get the camera in a readmode again and making sure it remembers the filename GP_DEBUG("continuing the read where it stopped %s position %ld", url, nRead); } #endif -- cgit v1.2.1 From 80384dbf8b484fd61488d15b0b06562f8d4af0ac Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Fri, 28 Jun 2019 12:47:39 +0200 Subject: make zoom setting work --- camlibs/lumix/lumix.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 275ea826d..0575a4f09 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -1060,9 +1060,7 @@ camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) CameraWidget *widget; char *val; - if (gp_widget_get_child_by_label(window, "zoom", &widget) && - gp_widget_changed (widget) - ) { + if ((GP_OK == gp_widget_get_child_by_name(window, "zoom", &widget)) && gp_widget_changed (widget)) { char buf[30]; gp_widget_get_value (widget, &val); -- cgit v1.2.1 From 7df739271ec7c10453bfbbe865cd90b0400bdf01 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Fri, 28 Jun 2019 13:42:31 +0200 Subject: try to decode shutterspeed and aperture able to do zoom --- camlibs/lumix/lumix.c | 90 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 9 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 0575a4f09..582a37ee6 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -86,7 +86,6 @@ char* RECMODE = "cam.cgi?mode=camcmd&value=recmode"; char* PLAYMODE = "cam.cgi?mode=camcmd&value=playmode"; char* SHUTTERSTART = "cam.cgi?mode=camcmd&value=capture"; char* SHUTTERSTOP = "cam.cgi?mode=camcmd&value=capture_cancel"; -char* SETAPERTURE = "cam.cgi?mode=setsetting&type=focal&value="; char* CDS_Control = ":60606/Server0/CDS_control"; int ReadoutMode = 2; // this should be picked up from the settings.... 0-> JPG; 1->RAW; 2 -> Thumbnails char* cameraShutterSpeed = "B"; // //placeholder to store the value of the shutterspeed set in camera; "B" is for bulb. @@ -463,12 +462,50 @@ Get_ISO(Camera *camera) { static char* Get_ShutterSpeed(Camera *camera) { - return loadCmd(camera,"cam.cgi?mode=getsetting&type=shtrspeed"); + char *result, *s; + int nom, div; + char shutterspeed[20]; + + result = loadCmd(camera,"cam.cgi?mode=getsetting&type=shtrspeed"); + /* + * ok + */ + if (!strstr(result,"ok")) + return NULL; + + s = strstr(result, "", &nom, &div) != 2) + return NULL; + + if (0 == (nom*10/div)%10) + sprintf(shutterspeed,"%d", nom/div); + else + sprintf(shutterspeed,"%d/%d", nom, div); + return strdup(shutterspeed); } static char* Get_Aperture(Camera *camera) { - return loadCmd(camera,"cam.cgi?mode=getsetting&type=focal"); + int nom, div; + char aperture[20]; + char *result, *s; + + /* + * ok + */ + result = loadCmd(camera,"cam.cgi?mode=getsetting&type=focal"); + if (!strstr(result,"ok")) + return NULL; + s = strstr(result, "", &nom, &div) != 2) + return NULL; + if (0 == (nom*10/div)%10) + sprintf(aperture,"%d", nom/div); + else + sprintf(aperture,"%d.%d", nom/div, (nom*10/div)%10); + return strdup(aperture); } static char* @@ -517,7 +554,7 @@ Get_CurMenu(Camera *camera) { } -static void Set_Speed(Camera *camera,const char* SpeedValue) { +static void Set_ShutterSpeed(Camera *camera,const char* SpeedValue) { char buf[200]; sprintf(buf, "?mode=setsetting&type=shtrspeed&value=%s",SpeedValue); loadCmd(camera,buf); @@ -909,7 +946,7 @@ Raw: // http-get:*:application/octet-stream;PANASONIC.COM_PN=CAM_RAW // but not // http-get:*:application/octet-stream;PANASONIC.COM_PN=CAM_RAW_JPG - if (strstr((char*)attrcontent,"PANASONIC.COM_PN=CAM_RAW") && + if (strstr((char*)attrcontent,"PANASONIC.COM_PN=CAM_RAW") && !strstr((char*)attrcontent,"PANASONIC.COM_PN=CAM_RAW_JPG") ) { camera->pl->pics[i].url_raw = strdup((char*)xmlNodeGetContent(child)); @@ -958,6 +995,7 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) { CameraWidget *widget,*section; int ret; + char *val; loadCmd (camera, RECMODE); @@ -973,9 +1011,10 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_value (widget, Get_Clock(camera)); gp_widget_append (section, widget); + val = Get_ShutterSpeed(camera); gp_widget_new (GP_WIDGET_TEXT, _("Shutterspeed"), &widget); gp_widget_set_name (widget, "shutterspeed"); - gp_widget_set_value (widget, Get_ShutterSpeed(camera)); + gp_widget_set_value (widget, val?val:"unknown"); gp_widget_append (section, widget); gp_widget_new (GP_WIDGET_TEXT, _("Quality"), &widget); @@ -983,9 +1022,11 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_value (widget, Get_Quality(camera)); gp_widget_append (section, widget); + + val = Get_Aperture(camera); gp_widget_new (GP_WIDGET_TEXT, _("Aperture"), &widget); gp_widget_set_name (widget, "aperture"); - gp_widget_set_value (widget, Get_Aperture(camera)); + gp_widget_set_value (widget, val?val:"unknown"); gp_widget_append (section, widget); gp_widget_new (GP_WIDGET_TEXT, _("ISO"), &widget); @@ -1031,6 +1072,7 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_add_choice (widget, "wide-normal"); gp_widget_add_choice (widget, "tele-normal"); gp_widget_add_choice (widget, "tele-fast"); + gp_widget_add_choice (widget, "stop"); gp_widget_append (section, widget); #if 0 @@ -1058,15 +1100,45 @@ static int camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) { CameraWidget *widget; - char *val; + char *val; + int ret; if ((GP_OK == gp_widget_get_child_by_name(window, "zoom", &widget)) && gp_widget_changed (widget)) { char buf[30]; - gp_widget_get_value (widget, &val); + if (GP_OK != (ret = gp_widget_get_value (widget, &val))) + return ret; + + /* all valid values */ + if ( strcmp(val, "wide-fast") && + strcmp(val, "wide-normal") && + strcmp(val, "tele-normal") && + strcmp(val, "tele-fast") && + strcmp(val, "stop") + ) + return GP_ERROR_BAD_PARAMETERS; + + if (!strcmp(val, "stop")) + val = "zoomstop"; sprintf(buf,"cam.cgi?mode=camcmd&value=%s", val); loadCmd(camera,buf); } + + if ((GP_OK == gp_widget_get_child_by_name(window, "shutterspeed", &widget)) && gp_widget_changed (widget)) { + + if (GP_OK != (ret = gp_widget_get_value (widget, &val))) + return ret; + Set_ShutterSpeed(camera,val); + } + + if ((GP_OK == gp_widget_get_child_by_name(window, "aperture", &widget)) && gp_widget_changed (widget)) { + char buf[50]; + + if (GP_OK != (ret = gp_widget_get_value (widget, &val))) + return ret; + sprintf(buf,"cam.cgi?mode=setsetting&type=focal&value=%s", val); + loadCmd(camera,buf); + } return GP_OK; } -- cgit v1.2.1 From 2aae90ed79252ffc60699f1abbe982b7dc1b07cf Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Fri, 28 Jun 2019 15:24:40 +0200 Subject: work on capturing images ... coming close --- camlibs/lumix/lumix.c | 289 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 229 insertions(+), 60 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 582a37ee6..e8591715d 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -82,8 +82,6 @@ # define N_(String) (String) #endif -char* RECMODE = "cam.cgi?mode=camcmd&value=recmode"; -char* PLAYMODE = "cam.cgi?mode=camcmd&value=playmode"; char* SHUTTERSTART = "cam.cgi?mode=camcmd&value=capture"; char* SHUTTERSTOP = "cam.cgi?mode=camcmd&value=capture_cancel"; char* CDS_Control = ":60606/Server0/CDS_control"; @@ -93,6 +91,8 @@ int captureDuration = 10; //placeholder to store the value of the bulb shot this static int NumberPix(Camera *camera); static char* loadCmd (Camera *camera,char* cmd); +static char* switchToRecMode(Camera *camera); +static char* switchToPlayMode(Camera *camera); typedef struct { char *data; @@ -139,7 +139,7 @@ camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) char *xpath; int i, start, end, tries; - loadCmd (camera, RECMODE); + switchToRecMode (camera); if (!camera->pl->liveview) { loadCmd(camera,"cam.cgi?mode=startstream&value=49199"); @@ -197,8 +197,6 @@ camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) return GP_ERROR; } -//int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context); - static int camera_about (Camera *camera, CameraText *about, GPContext *context); @@ -440,10 +438,17 @@ loadCmd (Camera *camera,char* cmd) { return lmb.data; } -static void switchToRecMode(Camera *camera) { - loadCmd(camera,"?mode=camcmd&value=recmode"); +static char* +switchToRecMode(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=camcmd&value=recmode"); } +static char* +switchToPlayMode(Camera *camera) { + return loadCmd(camera,"cam.cgi?mode=camcmd&value=playmode"); +} + + static void Set_ISO(Camera *camera,const char * ISOValue) { char buf[200]; sprintf(buf, "?mode=setsetting&type=iso&value=%s",ISOValue); @@ -463,7 +468,6 @@ Get_ISO(Camera *camera) { static char* Get_ShutterSpeed(Camera *camera) { char *result, *s; - int nom, div; char shutterspeed[20]; result = loadCmd(camera,"cam.cgi?mode=getsetting&type=shtrspeed"); @@ -475,19 +479,13 @@ Get_ShutterSpeed(Camera *camera) { s = strstr(result, "", &nom, &div) != 2) + if (sscanf(s,"", shutterspeed) != 1) return NULL; - - if (0 == (nom*10/div)%10) - sprintf(shutterspeed,"%d", nom/div); - else - sprintf(shutterspeed,"%d/%d", nom, div); return strdup(shutterspeed); } static char* Get_Aperture(Camera *camera) { - int nom, div; char aperture[20]; char *result, *s; @@ -499,12 +497,8 @@ Get_Aperture(Camera *camera) { return NULL; s = strstr(result, "", &nom, &div) != 2) + if (sscanf(s,"", aperture) != 2) return NULL; - if (0 == (nom*10/div)%10) - sprintf(aperture,"%d", nom/div); - else - sprintf(aperture,"%d.%d", nom/div, (nom*10/div)%10); return strdup(aperture); } @@ -573,41 +567,54 @@ Set_quality(Camera *camera,const char* Quality) { } -static void -shotPicture(Camera *camera) { - loadCmd(camera,"?mode=camcmd&value=capture"); +static int +startCapture(Camera *camera) { + char *result; + + result = loadCmd(camera,"cam.cgi?mode=camcmd&value=capture"); + + if (strstr(result,"ok")) return GP_OK; + if (strstr(result,"err_busy")) return GP_ERROR_CAMERA_BUSY; + return GP_ERROR; } -static void stopCapture(Camera *camera) { - loadCmd(camera,"?mode=camcmd&value=capture_cancel"); +static int +stopCapture(Camera *camera) { + char *result; + + result = loadCmd(camera,"cam.cgi?mode=camcmd&value=capture_cancel"); + + if (strstr(result,"ok")) return GP_OK; + if (strstr(result,"err_busy")) return GP_ERROR_CAMERA_BUSY; + return GP_ERROR; } static void startMovie(Camera *camera) { - loadCmd(camera,"?mode=camcmd&value=video_recstart"); + loadCmd(camera,"cam.cgi?mode=camcmd&value=video_recstart"); } static void stopMovie(Camera *camera) { - loadCmd(camera,"?mode=camcmd&value=video_recstop"); + loadCmd(camera,"cam.cgi?mode=camcmd&value=video_recstop"); } static void zoomIn(Camera *camera) { - loadCmd(camera,"?mode=camcmd&value=tele-fast"); + loadCmd(camera,"cam.cgi?mode=camcmd&value=tele-fast"); } static void zoomOut(Camera *camera) { - loadCmd(camera,"?mode=camcmd&value=wide-fast"); + loadCmd(camera,"cam.cgi?mode=camcmd&value=wide-fast"); } static void zoomStop(Camera *camera) { - loadCmd(camera,"?mode=camcmd&value=zoomstop"); + loadCmd(camera,"cam.cgi?mode=camcmd&value=zoomstop"); } static void focusIn(Camera *camera) { - loadCmd(camera,"?mode=camctrl&type=focus&value=tele-fast"); + loadCmd(camera,"cam.cgi?mode=camctrl&type=focus&value=tele-fast"); } static void focusOut(Camera *camera) { - loadCmd(camera,"?mode=camctrl&type=focus&value=wide-fast"); + loadCmd(camera,"cam.cgi?mode=camctrl&type=focus&value=wide-fast"); } /* @@ -643,10 +650,23 @@ NumberPix(Camera *camera) { /*GP_LOG_D("NumberPix Decode current root node is %s \n", doc); */ if (cur == NULL) { - fprintf(stderr,"empty document\n"); + GP_LOG_E("empty xml result document"); xmlFreeDoc(doc); return GP_ERROR; } + /* + * busy mode: + err_busy + + * regular return: + + ok2651651 + */ + if (strstr(temp, "err_busy")) { + xmlFreeDoc(doc); + return GP_ERROR_CAMERA_BUSY; + } + cur = cur->xmlChildrenNode; while (cur != NULL) { /*GP_LOG_D("NumberPix Decode current node is %s \n", (char*)cur);*/ @@ -660,7 +680,7 @@ NumberPix(Camera *camera) { xmlFreeDoc(doc); return GP_ERROR; } - GP_LOG_D("NumberPix Found is %s \n", (char *) keyz); + GP_LOG_D("NumberPix Found is %s", (char *) keyz); numpics = strtol((char*)keyz, NULL, 10); xmlFreeDoc(doc); @@ -725,7 +745,7 @@ GetPixRange(Camera *camera, int start, int num) { LumixMemoryBuffer lmb; char URL[1000]; - loadCmd(camera,PLAYMODE); + switchToPlayMode (camera); NumPix = NumberPix(camera); //GP_LOG_D("NumPix is %d \n", NumPix); if (NumPix < GP_OK) return NULL; @@ -983,21 +1003,103 @@ Raw: return strdup((char*)xchar); } -/** -* Get the full configuration tree of the camera. -* -* This function is a method of the Camera object. -* TO DO - - i started to include some items to set the quality (raw and raw+jpg) as well as dictionary for ISO and shutter speed -* mostly every thing is still to do -*/ +static struct shuttermap { + char *speed; + char *cameraspeed; +} shutterspeeds[] = { + {"3072/256","4000"}, + {"2987/256","3200"}, + {"2902/256","2500"}, + {"2816/256","2000"}, + {"2731/256","1600"}, + {"2646/256","1300"}, + {"2560/256","1000"}, + {"2475/256","800"}, + {"2390/256","640"}, + {"2304/256","500"}, + {"2219/256","400"}, + {"2134/256","320"}, + {"2048/256","250"}, + {"1963/256","200"}, + {"1878/256","160"}, + {"1792/256","125"}, + {"1707/256","100"}, + {"1622/256","80"}, + {"1536/256","60"}, + {"1451/256","50"}, + {"1366/256","40"}, + {"1280/256","30"}, + {"1195/256","25"}, + {"1110/256","20"}, + {"1024/256","15"}, + {"939/256","13"}, + {"854/256","10"}, + {"768/256","8"}, + {"683/256","6"}, + {"598/256","5"}, + {"512/256","4"}, + {"427/256","3.2"}, + {"342/256","2.5"}, + {"256/256","2"}, + {"171/256","1.6"}, + {"86/256","1.3"}, + {"0/256","1"}, + {"-85/256","1.3s"}, + {"-170/256","1.6s"}, + {"-256/256","2s"}, + {"-341/256","2.5s"}, + {"-426/256","3.2s"}, + {"-512/256","4s"}, + {"-682/256","5s"}, + {"-768/256","6s"}, + {"-853/256","8s"}, + {"-938/256","10s"}, + {"-1024/256","13s"}, + {"-1109/256","15s"}, + {"-1194/256","20s"}, + {"-1280/256","25s"}, + {"-1365/256","30s"}, + {"-1450/256","40s"}, + {"-1536/256","50s"}, + {"16384/256","60s"}, + {"256/256","B"}, +}; + +static struct aperturemap { + char *aperture; + char *cameraaperture; +} apertures[] = { + {"392/256","1.7"}, + {"427/256","1.8"}, + {"512/256","2"}, + {"598/256","2.2"}, + {"683/256","2.5"}, + {"768/256","2.8"}, + {"854/256","3.2"}, + {"938/256","3.5"}, + {"1024/256","4"}, + {"1110/256","4.5"}, + {"1195/256","5"}, + {"1280/256","5.6"}, + {"1366/256","6.3"}, + {"1451/256","7.1"}, + {"1536/256","8"}, + {"1622/256","9"}, + {"1707/256","10"}, + {"1792/256","11"}, + {"1878/256","13"}, + {"1963/256","14"}, + {"2048/256","16"}, +}; + static int camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) { - CameraWidget *widget,*section; - int ret; - char *val; + CameraWidget *widget,*section; + int ret, i, valset; + char *val, *curval; - loadCmd (camera, RECMODE); + switchToRecMode (camera); gp_widget_new (GP_WIDGET_WINDOW, _("Lumix Configuration"), window); gp_widget_set_name (*window, "config"); @@ -1011,10 +1113,20 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_value (widget, Get_Clock(camera)); gp_widget_append (section, widget); + val = Get_ShutterSpeed(camera); - gp_widget_new (GP_WIDGET_TEXT, _("Shutterspeed"), &widget); + if (!val) val = "unknown"; + gp_widget_new (GP_WIDGET_RADIO, _("Shutterspeed"), &widget); gp_widget_set_name (widget, "shutterspeed"); - gp_widget_set_value (widget, val?val:"unknown"); + valset = 0; + for (i=0;i before) + GetPixRange(camera,before,after-before); + /* handle case where we have more than one picture, otherwise we just take one */ + url = "unknown"; + if (camera->pl->pics[after].url_large) url = camera->pl->pics[after].url_large; + if (camera->pl->pics[after].url_raw) url = camera->pl->pics[after].url_raw; + s = strrchr(url,'/')+1; + strcpy(path->name, s); + strcpy(path->folder, "/"); + return GP_OK; } /** @@ -1494,7 +1664,7 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, C break; } - loadCmd(camera,PLAYMODE); + switchToPlayMode (camera); imageUrl = curl_easy_init(); @@ -1614,16 +1784,15 @@ camera_init (Camera *camera, GPContext *context) gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera); - if (loadCmd(camera,RECMODE) != NULL) { + if (switchToRecMode (camera) != NULL) { int numpix; Set_quality(camera,"raw_fine"); - loadCmd(camera,PLAYMODE); // 'making sure the camera is in Playmode + switchToPlayMode (camera); numpix = NumberPix(camera); GetPixRange(camera,0,numpix); - return GP_OK; } else return GP_ERROR_IO; -- cgit v1.2.1 From ab5b0ad8b2847f08a87c5b7920a39aea593b3366 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Fri, 28 Jun 2019 17:04:05 +0200 Subject: get shutterspeed und aperture content with libxml reader --- camlibs/lumix/lumix.c | 123 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 48 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index e8591715d..9dee6db6f 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -82,8 +82,6 @@ # define N_(String) (String) #endif -char* SHUTTERSTART = "cam.cgi?mode=camcmd&value=capture"; -char* SHUTTERSTOP = "cam.cgi?mode=camcmd&value=capture_cancel"; char* CDS_Control = ":60606/Server0/CDS_control"; int ReadoutMode = 2; // this should be picked up from the settings.... 0-> JPG; 1->RAW; 2 -> Thumbnails char* cameraShutterSpeed = "B"; // //placeholder to store the value of the shutterspeed set in camera; "B" is for bulb. @@ -467,39 +465,98 @@ Get_ISO(Camera *camera) { static char* Get_ShutterSpeed(Camera *camera) { - char *result, *s; - char shutterspeed[20]; + char *result, *s; + xmlDocPtr docin; + xmlNodePtr docroot, output; + xmlAttr *attr; result = loadCmd(camera,"cam.cgi?mode=getsetting&type=shtrspeed"); + docin = xmlReadMemory (result, strlen(result), "http://gphoto.org/", "utf-8", 0); /* * ok */ - if (!strstr(result,"ok")) - return NULL; - s = strstr(result, "", shutterspeed) != 1) + if (!docin) return NULL; + docroot = xmlDocGetRootElement (docin); + if (!docroot) { + xmlFreeDoc (docin); + return NULL; + } + if (strcmp((char*)docroot->name,"camrply")) { + GP_LOG_E ("docroot name unexpected %s", docroot->name); + return NULL; + } + output = docroot->children; + if (strcmp((char*)output->name, "result")) { + GP_LOG_E ("node name expected 'result', got %s", output->name); + return NULL; + } + if (strcmp((char*)xmlNodeGetContent (output),"ok")) { + GP_LOG_E ("result was not 'ok', got %s", (char*)xmlNodeGetContent (output)); return NULL; - return strdup(shutterspeed); + } + output = xmlNextElementSibling (output); + if (strcmp((char*)output->name, "settingvalue")) { + GP_LOG_E ("node name expected 'settingvalue', got %s", output->name); + return NULL; + } + attr = output->properties; + if (strcmp((char*)attr->name, "shtrspeed")) { + GP_LOG_E ("attr name expected 'shtrspeed', got %s", output->name); + return NULL; + } + s = (char*)xmlNodeGetContent (attr->children); + GP_LOG_D("focal content %s", s); + xmlFreeDoc (docin); + return strdup(s); } static char* Get_Aperture(Camera *camera) { - char aperture[20]; - char *result, *s; + char *result, *s; + xmlDocPtr docin; + xmlNodePtr docroot, output; + xmlAttr *attr; /* * ok */ result = loadCmd(camera,"cam.cgi?mode=getsetting&type=focal"); - if (!strstr(result,"ok")) + docin = xmlReadMemory (result, strlen(result), "http://gphoto.org/", "utf-8", 0); + + if (!docin) return NULL; + docroot = xmlDocGetRootElement (docin); + if (!docroot) { + xmlFreeDoc (docin); + return NULL; + } + if (strcmp((char*)docroot->name,"camrply")) { + GP_LOG_E ("docroot name unexpected %s", docroot->name); return NULL; - s = strstr(result, "", aperture) != 2) + } + output = docroot->children; + if (strcmp((char*)output->name, "result")) { + GP_LOG_E ("node name expected 'result', got %s", output->name); + return NULL; + } + if (strcmp((char*)xmlNodeGetContent (output),"ok")) { + GP_LOG_E ("result was not 'ok', got %s", (char*)xmlNodeGetContent (output)); + return NULL; + } + output = xmlNextElementSibling (output); + if (strcmp((char*)output->name, "settingvalue")) { + GP_LOG_E ("node name expected 'settingvalue', got %s", output->name); + return NULL; + } + attr = output->properties; + if (strcmp((char*)attr->name, "focal")) { + GP_LOG_E ("attr name expected 'focal', got %s", output->name); return NULL; - return strdup(aperture); + } + s = (char*)xmlNodeGetContent (attr->children); + GP_LOG_D("focal content %s", s); + xmlFreeDoc (docin); + return strdup(s); } static char* @@ -647,7 +704,6 @@ NumberPix(Camera *camera) { xmlNodePtr cur = NULL; cur = xmlDocGetRootElement(doc); - /*GP_LOG_D("NumberPix Decode current root node is %s \n", doc); */ if (cur == NULL) { GP_LOG_E("empty xml result document"); @@ -696,39 +752,9 @@ SoapEnvelop(int start, int num){ return Envelop; } -static int -traverse_tree (int depth, xmlNodePtr node) -{ - xmlNodePtr next; - xmlChar *xchar; - int n; - char *xx; - - - if (!node) return 0; - xx = malloc (depth * 4 + 1); - memset (xx, ' ', depth*4); - xx[depth*4] = 0; - - n = xmlChildElementCount (node); - - next = node; - do { - fprintf(stderr,"%snode %s\n", xx,next->name); - fprintf(stderr,"%selements %d\n", xx,n); - xchar = xmlNodeGetContent (next); - fprintf(stderr,"%scontent %s\n", xx,xchar); - traverse_tree (depth+1,xmlFirstElementChild (next)); - } while ((next = xmlNextElementSibling (next))); - free (xx); - return 1; -} - - /* * retrieves the XML doc with the last num pictures avail in the camera. */ - static char* GetPixRange(Camera *camera, int start, int num) { long NumPix; @@ -1536,6 +1562,7 @@ camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GP if (ret == GP_ERROR_CAMERA_BUSY) sleep(1); } while ((ret == GP_ERROR_CAMERA_BUSY) && (tries--)); + if (ret < GP_OK) return ret; -- cgit v1.2.1 From 7c3dce618537276235ccdf4bec654120256599d0 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Fri, 28 Jun 2019 17:14:11 +0200 Subject: refactor to use a generic setting getter for all values --- camlibs/lumix/lumix.c | 94 +++++++++++++++++++-------------------------------- 1 file changed, 34 insertions(+), 60 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 9dee6db6f..ab8ac381a 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -459,21 +459,19 @@ Get_Clock(Camera *camera) { } static char* -Get_ISO(Camera *camera) { - return loadCmd(camera,"cam.cgi?mode=getsetting&type=iso"); -} - -static char* -Get_ShutterSpeed(Camera *camera) { +generic_setting_getter(Camera *camera, char *type) { char *result, *s; xmlDocPtr docin; xmlNodePtr docroot, output; xmlAttr *attr; + char url[50]; - result = loadCmd(camera,"cam.cgi?mode=getsetting&type=shtrspeed"); + sprintf(url,"cam.cgi?mode=getsetting&type=%s", type); + result = loadCmd(camera, url); docin = xmlReadMemory (result, strlen(result), "http://gphoto.org/", "utf-8", 0); + /* - * ok + * ok */ if (!docin) return NULL; @@ -501,87 +499,63 @@ Get_ShutterSpeed(Camera *camera) { return NULL; } attr = output->properties; - if (strcmp((char*)attr->name, "shtrspeed")) { - GP_LOG_E ("attr name expected 'shtrspeed', got %s", output->name); + if (strcmp((char*)attr->name, type)) { + GP_LOG_E ("attr name expected '%s', got %s", type, output->name); return NULL; } s = (char*)xmlNodeGetContent (attr->children); - GP_LOG_D("focal content %s", s); + GP_LOG_D("%s content %s", type, s); xmlFreeDoc (docin); return strdup(s); } static char* -Get_Aperture(Camera *camera) { - char *result, *s; - xmlDocPtr docin; - xmlNodePtr docroot, output; - xmlAttr *attr; +Get_ISO(Camera *camera) { + /* + * ok + */ + return generic_setting_getter(camera,"iso"); +} +static char* +Get_ShutterSpeed(Camera *camera) { + /* + * ok + */ + return generic_setting_getter(camera, "shtrspeed"); +} + +static char* +Get_Aperture(Camera *camera) { /* * ok */ - result = loadCmd(camera,"cam.cgi?mode=getsetting&type=focal"); - docin = xmlReadMemory (result, strlen(result), "http://gphoto.org/", "utf-8", 0); - - if (!docin) return NULL; - docroot = xmlDocGetRootElement (docin); - if (!docroot) { - xmlFreeDoc (docin); - return NULL; - } - if (strcmp((char*)docroot->name,"camrply")) { - GP_LOG_E ("docroot name unexpected %s", docroot->name); - return NULL; - } - output = docroot->children; - if (strcmp((char*)output->name, "result")) { - GP_LOG_E ("node name expected 'result', got %s", output->name); - return NULL; - } - if (strcmp((char*)xmlNodeGetContent (output),"ok")) { - GP_LOG_E ("result was not 'ok', got %s", (char*)xmlNodeGetContent (output)); - return NULL; - } - output = xmlNextElementSibling (output); - if (strcmp((char*)output->name, "settingvalue")) { - GP_LOG_E ("node name expected 'settingvalue', got %s", output->name); - return NULL; - } - attr = output->properties; - if (strcmp((char*)attr->name, "focal")) { - GP_LOG_E ("attr name expected 'focal', got %s", output->name); - return NULL; - } - s = (char*)xmlNodeGetContent (attr->children); - GP_LOG_D("focal content %s", s); - xmlFreeDoc (docin); - return strdup(s); + return generic_setting_getter(camera, "focal"); } static char* Get_AFMode(Camera *camera) { - return loadCmd(camera,"cam.cgi?mode=getsetting&type=afmode"); + return generic_setting_getter(camera,"afmode"); } static char* Get_FocusMode(Camera *camera) { - return loadCmd(camera,"cam.cgi?mode=getsetting&type=focusmode"); + return generic_setting_getter(camera,"focusmode"); } static char* Get_MFAssist(Camera *camera) { - return loadCmd(camera,"cam.cgi?mode=getsetting&type=mf_asst"); + return generic_setting_getter(camera,"mf_asst"); } static char* Get_MFAssist_Mag(Camera *camera) { - return loadCmd(camera,"cam.cgi?mode=getsetting&type=mf_asst_mag"); + return generic_setting_getter(camera,"mf_asst_mag"); } static char* Get_ExTeleConv(Camera *camera) { - return loadCmd(camera,"cam.cgi?mode=getsetting&type=ex_tele_conv"); + return generic_setting_getter(camera,"ex_tele_conv"); } static char* @@ -613,7 +587,7 @@ static void Set_ShutterSpeed(Camera *camera,const char* SpeedValue) { static char* Get_Quality(Camera *camera) { - return loadCmd(camera,"cam.cgi?mode=getsetting&type=quality"); + return generic_setting_getter(camera,"quality"); } static void @@ -1030,8 +1004,8 @@ Raw: } static struct shuttermap { - char *speed; char *cameraspeed; + char *speed; } shutterspeeds[] = { {"3072/256","4000"}, {"2987/256","3200"}, @@ -1092,8 +1066,8 @@ static struct shuttermap { }; static struct aperturemap { - char *aperture; char *cameraaperture; + char *aperture; } apertures[] = { {"392/256","1.7"}, {"427/256","1.8"}, -- cgit v1.2.1 From 8a5a0ee6c731bd513865a08634f9b4af1e2d4c87 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Fri, 28 Jun 2019 17:18:23 +0200 Subject: added videoquality --- camlibs/lumix/lumix.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index ab8ac381a..b1180ee98 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -453,11 +453,6 @@ static void Set_ISO(Camera *camera,const char * ISOValue) { loadCmd(camera,buf); } -static char* -Get_Clock(Camera *camera) { - return loadCmd(camera,"cam.cgi?mode=getsetting&type=clock"); -} - static char* generic_setting_getter(Camera *camera, char *type) { char *result, *s; @@ -509,6 +504,16 @@ generic_setting_getter(Camera *camera, char *type) { return strdup(s); } +static char* +Get_Clock(Camera *camera) { + return generic_setting_getter(camera,"clock"); +} + +static char* +Get_Video_Quality(Camera *camera) { + return generic_setting_getter(camera,"videoquality"); +} + static char* Get_ISO(Camera *camera) { /* @@ -1134,6 +1139,11 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_value (widget, Get_Quality(camera)); gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("Video Quality"), &widget); + gp_widget_set_name (widget, "videoquality"); + gp_widget_set_value (widget, Get_Video_Quality(camera)); + gp_widget_append (section, widget); + val = Get_Aperture(camera); if (!val) val = "unknown"; -- cgit v1.2.1 From d96088e00ff039650c25d5deec9cf7ca1057b56a Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Fri, 28 Jun 2019 17:20:53 +0200 Subject: added iso --- camlibs/lumix/lumix.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index b1180ee98..4b5e751f3 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -1161,9 +1161,19 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_append (section, widget); - gp_widget_new (GP_WIDGET_TEXT, _("ISO"), &widget); + gp_widget_new (GP_WIDGET_RADIO, _("ISO"), &widget); gp_widget_set_name (widget, "iso"); gp_widget_set_value (widget, Get_ISO(camera)); + gp_widget_add_choice (widget, "auto"); + gp_widget_add_choice (widget, "80"); + gp_widget_add_choice (widget, "100"); + gp_widget_add_choice (widget, "200"); + gp_widget_add_choice (widget, "400"); + gp_widget_add_choice (widget, "800"); + gp_widget_add_choice (widget, "1600"); + gp_widget_add_choice (widget, "3200"); + gp_widget_add_choice (widget, "6400"); + gp_widget_add_choice (widget, "12800"); gp_widget_append (section, widget); @@ -1271,6 +1281,14 @@ camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) sprintf(buf,"cam.cgi?mode=setsetting&type=focal&value=%s", val); loadCmd(camera,buf); } + if ((GP_OK == gp_widget_get_child_by_name(window, "iso", &widget)) && gp_widget_changed (widget)) { + char buf[50]; + + if (GP_OK != (ret = gp_widget_get_value (widget, &val))) + return ret; + sprintf(buf,"cam.cgi?mode=setsetting&type=iso&value=%s", val); + loadCmd(camera,buf); + } return GP_OK; } -- cgit v1.2.1 From 8f929c5bdc2f8243e54b738f722dd23bd36da837 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Sat, 29 Jun 2019 09:01:10 +0200 Subject: map speed and aperture back from display values to camera values --- camlibs/lumix/lumix.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 4b5e751f3..36606f0f4 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -1243,10 +1243,10 @@ camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) { CameraWidget *widget; char *val; - int ret; + char buf[50]; + int i, ret; if ((GP_OK == gp_widget_get_child_by_name(window, "zoom", &widget)) && gp_widget_changed (widget)) { - char buf[30]; if (GP_OK != (ret = gp_widget_get_value (widget, &val))) return ret; @@ -1267,18 +1267,33 @@ camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) } if ((GP_OK == gp_widget_get_child_by_name(window, "shutterspeed", &widget)) && gp_widget_changed (widget)) { + char *cameraspeed = NULL; if (GP_OK != (ret = gp_widget_get_value (widget, &val))) return ret; - Set_ShutterSpeed(camera,val); + for (i=0;i Date: Mon, 1 Jul 2019 08:34:33 +0200 Subject: rename GP_PORT_TCP -> GP_PORT_IP as we just use it specify an IP, regardless of what the driver does --- camlibs/lumix/lumix.c | 16 +++++----------- libgphoto2_port/gphoto2/gphoto2-port-info-list.h | 2 +- libgphoto2_port/ptpip/ptpip.c | 10 +++++----- libgphoto2_port/test/test-port-list.c | 2 +- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 36606f0f4..5442b78d5 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -134,7 +134,6 @@ camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) struct sockaddr_in serv_addr; unsigned char buffer[65536]; GPPortInfo info; - char *xpath; int i, start, end, tries; switchToRecMode (camera); @@ -149,7 +148,6 @@ camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) } gp_port_get_info (camera->port, &info); - gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ memset(&serv_addr, 0, sizeof(serv_addr)); @@ -411,8 +409,8 @@ loadCmd (Camera *camera,char* cmd) { curl = curl_easy_init(); gp_port_get_info (camera->port, &info); - gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ - snprintf( URL,100, "http://%s/%s", xpath+4, cmd); + gp_port_info_get_path (info, &xpath); /* xpath now contains ip:192.168.1.1 */ + snprintf( URL,100, "http://%s/%s", xpath+strlen("ip:"), cmd); GP_LOG_D("cam url is %s", URL); curl_easy_setopt(curl, CURLOPT_URL, URL); @@ -772,8 +770,8 @@ GetPixRange(Camera *camera, int start, int num) { list = curl_slist_append(list, "Accept: text/xml"); gp_port_get_info (camera->port, &info); - gp_port_info_get_path (info, &xpath); /* xpath now contains tcp:192.168.1.1 */ - snprintf( URL, 1000, "http://%s%s",xpath+4, CDS_Control); + gp_port_info_get_path (info, &xpath); /* xpath now contains ip:192.168.1.1 */ + snprintf( URL, 1000, "http://%s%s",xpath+strlen("ip:"), CDS_Control); curl_easy_setopt(curl, CURLOPT_URL, URL); lmb.size = 0; @@ -1758,7 +1756,7 @@ int camera_abilities (CameraAbilitiesList *list) { memset(&a, 0, sizeof(a)); strcpy(a.model, "Panasonic:LumixGSeries"); a.status = GP_DRIVER_STATUS_EXPERIMENTAL; - a.port = GP_PORT_TCP; + a.port = GP_PORT_IP; a.operations = GP_CAPTURE_IMAGE| GP_OPERATION_CAPTURE_VIDEO | GP_OPERATION_CONFIG; a.file_operations = GP_FILE_OPERATION_PREVIEW ; /* it should be possible to browse and DL images the files using the ReadImageFromCamera() function but for now lets keep it simple*/ @@ -1799,7 +1797,6 @@ int camera_init (Camera *camera, GPContext *context) { GPPortInfo info; - char *xpath; int ret; camera->pl = calloc(sizeof(CameraPrivateLibrary),1); @@ -1823,9 +1820,6 @@ camera_init (Camera *camera, GPContext *context) GP_LOG_E ("Failed to get port info?"); return ret; } - gp_port_info_get_path (info, &xpath); - /* xpath now contains tcp:192.168.1.1 */ - gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera); if (switchToRecMode (camera) != NULL) { diff --git a/libgphoto2_port/gphoto2/gphoto2-port-info-list.h b/libgphoto2_port/gphoto2/gphoto2-port-info-list.h index eec6ceabe..fcb840b68 100644 --- a/libgphoto2_port/gphoto2/gphoto2-port-info-list.h +++ b/libgphoto2_port/gphoto2/gphoto2-port-info-list.h @@ -39,7 +39,7 @@ typedef enum { GP_PORT_PTPIP = 1 << 4, /**< \brief PTP/IP port. */ GP_PORT_USB_DISK_DIRECT = 1 << 5, /**< \brief Direct IO to an usb mass storage device. */ GP_PORT_USB_SCSI = 1 << 6, /**< \brief USB Mass Storage raw SCSI port. */ - GP_PORT_TCP = 1 << 7 /**< \brief generic TCP port. */ + GP_PORT_IP = 1 << 7 /**< \brief generic IP address port. */ } GPPortType; /** diff --git a/libgphoto2_port/ptpip/ptpip.c b/libgphoto2_port/ptpip/ptpip.c index 225419a9d..20947d805 100644 --- a/libgphoto2_port/ptpip/ptpip.c +++ b/libgphoto2_port/ptpip/ptpip.c @@ -186,16 +186,16 @@ gp_port_library_list (GPPortInfoList *list) gp_port_info_list_append (list, info); /* do not check return */ gp_port_info_new (&info); - gp_port_info_set_type (info, GP_PORT_TCP); - gp_port_info_set_name (info, _("TCP Connection")); - gp_port_info_set_path (info, "tcp:"); + gp_port_info_set_type (info, GP_PORT_IP); + gp_port_info_set_name (info, _("IP Connection")); + gp_port_info_set_path (info, "ip:"); CHECK (gp_port_info_list_append (list, info)); /* Generic matcher so you can pass any IP address */ gp_port_info_new (&info); - gp_port_info_set_type (info, GP_PORT_TCP); + gp_port_info_set_type (info, GP_PORT_IP); gp_port_info_set_name (info, ""); - gp_port_info_set_path (info, "^tcp:"); + gp_port_info_set_path (info, "^ip:"); gp_port_info_list_append (list, info); /* do not check return */ #ifdef HAVE_MDNS_BONJOUR ret = DNSServiceBrowse ( diff --git a/libgphoto2_port/test/test-port-list.c b/libgphoto2_port/test/test-port-list.c index 10c3ecdd0..4da17af58 100644 --- a/libgphoto2_port/test/test-port-list.c +++ b/libgphoto2_port/test/test-port-list.c @@ -107,7 +107,7 @@ run_test () case GP_PORT_USB_SCSI: port_type_str = "USBSCSI"; break; case GP_PORT_DISK: port_type_str = "DISK"; break; case GP_PORT_PTPIP: port_type_str = "PTPIP"; break; - case GP_PORT_TCP: port_type_str = "TCP"; break; + case GP_PORT_IP: port_type_str = "IP"; break; default: port_type_str = "UNKNOWN"; return 3; break; } printf ("No: %d\n" -- cgit v1.2.1 From 2b22ebfe43e8aac831773c759f291753065433a8 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Sat, 6 Jul 2019 18:34:43 +0200 Subject: add liveview size getter / setter --- camlibs/lumix/lumix.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 5442b78d5..06ae2ec86 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -541,6 +541,11 @@ Get_AFMode(Camera *camera) { return generic_setting_getter(camera,"afmode"); } +static char* +Get_LiveViewSize(Camera *camera) { + return generic_setting_getter(camera,"liveviewsize"); +} + static char* Get_FocusMode(Camera *camera) { return generic_setting_getter(camera,"focusmode"); @@ -1180,6 +1185,11 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_value (widget, Get_AFMode(camera)); gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("Liveview Size"), &widget); + gp_widget_set_name (widget, "liveviewsize"); + gp_widget_set_value (widget, Get_LiveViewSize(camera)); + gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("Focus Mode"), &widget); gp_widget_set_name (widget, "focusmode"); gp_widget_set_value (widget, Get_FocusMode(camera)); @@ -1302,6 +1312,14 @@ camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) sprintf(buf,"cam.cgi?mode=setsetting&type=iso&value=%s", val); loadCmd(camera,buf); } + if ((GP_OK == gp_widget_get_child_by_name(window, "liveviewsize", &widget)) && gp_widget_changed (widget)) { + char buf[50]; + + if (GP_OK != (ret = gp_widget_get_value (widget, &val))) + return ret; + sprintf(buf,"cam.cgi?mode=setsetting&type=liveviewsize&value=%s", val); + loadCmd(camera,buf); + } return GP_OK; } -- cgit v1.2.1 From 12f2ae7f489db4db799c0fd454480732918e5047 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Sun, 7 Jul 2019 20:34:13 +0200 Subject: able to set/get devicename (that uses the camera) comments about startup --- camlibs/lumix/lumix.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 06ae2ec86..7f16d8f0b 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -546,6 +546,11 @@ Get_LiveViewSize(Camera *camera) { return generic_setting_getter(camera,"liveviewsize"); } +static char* +Get_DeviceName(Camera *camera) { + return generic_setting_getter(camera,"device_name"); +} + static char* Get_FocusMode(Camera *camera) { return generic_setting_getter(camera,"focusmode"); @@ -1190,6 +1195,11 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_value (widget, Get_LiveViewSize(camera)); gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("Device Name"), &widget); + gp_widget_set_name (widget, "devicename"); + gp_widget_set_value (widget, Get_DeviceName(camera)); + gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("Focus Mode"), &widget); gp_widget_set_name (widget, "focusmode"); gp_widget_set_value (widget, Get_FocusMode(camera)); @@ -1320,6 +1330,14 @@ camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) sprintf(buf,"cam.cgi?mode=setsetting&type=liveviewsize&value=%s", val); loadCmd(camera,buf); } + if ((GP_OK == gp_widget_get_child_by_name(window, "devicename", &widget)) && gp_widget_changed (widget)) { + char buf[50]; + + if (GP_OK != (ret = gp_widget_get_value (widget, &val))) + return ret; + sprintf(buf,"cam.cgi?mode=setsetting&type=device_name&value=%s", val); + loadCmd(camera,buf); + } return GP_OK; } @@ -1840,6 +1858,13 @@ camera_init (Camera *camera, GPContext *context) } gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera); +/* + startup code might need: + + loadCmd(camera,"cam.cgi?mode=accctrl&type=req_acc&value=4D454930-0100-1000-8001-020D0090325B&value2=GT-I9300"); + loadCmd(camera,"cam.cgi?mode=setsetting&type=device_name&value=GT-I9300"); +*/ + if (switchToRecMode (camera) != NULL) { int numpix; -- cgit v1.2.1 From 4bcbb27564bf2a246fdb03b642fbfa940b315db6 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Mon, 8 Jul 2019 07:51:14 +0200 Subject: more shutterspeeds fixed realloc --- camlibs/lumix/lumix.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index 7f16d8f0b..e3b999ccc 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -765,7 +765,7 @@ GetPixRange(Camera *camera, int start, int num) { if (camera->pl->numpics < NumPix) { camera->pl->pics = realloc(camera->pl->pics,NumPix * sizeof(camera->pl->pics[0])); - memset(camera->pl->pics+camera->pl->numpics, 0, NumPix * sizeof(camera->pl->pics[0])); + memset(camera->pl->pics+camera->pl->numpics, 0, (NumPix - camera->pl->numpics) * sizeof(camera->pl->pics[0])); camera->pl->numpics = NumPix; } @@ -1020,6 +1020,9 @@ static struct shuttermap { char *cameraspeed; char *speed; } shutterspeeds[] = { + {"3328/256","8000"}, + {"3243/256","6400"}, + {"3158/256","5000"}, {"3072/256","4000"}, {"2987/256","3200"}, {"2902/256","2500"}, -- cgit v1.2.1 From f124228ff6bc592cc80aa0afe943ab0aa37373ee Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Tue, 9 Jul 2019 08:35:00 +0200 Subject: added bulb config that just starts / ends captuzre --- camlibs/lumix/lumix.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index e3b999ccc..cb374576b 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -1187,6 +1187,11 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_add_choice (widget, "12800"); gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TOGGLE, _("Bulb"), &widget); + gp_widget_set_name (widget, "bulb"); + gp_widget_set_value (widget, 2); + gp_widget_append (section, widget); + gp_widget_new (GP_WIDGET_TEXT, _("Autofocus Mode"), &widget); gp_widget_set_name (widget, "afmode"); @@ -1341,6 +1346,20 @@ camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) sprintf(buf,"cam.cgi?mode=setsetting&type=device_name&value=%s", val); loadCmd(camera,buf); } + if ((GP_OK == gp_widget_get_child_by_name(window, "bulb", &widget)) && gp_widget_changed (widget)) { + int val; + + if (GP_OK != (ret = gp_widget_get_value (widget, &val))) + return ret; + + if (val) { + ret = startCapture (camera); + if (ret != GP_OK) + return ret; + } else { + stopCapture(camera); + } + } return GP_OK; } -- cgit v1.2.1 From 9864bf95e880f2d72b706b2c8ab9197ba8641c6b Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Tue, 9 Jul 2019 09:10:05 +0200 Subject: added also movie start/stop code --- camlibs/lumix/lumix.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index cb374576b..a1cccf950 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -1187,9 +1187,16 @@ camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_add_choice (widget, "12800"); gp_widget_append (section, widget); + valset = 2; gp_widget_new (GP_WIDGET_TOGGLE, _("Bulb"), &widget); gp_widget_set_name (widget, "bulb"); - gp_widget_set_value (widget, 2); + gp_widget_set_value (widget, &valset); + gp_widget_append (section, widget); + + valset = 2; + gp_widget_new (GP_WIDGET_TOGGLE, _("Movie"), &widget); + gp_widget_set_name (widget, "movie"); + gp_widget_set_value (widget, &valset); gp_widget_append (section, widget); @@ -1360,6 +1367,18 @@ camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) stopCapture(camera); } } + if ((GP_OK == gp_widget_get_child_by_name(window, "movie", &widget)) && gp_widget_changed (widget)) { + int val; + + if (GP_OK != (ret = gp_widget_get_value (widget, &val))) + return ret; + + if (val) { + startMovie (camera); + } else { + stopMovie(camera); + } + } return GP_OK; } -- cgit v1.2.1 From 9af89b9f54aed7108759c92845c1932e108a382a Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 10 Jul 2019 08:18:14 +0200 Subject: fixed shutterspeed setting command --- camlibs/lumix/lumix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index a1cccf950..a651c5057 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -594,7 +594,7 @@ Get_CurMenu(Camera *camera) { static void Set_ShutterSpeed(Camera *camera,const char* SpeedValue) { char buf[200]; - sprintf(buf, "?mode=setsetting&type=shtrspeed&value=%s",SpeedValue); + sprintf(buf, "cam.cgi?mode=setsetting&type=shtrspeed&value=%s",SpeedValue); loadCmd(camera,buf); } -- cgit v1.2.1 From 0ebcaa21a6131d3840d6431c0854c63c7b06ffb6 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 10 Jul 2019 08:33:53 +0200 Subject: fixed added image detection --- camlibs/lumix/lumix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/camlibs/lumix/lumix.c b/camlibs/lumix/lumix.c index a651c5057..eeb0a0b54 100644 --- a/camlibs/lumix/lumix.c +++ b/camlibs/lumix/lumix.c @@ -1665,8 +1665,8 @@ camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GP GetPixRange(camera,before,after-before); /* handle case where we have more than one picture, otherwise we just take one */ url = "unknown"; - if (camera->pl->pics[after].url_large) url = camera->pl->pics[after].url_large; - if (camera->pl->pics[after].url_raw) url = camera->pl->pics[after].url_raw; + if (camera->pl->pics[after-1].url_large) url = camera->pl->pics[after-1].url_large; + if (camera->pl->pics[after-1].url_raw) url = camera->pl->pics[after-1].url_raw; s = strrchr(url,'/')+1; strcpy(path->name, s); strcpy(path->folder, "/"); -- cgit v1.2.1