Beispiel #1
0
static void
relative_seek (GstPlay * play, gdouble percent)
{
  gint64 dur = -1, pos = -1;

  g_return_if_fail (percent >= -1.0 && percent <= 1.0);

  g_object_get (play->player, "position", &pos, "duration", &dur, NULL);

  if (dur <= 0)
    goto seek_failed;

  pos = pos + dur * percent;
  if (pos > dur) {
    if (!play_next (play)) {
      g_print ("\nReached end of play list.\n");
      g_main_loop_quit (play->loop);
    }
  } else {
    if (pos < 0)
      pos = 0;
    gst_player_seek (play->player, pos);
  }

  return;

seek_failed:
  {
    g_print ("\nCould not seek.\n");
  }
}
Beispiel #2
0
static void
end_of_stream_cb (GstPlayer * player, GstPlay * play)
{
  g_print ("\n");
  /* and switch to next item in list */
  if (!play_next (play)) {
    g_print ("Reached end of play list.\n");
    g_main_loop_quit (play->loop);
  }
}
static void
keyboard_cb (const gchar * key_input, gpointer user_data)
{
  GstPlay *play = (GstPlay *) user_data;

  switch (g_ascii_tolower (key_input[0])) {
    case 'i':
    {
      GstPlayerMediaInfo *media_info = gst_player_get_media_info (play->player);
      if (media_info) {
        print_media_info (media_info);
        g_object_unref (media_info);
        print_current_tracks (play);
      }
      break;
    }
    case ' ':
      toggle_paused (play);
      break;
    case 'q':
    case 'Q':
      g_main_loop_quit (play->loop);
      break;
    case '>':
      if (!play_next (play)) {
        g_print ("\nReached end of play list.\n");
        g_main_loop_quit (play->loop);
      }
      break;
    case '<':
      play_prev (play);
      break;
    case 27:                   /* ESC */
      if (key_input[1] == '\0') {
        g_main_loop_quit (play->loop);
        break;
      }
      /* fall through */
    default:
      if (strcmp (key_input, GST_PLAY_KB_ARROW_RIGHT) == 0) {
        relative_seek (play, +0.08);
      } else if (strcmp (key_input, GST_PLAY_KB_ARROW_LEFT) == 0) {
        relative_seek (play, -0.01);
      } else if (strcmp (key_input, GST_PLAY_KB_ARROW_UP) == 0) {
        play_set_relative_volume (play, +1.0 / VOLUME_STEPS);
      } else if (strcmp (key_input, GST_PLAY_KB_ARROW_DOWN) == 0) {
        play_set_relative_volume (play, -1.0 / VOLUME_STEPS);
      } else {
        GST_INFO ("keyboard input:");
        for (; *key_input != '\0'; ++key_input)
          GST_INFO ("  code %3d", *key_input);
      }
      break;
  }
}
Beispiel #4
0
static void
error_cb (GstPlayer * player, GError * err, GstPlay * play)
{
  g_printerr ("ERROR %s for %s\n", err->message, play->uris[play->cur_idx]);

  /* try next item in list then */
  if (!play_next (play)) {
    g_print ("Reached end of play list.\n");
    g_main_loop_quit (play->loop);
  }
}
static void
do_play (GstPlay * play)
{
  gint i;

  /* dump playlist */
  for (i = 0; i < play->num_uris; ++i)
    GST_INFO ("%4u : %s", i, play->uris[i]);

  if (!play_next (play))
    return;

  g_main_loop_run (play->loop);
}
Beispiel #6
0
void
play_skip(struct info *data)
{
	char errormsg[] = "Skip not allowed.";
	struct track *t;

	t = data->m->track[data->m->track_count-1];
	if (t == NULL)
		return;
	if (t->skip_allowed == TRUE && t->last == FALSE) {
		play_next(data);
	} else
		draw_error(errormsg);
}
static void
error_cb (GstPlayer * player, GError * err, GstPlay * play)
{
  g_printerr ("ERROR %s for %s\n", err->message, play->uris[play->cur_idx]);

  /* if looping is enabled, then disable it else will keep looping forever */
  play->repeat = FALSE;

  /* try next item in list then */
  if (!play_next (play)) {
    g_print ("Reached end of play list.\n");
    g_main_loop_quit (play->loop);
  }
}
Beispiel #8
0
void
play_nextmix(struct info *data)
{
	char errormsg[] = "Next mix not found.";
	int errn;

	errn = search_nextmix(data);
	if (errn == ERROR) {
		draw_error(errormsg);
		data->state = START;
		return;
	}
	data->scroll = 0;
	play_next(data);
}
static void
relative_seek (GstPlay * play, gdouble percent)
{
  GstQuery *query;
  gboolean seekable = FALSE;
  gint64 dur = -1, pos = -1, step;

  g_return_if_fail (percent >= -1.0 && percent <= 1.0);

  if (!gst_element_query_position (play->playbin, GST_FORMAT_TIME, &pos))
    goto seek_failed;

  query = gst_query_new_seeking (GST_FORMAT_TIME);
  if (!gst_element_query (play->playbin, query)) {
    gst_query_unref (query);
    goto seek_failed;
  }

  gst_query_parse_seeking (query, NULL, &seekable, NULL, &dur);
  gst_query_unref (query);

  if (!seekable || dur <= 0)
    goto seek_failed;

  step = dur * percent;
  if (ABS (step) < GST_SECOND)
    step = (percent < 0) ? -GST_SECOND : GST_SECOND;

  pos = pos + step;
  if (pos > dur) {
    if (!play_next (play)) {
      g_print ("\n%s\n", _("Reached end of play list."));
      g_main_loop_quit (play->loop);
    }
  } else {
    if (pos < 0)
      pos = 0;

    play_do_seek (play, pos, play->rate, play->trick_mode);
  }

  return;

seek_failed:
  {
    g_print ("\nCould not seek.\n");
  }
}
Beispiel #10
0
static void
relative_seek (GstPlay * play, gdouble percent)
{
  GstQuery *query;
  gboolean seekable = FALSE;
  gint64 dur = -1, pos = -1;

  g_return_if_fail (percent >= -1.0 && percent <= 1.0);

  if (!gst_element_query_position (play->playbin, GST_FORMAT_TIME, &pos))
    goto seek_failed;

  query = gst_query_new_seeking (GST_FORMAT_TIME);
  if (!gst_element_query (play->playbin, query)) {
    gst_query_unref (query);
    goto seek_failed;
  }

  gst_query_parse_seeking (query, NULL, &seekable, NULL, &dur);
  gst_query_unref (query);

  if (!seekable || dur <= 0)
    goto seek_failed;

  pos = pos + dur * percent;
  if (pos > dur) {
    if (!play_next (play)) {
      g_print ("\nReached end of play list.\n");
      g_main_loop_quit (play->loop);
    }
  } else {
    if (pos < 0)
      pos = 0;
    if (!gst_element_seek_simple (play->playbin, GST_FORMAT_TIME,
            GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, pos))
      goto seek_failed;
  }

  return;

seek_failed:
  {
    g_print ("\nCould not seek.\n");
  }
}
Beispiel #11
0
void	find_next(t_sh *shell, t_term *term, char *str)
{
	t_bin	*map;

	map = shell->map;
	while (map && map->next)
	{
		if (starts_with(str, map->name))
		{
			if (map->prev && starts_with(str, map->prev->name))
			{
				;
			}
			else if (map->next && starts_with(str, map->next->name))
				;
			else
			{
				play_next(shell, term, str, map->name);
				return ;
			}
		}
		map = map->next;
	}
}
static gboolean
play_bus_msg (GstBus * bus, GstMessage * msg, gpointer user_data)
{
  GstPlay *play = user_data;

  switch (GST_MESSAGE_TYPE (msg)) {
    case GST_MESSAGE_ASYNC_DONE:

      /* dump graph on preroll */
      GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin),
          GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.async-done");

      g_print ("Prerolled.\r");
      if (play->missing != NULL && play_install_missing_plugins (play)) {
        g_print ("New plugins installed, trying again...\n");
        --play->cur_idx;
        play_next (play);
      }
      break;
    case GST_MESSAGE_BUFFERING:{
      gint percent;

      if (!play->buffering)
        g_print ("\n");

      gst_message_parse_buffering (msg, &percent);
      g_print ("%s %d%%  \r", _("Buffering..."), percent);

      if (percent == 100) {
        /* a 100% message means buffering is done */
        if (play->buffering) {
          play->buffering = FALSE;
          /* no state management needed for live pipelines */
          if (!play->is_live)
            gst_element_set_state (play->playbin, play->desired_state);
        }
      } else {
        /* buffering... */
        if (!play->buffering) {
          if (!play->is_live)
            gst_element_set_state (play->playbin, GST_STATE_PAUSED);
          play->buffering = TRUE;
        }
      }
      break;
    }
    case GST_MESSAGE_CLOCK_LOST:{
      g_print (_("Clock lost, selecting a new one\n"));
      gst_element_set_state (play->playbin, GST_STATE_PAUSED);
      gst_element_set_state (play->playbin, GST_STATE_PLAYING);
      break;
    }
    case GST_MESSAGE_LATENCY:
      g_print ("Redistribute latency...\n");
      gst_bin_recalculate_latency (GST_BIN (play->playbin));
      break;
    case GST_MESSAGE_REQUEST_STATE:{
      GstState state;
      gchar *name;

      name = gst_object_get_path_string (GST_MESSAGE_SRC (msg));

      gst_message_parse_request_state (msg, &state);

      g_print ("Setting state to %s as requested by %s...\n",
          gst_element_state_get_name (state), name);

      gst_element_set_state (play->playbin, state);
      g_free (name);
      break;
    }
    case GST_MESSAGE_EOS:
      /* print final position at end */
      play_timeout (play);
      g_print ("\n");
      /* and switch to next item in list */
      if (!play_next (play)) {
        g_print ("%s\n", _("Reached end of play list."));
        g_main_loop_quit (play->loop);
      }
      break;
    case GST_MESSAGE_WARNING:{
      GError *err;
      gchar *dbg = NULL;

      /* dump graph on warning */
      GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin),
          GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.warning");

      gst_message_parse_warning (msg, &err, &dbg);
      g_printerr ("WARNING %s\n", err->message);
      if (dbg != NULL)
        g_printerr ("WARNING debug information: %s\n", dbg);
      g_clear_error (&err);
      g_free (dbg);
      break;
    }
    case GST_MESSAGE_ERROR:{
      GError *err;
      gchar *dbg;

      /* dump graph on error */
      GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin),
          GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.error");

      gst_message_parse_error (msg, &err, &dbg);
      g_printerr ("ERROR %s for %s\n", err->message, play->uris[play->cur_idx]);
      if (dbg != NULL)
        g_printerr ("ERROR debug information: %s\n", dbg);
      g_clear_error (&err);
      g_free (dbg);

      /* flush any other error messages from the bus and clean up */
      gst_element_set_state (play->playbin, GST_STATE_NULL);

      if (play->missing != NULL && play_install_missing_plugins (play)) {
        g_print ("New plugins installed, trying again...\n");
        --play->cur_idx;
        play_next (play);
        break;
      }
      /* try next item in list then */
      if (!play_next (play)) {
        g_print ("%s\n", _("Reached end of play list."));
        g_main_loop_quit (play->loop);
      }
      break;
    }
    case GST_MESSAGE_ELEMENT:
    {
      GstNavigationMessageType mtype = gst_navigation_message_get_type (msg);
      if (mtype == GST_NAVIGATION_MESSAGE_EVENT) {
        GstEvent *ev = NULL;

        if (gst_navigation_message_parse_event (msg, &ev)) {
          GstNavigationEventType e_type = gst_navigation_event_get_type (ev);
          switch (e_type) {
            case GST_NAVIGATION_EVENT_KEY_PRESS:
            {
              const gchar *key;

              if (gst_navigation_event_parse_key_event (ev, &key)) {
                GST_INFO ("Key press: %s", key);

                if (strcmp (key, "Left") == 0)
                  key = GST_PLAY_KB_ARROW_LEFT;
                else if (strcmp (key, "Right") == 0)
                  key = GST_PLAY_KB_ARROW_RIGHT;
                else if (strcmp (key, "Up") == 0)
                  key = GST_PLAY_KB_ARROW_UP;
                else if (strcmp (key, "Down") == 0)
                  key = GST_PLAY_KB_ARROW_DOWN;
                else if (strcmp (key, "space") == 0)
                  key = " ";
                else if (strlen (key) > 1)
                  break;

                keyboard_cb (key, user_data);
              }
              break;
            }
            case GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS:
            {
              gint button;
              if (gst_navigation_event_parse_mouse_button_event (ev, &button,
                      NULL, NULL)) {
                if (button == 4) {
                  /* wheel up */
                  relative_seek (play, +0.08);
                } else if (button == 5) {
                  /* wheel down */
                  relative_seek (play, -0.01);
                }
              }
              break;
            }
            default:
              break;
          }
        }
        if (ev)
          gst_event_unref (ev);
      }
      break;
    }
    default:
      if (gst_is_missing_plugin_message (msg)) {
        gchar *desc;

        desc = gst_missing_plugin_message_get_description (msg);
        g_print ("Missing plugin: %s\n", desc);
        g_free (desc);
        play->missing = g_list_append (play->missing, gst_message_ref (msg));
      }
      break;
  }

  return TRUE;
}
static void
keyboard_cb (const gchar * key_input, gpointer user_data)
{
  GstPlay *play = (GstPlay *) user_data;
  gchar key = '\0';

  /* only want to switch/case on single char, not first char of string */
  if (key_input[0] != '\0' && key_input[1] == '\0')
    key = g_ascii_tolower (key_input[0]);

  switch (key) {
    case 'k':
      print_keyboard_help ();
      break;
    case ' ':
      toggle_paused (play);
      break;
    case 'q':
    case 'Q':
      g_main_loop_quit (play->loop);
      break;
    case 'n':
    case '>':
      if (!play_next (play)) {
        g_print ("\n%s\n", _("Reached end of play list."));
        g_main_loop_quit (play->loop);
      }
      break;
    case 'b':
    case '<':
      play_prev (play);
      break;
    case '+':
      if (play->rate > -0.2 && play->rate < 0.0)
        play_set_relative_playback_rate (play, 0.0, TRUE);
      else if (ABS (play->rate) < 2.0)
        play_set_relative_playback_rate (play, 0.1, FALSE);
      else if (ABS (play->rate) < 4.0)
        play_set_relative_playback_rate (play, 0.5, FALSE);
      else
        play_set_relative_playback_rate (play, 1.0, FALSE);
      break;
    case '-':
      if (play->rate > 0.0 && play->rate < 0.20)
        play_set_relative_playback_rate (play, 0.0, TRUE);
      else if (ABS (play->rate) <= 2.0)
        play_set_relative_playback_rate (play, -0.1, FALSE);
      else if (ABS (play->rate) <= 4.0)
        play_set_relative_playback_rate (play, -0.5, FALSE);
      else
        play_set_relative_playback_rate (play, -1.0, FALSE);
      break;
    case 'd':
      play_set_relative_playback_rate (play, 0.0, TRUE);
      break;
    case 't':
      play_switch_trick_mode (play);
      break;
    case 27:                   /* ESC */
      if (key_input[1] == '\0') {
        g_main_loop_quit (play->loop);
        break;
      }
    case 'a':
      play_cycle_track_selection (play, GST_PLAY_TRACK_TYPE_AUDIO);
      break;
    case 'v':
      play_cycle_track_selection (play, GST_PLAY_TRACK_TYPE_VIDEO);
      break;
    case 's':
      play_cycle_track_selection (play, GST_PLAY_TRACK_TYPE_SUBTITLE);
      break;
    case '0':
      play_do_seek (play, 0, play->rate, play->trick_mode);
      break;
    default:
      if (strcmp (key_input, GST_PLAY_KB_ARROW_RIGHT) == 0) {
        relative_seek (play, +0.08);
      } else if (strcmp (key_input, GST_PLAY_KB_ARROW_LEFT) == 0) {
        relative_seek (play, -0.01);
      } else if (strcmp (key_input, GST_PLAY_KB_ARROW_UP) == 0) {
        play_set_relative_volume (play, +1.0 / VOLUME_STEPS);
      } else if (strcmp (key_input, GST_PLAY_KB_ARROW_DOWN) == 0) {
        play_set_relative_volume (play, -1.0 / VOLUME_STEPS);
      } else {
        GST_INFO ("keyboard input:");
        for (; *key_input != '\0'; ++key_input)
          GST_INFO ("  code %3d", *key_input);
      }
      break;
  }
}
Beispiel #14
0
static gboolean
play_bus_msg (GstBus * bus, GstMessage * msg, gpointer user_data)
{
  GstPlay *play = user_data;

  switch (GST_MESSAGE_TYPE (msg)) {
    case GST_MESSAGE_ASYNC_DONE:

      /* dump graph on preroll */
      GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin),
          GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.async-done");

      g_print ("Prerolled.\r");
      if (play->missing != NULL && play_install_missing_plugins (play)) {
        g_print ("New plugins installed, trying again...\n");
        --play->cur_idx;
        play_next (play);
      }
      break;
    case GST_MESSAGE_BUFFERING:{
      gint percent;

      if (!play->buffering)
        g_print ("\n");

      gst_message_parse_buffering (msg, &percent);
      g_print ("%s %d%%  \r", _("Buffering..."), percent);

      if (percent == 100) {
        /* a 100% message means buffering is done */
        if (play->buffering) {
          play->buffering = FALSE;
          /* no state management needed for live pipelines */
          if (!play->is_live)
            gst_element_set_state (play->playbin, play->desired_state);
        }
      } else {
        /* buffering... */
        if (!play->buffering) {
          if (!play->is_live)
            gst_element_set_state (play->playbin, GST_STATE_PAUSED);
          play->buffering = TRUE;
        }
      }
      break;
    }
    case GST_MESSAGE_CLOCK_LOST:{
      g_print (_("Clock lost, selecting a new one\n"));
      gst_element_set_state (play->playbin, GST_STATE_PAUSED);
      gst_element_set_state (play->playbin, GST_STATE_PLAYING);
      break;
    }
    case GST_MESSAGE_LATENCY:
      g_print ("Redistribute latency...\n");
      gst_bin_recalculate_latency (GST_BIN (play->playbin));
      break;
    case GST_MESSAGE_REQUEST_STATE:{
      GstState state;
      gchar *name;

      name = gst_object_get_path_string (GST_MESSAGE_SRC (msg));

      gst_message_parse_request_state (msg, &state);

      g_print ("Setting state to %s as requested by %s...\n",
          gst_element_state_get_name (state), name);

      gst_element_set_state (play->playbin, state);
      g_free (name);
      break;
    }
    case GST_MESSAGE_EOS:
      /* print final position at end */
      play_timeout (play);
      g_print ("\n");
      /* and switch to next item in list */
      if (!play_next (play)) {
        g_print ("Reached end of play list.\n");
        g_main_loop_quit (play->loop);
      }
      break;
    case GST_MESSAGE_WARNING:{
      GError *err;
      gchar *dbg = NULL;

      /* dump graph on warning */
      GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin),
          GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.warning");

      gst_message_parse_warning (msg, &err, &dbg);
      g_printerr ("WARNING %s\n", err->message);
      if (dbg != NULL)
        g_printerr ("WARNING debug information: %s\n", dbg);
      g_error_free (err);
      g_free (dbg);
      break;
    }
    case GST_MESSAGE_ERROR:{
      GError *err;
      gchar *dbg;

      /* dump graph on error */
      GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (play->playbin),
          GST_DEBUG_GRAPH_SHOW_ALL, "gst-play.error");

      gst_message_parse_error (msg, &err, &dbg);
      g_printerr ("ERROR %s for %s\n", err->message, play->uris[play->cur_idx]);
      if (dbg != NULL)
        g_printerr ("ERROR debug information: %s\n", dbg);
      g_error_free (err);
      g_free (dbg);

      /* flush any other error messages from the bus and clean up */
      gst_element_set_state (play->playbin, GST_STATE_NULL);

      if (play->missing != NULL && play_install_missing_plugins (play)) {
        g_print ("New plugins installed, trying again...\n");
        --play->cur_idx;
        play_next (play);
        break;
      }
      /* try next item in list then */
      if (!play_next (play)) {
        g_print ("Reached end of play list.\n");
        g_main_loop_quit (play->loop);
      }
      break;
    }
    default:
      if (gst_is_missing_plugin_message (msg)) {
        gchar *desc;

        desc = gst_missing_plugin_message_get_description (msg);
        g_print ("Missing plugin: %s\n", desc);
        g_free (desc);
        play->missing = g_list_append (play->missing, gst_message_ref (msg));
      }
      break;
  }

  return TRUE;
}
Beispiel #15
0
void run()
{
	WSADATA wsa;
	if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
	{
		printf("Init failed");
		exit(-1);
	}

	SOCKET server_fd;

	server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	if (server_fd == INVALID_SOCKET)
	{
		printf("Invalid socket");
		exit(-1);
	}

	struct sockaddr_in server_addr;
	int port = 56789;
	memset(&server_addr, 0, sizeof(struct sockaddr_in));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = INADDR_ANY;
	server_addr.sin_port = htons(port);

	if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR)
	{
		printf("Socket bind error");
		exit(-1);
	}

	if (listen(server_fd, SOMAXCONN) == SOCKET_ERROR)
	{
		printf("Socket execute error");
		exit(-1);
	}

	char hostname[255];
	char *ip;
	char *local = "*";
	struct hostent *hostinfo;
	if (gethostname(hostname, sizeof(hostname)) == 0)
	{
		if ((hostinfo = gethostbyname(hostname)) != NULL)
		{
			ip = inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list);
		}
		else
		{			
			ip = local;
		}
	}
	else
	{
		ip = local;
	}

	printf("Server is listening on %s:%d\n", ip, port);
	char doccmd[BUF_SIZE];
	sprintf_s(doccmd, BUF_SIZE, "start http://%s:%d/", ip, port);
	//system(doccmd);

	while (true)
	{
		SOCKET client;
		struct sockaddr_in client_addr;
		memset(&client_addr, 0, sizeof(struct sockaddr_in));
		client = accept(server_fd, (struct sockaddr*)&client_addr, 0);
		if (client == INVALID_SOCKET)
		{
			printf("Invalid socket");
		}

		char request[BUF_SIZE];
		char htmlfile[255];

		int receive_rs = recv(client, request, sizeof(request), 0);
		struct req_head head = parse_request_head(request);
		printf("Request: %s\n", head.path);

		if (strcmp(head.path, "/next") == 0)
		{
			play_next();
			strcpy_s(htmlfile, "html/index.html");
		}
		else if (strcmp(head.path, "/prev") == 0)
		{
			play_prev();
			strcpy_s(htmlfile, "html/index.html");
		}
		else if (strcmp(head.path, "/play") == 0)
		{
			play();
			strcpy_s(htmlfile, "html/index.html");
		}
		else if (strcmp(head.path, "/up") == 0)
		{
			volume_up();
			strcpy_s(htmlfile, "html/index.html");
		}
		else if (strcmp(head.path, "/down") == 0)
		{
			volume_down();
			strcpy_s(htmlfile, "html/index.html");
		}
		else if (strcmp(head.path, "/mute") == 0)
		{
			mute();
			strcpy_s(htmlfile, "html/index.html");
		}
		else if (strcmp(head.path, "/shutdown") == 0)
		{
			poweroff();
			strcpy_s(htmlfile, "html/index.html");
		}
		else if (strcmp(head.path, "/") == 0)
		{
			strcpy_s(htmlfile, "html/index.html");
		}	
		else
		{
			strcpyn(htmlfile, head.path, 1, sizeof(head) - 1);
		}

		// 加载要显示的页面
		struct fbuf *html = load_file(htmlfile);
		//printf("Loading file: %s\n", htmlfile);

		char *content;
		if (html == NULL)
		{
			content = (char *)calloc(BUF_SIZE, sizeof(char));
			sprintf_s(content, BUF_SIZE, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s", 22, "<h1>404 NOT FOUND</h1>");
			send(client, content, strlen(content), 0);
		}
		else
		{
			size_t total_size = html->buf_size + 67;
			content = (char *)calloc(total_size, sizeof(char));
			sprintf_s(content, total_size, "HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %d\r\n\r\n", html->mime, html->buf_size * sizeof(char));
			// send head
			send(client, content, strlen(content), 0);

			// send body
			send(client, html->buf, html->buf_size, 0);
		}
		
		free(content);
		free(html);

		closesocket(client);
	}

	closesocket(server_fd);
}