Configured and ran clang-format on src files

This commit is contained in:
Andrew Carr 2021-05-23 04:09:25 +00:00
parent b35e705066
commit 9a0cf4a43b
9 changed files with 441 additions and 292 deletions

168
.clang-format Normal file
View File

@ -0,0 +1,168 @@
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: true
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: true
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
SortPriority: 0
- Regex: '^<.*\.h>'
Priority: 1
SortPriority: 0
- Regex: '^<.*'
Priority: 2
SortPriority: 0
- Regex: '.*'
Priority: 3
SortPriority: 0
IncludeIsMainRegex: '([-_](test|unittest))?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: true
IndentGotoLabels: true
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Auto
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false
UseTab: Never
...

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# Build Artifacts
build/

View File

@ -10,4 +10,23 @@ Manual Usage:
> npx prettier --write . > npx prettier --write .
``` ```
The C source and header files have been formatted with `clang-format`. The C source and header files have been formatted with `clang-format`. There's no easy way to manually execute the formatter on all of the C files at the same time. The clang format is based off of the 'Google' style with ajdustments to make the changes not as disruptive. See [.clang-format](./.clang-format) file for the formatting rules. Various editors should be able to automatically format the source on save.
The only files formatted are the non-third party library files.
Manual Usage:
```bash
> clang-format -i -style=file <filename>
```
Manually formatted files:
- http_server.c
- http_server.h
- json_encode.h
- mpd_client.c
- mpd_client.h
- ympd.c
For help with the rules, see [Clang Format Configurator](https://zed0.co.uk/clang-format-configurator/) for an interactive tool and [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) for the rules reference.

View File

@ -1,7 +1,7 @@
/* ympd /* ympd
(c) 2013-2014 Andrew Karpow <andy@ndyk.de> (c) 2013-2014 Andrew Karpow <andy@ndyk.de>
This project's homepage is: http://www.ympd.org This project's homepage is: http://www.ympd.org
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. the Free Software Foundation; version 2 of the License.
@ -16,24 +16,22 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <string.h>
#include "http_server.h" #include "http_server.h"
int callback_http(struct mg_connection *c) #include <string.h>
{
int callback_http(struct mg_connection *c) {
const struct embedded_file *req_file; const struct embedded_file *req_file;
if(!strcmp(c->uri, "/")) if (!strcmp(c->uri, "/"))
req_file = find_embedded_file("/index.html"); req_file = find_embedded_file("/index.html");
else else
req_file = find_embedded_file(c->uri); req_file = find_embedded_file(c->uri);
if(req_file) if (req_file) {
{
mg_send_header(c, "Content-Type", req_file->mimetype); mg_send_header(c, "Content-Type", req_file->mimetype);
mg_send_data(c, req_file->data, req_file->size); mg_send_data(c, req_file->data, req_file->size);
return MG_TRUE; return MG_TRUE;
} }

View File

@ -1,7 +1,7 @@
/* ympd /* ympd
(c) 2013-2014 Andrew Karpow <andy@ndyk.de> (c) 2013-2014 Andrew Karpow <andy@ndyk.de>
This project's homepage is: http://www.ympd.org This project's homepage is: http://www.ympd.org
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. the Free Software Foundation; version 2 of the License.
@ -22,14 +22,13 @@
#include "mongoose.h" #include "mongoose.h"
struct embedded_file { struct embedded_file {
const char *name; const char *name;
const unsigned char *data; const unsigned char *data;
const char *mimetype; const char *mimetype;
size_t size; size_t size;
}; };
const struct embedded_file *find_embedded_file(const char *name); const struct embedded_file *find_embedded_file(const char *name);
int callback_http(struct mg_connection *c); int callback_http(struct mg_connection *c);
#endif #endif

View File

@ -1,7 +1,7 @@
/* ympd /* ympd
(c) 2013-2014 Andrew Karpow <andy@ndyk.de> (c) 2013-2014 Andrew Karpow <andy@ndyk.de>
This project's homepage is: http://www.ympd.org This project's homepage is: http://www.ympd.org
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. the Free Software Foundation; version 2 of the License.
@ -15,7 +15,7 @@
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#ifndef __JSON_ENCODE_H__ #ifndef __JSON_ENCODE_H__
#define __JSON_ENCODE_H__ #define __JSON_ENCODE_H__

View File

@ -1,7 +1,7 @@
/* ympd /* ympd
(c) 2013-2014 Andrew Karpow <andy@ndyk.de> (c) 2013-2014 Andrew Karpow <andy@ndyk.de>
This project's homepage is: http://www.ympd.org This project's homepage is: http://www.ympd.org
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. the Free Software Foundation; version 2 of the License.
@ -16,15 +16,16 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <stdio.h> #include "mpd_client.h"
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <libgen.h> #include <libgen.h>
#include <mpd/client.h> #include <mpd/client.h>
#include <mpd/message.h> #include <mpd/message.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "mpd_client.h"
#include "config.h" #include "config.h"
#include "json_encode.h" #include "json_encode.h"
@ -32,44 +33,39 @@
static int mpd_notify_callback(struct mg_connection *c, enum mg_event ev); static int mpd_notify_callback(struct mg_connection *c, enum mg_event ev);
struct t_mpd mpd; struct t_mpd mpd;
const char * mpd_cmd_strs[] = { const char *mpd_cmd_strs[] = {MPD_CMDS(GEN_STR)};
MPD_CMDS(GEN_STR)
};
char * get_arg1 (char *p) { char *get_arg1(char *p) {
return strchr(p, ',') + 1; return strchr(p, ',') + 1;
} }
char * get_arg2 (char *p) { char *get_arg2(char *p) {
return get_arg1(get_arg1(p)); return get_arg1(get_arg1(p));
} }
static inline enum mpd_cmd_ids get_cmd_id(char *cmd) static inline enum mpd_cmd_ids get_cmd_id(char *cmd) {
{ for (int i = 0; i < sizeof(mpd_cmd_strs) / sizeof(mpd_cmd_strs[0]); i++)
for(int i = 0; i < sizeof(mpd_cmd_strs)/sizeof(mpd_cmd_strs[0]); i++) if (!strncmp(cmd, mpd_cmd_strs[i], strlen(mpd_cmd_strs[i])))
if(!strncmp(cmd, mpd_cmd_strs[i], strlen(mpd_cmd_strs[i])))
return i; return i;
return -1; return -1;
} }
int callback_mpd(struct mg_connection *c) int callback_mpd(struct mg_connection *c) {
{
enum mpd_cmd_ids cmd_id = get_cmd_id(c->content); enum mpd_cmd_ids cmd_id = get_cmd_id(c->content);
size_t n = 0; size_t n = 0;
unsigned int uint_buf, uint_buf_2; unsigned int uint_buf, uint_buf_2;
int int_buf; int int_buf;
char *p_charbuf = NULL, *token; char *p_charbuf = NULL, *token;
if(cmd_id == -1) if (cmd_id == -1)
return MG_TRUE; return MG_TRUE;
if(mpd.conn_state != MPD_CONNECTED && cmd_id != MPD_API_SET_MPDHOST && if (mpd.conn_state != MPD_CONNECTED && cmd_id != MPD_API_SET_MPDHOST &&
cmd_id != MPD_API_GET_MPDHOST && cmd_id != MPD_API_SET_MPDPASS) cmd_id != MPD_API_GET_MPDHOST && cmd_id != MPD_API_SET_MPDPASS)
return MG_TRUE; return MG_TRUE;
switch(cmd_id) switch (cmd_id) {
{
case MPD_API_UPDATE_DB: case MPD_API_UPDATE_DB:
mpd_run_update(mpd.conn, NULL); mpd_run_update(mpd.conn, NULL);
break; break;
@ -92,43 +88,42 @@ int callback_mpd(struct mg_connection *c)
mpd_run_clear(mpd.conn); mpd_run_clear(mpd.conn);
break; break;
case MPD_API_RM_TRACK: case MPD_API_RM_TRACK:
if(sscanf(c->content, "MPD_API_RM_TRACK,%u", &uint_buf)) if (sscanf(c->content, "MPD_API_RM_TRACK,%u", &uint_buf))
mpd_run_delete_id(mpd.conn, uint_buf); mpd_run_delete_id(mpd.conn, uint_buf);
break; break;
case MPD_API_RM_RANGE: case MPD_API_RM_RANGE:
if(sscanf(c->content, "MPD_API_RM_RANGE,%u,%u", &uint_buf, &uint_buf_2)) if (sscanf(c->content, "MPD_API_RM_RANGE,%u,%u", &uint_buf, &uint_buf_2))
mpd_run_delete_range(mpd.conn, uint_buf, uint_buf_2); mpd_run_delete_range(mpd.conn, uint_buf, uint_buf_2);
break; break;
case MPD_API_MOVE_TRACK: case MPD_API_MOVE_TRACK:
if (sscanf(c->content, "MPD_API_MOVE_TRACK,%u,%u", &uint_buf, &uint_buf_2) == 2) if (sscanf(c->content, "MPD_API_MOVE_TRACK,%u,%u", &uint_buf, &uint_buf_2) == 2) {
{
uint_buf -= 1; uint_buf -= 1;
uint_buf_2 -= 1; uint_buf_2 -= 1;
mpd_run_move(mpd.conn, uint_buf, uint_buf_2); mpd_run_move(mpd.conn, uint_buf, uint_buf_2);
} }
break; break;
case MPD_API_PLAY_TRACK: case MPD_API_PLAY_TRACK:
if(sscanf(c->content, "MPD_API_PLAY_TRACK,%u", &uint_buf)) if (sscanf(c->content, "MPD_API_PLAY_TRACK,%u", &uint_buf))
mpd_run_play_id(mpd.conn, uint_buf); mpd_run_play_id(mpd.conn, uint_buf);
break; break;
case MPD_API_TOGGLE_RANDOM: case MPD_API_TOGGLE_RANDOM:
if(sscanf(c->content, "MPD_API_TOGGLE_RANDOM,%u", &uint_buf)) if (sscanf(c->content, "MPD_API_TOGGLE_RANDOM,%u", &uint_buf))
mpd_run_random(mpd.conn, uint_buf); mpd_run_random(mpd.conn, uint_buf);
break; break;
case MPD_API_TOGGLE_REPEAT: case MPD_API_TOGGLE_REPEAT:
if(sscanf(c->content, "MPD_API_TOGGLE_REPEAT,%u", &uint_buf)) if (sscanf(c->content, "MPD_API_TOGGLE_REPEAT,%u", &uint_buf))
mpd_run_repeat(mpd.conn, uint_buf); mpd_run_repeat(mpd.conn, uint_buf);
break; break;
case MPD_API_TOGGLE_CONSUME: case MPD_API_TOGGLE_CONSUME:
if(sscanf(c->content, "MPD_API_TOGGLE_CONSUME,%u", &uint_buf)) if (sscanf(c->content, "MPD_API_TOGGLE_CONSUME,%u", &uint_buf))
mpd_run_consume(mpd.conn, uint_buf); mpd_run_consume(mpd.conn, uint_buf);
break; break;
case MPD_API_TOGGLE_SINGLE: case MPD_API_TOGGLE_SINGLE:
if(sscanf(c->content, "MPD_API_TOGGLE_SINGLE,%u", &uint_buf)) if (sscanf(c->content, "MPD_API_TOGGLE_SINGLE,%u", &uint_buf))
mpd_run_single(mpd.conn, uint_buf); mpd_run_single(mpd.conn, uint_buf);
break; break;
case MPD_API_TOGGLE_CROSSFADE: case MPD_API_TOGGLE_CROSSFADE:
if(sscanf(c->content, "MPD_API_TOGGLE_CROSSFADE,%u", &uint_buf)) if (sscanf(c->content, "MPD_API_TOGGLE_CROSSFADE,%u", &uint_buf))
mpd_run_crossfade(mpd.conn, uint_buf); mpd_run_crossfade(mpd.conn, uint_buf);
break; break;
case MPD_API_GET_OUTPUTS: case MPD_API_GET_OUTPUTS:
@ -145,123 +140,123 @@ int callback_mpd(struct mg_connection *c)
} }
break; break;
case MPD_API_SET_VOLUME: case MPD_API_SET_VOLUME:
if(sscanf(c->content, "MPD_API_SET_VOLUME,%ud", &uint_buf) && uint_buf <= 100) if (sscanf(c->content, "MPD_API_SET_VOLUME,%ud", &uint_buf) && uint_buf <= 100)
mpd_run_set_volume(mpd.conn, uint_buf); mpd_run_set_volume(mpd.conn, uint_buf);
break; break;
case MPD_API_SET_SEEK: case MPD_API_SET_SEEK:
if(sscanf(c->content, "MPD_API_SET_SEEK,%u,%u", &uint_buf, &uint_buf_2)) if (sscanf(c->content, "MPD_API_SET_SEEK,%u,%u", &uint_buf, &uint_buf_2))
mpd_run_seek_id(mpd.conn, uint_buf, uint_buf_2); mpd_run_seek_id(mpd.conn, uint_buf, uint_buf_2);
break; break;
case MPD_API_GET_QUEUE: case MPD_API_GET_QUEUE:
if(sscanf(c->content, "MPD_API_GET_QUEUE,%u", &uint_buf)) if (sscanf(c->content, "MPD_API_GET_QUEUE,%u", &uint_buf))
n = mpd_put_queue(mpd.buf, uint_buf); n = mpd_put_queue(mpd.buf, uint_buf);
break; break;
case MPD_API_GET_BROWSE: case MPD_API_GET_BROWSE:
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_GET_BROWSE")) if (strcmp(strtok(p_charbuf, ","), "MPD_API_GET_BROWSE"))
goto out_browse; goto out_browse;
uint_buf = strtoul(strtok(NULL, ","), NULL, 10); uint_buf = strtoul(strtok(NULL, ","), NULL, 10);
if((token = strtok(NULL, ",")) == NULL) if ((token = strtok(NULL, ",")) == NULL)
goto out_browse; goto out_browse;
free(p_charbuf); free(p_charbuf);
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
n = mpd_put_browse(mpd.buf, get_arg2(p_charbuf), uint_buf); n = mpd_put_browse(mpd.buf, get_arg2(p_charbuf), uint_buf);
out_browse: out_browse:
free(p_charbuf); free(p_charbuf);
break; break;
case MPD_API_ADD_TRACK: case MPD_API_ADD_TRACK:
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_TRACK")) if (strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_TRACK"))
goto out_add_track; goto out_add_track;
if((token = strtok(NULL, ",")) == NULL) if ((token = strtok(NULL, ",")) == NULL)
goto out_add_track; goto out_add_track;
free(p_charbuf); free(p_charbuf);
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
mpd_run_add(mpd.conn, get_arg1(p_charbuf)); mpd_run_add(mpd.conn, get_arg1(p_charbuf));
out_add_track: out_add_track:
free(p_charbuf); free(p_charbuf);
break; break;
case MPD_API_ADD_PLAY_TRACK: case MPD_API_ADD_PLAY_TRACK:
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_PLAY_TRACK")) if (strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_PLAY_TRACK"))
goto out_play_track; goto out_play_track;
if((token = strtok(NULL, ",")) == NULL) if ((token = strtok(NULL, ",")) == NULL)
goto out_play_track; goto out_play_track;
free(p_charbuf); free(p_charbuf);
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
int_buf = mpd_run_add_id(mpd.conn, get_arg1(p_charbuf)); int_buf = mpd_run_add_id(mpd.conn, get_arg1(p_charbuf));
if(int_buf != -1) if (int_buf != -1)
mpd_run_play_id(mpd.conn, int_buf); mpd_run_play_id(mpd.conn, int_buf);
out_play_track: out_play_track:
free(p_charbuf); free(p_charbuf);
break; break;
case MPD_API_ADD_PLAYLIST: case MPD_API_ADD_PLAYLIST:
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_PLAYLIST")) if (strcmp(strtok(p_charbuf, ","), "MPD_API_ADD_PLAYLIST"))
goto out_playlist; goto out_playlist;
if((token = strtok(NULL, ",")) == NULL) if ((token = strtok(NULL, ",")) == NULL)
goto out_playlist; goto out_playlist;
free(p_charbuf); free(p_charbuf);
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
mpd_run_load(mpd.conn, get_arg1(p_charbuf)); mpd_run_load(mpd.conn, get_arg1(p_charbuf));
out_playlist: out_playlist:
free(p_charbuf); free(p_charbuf);
break; break;
case MPD_API_SAVE_QUEUE: case MPD_API_SAVE_QUEUE:
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_SAVE_QUEUE")) if (strcmp(strtok(p_charbuf, ","), "MPD_API_SAVE_QUEUE"))
goto out_save_queue; goto out_save_queue;
if((token = strtok(NULL, ",")) == NULL) if ((token = strtok(NULL, ",")) == NULL)
goto out_save_queue; goto out_save_queue;
free(p_charbuf); free(p_charbuf);
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
mpd_run_save(mpd.conn, get_arg1(p_charbuf)); mpd_run_save(mpd.conn, get_arg1(p_charbuf));
out_save_queue: out_save_queue:
free(p_charbuf); free(p_charbuf);
break; break;
case MPD_API_SEARCH: case MPD_API_SEARCH:
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_SEARCH")) if (strcmp(strtok(p_charbuf, ","), "MPD_API_SEARCH"))
goto out_search;
if((token = strtok(NULL, ",")) == NULL)
goto out_search; goto out_search;
free(p_charbuf); if ((token = strtok(NULL, ",")) == NULL)
goto out_search;
free(p_charbuf);
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
n = mpd_search(mpd.buf, get_arg1(p_charbuf)); n = mpd_search(mpd.buf, get_arg1(p_charbuf));
out_search: out_search:
free(p_charbuf); free(p_charbuf);
break; break;
case MPD_API_SEND_MESSAGE: case MPD_API_SEND_MESSAGE:
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_SEND_MESSAGE")) if (strcmp(strtok(p_charbuf, ","), "MPD_API_SEND_MESSAGE"))
goto out_send_message;
if((token = strtok(NULL, ",")) == NULL)
goto out_send_message; goto out_send_message;
free(p_charbuf); if ((token = strtok(NULL, ",")) == NULL)
goto out_send_message;
free(p_charbuf);
p_charbuf = strdup(get_arg1(c->content)); p_charbuf = strdup(get_arg1(c->content));
if ( strtok(p_charbuf, ",") == NULL ) if (strtok(p_charbuf, ",") == NULL)
goto out_send_message; goto out_send_message;
if ( (token = strtok(NULL, ",")) == NULL ) if ((token = strtok(NULL, ",")) == NULL)
goto out_send_message; goto out_send_message;
mpd_run_send_message(mpd.conn, p_charbuf, token); mpd_run_send_message(mpd.conn, p_charbuf, token);
out_send_message: out_send_message:
free(p_charbuf); free(p_charbuf);
break; break;
#ifdef WITH_MPD_HOST_CHANGE #ifdef WITH_MPD_HOST_CHANGE
@ -269,13 +264,13 @@ out_send_message:
case MPD_API_SET_MPDHOST: case MPD_API_SET_MPDHOST:
int_buf = 0; int_buf = 0;
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_SET_MPDHOST")) if (strcmp(strtok(p_charbuf, ","), "MPD_API_SET_MPDHOST"))
goto out_host_change; goto out_host_change;
if((int_buf = strtol(strtok(NULL, ","), NULL, 10)) <= 0) if ((int_buf = strtol(strtok(NULL, ","), NULL, 10)) <= 0)
goto out_host_change; goto out_host_change;
if((token = strtok(NULL, ",")) == NULL) if ((token = strtok(NULL, ",")) == NULL)
goto out_host_change; goto out_host_change;
strncpy(mpd.host, token, sizeof(mpd.host)); strncpy(mpd.host, token, sizeof(mpd.host));
@ -283,55 +278,56 @@ out_send_message:
mpd.conn_state = MPD_RECONNECT; mpd.conn_state = MPD_RECONNECT;
free(p_charbuf); free(p_charbuf);
return MG_TRUE; return MG_TRUE;
out_host_change: out_host_change:
free(p_charbuf); free(p_charbuf);
break; break;
case MPD_API_GET_MPDHOST: case MPD_API_GET_MPDHOST:
n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"mpdhost\", \"data\": " n = snprintf(mpd.buf, MAX_SIZE,
"{\"host\" : \"%s\", \"port\": \"%d\", \"passwort_set\": %s}" "{\"type\":\"mpdhost\", \"data\": "
"}", mpd.host, mpd.port, mpd.password ? "true" : "false"); "{\"host\" : \"%s\", \"port\": \"%d\", \"passwort_set\": %s}"
"}",
mpd.host, mpd.port, mpd.password ? "true" : "false");
break; break;
case MPD_API_SET_MPDPASS: case MPD_API_SET_MPDPASS:
p_charbuf = strdup(c->content); p_charbuf = strdup(c->content);
if(strcmp(strtok(p_charbuf, ","), "MPD_API_SET_MPDPASS")) if (strcmp(strtok(p_charbuf, ","), "MPD_API_SET_MPDPASS"))
goto out_set_pass; goto out_set_pass;
if((token = strtok(NULL, ",")) == NULL) if ((token = strtok(NULL, ",")) == NULL)
goto out_set_pass; goto out_set_pass;
if(mpd.password) if (mpd.password)
free(mpd.password); free(mpd.password);
mpd.password = strdup(token); mpd.password = strdup(token);
mpd.conn_state = MPD_RECONNECT; mpd.conn_state = MPD_RECONNECT;
free(p_charbuf); free(p_charbuf);
return MG_TRUE; return MG_TRUE;
out_set_pass: out_set_pass:
free(p_charbuf); free(p_charbuf);
break; break;
#endif #endif
} }
if(mpd.conn_state == MPD_CONNECTED && mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS) if (mpd.conn_state == MPD_CONNECTED &&
{ mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS) {
n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"error\", \"data\": \"%s\"}", n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"error\", \"data\": \"%s\"}",
mpd_connection_get_error_message(mpd.conn)); mpd_connection_get_error_message(mpd.conn));
/* Try to recover error */ /* Try to recover error */
if (!mpd_connection_clear_error(mpd.conn)) if (!mpd_connection_clear_error(mpd.conn))
mpd.conn_state = MPD_FAILURE; mpd.conn_state = MPD_FAILURE;
} }
if(n > 0) if (n > 0)
mg_websocket_write(c, 1, mpd.buf, n); mg_websocket_write(c, 1, mpd.buf, n);
return MG_TRUE; return MG_TRUE;
} }
int mpd_close_handler(struct mg_connection *c) int mpd_close_handler(struct mg_connection *c) {
{
/* Cleanup session data */ /* Cleanup session data */
if(c->connection_param) if (c->connection_param)
free(c->connection_param); free(c->connection_param);
return 0; return 0;
} }
@ -339,41 +335,36 @@ int mpd_close_handler(struct mg_connection *c)
static int mpd_notify_callback(struct mg_connection *c, enum mg_event ev) { static int mpd_notify_callback(struct mg_connection *c, enum mg_event ev) {
size_t n; size_t n;
if(!c->is_websocket) if (!c->is_websocket)
return MG_TRUE; return MG_TRUE;
if(c->callback_param) if (c->callback_param) {
{
/* error message? */ /* error message? */
n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"error\",\"data\":\"%s\"}", n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"error\",\"data\":\"%s\"}",
(const char *)c->callback_param); (const char *)c->callback_param);
mg_websocket_write(c, 1, mpd.buf, n); mg_websocket_write(c, 1, mpd.buf, n);
return MG_TRUE; return MG_TRUE;
} }
if(!c->connection_param) if (!c->connection_param)
c->connection_param = calloc(1, sizeof(struct t_mpd_client_session)); c->connection_param = calloc(1, sizeof(struct t_mpd_client_session));
struct t_mpd_client_session *s = (struct t_mpd_client_session *)c->connection_param; struct t_mpd_client_session *s = (struct t_mpd_client_session *)c->connection_param;
if(mpd.conn_state != MPD_CONNECTED) { if (mpd.conn_state != MPD_CONNECTED) {
n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"disconnected\"}"); n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"disconnected\"}");
mg_websocket_write(c, 1, mpd.buf, n); mg_websocket_write(c, 1, mpd.buf, n);
} } else {
else
{
mg_websocket_write(c, 1, mpd.buf, mpd.buf_size); mg_websocket_write(c, 1, mpd.buf, mpd.buf_size);
if(s->song_id != mpd.song_id) if (s->song_id != mpd.song_id) {
{
n = mpd_put_current_song(mpd.buf); n = mpd_put_current_song(mpd.buf);
mg_websocket_write(c, 1, mpd.buf, n); mg_websocket_write(c, 1, mpd.buf, n);
s->song_id = mpd.song_id; s->song_id = mpd.song_id;
} }
if(s->queue_version != mpd.queue_version) if (s->queue_version != mpd.queue_version) {
{
n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"update_queue\"}"); n = snprintf(mpd.buf, MAX_SIZE, "{\"type\":\"update_queue\"}");
mg_websocket_write(c, 1, mpd.buf, n); mg_websocket_write(c, 1, mpd.buf, n);
s->queue_version = mpd.queue_version; s->queue_version = mpd.queue_version;
@ -383,8 +374,7 @@ static int mpd_notify_callback(struct mg_connection *c, enum mg_event ev) {
return MG_TRUE; return MG_TRUE;
} }
void mpd_poll(struct mg_server *s) void mpd_poll(struct mg_server *s) {
{
switch (mpd.conn_state) { switch (mpd.conn_state) {
case MPD_DISCONNECTED: case MPD_DISCONNECTED:
/* Try to connect */ /* Try to connect */
@ -398,8 +388,7 @@ void mpd_poll(struct mg_server *s)
if (mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS) { if (mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS) {
fprintf(stderr, "MPD connection: %s\n", mpd_connection_get_error_message(mpd.conn)); fprintf(stderr, "MPD connection: %s\n", mpd_connection_get_error_message(mpd.conn));
for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) {
{
c->callback_param = (void *)mpd_connection_get_error_message(mpd.conn); c->callback_param = (void *)mpd_connection_get_error_message(mpd.conn);
mpd_notify_callback(c, MG_POLL); mpd_notify_callback(c, MG_POLL);
} }
@ -407,11 +396,9 @@ void mpd_poll(struct mg_server *s)
return; return;
} }
if(mpd.password && !mpd_run_password(mpd.conn, mpd.password)) if (mpd.password && !mpd_run_password(mpd.conn, mpd.password)) {
{
fprintf(stderr, "MPD connection: %s\n", mpd_connection_get_error_message(mpd.conn)); fprintf(stderr, "MPD connection: %s\n", mpd_connection_get_error_message(mpd.conn));
for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) {
{
c->callback_param = (void *)mpd_connection_get_error_message(mpd.conn); c->callback_param = (void *)mpd_connection_get_error_message(mpd.conn);
mpd_notify_callback(c, MG_POLL); mpd_notify_callback(c, MG_POLL);
} }
@ -424,8 +411,7 @@ void mpd_poll(struct mg_server *s)
mpd.conn_state = MPD_CONNECTED; mpd.conn_state = MPD_CONNECTED;
/* write outputs */ /* write outputs */
mpd.buf_size = mpd_put_outputs(mpd.buf, 1); mpd.buf_size = mpd_put_outputs(mpd.buf, 1);
for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) {
{
c->callback_param = NULL; c->callback_param = NULL;
mpd_notify_callback(c, MG_POLL); mpd_notify_callback(c, MG_POLL);
} }
@ -436,7 +422,7 @@ void mpd_poll(struct mg_server *s)
case MPD_DISCONNECT: case MPD_DISCONNECT:
case MPD_RECONNECT: case MPD_RECONNECT:
if(mpd.conn != NULL) if (mpd.conn != NULL)
mpd_connection_free(mpd.conn); mpd_connection_free(mpd.conn);
mpd.conn = NULL; mpd.conn = NULL;
mpd.conn_state = MPD_DISCONNECTED; mpd.conn_state = MPD_DISCONNECTED;
@ -444,14 +430,12 @@ void mpd_poll(struct mg_server *s)
case MPD_CONNECTED: case MPD_CONNECTED:
mpd.buf_size = mpd_put_state(mpd.buf, &mpd.song_id, &mpd.queue_version); mpd.buf_size = mpd_put_state(mpd.buf, &mpd.song_id, &mpd.queue_version);
for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) {
{
c->callback_param = NULL; c->callback_param = NULL;
mpd_notify_callback(c, MG_POLL); mpd_notify_callback(c, MG_POLL);
} }
mpd.buf_size = mpd_put_outputs(mpd.buf, 0); mpd.buf_size = mpd_put_outputs(mpd.buf, 0);
for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) {
{
c->callback_param = NULL; c->callback_param = NULL;
mpd_notify_callback(c, MG_POLL); mpd_notify_callback(c, MG_POLL);
} }
@ -459,56 +443,51 @@ void mpd_poll(struct mg_server *s)
} }
} }
char* mpd_get_title(struct mpd_song const *song) char *mpd_get_title(struct mpd_song const *song) {
{
char *str; char *str;
str = (char *)mpd_song_get_tag(song, MPD_TAG_TITLE, 0); str = (char *)mpd_song_get_tag(song, MPD_TAG_TITLE, 0);
if(str == NULL){ if (str == NULL) {
str = basename((char *)mpd_song_get_uri(song)); str = basename((char *)mpd_song_get_uri(song));
} }
return str; return str;
} }
char* mpd_get_album(struct mpd_song const *song) char *mpd_get_album(struct mpd_song const *song) {
{
char *str; char *str;
str = (char *)mpd_song_get_tag(song, MPD_TAG_ALBUM, 0); str = (char *)mpd_song_get_tag(song, MPD_TAG_ALBUM, 0);
if(str == NULL){ if (str == NULL) {
str = "-"; str = "-";
} }
return str; return str;
} }
char* mpd_get_artist(struct mpd_song const *song) char *mpd_get_artist(struct mpd_song const *song) {
{
char *str; char *str;
str = (char *)mpd_song_get_tag(song, MPD_TAG_ARTIST, 0); str = (char *)mpd_song_get_tag(song, MPD_TAG_ARTIST, 0);
if(str == NULL){ if (str == NULL) {
str = "-"; str = "-";
} }
return str; return str;
} }
char* mpd_get_year(struct mpd_song const *song) char *mpd_get_year(struct mpd_song const *song) {
{
char *str; char *str;
str = (char *)mpd_song_get_tag(song, MPD_TAG_DATE, 0); str = (char *)mpd_song_get_tag(song, MPD_TAG_DATE, 0);
if(str == NULL){ if (str == NULL) {
str = "-"; str = "-";
} }
return str; return str;
} }
int mpd_put_state(char *buffer, int *current_song_id, unsigned *queue_version) int mpd_put_state(char *buffer, int *current_song_id, unsigned *queue_version) {
{
struct mpd_status *status; struct mpd_status *status;
int len; int len;
@ -520,23 +499,18 @@ int mpd_put_state(char *buffer, int *current_song_id, unsigned *queue_version)
} }
len = snprintf(buffer, MAX_SIZE, len = snprintf(buffer, MAX_SIZE,
"{\"type\":\"state\", \"data\":{" "{\"type\":\"state\", \"data\":{"
" \"state\":%d, \"volume\":%d, \"repeat\":%d," " \"state\":%d, \"volume\":%d, \"repeat\":%d,"
" \"single\":%d, \"crossfade\":%d, \"consume\":%d, \"random\":%d, " " \"single\":%d, \"crossfade\":%d, \"consume\":%d, \"random\":%d, "
" \"songpos\": %d, \"elapsedTime\": %d, \"totalTime\":%d, " " \"songpos\": %d, \"elapsedTime\": %d, \"totalTime\":%d, "
" \"currentsongid\": %d" " \"currentsongid\": %d"
"}}", "}}",
mpd_status_get_state(status), mpd_status_get_state(status), mpd_status_get_volume(status),
mpd_status_get_volume(status), mpd_status_get_repeat(status), mpd_status_get_single(status),
mpd_status_get_repeat(status), mpd_status_get_crossfade(status), mpd_status_get_consume(status),
mpd_status_get_single(status), mpd_status_get_random(status), mpd_status_get_song_pos(status),
mpd_status_get_crossfade(status), mpd_status_get_elapsed_time(status), mpd_status_get_total_time(status),
mpd_status_get_consume(status), mpd_status_get_song_id(status));
mpd_status_get_random(status),
mpd_status_get_song_pos(status),
mpd_status_get_elapsed_time(status),
mpd_status_get_total_time(status),
mpd_status_get_song_id(status));
*current_song_id = mpd_status_get_song_id(status); *current_song_id = mpd_status_get_song_id(status);
*queue_version = mpd_status_get_queue_version(status); *queue_version = mpd_status_get_queue_version(status);
@ -544,16 +518,15 @@ int mpd_put_state(char *buffer, int *current_song_id, unsigned *queue_version)
return len; return len;
} }
int mpd_put_outputs(char *buffer, int names) int mpd_put_outputs(char *buffer, int names) {
{
struct mpd_output *out; struct mpd_output *out;
int nout; int nout;
char *str, *strend; char *str, *strend;
str = buffer; str = buffer;
strend = buffer+MAX_SIZE; strend = buffer + MAX_SIZE;
str += snprintf(str, strend-str, "{\"type\":\"%s\", \"data\":{", str += snprintf(str, strend - str, "{\"type\":\"%s\", \"data\":{",
names ? "outputnames" : "outputs"); names ? "outputnames" : "outputs");
mpd_send_outputs(mpd.conn); mpd_send_outputs(mpd.conn);
nout = 0; nout = 0;
@ -561,11 +534,11 @@ int mpd_put_outputs(char *buffer, int names)
if (nout++) if (nout++)
*str++ = ','; *str++ = ',';
if (names) if (names)
str += snprintf(str, strend - str, " \"%d\":\"%s\"", str += snprintf(str, strend - str, " \"%d\":\"%s\"", mpd_output_get_id(out),
mpd_output_get_id(out), mpd_output_get_name(out)); mpd_output_get_name(out));
else else
str += snprintf(str, strend-str, " \"%d\":%d", str += snprintf(str, strend - str, " \"%d\":%d", mpd_output_get_id(out),
mpd_output_get_id(out), mpd_output_get_enabled(out)); mpd_output_get_enabled(out));
mpd_output_free(out); mpd_output_free(out);
} }
if (!mpd_response_finish(mpd.conn)) { if (!mpd_response_finish(mpd.conn)) {
@ -573,18 +546,17 @@ int mpd_put_outputs(char *buffer, int names)
mpd_connection_clear_error(mpd.conn); mpd_connection_clear_error(mpd.conn);
return 0; return 0;
} }
str += snprintf(str, strend-str, " }}"); str += snprintf(str, strend - str, " }}");
return str-buffer; return str - buffer;
} }
int mpd_put_current_song(char *buffer) int mpd_put_current_song(char *buffer) {
{
char *cur = buffer; char *cur = buffer;
const char *end = buffer + MAX_SIZE; const char *end = buffer + MAX_SIZE;
struct mpd_song *song; struct mpd_song *song;
song = mpd_run_current_song(mpd.conn); song = mpd_run_current_song(mpd.conn);
if(song == NULL) if (song == NULL)
return 0; return 0;
cur += json_emit_raw_str(cur, end - cur, "{\"type\": \"song_change\", \"data\":{\"pos\":"); cur += json_emit_raw_str(cur, end - cur, "{\"type\": \"song_change\", \"data\":{\"pos\":");
@ -603,23 +575,22 @@ int mpd_put_current_song(char *buffer)
return cur - buffer; return cur - buffer;
} }
int mpd_put_queue(char *buffer, unsigned int offset) int mpd_put_queue(char *buffer, unsigned int offset) {
{
char *cur = buffer; char *cur = buffer;
const char *end = buffer + MAX_SIZE; const char *end = buffer + MAX_SIZE;
struct mpd_entity *entity; struct mpd_entity *entity;
unsigned long totalTime = 0; unsigned long totalTime = 0;
if (!mpd_send_list_queue_range_meta(mpd.conn, offset, offset+MAX_ELEMENTS_PER_PAGE)) if (!mpd_send_list_queue_range_meta(mpd.conn, offset, offset + MAX_ELEMENTS_PER_PAGE))
RETURN_ERROR_AND_RECOVER("mpd_send_list_queue_meta"); RETURN_ERROR_AND_RECOVER("mpd_send_list_queue_meta");
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"queue\",\"data\":[ "); cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"queue\",\"data\":[ ");
while((entity = mpd_recv_entity(mpd.conn)) != NULL) { while ((entity = mpd_recv_entity(mpd.conn)) != NULL) {
const struct mpd_song *song; const struct mpd_song *song;
unsigned int drtn; unsigned int drtn;
if(mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) { if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) {
song = mpd_entity_get_song(entity); song = mpd_entity_get_song(entity);
drtn = mpd_song_get_duration(song); drtn = mpd_song_get_duration(song);
@ -655,8 +626,7 @@ int mpd_put_queue(char *buffer, unsigned int offset)
return cur - buffer; return cur - buffer;
} }
int mpd_put_browse(char *buffer, char *path, unsigned int offset) int mpd_put_browse(char *buffer, char *path, unsigned int offset) {
{
char *cur = buffer; char *cur = buffer;
const char *end = buffer + MAX_SIZE; const char *end = buffer + MAX_SIZE;
struct mpd_entity *entity; struct mpd_entity *entity;
@ -665,25 +635,22 @@ int mpd_put_browse(char *buffer, char *path, unsigned int offset)
if (!mpd_send_list_meta(mpd.conn, path)) if (!mpd_send_list_meta(mpd.conn, path))
RETURN_ERROR_AND_RECOVER("mpd_send_list_meta"); RETURN_ERROR_AND_RECOVER("mpd_send_list_meta");
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"browse\",\"data\":[ "); cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"browse\",\"data\":[ ");
while((entity = mpd_recv_entity(mpd.conn)) != NULL) { while ((entity = mpd_recv_entity(mpd.conn)) != NULL) {
const struct mpd_song *song; const struct mpd_song *song;
const struct mpd_directory *dir; const struct mpd_directory *dir;
const struct mpd_playlist *pl; const struct mpd_playlist *pl;
if(offset > entity_count) if (offset > entity_count) {
{
mpd_entity_free(entity); mpd_entity_free(entity);
entity_count++; entity_count++;
continue; continue;
} } else if (offset + MAX_ELEMENTS_PER_PAGE - 1 < entity_count) {
else if(offset + MAX_ELEMENTS_PER_PAGE - 1 < entity_count)
{
mpd_entity_free(entity); mpd_entity_free(entity);
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"wrap\",\"count\":"); cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"wrap\",\"count\":");
cur += json_emit_int(cur, end - cur, entity_count); cur += json_emit_int(cur, end - cur, entity_count);
cur += json_emit_raw_str(cur, end - cur, "} "); cur += json_emit_raw_str(cur, end - cur, "} ");
break; break;
} }
@ -738,23 +705,22 @@ int mpd_put_browse(char *buffer, char *path, unsigned int offset)
return cur - buffer; return cur - buffer;
} }
int mpd_search(char *buffer, char *searchstr) int mpd_search(char *buffer, char *searchstr) {
{
int i = 0; int i = 0;
char *cur = buffer; char *cur = buffer;
const char *end = buffer + MAX_SIZE; const char *end = buffer + MAX_SIZE;
struct mpd_song *song; struct mpd_song *song;
if(mpd_search_db_songs(mpd.conn, false) == false) if (mpd_search_db_songs(mpd.conn, false) == false)
RETURN_ERROR_AND_RECOVER("mpd_search_db_songs"); RETURN_ERROR_AND_RECOVER("mpd_search_db_songs");
else if(mpd_search_add_any_tag_constraint(mpd.conn, MPD_OPERATOR_DEFAULT, searchstr) == false) else if (mpd_search_add_any_tag_constraint(mpd.conn, MPD_OPERATOR_DEFAULT, searchstr) == false)
RETURN_ERROR_AND_RECOVER("mpd_search_add_any_tag_constraint"); RETURN_ERROR_AND_RECOVER("mpd_search_add_any_tag_constraint");
else if(mpd_search_commit(mpd.conn) == false) else if (mpd_search_commit(mpd.conn) == false)
RETURN_ERROR_AND_RECOVER("mpd_search_commit"); RETURN_ERROR_AND_RECOVER("mpd_search_commit");
else { else {
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"search\",\"data\":[ "); cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"search\",\"data\":[ ");
while((song = mpd_recv_song(mpd.conn)) != NULL) { while ((song = mpd_recv_song(mpd.conn)) != NULL) {
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"song\",\"uri\":"); cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"song\",\"uri\":");
cur += json_emit_quoted_str(cur, end - cur, mpd_song_get_uri(song)); cur += json_emit_quoted_str(cur, end - cur, mpd_song_get_uri(song));
cur += json_emit_raw_str(cur, end - cur, ",\"album\":"); cur += json_emit_raw_str(cur, end - cur, ",\"album\":");
@ -773,8 +739,7 @@ int mpd_search(char *buffer, char *searchstr)
mpd_song_free(song); mpd_song_free(song);
/* Maximum results */ /* Maximum results */
if(i++ >= 300) if (i++ >= 300) {
{
cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"wrap\"},"); cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"wrap\"},");
break; break;
} }
@ -788,9 +753,7 @@ int mpd_search(char *buffer, char *searchstr)
return cur - buffer; return cur - buffer;
} }
void mpd_disconnect() {
void mpd_disconnect()
{
mpd.conn_state = MPD_DISCONNECT; mpd.conn_state = MPD_DISCONNECT;
mpd_poll(NULL); mpd_poll(NULL);
} }

