Skip to content

Commit 13658dc

Browse files
Perform plugin actions via command line
1 parent e619837 commit 13658dc

6 files changed

Lines changed: 300 additions & 4 deletions

File tree

osx/deadbeef.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,10 @@
943943
2D2C515A2B6BE15900EAC44E /* undostack.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D2C51572B6BE15800EAC44E /* undostack.h */; };
944944
2D2C515B2B6BE15900EAC44E /* undostack.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D2C51582B6BE15900EAC44E /* undostack.c */; };
945945
2D2C515C2B6BE15900EAC44E /* undostack.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D2C51582B6BE15900EAC44E /* undostack.c */; };
946+
2D2F47072F689551000EF7EF /* actionhelp.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D2F47062F689551000EF7EF /* actionhelp.c */; };
947+
2D2F47082F689551000EF7EF /* actionhelp.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D2F47052F689551000EF7EF /* actionhelp.h */; };
948+
2D2F47092F689551000EF7EF /* actionhelp.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D2F47052F689551000EF7EF /* actionhelp.h */; };
949+
2D2F470A2F689551000EF7EF /* actionhelp.c in Sources */ = {isa = PBXBuildFile; fileRef = 2D2F47062F689551000EF7EF /* actionhelp.c */; };
946950
2D30D0B425E2A5DD0023A299 /* DesignModeState.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D30D0B225E2A5DD0023A299 /* DesignModeState.h */; };
947951
2D30D0B525E2A5DD0023A299 /* DesignModeState.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D30D0B325E2A5DD0023A299 /* DesignModeState.m */; };
948952
2D30D20C25E2A8930023A299 /* WidgetTopLevelView.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D30D20A25E2A8930023A299 /* WidgetTopLevelView.h */; };
@@ -5757,6 +5761,8 @@
57575761
2D2A14F019B64F2900AD1EB7 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
57585762
2D2C51572B6BE15800EAC44E /* undostack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = undostack.h; sourceTree = "<group>"; };
57595763
2D2C51582B6BE15900EAC44E /* undostack.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = undostack.c; sourceTree = "<group>"; };
5764+
2D2F47052F689551000EF7EF /* actionhelp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = actionhelp.h; sourceTree = "<group>"; };
5765+
2D2F47062F689551000EF7EF /* actionhelp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = actionhelp.c; sourceTree = "<group>"; };
57605766
2D30D0B225E2A5DD0023A299 /* DesignModeState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DesignModeState.h; sourceTree = "<group>"; };
57615767
2D30D0B325E2A5DD0023A299 /* DesignModeState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DesignModeState.m; sourceTree = "<group>"; };
57625768
2D30D20A25E2A8930023A299 /* WidgetTopLevelView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WidgetTopLevelView.h; sourceTree = "<group>"; };
@@ -11225,6 +11231,8 @@
1122511231
2D7387D329BE5DA1003E3126 /* undo */,
1122611232
2D0212FA2DA0793600BAEA12 /* actionhandlers.h */,
1122711233
2D0212FB2DA0793600BAEA12 /* actionhandlers.c */,
11234+
2D2F47052F689551000EF7EF /* actionhelp.h */,
11235+
2D2F47062F689551000EF7EF /* actionhelp.c */,
1122811236
2D1E1D8427AD9B25004DEF1D /* buffered_file_writer.h */,
1122911237
2D1E1D8527AD9B25004DEF1D /* buffered_file_writer.c */,
1123011238
2DD9EF0419A5089F00189344 /* cocoautil.h */,
@@ -13848,6 +13856,7 @@
1384813856
2DDD76C925E152BF00FA6FE5 /* DesignModeDefs.h in Headers */,
1384913857
2D4020901F27BD7200D4EA4F /* cueutil.h in Headers */,
1385013858
2D30D20D25E2A8930023A299 /* WidgetTopLevelView.h in Headers */,
13859+
2D2F47082F689551000EF7EF /* actionhelp.h in Headers */,
1385113860
2DC657EB274A605E00583E14 /* PlaylistBrowserViewController.h in Headers */,
1385213861
2DC657D52749581900583E14 /* DdbTabStripViewController.h in Headers */,
1385313862
2DC657CD2749544000583E14 /* PlaylistWithTabsWidget.h in Headers */,
@@ -15327,6 +15336,7 @@
1532715336
2D9793E9276E88140062585E /* gobjcache.h in Headers */,
1532815337
2DC657BF2746F67600583E14 /* RenameTabViewController.h in Headers */,
1532915338
2D828E5B19E56B4D00EE874F /* SearchViewController.h in Headers */,
15339+
2D2F47092F689551000EF7EF /* actionhelp.h in Headers */,
1533015340
2DD3775127412EDA007AD315 /* SpectrumAnalyzerPreferencesViewController.h in Headers */,
1533115341
2DD886562B70D83B000434FB /* KeyboardShortcutTextField.h in Headers */,
1533215342
2DC657A72746D9E400583E14 /* TabsWidget.h in Headers */,
@@ -17553,6 +17563,7 @@
1755317563
2D01D7E51AB2219C00BCD3C4 /* vfs.c in Sources */,
1755417564
2D7387EB29BE5DA2003E3126 /* undo_playlist.c in Sources */,
1755517565
2D7387EA29BE5DA2003E3126 /* undobuffer.c in Sources */,
17566+
2D2F47072F689551000EF7EF /* actionhelp.c in Sources */,
1755617567
2D40208F1F27BD7200D4EA4F /* cueutil.c in Sources */,
1755717568
2D7DE4A51E64CD7700AA0F83 /* streamreader.c in Sources */,
1755817569
2D92D33D29B9324A00218F1D /* tftintutil.c in Sources */,
@@ -19093,6 +19104,7 @@
1909319104
2D9C0C26238DC2C100CE8C10 /* GroupByCustomWindowController.m in Sources */,
1909419105
2D92D33B29B9323600218F1D /* scope.c in Sources */,
1909519106
2DC6582A274AB03800583E14 /* LyricsViewController.m in Sources */,
19107+
2D2F470A2F689551000EF7EF /* actionhelp.c in Sources */,
1909619108
2DD062D12EC13F61006F3223 /* AddNewFieldWindowController.m in Sources */,
1909719109
2D95F72A293BB295002D8499 /* DdbUndoBufferRetainer.m in Sources */,
1909819110
2D04701625E2D97D00F68459 /* WidgetMenuBuilder.m in Sources */,

