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