View File

@ -1,7 +1,7 @@
/* ympd /* ympd
(c) 2013-2014 Andrew Karpow <andy@ndyk.de> (c) 2013-2014 Andrew Karpow <andy@ndyk.de>
This project's homepage is: http://www.ympd.org This project's homepage is: http://www.ympd.org
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. the Free Software Foundation; version 2 of the License.
@ -15,63 +15,61 @@
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#ifndef __MPD_CLIENT_H__ #ifndef __MPD_CLIENT_H__
#define __MPD_CLIENT_H__ #define __MPD_CLIENT_H__
#include "mongoose.h" #include "mongoose.h"
#define RETURN_ERROR_AND_RECOVER(X) do { \ #define RETURN_ERROR_AND_RECOVER(X) \
fprintf(stderr, "MPD X: %s\n", mpd_connection_get_error_message(mpd.conn)); \ do { \
cur += snprintf(cur, end - cur, "{\"type\":\"error\",\"data\":\"%s\"}", \ fprintf(stderr, "MPD X: %s\n", mpd_connection_get_error_message(mpd.conn)); \
mpd_connection_get_error_message(mpd.conn)); \ cur += snprintf(cur, end - cur, "{\"type\":\"error\",\"data\":\"%s\"}", \
if (!mpd_connection_clear_error(mpd.conn)) \ mpd_connection_get_error_message(mpd.conn)); \
mpd.conn_state = MPD_FAILURE; \ if (!mpd_connection_clear_error(mpd.conn)) \
return cur - buffer; \ mpd.conn_state = MPD_FAILURE; \
} while(0) return cur - buffer; \
} while (0)
#define MAX_SIZE 1024 * 100 #define MAX_SIZE 1024 * 100
#define MAX_ELEMENTS_PER_PAGE 512 #define MAX_ELEMENTS_PER_PAGE 512
#define GEN_ENUM(X) X, #define GEN_ENUM(X) X,
#define GEN_STR(X) #X, #define GEN_STR(X) #X,
#define MPD_CMDS(X) \ #define MPD_CMDS(X) \
X(MPD_API_GET_QUEUE) \ X(MPD_API_GET_QUEUE) \
X(MPD_API_GET_BROWSE) \ X(MPD_API_GET_BROWSE) \
X(MPD_API_GET_MPDHOST) \ X(MPD_API_GET_MPDHOST) \
X(MPD_API_ADD_TRACK) \ X(MPD_API_ADD_TRACK) \
X(MPD_API_ADD_PLAY_TRACK) \ X(MPD_API_ADD_PLAY_TRACK) \
X(MPD_API_ADD_PLAYLIST) \ X(MPD_API_ADD_PLAYLIST) \
X(MPD_API_PLAY_TRACK) \ X(MPD_API_PLAY_TRACK) \
X(MPD_API_SAVE_QUEUE) \ X(MPD_API_SAVE_QUEUE) \
X(MPD_API_RM_TRACK) \ X(MPD_API_RM_TRACK) \
X(MPD_API_RM_RANGE) \ X(MPD_API_RM_RANGE) \
X(MPD_API_RM_ALL) \ X(MPD_API_RM_ALL) \
X(MPD_API_MOVE_TRACK) \ X(MPD_API_MOVE_TRACK) \
X(MPD_API_SEARCH) \ X(MPD_API_SEARCH) \
X(MPD_API_SEND_MESSAGE) \ X(MPD_API_SEND_MESSAGE) \
X(MPD_API_SET_VOLUME) \ X(MPD_API_SET_VOLUME) \
X(MPD_API_SET_PAUSE) \ X(MPD_API_SET_PAUSE) \
X(MPD_API_SET_PLAY) \ X(MPD_API_SET_PLAY) \
X(MPD_API_SET_STOP) \ X(MPD_API_SET_STOP) \
X(MPD_API_SET_SEEK) \ X(MPD_API_SET_SEEK) \
X(MPD_API_SET_NEXT) \ X(MPD_API_SET_NEXT) \
X(MPD_API_SET_PREV) \ X(MPD_API_SET_PREV) \
X(MPD_API_SET_MPDHOST) \ X(MPD_API_SET_MPDHOST) \
X(MPD_API_SET_MPDPASS) \ X(MPD_API_SET_MPDPASS) \
X(MPD_API_UPDATE_DB) \ X(MPD_API_UPDATE_DB) \
X(MPD_API_GET_OUTPUTS) \ X(MPD_API_GET_OUTPUTS) \
X(MPD_API_TOGGLE_OUTPUT) \ X(MPD_API_TOGGLE_OUTPUT) \
X(MPD_API_TOGGLE_RANDOM) \ X(MPD_API_TOGGLE_RANDOM) \
X(MPD_API_TOGGLE_CONSUME) \ X(MPD_API_TOGGLE_CONSUME) \
X(MPD_API_TOGGLE_SINGLE) \ X(MPD_API_TOGGLE_SINGLE) \
X(MPD_API_TOGGLE_CROSSFADE) \ X(MPD_API_TOGGLE_CROSSFADE) \
X(MPD_API_TOGGLE_REPEAT) X(MPD_API_TOGGLE_REPEAT)
enum mpd_cmd_ids { enum mpd_cmd_ids { MPD_CMDS(GEN_ENUM) };
MPD_CMDS(GEN_ENUM)
};
enum mpd_conn_states { enum mpd_conn_states {
MPD_DISCONNECTED, MPD_DISCONNECTED,
@ -83,10 +81,10 @@ enum mpd_conn_states {
struct t_mpd { struct t_mpd {
int port; int port;
int local_port; int local_port;
char host[128]; char host[128];
char *password; char *password;
char *gpass; char *gpass;
struct mpd_connection *conn; struct mpd_connection *conn;
enum mpd_conn_states conn_state; enum mpd_conn_states conn_state;
@ -117,4 +115,3 @@ int mpd_put_browse(char *buffer, char *path, unsigned int offset);
int mpd_search(char *buffer, char *searchstr); int mpd_search(char *buffer, char *searchstr);
void mpd_disconnect(); void mpd_disconnect();
#endif #endif

View File

@ -1,7 +1,7 @@
/* ympd /* ympd
(c) 2013-2014 Andrew Karpow <andy@ndyk.de> (c) 2013-2014 Andrew Karpow <andy@ndyk.de>
This project's homepage is: http://www.ympd.org This project's homepage is: http://www.ympd.org
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. the Free Software Foundation; version 2 of the License.
@ -16,25 +16,24 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <getopt.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/time.h> #include <sys/time.h>
#include <pthread.h> #include <unistd.h>
#include "mongoose.h"
#include "http_server.h"
#include "mpd_client.h"
#include "config.h" #include "config.h"
#include "http_server.h"
#include "mongoose.h"
#include "mpd_client.h"
extern char *optarg; extern char *optarg;
int force_exit = 0; int force_exit = 0;
void bye() void bye() {
{
force_exit = 1; force_exit = 1;
} }
@ -42,14 +41,14 @@ static int server_callback(struct mg_connection *c, enum mg_event ev) {
int result = MG_FALSE; int result = MG_FALSE;
FILE *fp = NULL; FILE *fp = NULL;
switch(ev) { switch (ev) {
case MG_CLOSE: case MG_CLOSE:
mpd_close_handler(c); mpd_close_handler(c);
return MG_TRUE; return MG_TRUE;
case MG_REQUEST: case MG_REQUEST:
if (c->is_websocket) { if (c->is_websocket) {
c->content[c->content_len] = '\0'; c->content[c->content_len] = '\0';
if(c->content_len) if (c->content_len)
return callback_mpd(c); return callback_mpd(c);
else else
return MG_TRUE; return MG_TRUE;
@ -61,10 +60,11 @@ static int server_callback(struct mg_connection *c, enum mg_event ev) {
#endif #endif
case MG_AUTH: case MG_AUTH:
// no auth for websockets since mobile safari does not support it // no auth for websockets since mobile safari does not support it
if ( (mpd.gpass == NULL) || (c->is_websocket) || ((mpd.local_port > 0) && (c->local_port == mpd.local_port)) ) if ((mpd.gpass == NULL) || (c->is_websocket) ||
((mpd.local_port > 0) && (c->local_port == mpd.local_port)))
return MG_TRUE; return MG_TRUE;
else { else {
if ( (fp = fopen(mpd.gpass, "r")) != NULL ) { if ((fp = fopen(mpd.gpass, "r")) != NULL) {
result = mg_authorize_digest(c, fp); result = mg_authorize_digest(c, fp);
fclose(fp); fclose(fp);
} }
@ -75,8 +75,7 @@ static int server_callback(struct mg_connection *c, enum mg_event ev) {
} }
} }
int main(int argc, char **argv) int main(int argc, char **argv) {
{
int n, option_index = 0; int n, option_index = 0;
struct mg_server *server = mg_create_server(NULL, server_callback); struct mg_server *server = mg_create_server(NULL, server_callback);
unsigned int current_timer = 0, last_timer = 0; unsigned int current_timer = 0, last_timer = 0;
@ -92,9 +91,10 @@ int main(int argc, char **argv)
mg_set_option(server, "auth_domain", "ympd"); mg_set_option(server, "auth_domain", "ympd");
mpd.port = 6600; mpd.port = 6600;
mpd.local_port = 0; mpd.local_port = 0;
mpd.gpass = NULL; mpd.gpass = NULL;
strcpy(mpd.host, "127.0.0.1"); strcpy(mpd.host, "127.0.0.1");
/* clang-format off */
static struct option long_options[] = { static struct option long_options[] = {
{"digest", required_argument, 0, 'D'}, {"digest", required_argument, 0, 'D'},
{"host", required_argument, 0, 'h'}, {"host", required_argument, 0, 'h'},
@ -107,9 +107,9 @@ int main(int argc, char **argv)
{"mpdpass", required_argument, 0, 'm'}, {"mpdpass", required_argument, 0, 'm'},
{0, 0, 0, 0 } {0, 0, 0, 0 }
}; };
/* clang-format on */
while((n = getopt_long(argc, argv, "D:h:p:l:w:u:d:v:m", while ((n = getopt_long(argc, argv, "D:h:p:l:w:u:d:v:m", long_options, &option_index)) != -1) {
long_options, &option_index)) != -1) {
switch (n) { switch (n) {
case 'D': case 'D':
mpd.gpass = strdup(optarg); mpd.gpass = strdup(optarg);
@ -134,14 +134,19 @@ int main(int argc, char **argv)
mpd.password = strdup(optarg); mpd.password = strdup(optarg);
break; break;
case 'v': case 'v':
fprintf(stdout, "ympd %d.%d.%d\n" fprintf(stdout,
"ympd %d.%d.%d\n"
"Copyright (C) 2014 Andrew Karpow <andy@ndyk.de>\n" "Copyright (C) 2014 Andrew Karpow <andy@ndyk.de>\n"
"built " __DATE__ " "__TIME__ " ("__VERSION__")\n", "built " __DATE__
" "__TIME__
" ("__VERSION__
")\n",
YMPD_VERSION_MAJOR, YMPD_VERSION_MINOR, YMPD_VERSION_PATCH); YMPD_VERSION_MAJOR, YMPD_VERSION_MINOR, YMPD_VERSION_PATCH);
return EXIT_SUCCESS; return EXIT_SUCCESS;
break; break;
default: default:
fprintf(stderr, "Usage: %s [OPTION]...\n\n" fprintf(stderr,
"Usage: %s [OPTION]...\n\n"
" -D, --digest <htdigest>\tpath to htdigest file for authorization\n" " -D, --digest <htdigest>\tpath to htdigest file for authorization\n"
" \t(realm ympd) [no authorization]\n" " \t(realm ympd) [no authorization]\n"
" -h, --host <host>\t\tconnect to mpd at host [localhost]\n" " -h, --host <host>\t\tconnect to mpd at host [localhost]\n"
@ -150,31 +155,30 @@ int main(int argc, char **argv)
" -w, --webport [ip:]<port>\tlisten interface/port for webserver [8080]\n" " -w, --webport [ip:]<port>\tlisten interface/port for webserver [8080]\n"
" -u, --user <username>\t\tdrop priviliges to user after socket bind\n" " -u, --user <username>\t\tdrop priviliges to user after socket bind\n"
" -v, --version\t\t\tget version\n" " -v, --version\t\t\tget version\n"
" -m, --mpdpass <password>\tspecifies the password to use when connecting to mpd\n" " -m, --mpdpass <password>\tspecifies the password to use when connecting "
" --help\t\t\t\tthis help\n" "to mpd\n"
, argv[0]); " --help\t\t\t\tthis help\n",
argv[0]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if(error_msg) if (error_msg) {
{
fprintf(stderr, "Mongoose error: %s\n", error_msg); fprintf(stderr, "Mongoose error: %s\n", error_msg);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
error_msg = mg_set_option(server, "listening_port", webport); error_msg = mg_set_option(server, "listening_port", webport);
if(error_msg) { if (error_msg) {
fprintf(stderr, "Mongoose error: %s\n", error_msg); fprintf(stderr, "Mongoose error: %s\n", error_msg);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* drop privilges at last to ensure proper port binding */ /* drop privilges at last to ensure proper port binding */
if(run_as_user != NULL) { if (run_as_user != NULL) {
error_msg = mg_set_option(server, "run_as_user", run_as_user); error_msg = mg_set_option(server, "run_as_user", run_as_user);
free(run_as_user); free(run_as_user);
if(error_msg) if (error_msg) {
{
fprintf(stderr, "Mongoose error: %s\n", error_msg); fprintf(stderr, "Mongoose error: %s\n", error_msg);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -183,8 +187,7 @@ int main(int argc, char **argv)
while (!force_exit) { while (!force_exit) {
mg_poll_server(server, 200); mg_poll_server(server, 200);
current_timer = time(NULL); current_timer = time(NULL);
if(current_timer - last_timer) if (current_timer - last_timer) {
{
last_timer = current_timer; last_timer = current_timer;
mpd_poll(server); mpd_poll(server);
} }