mirror of
https://gitflic.ru/project/astankevich/mtpview.git
synced 2024-11-23 15:08:23 +01:00
413 lines
11 KiB
C++
413 lines
11 KiB
C++
#include "App.h"
|
|
#include "MainWindow.h"
|
|
|
|
//#include "common.h"
|
|
#include <libmtp.h>
|
|
//#include "util.h"
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
App *app;
|
|
MainWindow *mainwin;
|
|
LIBMTP_mtpdevice_t *detected_device=0;
|
|
|
|
bool finish_read_device = false;
|
|
uint64_t prev_progress = 0;
|
|
|
|
int progress (uint64_t const sent, uint64_t const total,
|
|
void const * const data)
|
|
{
|
|
uint64_t progress_percent = (100*sent)/total;
|
|
if (((progress_percent % 10) == 0) &&
|
|
(progress_percent > prev_progress) &&
|
|
(total>10*1024*1024)){
|
|
|
|
printf(" Progress %d\n", progress_percent);
|
|
mainwin->uploadDownloadNotification->SetProgress((float)sent/total);
|
|
prev_progress = (progress_percent < 100)? progress_percent: 0;
|
|
mainwin->uploadDownloadNotification->Send();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Find the file type based on extension */
|
|
LIBMTP_filetype_t
|
|
find_filetype (const char * filename)
|
|
{
|
|
char *ptype;
|
|
LIBMTP_filetype_t filetype;
|
|
|
|
#ifdef __WIN32__
|
|
ptype = strrchr(filename, '.');
|
|
#else
|
|
ptype = rindex(filename,'.');
|
|
#endif
|
|
// This accounts for the case with a filename without any "." (period).
|
|
if (!ptype) {
|
|
ptype = "";
|
|
} else {
|
|
++ptype;
|
|
}
|
|
|
|
/* This need to be kept constantly updated as new file types arrive. */
|
|
if (!strcasecmp (ptype, "wav")) {
|
|
filetype = LIBMTP_FILETYPE_WAV;
|
|
} else if (!strcasecmp (ptype, "mp3")) {
|
|
filetype = LIBMTP_FILETYPE_MP3;
|
|
} else if (!strcasecmp (ptype, "wma")) {
|
|
filetype = LIBMTP_FILETYPE_WMA;
|
|
} else if (!strcasecmp (ptype, "ogg")) {
|
|
filetype = LIBMTP_FILETYPE_OGG;
|
|
} else if (!strcasecmp (ptype, "mp4")) {
|
|
filetype = LIBMTP_FILETYPE_MP4;
|
|
} else if (!strcasecmp (ptype, "wmv")) {
|
|
filetype = LIBMTP_FILETYPE_WMV;
|
|
} else if (!strcasecmp (ptype, "avi")) {
|
|
filetype = LIBMTP_FILETYPE_AVI;
|
|
} else if (!strcasecmp (ptype, "mpeg") || !strcasecmp (ptype, "mpg")) {
|
|
filetype = LIBMTP_FILETYPE_MPEG;
|
|
} else if (!strcasecmp (ptype, "asf")) {
|
|
filetype = LIBMTP_FILETYPE_ASF;
|
|
} else if (!strcasecmp (ptype, "qt") || !strcasecmp (ptype, "mov")) {
|
|
filetype = LIBMTP_FILETYPE_QT;
|
|
} else if (!strcasecmp (ptype, "wma")) {
|
|
filetype = LIBMTP_FILETYPE_WMA;
|
|
} else if (!strcasecmp (ptype, "jpg") || !strcasecmp (ptype, "jpeg")) {
|
|
filetype = LIBMTP_FILETYPE_JPEG;
|
|
} else if (!strcasecmp (ptype, "jfif")) {
|
|
filetype = LIBMTP_FILETYPE_JFIF;
|
|
} else if (!strcasecmp (ptype, "tif") || !strcasecmp (ptype, "tiff")) {
|
|
filetype = LIBMTP_FILETYPE_TIFF;
|
|
} else if (!strcasecmp (ptype, "bmp")) {
|
|
filetype = LIBMTP_FILETYPE_BMP;
|
|
} else if (!strcasecmp (ptype, "gif")) {
|
|
filetype = LIBMTP_FILETYPE_GIF;
|
|
} else if (!strcasecmp (ptype, "pic") || !strcasecmp (ptype, "pict")) {
|
|
filetype = LIBMTP_FILETYPE_PICT;
|
|
} else if (!strcasecmp (ptype, "png")) {
|
|
filetype = LIBMTP_FILETYPE_PNG;
|
|
} else if (!strcasecmp (ptype, "wmf")) {
|
|
filetype = LIBMTP_FILETYPE_WINDOWSIMAGEFORMAT;
|
|
} else if (!strcasecmp (ptype, "ics")) {
|
|
filetype = LIBMTP_FILETYPE_VCALENDAR2;
|
|
} else if (!strcasecmp (ptype, "exe") || !strcasecmp (ptype, "com") ||
|
|
!strcasecmp (ptype, "bat") || !strcasecmp (ptype, "dll") ||
|
|
!strcasecmp (ptype, "sys")) {
|
|
filetype = LIBMTP_FILETYPE_WINEXEC;
|
|
} else if (!strcasecmp (ptype, "aac")) {
|
|
filetype = LIBMTP_FILETYPE_AAC;
|
|
} else if (!strcasecmp (ptype, "mp2")) {
|
|
filetype = LIBMTP_FILETYPE_MP2;
|
|
} else if (!strcasecmp (ptype, "flac")) {
|
|
filetype = LIBMTP_FILETYPE_FLAC;
|
|
} else if (!strcasecmp (ptype, "m4a")) {
|
|
filetype = LIBMTP_FILETYPE_M4A;
|
|
} else if (!strcasecmp (ptype, "doc")) {
|
|
filetype = LIBMTP_FILETYPE_DOC;
|
|
} else if (!strcasecmp (ptype, "xml")) {
|
|
filetype = LIBMTP_FILETYPE_XML;
|
|
} else if (!strcasecmp (ptype, "xls")) {
|
|
filetype = LIBMTP_FILETYPE_XLS;
|
|
} else if (!strcasecmp (ptype, "ppt")) {
|
|
filetype = LIBMTP_FILETYPE_PPT;
|
|
} else if (!strcasecmp (ptype, "mht")) {
|
|
filetype = LIBMTP_FILETYPE_MHT;
|
|
} else if (!strcasecmp (ptype, "jp2")) {
|
|
filetype = LIBMTP_FILETYPE_JP2;
|
|
} else if (!strcasecmp (ptype, "jpx")) {
|
|
filetype = LIBMTP_FILETYPE_JPX;
|
|
} else if (!strcasecmp (ptype, "bin")) {
|
|
filetype = LIBMTP_FILETYPE_FIRMWARE;
|
|
} else if (!strcasecmp (ptype, "vcf")) {
|
|
filetype = LIBMTP_FILETYPE_VCARD3;
|
|
} else {
|
|
/* Tagging as unknown file type */
|
|
filetype = LIBMTP_FILETYPE_UNKNOWN;
|
|
}
|
|
printf("type: %s, %d\n", ptype, filetype);
|
|
return filetype;
|
|
}
|
|
|
|
static char *basename(char *in) {
|
|
char *p;
|
|
|
|
if (in == NULL)
|
|
return NULL;
|
|
p = in + strlen(in) - 1;
|
|
while (*p != '\\' && *p != '/' && *p != ':')
|
|
{ p--; }
|
|
return ++p;
|
|
}
|
|
|
|
int sendfile_function(char * from_path, int32_t parent_id, int32_t & ret_newFileID)
|
|
{
|
|
//printf("Sending %s to %s\n",from_path,to_path);
|
|
char *filename;
|
|
uint64_t filesize;
|
|
struct stat sb;
|
|
LIBMTP_file_t *genfile;
|
|
int ret;
|
|
//uint32_t parent_id = 0;
|
|
|
|
if ( stat(from_path, &sb) == -1 ) {
|
|
fprintf(stderr, "%s: ", from_path);
|
|
perror("stat");
|
|
return 1;
|
|
}
|
|
|
|
filesize = sb.st_size;
|
|
filename = basename(from_path);
|
|
//parent_id = parse_path (to_path,files,folders);
|
|
if (parent_id == -1) {
|
|
printf("Parent folder could not be found, skipping\n");
|
|
return 0;
|
|
}
|
|
|
|
genfile = LIBMTP_new_file_t();
|
|
genfile->filesize = filesize;
|
|
genfile->filename = strdup(filename);
|
|
genfile->filetype = find_filetype (filename);
|
|
genfile->parent_id = parent_id;
|
|
genfile->storage_id = 0;
|
|
|
|
printf("Sending file...\n");
|
|
ret = LIBMTP_Send_File_From_File(detected_device, from_path, genfile, progress, NULL);
|
|
printf("\n");
|
|
if (ret != 0) {
|
|
printf("Error sending file.\n");
|
|
LIBMTP_Dump_Errorstack(detected_device);
|
|
LIBMTP_Clear_Errorstack(detected_device);
|
|
ret = 1;
|
|
} else {
|
|
printf("New file ID: %d\n", genfile->item_id);
|
|
ret_newFileID = genfile->item_id;
|
|
}
|
|
|
|
LIBMTP_destroy_file_t(genfile);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
/* Clever prototype to be able to recurse */
|
|
void recursive_file_tree(LIBMTP_mtpdevice_t *,
|
|
LIBMTP_devicestorage_t *,
|
|
uint32_t,
|
|
int);
|
|
|
|
void recursive_file_tree(LIBMTP_mtpdevice_t *device,
|
|
LIBMTP_devicestorage_t *storage,
|
|
uint32_t leaf,
|
|
int depth)
|
|
{
|
|
LIBMTP_file_t *files;
|
|
LIBMTP_file_t *file;
|
|
|
|
files = LIBMTP_Get_Files_And_Folders(device,
|
|
storage->id,
|
|
leaf);
|
|
if (files == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* Iterate over the filelisting */
|
|
file = files;
|
|
while (file != NULL) {
|
|
LIBMTP_file_t *oldfile;
|
|
if (strcmp(file->filename, "Android")!=0) //skip system folder
|
|
{
|
|
|
|
/* Indent */
|
|
/*
|
|
int i;
|
|
for (i = 0; i < depth; i++) {
|
|
printf(" ");
|
|
}
|
|
printf("%u %s\n", file->item_id, file->filename);*/
|
|
mainwin->listView()->AddItem(new FileItem(device, storage,
|
|
file->item_id,
|
|
file->filename,
|
|
file->filetype != LIBMTP_FILETYPE_FOLDER,
|
|
depth));
|
|
if (file->filetype == LIBMTP_FILETYPE_FOLDER) {
|
|
recursive_file_tree(device, storage, file->item_id, depth+1);
|
|
}
|
|
}
|
|
oldfile = file;
|
|
file = file->next;
|
|
LIBMTP_destroy_file_t(oldfile);
|
|
}
|
|
}
|
|
|
|
void file_list(LIBMTP_mtpdevice_t *device,
|
|
LIBMTP_devicestorage_t *storage,
|
|
uint32_t leaf,
|
|
int depth,
|
|
BListItem * parentItem = NULL)
|
|
{
|
|
LIBMTP_file_t *files;
|
|
LIBMTP_file_t *file;
|
|
|
|
files = LIBMTP_Get_Files_And_Folders(device,
|
|
storage->id,
|
|
leaf);
|
|
if (files == NULL) {
|
|
return;
|
|
}
|
|
|
|
/* Iterate over the filelisting */
|
|
file = files;
|
|
while (file != NULL) {
|
|
LIBMTP_file_t *oldfile;
|
|
if (strcmp(file->filename, "Android")!=0) //skip system folder
|
|
{
|
|
FileItem * newItem = new FileItem(device, storage,
|
|
file->item_id,
|
|
file->filename,
|
|
file->filetype != LIBMTP_FILETYPE_FOLDER,
|
|
depth);
|
|
if (parentItem == NULL) {
|
|
mainwin->listView()->AddItem(newItem);
|
|
} else {
|
|
mainwin->listView()->AddUnder(newItem, parentItem);
|
|
|
|
}
|
|
|
|
/*
|
|
if (file->filetype == LIBMTP_FILETYPE_FOLDER) {
|
|
recursive_file_tree(device, storage, file->item_id, depth+1);
|
|
}*/
|
|
}
|
|
oldfile = file;
|
|
file = file->next;
|
|
LIBMTP_destroy_file_t(oldfile);
|
|
}
|
|
}
|
|
|
|
int init_mtp (/*int argc, char **argv*/)
|
|
{
|
|
LIBMTP_raw_device_t * rawdevices;
|
|
int numrawdevices;
|
|
LIBMTP_error_number_t err;
|
|
int i;
|
|
|
|
|
|
LIBMTP_Init();
|
|
|
|
err = LIBMTP_Detect_Raw_Devices(&rawdevices, &numrawdevices);
|
|
switch(err) {
|
|
case LIBMTP_ERROR_NO_DEVICE_ATTACHED:
|
|
fprintf(stdout, " No raw devices found.\n");
|
|
mainwin->showErrorAlert("No raw devices found. Be sure device connected and configured transfer mode.");
|
|
return 0;
|
|
case LIBMTP_ERROR_CONNECTING:
|
|
fprintf(stderr, "Detect: There has been an error connecting. Exiting\n");
|
|
mainwin->showErrorAlert("There has been an error connecting.");
|
|
return 1;
|
|
case LIBMTP_ERROR_MEMORY_ALLOCATION:
|
|
fprintf(stderr, "Detect: Encountered a Memory Allocation Error. Exiting\n");
|
|
mainwin->showErrorAlert("Encountered a Memory Allocation Error.");
|
|
return 1;
|
|
case LIBMTP_ERROR_NONE:
|
|
break;
|
|
case LIBMTP_ERROR_GENERAL:
|
|
default:
|
|
fprintf(stderr, "Unknown connection error.\n");
|
|
mainwin->showErrorAlert("Unknown connection error.");
|
|
return 1;
|
|
}
|
|
|
|
/* Iterate over connected MTP devices */
|
|
fprintf(stdout, "Attempting to connect device(s)\n");
|
|
for (i = 0; i < numrawdevices; i++) {
|
|
LIBMTP_mtpdevice_t *device;
|
|
LIBMTP_devicestorage_t *storage;
|
|
char *friendlyname;
|
|
int ret;
|
|
|
|
device = LIBMTP_Open_Raw_Device_Uncached(&rawdevices[i]);
|
|
if (device == NULL) {
|
|
fprintf(stderr, "Unable to open raw device %d\n", i);
|
|
mainwin->showErrorAlert("Unable to open raw device.");
|
|
continue;
|
|
}
|
|
detected_device = device;
|
|
LIBMTP_Dump_Errorstack(device);
|
|
LIBMTP_Clear_Errorstack(device);
|
|
|
|
friendlyname = LIBMTP_Get_Friendlyname(device);
|
|
if (friendlyname == NULL) {
|
|
printf("Device: (NULL)\n");
|
|
} else {
|
|
printf("Device: %s\n", friendlyname);
|
|
//LIBMTP_FreeMemory(friendlyname);
|
|
}
|
|
|
|
/* Get all storages for this device */
|
|
ret = LIBMTP_Get_Storage(device, LIBMTP_STORAGE_SORTBY_NOTSORTED);
|
|
if (ret != 0) {
|
|
perror("LIBMTP_Get_Storage()");
|
|
goto bailout;
|
|
}
|
|
|
|
/* Loop over storages */
|
|
for (storage = device->storage; storage != 0; storage = storage->next) {
|
|
fprintf(stdout, "Storage: %s\n", storage->StorageDescription);
|
|
//recursive_file_tree(device, storage, LIBMTP_FILES_AND_FOLDERS_ROOT, 0);
|
|
file_list (device, storage, LIBMTP_FILES_AND_FOLDERS_ROOT, 0);
|
|
}
|
|
continue; //do not release device because later use
|
|
bailout:
|
|
LIBMTP_Release_Device(device);
|
|
|
|
} /* End For Loop */
|
|
|
|
//LIBMTP_FreeMemory(rawdevices); missing in current libmtp.h
|
|
|
|
printf("OK.\n");
|
|
return 0;
|
|
}
|
|
|
|
App::App(void)
|
|
: BApplication("application/x-vnd.dw-ListColors")
|
|
{
|
|
mainwin = new MainWindow();
|
|
init_mtp();
|
|
mainwin->Show();
|
|
}
|
|
|
|
void App::AppActivated(bool active) {
|
|
|
|
fprintf(stdout, "App activated\n");
|
|
|
|
|
|
}
|
|
|
|
bool add_sub_files (BListItem * item, void* arg) {
|
|
FileItem * fileItem =((FileItem * ) item );
|
|
if (fileItem->isFolder() && mainwin->listView()->CountItemsUnder(item, true) == 0) {
|
|
fprintf(stdout, "Getting sub files for %d\n", fileItem->fileId());
|
|
file_list(fileItem->device(), fileItem->storage(), fileItem->fileId(), fileItem->OutlineLevel() +1, fileItem);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void App::ReadyToRun() {
|
|
fprintf(stdout, "App ready to run\n");
|
|
mainwin->listView()->DoForEach(&add_sub_files, NULL);
|
|
mainwin->listView()->FullListDoForEach(&add_sub_files, NULL);
|
|
finish_read_device = true;
|
|
}
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
app = new App();
|
|
app->Run();
|
|
delete app;
|
|
return 0;
|
|
}
|