Skip to content

Commit

Permalink
cocoaui: cut/copy/paste
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleksiy-Yakovenko committed Feb 7, 2024
1 parent 672b9a4 commit 0148608
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 2 deletions.
2 changes: 2 additions & 0 deletions include/deadbeef/deadbeef.h
Original file line number Diff line number Diff line change
Expand Up @@ -1749,6 +1749,8 @@ typedef struct {
/// This function can be called only once per session,
/// usually from the UI plugin's start method.
void (*register_for_undo) (ddb_undo_hooks_t *undo_hooks);

size_t (*plt_get_selected_items) (ddb_playlist_t *plt, ddb_playItem_t ***out_items);
#endif
} DB_functions_t;

Expand Down
4 changes: 4 additions & 0 deletions plugins/cocoaui/Playlist/MedialibItemDragDropHolder.m
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder {
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
for (NSInteger i = 0; i < _count; i++) {
deadbeef->pl_item_ref (_items[i]);
}

NSUInteger length = sizeof (NSInteger) + self.count * sizeof (ddb_playItem_t *);
void *bytes = malloc (length);
memcpy (bytes, &_count, sizeof (NSInteger));
Expand Down
70 changes: 70 additions & 0 deletions plugins/cocoaui/Playlist/PlaylistViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#import "TrackContextMenu.h"
#import "TrackPropertiesManager.h"
#import "tftintutil.h"
#import "MedialibItemDragDropHolder.h"

#include <deadbeef/deadbeef.h>
#include "utf8.h"
Expand Down Expand Up @@ -1544,6 +1545,75 @@ - (NSMenu *)contextMenuForEvent:(NSEvent *)event forView:(NSView *)view {
return self.trackContextMenu;
}

#pragma mark - Copy & paste

- (void)copyAndDeleteSelected:(BOOL)deleteSelected {
ddb_playlist_t *plt = deadbeef->plt_get_curr ();

ddb_playItem_t **items = NULL;
ssize_t count = deadbeef->plt_get_selected_items (plt, &items);
if (count == 0) {
deadbeef->plt_unref (plt);
return;
}

MedialibItemDragDropHolder *holder = [[MedialibItemDragDropHolder alloc] initWithItems:items count:count];

for (ssize_t index = 0; index < count; index++) {
deadbeef->pl_item_unref (items[index]);
}
free (items);

NSPasteboard *pasteboard = NSPasteboard.generalPasteboard;
[pasteboard clearContents];
[pasteboard writeObjects:@[holder]];

if (deleteSelected) {
deadbeef->plt_delete_selected (plt);
}

deadbeef->plt_unref (plt);

if (deleteSelected) {
deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
}
}

- (void)cut:(id)sender {
[self copyAndDeleteSelected:YES];
}

- (void)copy:(id)sender {
[self copyAndDeleteSelected:NO];
}

- (void)paste:(id)sender {
NSPasteboard *pasteboard = NSPasteboard.generalPasteboard;
NSArray *copiedItems = [pasteboard readObjectsForClasses:@[MedialibItemDragDropHolder.class] options:@{}];
if (copiedItems != nil) {
MedialibItemDragDropHolder *holder = copiedItems.firstObject;
ddb_playlist_t *plt = deadbeef->plt_get_curr ();
int cursor = deadbeef->plt_get_cursor (plt, PL_MAIN);
if (cursor == -1) {
cursor = 0;
}
ddb_playItem_t *before = deadbeef->plt_get_item_for_idx (plt, cursor, PL_MAIN);

[self dropPlayItems:(DdbListviewRow_t *)holder.items before:(DdbListviewRow_t)before count:(int)holder.count];
if (before != NULL) {
deadbeef->pl_item_unref (before);
}

deadbeef->plt_deselect_all (plt);
deadbeef->plt_set_cursor (plt, PL_MAIN, (int)(cursor + holder.count));
deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, (uintptr_t)self.view, DDB_PLAYLIST_CHANGE_SELECTION, 0);

// TODO: scroll to cursor

deadbeef->plt_unref (plt);
}
}

#pragma mark - TrackContextMenuDelegate

- (void)trackContextMenuShowTrackProperties:(TrackContextMenu *)trackContextMenu {
Expand Down
30 changes: 28 additions & 2 deletions src/playlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -1484,10 +1484,11 @@ plt_insert_dir_int (
// no hidden files
// windows/svr4 unixes: missing dirent[]->d_type
#if defined(__MINGW32__) || defined(__SVR4)
if (namelist[i]->d_name[0] == '.') {
if (namelist[i]->d_name[0] == '.')
#else
if (namelist[i]->d_name[0] == '.' || (namelist[i]->d_type != DT_REG && namelist[i]->d_type != DT_UNKNOWN)) {
if (namelist[i]->d_name[0] == '.' || (namelist[i]->d_type != DT_REG && namelist[i]->d_type != DT_UNKNOWN))
#endif
{
continue;
}

Expand Down Expand Up @@ -4470,3 +4471,28 @@ pl_items_from_same_album (playItem_t *a, playItem_t *b) {
}
return pl_find_meta_raw (a, "album") == pl_find_meta_raw (b, "album") && a_artist == b_artist;
}

size_t
plt_get_selected_items(playlist_t *plt, playItem_t ***out_items) {
LOCK;
int count = plt_getselcount (plt);
if (count == 0) {
UNLOCK;
return 0;
}

playItem_t **items = calloc (count, sizeof (playItem_t *));

int index = 0;
for (playItem_t *item = plt->head[PL_MAIN]; item != NULL; item = item->next[PL_MAIN]) {
if (item->selected) {
items[index++] = item;
pl_item_ref (item);
}
}

UNLOCK;

*out_items = items;
return count;
}
3 changes: 3 additions & 0 deletions src/playlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,9 @@ pl_set_shufflerating (playItem_t *it, int rating);
int
pl_items_from_same_album(playItem_t* a, playItem_t* b);

size_t
plt_get_selected_items(playlist_t *plt, playItem_t ***out_items);

#ifdef __cplusplus
}
#endif
Expand Down
1 change: 1 addition & 0 deletions src/plugins.c
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ static DB_functions_t deadbeef_api = {
.plt_move_all_items = (void (*) (ddb_playlist_t *to, ddb_playlist_t *from, ddb_playItem_t *insert_after))plt_move_all_items,
.undo_process = _undo_process,
.register_for_undo = _register_for_undo,
.plt_get_selected_items = (size_t (*) (ddb_playlist_t *plt, ddb_playItem_t ***out_items))plt_get_selected_items,
};

DB_functions_t *deadbeef = &deadbeef_api;
Expand Down

0 comments on commit 0148608

Please sign in to comment.