shortlicense.zlib

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
DeaDBeeF -- the music player
3-
Copyright (C) 2009-2025 Oleksiy Yakovenko and other contributors
3+
Copyright (C) 2009-2026 Oleksiy Yakovenko and other contributors
44

55
This software is provided 'as-is', without any express or implied
66
warranty. In no event will the authors be held liable for any damages

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ bin_PROGRAMS = deadbeef
22

33
deadbeef_SOURCES =\
44
actionhandlers.c actionhandlers.h\
5+
actionhelp.c actionhelp.h\
56
buffered_file_writer.c buffered_file_writer.h\
67
coreplugin.c coreplugin.h\
78
conf.c conf.h\

src/actionhelp.c

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
DeaDBeeF -- the music player
3+
Copyright (C) 2009-2026 Oleksiy Yakovenko and other contributors
4+
5+
This software is provided 'as-is', without any express or implied
6+
warranty. In no event will the authors be held liable for any damages
7+
arising from the use of this software.
8+
9+
Permission is granted to anyone to use this software for any purpose,
10+
including commercial applications, and to alter it and redistribute it
11+
freely, subject to the following restrictions:
12+
13+
1. The origin of this software must not be misrepresented; you must not
14+
claim that you wrote the original software. If you use this software
15+
in a product, an acknowledgment in the product documentation would be
16+
appreciated but is not required.
17+
18+
2. Altered source versions must be plainly marked as such, and must not be
19+
misrepresented as being the original software.
20+
21+
3. This notice may not be removed or altered from any source distribution.
22+
*/
23+
24+
#include <stdio.h>
25+
#include <stdlib.h>
26+
#include <string.h>
27+
#include <deadbeef/deadbeef.h>
28+
#include "plugins.h"
29+
#include "actionhelp.h"
30+
#include "gettext.h"
31+
32+
static int
33+
action_alphasort(const void *a, const void *b)
34+
{
35+
const DB_plugin_action_t *A = *(DB_plugin_action_t **)a;
36+
const DB_plugin_action_t *B = *(DB_plugin_action_t **)b;
37+
return strcmp(A->title, B->title);
38+
}
39+
40+
char *
41+
build_actions_string(void) {
42+
DB_plugin_t **plugins = plug_get_list();
43+
44+
const int MAX_DEPTH = 32;
45+
const int NAME_COLUMN = 40;
46+
const int INITIAL_BUF = 4096;
47+
48+
/* ---------- dynamic buffer ---------- */
49+
size_t buf_capacity = INITIAL_BUF;
50+
size_t buf_len = 0;
51+
char *buf = malloc(buf_capacity);
52+
if (!buf) {
53+
return NULL;
54+
}
55+
buf[0] = 0;
56+
57+
/* ---------- helper to append to buffer ---------- */
58+
#define APPEND(...) do { \
59+
int needed = snprintf(NULL, 0, __VA_ARGS__); \
60+
if (buf_len + needed + 1 > buf_capacity) { \
61+
buf_capacity = (buf_len + needed + 1) * 2; \
62+
buf = realloc(buf, buf_capacity); \
63+
} \
64+
buf_len += snprintf(buf + buf_len, buf_capacity - buf_len, __VA_ARGS__); \
65+
} while(0)
66+
67+
/* ---------- header ---------- */
68+
APPEND("\n");
69+
APPEND(_("List of all actions.\n"));
70+
APPEND(_("Perform actions using \"--action=NAME\" command line argument.\n\n"));
71+
APPEND(_("Title"));
72+
int header_pos = 5;
73+
for (int i = header_pos; i < NAME_COLUMN; i++) {
74+
APPEND(" ");
75+
}
76+
APPEND("| ");
77+
APPEND(_("Name"));
78+
APPEND("\n");
79+
80+
/* ---------- full-width divider ---------- */
81+
int total_width = NAME_COLUMN + 40; // approximate total width
82+
for (int i = 0; i < total_width; i++) {
83+
APPEND(i == NAME_COLUMN ? "|" : "-");
84+
}
85+
APPEND("\n");
86+
87+
/* ---------- collect actions ---------- */
88+
int capacity = 64, count = 0;
89+
DB_plugin_action_t **list = malloc(sizeof(DB_plugin_action_t *) * capacity);
90+
if (!list) {
91+
free(buf);
92+
return NULL;
93+
}
94+
95+
for (int pi = 0; plugins[pi] != NULL; pi++) {
96+
DB_plugin_t *plugin = plugins[pi];
97+
if (!plugin->get_actions) {
98+
continue;
99+
}
100+
DB_plugin_action_t *action = plugin->get_actions(NULL);
101+
while (action) {
102+
if (count == capacity) {
103+
capacity *= 2;
104+
list = realloc(list, sizeof(DB_plugin_action_t*) * capacity);
105+
}
106+
list[count++] = action;
107+
action = action->next;
108+
}
109+
}
110+
111+
if (count == 0) {
112+
free(list);
113+
return buf;
114+
}
115+
116+
/* ---------- sort ---------- */
117+
qsort(list, count, sizeof(DB_plugin_action_t *), action_alphasort);
118+
119+
/* ---------- tree printing ---------- */
120+
char prev_parts[MAX_DEPTH][256];
121+
int prev_depth = 0;
122+
123+
for (int ai = 0; ai < count; ai++) {
124+
const char *src = list[ai]->title;
125+
char parts[MAX_DEPTH][256];
126+
int depth = 0;
127+
128+
/* split path handling escaped \/ */
129+
while (*src && depth < MAX_DEPTH) {
130+
int idx = 0;
131+
while (*src) {
132+
if (src[0] == '\\' && src[1] == '/') {
133+
parts[depth][idx++] = '/';
134+
src += 2;
135+
continue;
136+
}
137+
if (*src == '/') {
138+
break;
139+
}
140+
parts[depth][idx++] = *src++;
141+
}
142+
parts[depth][idx] = 0;
143+
depth++;
144+
if (*src == '/') {
145+
src++;
146+
}
147+
else {
148+
break;
149+
}
150+
}
151+
152+
int shared = 0;
153+
while (shared < depth
154+
&& shared < prev_depth
155+
&& strcmp(parts[shared], prev_parts[shared]) == 0) {
156+
shared++;
157+
}
158+
159+
for (int level = shared; level < depth; level++) {
160+
int indent = level * 4;
161+
for (int i = 0; i < indent; i++) {
162+
APPEND(" ");
163+
}
164+
APPEND("%s", parts[level]);
165+
int current_pos = indent + (int)strlen(parts[level]);
166+
if (level == depth - 1) {
167+
if (current_pos < NAME_COLUMN) {
168+
for (int i = current_pos; i < NAME_COLUMN; i++) {
169+
APPEND(" ");
170+
}
171+
} else {
172+
APPEND(" ");
173+
}
174+
APPEND("| %s", list[ai]->name);
175+
}
176+
APPEND("\n");
177+
strcpy(prev_parts[level], parts[level]);
178+
}
179+
prev_depth = depth;
180+
}
181+
182+
free(list);
183+
return buf;
184+
185+
#undef APPEND
186+
}
187+

src/actionhelp.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
DeaDBeeF -- the music player
3+
Copyright (C) 2009-2026 Oleksiy Yakovenko and other contributors
4+
5+
This software is provided 'as-is', without any express or implied
6+
warranty. In no event will the authors be held liable for any damages
7+
arising from the use of this software.
8+
9+
Permission is granted to anyone to use this software for any purpose,
10+
including commercial applications, and to alter it and redistribute it
11+
freely, subject to the following restrictions:
12+
13+
1. The origin of this software must not be misrepresented; you must not
14+
claim that you wrote the original software. If you use this software
15+
in a product, an acknowledgment in the product documentation would be
16+
appreciated but is not required.
17+
18+
2. Altered source versions must be plainly marked as such, and must not be
19+
misrepresented as being the original software.
20+
21+
3. This notice may not be removed or altered from any source distribution.
22+
*/
23+
24+
#ifndef actionhelp_h
25+
#define actionhelp_h
26+
27+
char *
28+
build_actions_string (void);
29+
30+
#endif /* actionhelp_h */

0 commit comments

Comments
 (0)