mtpview/App.cpp

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;
}