113498266Sopenharmony_ci/***************************************************************************
213498266Sopenharmony_ci *                                  _   _ ____  _
313498266Sopenharmony_ci *  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci *                             / __| | | | |_) | |
513498266Sopenharmony_ci *                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci *                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci *
813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
913498266Sopenharmony_ci *
1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci *
1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci *
1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci * KIND, either express or implied.
2013498266Sopenharmony_ci *
2113498266Sopenharmony_ci * SPDX-License-Identifier: curl
2213498266Sopenharmony_ci *
2313498266Sopenharmony_ci ***************************************************************************/
2413498266Sopenharmony_ci/* <DESC>
2513498266Sopenharmony_ci * A multi threaded application that uses a progress bar to show
2613498266Sopenharmony_ci * status.  It uses Gtk+ to make a smooth pulse.
2713498266Sopenharmony_ci * </DESC>
2813498266Sopenharmony_ci */
2913498266Sopenharmony_ci/*
3013498266Sopenharmony_ci * Written by Jud Bishop after studying the other examples provided with
3113498266Sopenharmony_ci * libcurl.
3213498266Sopenharmony_ci *
3313498266Sopenharmony_ci * To compile (on a single line):
3413498266Sopenharmony_ci * gcc -ggdb `pkg-config --cflags  --libs gtk+-2.0` -lcurl -lssl -lcrypto
3513498266Sopenharmony_ci *   -lgthread-2.0 -dl  smooth-gtk-thread.c -o smooth-gtk-thread
3613498266Sopenharmony_ci */
3713498266Sopenharmony_ci
3813498266Sopenharmony_ci#include <stdio.h>
3913498266Sopenharmony_ci#include <gtk/gtk.h>
4013498266Sopenharmony_ci#include <glib.h>
4113498266Sopenharmony_ci#include <unistd.h>
4213498266Sopenharmony_ci#include <pthread.h>
4313498266Sopenharmony_ci
4413498266Sopenharmony_ci#include <curl/curl.h>
4513498266Sopenharmony_ci
4613498266Sopenharmony_ci#define NUMT 4
4713498266Sopenharmony_ci
4813498266Sopenharmony_cipthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
4913498266Sopenharmony_ciint j = 0;
5013498266Sopenharmony_cigint num_urls = 9; /* Just make sure this is less than urls[]*/
5113498266Sopenharmony_ciconst char * const urls[]= {
5213498266Sopenharmony_ci  "90022",
5313498266Sopenharmony_ci  "90023",
5413498266Sopenharmony_ci  "90024",
5513498266Sopenharmony_ci  "90025",
5613498266Sopenharmony_ci  "90026",
5713498266Sopenharmony_ci  "90027",
5813498266Sopenharmony_ci  "90028",
5913498266Sopenharmony_ci  "90029",
6013498266Sopenharmony_ci  "90030"
6113498266Sopenharmony_ci};
6213498266Sopenharmony_ci
6313498266Sopenharmony_cisize_t write_file(void *ptr, size_t size, size_t nmemb, FILE *stream)
6413498266Sopenharmony_ci{
6513498266Sopenharmony_ci  return fwrite(ptr, size, nmemb, stream);
6613498266Sopenharmony_ci}
6713498266Sopenharmony_ci
6813498266Sopenharmony_cistatic void run_one(gchar *http, int j)
6913498266Sopenharmony_ci{
7013498266Sopenharmony_ci  FILE *outfile = fopen(urls[j], "wb");
7113498266Sopenharmony_ci  CURL *curl;
7213498266Sopenharmony_ci
7313498266Sopenharmony_ci  curl = curl_easy_init();
7413498266Sopenharmony_ci  if(curl) {
7513498266Sopenharmony_ci    printf("j = %d\n", j);
7613498266Sopenharmony_ci
7713498266Sopenharmony_ci    /* Set the URL and transfer type */
7813498266Sopenharmony_ci    curl_easy_setopt(curl, CURLOPT_URL, http);
7913498266Sopenharmony_ci
8013498266Sopenharmony_ci    /* Write to the file */
8113498266Sopenharmony_ci    curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
8213498266Sopenharmony_ci    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_file);
8313498266Sopenharmony_ci    curl_easy_perform(curl);
8413498266Sopenharmony_ci
8513498266Sopenharmony_ci    fclose(outfile);
8613498266Sopenharmony_ci    curl_easy_cleanup(curl);
8713498266Sopenharmony_ci  }
8813498266Sopenharmony_ci}
8913498266Sopenharmony_ci
9013498266Sopenharmony_civoid *pull_one_url(void *NaN)
9113498266Sopenharmony_ci{
9213498266Sopenharmony_ci  /* protect the reading and increasing of 'j' with a mutex */
9313498266Sopenharmony_ci  pthread_mutex_lock(&lock);
9413498266Sopenharmony_ci  while(j < num_urls) {
9513498266Sopenharmony_ci    int i = j;
9613498266Sopenharmony_ci    j++;
9713498266Sopenharmony_ci    pthread_mutex_unlock(&lock);
9813498266Sopenharmony_ci    http = g_strdup_printf("https://example.com/%s", urls[i]);
9913498266Sopenharmony_ci    if(http) {
10013498266Sopenharmony_ci      run_one(http, i);
10113498266Sopenharmony_ci      g_free(http);
10213498266Sopenharmony_ci    }
10313498266Sopenharmony_ci    pthread_mutex_lock(&lock);
10413498266Sopenharmony_ci  }
10513498266Sopenharmony_ci  pthread_mutex_unlock(&lock);
10613498266Sopenharmony_ci  return NULL;
10713498266Sopenharmony_ci}
10813498266Sopenharmony_ci
10913498266Sopenharmony_ci
11013498266Sopenharmony_cigboolean pulse_bar(gpointer data)
11113498266Sopenharmony_ci{
11213498266Sopenharmony_ci  gdk_threads_enter();
11313498266Sopenharmony_ci  gtk_progress_bar_pulse(GTK_PROGRESS_BAR (data));
11413498266Sopenharmony_ci  gdk_threads_leave();
11513498266Sopenharmony_ci
11613498266Sopenharmony_ci  /* Return true so the function will be called again;
11713498266Sopenharmony_ci   * returning false removes this timeout function.
11813498266Sopenharmony_ci   */
11913498266Sopenharmony_ci  return TRUE;
12013498266Sopenharmony_ci}
12113498266Sopenharmony_ci
12213498266Sopenharmony_civoid *create_thread(void *progress_bar)
12313498266Sopenharmony_ci{
12413498266Sopenharmony_ci  pthread_t tid[NUMT];
12513498266Sopenharmony_ci  int i;
12613498266Sopenharmony_ci
12713498266Sopenharmony_ci  /* Make sure I do not create more threads than urls. */
12813498266Sopenharmony_ci  for(i = 0; i < NUMT && i < num_urls ; i++) {
12913498266Sopenharmony_ci    int error = pthread_create(&tid[i],
13013498266Sopenharmony_ci                               NULL, /* default attributes please */
13113498266Sopenharmony_ci                               pull_one_url,
13213498266Sopenharmony_ci                               NULL);
13313498266Sopenharmony_ci    if(0 != error)
13413498266Sopenharmony_ci      fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
13513498266Sopenharmony_ci    else
13613498266Sopenharmony_ci      fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]);
13713498266Sopenharmony_ci  }
13813498266Sopenharmony_ci
13913498266Sopenharmony_ci  /* Wait for all threads to terminate. */
14013498266Sopenharmony_ci  for(i = 0; i < NUMT && i < num_urls; i++) {
14113498266Sopenharmony_ci    pthread_join(tid[i], NULL);
14213498266Sopenharmony_ci    fprintf(stderr, "Thread %d terminated\n", i);
14313498266Sopenharmony_ci  }
14413498266Sopenharmony_ci
14513498266Sopenharmony_ci  /* This stops the pulsing if you have it turned on in the progress bar
14613498266Sopenharmony_ci     section */
14713498266Sopenharmony_ci  g_source_remove(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(progress_bar),
14813498266Sopenharmony_ci                                                    "pulse_id")));
14913498266Sopenharmony_ci
15013498266Sopenharmony_ci  /* This destroys the progress bar */
15113498266Sopenharmony_ci  gtk_widget_destroy(progress_bar);
15213498266Sopenharmony_ci
15313498266Sopenharmony_ci  /* [Un]Comment this out to kill the program rather than pushing close. */
15413498266Sopenharmony_ci  /* gtk_main_quit(); */
15513498266Sopenharmony_ci
15613498266Sopenharmony_ci
15713498266Sopenharmony_ci  return NULL;
15813498266Sopenharmony_ci
15913498266Sopenharmony_ci}
16013498266Sopenharmony_ci
16113498266Sopenharmony_cistatic gboolean cb_delete(GtkWidget *window, gpointer data)
16213498266Sopenharmony_ci{
16313498266Sopenharmony_ci  gtk_main_quit();
16413498266Sopenharmony_ci  return FALSE;
16513498266Sopenharmony_ci}
16613498266Sopenharmony_ci
16713498266Sopenharmony_ciint main(int argc, char **argv)
16813498266Sopenharmony_ci{
16913498266Sopenharmony_ci  GtkWidget *top_window, *outside_frame, *inside_frame, *progress_bar;
17013498266Sopenharmony_ci
17113498266Sopenharmony_ci  /* Must initialize libcurl before any threads are started */
17213498266Sopenharmony_ci  curl_global_init(CURL_GLOBAL_ALL);
17313498266Sopenharmony_ci
17413498266Sopenharmony_ci  /* Init thread */
17513498266Sopenharmony_ci  g_thread_init(NULL);
17613498266Sopenharmony_ci  gdk_threads_init();
17713498266Sopenharmony_ci  gdk_threads_enter();
17813498266Sopenharmony_ci
17913498266Sopenharmony_ci  gtk_init(&argc, &argv);
18013498266Sopenharmony_ci
18113498266Sopenharmony_ci  /* Base window */
18213498266Sopenharmony_ci  top_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
18313498266Sopenharmony_ci
18413498266Sopenharmony_ci  /* Frame */
18513498266Sopenharmony_ci  outside_frame = gtk_frame_new(NULL);
18613498266Sopenharmony_ci  gtk_frame_set_shadow_type(GTK_FRAME(outside_frame), GTK_SHADOW_OUT);
18713498266Sopenharmony_ci  gtk_container_add(GTK_CONTAINER(top_window), outside_frame);
18813498266Sopenharmony_ci
18913498266Sopenharmony_ci  /* Frame */
19013498266Sopenharmony_ci  inside_frame = gtk_frame_new(NULL);
19113498266Sopenharmony_ci  gtk_frame_set_shadow_type(GTK_FRAME(inside_frame), GTK_SHADOW_IN);
19213498266Sopenharmony_ci  gtk_container_set_border_width(GTK_CONTAINER(inside_frame), 5);
19313498266Sopenharmony_ci  gtk_container_add(GTK_CONTAINER(outside_frame), inside_frame);
19413498266Sopenharmony_ci
19513498266Sopenharmony_ci  /* Progress bar */
19613498266Sopenharmony_ci  progress_bar = gtk_progress_bar_new();
19713498266Sopenharmony_ci  gtk_progress_bar_pulse(GTK_PROGRESS_BAR (progress_bar));
19813498266Sopenharmony_ci  /* Make uniform pulsing */
19913498266Sopenharmony_ci  gint pulse_ref = g_timeout_add(300, pulse_bar, progress_bar);
20013498266Sopenharmony_ci  g_object_set_data(G_OBJECT(progress_bar), "pulse_id",
20113498266Sopenharmony_ci                    GINT_TO_POINTER(pulse_ref));
20213498266Sopenharmony_ci  gtk_container_add(GTK_CONTAINER(inside_frame), progress_bar);
20313498266Sopenharmony_ci
20413498266Sopenharmony_ci  gtk_widget_show_all(top_window);
20513498266Sopenharmony_ci  printf("gtk_widget_show_all\n");
20613498266Sopenharmony_ci
20713498266Sopenharmony_ci  g_signal_connect(G_OBJECT (top_window), "delete-event",
20813498266Sopenharmony_ci                   G_CALLBACK(cb_delete), NULL);
20913498266Sopenharmony_ci
21013498266Sopenharmony_ci  if(!g_thread_create(&create_thread, progress_bar, FALSE, NULL) != 0)
21113498266Sopenharmony_ci    g_warning("cannot create the thread");
21213498266Sopenharmony_ci
21313498266Sopenharmony_ci  gtk_main();
21413498266Sopenharmony_ci  gdk_threads_leave();
21513498266Sopenharmony_ci  printf("gdk_threads_leave\n");
21613498266Sopenharmony_ci
21713498266Sopenharmony_ci  return 0;
21813498266Sopenharmony_ci}
219