diff --git a/NEWS b/NEWS
index c66d91e3e..9b9535d40 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ ver 0.18 (2012/??/??)
 * protocol:
   - new command "toggleoutput"
   - search for album artist falls back to the artist tag
+  - re-add the "volume" command
 * input:
   - curl: enable https
   - soup: plugin removed
diff --git a/doc/protocol.xml b/doc/protocol.xml
index 50e58db63..d40d6586d 100644
--- a/doc/protocol.xml
+++ b/doc/protocol.xml
@@ -768,6 +768,25 @@
             </para>
           </listitem>
         </varlistentry>
+        <varlistentry id="command_volume">
+          <term>
+            <cmdsynopsis>
+              <command>volume</command>
+              <arg choice="req"><replaceable>CHANGE</replaceable></arg>
+            </cmdsynopsis>
+          </term>
+          <listitem>
+            <para>
+              Changes volume by amount <varname>CHANGE</varname>.
+            </para>
+            <note>
+              <para>
+                <command>volume</command> is deprecated, use
+                <command>setvol</command> instead.
+              </para>
+            </note>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </section>
 
diff --git a/src/command/AllCommands.cxx b/src/command/AllCommands.cxx
index 2271aeff2..b83b42a29 100644
--- a/src/command/AllCommands.cxx
+++ b/src/command/AllCommands.cxx
@@ -161,6 +161,7 @@ static const struct command commands[] = {
 	{ "unsubscribe", PERMISSION_READ, 1, 1, handle_unsubscribe },
 	{ "update", PERMISSION_CONTROL, 0, 1, handle_update },
 	{ "urlhandlers", PERMISSION_READ, 0, 0, handle_urlhandlers },
+	{ "volume", PERMISSION_CONTROL, 1, 1, handle_volume },
 };
 
 static const unsigned num_commands = sizeof(commands) / sizeof(commands[0]);
diff --git a/src/command/OtherCommands.cxx b/src/command/OtherCommands.cxx
index 55391af16..510ef89e7 100644
--- a/src/command/OtherCommands.cxx
+++ b/src/command/OtherCommands.cxx
@@ -236,6 +236,39 @@ handle_setvol(Client &client, gcc_unused int argc, char *argv[])
 	return CommandResult::OK;
 }
 
+CommandResult
+handle_volume(Client &client, gcc_unused int argc, char *argv[])
+{
+	int relative;
+	if (!check_int(client, &relative, argv[1]))
+		return CommandResult::ERROR;
+
+	if (relative < -100 || relative > 100) {
+		command_error(client, ACK_ERROR_ARG, "Invalid volume value");
+		return CommandResult::ERROR;
+	}
+
+	const int old_volume = volume_level_get();
+	if (old_volume < 0) {
+		command_error(client, ACK_ERROR_SYSTEM, "No mixer");
+		return CommandResult::ERROR;
+	}
+
+	int new_volume = old_volume + relative;
+	if (new_volume < 0)
+		new_volume = 0;
+	else if (new_volume > 100)
+		new_volume = 100;
+
+	if (new_volume != old_volume && !volume_level_change(new_volume)) {
+		command_error(client, ACK_ERROR_SYSTEM,
+			      "problems setting volume");
+		return CommandResult::ERROR;
+	}
+
+	return CommandResult::OK;
+}
+
 CommandResult
 handle_stats(Client &client,
 	     gcc_unused int argc, gcc_unused char *argv[])
diff --git a/src/command/OtherCommands.hxx b/src/command/OtherCommands.hxx
index fe3e145c4..20201e8b9 100644
--- a/src/command/OtherCommands.hxx
+++ b/src/command/OtherCommands.hxx
@@ -51,6 +51,9 @@ handle_rescan(Client &client, int argc, char *argv[]);
 CommandResult
 handle_setvol(Client &client, int argc, char *argv[]);
 
+CommandResult
+handle_volume(Client &client, int argc, char *argv[]);
+
 CommandResult
 handle_stats(Client &client, int argc, char *argv[]);