Initial commit. It includes a batch of changes because develop starts without git.

This commit is contained in:
astankevich 2024-10-01 19:24:14 +07:00
commit c6b7eea1b5
13 changed files with 848 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
(Objects.mtpview)
mtpview
mtpview.hpkg
pkg/apps/mtpview

326
App.cpp Normal file
View File

@ -0,0 +1,326 @@
#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;
int progress (uint64_t const sent, uint64_t const total,
void const * const data)
{
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)
{
//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);
}
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,
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+2);
}
}
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");
return 0;
case LIBMTP_ERROR_CONNECTING:
fprintf(stderr, "Detect: There has been an error connecting. Exiting\n");
return 1;
case LIBMTP_ERROR_MEMORY_ALLOCATION:
fprintf(stderr, "Detect: Encountered a Memory Allocation Error. Exiting\n");
return 1;
case LIBMTP_ERROR_NONE:
break;
case LIBMTP_ERROR_GENERAL:
default:
fprintf(stderr, "Unknown connection error.\n");
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);
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);
}
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();
}
int
main(void)
{
app = new App();
app->Run();
delete app;
return 0;
}

12
App.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef APP_H
#define APP_H
#include <Application.h>
class App : public BApplication
{
public:
App(void);
};
#endif

244
MainWindow.cpp Normal file
View File

