Hello,
Please keep the mailing list on Cc, so all developers can participate.
Done.
commit 6c1d9df29ad22c6ef13528718a3d91fcff34819f Author: Gunnar Roth <gun...@garmedia.(none)>That email address is invalid.The comment of the editor told me that # lines will not be in the comit, but that menat probably only # i added myself. i did not edit the mail adress because i thought this was just informational for me.The author field is public, and should contain useful information.
I see.
It's "-Werror" (or "--enable-werror" on configure), and enabling it is a good thing. Especially because your code was wrong. A "gsize" cannot be negative, and thus your check could never succeed. That's a good example which proves why "-Werror" is good - if you had enabled it, you would have noticed your mistake.
Well "--enable-werror maybe it should be default. Problem on windows vs 2008 is that i get a lot other warnings, so cannot make warnings to errors.
No uppercase letters in file names.Ok its no problem on windows, but i accept this as a policy.It's not just a "policy", it's to make sure that cross builds work.
Oh yes you are right, did never crosscompile for windows, so i hadnt this in mind.
Well before i did only change xClose but then it was removed so i changed all the other placesTrue, but you removed xClose() in git, and i dint want to add it again. So how should this wrapper be called? or just a #define closesocket(x) close(x) for non win32?xclose() does not have anything to do with this.
and took as example this code from the git version: #ifdef WIN32 ret = _pipe(event_pipe, 512, _O_BINARY); #else ret = pipe(event_pipe); #endif
Also: don't code in CPP when you can code in C. There are many advantages in inline functions compared to macros.
Of course you are right. So i made a inline function inline closesocket(int fd) { close(fd); } in utils.h ( oscompat.h was removed from git)
Yes, you could wrap g_io_channel_win32_new_socket() / g_io_channel_unix_new() in some OS dependent inline function, if you want.
added g_io_channel_new_socket and g_io_channel_new_fd inline func in utils.h
I just misunderstood what you meant by replace, because i didnt know that recv is available on linux too.Why yet another #ifdef hack, when you could just replace read() with recv()? On POSIX compliant systems, both is allowed, while Windows only allows recv().recv() has one more parameter than read(). (note the ,0)I know that. So?
so i simply removed the read and the ifdefs.
if (bytesRead > 0) return client_input_received(client, bytesRead); +#ifdef _WIN32 + else if (bytesRead < 0 && WSAGetLastError() == WSAEINTR) +#else else if (bytesRead < 0 && errno == EINTR) +#endif /* try again later, after select() */ return 0; else@@ -483,13 +506,18 @@ client_out_event(G_GNUC_UNUSED GIOChannel *source,static gboolean client_in_event(G_GNUC_UNUSED GIOChannel *source, - G_GNUC_UNUSED GIOCondition condition, + GIOCondition condition, gpointer data) { struct client *client = data; int ret; assert(!client_is_expired(client)); + if (condition != G_IO_IN) { + client_set_expired(client); + return false; + } + client->lastTime = time(NULL); @@ -542,7 +570,7 @@ client_out_event(G_GNUC_UNUSED GIOChannel *source, if (g_queue_is_empty(client->deferred_send)) { /* done sending deferred buffers exist: schedule read */ - client->source_id = g_io_add_watch(client->channel, G_IO_IN, + client->source_id = g_io_add_watch(client->channel, G_IO_IN|G_IO_NVAL | G_IO_HUP | G_IO_ERR, client_in_event, client); return false; }Care to explain this one? On Unix, it's enough to listen for G_IO_IN, since the socket becomes readable when the peer closes the connection.I dont know what happen on unix. on windows the connect list run full ,when i was in the debugger and stepped.Trial'n'error is the wrong way to develop software. Do some research instead of trying until it succeeds. This leads to fragile code.
i was debbuging some other stuuf ( better see how the code flows) but due to debugger stops mpd did not answer to the client, which opened more conections then.
I cannot see code in client_in_event which handles connection close when no close command is issued before by the client.See client.c:476: else /* peer disconnected or I/O error */ return COMMAND_RETURN_CLOSE; This is executed when read() returns a non-positive value (except for EINTR). This is known to work well on POSIX compliant systems.
So it does not work with glib on windows it seems.
send also has one more parameter than write()I know that, too. So?
so same case as recv above
diff --git a/src/cmdline.c b/src/cmdline.c old mode 100644 new mode 100755 index 48c1e87..ef7dd2c --- a/src/cmdline.c +++ b/src/cmdline.c @@ -32,7 +32,11 @@ #include <stdio.h> #include <stdlib.h> +#ifdef _WIN32 +#define SYSTEM_CONFIG_FILE_LOCATION "c:/.mpd/mpd.conf" +#else #define SYSTEM_CONFIG_FILE_LOCATION "/etc/mpd.conf" +#endif #define USER_CONFIG_FILE_LOCATION ".mpdconf"Is that actually a good default location for win32? This looks like it violates Microsoft's policies.the patch uses HOMEDIR\.mpdconf as default. SYSTEM_CONFIG_FILE_LOCATION is just for testing. but better is to use ALLUSERSPROFILE env varDon't submit "just for testing" code, it won't be merged. Even better would be to follow the Microsoft policy. I'm not sure if ALLUSERSPROFILE is compliant. Find out, and add references to the documentation to the patch description and to source code comments.
hmm ok, wxwidgets uses this: // return the directory with system config files: // /etc under Unix, c:\Documents and Settings\All Users\Application Data // under Windows, /Library/Preferences for Mac virtual wxString GetConfigDir() const = 0; but to get this, its not just reading a env var.( need to call SHGetSpecialFolderLocation with CSIDL_COMMON_APPDATA, feéd item list result to SHGetPathFromIDListto get actual string, call SHGetMalloc to free the item list)
I disabled this code on Win32 for a good reason, which can be read in the according patch. Please explain this hunk.well ok, i thought this is disabled because no uid checks on windows, but i wanted to be able to test this feature.Again, don't submit "just for testing" code.maybe it should be configurable, if the files must belong to the mpd user.as this is a rather hard restrinction, because no files of me would belong to this user.Why not use the same semantics as MPD on Unix?
I meant unix. ( i use mpd on linux actually) For windows i thought this feature could be open as a start. because setting access right and creating user is rather complicated for a user without a setup program.
--- a/src/event_pipe.c +++ b/src/event_pipe.c @@ -53,15 +53,16 @@ event_pipe_invoke(enum pipe_event event) } static gboolean -main_notify_event(G_GNUC_UNUSED GIOChannel *source, +main_notify_event(GIOChannel *source, G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer data) { char buffer[256]; - ssize_t r = read(event_pipe[0], buffer, sizeof(buffer)); + gsize bytes_read = 0; + GIOStatus status = g_io_channel_read_chars(source,buffer,1,&bytes_read,NULL); bool events[PIPE_EVENT_MAX]; - if (r < 0 && errno != EAGAIN && errno != EINTR) + if (bytes_read < 0 && status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) g_error("error reading from pipe: %s", strerror(errno)); g_mutex_lock(event_pipe_mutex);This hunk is wrong and breaks the Linux build, and should also break the Windows build.you are right, but as mentioned did not break here. i replacethe line by if(status == G_IO_STATUS_AGAIN) return true; else if (status != G_IO_STATUS_NORMAL ) g_error("error reading from pipe: %s", strerror(errno));It looked like it didn't break, because you didn't trigger the error condition which is checked here, did you?
I emant it did not break the compile. i already said , i see it is wrong code.
@@ -76,10 +77,9 @@ main_notify_event(G_GNUC_UNUSED GIOChannel *source, return true; } - +static GIOChannel *channel; void event_pipe_init(void) { - GIOChannel *channel; int ret; #ifdef WIN32 @@ -89,14 +89,16 @@ void event_pipe_init(void) #endif if (ret < 0) g_error("Couldn't open pipe: %s", strerror(errno)); +#ifdef _WIN32 + channel = g_io_channel_win32_new_fd(event_pipe[0]); +#else if (set_nonblocking(event_pipe[1]) < 0) g_error("Couldn't set non-blocking I/O: %s", strerror(errno)); - channel = g_io_channel_unix_new(event_pipe[0]); +#endif event_pipe_source_id = g_io_add_watch(channel, G_IO_IN, main_notify_event, NULL); - g_io_channel_unref(channel); - + event_pipe_mutex = g_mutex_new(); } @@ -105,8 +107,11 @@ void event_pipe_deinit(void) g_mutex_free(event_pipe_mutex); g_source_remove(event_pipe_source_id); - - close(event_pipe[0]); + + g_io_channel_shutdown(channel,false,NULL); + g_io_channel_unref(channel); + channel = NULL; + close(event_pipe[1]); }The whole event_pipe.c patch requires explanationok first this from g lib header /* Create an IO channel for C runtime (emulated Unix-like) file * descriptors. After calling g_io_add_watch() on a IO channel * returned by this function, you shouldn't call read() on the file * descriptor. This is because adding polling for a file descriptor is * implemented on Win32 by starting a thread that sits blocked in a * read() from the file descriptor most of the time. All reads from * the file descriptor should be done by this internal GLib * thread. Your code should call only g_io_channel_read_chars(). */ GIOChannel* g_io_channel_win32_new_fd (gint fd); so i have to use g_io_channel_read_chars() as i/o would block, i only read 1 byte on incoming event. that will not block, because on event at least one byte is there.I believe you misunderstood non-blocking I/O here. A read does not block if at least 1 byte is *available*, not if exactly one byte is *requested*. You can request any number of bytes, but read() will not block and return what's available.
You didnt understand me. First a pipe creaste with _pipe() is always blocking on windows. So if a byte is written to the pipe , the event callback is called and the 256 byte read call
blocks, because it would only return on eof or if 256 bytes can be read.
i also need to use g_io_channel_shutdown() because else the internal glib thread would not be stopped. i also think that imho if giochnnel is used for a fd ( socket) giochannel functions should be used for read/write/close. ( would also remove closescoket/close recv/read send/write problems) but i thought that could be done later.Proper patch welcome. Don't wait until "later", don't write half-finished code with improper solutions.
recv send and closesocket only used now
@@ -228,23 +239,6 @@ parseListenConfigParam(G_GNUC_UNUSED unsigned int port, ConfigParam * param) BINDERROR(); freeaddrinfo(ai); -#else /* WIN32 */ - const struct hostent *he; - - g_debug("binding to address for %s", param->value); - - he = gethostbyname(param->value); - if (he == NULL) - g_error("can't lookup host \"%s\" at line %i", - param->value, param->line); - - if (he->h_addrtype != AF_INET) - g_error("IPv4 address expected for host \"%s\" at line %i", - param->value, param->line); - - if (establishListen(AF_INET, he->h_addr, he->h_length) < 0) - BINDERROR(); -#endif /* !WIN32 */Please explain.Well the i removed that because the other code does also compile on windows.What other code? You removed the whole host lookup code! That breaks the bind_to_address setting.
i removed the win32 version
diff --git a/src/song.h b/src/song.h old mode 100644 new mode 100755 index a4c72cf..e717c07 --- a/src/song.h +++ b/src/song.h @@ -21,7 +21,7 @@ #include <stddef.h> #include <stdbool.h> -#include <sys/time.h> +#include <time.h> #define SONG_BEGIN "songList begin" #define SONG_END "songList end" diff --git a/src/tag.c b/src/tag.c old mode 100644 new mode 100755 index e7ce51c..d2f02cb --- a/src/tag.c +++ b/src/tag.c @@ -152,8 +152,11 @@ struct tag *tag_ape_load(const char *file) TAG_ITEM_TRACK, TAG_ITEM_DATE, }; - +#ifdef _Win32 + fp = fopen(file, "rb"); +#else fp = fopen(file, "r"); +#endif if (!fp) return NULL;The "b" flag is portable, and the #ifdef can be removedok, i just wasnt sure, because i thought O_BINARY were also portable, but was not. so i chaged al "rb" to be in #ifdef _WIN32 but will change it backAnother incidence of trial'n'error engineering: instead of looking up the fopen() documentation, you made wrong assumptions, and made the code more a mess than it could be.
yes should have read the man page
#include <pwd.h> #endif - #ifdef HAVE_IPV6 +#ifndef _WIN32 #include <sys/socket.h> #endif +#endif #ifdef WIN32 #include <windows.h> @@ -56,7 +59,14 @@ void my_usleep(long usec) char *parsePath(char *path) { -#ifndef WIN32 + +#ifdef _WIN32 + if (path[1] != ':' && path[0] != '/') { + g_warning("\"%s\" is not an absolute path", path); + return NULL; + } + +#elseThis causes a crash if path is an empty string.replaced it by if (path && strlen(path) > 0 && path[1] != ':' && path[0] != '/') {Why the "path != NULL" check? It's illegal to pass NULL here, and it should crash then. Maybe add an assertion. strlen() can be a huge overhead, because strlen() reads the whole string. Why not just check "*path != 0", which is essentially the same as "strlen(path) > 0"?
ok
int set_nonblocking(int fd) { -#ifdef WIN32 - u_long val = 0; - +#ifdef _WIN32 + u_long val = 1; + return ioctlsocket(fd, FIONBIO, &val) == 0 ? 0 : -1; #else int ret, flags;Please explain.from msdn example code / Set the socket I/O mode: In this case FIONBIO // enables or disables the blocking mode for the // socket based on the numerical value of iMode. // If iMode = 0, blocking is enabled; // If iMode != 0, non-blocking mode is enabled. u_long iMode = 0; ioctlsocket(m_socket, FIONBIO, &iMode); so to enable non-blocking you set param to be NOT 0That description belongs to the patch documentation (commit message). It's not obvious what you were trying to achieve, and it's not obvious why the old code was wrong.
hmm i thought it was obvious.
diff --git a/src/volume.c b/src/volume.c old mode 100644 new mode 100755 index 5eb0bd6..ac2add0 --- a/src/volume.c +++ b/src/volume.c @@ -40,7 +40,11 @@ #define SW_VOLUME_STATE "sw_volume: " const struct audio_output_plugin *default_mixer; +#ifdef _WIN32 +static int volume_mixer_type = VOLUME_MIXER_TYPE_SOFTWARE; /* hardware mixer on windows not implemented yet!*/ +#else static int volume_mixer_type = VOLUME_MIXER_TYPE_HARDWARE; +#endif static int volume_software_set = 100; void volume_finish(void)This is wrong. MPD should always attempt to find a hardware mixer. If none is implemented, MPD should automatically fall back to software. This is a non-solution.Ok i didnt know, but sounds right. fallback just does not seem work. so to make it work for windows it did that can remove it of course.Another "trial'n'error" fix: instead of fixing the root cause of the problem (fallback not working), you changed a global constant.
i didnt know about a fallback, so didnt know behaviour wasnt correct.removd the change and use conf setting to force software mixer in my mpd.conf
diff --git a/src/zeroconf.c b/src/zeroconf.c old mode 100644 new mode 100755 index dd9790a..4f40419 --- a/src/zeroconf.c +++ b/src/zeroconf.c @@ -22,7 +22,7 @@ #include "config.h" #include <glib.h> - +#ifdef HAVE_ZEROCONF /* The default service name to publish * (overridden by 'zeroconf_name' config parameter) */ @@ -71,3 +71,4 @@ void finishZeroconf(void) bonjour_finish(); #endif } +#endif /*HAVE_ZEROCONF*/ \ No newline at end of fileThis hunk is wrong, since zeroconf.c shouldn't be compiled at all if HAVE_ZEROCONF is not defined.ok didnt know that it is not compiled at all on unix. as i use vcproj it was easier for me this way, but i remove this change, no problem.You didn't know, maybe because you didn't look at Makefile.am: if HAVE_ZEROCONF mpd_SOURCES += zeroconf.c [...] endif I suggest you just use autoconf/automake for building, instead of proprietary Visual Studio files. This way, you don't have to duplicate all the code in Makefile.am.
Sorry but one of MY main goals is to be able to use vs2008 for building mpd.
No, that would mean that I have to merge your first huge patch, and then more patches which undo lots of its changes. Won't happen, I will only merge individual clean patches. I recommend that you use "stgit" for creating smaller patches. The MPD wiki has some information on it: http://mpd.wikia.com/wiki/git In your case, I'd "uncommit" (stg uncommit) the huge patch, and pop it off the stack (stg pop), and re-create lots of smaller patches from it ("stg-fold-files-from" might be helpful). Either throw away the big patch at the end, or "push" it on top after each new patch, and fix all the merge conflicts manually.
Puh i didnt manage to understand whats going on, did uncommit and pop, but somehow i dont get it. as i am not at home for some days,i will have no time in the next few days to continue. Hopefully can continue on weekend.
i attach a git diff file as a reference, there are not many changes left anymore just 747 lines.
regards, gunnar
mpd_git.diff
Description: Binary data
------------------------------------------------------------------------------ This SF.net email is sponsored by: SourcForge Community SourceForge wants to tell your story. http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________ Musicpd-dev-team mailing list Musicpd-dev-team@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/musicpd-dev-team