@ -0,0 +1,244 @@
#include <libmtp.h>
#include "App.h"
#include "MainWindow.h"
#include <Button.h>
#include <ListItem.h>
#include <ScrollView.h>
#include <Path.h>
//extern LIBMTP_mtpdevice_t * detected_device;
//extern App *app;
//extern LIBMTP_mtpdevice_t *detected_device=0;
int sendfile_function(char * from_path, int32_t parent_id);
int progress (uint64_t const sent, uint64_t const total,
void const * const data);
enum
{
M_DOWNLOAD_FILE = 'dlfl',
M_UPLOAD_FILE = 'upfl',
M_SET_TITLE = 'sttl'
};
FileItem::FileItem(LIBMTP_mtpdevice_t * device, int id, BString filename, bool isFile, int depth)
:BStringItem(filename, depth, false)
{
this->fDevice=device;
this->fId=id;
this->fIsFile=isFile;
}
MainWindow::MainWindow(void)
: BWindow(BRect(100,100,500,400),"MTP view",B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE)
{
// Here we will make a BView that covers the white area so that we can set the
// "background color"
BRect r(Bounds());
BView *top = new BView(r,"topview",B_FOLLOW_ALL,B_WILL_DRAW);
AddChild(top);
// ui_color() returns a system color, such as the window tab color, menu text color,
// and so forth.
top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
// Create a button and place it at the bottom right corner of the window. The empty BRect
// that we use for the BButton's frame is because we're going to have it resize itself and
// then move it to the corner based on the actual size of the button
download = new BButton(BRect(),"downloadbutton","Download", new BMessage(M_DOWNLOAD_FILE),
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
download->SetEnabled(false);
top->AddChild(download);
download->ResizeToPreferred();
upload = new BButton(BRect(),"uploadbutton","Upload", new BMessage(M_UPLOAD_FILE),
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
top->AddChild(upload);
upload->ResizeToPreferred();
// Bottom right corner of the window with 10 pixels of padding between the button and the
// window edge. 10 pixels is kind of a de facto standard for control padding.
download->MoveTo(Bounds().right - download->Bounds().Width() - 10.0,
Bounds().bottom - download->Bounds().Height() - 10.0);
upload->MoveTo(Bounds().right - download->Bounds().Width()-upload->Bounds().Width() - 20.0,
Bounds().bottom - upload->Bounds().Height() - 10.0);
r = Bounds();
r.InsetBy(10.0,10.0);
// When working with BScrollViews, you must compensate for the width/height of the scrollbars.
// B_V_SCROLL_BAR_WIDTH is a defined constant for the width of the vertical scroll bar.
r.right -= B_V_SCROLL_BAR_WIDTH;
// Frame() works like Bounds() except that it returns the size and location of the control
// in the coordinate space of the parent view. This will make fListView's bottom stop 10
// pixels above the button.
r.bottom = download->Frame().top - 10.0 - B_H_SCROLL_BAR_HEIGHT;
// Most of these parameters are exactly the same as for BView except that we can also
// specify whether the user is able to select just 1 item in the list or multiple items by
// clicking on items while holding a modifier key on the keyboard.
fListView = new BOutlineListView(r,"sportlist",B_SINGLE_SELECTION_LIST,B_FOLLOW_ALL);
// We didn't call AddChild on fListView because our BScrollView will do that for us. When
// created, it creates scrollbars and targets the specified view for any scrolling they do.
// When the BScrollView is attached to the window, it calls AddChild on fListView for us.
// If we call AddChild on fListView before we create this scrollview, our program will drop
// to the debugger when we call AddChild on the BScrollView -- a BView can have only one parent.
BScrollView *scrollView = new BScrollView("scrollview",fListView, B_FOLLOW_ALL, 0,true,true);
top->AddChild(scrollView);
// A BListView's selection message is sent to the window any time that the list's selection
// changes.
fListView->SetSelectionMessage(new BMessage(M_SET_TITLE));
messenger = new BMessenger(this);
openPanel = new BFilePanel(B_OPEN_PANEL, messenger, NULL, B_FILE_NODE, false);
//savePanel = new BFilePanel(B_SAVE_PANEL, messenger, NULL, B_DIRECTORY_NODE, false); //B_DIRECTORY_NODE has no effect
savePanel = new BFilePanel(B_SAVE_PANEL, messenger, NULL, B_FILE_NODE, false);
selectedItem = NULL;
//openPanel->SetTarget(messenger);
//savePanel->SetTarget(messenger);
printf("MainWindow created\n" );
}
void
MainWindow::MessageReceived(BMessage *msg)
{
switch (msg->what)
{
case M_DOWNLOAD_FILE:
{
int32 selection = fListView->CurrentSelection();
if (selection < 0)
{
break;
}
selectedItem = (FileItem*)fListView->ItemAt(selection);
if (selectedItem) {
printf("Show save dialog\n" );
savePanel->SetSaveText(selectedItem->Text());
savePanel->Show();
}
break;
}
case M_UPLOAD_FILE:
{
int32 selection = fListView->CurrentSelection();
if (selection < 0)
{
break;
}
selectedItem = (FileItem*)fListView->ItemAt(selection);
if (selectedItem) {
printf("Show open dialog\n" );
openPanel->Show();
}
break;
}
case M_SET_TITLE:
{
int32 selection = fListView->CurrentSelection();
if (selection < 0)
{
// This code is here because when we press the Reset button, the selection
// changes and an M_SET_TITLE message is sent, but because nothing is
// selected, CurrentSelection() returns -1.
SetTitle("MTP view");
selectedItem = NULL;
break;
}
//BStringItem *item = dynamic_cast<BStringItem*>(fListView->ItemAt(selection));
selectedItem = (FileItem*)fListView->ItemAt(selection);
if (selectedItem)
{
SetTitle(selectedItem->Text());
download->SetEnabled(selectedItem->isFile());
upload->SetEnabled(!selectedItem->isFile());
}
break;
}
case B_REFS_RECEIVED:{
printf(" User select Open\n" );
if (selectedItem) {
entry_ref ref;
if (msg->FindRef("refs", &ref) == B_OK) {
BEntry entry;
if (entry.SetTo(&ref) == B_OK) {
BPath path;
entry.GetPath(&path);
char openFileName[B_FILE_NAME_LENGTH];
strcpy(openFileName, path.Path());
printf("Try to upload %s to dir %d %s\n", openFileName, selectedItem->fileId(), selectedItem->Text());
sendfile_function(openFileName, selectedItem->fileId());
}
}
else
printf(" No refs in message\n" );
}
break;
}
case B_SAVE_REQUESTED:
{
printf(" User select Save\n" );
if (selectedItem) {
entry_ref ref;
if (msg->FindRef("directory", &ref) == B_OK) {
BEntry entry;
if (entry.SetTo(&ref) == B_OK) {
BPath path;
entry.GetPath(&path);
char fullSaveFileName [B_FILE_NAME_LENGTH];
const char * shortSaveFileName = NULL;// [B_FILE_NAME_LENGTH];
strcpy (fullSaveFileName, path.Path());
strcat(fullSaveFileName, "/");
if (msg->FindString("name", &shortSaveFileName) == B_OK) {
strcat(fullSaveFileName, shortSaveFileName);
}
//strcat(fullSaveFileName, selectedItem->Text());
printf("Try to download %d %s to %s\n", selectedItem->fileId(), selectedItem->Text(), fullSaveFileName);
if (LIBMTP_Get_File_To_File(selectedItem->device(), selectedItem->fileId(),
/*selectedItem->Text()*/ fullSaveFileName, progress, NULL) != 0 ){
printf("\nError getting file from MTP device.\n");
LIBMTP_Dump_Errorstack(selectedItem->device());
LIBMTP_Clear_Errorstack(selectedItem->device());
} else
printf("OK\n");
}
}
}
break;
}
case B_CANCEL:
{
printf(" User select Cancel\n" );
break;
}
default:
{
BWindow::MessageReceived(msg);
break;
}
}
}

41
MainWindow.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <Window.h>
#include <OutlineListView.h>
#include <FilePanel.h>
#include <Messenger.h>
#include <libmtp.h>
class FileItem: public BStringItem
{
public:
FileItem(LIBMTP_mtpdevice_t * device, int id, BString filename, bool isFile, int depth);
inline int fileId(){return fId;}
inline bool isFile(){return fIsFile;}
inline LIBMTP_mtpdevice_t * device(){return this->fDevice;}
private:
int fId;
bool fIsFile;
LIBMTP_mtpdevice_t * fDevice;
};
class MainWindow : public BWindow
{
public:
MainWindow(void);
void MessageReceived(BMessage *msg);
inline BOutlineListView * listView(){return this->fListView;};
private:
BOutlineListView *fListView;
BButton *download;
BButton *upload;
BFilePanel* openPanel;
BFilePanel* savePanel;
BMessenger * messenger;
FileItem * selectedItem;
};
#endif

130
Makefile Normal file
View File

@ -0,0 +1,130 @@
## Haiku Generic Makefile v2.6 ##
## Fill in this file to specify the project being created, and the referenced
## Makefile-Engine will do all of the hard work for you. This handles any
## architecture of Haiku.
# The name of the binary.
NAME = mtpview
TARGET_DIR = .
# The type of binary, must be one of:
# APP: Application
# SHARED: Shared library or add-on
# STATIC: Static library archive
# DRIVER: Kernel driver
TYPE = APP
# If you plan to use localization, specify the application's MIME signature.
APP_MIME_SIG =
# The following lines tell Pe and Eddie where the SRCS, RDEFS, and RSRCS are
# so that Pe and Eddie can fill them in for you.
#%{
# @src->@
# Specify the source files to use. Full paths or paths relative to the
# Makefile can be included. All files, regardless of directory, will have
# their object files created in the common object directory. Note that this
# means this Makefile will not work correctly if two source files with the
# same name (source.c or source.cpp) are included from different directories.
# Also note that spaces in folder names do not work well with this Makefile.
SRCS = App.cpp \
MainWindow.cpp
# Specify the resource definition files to use. Full or relative paths can be
# used.
RDEFS =
# Specify the resource files to use. Full or relative paths can be used.
# Both RDEFS and RSRCS can be utilized in the same Makefile.
RSRCS =
# End Pe/Eddie support.
# @<-src@
#%}
# Specify libraries to link against.
# There are two acceptable forms of library specifications:
# - if your library follows the naming pattern of libXXX.so or libXXX.a,
# you can simply specify XXX for the library. (e.g. the entry for
# "libtracker.so" would be "tracker")
#
# - for GCC-independent linking of standard C++ libraries, you can use
# $(STDCPPLIBS) instead of the raw "stdc++[.r4] [supc++]" library names.
#
# - if your library does not follow the standard library naming scheme,
# you need to specify the path to the library and it's name.
# (e.g. for mylib.a, specify "mylib.a" or "path/mylib.a")
LIBS = /boot/system/develop/lib/libbe.so \
/boot/system/develop/lib/libmtp.so \
/boot/system/develop/lib/libtracker.so
# Specify additional paths to directories following the standard libXXX.so
# or libXXX.a naming scheme. You can specify full paths or paths relative
# to the Makefile. The paths included are not parsed recursively, so
# include all of the paths where libraries must be found. Directories where
# source files were specified are automatically included.
LIBPATHS =
# Additional paths to look for system headers. These use the form
# "#include <header>". Directories that contain the files in SRCS are
# NOT auto-included here.
SYSTEM_INCLUDE_PATHS = /boot/system/develop/headers \
/boot/system/develop/headers/be \
/boot/system/develop/headers/cpp \
/boot/system/develop/headers/posix
# Additional paths paths to look for local headers. These use the form
# #include "header". Directories that contain the files in SRCS are
# automatically included.
LOCAL_INCLUDE_PATHS = .
# Specify the level of optimization that you want. Specify either NONE (O0),
# SOME (O1), FULL (O2), or leave blank (for the default optimization level).
OPTIMIZE := NONE
# Specify the codes for languages you are going to support in this
# application. The default "en" one must be provided too. "make catkeys"
# will recreate only the "locales/en.catkeys" file. Use it as a template
# for creating catkeys for other languages. All localization files must be
# placed in the "locales" subdirectory.
LOCALES =
# Specify all the preprocessor symbols to be defined. The symbols will not
# have their values set automatically; you must supply the value (if any) to
# use. For example, setting DEFINES to "DEBUG=1" will cause the compiler
# option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" would pass
# "-DDEBUG" on the compiler's command line.
DEFINES =
# Specify the warning level. Either NONE (suppress all warnings),
# ALL (enable all warnings), or leave blank (enable default warnings).
WARNINGS =
# With image symbols, stack crawls in the debugger are meaningful.
# If set to "TRUE", symbols will be created.
SYMBOLS :=
# Includes debug information, which allows the binary to be debugged easily.
# If set to "TRUE", debug info will be created.
DEBUGGER :=
# Specify any additional compiler flags to be used.
COMPILER_FLAGS =
# Specify any additional linker flags to be used.
LINKER_FLAGS =
# (Only used when "TYPE" is "DRIVER"). Specify the desired driver install
# location in the /dev hierarchy. Example:
# DRIVER_PATH = video/usb
# will instruct the "driverinstall" rule to place a symlink to your driver's
# binary in ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will
# appear at /dev/video/usb when loaded. The default is "misc".
DRIVER_PATH =
## Include the Makefile-Engine
DEVEL_DIRECTORY := \
$(shell findpaths -r "makefile_engine" B_FIND_PATH_DEVELOP_DIRECTORY)
include $(DEVEL_DIRECTORY)/etc/makefile-engine

7
README.md Normal file
View File

@ -0,0 +1,7 @@
## Description
Haiku's app to show a MTP-compilant device context and download/upload selected file to/from choosed location.
Note: Skip Android folder on device for perfomance.
## Compiling
Required: libmtp
Open moex_view.pld with Paladin. Choose Build->Make project.

13
changelog_ru.txt Normal file
View File

@ -0,0 +1,13 @@
5 июля 2023:
Убран вывод дерева файлов в консоль в целях повышения производительности.
Добавлено включение/выключение кнопки Download в зависимости от того что выбрано : файл или каталог.
Добавлен тестовый функционал для загрузки файлов на устройство.
18 июля 2023:
Добавлены диалоги открытия и сохранения файлов, а также соответствующие обработчики событий.
31 июля 2023:
Создана директория pkg с .PackageInfo и соотвествующей структурой. Файл mtpview в настоящее время нужно скопировать вручную в директорию apps.
9 сентября 2024:
Реализованы корректные обрабочики событий от диалогов загрузки и сохранения.

1
compile Normal file
View File

@ -0,0 +1 @@
gcc -o Run *.cpp -lbe

3
compile_commands.json Normal file
View File

@ -0,0 +1,3 @@
[
]

9
create_package.sh Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/sh
#Update binary
cp mtpview pkg/apps/mtpview
#Create package
pushd pkg
package create -C ./ ../mtpview.hpkg
popd

26
mtpview.pld Normal file
View File

@ -0,0 +1,26 @@
NAME=MTP_view
TARGETNAME=mtpview
PLATFORM=HaikuGCC4
SCM=none
GROUP=Source files
EXPANDGROUP=yes
SOURCEFILE=App.cpp
DEPENDENCY=MainWindow.h
SOURCEFILE=MainWindow.cpp
DEPENDENCY=App.h MainWindow.h
LOCALINCLUDE=.
SYSTEMINCLUDE=B_FIND_PATH_DEVELOP_HEADERS_DIRECTORY
SYSTEMINCLUDE=B_FIND_PATH_DEVELOP_HEADERS_DIRECTORY/be
SYSTEMINCLUDE=B_FIND_PATH_DEVELOP_HEADERS_DIRECTORY/cpp
SYSTEMINCLUDE=B_FIND_PATH_DEVELOP_HEADERS_DIRECTORY/posix
LIBRARY=B_FIND_PATH_DEVELOP_LIB_DIRECTORY/libbe.so
LIBRARY=B_FIND_PATH_DEVELOP_LIB_DIRECTORY/libmtp.so
LIBRARY=B_FIND_PATH_DEVELOP_LIB_DIRECTORY/libtracker.so
RUNARGS=
CCDEBUG=yes
CCPROFILE=no
CCOPSIZE=no
CCOPLEVEL=0
CCTARGETTYPE=0
CCEXTRA=
LDEXTRA=

32
pkg/.PackageInfo Normal file
View File

@ -0,0 +1,32 @@
name mtpview
version 0.1.1-1
architecture x86_64
summary "View android device contents"
description "View android content through MTP protocol.
* Upload file. Select dir in list and click UPload button. In dialog appeared select file on disk."
packager "Anton Stankevich <ashc@mail.ru>"
vendor "Anton Stankevich"
licenses {
"Apache v2"
}
copyrights {
"2024 Anton Stankevich"
}
provides {
mtpview = 0.1.1
app:mtpview = 0.1.1
}
requires {
haiku >= r1~beta4_hrev56578_4-1
libmtp >= 1.1.19-2
}
urls {
"https://example.com"
}
source-urls {
# Download
"https://example.com"
# Location 2
"https://example.com"
}